Multiple files AND folder selection in a QFileDialog?

sahilgupta picture sahilgupta · Jun 26, 2011 · Viewed 9.3k times · Source

I am using pyQt4 and want to have a Browse button in my GUI which opens up a Dialog box allowing user to select multiple files AND folders. I have researched quite a bit but din't find any way to be able to do this.

The QFileDialog.getOpenFileNames() only allows me to choose files and QFileDialog.getExistingDirectory() only allows to choose directories.

Is there any way I can somehow combine their functionality. Ideally I would like to use the nativeDialogs but that doesn't seem to be possible. As a result I am willing to compromise on the looks. Is there any way I can implement the said?

The same question has been asked here as well but the answer is in c++. I need a python implementation. Allow user to select a file or a folder in QFileDialog

Answer

Luke picture Luke · Jul 5, 2011

Here's a hack that should work for you: Create a subclass of QFileDialog that disconnects the "Open" button and reconnects it to a customized function. It's not guaranteed to work across different versions of Qt, though, since it relies on being able to find specific sub-widgets that may be reconfigured at some point.

class FileDialog(QtGui.QFileDialog):
    def __init__(self, *args):
        QtGui.QFileDialog.__init__(self, *args)
        self.setOption(self.DontUseNativeDialog, True)
        self.setFileMode(self.ExistingFiles)
        btns = self.findChildren(QtGui.QPushButton)
        self.openBtn = [x for x in btns if 'open' in str(x.text()).lower()][0]
        self.openBtn.clicked.disconnect()
        self.openBtn.clicked.connect(self.openClicked)
        self.tree = self.findChild(QtGui.QTreeView)

    def openClicked(self):
        inds = self.tree.selectionModel().selectedIndexes()
        files = []
        for i in inds:
            if i.column() == 0:
                files.append(os.path.join(str(self.directory().absolutePath()),str(i.data().toString())))
        self.selectedFiles = files
        self.hide()

    def filesSelected(self):
        return self.selectedFiles