Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

drag a file into QtGui.QLineEdit() to set url text

I've made a QtGui.LineEdit() widget in a python script using pySide Qt bindings and I'd like to be able to drag a file from the desktop into the QLineEdit to set the text in the QLineEdit to the path of the file. I've done QLineEdit.setDragEnabled(True) to enable drag and drop operations but I'm a bot lost about how to procede from here. Does anyone know how to achieve this?

like image 380
jonathan topf Avatar asked Aug 08 '12 19:08

jonathan topf


2 Answers

Usually, for events you can use the QObject.eventFilter and QObject.installEventFilter to do intercept events and process them. However, it does not seem to work for QDrag/QDrop events (and if I'm wrong on this - someone else please let me know as I've about pulled all my hair out trying to figure the way to get it to work with filtering).

The best way I know how to do it, you have to subclass the QLineEdit and overload the dragEnterEvent, dragMoveEvent and dropEvent methods to check to see if what is being dragged into your class is valid. Something like:

    from PySide.QtGui import QLineEdit

    class FileEdit(QLineEdit):
        def __init__( self, parent ):
            super(FileEdit, self).__init__(parent)

            self.setDragEnabled(True)

        def dragEnterEvent( self, event ):
            data = event.mimeData()
            urls = data.urls()
            if ( urls and urls[0].scheme() == 'file' ):
                event.acceptProposedAction()

        def dragMoveEvent( self, event ):
            data = event.mimeData()
            urls = data.urls()
            if ( urls and urls[0].scheme() == 'file' ):
                event.acceptProposedAction()

        def dropEvent( self, event ):
            data = event.mimeData()
            urls = data.urls()
            if ( urls and urls[0].scheme() == 'file' ):
                # for some reason, this doubles up the intro slash
                filepath = str(urls[0].path())[1:]
                self.setText(filepath)
like image 121
Eric Hulser Avatar answered Oct 12 '22 10:10

Eric Hulser


Using the eventFilter mechanism, mentioned above, does work, when used like this:

from PyQt4.QtCore import QObject, QEvent


class QLineEditDropHandler(QObject):    
    def eventFilter(self, watched, event):
        if event.type() == QEvent.DragEnter:
            # we need to accept this event explicitly to be able to receive QDropEvents!
            event.accept()
        if event.type() == QEvent.Drop:
            md = event.mimeData()
            if md.hasUrls():
                obj.setText(url.toLocalFile())
                return True
        return super().eventFilter(watched, event)

Now, one can use the drop handler on any line edit without subclassing:

lineEdit.installEventFilter(QLineEditDropHandler(self))
like image 6
Sebastian Elsner Avatar answered Oct 12 '22 10:10

Sebastian Elsner