diff --git a/src/plugins/coreplugin/find/currentdocumentfind.cpp b/src/plugins/coreplugin/find/currentdocumentfind.cpp
index 7fe84aac158..529bbc4a2ba 100644
--- a/src/plugins/coreplugin/find/currentdocumentfind.cpp
+++ b/src/plugins/coreplugin/find/currentdocumentfind.cpp
@@ -81,6 +81,13 @@ bool CurrentDocumentFind::supportsReplace() const
return m_currentFind->supportsReplace();
}
+bool CurrentDocumentFind::supportsSelectAll() const
+{
+ if (!m_currentFind)
+ return false;
+ return m_currentFind->supportsSelectAll();
+}
+
FindFlags CurrentDocumentFind::supportedFindFlags() const
{
QTC_ASSERT(m_currentFind, return {});
@@ -119,6 +126,12 @@ IFindSupport::Result CurrentDocumentFind::findStep(const QString &txt, FindFlags
return m_currentFind->findStep(txt, findFlags);
}
+void CurrentDocumentFind::selectAll(const QString &txt, FindFlags findFlags)
+{
+ QTC_ASSERT(m_currentFind && m_currentFind->supportsSelectAll(), return);
+ m_currentFind->selectAll(txt, findFlags);
+}
+
void CurrentDocumentFind::replace(const QString &before, const QString &after, FindFlags findFlags)
{
QTC_ASSERT(m_currentFind, return);
diff --git a/src/plugins/coreplugin/find/currentdocumentfind.h b/src/plugins/coreplugin/find/currentdocumentfind.h
index 32aa5b97f8e..4a879a134fc 100644
--- a/src/plugins/coreplugin/find/currentdocumentfind.h
+++ b/src/plugins/coreplugin/find/currentdocumentfind.h
@@ -42,6 +42,7 @@ public:
void resetIncrementalSearch();
void clearHighlights();
bool supportsReplace() const;
+ bool supportsSelectAll() const;
FindFlags supportedFindFlags() const;
QString currentFindString() const;
QString completedFindString() const;
@@ -51,6 +52,7 @@ public:
void highlightAll(const QString &txt, FindFlags findFlags);
IFindSupport::Result findIncremental(const QString &txt, FindFlags findFlags);
IFindSupport::Result findStep(const QString &txt, FindFlags findFlags);
+ void selectAll(const QString &txt, FindFlags findFlags);
void replace(const QString &before, const QString &after, FindFlags findFlags);
bool replaceStep(const QString &before, const QString &after, FindFlags findFlags);
int replaceAll(const QString &before, const QString &after, FindFlags findFlags);
diff --git a/src/plugins/coreplugin/find/findtoolbar.cpp b/src/plugins/coreplugin/find/findtoolbar.cpp
index 498b290b264..4a374fa742e 100644
--- a/src/plugins/coreplugin/find/findtoolbar.cpp
+++ b/src/plugins/coreplugin/find/findtoolbar.cpp
@@ -222,6 +222,17 @@ FindToolBar::FindToolBar(CurrentDocumentFind *currentDocumentFind)
connect(m_findPreviousSelectedAction, &QAction::triggered,
this, &FindToolBar::findPreviousSelected);
+ m_selectAllAction = new QAction(tr("Select All"), this);
+ cmd = ActionManager::registerAction(m_selectAllAction, Constants::FIND_SELECT_ALL);
+ cmd->setDefaultKeySequence(QKeySequence(tr("Alt+Return")));
+ mfind->addAction(cmd, Constants::G_FIND_ACTIONS);
+ connect(m_selectAllAction, &QAction::triggered, this, &FindToolBar::selectAll);
+ m_localSelectAllAction = new QAction(m_selectAllAction->text(), this);
+ cmd = ActionManager::registerAction(m_localSelectAllAction, Constants::FIND_SELECT_ALL, findcontext);
+ cmd->setDefaultKeySequence(QKeySequence(tr("Alt+Return")));
+ connect(m_localSelectAllAction, &QAction::triggered, this, &FindToolBar::selectAll);
+ m_ui.selectAllButton->setDefaultAction(m_localSelectAllAction);
+
m_replaceAction = new QAction(tr("Replace"), this);
cmd = ActionManager::registerAction(m_replaceAction, Constants::REPLACE);
cmd->setDefaultKeySequence(QKeySequence());
@@ -400,6 +411,7 @@ void FindToolBar::updateActions()
if (m_enterFindStringAction)
m_enterFindStringAction->setEnabled(enabled);
updateFindReplaceEnabled();
+ m_selectAllAction->setEnabled(m_currentDocumentFind->supportsSelectAll());
}
void FindToolBar::updateToolBar()
@@ -869,6 +881,15 @@ void FindToolBar::findPreviousSelected()
invokeFindPrevious();
}
+void FindToolBar::selectAll()
+{
+ if (m_currentDocumentFind->isEnabled()) {
+ const FindFlags ef = effectiveFindFlags();
+ Find::updateFindCompletion(getFindText(), ef);
+ m_currentDocumentFind->selectAll(getFindText(), ef);
+ }
+}
+
bool FindToolBar::focusNextPrevChild(bool next)
{
QAbstractButton *optionsButton = m_ui.findEdit->button(Utils::FancyLineEdit::Left);
@@ -1000,6 +1021,7 @@ void FindToolBar::updateFindReplaceEnabled()
m_localFindPreviousAction->setEnabled(enabled);
m_findEnabled = enabled;
}
+ m_localSelectAllAction->setEnabled(enabled && m_currentDocumentFind->supportsSelectAll());
m_findNextAction->setEnabled(enabled && m_findInDocumentAction->isEnabled());
m_findPreviousAction->setEnabled(enabled && m_findInDocumentAction->isEnabled());
diff --git a/src/plugins/coreplugin/find/findtoolbar.h b/src/plugins/coreplugin/find/findtoolbar.h
index 34103b234ac..485e67381df 100644
--- a/src/plugins/coreplugin/find/findtoolbar.h
+++ b/src/plugins/coreplugin/find/findtoolbar.h
@@ -104,6 +104,7 @@ private:
void openFind(bool focus = true);
void findNextSelected();
void findPreviousSelected();
+ void selectAll();
void updateActions();
void updateToolBar();
void findFlagsChanged();
@@ -149,6 +150,7 @@ private:
QAction *m_findInDocumentAction = nullptr;
QAction *m_findNextSelectedAction = nullptr;
QAction *m_findPreviousSelectedAction = nullptr;
+ QAction *m_selectAllAction = nullptr;
QAction *m_enterFindStringAction = nullptr;
QAction *m_findNextAction = nullptr;
QAction *m_findPreviousAction = nullptr;
@@ -163,6 +165,7 @@ private:
QAction *m_localFindNextAction = nullptr;
QAction *m_localFindPreviousAction = nullptr;
+ QAction *m_localSelectAllAction = nullptr;
QAction *m_localReplaceAction = nullptr;
QAction *m_localReplaceNextAction = nullptr;
QAction *m_localReplacePreviousAction = nullptr;
diff --git a/src/plugins/coreplugin/find/findwidget.ui b/src/plugins/coreplugin/find/findwidget.ui
index 89c847b3203..2e50aaa878b 100644
--- a/src/plugins/coreplugin/find/findwidget.ui
+++ b/src/plugins/coreplugin/find/findwidget.ui
@@ -73,6 +73,13 @@
-
+ -
+
+
+
+
+
+
-
diff --git a/src/plugins/coreplugin/find/ifindsupport.cpp b/src/plugins/coreplugin/find/ifindsupport.cpp
index 9dc51794d69..84087553b36 100644
--- a/src/plugins/coreplugin/find/ifindsupport.cpp
+++ b/src/plugins/coreplugin/find/ifindsupport.cpp
@@ -66,6 +66,15 @@ using namespace Core;
Returns whether the find filter supports search and replace.
*/
+/*!
+ \fn bool Core::IFindSupport::supportsSelectAll() const
+ Returns whether the find filter supports selecting all results.
+*/
+bool IFindSupport::supportsSelectAll() const
+{
+ return false;
+}
+
/*!
\fn Core::FindFlags Core::IFindSupport::supportedFindFlags() const
Returns the find flags, such as whole words or regular expressions,
@@ -165,6 +174,15 @@ int IFindSupport::replaceAll(const QString &before, const QString &after, FindFl
return 0;
}
+/*!
+ Finds and selects all instances of \a txt with specified \a findFlags.
+*/
+void IFindSupport::selectAll(const QString &txt, FindFlags findFlags)
+{
+ Q_UNUSED(txt)
+ Q_UNUSED(findFlags)
+}
+
/*!
Shows \a parent overlayed with the wrap indicator.
*/
diff --git a/src/plugins/coreplugin/find/ifindsupport.h b/src/plugins/coreplugin/find/ifindsupport.h
index f1ec970b924..106e3ea9bc1 100644
--- a/src/plugins/coreplugin/find/ifindsupport.h
+++ b/src/plugins/coreplugin/find/ifindsupport.h
@@ -43,6 +43,7 @@ public:
~IFindSupport() override = default;
virtual bool supportsReplace() const = 0;
+ virtual bool supportsSelectAll() const;
virtual FindFlags supportedFindFlags() const = 0;
virtual void resetIncrementalSearch() = 0;
virtual void clearHighlights() = 0;
@@ -58,6 +59,7 @@ public:
FindFlags findFlags);
virtual int replaceAll(const QString &before, const QString &after,
FindFlags findFlags);
+ virtual void selectAll(const QString &txt, FindFlags findFlags);
virtual void defineFindScope(){}
virtual void clearFindScope(){}
diff --git a/src/plugins/coreplugin/find/textfindconstants.h b/src/plugins/coreplugin/find/textfindconstants.h
index d670abd0f04..120a01fd171 100644
--- a/src/plugins/coreplugin/find/textfindconstants.h
+++ b/src/plugins/coreplugin/find/textfindconstants.h
@@ -47,6 +47,7 @@ const char ADVANCED_FIND[] = "Find.Dialog";
const char FIND_IN_DOCUMENT[] = "Find.FindInCurrentDocument";
const char FIND_NEXT_SELECTED[]= "Find.FindNextSelected";
const char FIND_PREV_SELECTED[]= "Find.FindPreviousSelected";
+const char FIND_SELECT_ALL[] = "Find.SelectAll";
const char FIND_NEXT[] = "Find.FindNext";
const char FIND_PREVIOUS[] = "Find.FindPrevious";
const char REPLACE[] = "Find.Replace";
diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp
index 58a5913675a..455a0203dbf 100644
--- a/src/plugins/texteditor/texteditor.cpp
+++ b/src/plugins/texteditor/texteditor.cpp
@@ -825,6 +825,76 @@ public:
QStack m_undoCursorStack;
};
+class TextEditorWidgetFind : public BaseTextFind
+{
+public:
+ TextEditorWidgetFind(TextEditorWidget *editor)
+ : BaseTextFind(editor)
+ , m_editor(editor)
+ {
+ setMultiTextCursorProvider([editor]() { return editor->multiTextCursor(); });
+ }
+
+ bool supportsSelectAll() const override { return true; }
+ void selectAll(const QString &txt, FindFlags findFlags) override;
+
+ static void cancelCurrentSelectAll();
+
+private:
+ TextEditorWidget * const m_editor;
+ static QFutureWatcher *m_selectWatcher;
+};
+
+QFutureWatcher *TextEditorWidgetFind::m_selectWatcher = nullptr;
+
+void TextEditorWidgetFind::selectAll(const QString &txt, FindFlags findFlags)
+{
+ if (txt.isEmpty())
+ return;
+
+ cancelCurrentSelectAll();
+
+ m_selectWatcher = new QFutureWatcher();
+ connect(m_selectWatcher, &QFutureWatcher::finished,
+ this, [this]() {
+ const FileSearchResultList &results = m_selectWatcher->result();
+ const QTextCursor c(m_editor->document());
+ auto cursorForResult = [c](const FileSearchResult &r) {
+ return Utils::Text::selectAt(c, r.lineNumber, r.matchStart + 1, r.matchLength);
+ };
+ QList cursors = Utils::transform(results, cursorForResult);
+ cursors = Utils::filtered(cursors, [this](const QTextCursor &c) {
+ return m_editor->inFindScope(c);
+ });
+ m_editor->setMultiTextCursor(MultiTextCursor(cursors));
+ m_editor->setFocus();
+ });
+
+ const QString &fileName = m_editor->textDocument()->filePath().toString();
+ QMap fileToContentsMap;
+ fileToContentsMap[fileName] = m_editor->textDocument()->plainText();
+
+ FileListIterator *it = new FileListIterator({fileName},
+ {const_cast(
+ m_editor->textDocument()->codec())});
+ const QTextDocument::FindFlags findFlags2 = textDocumentFlagsForFindFlags(findFlags);
+
+ if (findFlags & FindRegularExpression)
+ m_selectWatcher->setFuture(findInFilesRegExp(txt, it, findFlags2, fileToContentsMap));
+ else
+ m_selectWatcher->setFuture(findInFiles(txt, it, findFlags2, fileToContentsMap));
+}
+
+void TextEditorWidgetFind::cancelCurrentSelectAll()
+{
+ if (m_selectWatcher) {
+ m_selectWatcher->disconnect();
+ m_selectWatcher->cancel();
+ m_selectWatcher->deleteLater();
+ m_selectWatcher = nullptr;
+ }
+}
+
TextEditorWidgetPrivate::TextEditorWidgetPrivate(TextEditorWidget *parent)
: q(parent),
m_marksVisible(false),
@@ -841,8 +911,7 @@ TextEditorWidgetPrivate::TextEditorWidgetPrivate(TextEditorWidget *parent)
m_autoCompleter(new AutoCompleter)
{
auto aggregate = new Aggregation::Aggregate;
- m_find = new BaseTextFind(q);
- m_find->setMultiTextCursorProvider([this]() { return m_cursors; });
+ m_find = new TextEditorWidgetFind(q);
connect(m_find, &BaseTextFind::highlightAllRequested,
this, &TextEditorWidgetPrivate::highlightSearchResultsSlot);
connect(m_find, &BaseTextFind::findScopeChanged,
@@ -2307,6 +2376,7 @@ void TextEditorWidget::keyPressEvent(QKeyEvent *e)
} else {
d->m_maybeFakeTooltipEvent = false;
if (e->key() == Qt::Key_Escape ) {
+ TextEditorWidgetFind::cancelCurrentSelectAll();
if (d->m_snippetOverlay->isVisible()) {
e->accept();
d->m_snippetOverlay->accept();
@@ -7823,7 +7893,7 @@ void TextEditorWidget::setRefactorMarkers(const RefactorMarkers &markers)
emit requestBlockUpdate(marker.cursor.block());
}
-bool TextEditorWidget::inFindScope(const QTextCursor &cursor)
+bool TextEditorWidget::inFindScope(const QTextCursor &cursor) const
{
return d->m_find->inScope(cursor);
}
diff --git a/src/plugins/texteditor/texteditor.h b/src/plugins/texteditor/texteditor.h
index 2e702e20d28..7daed6de22c 100644
--- a/src/plugins/texteditor/texteditor.h
+++ b/src/plugins/texteditor/texteditor.h
@@ -564,6 +564,8 @@ public:
void contextHelpItem(const Core::IContext::HelpCallback &callback);
void setContextHelpItem(const Core::HelpItem &item);
+ Q_INVOKABLE bool inFindScope(const QTextCursor &cursor) const;
+
static TextEditorWidget *currentTextEditorWidget();
static TextEditorWidget *fromEditor(const Core::IEditor *editor);
@@ -610,8 +612,6 @@ protected:
virtual void slotCursorPositionChanged(); // Used in VcsBase
virtual void slotCodeStyleSettingsChanged(const QVariant &); // Used in CppEditor
- Q_INVOKABLE bool inFindScope(const QTextCursor &cursor);
-
private:
Internal::TextEditorWidgetPrivate *d;
friend class BaseTextEditor;