Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Item gets duplicated in the model after drag-n-drop in QTreeView



  • I have a QStandardItemModel() with a number of QStandardItem() elements displayed in a customized QTreeView().
    It's a simple tree, and after the element is dragged and dropped I need to save this change to the database.
    The drag-n-drop mode set to QAbstractItemView.InternalMove
    Now here's the problem that I'm facing.
    Suppose we had a tree:

    parent
    - childA
    - childB
    - childC
    

    And dragged childC above childB:

    parent
    - childA
    - childC
    - childB
    

    I'm listing the items using this code:

    self.model.itemChanged.connect(self.item_changed)
    

    ...

    def item_changed(self, item):
        par = item.parent()
            for i in range(0,par.rowCount()):
                print(i,par.child(i).text()) 
    

    And it returns this:

    childA
    childC
    childB
    childC
    

    I.e. it lists the dragged element twice - at its previous position and at its current position. In the tree everything is fine, the items are not duplicated.

    Why is that? How can I reliably track the reorder operations like this to save this state?
    Thanks.

    P.S. I also saw the same problem when I tried to get the data from the model inside dropEvent() of my QTreeView() implementation.



  • Looks like this is the expected behavior, and it's described here: https://stackoverflow.com/questions/52873025/pyqt5-qlistview-drag-and-drop-creates-new-hidden-items

    When an item moves from position i to position j, what is done is:

    • Insert an item in position j
    • Copy the data to the new item, at this moment the itemChanged signal is emitted and therefore you see that there are elements of more
    • Delete the item that was in the position i.

    So my question is: which method should I use to save the data after the item in the position i was deleted?

    At the moment it looks like I have to save the data in one of the 2 places:

    • in dropEvent() of my TreeView
    • in a method called by itemChanged() of the model, where I'll have to compare the model indexes to distinguish between the new and the old position of the element

Log in to reply