4
votes

So my current listview code simply allows me to drag and drop files on the computer into my listview. What I want is to be able to rearrange the listview items, the issue is when I try to it gets overwritten with the drop method to import files and nothing happens. For example if the drag is from outside the listview I want it to import, if the drag is internal, or rather from within the listview, I would like it to simply move like it would with InternalMove.

Adding this to my code:

self.listView.setDragDropMode(QtGui.QAbstractItemView.InternalMove);

While commenting out this:

def dropEvent(self, event):
    if event.mimeData().hasUrls:
        event.setDropAction(QtCore.Qt.CopyAction)
        event.accept()
        links = []
        for url in event.mimeData().urls():
            links.append(str(url.toLocalFile()))
        self.emit(QtCore.SIGNAL("dropped"), links)
    else:
        event.ignore()

Causes the rearranging to work flawlessly, but won't allow me to import files by dragging.

Because of this I've gathered the above is the cause of my issues but I just can't figure out how to fix it and have both working at the same time, it seems like it should be an easy fix.

I don't know if it's the right direction, but I know:

if event.mimeData().hasUrls:

Returns true if from outside the listview, and returns false if within the listview

You will most possibly notice the above code is from: http://tech.xster.net/tips/pyqt-drag-images-into-list-widget-for-thumbnail-list/ and http://zetcode.com/tutorials/pyqt4/dragdrop/

I know I could create a setup that query's the mouse pos and deletes the item and re-adds it at the closest position, but that seems like so much trouble when InternalMove is built in and works for my needs.

Any help would be greatly appreciated, thanks for the time!

1
That appears to be what I'm looking for, but I'll let you know once I have it working, you should re-post it as an answer that way if it does work I can select it! Thanks!cbarnett

1 Answers

4
votes

Piotr's answer was half way to where I needed to be. I actually found the rest of the answer to my question here -> http://sjt.is/2012/05/23/pyqt-and-dragndrop/

I simply defined my listview as:

mylist = TestListView(self)

Then used the below code as the class definition:

class TestListView(QtGui.QListWidget):

    def __init__(self, parent):
        super(TestListView, self).__init__(parent)
        self.setAcceptDrops(True)
        self.setIconSize(QtCore.QSize(100, 100))
        self.itemClicked.connect(self.on_item_clicked)
        self.setDragDropMode(QtGui.QAbstractItemView.InternalMove)


    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls:
            event.acceptProposedAction()
        else:
            super(TestListView, self).dragEnterEvent(event)

    def dragMoveEvent(self, event):
        super(TestListView, self).dragMoveEvent(event)

    def dropEvent(self, event):
        if event.mimeData().hasUrls():
            links = []
            for url in event.mimeData().urls():
                links.append(str(url.toLocalFile()))
            self.emit(QtCore.SIGNAL("dropped"), links)
            event.acceptProposedAction()
        else:
            super(TestListView,self).dropEvent(event)

When new files are dropped it emits a signal to a function connected to the listview. When an old file is dropped it is moved. Thanks for the help!