after being unable to find a decent generic hierarchical reorderable drag and drop example for Qt5's QTreeView, I tried to transform the Editable Tree Model example code accordingly.
There's an related question recorded at: QTreeView with drag and drop support in PyQt, but while it's PyQt4, which isn't a problem in itself (I'm going to convert this to PyQt anyway ;)), the treeview + abstract model doesn't work properly. At least, it doesn't reorder any items here.
This example code doesn't work as well: it allows moving items, but dropping them results in an empty row, but the entry isn't moved.
diff -up editabletreemodel.orig/mainwindow.cpp editabletreemodel/mainwindow.cpp
--- editabletreemodel.orig/mainwindow.cpp 2016-06-10 08:48:56.000000000 +0200
+++ editabletreemodel/mainwindow.cpp 2016-10-25 23:20:09.909671875 +0200
@@ -67,6 +67,7 @@ MainWindow::MainWindow(QWidget *parent)
file.close();
view->setModel(model);
+ view->setDragDropMode(QAbstractItemView::InternalMove);
for (int column = 0; column < model->columnCount(); ++column)
view->resizeColumnToContents(column);
diff -up editabletreemodel.orig/treemodel.cpp editabletreemodel/treemodel.cpp
--- editabletreemodel.orig/treemodel.cpp 2016-06-10 08:48:56.000000000 +0200
+++ editabletreemodel/treemodel.cpp 2016-10-25 23:23:47.408024344 +0200
@@ -96,10 +96,12 @@ QVariant TreeModel::data(const QModelInd
//! [3]
Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
{
- if (!index.isValid())
- return 0;
+ Qt::ItemFlags defaultFlags = Qt::ItemIsEditable | QAbstractItemModel::flags(index);
- return Qt::ItemIsEditable | QAbstractItemModel::flags(index);
+ if (index.isValid())
+ return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
+ else
+ return Qt::ItemIsDropEnabled | defaultFlags;
}
//! [3]
@@ -295,3 +297,8 @@ void TreeModel::setupModelData(const QSt
++number;
}
}
+
+Qt::DropActions TreeModel::supportedDropActions() const
+{
+ return Qt::MoveAction;
+}
diff -up editabletreemodel.orig/treemodel.h editabletreemodel/treemodel.h
--- editabletreemodel.orig/treemodel.h 2016-06-10 08:48:56.000000000 +0200
+++ editabletreemodel/treemodel.h 2016-10-25 23:19:18.884870266 +0200
@@ -95,6 +95,7 @@ public:
const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE;
bool removeRows(int position, int rows,
const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE;
+ Qt::DropActions supportedDropActions() const Q_DECL_OVERRIDE;
private:
void setupModelData(const QStringList &lines, TreeItem *parent);
In theory, this is all, what is needed to be able to reorder items.
Here's the PyQt5 version: --- editabletreemodel.py.orig 2015-07-17 13:39:33.000000000 +0200 +++ editabletreemodel.py 2016-10-26 00:24:51.857176297 +0200 @@ -44,7 +44,7 @@
from PyQt5.QtCore import (QAbstractItemModel, QFile, QIODevice,
QItemSelectionModel, QModelIndex, Qt)
-from PyQt5.QtWidgets import QApplication, QMainWindow
+from PyQt5.QtWidgets import QApplication, QMainWindow, QAbstractItemView
import editabletreemodel_rc
from ui_mainwindow import Ui_MainWindow
@@ -151,10 +151,12 @@ class TreeModel(QAbstractItemModel):
return item.data(index.column())
def flags(self, index):
- if not index.isValid():
- return 0
+ defaultFlags = Qt.ItemIsEditable | super(TreeModel, self).flags(index)
- return Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable
+ if index.isValid():
+ return defaultFlags | Qt.ItemIsDragEnabled | Qt.ItemIsDropEnabled
+ else:
+ return defaultFlags | Qt.ItemIsDropEnabled
def getItem(self, index):
if index.isValid():
@@ -296,6 +298,9 @@ class TreeModel(QAbstractItemModel):
number += 1
+ def supportedDropActions(self):
+ return Qt.MoveAction
+
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
@@ -311,6 +316,7 @@ class MainWindow(QMainWindow, Ui_MainWin
file.close()
self.view.setModel(model)
+ self.view.setDragDropMode(QAbstractItemView.InternalMove)
for column in range(model.columnCount()):
self.view.resizeColumnToContents(column)