Как обновить TreeModel после перемещения поддерева - PullRequest
3 голосов
/ 06 сентября 2011

У меня есть пользовательский GenericTreeModel, который работает просто отлично. Теперь я хочу, чтобы пользователь мог переставлять узлы с помощью перетаскивания, поэтому я перемещаю узел к его новому родителю в модели данных. Однако затем TreeModel хочет получать уведомления, используя такие методы, как row_has_child_toggled, row_deleted и row_inserted.

Таким образом, очевидно, что нет row_moved, и вызовов row_deleted (для первоначального пути) и row_inserted (для нового пути) кажется недостаточно. Поэтому я подумал, что, возможно, придется рекурсивно выдавать эти изменения.

Рассмотрим следующий пример:

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

Теперь, если я переместлю C в A, произойдут следующие вещи:

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'

Однако gtk по-прежнему жалуется на несовместимое состояние модели. Две вещи приходят мне на ум:

  • может быть, порядок вызова этих функций уместен (если да, то как?)
  • технически child_toggle( (1,0) ) также происходит, однако строка a) уже удалена и b) row_has_child_toggled нужна ссылка tree_iter, которую я не могу получить, поскольку ее больше не существует.

Может быть, я придерживаюсь абсолютно неправильного подхода, так как лучше всего это сделать?

Ответы [ 2 ]

2 голосов
/ 09 сентября 2011

Понял: удаление поддерева работает нормально, удаляя строку корневого узла поддерева (уведомите модель об отсутствии пути и условно переключив parent.has_child).То же самое касается вставки нового поддерева, поэтому мне не нужно рекурсивно рассказывать материал модели.

Однако комбинация имеет решающее значение, поэтому

  1. сначала удалите, уведомите модель
  2. , затем вставьте и уведомите модель снова.
1 голос
/ 06 сентября 2011

ИМХО, это обновление должно происходить автоматически для древовидной структуры, если вы правильно подключите древовидную структуру с помощью методов «drag_data_get» и «drag_data_received» И позволит ей быть источником и местом назначения с помощью методов «enable_model_drag_dest» и «enable_model_drag_source» , Больше ничего не нужно делать для дерева.

Модель должна быть обновлена ​​в вызовах ее «drag_data_received_data», но нет «удаления», чтобы сделать, только конкретные «insert_before» или «insert_after», как показано здесь:

   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

Этот фрагмент взят из:

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

, где программа treeviewdnd.py отлично работает, чтобы показать вам, что вам нужно.

Надеюсь, это решит ваш квест!

...