I want to use QFileDialog to have the user select an executable. The dialog should show only actual executables, aside from directories.
My Windows version works just fine, simply checking if the extension is exe. However, in Linux, I don't manage to do it as I want.
In C++, my attempt looked like this:
QString target_dir = ...
QFileDialog file_dialog;
file_dialog.setFilter(QDir::Executable | QDir::Files);
QString file = file_dialog.getOpenFileName(this, tr("Open Exectuable"), target_dir);
However, this code results in displaying all files.
I experimented with adding some other filters, but nothing worked so far. There are already two questions on StackOverflow that are essentially the same as mine, both without an actual answer:
Filtering executable files in QFileDialog on Linux
show only directories and executables on Ubuntu using QFileDialog
Does anybody know how it can be done? Or is QFileDialog simply not able to do it? Can it be done at all or is recognizing executables not that simple in general?
(Note: I work with Qt 4.8.5 since I use third party code that is incompatible with Qt 5, if that matters.)
(Note: Haven't tagged this as C++ since it's also relevant for Python.)
if you use native file dialogs some settings have no effect.
This should work:
QFileDialog dlg(this, tr("Select executable"));
dlg.setOption(QFileDialog::DontUseNativeDialog, true);
dlg.setFilter(QDir::Executable | QDir::Files);
Note that this will filer only executables. TO show folders at same time there is no known solution.
Use proxy model for file dialog.
In my case code is the following:
#include <QSortFilterProxyModel>
#include <QFileSystemModel>
// Custom proxy for filtering executables
class FileFilterProxyModel : public QSortFilterProxyModel
{
private:
virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
};
bool FileFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
QFileSystemModel* fileModel = qobject_cast<QFileSystemModel*>(sourceModel());
QFileInfo file( fileModel->filePath(sourceModel()->index(sourceRow, 0, sourceParent)) );
if (fileModel!=NULL && file.isExecutable())
return true;
else
return false;
}
// usage of proxy model
QFileDialog dialog( this, tr("Choose a file"));
FileFilterProxyModel* proxyModel = new FileFilterProxyModel;
dialog.setProxyModel(proxyModel);
dialog.setOption(QFileDialog::DontUseNativeDialog); // required by proxy model
if( dialog.exec() == QDialog::Accepted ) {
...
}
This shows executables and folders, tested on both Linux and Windows (Qt 4.8.6)
Full sources