From a144160c44ed43f75e323d50f993a7e25d33658e Mon Sep 17 00:00:00 2001
From: Eike Ziller <eike.ziller@qt.io>
Date: Thu, 23 Feb 2017 15:42:36 +0100
Subject: [PATCH] Provide exclusion filters for custom locator filters

Change-Id: Ibd853b456d431ed6fd72d0617b1785b8f305e6c1
Reviewed-by: David Schulz <david.schulz@qt.io>
---
 src/libs/utils/filesearch.cpp                 | 27 ++++++++++++
 src/libs/utils/filesearch.h                   | 12 +++++
 .../coreplugin/locator/directoryfilter.cpp    | 44 ++++++++++++-------
 .../coreplugin/locator/directoryfilter.h      |  1 +
 .../coreplugin/locator/directoryfilter.ui     | 24 ++++++----
 src/plugins/texteditor/basefilefind.cpp       | 19 ++------
 6 files changed, 88 insertions(+), 39 deletions(-)

diff --git a/src/libs/utils/filesearch.cpp b/src/libs/utils/filesearch.cpp
index beac6433bd..395eb0a62c 100644
--- a/src/libs/utils/filesearch.cpp
+++ b/src/libs/utils/filesearch.cpp
@@ -506,6 +506,33 @@ filterFilesFunction(const QStringList &filters, const QStringList &exclusionFilt
     };
 }
 
