20.2. Retrieving the selection

Retrieving the selection is an asynchronous process. To start the process, you call:
 
result = widget.selection_convert(selection, target, time)

This converts the selection into the form specified by target. selection is an atom corresponding to the selection type; the common selections (defined in GDK.py) are:
 
SELECTION_PRIMARY
SELECTION_SECONDARY

If at all possible, the time field should be the time from the event that triggered the selection. This helps make sure that events occur in the order that the user requested them. However, if it is not available (for instance, if the conversion was triggered by a "clicked" signal), then you can use the constant CURRENT_TIME (defined in GDK.py). result is TRUE if the conversion succeeded, FALSE otherwise.

When the selection owner responds to the request, a "selection_received" signal is sent to your application. The handler for this signal receives a GtkSelectionData object, which has the following attributes:
 
  selection
  target
  type
  format
  data
  length

selection and target are the values you gave in your selection_convert() method.

type is an atom that identifies the type of data returned by the selection owner. Some possible values are "STRING", a string of latin-1 characters, "ATOM", a series of atoms, "INTEGER", an integer, "image/x-xpixmap", etc. Most targets can only return one type.

format gives the length of the units (for instance characters) in bits. Usually, you don't care about this when receiving data.

data is the returned data in the form of a string.

length gives the length of the returned data, in bytes. If length is negative, then an error occurred and the selection could not be retrieved. This might happen if no application owned the selection, or if you requested a target that the application didn't support.

PyGTK wraps all received data into a string. This makes it easy to handle string targets. To retrieve targets of other types (e.g. ATOM or INTEGER) the program must extract the information from the returned string. The example below illustrates one way of doing this.

The getselection.py example program demonstrates the retrieving of a "STRING" or "TARGETS" target from the primary selection and printing the corresponding data to the console when the button is "clicked". Figure 20.1 illustrates the program display:

Figure 20.1 Get Selection Example

The source code for the getsselection.py program is:
 
    1   #!/usr/bin/env python
    2   
    3   # example getselection.py
    4   
    5   import gtk
    6   import GDK
    7   import struct
    8   
    9   class GetSelectionExample:
   10       SELECTION_PRIMARY = 1
   11       CURRENT_TIME = 0
   12       # Signal handler invoked when user clicks on the
   13       # "Get String Target" button
   14       def get_stringtarget(self, widget):
   15           # Get the atom corresponding to the string "STRING"
   16           if self.string_atom == None:
   17               self.string_atom = gtk.atom_intern("STRING", gtk.FALSE)
   18           # And request the "STRING" target for the primary selection
   19           ret = widget.selection_convert(self.SELECTION_PRIMARY,
   20                                          self.string_atom,
   21                                          self.CURRENT_TIME)
   22           return
   23   
   24       # Signal handler invoked when user clicks on the "Get Targets" button
   25       def get_targets(self, widget):
   26           # Get the atom corresponding to the string "TARGETS"
   27           if self.targets_atom == None:
   28               self.targets_atom = gtk.atom_intern("TARGETS", gtk.FALSE)
   29   
   30           # And request the "TARGETS" target for the primary selection
   31           widget.selection_convert(self.SELECTION_PRIMARY,
   32                                    self.targets_atom,
   33                                    self.CURRENT_TIME)
   34           return
   35   
   36       # Signal handler called when the selections owner returns the data
   37       def selection_received(self, widget, selection_data, data):
   38          # **** IMPORTANT **** Check to see if retrieval succeeded 
   39           if selection_data.length < 0:
   40               print "Selection retrieval failed"
   41               return
   42   
   43           # Make sure we got the data in the expected form
   44           if selection_data.type == GDK.SELECTION_TYPE_STRING:
   45               # Print out the string we received
   46               print "STRING TARGET: %s" % selection_data.data
   47   
   48           elif selection_data.type == GDK.SELECTION_TYPE_ATOM:
   49               # Print out the atoms we received
   50               atoms = struct.unpack(
   51                   'L'*(selection_data.length*8/selection_data.format),
   52                   selection_data.data)
   53               for atom in atoms:
   54                   name = gtk.atom_name(atom)
   55                   if name != None:
   56                       print "%s" % name
   57                   else:
   58                       print "(bad atom)"
   59   
   60           else:
   61               print "Selection was not returned as \"STRING\" or \"ATOM\"!"
   62   
   63           return
   64     
   65   
   66       def __init__(self):
   67           self.string_atom = None
   68           self.targets_atom = None
   69           # Create the toplevel window
   70           window = gtk.GtkWindow(gtk.WINDOW_TOPLEVEL)
   71           window.set_title("Get Selection")
   72           window.set_border_width(10)
   73           window.connect("destroy", gtk.mainquit)
   74   
   75           vbox = gtk.GtkVBox(gtk.FALSE, 0)
   76           window.add(vbox)
   77           vbox.show()
   78   
   79           # Create a button the user can click to get the string target
   80           button = gtk.GtkButton("Get String Target")
   81           button.connect("clicked", self.get_stringtarget)
   82           button.connect("selection_received", self.selection_received)
   83           vbox.pack_start(button)
   84           button.show()
   85   
   86           # Create a button the user can click to get targets
   87           button = gtk.GtkButton("Get Targets")
   88           button.connect("clicked", self.get_targets)
   89           button.connect("selection_received", self.selection_received)
   90           vbox.pack_start(button)
   91           button.show()
   92   
   93           window.show()
   94   
   95   def main():
   96       gtk.mainloop()
   97       return 0
   98   
   99   if __name__ == "__main__":
  100       GetSelectionExample()
  101       main()

Lines 48-58 handle the retrieval of the "TARGETS" selection data which is an array of ATOMs (unsigned long). Lines 50-52 extract the atoms from the selection data by using the Python struct module to unpack the data into a tuple of longs.