Search code examples
c++qtdrag-and-dropqtreewidgetqtreewidgetitem

QTreeWidget reordering child items by dragging


I have a QTreeWidget which displays a single root node and one level of child nodes only. I need to permit the re-ordering of the child nodes. They must never be re-parented.

This is how I enable the dragging of items in the QTreeWidget :

ui->levelElements->setSelectionMode(QAbstractItemView::SingleSelection);
ui->levelElements->setDragEnabled(true);
ui->levelElements->viewport()->setAcceptDrops(true);
ui->levelElements->setDropIndicatorShown(true);
ui->levelElements->setDragDropMode(QAbstractItemView::InternalMove);

The root item is inserted like this :

pItem = new QTreeWidgetItem(ui->levelElements);
pItem->setText(0, node.firstChild().nodeValue());
pItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled);

When I insert a child into the view, it is declared like this :

pItem = new QTreeWidgetItem();
pItem->setText(0, strFileName);
pItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled);
pTreeRoot->addChild(pItem);

At this point, I am able to drag a child item and "re-insert" it in the list of child items. I can also move it to the root level - which I do not want.

I am using QT Creator v3 and so the QTreeWidget is within my UI definition file.

Have I missed something here ?


Solution

  • For example you can override: virtual void dropEvent(QDropEvent * event)

    #include <QApplication>
    #include <QTreeWidget>
    #include <QTreeWidgetItem>
    #include <QDropEvent>
    
    class TreeView: public QTreeWidget
    {
    public:
      TreeView()
      {
        resize(200, 300);
    
        setSelectionMode(QAbstractItemView::SingleSelection);
        setDragEnabled(true);
        viewport()->setAcceptDrops(true);
        setDropIndicatorShown(true);
        setDragDropMode(QAbstractItemView::InternalMove);
    
        QTreeWidgetItem* parentItem = new QTreeWidgetItem(this);
        parentItem->setText(0, "Test");
        parentItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled);
    
        for(int i = 0; i < 10; ++i)
        {
          QTreeWidgetItem* pItem = new QTreeWidgetItem(parentItem);
          pItem->setText(0, QString("Number %1").arg(i) );
          pItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled);
          pItem->addChild(pItem);
        }
      }
    
    private:
      virtual void  dropEvent(QDropEvent * event)
      {
        QModelIndex droppedIndex = indexAt( event->pos() );
    
        if( !droppedIndex.isValid() )
          return;
    
        QTreeWidget::dropEvent(event);
      }
    };
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        TreeView widget;
        widget.show();
    
        return a.exec();
    }