+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(); });
+}
+
+
+QString msgFilePatternLabel()
+{
+    return QCoreApplication::translate("Utils::FileSearch", "Fi&le pattern:");
+}
+
+QString msgExclusionPatternLabel()
+{
+    return QCoreApplication::translate("Utils::FileSearch", "Exclusion pattern:");
+}
+
+QString msgFilePatternToolTip()
+{
+    return QCoreApplication::translate("Utils::FileSearch",
+                                       "List of comma separated wildcard filters. "
+                                       "Files with file name or full file path matching any filter are included.");
+}
+
 QString matchCaseReplacement(const QString &originalText, const QString &replaceText)
 {
     if (originalText.isEmpty())
diff --git a/src/libs/utils/filesearch.h b/src/libs/utils/filesearch.h
index 540cd9304d..23336c3f11 100644
--- a/src/libs/utils/filesearch.h
+++ b/src/libs/utils/filesearch.h
@@ -47,6 +47,18 @@ QTCREATOR_UTILS_EXPORT
 std::function<QStringList(const QStringList &)>
 filterFilesFunction(const QStringList &filters, const QStringList &exclusionFilters);
 
+QTCREATOR_UTILS_EXPORT
+QStringList splitFilterUiText(const QString &text);
+
+QTCREATOR_UTILS_EXPORT
+QString msgFilePatternLabel();
+
+QTCREATOR_UTILS_EXPORT
+QString msgExclusionPatternLabel();
+
+QTCREATOR_UTILS_EXPORT
+QString msgFilePatternToolTip();
+
 class QTCREATOR_UTILS_EXPORT FileIterator
 {
 public:
diff --git a/src/plugins/coreplugin/locator/directoryfilter.cpp b/src/plugins/coreplugin/locator/directoryfilter.cpp
index cc95a200ef..2be77816f6 100644
--- a/src/plugins/coreplugin/locator/directoryfilter.cpp
+++ b/src/plugins/coreplugin/locator/directoryfilter.cpp
@@ -26,6 +26,7 @@
 #include "directoryfilter.h"
 
 #include <coreplugin/coreconstants.h>
+#include <utils/algorithm.h>
 #include <utils/filesearch.h>
 
 #include <QFileDialog>
@@ -35,16 +36,13 @@ using namespace Core;
 using namespace Core::Internal;
 
 DirectoryFilter::DirectoryFilter(Id id)
-    : m_dialog(nullptr)
+    : m_dialog(nullptr),
+      m_filters({"*.h", "*.cpp", "*.ui", "*.qrc"}),
+      m_exclusionFilters({"*/.git/*", "*/.cvs/*", "*/.svn/*"})
 {
     setId(id);
     setIncludedByDefault(true);
     setDisplayName(tr("Generic Directory Filter"));
-
-    m_filters.append(QLatin1String("*.h"));
-    m_filters.append(QLatin1String("*.cpp"));
-    m_filters.append(QLatin1String("*.ui"));
-    m_filters.append(QLatin1String("*.qrc"));
 }
 
 QByteArray DirectoryFilter::saveState() const
@@ -58,6 +56,7 @@ QByteArray DirectoryFilter::saveState() const
     out << shortcutString();
     out << isIncludedByDefault();
     out << m_files;
+    out << m_exclusionFilters;
     return value;
 }
 
@@ -76,6 +75,10 @@ bool DirectoryFilter::restoreState(const QByteArray &state)
     in >> shortcut;
     in >> defaultFilter;
     in >> m_files;
+    if (!in.atEnd()) // Qt Creator 4.3 and later
+        in >> m_exclusionFilters;
+    else
+        m_exclusionFilters.clear();
 
     setDisplayName(name);
     setShortcutString(shortcut);
@@ -108,19 +111,29 @@ bool DirectoryFilter::openConfigDialog(QWidget *parent, bool &needsRefresh)
     m_ui.nameEdit->selectAll();
     m_ui.directoryList->clear();
     m_ui.directoryList->addItems(m_directories);
-    m_ui.fileTypeEdit->setText(m_filters.join(QLatin1Char(',')));
+    m_ui.filePatternLabel->setText(Utils::msgFilePatternLabel());
+    m_ui.filePatternLabel->setBuddy(m_ui.filePattern);
+    m_ui.filePattern->setToolTip(Utils::msgFilePatternToolTip());
+    m_ui.filePattern->setText(Utils::transform(m_filters, &QDir::toNativeSeparators)
+                              .join(QLatin1Char(',')));
+    m_ui.exclusionPatternLabel->setText(Utils::msgExclusionPatternLabel());
+    m_ui.exclusionPatternLabel->setBuddy(m_ui.exclusionPattern);
+    m_ui.exclusionPattern->setToolTip(Utils::msgFilePatternToolTip());
+    m_ui.exclusionPattern->setText(Utils::transform(m_exclusionFilters, &QDir::toNativeSeparators)
+                                   .join(QLatin1Char(',')));
     m_ui.shortcutEdit->setText(shortcutString());
     m_ui.defaultFlag->setChecked(isIncludedByDefault());
     updateOptionButtons();
     if (dialog.exec() == QDialog::Accepted) {
         QMutexLocker locker(&m_lock);
         bool directoriesChanged = false;
-        QStringList oldDirectories = m_directories;
-        QStringList oldFilters = m_filters;
+        const QStringList oldDirectories = m_directories;
+        const QStringList oldFilters = m_filters;
+        const QStringList oldExclusionFilters = m_exclusionFilters;
         setDisplayName(m_ui.nameEdit->text().trimmed());
         m_directories.clear();
-        int oldCount = oldDirectories.count();
-        int newCount = m_ui.directoryList->count();
+        const int oldCount = oldDirectories.count();
+        const int newCount = m_ui.directoryList->count();
         if (oldCount != newCount)
             directoriesChanged = true;
         for (int i = 0; i < newCount; ++i) {
@@ -128,11 +141,12 @@ bool DirectoryFilter::openConfigDialog(QWidget *parent, bool &needsRefresh)
             if (!directoriesChanged && m_directories.at(i) != oldDirectories.at(i))
                 directoriesChanged = true;
         }
-        m_filters = m_ui.fileTypeEdit->text().trimmed().split(QLatin1Char(','));
+        m_filters = Utils::splitFilterUiText(m_ui.filePattern->text());
+        m_exclusionFilters = Utils::splitFilterUiText(m_ui.exclusionPattern->text());
         setShortcutString(m_ui.shortcutEdit->text().trimmed());
         setIncludedByDefault(m_ui.defaultFlag->isChecked());
-        if (directoriesChanged || oldFilters != m_filters)
-            needsRefresh = true;
+        needsRefresh = directoriesChanged || oldFilters != m_filters
+                || oldExclusionFilters != m_exclusionFilters;
         success = true;
     }
     return success;
@@ -190,7 +204,7 @@ void DirectoryFilter::refresh(QFutureInterface<void> &future)
         }
         directories = m_directories;
     }
-    Utils::SubDirFileIterator subDirIterator(directories, m_filters, {});
+    Utils::SubDirFileIterator subDirIterator(directories, m_filters, m_exclusionFilters);
     future.setProgressRange(0, subDirIterator.maxProgress());
     QStringList filesFound;
     auto end = subDirIterator.end();
