Here some code where opens default windows dialog and user can select file which name starts with prefixName
and ends with ".log"
void doSomething(QString prefixName) {
auto result = QFileDialog::getOpenFileName(this, tr("Open log file"), path, QString(tr("%1 Log Files (%1*.log);;All Log Files(*.log)")).arg(prefixName));
if (result) {
// do something
}
}
Everything works fine when prefixName
contains just one word, i.e. prefixName = my_server
:
my_server_2023_10_10.log
my_server_2023_10_11.log
are shown
but if prefixName
contains )
no files will be shown.
Let's assume prefixName = my_server(007)
. I expect
my_server(007)_2023_10_10.log
my_server(007)_2023_10_11.log
files will be shown, but they don't
Why it can't list files with nested parenthesis?
After some while I found answer which works, but in not that way I was expecting. Result:
class LogFilterProxyModel : public QSortFilterProxyModel
{
private:
QRegExp m_regexp{".*"}; // by default accept all
public:
LogFilterProxyModel(QRegExp regexp) { m_regexp = regexp; }
void setRegexp(QRegExp re) { m_regexp = re; }
protected:
virtual bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override
{
if (!sourceParent.isValid()) { return true; }
QFileSystemModel* fileModel = qobject_cast<QFileSystemModel*>(sourceModel());
QModelIndex index0 = fileModel->index(sourceRow, 0, sourceParent);
// Don't apply filter on directories
if (fileModel == nullptr || fileModel->isDir(index0)) { return true; }
return m_regexp.exactMatch(index0.data().toString());
}
};
void someOtherFunc(QString configName) {
QString escapedConfigPath {configName};
escapedConfigPath.replace("(", "\\(").replace(")", "\\)");
QFileDialog dialog(this);
const QRegExp specificLogsRegex (escapedConfigPath + ".*\\.log");
const QRegExp anyLogRegex (".*\\.log");
LogFilterProxyModel* pLogFilter = new LogFilterProxyModel(specificLogsRegex);
QString filter1 {tr("%1 Log Files (*.log)").arg(configName)};
QString filter2 {tr("All Log Files (*.log)")};
dialog.setNameFilters({filter1, filter2});
connect(&dialog, &QFileDialog::filterSelected, this, [&](const QString& curFilter){
if (curFilter == filter1) {
pLogFilter->setRegexp(specificLogsRegex);
} else if (curFilter == filter2) {
pLogFilter->setRegexp(anyLogRegex);
}
});
dialog.exec();
}
I wanted on line QString filter1 {tr("%1 Log Files (*.log)").arg(configName)};
to search by %1 Log Files (%1*.log)".arg(configName)
(which will show to user which files are being searched by file dialog), but it starts searching incorrect with parentheses, so I gave up and left it as is.
This solution searches all .log files in the directory and only then applies custom regexp filter to them