FAQ Index - Search - Recent Changes - Everything - Add entry

<< Previous Entry | FAQ Entry 13.54 | Next Entry >>

13.54. How can I cut/copy/paste TreeStore rows using clipboard?

The clipboard accepts text or image data, not an arbitrary object. The trick is to create a text representation of selected tree rows and copy it into clipboard. When pasting, create tree rows based on the text obtained from clipboard. Ideal format for this is XML, as a side effect the same serialization/deserialization method can be used when saving/loading the tree contents to/from a file.

The XML tree should contain at least a root XML tag with format description and cell XML tags for each tree row. If the tree model contains columns with short values like checkboxes, put these values directly ito cell XML tags as parameters. If your model contains columns with potentially long text, you can add a special data XML tag as a child of every cell XML tag. Example of format for two-column model with checkbox and text with a parent and child row - (0,) and (0,0):

  <tree version="1.0" creator="my_app">
    <cell toggle="False">
      <data>Text 1</data>
      <cell toggle="True">
        <data>Text 2</data>
      </cell>
    </cell>
  </tree>
Note that putting text directly between cells without a special data XML tag (we use 'data' for this) would prohibit pretty-printing and the resulting XML would be hard to read. This is because prettyprinting adds whitespaces but adding whitespaces into the text would alter the text itself.

Example of creating XML tree (replace the constants with data from TreeStore):

  from lxml import etree

  xml_root = etree.Element('root', { 'version' : '1.0', 'creator' : 'my_app' })
  xml_cell = etree.Element('cell', { 'toggle' : 'False' })
  xml_data = etree.Element('data')
  xml_data.text = 'Text 1'
  xml_cell.append(xml_data)
  xml_root.append(xml_cell)
  xml_text = etree.tostring(xml_root, pretty_print=True)
Other useful methods for XML manipulation:
  try:
    xml_root = etree.fromstring(xml_text)
  except etree.XMLSyntaxError:
    ...
  xml_cell.iterchildren(tag='data')
  xml_cell.get('toggle')
  try:
    xml_root = etree.parse(filename)
  except etree.XMLSyntaxError:
    ...
Useful methods for clipboard manipulation:
  clipboard = gtk.Clipboard(gtk.gdk.display_manager_get().get_default_display(), "CLIPBOARD")
  clipboard.set_text(xml_text)
  xml_text = clipboard.wait_for_text()
How to get all paths in TreeStore (useful for save):
  paths = []
  self.tree_store.foreach(lambda model, path, iter, user_data: paths.append(path), None)
See also [www.le-web.org] for details about URI copy/paste in Nautilus.

Note: If you allow multiple selections in TreeView the user may select a non-contiguous range of rows. Then you have to decide how to paste such weird selections. It is more convenient to describe the selections by paths than via iterators.

PyGTK FAQ Wizard | PyGTK Homepage | Feedback to faq at pygtk.org