开发者

How to update TreeModel after moving subtree

开发者 https://www.devze.com 2023-04-03 10:02 出处:网络
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.

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 the order of calling these functions is relevant (if so any idea how?)
  • technically child_toggle( (1,开发者_StackOverflow0) ) also happens, however the row is a) already deleted and b) row_has_child_toggled needs a tree_iter reference, which I can't get as it doesn't exist any more.

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


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.


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 !

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号