Handling Spreadsheet Data Through the Clipboard in Gtk

Handling spreadsheet data through the clipboard in GTK

To catch the paste event, you need to first create a custom entry class (PastableEntry in this example) that inherits from gtksheet.ItemEntry. During its initialisation, we connect to the paste-clipboard signal to trap paste events:

class PastableEntry(gtksheet.ItemEntry):
def __init__(self):
gtksheet.ItemEntry.__init__(self)
self.connect('paste-clipboard', self.__on_paste)

The hard work is in the event handler. First we need to get the clipboard contents. In Unix, clipboard sources can advertise multiple data formats. Based on your screenshot, I assume you're trying to copy data from Gnumeric. Gnumeric supports application/x-gnumeric, text/html, UTF8_STRING, COMPOUND_TEXT, and STRING. For this example we'll use the UTF8_STRING format, which looks like this:

1,1 <tab> 1,2 <tab> 1,3 <newline>
2,1 <tab> 2,2 <tab> 2,3 <newline>
3,1 <tab> 3,2 <tab> 3,3

Obviously this fails horribly if any of the cells contain a tab or newline character, but we'll use this for simplicity. In a real world application you may want to parse the application/x-gnumeric or text/html formatted data.

Back to our PastableEntry class, now we define the paste event handler:

    def __on_paste(self, entry):
clip = gtk.Clipboard()
data = clip.wait_for_contents('UTF8_STRING')
text = data.get_text()
sheet = self.parent
o_row, o_col = sheet.get_active_cell()
for i_row, row in enumerate(text.split('\n')):
for i_col, cell in enumerate(row.split('\t')):
sheet.set_cell_text(o_row + i_row, o_col + i_col, cell)
self.stop_emission('paste-clipboard')

It should be quite self-explanatory. We split the clipboard data into rows (by newline characters) and then into cells (by tab characters), and set the Sheet cell values accordingly.

The stop_emission is there to stop GTK+ from running the default handler for paste operations. Without that line, the selected cell will be overwritten with the raw data.

We then register the class with GObject:

gobject.type_register(PastableEntry)

Finally, to actually use our custom entry class, pass it to the constructor of gtksheet.Sheet:

s = gtksheet.Sheet(20, 20, "Sheet 1", entry_type=PastableEntry)

What does gobject.type_register() do?

A PyGTK type can be used as the type of a PyGTK property. To be known to the GObject type system, a type has to be registered. I don't think you actually have to call this function in PyGTK, it is probably done automatically when you call __gobject_init__.

Sometimes the PyGTK docs are too succinct. In that case you might want to read the C docs.



Related Topics



Leave a reply



Submit