Development Team/Almanac/GTK's Clipboard Module

From Sugar Labs
Jump to navigation Jump to search

Working With Text on the Clipboard

How do I perform a simple copy and paste from GTK widgets?

According to the PyGtk Tutorial, widgets of type Entry, SpinButton and TextView have some built in functionality to cut, copy and paste text to and from a clipboard. In particular, these widgets implement the Editable interface that has standard calls for clipboard functionality.

The code below creates a simple gtk.Entry widget where text can be entered. Right below this widget, there is one button to copy text inside of the entry and another to paste text from the clipboard in to the Entry widget. In addition to using the "Copy" and "Paste" buttons, users can also use CONTROL-X, CONTROL-C, and CONTROL-V to cut, copy and paste text from widgets that implement the Editable interface. The meat of the work is done in short callbacks that are connected to the Copy and Paste buttons. The code for creating the UI has been included primarily for completeness and added clarity.

    #### Method: _createCanvas, creates a top level UI canvas object for this activity
    def _createCanvas(self):
        top_container = Notebook()
        
        #Create pages for the notebook
        first_page = gtk.VBox()
        second_page = gtk.VBox()
        third_page = gtk.Frame()
        
        #FOR FIRST PAGE:: Create a text entry box with two buttons for copy and paste right below it. 
        first_page_entry_box = gtk.VBox(homogeneous=False, spacing=5)
        button_row = gtk.HBox()
        #### Create the actual gtk.Entry for text entry
        self.clipInput = gtk.Entry(max=0)
        self.clipInput.set_width_chars(100)
        #### Create the copy button and assign callback
        copyClipInput = gtk.Button(label='Copy Text')
        copyClipInput.connect("clicked", self._copyClipInput_cb, None)  # CALLBACK USED WHEN COPY BUTTON PRESSED!
        button_row.pack_start(copyClipInput, expand=False, fill=False)
        #### Create the paste button and assign callback
        pasteClipInput = gtk.Button(label='Paste Text')
        pasteClipInput.connect("clicked", self._pasteClipInput_cb, None) # CALLBACK USED WHEN PASTE BUTTON PRESSED!
        ...

    #### Method: _copyClipInput_cb, which is called when the "Copy Text" button is clicked
    def _copyClipInput_cb(self, widget, data=None):
        #Select all text in self.copyClipInput and copy it to the clipboard
        self.clipInput.select_region(0, -1)
        self.clipInput.copy_clipboard()
        _logger.debug("$$$$$$$$$$$$$$$$$$$ Copy button pressed")

    #### Method: _pasteClipInput_cb, which is called when the "Paste Text" button is clicked
    def _pasteClipInput_cb(self, widget, data=None):
        self.clipInput.paste_clipboard()
        _logger.debug("******************* Paste button pressed.")

Note that when you cut or copy text programmatically, you must first select a region in the widget. That is why we have the call to select_region() in the _copyClipInput_cb method. The -1 argument ensures that all text in the widget is selected. [1]

How do I create my own named clipboard?

When you use the standard copy and paste methods for Editable widgets in GTK, the data is typically copied to a standard clipboard named "CLIPBOARD".[2]

With GTK's clipboard class, you can create multiple clipboard instances and control where data gets saved for sharing. Rather than having all your data going to the standard "CLIPBOARD" destination, you can create alternative clipboards that are responsible for sharing specific information.

The code below shows how named clipboards are created. Note there are distinct variable references for the two clipboards created, so they can be accessed separately. Passing unique names to the gtk.clipboard_get() method ensures that the clipboards are indeed distinct and data from one will not interfere with the other.

        #Create a clipboard specifically for data on the first page of this activity's notebook
        self.pg1_clipboard = gtk.clipboard_get('ANNOTATE_CLIPBOARD_1')
        #Create a clipboard specifically for data on the second page of this activity's notebook
        self.pg2_clipboard = gtk.clipboard_get('ANNOTATE_CLIPBOARD_2')


How do I work with multiple clipboards in my activity?

First, you need to create [How_do_I_create_my_own_named_clipboard.3F named clipboards] for each context that you will be saving data.

Working with More Complex Data Structures on the Clipboard

Notes