Filtering in QFileDialog

2019-01-15 15:35发布

问题:

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?

回答1:

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.setProxyModel(new FileFilterProxyModel);
dialog.setNameFilter("XML (*.xml)");
dialog.setOption(QFileDialog::DontUseNativeDialog);
dialog.exec();

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



回答2:

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 (not the way that @serge_gubenko did it). 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



回答3:

Okay, I've used it with QFileDialog object. And this only shows me the files listed in the appropriate directory. It is excellent to just choose the files to be processed. For example, an XML file, a PNG image, etcetera.

Here I present my example

 OlFileDialog QFileDialog (this); 
 QString slFileName; 
 olFileDialog.setNameFilter (tr ("Files (* xml)")); 
 olFileDialog.setFileMode (QFileDialog :: anyfile); 
 olFileDialog.setViewMode (QFileDialog :: Detail); 
 if (olFileDialog.exec ()) 
     olFileDialog.selectFile (slFileName); 
 else 
     return; 

The dialog box will display only presents xml files.