Reputation: 402
I'm using a QTreeView to display a custom model that derives from QAbstractItemModel.
I want to enable moving of tree items within the QTreeView via drag and drop and thus used setDragDropMode(QAbstractItemView.InternalMove)
on the QTreeView. This works well for moving items around within the view, but this now also allows dragging items onto other elements, like for example all window title bars or the bookmarks bar in Firefox. Dropping items there causes the tree item to be deleted from the view.
Is that intended behavior of QAbstractItemView.InternalMove
? The docs specify this option as The view accepts move (not copy) operations only from itself.
(source) which implies that dragging outside the view should not be possible to me.
Am I missing a different property here? Is it even possible to allow drag and drop only within a view? The docs are pretty vague regarding this.
Edit: Minimal, Reproducible Example with PyQt
import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
app = QApplication(sys.argv)
model = QStandardItemModel()
model.setRowCount(10)
model.setColumnCount(1)
for i in range(0, 10):
model.setData(model.index(i, 0), 'Row %d' % i, Qt.DisplayRole)
view = QTreeView()
view.setDragDropMode(QAbstractItemView.InternalMove)
view.setModel(model)
view.show()
app.exec_()
Upvotes: 1
Views: 1720
Reputation: 1997
Well, the native (OS) drag-n-drop protocols don't allow to say "internal move only". Qt implements InternalMove
internally (to forbid dropping on other Qt views) but from the point of the view of the native DnD protocol, it's a move, which can be dropped to another process, if it accepts it.
IMHO the real bug here is that the Firefox bookmarks bar accepts any drop, whatever the mimeType. It then does nothing with it (obviously, since it can't read its contents), but since it accepts the drop, Qt proceeds to remove the row from the source model.
Anyhow - there are solutions once you implement a custom model rather than using QStandardItemModel
(which I assume was just for the benefit of making the example short). In your own model you can implement dropMimeData()
, move items there, and return false. If you don't implement removeRows()
in that model, then the removal in case of external DnD won't happen. I'm working on videos (for the KDABTV YouTube channel) and code samples with such code, but that's not published yet.
Upvotes: 0