Handling spreadsheet data through the clipboard in GTK

后端 未结 1 756
别跟我提以往
别跟我提以往 2021-01-21 01:48

I\'m using a GtkSheet widget in PyGTK to power my application\'s spreadsheet, and it gives me an API to pull and push data out of cells. (I looked at using GtkTreeView, but it s

相关标签:
1条回答
  • 2021-01-21 02:25

    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)
    
    0 讨论(0)
提交回复
热议问题