aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Ziller <eike.ziller@qt.io>2016-12-09 13:33:12 +0100
committerEike Ziller <eike.ziller@qt.io>2017-02-28 10:48:23 +0000
commit1f8b2dc3610635f019b7fef8192171f4e085f814 (patch)
tree3611fc53841940069d7adc70a42865c781932b4a
parent99a6d78bba07a40a8407f1b7ba44b57f7da1983e (diff)
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 <david.schulz@qt.io> Reviewed-by: Orgad Shaneh <orgads@gmail.com>
-rw-r--r--doc/src/vcs/creator-vcs.qdoc2
-rw-r--r--src/libs/utils/filesearch.cpp74
-rw-r--r--src/libs/utils/filesearch.h16
-rw-r--r--src/plugins/coreplugin/locator/directoryfilter.cpp2
-rw-r--r--src/plugins/git/gitgrep.cpp10
-rw-r--r--src/plugins/git/gitplugin.cpp2
-rw-r--r--src/plugins/projectexplorer/allprojectsfind.cpp54
-rw-r--r--src/plugins/projectexplorer/allprojectsfind.h2
-rw-r--r--src/plugins/projectexplorer/currentprojectfind.cpp7
-rw-r--r--src/plugins/projectexplorer/currentprojectfind.h1
-rw-r--r--src/plugins/texteditor/basefilefind.cpp131
-rw-r--r--src/plugins/texteditor/basefilefind.h11
-rw-r--r--src/plugins/texteditor/findincurrentfile.cpp4
-rw-r--r--src/plugins/texteditor/findincurrentfile.h1
-rw-r--r--src/plugins/texteditor/findinfiles.cpp23
-rw-r--r--src/plugins/texteditor/findinfiles.h1
-rw-r--r--src/plugins/texteditor/findinopenfiles.cpp6
-rw-r--r--src/plugins/texteditor/findinopenfiles.h1
18 files changed, 244 insertions, 104 deletions
diff --git a/doc/src/vcs/creator-vcs.qdoc b/doc/src/vcs/creator-vcs.qdoc
index 655394bc7a..561dc8a54d 100644
--- a/doc/src/vcs/creator-vcs.qdoc
+++ b/doc/src/vcs/creator-vcs.qdoc
@@ -58,7 +58,7 @@
\row
\li \l{Using Git}{Git}
\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
\row
diff --git a/src/libs/utils/filesearch.cpp b/src/libs/utils/filesearch.cpp
index 1a13378d1c..beac6433bd 100644
--- a/src/libs/utils/filesearch.cpp
+++ b/src/libs/utils/filesearch.cpp
@@ -23,11 +23,14 @@
**
****************************************************************************/
+#include "algorithm.h"
#include "filesearch.h"
+#include "fileutils.h"
#include "mapreduce.h"
#include <QCoreApplication>
#include <QMutex>
+#include <QRegExp>
#include <QRegularExpression>
#include <QTextCodec>
@@ -457,6 +460,50 @@ QString matchCaseReplacement(const QString &originalText, const QString &replace
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)
@@ -562,8 +609,9 @@ namespace {
}
SubDirFileIterator::SubDirFileIterator(const QStringList &directories, const QStringList &filters,
- QTextCodec *encoding)
- : m_filters(filters), m_progress(0)
+ const QStringList &exclusionFilters, QTextCodec *encoding)
+ : m_filterFiles(filterFilesFunction(filters, exclusionFilters)),
+ m_progress(0)
{
m_encoding = (encoding == 0 ? QTextCodec::codecForLocale() : encoding);
qreal maxPer = qreal(MAX_PROGRESS) / directories.count();
@@ -591,19 +639,21 @@ void SubDirFileIterator::update(int index)
const qreal dirProgressMax = m_progressValues.pop();
const bool processed = m_processedValues.pop();
if (dir.exists()) {
+ const QString dirPath = dir.path();
QStringList subDirs;
if (!processed)
subDirs = dir.entryList(QDir::Dirs|QDir::Hidden|QDir::NoDotAndDotDot);
if (subDirs.isEmpty()) {
- QStringList fileEntries = dir.entryList(m_filters,
- QDir::Files|QDir::Hidden);
- QStringListIterator it(fileEntries);
- it.toBack();
- m_items.reserve(m_items.size() + fileEntries.size());
- while (it.hasPrevious()) {
- const QString &file = it.previous();
- m_items.append(new Item(dir.path()+ QLatin1Char('/') + file, m_encoding));
- }
+ const QStringList allFileEntries = dir.entryList(QDir::Files|QDir::Hidden);
+ const QStringList allFilePaths = Utils::transform(allFileEntries,
+ [&dirPath](const QString &entry) {
+ return QString(dirPath + '/' + entry);
+ });
+ const QStringList filePaths = m_filterFiles(allFilePaths);
+ m_items.reserve(m_items.size() + filePaths.size());
+ Utils::reverseForeach(filePaths, [this](const QString &file) {
+ m_items.append(new Item(file, m_encoding));
+ });
m_progress += dirProgressMax;
} else {
qreal subProgress = dirProgressMax/(subDirs.size()+1);
@@ -614,7 +664,7 @@ void SubDirFileIterator::update(int index)
it.toBack();
while (it.hasPrevious()) {
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_processedValues.push(false);
}
diff --git a/src/libs/utils/filesearch.h b/src/libs/utils/filesearch.h
index 05cadc261d..540cd9304d 100644
--- a/src/libs/utils/filesearch.h
+++ b/src/libs/utils/filesearch.h
@@ -33,10 +33,20 @@
#include <QStack>
#include <QTextDocument>
+#include <functional>
+
QT_FORWARD_DECLARE_CLASS(QTextCodec)
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
{
public:
@@ -119,7 +129,9 @@ private:
class QTCREATOR_UTILS_EXPORT SubDirFileIterator : public FileIterator
{
public:
- SubDirFileIterator(const QStringList &directories, const QStringList &filters,
+ SubDirFileIterator(const QStringList &directories,
+ const QStringList &filters,
+ const QStringList &exclusionFilters,
QTextCodec *encoding = 0);
~SubDirFileIterator();
@@ -132,7 +144,7 @@ protected:
const Item &itemAt(int index) const override;
private:
- QStringList m_filters;
+ std::function<QStringList(const QStringList &)> m_filterFiles;
QTextCodec *m_encoding;
QStack<QDir> m_dirs;
QStack<qreal> m_progressValues;
diff --git a/src/plugins/coreplugin/locator/directoryfilter.cpp b/src/plugins/coreplugin/locator/directoryfilter.cpp
index 8a3bc2b395..cc95a200ef 100644
--- a/src/plugins/coreplugin/locator/directoryfilter.cpp
+++ b/src/plugins/coreplugin/locator/directoryfilter.cpp
@@ -190,7 +190,7 @@ void DirectoryFilter::refresh(QFutureInterface<void> &future)
}
directories = m_directories;
}
- Utils::SubDirFileIterator subDirIterator(directories, m_filters);
+ Utils::SubDirFileIterator subDirIterator(directories, m_filters, {});
future.setProgressRange(0, subDirIterator.maxProgress());
QStringList filesFound;
auto end = subDirIterator.end();
diff --git a/src/plugins/git/gitgrep.cpp b/src/plugins/git/gitgrep.cpp
index c391fe1a4a..3c0096921f 100644
--- a/src/plugins/git/gitgrep.cpp
+++ b/src/plugins/git/gitgrep.cpp
@@ -35,6 +35,7 @@
#include <vcsbase/vcscommand.h>
#include <vcsbase/vcsbaseconstants.h>
+#include <utils/algorithm.h>
#include <utils/asconst.h>
#include <utils/fancylineedit.h>
#include <utils/filesearch.h>
@@ -159,7 +160,14 @@ public:
arguments << 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));
command->addFlags(VcsCommand::SilentOutput | VcsCommand::SuppressFailMessage);
command->setProgressiveOutput(true);
diff --git a/src/plugins/git/gitplugin.cpp b/src/plugins/git/gitplugin.cpp
index 093028c740..08de519e02 100644
--- a/src/plugins/git/gitplugin.cpp
+++ b/src/plugins/git/gitplugin.cpp
@@ -97,7 +97,7 @@ using namespace VcsBase;
namespace Git {
namespace Internal {
-const unsigned minimumRequiredVersion = 0x010800;
+const unsigned minimumRequiredVersion = 0x010900;
const VcsBaseEditorParameters editorParameters[] = {
{
diff --git a/src/plugins/projectexplorer/allprojectsfind.cpp b/src/plugins/projectexplorer/allprojectsfind.cpp
index 7ce05f7495..46b7fbb894 100644
--- a/src/plugins/projectexplorer/allprojectsfind.cpp
+++ b/src/plugins/projectexplorer/allprojectsfind.cpp
@@ -68,41 +68,28 @@ bool AllProjectsFind::isEnabled() const
}
Utils::FileIterator *AllProjectsFind::files(const QStringList &nameFilters,
+ const QStringList &exclusionFilters,
const QVariant &additionalParameters) const
{
Q_UNUSED(additionalParameters)
- return filesForProjects(nameFilters, SessionManager::projects());
+ return filesForProjects(nameFilters, exclusionFilters, SessionManager::projects());
}
Utils::FileIterator *AllProjectsFind::filesForProjects(const QStringList &nameFilters,
- const QList<Project *> &projects) const
+ const QStringList &exclusionFilters,
+ const QList<Project *> &projects) const
{
- QList<QRegExp> filterRegs;
- foreach (const QString &filter, nameFilters) {
- filterRegs << QRegExp(filter, Qt::CaseInsensitive, QRegExp::Wildcard);
- }
- QMap<QString, QTextCodec *> openEditorEncodings = TextDocument::openedTextDocumentEncodings();
+ std::function<QStringList(const QStringList &)> filterFiles =
+ Utils::filterFilesFunction(nameFilters, exclusionFilters);
+ const QMap<QString, QTextCodec *> openEditorEncodings = TextDocument::openedTextDocumentEncodings();
QMap<QString, QTextCodec *> encodings;
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();
QTextCodec *projectCodec = config->useGlobalSettings()
? Core::EditorManager::defaultTextCodec()
: 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);
if (!codec)
codec = projectCodec;
@@ -124,8 +111,10 @@ QString AllProjectsFind::label() const
QString AllProjectsFind::toolTip() const
{
- // %2 is filled by BaseFileFind::runNewSearch
- return tr("Filter: %1\n%2").arg(fileNameFilters().join(QLatin1Char(',')));
+ // last arg is filled by BaseFileFind::runNewSearch
+ return tr("Filter: %1\nExcluding: %2\n%3")
+ .arg(fileNameFilters().join(','))
+ .arg(fileExclusionFilters().join(','));
}
void AllProjectsFind::handleFileListChanged()
@@ -140,14 +129,13 @@ QWidget *AllProjectsFind::createConfigWidget()
auto gridLayout = new QGridLayout(m_configWidget);
gridLayout->setMargin(0);
m_configWidget->setLayout(gridLayout);
- auto filePatternLabel = new QLabel(tr("Fi&le pattern:"));
- filePatternLabel->setMinimumWidth(80);
- filePatternLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
- filePatternLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
- QWidget *patternWidget = createPatternWidget();
- filePatternLabel->setBuddy(patternWidget);
- gridLayout->addWidget(filePatternLabel, 0, 0, Qt::AlignRight);
- gridLayout->addWidget(patternWidget, 0, 1);
+ const QList<QPair<QWidget *, QWidget *>> patternWidgets = createPatternWidgets();
+ int row = 0;
+ for (const QPair<QWidget *, QWidget *> &p : patternWidgets) {
+ gridLayout->addWidget(p.first, row, 0, Qt::AlignRight);
+ gridLayout->addWidget(p.second, row, 1);
+ ++row;
+ }
m_configWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
}
return m_configWidget;
@@ -163,6 +151,6 @@ void AllProjectsFind::writeSettings(QSettings *settings)
void AllProjectsFind::readSettings(QSettings *settings)
{
settings->beginGroup(QLatin1String("AllProjectsFind"));
- readCommonSettings(settings, QString(QLatin1Char('*')));
+ readCommonSettings(settings, "*", "");
settings->endGroup();
}
diff --git a/src/plugins/projectexplorer/allprojectsfind.h b/src/plugins/projectexplorer/allprojectsfind.h
index b3b9f4f1e0..87f2b77a14 100644
--- a/src/plugins/projectexplorer/allprojectsfind.h
+++ b/src/plugins/projectexplorer/allprojectsfind.h
@@ -53,8 +53,10 @@ public:
protected:
Utils::FileIterator *files(const QStringList &nameFilters,
+ const QStringList &exclusionFilters,
const QVariant &additionalParameters) const override;
Utils::FileIterator *filesForProjects(const QStringList &nameFilters,
+ const QStringList &exclusionFilters,
const QList<Project *> &projects) const;
QVariant additionalParameters() const override;
diff --git a/src/plugins/projectexplorer/currentprojectfind.cpp b/src/plugins/projectexplorer/currentprojectfind.cpp
index bffcd83945..c67c26a62f 100644
--- a/src/plugins/projectexplorer/currentprojectfind.cpp
+++ b/src/plugins/projectexplorer/currentprojectfind.cpp
@@ -73,14 +73,15 @@ QVariant CurrentProjectFind::additionalParameters() const
}
Utils::FileIterator *CurrentProjectFind::files(const QStringList &nameFilters,
- const QVariant &additionalParameters) const
+ const QStringList &exclusionFilters,
+ const QVariant &additionalParameters) const
{
QTC_ASSERT(additionalParameters.isValid(),
return new Utils::FileListIterator(QStringList(), QList<QTextCodec *>()));
QString projectFile = additionalParameters.toString();
foreach (Project *project, SessionManager::projects()) {
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 *>());
}
@@ -123,6 +124,6 @@ void CurrentProjectFind::writeSettings(QSettings *settings)
void CurrentProjectFind::readSettings(QSettings *settings)
{
settings->beginGroup(QLatin1String("CurrentProjectFind"));
- readCommonSettings(settings, QString(QLatin1Char('*')));
+ readCommonSettings(settings, "*", "");
settings->endGroup();
}
diff --git a/src/plugins/projectexplorer/currentprojectfind.h b/src/plugins/projectexplorer/currentprojectfind.h
index 301f97ebe3..244777464f 100644
--- a/src/plugins/projectexplorer/currentprojectfind.h
+++ b/src/plugins/projectexplorer/currentprojectfind.h
@@ -50,6 +50,7 @@ public:
protected:
Utils::FileIterator *files(const QStringList &nameFilters,
+ const QStringList &exclusionFilters,
const QVariant &additionalParameters) const override;
QVariant additionalParameters() const override;
QString label() const override;
diff --git a/src/plugins/texteditor/basefilefind.cpp b/src/plugins/texteditor/basefilefind.cpp
index d6a24dd653..96e812c096 100644
--- a/src/plugins/texteditor/basefilefind.cpp
+++ b/src/plugins/texteditor/basefilefind.cpp
@@ -36,6 +36,7 @@
#include <coreplugin/find/ifindsupport.h>
#include <texteditor/texteditor.h>
#include <texteditor/refactoringchanges.h>
+#include <utils/algorithm.h>
#include <utils/fadingindicator.h>
#include <utils/filesearch.h>
#include <utils/qtcassert.h>
@@ -78,7 +79,8 @@ public:
: Utils::findInFiles;
return func(parameters.text,
- baseFileFind->files(parameters.nameFilters, parameters.additionalParameters),
+ baseFileFind->files(parameters.nameFilters, parameters.exclusionFilters,
+ parameters.additionalParameters),
textDocumentFlagsForFindFlags(parameters.flags),
TextDocument::openedTextDocumentContents());
@@ -114,9 +116,14 @@ public:
QPointer<IFindSupport> m_currentFindSupport;
QLabel *m_resultLabel = 0;
+ // models in native path format
QStringListModel m_filterStrings;
+ QStringListModel m_exclusionStrings;
+ // current filter in portable path format
QString m_filterSetting;
+ QString m_exclusionSetting;
QPointer<QComboBox> m_filterCombo;
+ QPointer<QComboBox> m_exclusionCombo;
QVector<SearchEngine *> m_searchEngines;
SearchEngine *m_internalSearchEngine;
int m_currentSearchEngineIndex = -1;
@@ -128,9 +135,10 @@ static void syncComboWithSettings(QComboBox *combo, const QString &setting)
{
if (!combo)
return;
- int index = combo->findText(setting);
+ const QString &nativeSettings = QDir::toNativeSeparators(setting);
+ int index = combo->findText(nativeSettings);
if (index < 0)
- combo->setEditText(setting);
+ combo->setEditText(nativeSettings);
else
combo->setCurrentIndex(index);
}
@@ -188,18 +196,27 @@ bool BaseFileFind::isEnabled() const
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 filters;
- if (d->m_filterCombo && !d->m_filterCombo->currentText().isEmpty()) {
- const QStringList parts = d->m_filterCombo->currentText().split(',');
- foreach (const QString &part, parts) {
- const QString filter = part.trimmed();
- if (!filter.isEmpty())
- filters << filter;
- }
- }
- return filters;
+ if (d->m_filterCombo)
+ return splitFilterUiText(d->m_filterCombo->currentText());
+ return QStringList();
+}
+
+QStringList BaseFileFind::fileExclusionFilters() const
+{
+ if (d->m_exclusionCombo)
+ return splitFilterUiText(d->m_exclusionCombo->currentText());
+ return QStringList();
}
SearchEngine *BaseFileFind::currentSearchEngine() const
@@ -248,6 +265,8 @@ void BaseFileFind::runNewSearch(const QString &txt, FindFlags findFlags,
d->m_currentFindSupport = 0;
if (d->m_filterCombo)
updateComboEntries(d->m_filterCombo, true);
+ if (d->m_exclusionCombo)
+ updateComboEntries(d->m_exclusionCombo, true);
QString tooltip = toolTip();
SearchResult *search = SearchResultWindow::instance()->startNewSearch(
@@ -261,6 +280,7 @@ void BaseFileFind::runNewSearch(const QString &txt, FindFlags findFlags,
parameters.text = txt;
parameters.flags = findFlags;
parameters.nameFilters = fileNameFilters();
+ parameters.exclusionFilters = fileExclusionFilters();
parameters.additionalParameters = additionalParameters();
parameters.searchEngineParameters = currentSearchEngine()->parameters();
parameters.searchEngineIndex = d->m_currentSearchEngineIndex;
@@ -340,46 +360,93 @@ void BaseFileFind::doReplace(const QString &text,
}
}
-QWidget *BaseFileFind::createPatternWidget()
+static QComboBox *createCombo(QAbstractItemModel *model)
{
- QString filterToolTip = tr("List of comma separated wildcard filters");
- d->m_filterCombo = new QComboBox;
- d->m_filterCombo->setEditable(true);
- d->m_filterCombo->setModel(&d->m_filterStrings);
- d->m_filterCombo->setMaxCount(10);
- d->m_filterCombo->setMinimumContentsLength(10);
- d->m_filterCombo->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
- d->m_filterCombo->setInsertPolicy(QComboBox::InsertAtBottom);
- d->m_filterCombo->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ auto combo = new QComboBox;
+ combo->setEditable(true);
+ combo->setModel(model);
+ combo->setMaxCount(10);
+ combo->setMinimumContentsLength(10);
+ combo->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
+ combo->setInsertPolicy(QComboBox::InsertAtBottom);
+ combo->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ return combo;
+}
+
+static QLabel *createLabel(const QString &text)
+{
+ auto filePatternLabel = new QLabel(text);
+ filePatternLabel->setMinimumWidth(80);
+ filePatternLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
+ filePatternLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
+ return filePatternLabel;
+}
+
+QList<QPair<QWidget *, QWidget *>> BaseFileFind::createPatternWidgets()
+{
+ static const QString filterToolTip = tr("List of comma separated wildcard filters. "
+ "Files with file name or full file path matching any filter are included.");
+ QLabel *filterLabel = createLabel(tr("Fi&le pattern:"));
+ d->m_filterCombo = createCombo(&d->m_filterStrings);
d->m_filterCombo->setToolTip(filterToolTip);
+ filterLabel->setBuddy(d->m_filterCombo);
syncComboWithSettings(d->m_filterCombo, d->m_filterSetting);
- return d->m_filterCombo;
+ QLabel *exclusionLabel = createLabel(tr("Exclusion pattern:"));
+ d->m_exclusionCombo = createCombo(&d->m_exclusionStrings);
+ d->m_exclusionCombo->setToolTip(filterToolTip);
+ exclusionLabel->setBuddy(d->m_exclusionCombo);
+ syncComboWithSettings(d->m_exclusionCombo, d->m_exclusionSetting);
+ return { qMakePair(filterLabel, d->m_filterCombo),
+ qMakePair(exclusionLabel, d->m_exclusionCombo) };
}
void BaseFileFind::writeCommonSettings(QSettings *settings)
{
- settings->setValue("filters", d->m_filterStrings.stringList());
+ std::function<QStringList(const QStringList &)> fromNativeSeparators = [](const QStringList &files) {
+ return Utils::transform(files, &QDir::fromNativeSeparators);
+ };
+
+ settings->setValue("filters", fromNativeSeparators(d->m_filterStrings.stringList()));
if (d->m_filterCombo)
- settings->setValue("currentFilter", d->m_filterCombo->currentText());
+ settings->setValue("currentFilter",
+ QDir::fromNativeSeparators(d->m_filterCombo->currentText()));
+ settings->setValue("exclusionFilters", fromNativeSeparators(d->m_exclusionStrings.stringList()));
+ if (d->m_exclusionCombo)
+ settings->setValue("currentExclusionFilter",
+ QDir::fromNativeSeparators(d->m_exclusionCombo->currentText()));
foreach (SearchEngine *searchEngine, d->m_searchEngines)
searchEngine->writeSettings(settings);
settings->setValue("currentSearchEngineIndex", d->m_currentSearchEngineIndex);
}
-void BaseFileFind::readCommonSettings(QSettings *settings, const QString &defaultFilter)
+void BaseFileFind::readCommonSettings(QSettings *settings, const QString &defaultFilter,
+ const QString &defaultExclusionFilter)
{
+ std::function<QStringList(const QStringList &)> toNativeSeparators = [](const QStringList &files) {
+ return Utils::transform(files, &QDir::toNativeSeparators);
+ };
+
QStringList filters = settings->value("filters").toStringList();
- const QVariant currentFilter = settings->value("currentFilter");
- d->m_filterSetting = currentFilter.toString();
if (filters.isEmpty())
filters << defaultFilter;
- if (!currentFilter.isValid())
- d->m_filterSetting = filters.first();
- d->m_filterStrings.setStringList(filters);
+ const QVariant currentFilter = settings->value("currentFilter");
+ d->m_filterSetting = currentFilter.isValid() ? currentFilter.toString()
+ : filters.first();
+ d->m_filterStrings.setStringList(toNativeSeparators(filters));
if (d->m_filterCombo)
syncComboWithSettings(d->m_filterCombo, d->m_filterSetting);
+ QStringList exclusionFilters = settings->value("exclusionFilters").toStringList();
+ if (exclusionFilters.isEmpty())
+ exclusionFilters << defaultExclusionFilter;
+ const QVariant currentExclusionFilter = settings->value("currentExclusionFilter");
+ d->m_exclusionSetting = currentExclusionFilter.isValid() ? currentExclusionFilter.toString()
+ : exclusionFilters.first();
+ d->m_exclusionStrings.setStringList(toNativeSeparators(exclusionFilters));
+ if (d->m_exclusionCombo)
+ syncComboWithSettings(d->m_exclusionCombo, d->m_exclusionSetting);
+
foreach (SearchEngine* searchEngine, d->m_searchEngines)
searchEngine->readSettings(settings);
const int currentSearchEngineIndex = settings->value("currentSearchEngineIndex", 0).toInt();
diff --git a/src/plugins/texteditor/basefilefind.h b/src/plugins/texteditor/basefilefind.h
index 2a7b2bc151..56bbb4e5fd 100644
--- a/src/plugins/texteditor/basefilefind.h
+++ b/src/plugins/texteditor/basefilefind.h
@@ -57,11 +57,12 @@ class TEXTEDITOR_EXPORT FileFindParameters
{
public:
QString text;
- Core::FindFlags flags;
QStringList nameFilters;
+ QStringList exclusionFilters;
QVariant additionalParameters;
- int searchEngineIndex;
QVariant searchEngineParameters;
+ int searchEngineIndex;
+ Core::FindFlags flags;
};
class BaseFileFind;
@@ -111,6 +112,7 @@ public:
const QList<Core::SearchResultItem> &items,
bool preserveCase = false);
virtual Utils::FileIterator *files(const QStringList &nameFilters,
+ const QStringList &exclusionFilters,
const QVariant &additionalParameters) const = 0;
protected:
@@ -122,9 +124,10 @@ protected:
QFuture<Utils::FileSearchResultList> executeSearch(const FileFindParameters &parameters);
void writeCommonSettings(QSettings *settings);
- void readCommonSettings(QSettings *settings, const QString &defaultFilter);
- QWidget *createPatternWidget();
+ void readCommonSettings(QSettings *settings, const QString &defaultFilter, const QString &defaultExclusionFilter);
+ QList<QPair<QWidget *, QWidget *>> createPatternWidgets();
QStringList fileNameFilters() const;
+ QStringList fileExclusionFilters() const;
SearchEngine *currentSearchEngine() const;
QVector<SearchEngine *> searchEngines() const;
diff --git a/src/plugins/texteditor/findincurrentfile.cpp b/src/plugins/texteditor/findincurrentfile.cpp
index 03395955dd..df568a1311 100644
--- a/src/plugins/texteditor/findincurrentfile.cpp
+++ b/src/plugins/texteditor/findincurrentfile.cpp
@@ -57,9 +57,11 @@ QString FindInCurrentFile::displayName() const
}
Utils::FileIterator *FindInCurrentFile::files(const QStringList &nameFilters,
+ const QStringList &exclusionFilters,
const QVariant &additionalParameters) const
{
Q_UNUSED(nameFilters)
+ Q_UNUSED(exclusionFilters)
QString fileName = additionalParameters.toString();
QMap<QString, QTextCodec *> openEditorEncodings = TextDocument::openedTextDocumentEncodings();
QTextCodec *codec = openEditorEncodings.value(fileName);
@@ -116,6 +118,6 @@ void FindInCurrentFile::writeSettings(QSettings *settings)
void FindInCurrentFile::readSettings(QSettings *settings)
{
settings->beginGroup(QLatin1String("FindInCurrentFile"));
- readCommonSettings(settings, QLatin1String("*"));
+ readCommonSettings(settings, "*", "");
settings->endGroup();
}
diff --git a/src/plugins/texteditor/findincurrentfile.h b/src/plugins/texteditor/findincurrentfile.h
index 354680d63d..4f1295d818 100644
--- a/src/plugins/texteditor/findincurrentfile.h
+++ b/src/plugins/texteditor/findincurrentfile.h
@@ -52,6 +52,7 @@ public:
protected:
Utils::FileIterator *files(const QStringList &nameFilters,
+ const QStringList &exclusionFilters,
const QVariant &additionalParameters) const;
QVariant additionalParameters() const;
QString label() const;
diff --git a/src/plugins/texteditor/findinfiles.cpp b/src/plugins/texteditor/findinfiles.cpp
index 8c882e2d85..72ec48f204 100644
--- a/src/plugins/texteditor/findinfiles.cpp
+++ b/src/plugins/texteditor/findinfiles.cpp
@@ -80,10 +80,12 @@ QString FindInFiles::displayName() const
}
FileIterator *FindInFiles::files(const QStringList &nameFilters,
+ const QStringList &exclusionFilters,
const QVariant &additionalParameters) const
{
return new SubDirFileIterator(QStringList() << additionalParameters.toString(),
nameFilters,
+ exclusionFilters,
EditorManager::defaultTextCodec());
}
@@ -107,9 +109,10 @@ QString FindInFiles::label() const
QString FindInFiles::toolTip() const
{
//: the last arg is filled by BaseFileFind::runNewSearch
- QString tooltip = tr("Path: %1\nFilter: %2\n%3")
+ QString tooltip = tr("Path: %1\nFilter: %2\nExcluding: %3\n%4")
.arg(path().toUserOutput())
- .arg(fileNameFilters().join(QLatin1Char(',')));
+ .arg(fileNameFilters().join(','))
+ .arg(fileExclusionFilters().join(','));
const QString searchEngineToolTip = currentSearchEngine()->toolTip();
if (!searchEngineToolTip.isEmpty())
@@ -183,14 +186,12 @@ QWidget *FindInFiles::createConfigWidget()
dirLabel->setBuddy(m_directory);
gridLayout->addWidget(m_directory, row++, 1, 1, 2);
- QLabel * const filePatternLabel = new QLabel(tr("Fi&le pattern:"));
- filePatternLabel->setMinimumWidth(80);
- filePatternLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
- filePatternLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
- QWidget *patternWidget = createPatternWidget();
- filePatternLabel->setBuddy(patternWidget);
- gridLayout->addWidget(filePatternLabel, row, 0);
- gridLayout->addWidget(patternWidget, row++, 1, 1, 2);
+ const QList<QPair<QWidget *, QWidget *>> patternWidgets = createPatternWidgets();
+ for (const QPair<QWidget *, QWidget *> &p : patternWidgets) {
+ gridLayout->addWidget(p.first, row, 0, Qt::AlignRight);
+ gridLayout->addWidget(p.second, row, 1, 1, 2);
+ ++row;
+ }
m_configWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
// validity
@@ -221,7 +222,7 @@ void FindInFiles::writeSettings(QSettings *settings)
void FindInFiles::readSettings(QSettings *settings)
{
settings->beginGroup(QLatin1String("FindInFiles"));
- readCommonSettings(settings, QLatin1String("*.cpp,*.h"));
+ readCommonSettings(settings, "*.cpp,*.h", "*/.git/*,*/.cvs/*,*/.svn/*");
settings->endGroup();
}
diff --git a/src/plugins/texteditor/findinfiles.h b/src/plugins/texteditor/findinfiles.h
index e27c445b15..eb69ced567 100644
--- a/src/plugins/texteditor/findinfiles.h
+++ b/src/plugins/texteditor/findinfiles.h
@@ -66,6 +66,7 @@ signals:
protected:
Utils::FileIterator *files(const QStringList &nameFilters,
+ const QStringList &exclusionFilters,
const QVariant &additionalParameters) const override;
QVariant additionalParameters() const override;
QString label() const override;
diff --git a/src/plugins/texteditor/findinopenfiles.cpp b/src/plugins/texteditor/findinopenfiles.cpp
index 8aa8289522..80f0e13097 100644
--- a/src/plugins/texteditor/findinopenfiles.cpp
+++ b/src/plugins/texteditor/findinopenfiles.cpp
@@ -56,9 +56,11 @@ QString FindInOpenFiles::displayName() const
}
Utils::FileIterator *FindInOpenFiles::files(const QStringList &nameFilters,
- const QVariant &additionalParameters) const
+ const QStringList &exclusionFilters,
+ const QVariant &additionalParameters) const
{
Q_UNUSED(nameFilters)
+ Q_UNUSED(exclusionFilters)
Q_UNUSED(additionalParameters)
QMap<QString, QTextCodec *> openEditorEncodings
= TextDocument::openedTextDocumentEncodings();
@@ -110,7 +112,7 @@ void FindInOpenFiles::writeSettings(QSettings *settings)
void FindInOpenFiles::readSettings(QSettings *settings)
{
settings->beginGroup(QLatin1String("FindInOpenFiles"));
- readCommonSettings(settings, QLatin1String("*"));
+ readCommonSettings(settings, "*", "");
settings->endGroup();
}
diff --git a/src/plugins/texteditor/findinopenfiles.h b/src/plugins/texteditor/findinopenfiles.h
index 759636c1ae..6caf7936af 100644
--- a/src/plugins/texteditor/findinopenfiles.h
+++ b/src/plugins/texteditor/findinopenfiles.h
@@ -45,6 +45,7 @@ public:
protected:
Utils::FileIterator *files(const QStringList &nameFilters,
+ const QStringList &exclusionFilters,
const QVariant &additionalParameters) const;
QVariant additionalParameters() const;
QString label() const;