[PyQt] Editable reorderable (by drag and drop) QTreeView example
Hans-Peter Jansen
hpj at urpla.net
Wed Oct 26 14:03:44 BST 2016
Hi PyQties,
after being unable to find a decent generic hierarchical reorderable drag
and drop example for QTreeView, I tried to transform the Editable Tree Model
example code accordingly.
--- 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)
In theory, this is all, what is needed to be able to reorder items in a
QListView, is it?
While this change allows moving items, dropping them results in an empty row,
and the entry isn't moved at all.
Any idea, what I'm missing here, before I dive into the source of
Q{Standard,Abstract}ItemModel, that allows exactly this?
E.g.:
import sys
from PyQt5 import QtGui, QtCore, QtWidgets
class StandardItemModel(QtGui.QStandardItemModel):
def __init__(self, parent = None):
super(StandardItemModel, self).__init__(parent)
def itemList(self, parent = QtCore.QModelIndex()):
items = []
for row in range(self.rowCount(parent)):
idx = self.index(row, 0, parent)
items.append(self.data(idx))
if self.hasChildren(idx):
items.append(self.itemList(idx))
return items
def populate(self):
for row in range(0, 10):
parentItem = self.invisibleRootItem()
for col in range(0, 4):
item = QtGui.QStandardItem("item (%s, %s)" % (row, col))
parentItem.appendRow(item)
parentItem = item
class MainForm(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainForm, self).__init__(parent)
self.model = StandardItemModel()
self.model.populate()
self.view = QtWidgets.QTreeView()
self.view.setModel(self.model)
self.view.setHeaderHidden(True)
self.view.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove)
self.setCentralWidget(self.view)
def main():
app = QtWidgets.QApplication(sys.argv)
form = MainForm()
form.show()
app.exec_()
print(form.model.itemList())
if __name__ == '__main__':
main()
TIA,
Pete
-------------- next part --------------
A non-text attachment was scrubbed...
Name: dnd-py.diff
Type: text/x-patch
Size: 1581 bytes
Desc: not available
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20161026/9da1cdcb/attachment-0001.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: editabletreemodel.py
Type: text/x-python
Size: 14201 bytes
Desc: not available
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20161026/9da1cdcb/attachment-0002.py>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: treeview.py
Type: text/x-python
Size: 1432 bytes
Desc: not available
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20161026/9da1cdcb/attachment-0003.py>
More information about the PyQt
mailing list