13

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

Community
  • 1
  • 1
sahilgupta
  • 135
  • 1
  • 1
  • 8
  • 1
    Unfortunately, I suspect the answer is "no". The C++ answer you referred to above is not valid. Options are: 1) file a wish with the Qt devs, 2) write your own file dialog, 3) fix it yourself. If you can think of a Qt project that does this, it would be interesting to see how it was implemented. – Luke Jul 05 '11 at 15:25

2 Answers2

11

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
sahilgupta
  • 135
  • 1
  • 1
  • 8
Luke
  • 10,462
  • 2
  • 42
  • 58
  • 1
    Thanks a lot! It worked great. However I had to change one line to get it working as per my needs. `files.append(os.path.join(str(self.directory().absolutePath()),str(i.data().toString())))` – sahilgupta Jul 06 '11 at 13:51
  • I face one issue however, the selected directories are not indicated in the Files_name line edit in the dialog while the files are, although both **can** be selected and succesfully returned by the filesSelected(). Any workaround possible around this, to avoid the user ending up being confused? – sahilgupta Jul 06 '11 at 14:00
  • I suppose the treeview's selectionmodel emits a signal when the selection changes, and this signal is caught to update the text in the lineedit. You could disconnect the signal and reconnect it to a custom function that has the behavior you expect.. – Luke Jul 07 '11 at 12:52
  • I can't get this to work. Can someone provide an example of the call? Is it something like this: mylist = FileDialog.getExistingDirectory(self, "Select Files and Folders","", QtGui.QFileDialog.DontConfirmOverwrite) – panofish Nov 18 '14 at 18:41
  • @Luke: I implemented your idea in C++, but it does not work, meaning that it is either files or directories that selectedFiles will return (depending on the mode set in the ctor), but not handling both simultaneously. Here is [my snippet](https://paste.kde.org/phpd0bfbw). Can you please point out what I am doing wrong? – lpapp Dec 17 '14 at 08:41
2

In Qt5 you can simply use

return QtWidgets.QFileDialog.getOpenFileNames(self, title, directory, filter=filterFile)
nkr
  • 2,947
  • 7
  • 28
  • 37
jluc
  • 31
  • 1
  • come again ...? – markling Apr 24 '19 at 07:44
  • @markling Notice the 's' in `getOpenFileNames`: https://doc-snapshots.qt.io/qtforpython-5.15/PySide2/QtWidgets/QFileDialog.html?highlight=qfiledialog#PySide2.QtWidgets.PySide2.QtWidgets.QFileDialog.getOpenFileNames – Lorem Ipsum Apr 05 '21 at 17:22