Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Solved Treeview Drag and Drop row with multiple columns issue on root index

    General and Desktop
    2
    6
    330
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • alom
      alom last edited by

      Hi,
      I have a treeview/QStandardItemModel with a dragDropMode set to InternalMove and a selectionBehavoir set to SelectRows. The model has three columns. The expected behavior from the user is to move the three columns in a row as a whole and rearrange the tree hierarchy as needed.

      Everything works as expected when dragging and dropping a row from column 0 on top of anther column 0. I've set the items flags on the column 1/2 items not to accept drops. The issue comes when dragging from a row to the root Item on the model and dropping in on column 1 or 2. This causes the model to create extra columns and places column 0 data in one the incorrect columns.

      How can I treat the selected row and all its items drop to always drop on column 0, when dropping on the root index?
      Do I have to re implement one of the dragDrop functions on the QStandardItemModel?

      Thanks

      1 Reply Last reply Reply Quote 0
      • SGaist
        SGaist Lifetime Qt Champion last edited by

        Hi,

        What version of Qt are you using ?
        On what OS ?
        Can you provide a minimal compilable example that shows that behaviour ?

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply Reply Quote 1
        • alom
          alom last edited by alom

          Hi SGaist,
          Sure, I'm on Windows 10 pro, Pyside2 v5.13.2, py3.7.6
          I was hoping to post here without python code to get more eyes on this issue than in python forum, I'm sure some of the c++ guys have ran into this before.

          So you can drop a "child" index under any parent and root index. The parents can be drop in each other. The issue is when dropping a child or parent on the root index on column 1 or 2.

          
          import sys
          from PySide2 import QtWidgets, QtGui
          from PySide2.QtCore import Qt
          
          
          class SnippetTreeView(QtWidgets.QTreeView):
          
              def __init__(self, parent=None):
                  super(SnippetTreeView, self).__init__(parent)
                  self.setContextMenuPolicy(Qt.CustomContextMenu)
                  self.setDragEnabled(False)
                  self.setDragDropOverwriteMode(False)
                  self.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove)
                  self.setAlternatingRowColors(True)
                  self.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
                  # self.setSortingEnabled(True)
                  self.header().setStretchLastSection(True)
                  self.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
          
          
          def create_tag_color_items():
              item_tag = QtGui.QStandardItem('tag')
              item_tag.setDropEnabled(False)
              item_color = QtGui.QStandardItem('color')
              item_color.setDropEnabled(False)
              return item_tag, item_color
          
          
          def add_items(model):
              headers = [
                  'Name',
                  'Tag',
                  'Color',
              ]
              names = [
                  'child-0',
                  'child-1',
              ]
          
              model.setHorizontalHeaderLabels(headers)
              model.setColumnCount(len(headers))
          
              for num in range(2):
                  parent_item = QtGui.QStandardItem('parent-yesDrops-' + str(num))
                  parent_item.setDropEnabled(True)
                  item_tag, item_color = create_tag_color_items()
          
                  for name in names:
                      child_item = QtGui.QStandardItem(name + '-noDrops' )
                      child_item.setDropEnabled(False)
                      ch_item_tag, ch_item_color = create_tag_color_items()
                      parent_item.appendRow([child_item, ch_item_tag, ch_item_color])
          
                  model.appendRow([parent_item, item_tag, item_color])
          
          
          if __name__ == '__main__':
              app = QtWidgets.QApplication(sys.argv)
              tree = SnippetTreeView()
              model = QtGui.QStandardItemModel()
              add_items(model)
              tree.setModel(model)
              tree.show()
              rec = app.exec_()
              sys.exit(rec)
          
          1 Reply Last reply Reply Quote 0
          • alom
            alom last edited by alom

            I did see the canDropMineData function in the model.
            How correct/safe is this approach? Am I missing any important handing of other information floating around when doing this?

            I just return a false bool on any column greater than 0.

            class DropModel(QtGui.QStandardItemModel):
                def __init__(self, parent=None):
                    super(DropModel, self).__init__(parent)
            
                def canDropMimeData(self, data, action, row, column, parent):
                    if column > 0:
                        return False
                    return QtGui.QStandardItemModel().canDropMimeData(data, action, row, column, parent)
            
            1 Reply Last reply Reply Quote 0
            • SGaist
              SGaist Lifetime Qt Champion last edited by

              What about subclassing QStandardItemModel like that:

              class MyModel(QtGui.QStandardItemModel):
                  def dropMimeData(self, data, action, row, column, parent):
                      return super().dropMimeData(data, action, row, 0, parent)
              

              ?

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply Reply Quote 1
              • alom
                alom last edited by alom

                Oh very nice!
                I think that was what I was looking for. Feels much cleaner.
                Thanks @SGaist !

                1 Reply Last reply Reply Quote 0
                • First post
                  Last post