rumpel
rumpel

Reputation: 8290

How to update TreeModel after moving subtree

I have a custom GenericTreeModel, that works just fine. Now I want the user to be able to rearrange the nodes using drag and drop, so I move a node to its new parent in the data model. However then, the TreeModel wants to be notified using methods like row_has_child_toggled, row_deleted and row_inserted.

So apparently there is no row_moved and calling row_deleted (for the original path) and row_inserted (for the new path) seems not to be enough. So I thought I may have to recursively issue these changes.

Consider the following example:

* A (0,)
* B (1,)
  * C (1,0)
    * D (1,0,0)

Now, if I move C to A, the following things have happened:

row_delete( (1,0) ) # C
row_delete( (1,0,0) ) # D
row_inserted( (0,0) ) # C'
row_inserted( (0,0,0) ) # D'
child_toggle( (0,) ) # A
child_toggle( (1,) ) # B
child_toggle( (0,1) ) # C'

However, gtk still complains about inconsistent state of the model. Two things come to my mind:

Maybe I am following a totally wrong approach here, so what’s the best way to go about this?

Upvotes: 3

Views: 527

Answers (2)

rumpel
rumpel

Reputation: 8290

Figured it out: Removing a subtree works fine by removing the subtree’s root node row (notify the model that the path is gone and conditionally toggling parent.has_child). Same goes for insertion of a new subtree, so I don't need to tell the model stuff recursively.

However the combination is critical, so

  1. first remove, notify model
  2. then insert and notify model again.

Upvotes: 2

Louis
Louis

Reputation: 2890

IMHO, this update should happen automatically for the treeview, if you connect the treeview correctly with its "drag_data_get" and "drag_data_received" methods AND allows it to be a source and a destination with its "enable_model_drag_dest" and "enable_model_drag_source" methods. There should be nothing more to do for the treeview.

The model must be updated in the calls to its "drag_data_received_data", but there is no "delete" to do, just the specific "insert_before" or "insert_after" as shown here :

   def drag_data_received_data(self, treeview, context, x, y, selection,
                               info, etime):
       model = treeview.get_model()
       data = selection.data
       drop_info = treeview.get_dest_row_at_pos(x, y)
       if drop_info:
           path, position = drop_info
           iter = model.get_iter(path)
           if (position == gtk.TREE_VIEW_DROP_BEFORE
               or position == gtk.TREE_VIEW_DROP_INTO_OR_BEFORE):
               model.insert_before(iter, [data])
           else:
               model.insert_after(iter, [data])
       else:
           model.append([data])
       if context.action == gtk.gdk.ACTION_MOVE:
           context.finish(True, True, etime)
       return

This snippet comes from :

http://www.pygtk.org/pygtk2tutorial/sec-TreeViewDragAndDrop.html#DragDropReordering

where the program " treeviewdnd.py" works perfectly to show you what you need.

Hope this solves your quest !

Upvotes: 1

Related Questions