Trying to implement drag and drop for QAbstractItemModel

Rodrigo de Salvo Braz rodrigobraz at gmail.com
Fri May 7 03:32:58 BST 2021


Hi Maurizio and others,

Just getting back to this thread to share some supplementary information.

On Sun, Apr 18, 2021 at 8:35 PM Maurizio Berti <maurizio.berti at gmail.com>
wrote:

> An important thing to remember is that you can't always completely rely on
> IDEs for debugging: not only they will probably hide the actual exception
> depending on their implementations, but they normally don't show the full
> traceback. When in doubt, just run your program from terminal/prompt and
> check the output.
>
> In your case, the crash is caused by the fact that you didn't correctly
> implement setData(), which **always** expects a bool as the returned value.
>
> Then, the problem is that you didn't implement the most important function
> for drop events in a model: dropMimeData().
>

When I read your sentence above, I interpreted it to mean that implementing
dropMimeData() was a *required* step to get drag and drop working. Not sure
if that was what you really meant, but experimenting more and looking at
the source code (a good idea I got from you!), I finally realized that
there is a pretty appropriate default dropMimeData() implementation
already, which does pretty much the same thing as the implementation you
suggested.

So the program below implements drag and drop without reimplementing
dropMimeData at all. Which makes sense given that the
"application/x-qabstractitemmodeldatalist" format is not documented, so
users shouldn't really have to know how to use it.

Just sharing in case someone else searches for similar things in the future.

Cheers,

Rodrigo

---------
import sys

from PyQt5 import QtCore, QtWidgets
from PyQt5.QtCore import Qt, QDataStream, QIODevice, QModelIndex
from PyQt5.QtWidgets import QApplication, QMainWindow, QTableView,
QAbstractItemView

# Attempting to implement drag-and-drop for an QAbstractTableModel as
described in
#
https://doc.qt.io/archives/qt-5.5/model-view-programming.html#using-drag-and-drop-with-item-views

class TableModel(QtCore.QAbstractTableModel):
    def __init__(self):
        super().__init__()
        self.dataList = [["Lion", "Tiger", "Bear"], ["Gazelle", "Ox",
"Pig"], ["Mouse", "Cat", "Dog"], ["Cow", "Giraffe", "Rhino"]]

    def data(self, index, role=None):
        if role == Qt.DisplayRole:
            return f"{self.dataList[index.row()][index.column()]}"

    def setData(self, index, value, role):
        self.dataList[index.row()][index.column()] = value
        self.dataChanged.emit(index, index)
        return True

    def rowCount(self, index):
        return len(self.dataList)

    def columnCount(self, index):
        return 3

    def flags(self, index):
        return Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled |
Qt.ItemIsDragEnabled | Qt.ItemIsDropEnabled

    def supportedDropActions(self):
        return Qt.CopyAction | Qt.MoveAction


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Drag and Drop app")

        self.tableView = QTableView()

        self.model = TableModel()
        self.tableView.setModel(self.model)

self.tableView.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)

        self.tableView.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.tableView.setDragEnabled(True)
        self.tableView.viewport().setAcceptDrops(True)
        self.tableView.setDropIndicatorShown(True)
        self.tableView.setDragDropMode(QAbstractItemView.DragDrop)
        self.tableView.setDragDropOverwriteMode(False)

        self.setCentralWidget(self.tableView)


app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec_()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20210506/6987c295/attachment.htm>


More information about the PyQt mailing list