Commit 1f8b2dc3 authored by Eike Ziller's avatar Eike Ziller
Browse files

Advanced search: Add exclusion patterns



All files with full file path matching one of the exclusion patterns are
ignored in the search.
Searching with "git grep" now requires git >= 1.9

Change-Id: Ied5d11499bc1ff21247e50f8e146e8e5011dd2c1
Reviewed-by: David Schulz's avatarDavid Schulz <david.schulz@qt.io>
Reviewed-by: Orgad Shaneh's avatarOrgad Shaneh <orgads@gmail.com>
parent 99a6d78b
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
\row \row
\li \l{Using Git}{Git} \li \l{Using Git}{Git}
\li \l{http://git-scm.com/} \li \l{http://git-scm.com/}
\li Git version 1.8.0, or later \li Git version 1.9.0, or later
Gerrit version 2.6, or later Gerrit version 2.6, or later
\row \row
......
...@@ -23,11 +23,14 @@ ...@@ -23,11 +23,14 @@
** **
****************************************************************************/ ****************************************************************************/
#include "algorithm.h"
#include "filesearch.h" #include "filesearch.h"
#include "fileutils.h"
#include "mapreduce.h" #include "mapreduce.h"
#include <QCoreApplication> #include <QCoreApplication>
#include <QMutex> #include <QMutex>
#include <QRegExp>
#include <QRegularExpression> #include <QRegularExpression>
#include <QTextCodec> #include <QTextCodec>
...@@ -457,6 +460,50 @@ QString matchCaseReplacement(const QString &originalText, const QString &replace ...@@ -457,6 +460,50 @@ QString matchCaseReplacement(const QString &originalText, const QString &replace
return replaceText; // mixed return replaceText; // mixed
} }
} // namespace
static QList<QRegExp> filtersToRegExps(const QStringList &filters)
{
return Utils::transform(filters, [](const QString &filter) {
return QRegExp(filter, Qt::CaseInsensitive, QRegExp::Wildcard);
});
}
static bool matches(const QList<QRegExp> &exprList, const QString &filePath)
{
return Utils::anyOf(exprList, [&filePath](QRegExp reg) {
return (reg.exactMatch(filePath)
|| reg.exactMatch(Utils::FileName::fromString(filePath).fileName()));
});
}
static bool isFileIncluded(const QList<QRegExp> &filterRegs, const QList<QRegExp> &exclusionRegs,
const QString &filePath)
{
const bool isIncluded = filterRegs.isEmpty() || matches(filterRegs, filePath);
return isIncluded && (exclusionRegs.isEmpty() || !matches(exclusionRegs, filePath));
}
std::function<bool(const QString &)>
filterFileFunction(const QStringList &filters, const QStringList &exclusionFilters)
{
const QList<QRegExp> filterRegs = filtersToRegExps(filters);
const QList<QRegExp> exclusionRegs = filtersToRegExps(exclusionFilters);
return [filterRegs, exclusionRegs](const QString &filePath) {
return isFileIncluded(filterRegs, exclusionRegs, filePath);
};
}
std::function<QStringList(const QStringList &)>
filterFilesFunction(const QStringList &filters, const QStringList &exclusionFilters)
{
const QList<QRegExp> filterRegs = filtersToRegExps(filters);
const QList<QRegExp> exclusionRegs = filtersToRegExps(exclusionFilters);
return [filterRegs, exclusionRegs](const QStringList &filePaths) {
return Utils::filtered(filePaths, [&filterRegs, &exclusionRegs](const QString &filePath) {
return isFileIncluded(filterRegs, exclusionRegs, filePath);
});
};
} }
QString matchCaseReplacement(const QString &originalText, const QString &replaceText) QString matchCaseReplacement(const QString &originalText, const QString &replaceText)
...@@ -562,8 +609,9 @@ namespace { ...@@ -562,8 +609,9 @@ namespace {
} }
SubDirFileIterator::SubDirFileIterator(const QStringList &directories, const QStringList &filters, SubDirFileIterator::SubDirFileIterator(const QStringList &directories, const QStringList &filters,
QTextCodec *encoding) const QStringList &exclusionFilters, QTextCodec *encoding)
: m_filters(filters), m_progress(0) : m_filterFiles(filterFilesFunction(filters, exclusionFilters)),
m_progress(0)
{ {
m_encoding = (encoding == 0 ? QTextCodec::codecForLocale() : encoding); m_encoding = (encoding == 0 ? QTextCodec::codecForLocale() : encoding);
qreal maxPer = qreal(MAX_PROGRESS) / directories.count(); qreal maxPer = qreal(MAX_PROGRESS) / directories.count();
...@@ -591,19 +639,21 @@ void SubDirFileIterator::update(int index) ...@@ -591,19 +639,21 @@ void SubDirFileIterator::update(int index)
const qreal dirProgressMax = m_progressValues.pop(); const qreal dirProgressMax = m_progressValues.pop();
const bool processed = m_processedValues.pop(); const bool processed = m_processedValues.pop();
if (dir.exists()) { if (dir.exists()) {
const QString dirPath = dir.path();
QStringList subDirs; QStringList subDirs;
if (!processed) if (!processed)
subDirs = dir.entryList(QDir::Dirs|QDir::Hidden|QDir::NoDotAndDotDot); subDirs = dir.entryList(QDir::Dirs|QDir::Hidden|QDir::NoDotAndDotDot);
if (subDirs.isEmpty()) { if (subDirs.isEmpty()) {
QStringList fileEntries = dir.entryList(m_filters, const QStringList allFileEntries = dir.entryList(QDir::Files|QDir::Hidden);
QDir::Files|QDir::Hidden); const QStringList allFilePaths = Utils::transform(allFileEntries,
QStringListIterator it(fileEntries); [&dirPath](const QString &entry) {
it.toBack(); return QString(dirPath + '/' + entry);
m_items.reserve(m_items.size() + fileEntries.size()); });
while (it.hasPrevious()) { const QStringList filePaths = m_filterFiles(allFilePaths);
const QString &file = it.previous(); m_items.reserve(m_items.size() + filePaths.size());
m_items.append(new Item(dir.path()+ QLatin1Char('/') + file, m_encoding)); Utils::reverseForeach(filePaths, [this](const QString &file) {
} m_items.append(new Item(file, m_encoding));
});
m_progress += dirProgressMax; m_progress += dirProgressMax;
} else { } else {
qreal subProgress = dirProgressMax/(subDirs.size()+1); qreal subProgress = dirProgressMax/(subDirs.size()+1);
...@@ -614,7 +664,7 @@ void SubDirFileIterator::update(int index) ...@@ -614,7 +664,7 @@ void SubDirFileIterator::update(int index)
it.toBack(); it.toBack();
while (it.hasPrevious()) { while (it.hasPrevious()) {
const QString &directory = it.previous(); const QString &directory = it.previous();
m_dirs.push(QDir(dir.path()+ QLatin1Char('/') + directory)); m_dirs.push(QDir(dirPath + QLatin1Char('/') + directory));
m_progressValues.push(subProgress); m_progressValues.push(subProgress);
m_processedValues.push(false); m_processedValues.push(false);
} }
......
...@@ -33,10 +33,20 @@ ...@@ -33,10 +33,20 @@
#include <QStack> #include <QStack>
#include <QTextDocument> #include <QTextDocument>
#include <functional>
QT_FORWARD_DECLARE_CLASS(QTextCodec) QT_FORWARD_DECLARE_CLASS(QTextCodec)
namespace Utils { namespace Utils {
QTCREATOR_UTILS_EXPORT
std::function<bool(const QString &)>
filterFileFunction(const QStringList &filterRegs, const QStringList &exclusionRegs);
QTCREATOR_UTILS_EXPORT
std::function<QStringList(const QStringList &)>
filterFilesFunction(const QStringList &filters, const QStringList &exclusionFilters);
class QTCREATOR_UTILS_EXPORT FileIterator class QTCREATOR_UTILS_EXPORT FileIterator
{ {
public: public:
...@@ -119,7 +129,9 @@ private: ...@@ -119,7 +129,9 @@ private:
class QTCREATOR_UTILS_EXPORT SubDirFileIterator : public FileIterator class QTCREATOR_UTILS_EXPORT SubDirFileIterator : public FileIterator
{ {
public: public:
SubDirFileIterator(const QStringList &directories, const QStringList &filters, SubDirFileIterator(const QStringList &directories,
const QStringList &filters,
const QStringList &exclusionFilters,
QTextCodec *encoding = 0); QTextCodec *encoding = 0);
~SubDirFileIterator(); ~SubDirFileIterator();
...@@ -132,7 +144,7 @@ protected: ...@@ -132,7 +144,7 @@ protected:
const Item &itemAt(int index) const override; const Item &itemAt(int index) const override;
private: private:
QStringList m_filters; std::function<QStringList(const QStringList &)> m_filterFiles;
QTextCodec *m_encoding; QTextCodec *m_encoding;
QStack<QDir> m_dirs; QStack<QDir> m_dirs;
QStack<qreal> m_progressValues; QStack<qreal> m_progressValues;
......
...@@ -190,7 +190,7 @@ void DirectoryFilter::refresh(QFutureInterface<void> &future) ...@@ -190,7 +190,7 @@ void DirectoryFilter::refresh(QFutureInterface<void> &future)
} }
directories = m_directories; directories = m_directories;
} }
Utils::SubDirFileIterator subDirIterator(directories, m_filters); Utils::SubDirFileIterator subDirIterator(directories, m_filters, {});
future.setProgressRange(0, subDirIterator.maxProgress()); future.setProgressRange(0, subDirIterator.maxProgress());
QStringList filesFound; QStringList filesFound;
auto end = subDirIterator.end(); auto end = subDirIterator.end();
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <vcsbase/vcscommand.h> #include <vcsbase/vcscommand.h>
#include <vcsbase/vcsbaseconstants.h> #include <vcsbase/vcsbaseconstants.h>
#include <utils/algorithm.h>
#include <utils/asconst.h> #include <utils/asconst.h>
#include <utils/fancylineedit.h> #include <utils/fancylineedit.h>
#include <utils/filesearch.h> #include <utils/filesearch.h>
...@@ -159,7 +160,14 @@ public: ...@@ -159,7 +160,14 @@ public:
arguments << params.ref; arguments << params.ref;
m_ref = params.ref + ':'; m_ref = params.ref + ':';
} }
arguments << "--" << m_parameters.nameFilters; const QStringList filterArgs =
m_parameters.nameFilters.isEmpty() ? QStringList("*") // needed for exclusion filters
: m_parameters.nameFilters;
const QStringList exclusionArgs =
Utils::transform(m_parameters.exclusionFilters, [](const QString &filter) {
return QString(":!" + filter);
});
arguments << "--" << filterArgs << exclusionArgs;
QScopedPointer<VcsCommand> command(GitPlugin::client()->createCommand(m_directory)); QScopedPointer<VcsCommand> command(GitPlugin::client()->createCommand(m_directory));
command->addFlags(VcsCommand::SilentOutput | VcsCommand::SuppressFailMessage); command->addFlags(VcsCommand::SilentOutput | VcsCommand::SuppressFailMessage);
command->setProgressiveOutput(true); command->setProgressiveOutput(true);
......
...@@ -97,7 +97,7 @@ using namespace VcsBase; ...@@ -97,7 +97,7 @@ using namespace VcsBase;
namespace Git { namespace Git {
namespace Internal { namespace Internal {
const unsigned minimumRequiredVersion = 0x010800; const unsigned minimumRequiredVersion = 0x010900;
const VcsBaseEditorParameters editorParameters[] = { const VcsBaseEditorParameters editorParameters[] = {
{ {
......
...@@ -68,41 +68,28 @@ bool AllProjectsFind::isEnabled() const ...@@ -68,41 +68,28 @@ bool AllProjectsFind::isEnabled() const
} }
Utils::FileIterator *AllProjectsFind::files(const QStringList &nameFilters, Utils::FileIterator *AllProjectsFind::files(const QStringList &nameFilters,
const QStringList &exclusionFilters,
const QVariant &additionalParameters) const const QVariant &additionalParameters) const
{ {
Q_UNUSED(additionalParameters) Q_UNUSED(additionalParameters)
return filesForProjects(nameFilters, SessionManager::projects()); return filesForProjects(nameFilters, exclusionFilters, SessionManager::projects());
} }
Utils::FileIterator *AllProjectsFind::filesForProjects(const QStringList &nameFilters, Utils::FileIterator *AllProjectsFind::filesForProjects(const QStringList &nameFilters,
const QList<Project *> &projects) const const QStringList &exclusionFilters,
const QList<Project *> &projects) const
{ {
QList<QRegExp> filterRegs; std::function<QStringList(const QStringList &)> filterFiles =
foreach (const QString &filter, nameFilters) { Utils::filterFilesFunction(nameFilters, exclusionFilters);
filterRegs << QRegExp(filter, Qt::CaseInsensitive, QRegExp::Wildcard); const QMap<QString, QTextCodec *> openEditorEncodings = TextDocument::openedTextDocumentEncodings();
}
QMap<QString, QTextCodec *> openEditorEncodings = TextDocument::openedTextDocumentEncodings();
QMap<QString, QTextCodec *> encodings; QMap<QString, QTextCodec *> encodings;
foreach (const Project *project, projects) { foreach (const Project *project, projects) {
QStringList projectFiles = project->files(Project::AllFiles);
QStringList filteredFiles;
if (!filterRegs.isEmpty()) {
foreach (const QString &file, projectFiles) {
if (Utils::anyOf(filterRegs,
[&file](QRegExp reg) {
return (reg.exactMatch(file) || reg.exactMatch(Utils::FileName::fromString(file).fileName()));
})) {
filteredFiles.append(file);
}
}
} else {
filteredFiles = projectFiles;
}
const EditorConfiguration *config = project->editorConfiguration(); const EditorConfiguration *config = project->editorConfiguration();
QTextCodec *projectCodec = config->useGlobalSettings() QTextCodec *projectCodec = config->useGlobalSettings()
? Core::EditorManager::defaultTextCodec() ? Core::EditorManager::defaultTextCodec()
: config->textCodec(); : config->textCodec();
foreach (const QString &fileName, filteredFiles) { const QStringList filteredFiles = filterFiles(project->files(Project::AllFiles));
for (const QString &fileName : filteredFiles) {
QTextCodec *codec = openEditorEncodings.value(fileName); QTextCodec *codec = openEditorEncodings.value(fileName);
if (!codec) if (!codec)
codec = projectCodec; codec = projectCodec;
...@@ -124,8 +111,10 @@ QString AllProjectsFind::label() const ...@@ -124,8 +111,10 @@ QString AllProjectsFind::label() const
QString AllProjectsFind::toolTip() const QString AllProjectsFind::toolTip() const
{ {
// %2 is filled by BaseFileFind::runNewSearch // last arg is filled by BaseFileFind::runNewSearch
return tr("Filter: %1\n%2").arg(fileNameFilters().join(QLatin1Char(','))); return tr("Filter: %1\nExcluding: %2\n%3")
.arg(fileNameFilters().join(','))
.arg(fileExclusionFilters().join(','));
} }
void AllProjectsFind::handleFileListChanged() void AllProjectsFind::handleFileListChanged()
...@@ -140,14 +129,13 @@ QWidget *AllProjectsFind::createConfigWidget() ...@@ -140,14 +129,13 @@ QWidget *AllProjectsFind::createConfigWidget()
auto gridLayout = new QGridLayout(m_configWidget); auto gridLayout = new QGridLayout(m_configWidget);
gridLayout->setMargin(0); gridLayout->setMargin(0);
m_configWidget->setLayout(gridLayout); m_configWidget->setLayout(gridLayout);
auto filePatternLabel = new QLabel(tr("Fi&le pattern:")); const QList<QPair<QWidget *, QWidget *>> patternWidgets = createPatternWidgets();
filePatternLabel->setMinimumWidth(80); int row = 0;
filePatternLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); for (const QPair<QWidget *, QWidget *> &p : patternWidgets) {
filePatternLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); gridLayout->addWidget(p.first, row, 0, Qt::AlignRight);
QWidget *patternWidget = createPatternWidget(); gridLayout->addWidget(p.second, row, 1);
filePatternLabel->setBuddy(patternWidget); ++row;
gridLayout->addWidget(filePatternLabel, 0, 0, Qt::AlignRight); }
gridLayout->addWidget(patternWidget, 0, 1);
m_configWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); m_configWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
} }
return m_configWidget; return m_configWidget;
...@@ -163,6 +151,6 @@ void AllProjectsFind::writeSettings(QSettings *settings) ...@@ -163,6 +151,6 @@ void AllProjectsFind::writeSettings(QSettings *settings)
void AllProjectsFind::readSettings(QSettings *settings) void AllProjectsFind::readSettings(QSettings *settings)
{ {
settings->beginGroup(QLatin1String("AllProjectsFind")); settings->beginGroup(QLatin1String("AllProjectsFind"));
readCommonSettings(settings, QString(QLatin1Char('*'))); readCommonSettings(settings, "*", "");
settings->endGroup(); settings->endGroup();
} }
...@@ -53,8 +53,10 @@ public: ...@@ -53,8 +53,10 @@ public:
protected: protected:
Utils::FileIterator *files(const QStringList &nameFilters, Utils::FileIterator *files(const QStringList &nameFilters,
const QStringList &exclusionFilters,
const QVariant &additionalParameters) const override; const QVariant &additionalParameters) const override;
Utils::FileIterator *filesForProjects(const QStringList &nameFilters, Utils::FileIterator *filesForProjects(const QStringList &nameFilters,
const QStringList &exclusionFilters,
const QList<Project *> &projects) const; const QList<Project *> &projects) const;
QVariant additionalParameters() const override; QVariant additionalParameters() const override;
......
...@@ -73,14 +73,15 @@ QVariant CurrentProjectFind::additionalParameters() const ...@@ -73,14 +73,15 @@ QVariant CurrentProjectFind::additionalParameters() const
} }
Utils::FileIterator *CurrentProjectFind::files(const QStringList &nameFilters, Utils::FileIterator *CurrentProjectFind::files(const QStringList &nameFilters,
const QVariant &additionalParameters) const const QStringList &exclusionFilters,
const QVariant &additionalParameters) const
{ {
QTC_ASSERT(additionalParameters.isValid(), QTC_ASSERT(additionalParameters.isValid(),
return new Utils::FileListIterator(QStringList(), QList<QTextCodec *>())); return new Utils::FileListIterator(QStringList(), QList<QTextCodec *>()));
QString projectFile = additionalParameters.toString(); QString projectFile = additionalParameters.toString();
foreach (Project *project, SessionManager::projects()) { foreach (Project *project, SessionManager::projects()) {
if (project->document() && projectFile == project->projectFilePath().toString()) if (project->document() && projectFile == project->projectFilePath().toString())
return filesForProjects(nameFilters, QList<Project *>() << project); return filesForProjects(nameFilters, exclusionFilters, QList<Project *>() << project);
} }
return new Utils::FileListIterator(QStringList(), QList<QTextCodec *>()); return new Utils::FileListIterator(QStringList(), QList<QTextCodec *>());
} }
...@@ -123,6 +124,6 @@ void CurrentProjectFind::writeSettings(QSettings *settings) ...@@ -123,6 +124,6 @@ void CurrentProjectFind::writeSettings(QSettings *settings)
void CurrentProjectFind::readSettings(QSettings *settings) void CurrentProjectFind::readSettings(QSettings *settings)
{ {
settings->beginGroup(QLatin1String("CurrentProjectFind")); settings->beginGroup(QLatin1String("CurrentProjectFind"));
readCommonSettings(settings, QString(QLatin1Char('*'))); readCommonSettings(settings, "*", "");
settings->endGroup(); settings->endGroup();
} }
...@@ -50,6 +50,7 @@ public: ...@@ -50,6 +50,7 @@ public:
protected: protected:
Utils::FileIterator *files(const QStringList &nameFilters, Utils::FileIterator *files(const QStringList &nameFilters,
const QStringList &exclusionFilters,
const QVariant &additionalParameters) const override; const QVariant &additionalParameters) const override;
QVariant additionalParameters() const override; QVariant additionalParameters() const override;
QString label() const override; QString label() const override;
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <coreplugin/find/ifindsupport.h> #include <coreplugin/find/ifindsupport.h>
#include <texteditor/texteditor.h> #include <texteditor/texteditor.h>
#include <texteditor/refactoringchanges.h> #include <texteditor/refactoringchanges.h>
#include <utils/algorithm.h>
#include <utils/fadingindicator.h> #include <utils/fadingindicator.h>
#include <utils/filesearch.h> #include <utils/filesearch.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
...@@ -78,7 +79,8 @@ public: ...@@ -78,7 +79,8 @@ public:
: Utils::findInFiles; : Utils::findInFiles;
return func(parameters.text, return func(parameters.text,
baseFileFind->files(parameters.nameFilters, parameters.additionalParameters), baseFileFind->files(parameters.nameFilters, parameters.exclusionFilters,
parameters.additionalParameters),
textDocumentFlagsForFindFlags(parameters.flags), textDocumentFlagsForFindFlags(parameters.flags),
TextDocument::openedTextDocumentContents()); TextDocument::openedTextDocumentContents());
...@@ -114,9 +116,14 @@ public: ...@@ -114,9 +116,14 @@ public:
QPointer<IFindSupport> m_currentFindSupport; QPointer<IFindSupport> m_currentFindSupport;
QLabel *m_resultLabel = 0; QLabel *m_resultLabel = 0;
// models in native path format
QStringListModel m_filterStrings; QStringListModel m_filterStrings;
QStringListModel m_exclusionStrings;
// current filter in portable path format
QString m_filterSetting; QString m_filterSetting;
QString m_exclusionSetting;
QPointer<QComboBox> m_filterCombo; QPointer<QComboBox> m_filterCombo;
QPointer<QComboBox> m_exclusionCombo;
QVector<SearchEngine *> m_searchEngines; QVector<SearchEngine *> m_searchEngines;
SearchEngine *m_internalSearchEngine; SearchEngine *m_internalSearchEngine;
int m_currentSearchEngineIndex = -1; int m_currentSearchEngineIndex = -1;
...@@ -128,9 +135,10 @@ static void syncComboWithSettings(QComboBox *combo, const QString &setting) ...@@ -128,9 +135,10 @@ static void syncComboWithSettings(QComboBox *combo, const QString &setting)
{ {
if (!combo) if (!combo)
return; return;
int index = combo->findText(setting); const QString &nativeSettings = QDir::toNativeSeparators(setting);
int index = combo->findText(nativeSettings);
if (index < 0) if (index < 0)
combo->setEditText(setting); combo->setEditText(nativeSettings);
else else
combo->setCurrentIndex(index); combo->setCurrentIndex(index);
} }
...@@ -188,18 +196,27 @@ bool BaseFileFind::isEnabled() const ...@@ -188,18 +196,27 @@ bool BaseFileFind::isEnabled() const
return true; return true;
} }
static QStringList splitFilterUiText(const QString &text)
{
const QStringList parts = text.split(',');
const QStringList trimmedPortableParts = Utils::transform(parts, [](const QString &s) {
return QDir::fromNativeSeparators(s.trimmed());
});
return Utils::filtered(trimmedPortableParts, [](const QString &s) { return !s.isEmpty(); });
}
QStringList BaseFileFind::fileNameFilters() const QStringList BaseFileFind::fileNameFilters() const
{ {
QStringList filters; if (d->m_filterCombo)
if (d->m_filterCombo && !d->m_filterCombo->currentText().isEmpty()) { return splitFilterUiText(d->m_filterCombo->currentText());
const QStringList parts = d->m_filterCombo->currentText().split(','); return QStringList();
foreach (const QString &part, parts) { }
const QString filter = part.trimmed();
if (!filter.isEmpty()) QStringList BaseFileFind::fileExclusionFilters() const
filters << filter; {
} if (d->m_exclusionCombo)
} return splitFilterUiText(d->m_exclusionCombo->currentText());
return filters; return QStringList();
} }
SearchEngine *BaseFileFind::currentSearchEngine() const SearchEngine *BaseFileFind::currentSearchEngine() const
...@@ -248,6 +265,8 @@ void BaseFileFind::runNewSearch(const QString &txt, FindFlags findFlags, ...@@ -248,6 +265,8 @@ void BaseFileFind::runNewSearch(const QString &txt, FindFlags findFlags,
d->m_currentFindSupport = 0; d->m_currentFindSupport = 0;
if (d->m_filterCombo) if (d->m_filterCombo)