Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filtering in QFileDialog

I would like to filter the files that are shown in a QFileDialog more specifically than just by file extensions. The examples I found in the Qt documentation only show filters like Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml) and such. In addition to this I would also like to specify a filter for files that should not show up in the file dialog, e.g. XML files (*.xml) but not Backup XML files (*.backup.xml).

So the problem I have is that I would like to show some files in the file dialog that have certain file extension, but I would not like to show other files with a specific file name suffix (and the same file extension).

For example:

Files to show:

file1.xml  
file2.xml

Files not to show:

file1.backup.xml  
file2.backup.xml

I would like to ask if it is possible to define filters like these for a QFileDialog?

like image 980
Bitjuggler Avatar asked Feb 03 '11 23:02

Bitjuggler


2 Answers

I believe what you can do is:

  1. Create a custom proxy model. You can use QSortFilterProxyModel as a base class for your model;
  2. In the proxy model override the filterAcceptsRow method and return false for files which have the ".backup." word in their names;
  3. Set new proxy model to the file dialog: QFileDialog::setProxyModel;

Below is an example:

Proxy model:

class FileFilterProxyModel : public QSortFilterProxyModel
{
protected:
    virtual bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const;
};

bool FileFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
    QModelIndex index0 = sourceModel()->index(sourceRow, 0, sourceParent);
    QFileSystemModel* fileModel = qobject_cast<QFileSystemModel*>(sourceModel());
    return fileModel->fileName(index0).indexOf(".backup.") < 0;
    // uncomment to call the default implementation
    //return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
}

dialog was created this way:

QFileDialog dialog;
dialog.setOption(QFileDialog::DontUseNativeDialog);
dialog.setProxyModel(new FileFilterProxyModel);
dialog.setNameFilter("XML (*.xml)");
dialog.exec();

The proxy model is supported by non-native file dialogs only.

like image 78
serge_gubenko Avatar answered Oct 17 '22 07:10

serge_gubenko


The solution of @serge_gubenko is working well. Create your own ProxyModel by inheriting from the QSortFilterProxyModel.

class FileFilterProxyModel : public QSortFilterProxyModel
{
protected:
    virtual bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const;
};

bool FileFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
    // Your custom acceptance condition
    return true;
}

Just make sure to set DontUseNativeDialog before setting the Proxy model (Edit: @serge_gubenkos answer does that now). Native dialogs do not support custom ProxyModels.

QFileDialog dialog;
dialog.setOption(QFileDialog::DontUseNativeDialog);
dialog.setProxyModel(new FileFilterProxyModel);
dialog.setNameFilter("XML (*.xml)");
dialog.exec();

It took quite some time for me to find this out. This was written here

like image 41
miile7 Avatar answered Oct 17 '22 05:10

miile7