Reputation: 873
I have a QListView
where items can be reordered with drag-and-drop by setting dragDropMode to DragDrop and defaultDropAction to MoveAction. How can I intercept the drop event, to find out what is trying to be moved where in relation to the rest of the list, so that I can cancel this action under certain conditions? E.g. I want to forbid moving some items behind other.
Upvotes: 1
Views: 751
Reputation: 6112
You can access the indexes and items involved in the dropEvent
and setDropAction to Qt.IgnoreAction
to cancel the drop depending on your criteria. Since you weren't specific, for this demonstration I just created one item that stays at the bottom.
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class List(QListView):
def dropEvent(self, event):
i = self.selectedIndexes()[0]
j = self.indexAt(event.pos())
# To access the items involved
source = self.model().itemFromIndex(i)
target = self.model().itemFromIndex(j)
bottom = (self.model().rowCount() - 1, -1)
if i.row() in bottom or j.row() in bottom:
event.setDropAction(Qt.IgnoreAction)
else:
super().dropEvent(event)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = QWidget()
lv = List()
lv.setDragDropMode(QAbstractItemView.DragDrop)
lv.setDefaultDropAction(Qt.MoveAction)
model = QStandardItemModel(5, 1)
for i in range(4):
item = QStandardItem(f'Item {i + 1}')
item.setFlags(item.flags() & ~Qt.ItemIsDropEnabled)
model.setItem(i, 0, item)
item = QStandardItem('I stay at the bottom ._.')
model.setItem(4, 0, item)
lv.setModel(model)
vbox = QVBoxLayout(window)
vbox.addWidget(lv)
window.show()
sys.exit(app.exec_())
Upvotes: 3