diff --git a/src/plugins/git/gitgrep.cpp b/src/plugins/git/gitgrep.cpp index 20ec0507479a73e28bcf037e2405f7cd3fcdb020..3f0729e9f5496d11dd3af5bcc0dfefef023f65d4 100644 --- a/src/plugins/git/gitgrep.cpp +++ b/src/plugins/git/gitgrep.cpp @@ -27,24 +27,21 @@ #include "gitclient.h" #include "gitplugin.h" -#include <coreplugin/editormanager/editormanager.h> -#include <coreplugin/find/findplugin.h> #include <coreplugin/vcsmanager.h> +#include <texteditor/findinfiles.h> #include <vcsbase/vcsbaseconstants.h> #include <utils/filesearch.h> #include <utils/fileutils.h> -#include <utils/pathchooser.h> #include <utils/qtcassert.h> #include <utils/qtcprocess.h> #include <utils/runextensions.h> -#include <QDir> +#include <QCheckBox> +#include <QCoreApplication> #include <QEventLoop> #include <QFuture> #include <QFutureWatcher> -#include <QGridLayout> -#include <QLabel> #include <QSettings> using namespace Utils; @@ -54,18 +51,10 @@ namespace Internal { using namespace Core; -QString GitGrep::id() const -{ - return QLatin1String("Git Grep"); -} - -QString GitGrep::displayName() const -{ - return tr("Git Grep"); -} - namespace { +const char EnableGitGrep[] = "EnableGitGrep"; + class GitGrepRunner : public QObject { using FutureInterfaceType = QFutureInterface<FileSearchResultList>; @@ -180,116 +169,71 @@ private: } // namespace -QFuture<FileSearchResultList> GitGrep::executeSearch( - const TextEditor::FileFindParameters ¶meters) -{ - return Utils::runAsync<FileSearchResultList>(GitGrepRunner::run, parameters); -} - -FileIterator *GitGrep::files(const QStringList &, const QVariant &) const +static bool validateDirectory(const QString &path) { - QTC_ASSERT(false, return 0); + static IVersionControl *gitVc = VcsManager::versionControl(VcsBase::Constants::VCS_ID_GIT); + QTC_ASSERT(gitVc, return false); + return gitVc == VcsManager::findVersionControlForDirectory(path, 0); } -QVariant GitGrep::additionalParameters() const +GitGrep::GitGrep() { - return qVariantFromValue(path().toString()); + m_widget = new QCheckBox(tr("&Use Git Grep")); + m_widget->setToolTip(tr("Use Git Grep for searching. This includes only files " + "that are managed by source control.")); + TextEditor::FindInFiles *findInFiles = TextEditor::FindInFiles::instance(); + QTC_ASSERT(findInFiles, return); + QObject::connect(findInFiles, &TextEditor::FindInFiles::pathChanged, + m_widget.data(), [this](const QString &path) { + m_widget->setEnabled(validateDirectory(path)); + }); + findInFiles->setFindExtension(this); } -QString GitGrep::label() const +GitGrep::~GitGrep() { - const QChar slash = QLatin1Char('/'); - const QStringList &nonEmptyComponents = path().toFileInfo().absoluteFilePath() - .split(slash, QString::SkipEmptyParts); - return tr("Git Grep \"%1\":").arg(nonEmptyComponents.isEmpty() ? QString(slash) - : nonEmptyComponents.last()); + delete m_widget.data(); } -QString GitGrep::toolTip() const +QString GitGrep::title() const { - //: %3 is filled by BaseFileFind::runNewSearch - return tr("Path: %1\nFilter: %2\n%3") - .arg(path().toUserOutput(), fileNameFilters().join(QLatin1Char(','))); + return tr("Git Grep"); } -bool GitGrep::validateDirectory(FancyLineEdit *edit, QString *errorMessage) const +QWidget *GitGrep::widget() const { - static IVersionControl *gitVc = - VcsManager::versionControl(VcsBase::Constants::VCS_ID_GIT); - QTC_ASSERT(gitVc, return false); - if (!m_directory->defaultValidationFunction()(edit, errorMessage)) - return false; - const QString path = m_directory->path(); - IVersionControl *vc = VcsManager::findVersionControlForDirectory(path, 0); - if (vc == gitVc) - return true; - if (errorMessage) - *errorMessage = tr("The path \"%1\" is not managed by Git").arg(path); - return false; + return m_widget.data(); } -QWidget *GitGrep::createConfigWidget() +bool GitGrep::isEnabled() const { - if (!m_configWidget) { - m_configWidget = new QWidget; - QGridLayout * const gridLayout = new QGridLayout(m_configWidget); - gridLayout->setMargin(0); - m_configWidget->setLayout(gridLayout); - - QLabel *dirLabel = new QLabel(tr("Director&y:")); - gridLayout->addWidget(dirLabel, 0, 0, Qt::AlignRight); - m_directory = new PathChooser; - m_directory->setExpectedKind(PathChooser::ExistingDirectory); - m_directory->setHistoryCompleter(QLatin1String("Git.Grep.History"), true); - m_directory->setPromptDialogTitle(tr("Directory to search")); - m_directory->setValidationFunction([this](FancyLineEdit *edit, QString *errorMessage) { - return validateDirectory(edit, errorMessage); - }); - connect(m_directory.data(), &PathChooser::validChanged, - this, &GitGrep::enabledChanged); - dirLabel->setBuddy(m_directory); - gridLayout->addWidget(m_directory, 0, 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, 1, 0); - gridLayout->addWidget(patternWidget, 1, 1, 1, 2); - m_configWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); - } - return m_configWidget; + return m_widget->isEnabled() && m_widget->isChecked(); } -FileName GitGrep::path() const +bool GitGrep::isEnabled(const TextEditor::FileFindParameters ¶meters) const { - return m_directory->fileName(); + return parameters.extensionParameters.toBool(); } -void GitGrep::writeSettings(QSettings *settings) +QVariant GitGrep::parameters() const { - settings->beginGroup(QLatin1String("GitGrep")); - writeCommonSettings(settings); - settings->endGroup(); + return isEnabled(); } void GitGrep::readSettings(QSettings *settings) { - settings->beginGroup(QLatin1String("GitGrep")); - readCommonSettings(settings, QLatin1String("*")); - settings->endGroup(); + m_widget->setChecked(settings->value(QLatin1String(EnableGitGrep), false).toBool()); } -bool GitGrep::isValid() const +void GitGrep::writeSettings(QSettings *settings) const { - return m_directory->isValid(); + settings->setValue(QLatin1String(EnableGitGrep), m_widget->isChecked()); } -void GitGrep::setDirectory(const FileName &directory) +QFuture<FileSearchResultList> GitGrep::executeSearch( + const TextEditor::FileFindParameters ¶meters) { - m_directory->setFileName(directory); + return Utils::runAsync<FileSearchResultList>(GitGrepRunner::run, parameters); } } // Internal diff --git a/src/plugins/git/gitgrep.h b/src/plugins/git/gitgrep.h index d919cfad8d60597545d1288d5558abcef0db3c62..67a239bf582b49c7f51101fcfe403e5815b128bc 100644 --- a/src/plugins/git/gitgrep.h +++ b/src/plugins/git/gitgrep.h @@ -33,43 +33,30 @@ #include <QPointer> #include <QStringListModel> -namespace Utils { -class FancyLineEdit; -class PathChooser; -} +QT_FORWARD_DECLARE_CLASS(QCheckBox) namespace Git { namespace Internal { -class GitGrep : public TextEditor::BaseFileFind +class GitGrep : public TextEditor::FileFindExtension { - Q_OBJECT + Q_DECLARE_TR_FUNCTIONS(GitGrep) public: - QString id() const override; - QString displayName() const override; + GitGrep(); + ~GitGrep() override; + QString title() const override; + QWidget *widget() const override; + bool isEnabled() const override; + bool isEnabled(const TextEditor::FileFindParameters ¶meters) const override; + QVariant parameters() const override; + void readSettings(QSettings *settings) override; + void writeSettings(QSettings *settings) const override; QFuture<Utils::FileSearchResultList> executeSearch( const TextEditor::FileFindParameters ¶meters) override; - QWidget *createConfigWidget() override; - void writeSettings(QSettings *settings) override; - void readSettings(QSettings *settings) override; - bool isValid() const override; - - void setDirectory(const Utils::FileName &directory); - -protected: - Utils::FileIterator *files(const QStringList &nameFilters, - const QVariant &additionalParameters) const override; - QVariant additionalParameters() const override; - QString label() const override; - QString toolTip() const override; private: - Utils::FileName path() const; - bool validateDirectory(Utils::FancyLineEdit *edit, QString *errorMessage) const; - - QPointer<QWidget> m_configWidget; - QPointer<Utils::PathChooser> m_directory; + QPointer<QCheckBox> m_widget; }; } // namespace Internal diff --git a/src/plugins/texteditor/basefilefind.cpp b/src/plugins/texteditor/basefilefind.cpp index b5077262edf8d25088bba0fe065ed61912acceab..bb8c9f2f1cc8091cbe889129ffe067136d9a2f0c 100644 --- a/src/plugins/texteditor/basefilefind.cpp +++ b/src/plugins/texteditor/basefilefind.cpp @@ -68,15 +68,14 @@ public: class BaseFileFindPrivate { public: - BaseFileFindPrivate() : m_resultLabel(0), m_filterCombo(0) {} - QMap<QFutureWatcher<FileSearchResultList> *, QPointer<SearchResult> > m_watchers; QPointer<IFindSupport> m_currentFindSupport; - QLabel *m_resultLabel; + QLabel *m_resultLabel = 0; QStringListModel m_filterStrings; QString m_filterSetting; QPointer<QComboBox> m_filterCombo; + QPointer<FileFindExtension> m_extension; }; } // namespace Internal @@ -130,6 +129,11 @@ QStringList BaseFileFind::fileNameFilters() const return filters; } +FileFindExtension *BaseFileFind::extension() const +{ + return d->m_extension.data(); +} + void BaseFileFind::runNewSearch(const QString &txt, FindFlags findFlags, SearchResultWindow::SearchMode searchMode) { @@ -147,6 +151,8 @@ void BaseFileFind::runNewSearch(const QString &txt, FindFlags findFlags, parameters.flags = findFlags; parameters.nameFilters = fileNameFilters(); parameters.additionalParameters = additionalParameters(); + if (d->m_extension) + parameters.extensionParameters = d->m_extension->parameters(); search->setUserData(qVariantFromValue(parameters)); connect(search, &SearchResult::activated, this, &BaseFileFind::openEditor); if (searchMode == SearchResultWindow::SearchAndReplace) @@ -192,6 +198,12 @@ void BaseFileFind::replaceAll(const QString &txt, FindFlags findFlags) runNewSearch(txt, findFlags, SearchResultWindow::SearchAndReplace); } +void BaseFileFind::setFindExtension(FileFindExtension *extension) +{ + QTC_ASSERT(!d->m_extension, return); + d->m_extension = extension; +} + void BaseFileFind::doReplace(const QString &text, const QList<SearchResultItem> &items, bool preserveCase) @@ -263,6 +275,8 @@ void BaseFileFind::writeCommonSettings(QSettings *settings) settings->setValue(QLatin1String("filters"), d->m_filterStrings.stringList()); if (d->m_filterCombo) settings->setValue(QLatin1String("currentFilter"), d->m_filterCombo->currentText()); + if (d->m_extension) + d->m_extension->writeSettings(settings); } void BaseFileFind::readCommonSettings(QSettings *settings, const QString &defaultFilter) @@ -276,6 +290,8 @@ void BaseFileFind::readCommonSettings(QSettings *settings, const QString &defaul d->m_filterStrings.setStringList(filters); if (d->m_filterCombo) syncComboWithSettings(d->m_filterCombo, d->m_filterSetting); + if (d->m_extension) + d->m_extension->readSettings(settings); } void BaseFileFind::syncComboWithSettings(QComboBox *combo, const QString &setting) @@ -425,6 +441,9 @@ QVariant BaseFileFind::getAdditionalParameters(SearchResult *search) QFuture<FileSearchResultList> BaseFileFind::executeSearch(const FileFindParameters ¶meters) { + if (d->m_extension && d->m_extension->isEnabled(parameters)) + return d->m_extension->executeSearch(parameters); + auto func = parameters.flags & FindRegularExpression ? Utils::findInFilesRegExp : Utils::findInFiles; diff --git a/src/plugins/texteditor/basefilefind.h b/src/plugins/texteditor/basefilefind.h index 31f56ed368f993d2f09db79dd89ff4a4024498a2..fd74bccbe3eb52802f6213a757c08f11028435a9 100644 --- a/src/plugins/texteditor/basefilefind.h +++ b/src/plugins/texteditor/basefilefind.h @@ -57,6 +57,22 @@ public: Core::FindFlags flags; QStringList nameFilters; QVariant additionalParameters; + QVariant extensionParameters; +}; + +class TEXTEDITOR_EXPORT FileFindExtension : public QObject +{ +public: + virtual ~FileFindExtension() {} + virtual QString title() const = 0; + virtual QWidget *widget() const = 0; + virtual bool isEnabled() const = 0; + virtual bool isEnabled(const FileFindParameters ¶meters) const = 0; + virtual QVariant parameters() const = 0; + virtual void readSettings(QSettings *settings) = 0; + virtual void writeSettings(QSettings *settings) const = 0; + virtual QFuture<Utils::FileSearchResultList> executeSearch( + const FileFindParameters ¶meters) = 0; }; class TEXTEDITOR_EXPORT BaseFileFind : public Core::IFindFilter @@ -71,6 +87,7 @@ public: bool isReplaceSupported() const { return true; } void findAll(const QString &txt, Core::FindFlags findFlags); void replaceAll(const QString &txt, Core::FindFlags findFlags); + void setFindExtension(FileFindExtension *extension); /* returns the list of unique files that were passed in items */ static QStringList replaceAll(const QString &txt, @@ -94,6 +111,7 @@ protected: void syncComboWithSettings(QComboBox *combo, const QString &setting); void updateComboEntries(QComboBox *combo, bool onTop); QStringList fileNameFilters() const; + FileFindExtension *extension() const; private: void displayResult(int index); diff --git a/src/plugins/texteditor/findinfiles.cpp b/src/plugins/texteditor/findinfiles.cpp index 34510fb44d20d28c5ae8d83509f3ba90591cfec0..06c21c127679cb8415438c09ef68a0a576125021 100644 --- a/src/plugins/texteditor/findinfiles.cpp +++ b/src/plugins/texteditor/findinfiles.cpp @@ -92,10 +92,17 @@ QVariant FindInFiles::additionalParameters() const QString FindInFiles::label() const { + QString title = tr("Directory"); + if (FileFindExtension *ext = extension()) { + if (ext->isEnabled()) + title = ext->title(); + } const QChar slash = QLatin1Char('/'); const QStringList &nonEmptyComponents = path().toFileInfo().absoluteFilePath() .split(slash, QString::SkipEmptyParts); - return tr("Directory \"%1\":").arg(nonEmptyComponents.isEmpty() ? QString(slash) : nonEmptyComponents.last()); + return tr("%1 \"%2\":") + .arg(title) + .arg(nonEmptyComponents.isEmpty() ? QString(slash) : nonEmptyComponents.last()); } QString FindInFiles::toolTip() const @@ -114,15 +121,21 @@ QWidget *FindInFiles::createConfigWidget() gridLayout->setMargin(0); m_configWidget->setLayout(gridLayout); + int row = 0; + if (FileFindExtension *ext = extension()) + gridLayout->addWidget(ext->widget(), row++, 1, 1, 2); + QLabel *dirLabel = new QLabel(tr("Director&y:")); - gridLayout->addWidget(dirLabel, 0, 0, Qt::AlignRight); + gridLayout->addWidget(dirLabel, row, 0, Qt::AlignRight); m_directory = new PathChooser; m_directory->setExpectedKind(PathChooser::ExistingDirectory); - m_directory->setHistoryCompleter(QLatin1String(HistoryKey), - /*restoreLastItemFromHistory=*/ true); m_directory->setPromptDialogTitle(tr("Directory to Search")); + connect(m_directory.data(), &PathChooser::pathChanged, + this, &FindInFiles::pathChanged); connect(m_directory.data(), &PathChooser::validChanged, this, &FindInFiles::enabledChanged); + m_directory->setHistoryCompleter(QLatin1String(HistoryKey), + /*restoreLastItemFromHistory=*/ true); if (!HistoryCompleter::historyExistsFor(QLatin1String(HistoryKey))) { auto completer = static_cast<HistoryCompleter *>(m_directory->lineEdit()->completer()); const QStringList legacyHistory = Core::ICore::settings()->value( @@ -131,7 +144,7 @@ QWidget *FindInFiles::createConfigWidget() completer->addEntry(dir); } dirLabel->setBuddy(m_directory); - gridLayout->addWidget(m_directory, 0, 1, 1, 2); + gridLayout->addWidget(m_directory, row++, 1, 1, 2); QLabel * const filePatternLabel = new QLabel(tr("Fi&le pattern:")); filePatternLabel->setMinimumWidth(80); @@ -139,8 +152,8 @@ QWidget *FindInFiles::createConfigWidget() filePatternLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); QWidget *patternWidget = createPatternWidget(); filePatternLabel->setBuddy(patternWidget); - gridLayout->addWidget(filePatternLabel, 1, 0); - gridLayout->addWidget(patternWidget, 1, 1, 1, 2); + gridLayout->addWidget(filePatternLabel, row, 0); + gridLayout->addWidget(patternWidget, row++, 1, 1, 2); m_configWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); } return m_configWidget; @@ -170,6 +183,11 @@ void FindInFiles::setDirectory(const FileName &directory) m_directory->setFileName(directory); } +FileName FindInFiles::directory() const +{ + return m_directory->fileName(); +} + void FindInFiles::findOnFileSystem(const QString &path) { QTC_ASSERT(m_instance, return); @@ -178,3 +196,8 @@ void FindInFiles::findOnFileSystem(const QString &path) m_instance->setDirectory(FileName::fromString(folder)); FindPlugin::instance()->openFindDialog(m_instance); } + +FindInFiles *FindInFiles::instance() +{ + return m_instance; +} diff --git a/src/plugins/texteditor/findinfiles.h b/src/plugins/texteditor/findinfiles.h index e0bd247ac1f3ed2225ff1b18a9b6f88171e2ab77..c04982031158bb2fa5c9f18d479b60e9fd5cfa29 100644 --- a/src/plugins/texteditor/findinfiles.h +++ b/src/plugins/texteditor/findinfiles.h @@ -55,7 +55,12 @@ public: bool isValid() const; void setDirectory(const Utils::FileName &directory); + Utils::FileName directory() const; static void findOnFileSystem(const QString &path); + static FindInFiles *instance(); + +signals: + void pathChanged(const QString &directory); protected: Utils::FileIterator *files(const QStringList &nameFilters, diff --git a/src/plugins/texteditor/texteditorplugin.cpp b/src/plugins/texteditor/texteditorplugin.cpp index 29ee1ad42a92dae21ea648d71d11a90c9bbdcac9..8c729f9bdc041782f1c585e7e93b43a0e7380cd8 100644 --- a/src/plugins/texteditor/texteditorplugin.cpp +++ b/src/plugins/texteditor/texteditorplugin.cpp @@ -129,6 +129,10 @@ bool TextEditorPlugin::initialize(const QStringList &arguments, QString *errorMe m_baseTextMarkRegistry = new TextMarkRegistry(this); + addAutoReleasedObject(new FindInFiles); + addAutoReleasedObject(new FindInCurrentFile); + addAutoReleasedObject(new FindInOpenFiles); + return true; } @@ -146,10 +150,6 @@ void TextEditorPlugin::extensionsInitialized() updateSearchResultsTabWidth(m_settings->codeStyle()->currentTabSettings()); - addAutoReleasedObject(new FindInFiles); - addAutoReleasedObject(new FindInCurrentFile); - addAutoReleasedObject(new FindInOpenFiles); - Utils::MacroExpander *expander = Utils::globalMacroExpander(); expander->registerVariable(kCurrentDocumentSelection,