diff --git a/src/plugins/coreplugin/locator/directoryfilter.h b/src/plugins/coreplugin/locator/directoryfilter.h
index e0c5d0c379..e9521efdb4 100644
--- a/src/plugins/coreplugin/locator/directoryfilter.h
+++ b/src/plugins/coreplugin/locator/directoryfilter.h
@@ -56,6 +56,7 @@ private:
 
     QStringList m_directories;
     QStringList m_filters;
+    QStringList m_exclusionFilters;
     // Our config dialog, uses in addDirectory and editDirectory
     // to give their dialogs the right parent
     QDialog *m_dialog;
diff --git a/src/plugins/coreplugin/locator/directoryfilter.ui b/src/plugins/coreplugin/locator/directoryfilter.ui
index 496cf3c30d..37d26e4ed7 100644
--- a/src/plugins/coreplugin/locator/directoryfilter.ui
+++ b/src/plugins/coreplugin/locator/directoryfilter.ui
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>393</width>
-    <height>275</height>
+    <height>300</height>
    </rect>
   </property>
   <layout class="QGridLayout">
@@ -24,27 +24,33 @@
       <widget class="QLineEdit" name="nameEdit"/>
      </item>
      <item row="2" column="0">
-      <widget class="QLabel" name="label_3">
+      <widget class="QLabel" name="filePatternLabel">
        <property name="text">
-        <string>File types:</string>
+        <string notr="true">File pattern:</string>
        </property>
       </widget>
      </item>
      <item row="2" column="1" colspan="3">
-      <widget class="QLineEdit" name="fileTypeEdit">
-       <property name="toolTip">
-        <string>Specify file name filters, separated by comma. Filters may contain wildcards.</string>
+      <widget class="QLineEdit" name="filePattern"/>
+     </item>
+     <item row="3" column="0">
+      <widget class="QLabel" name="exclusionPatternLabel">
+       <property name="text">
+        <string notr="true">Exclusion pattern:</string>
        </property>
       </widget>
      </item>
-     <item row="3" column="0">
+     <item row="3" column="1" colspan="3">
+      <widget class="QLineEdit" name="exclusionPattern"/>
+     </item>
+     <item row="4" column="0">
       <widget class="QLabel" name="prefixLabel">
        <property name="text">
         <string notr="true">Prefix:</string>
        </property>
       </widget>
      </item>
-     <item row="3" column="1">
+     <item row="4" column="1">
       <widget class="QLineEdit" name="shortcutEdit">
        <property name="sizePolicy">
         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
@@ -64,7 +70,7 @@ To do this, you type this shortcut and a space in the Locator entry field, and t
        </property>
       </widget>
      </item>
-     <item row="3" column="2" colspan="2">
+     <item row="4" column="2" colspan="2">
       <widget class="QCheckBox" name="defaultFlag">
        <property name="text">
         <string notr="true">Include by default</string>
diff --git a/src/plugins/texteditor/basefilefind.cpp b/src/plugins/texteditor/basefilefind.cpp
index 96e812c096..a501ee6518 100644
--- a/src/plugins/texteditor/basefilefind.cpp
+++ b/src/plugins/texteditor/basefilefind.cpp
@@ -196,15 +196,6 @@ 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
 {
     if (d->m_filterCombo)
@@ -384,16 +375,14 @@ static QLabel *createLabel(const QString &text)
 
 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:"));
+    QLabel *filterLabel = createLabel(msgFilePatternLabel());
     d->m_filterCombo = createCombo(&d->m_filterStrings);
-    d->m_filterCombo->setToolTip(filterToolTip);
+    d->m_filterCombo->setToolTip(msgFilePatternToolTip());
     filterLabel->setBuddy(d->m_filterCombo);
     syncComboWithSettings(d->m_filterCombo, d->m_filterSetting);
-    QLabel *exclusionLabel = createLabel(tr("Exclusion pattern:"));
+    QLabel *exclusionLabel = createLabel(msgExclusionPatternLabel());
     d->m_exclusionCombo = createCombo(&d->m_exclusionStrings);
-    d->m_exclusionCombo->setToolTip(filterToolTip);
+    d->m_exclusionCombo->setToolTip(msgFilePatternToolTip());
     exclusionLabel->setBuddy(d->m_exclusionCombo);
     syncComboWithSettings(d->m_exclusionCombo, d->m_exclusionSetting);
     return { qMakePair(filterLabel,    d->m_filterCombo),
-- 
GitLab