MJB
MJB

Reputation: 873

How to modify drop event in QListView

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

Answers (1)

alec
alec

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

Related Questions