tags:

views:

550

answers:

2

I've got a Qt4 application (using the PyQt bindings) which contains a QListWidget, initialized like so:

class MyList(QtGui.QListWidget):
    def __init__(self):
        QtGui.QListWidget.__init__(self)
        self.setDragDropMode(self.InternalMove)

I can add items, and this allows me to drag and drop to reorder the list. But how do I get notification when the list gets reordered by the user? I tried adding a dropMimeData(self, index, data, action) method to the class, but it never gets called.

+1  A: 

Not a solution, but some ideas:

You should probably check what is returned by supportedDropActions method. It might be that you need to overwrite that method, to include Qt::MoveAction or Qt::CopyAction.

You have QListView::indexesMoved signal, but I am not sure whether it will be emitted if you're using QListWidget. It worths checking.

Cătălin Pitiș
There is a known bug in Qt 4.5.x that the QListView::indexesMoved signal never fires. You are forced to install an eventFilter and handle it yourself.
Trey Stout
+3  A: 

I just had to deal with this. It's a pain in the ass but you have to install an event filter on your ListWidget subclass and then watch for the ChildRemoved event. Note that this event covers moves as well as removal. So it should work for re-arranging items with drag and drop inside a list.

I write my Qt in C++, but here's an (untested) pythonification:

class MyList(QtGui.QListWidget):
    def __init__(self):
        QtGui.QListWidget.__init__(self)
        self.setDragDropMode(self.InternalMove)
        self.installEventFilter(self)

    def eventFilter(self, sender, event):
        if (evt.type() == QEvent::ChildRemoved):
            self.on_order_changed()
        return False # don't actually interrupt anything

    def on_order_changed(self):
        # do magic things with our newfound knowledge

If you have some other class that contains this list, you may want to move the event filter method there. Hope this helps, I know I had to fight with this for a day before figuring this out.

Trey Stout