Core: add action to select all find results in an Editor

Change-Id: I71f480abde17cfdb6b64d7d12a33c9887792fc61
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
David Schulz
2021-09-28 15:22:44 +02:00
parent cb8bbab171
commit 97a5a24a17
10 changed files with 143 additions and 5 deletions

View File

@@ -81,6 +81,13 @@ bool CurrentDocumentFind::supportsReplace() const
return m_currentFind->supportsReplace(); return m_currentFind->supportsReplace();
} }
bool CurrentDocumentFind::supportsSelectAll() const
{
if (!m_currentFind)
return false;
return m_currentFind->supportsSelectAll();
}
FindFlags CurrentDocumentFind::supportedFindFlags() const FindFlags CurrentDocumentFind::supportedFindFlags() const
{ {
QTC_ASSERT(m_currentFind, return {}); QTC_ASSERT(m_currentFind, return {});
@@ -119,6 +126,12 @@ IFindSupport::Result CurrentDocumentFind::findStep(const QString &txt, FindFlags
return m_currentFind->findStep(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) void CurrentDocumentFind::replace(const QString &before, const QString &after, FindFlags findFlags)
{ {
QTC_ASSERT(m_currentFind, return); QTC_ASSERT(m_currentFind, return);

View File

@@ -42,6 +42,7 @@ public:
void resetIncrementalSearch(); void resetIncrementalSearch();
void clearHighlights(); void clearHighlights();
bool supportsReplace() const; bool supportsReplace() const;
bool supportsSelectAll() const;
FindFlags supportedFindFlags() const; FindFlags supportedFindFlags() const;
QString currentFindString() const; QString currentFindString() const;
QString completedFindString() const; QString completedFindString() const;
@@ -51,6 +52,7 @@ public:
void highlightAll(const QString &txt, FindFlags findFlags); void highlightAll(const QString &txt, FindFlags findFlags);
IFindSupport::Result findIncremental(const QString &txt, FindFlags findFlags); IFindSupport::Result findIncremental(const QString &txt, FindFlags findFlags);
IFindSupport::Result findStep(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); void replace(const QString &before, const QString &after, FindFlags findFlags);
bool replaceStep(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); int replaceAll(const QString &before, const QString &after, FindFlags findFlags);

View File

@@ -222,6 +222,17 @@ FindToolBar::FindToolBar(CurrentDocumentFind *currentDocumentFind)
connect(m_findPreviousSelectedAction, &QAction::triggered, connect(m_findPreviousSelectedAction, &QAction::triggered,
this, &FindToolBar::findPreviousSelected); 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); m_replaceAction = new QAction(tr("Replace"), this);
cmd = ActionManager::registerAction(m_replaceAction, Constants::REPLACE); cmd = ActionManager::registerAction(m_replaceAction, Constants::REPLACE);
cmd->setDefaultKeySequence(QKeySequence()); cmd->setDefaultKeySequence(QKeySequence());
@@ -400,6 +411,7 @@ void FindToolBar::updateActions()
if (m_enterFindStringAction) if (m_enterFindStringAction)
m_enterFindStringAction->setEnabled(enabled); m_enterFindStringAction->setEnabled(enabled);
updateFindReplaceEnabled(); updateFindReplaceEnabled();
m_selectAllAction->setEnabled(m_currentDocumentFind->supportsSelectAll());
} }
void FindToolBar::updateToolBar() void FindToolBar::updateToolBar()
@@ -869,6 +881,15 @@ void FindToolBar::findPreviousSelected()
invokeFindPrevious(); 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) bool FindToolBar::focusNextPrevChild(bool next)
{ {
QAbstractButton *optionsButton = m_ui.findEdit->button(Utils::FancyLineEdit::Left); QAbstractButton *optionsButton = m_ui.findEdit->button(Utils::FancyLineEdit::Left);
@@ -1000,6 +1021,7 @@ void FindToolBar::updateFindReplaceEnabled()
m_localFindPreviousAction->setEnabled(enabled); m_localFindPreviousAction->setEnabled(enabled);
m_findEnabled = enabled; m_findEnabled = enabled;
} }
m_localSelectAllAction->setEnabled(enabled && m_currentDocumentFind->supportsSelectAll());
m_findNextAction->setEnabled(enabled && m_findInDocumentAction->isEnabled()); m_findNextAction->setEnabled(enabled && m_findInDocumentAction->isEnabled());
m_findPreviousAction->setEnabled(enabled && m_findInDocumentAction->isEnabled()); m_findPreviousAction->setEnabled(enabled && m_findInDocumentAction->isEnabled());

View File

@@ -104,6 +104,7 @@ private:
void openFind(bool focus = true); void openFind(bool focus = true);
void findNextSelected(); void findNextSelected();
void findPreviousSelected(); void findPreviousSelected();
void selectAll();
void updateActions(); void updateActions();
void updateToolBar(); void updateToolBar();
void findFlagsChanged(); void findFlagsChanged();
@@ -149,6 +150,7 @@ private:
QAction *m_findInDocumentAction = nullptr; QAction *m_findInDocumentAction = nullptr;
QAction *m_findNextSelectedAction = nullptr; QAction *m_findNextSelectedAction = nullptr;
QAction *m_findPreviousSelectedAction = nullptr; QAction *m_findPreviousSelectedAction = nullptr;
QAction *m_selectAllAction = nullptr;
QAction *m_enterFindStringAction = nullptr; QAction *m_enterFindStringAction = nullptr;
QAction *m_findNextAction = nullptr; QAction *m_findNextAction = nullptr;
QAction *m_findPreviousAction = nullptr; QAction *m_findPreviousAction = nullptr;
@@ -163,6 +165,7 @@ private:
QAction *m_localFindNextAction = nullptr; QAction *m_localFindNextAction = nullptr;
QAction *m_localFindPreviousAction = nullptr; QAction *m_localFindPreviousAction = nullptr;
QAction *m_localSelectAllAction = nullptr;
QAction *m_localReplaceAction = nullptr; QAction *m_localReplaceAction = nullptr;
QAction *m_localReplaceNextAction = nullptr; QAction *m_localReplaceNextAction = nullptr;
QAction *m_localReplacePreviousAction = nullptr; QAction *m_localReplacePreviousAction = nullptr;

View File

@@ -73,6 +73,13 @@
<item> <item>
<widget class="QToolButton" name="findNextButton"/> <widget class="QToolButton" name="findNextButton"/>
</item> </item>
<item>
<widget class="QToolButton" name="selectAllButton">
<property name="text">
<string/>
</property>
</widget>
</item>
<item> <item>
<spacer name="horizontalSpacer"> <spacer name="horizontalSpacer">
<property name="orientation"> <property name="orientation">

View File

@@ -66,6 +66,15 @@ using namespace Core;
Returns whether the find filter supports search and replace. 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 \fn Core::FindFlags Core::IFindSupport::supportedFindFlags() const
Returns the find flags, such as whole words or regular expressions, 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; 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. Shows \a parent overlayed with the wrap indicator.
*/ */

View File

@@ -43,6 +43,7 @@ public:
~IFindSupport() override = default; ~IFindSupport() override = default;
virtual bool supportsReplace() const = 0; virtual bool supportsReplace() const = 0;
virtual bool supportsSelectAll() const;
virtual FindFlags supportedFindFlags() const = 0; virtual FindFlags supportedFindFlags() const = 0;
virtual void resetIncrementalSearch() = 0; virtual void resetIncrementalSearch() = 0;
virtual void clearHighlights() = 0; virtual void clearHighlights() = 0;
@@ -58,6 +59,7 @@ public:
FindFlags findFlags); FindFlags findFlags);
virtual int replaceAll(const QString &before, const QString &after, virtual int replaceAll(const QString &before, const QString &after,
FindFlags findFlags); FindFlags findFlags);
virtual void selectAll(const QString &txt, FindFlags findFlags);
virtual void defineFindScope(){} virtual void defineFindScope(){}
virtual void clearFindScope(){} virtual void clearFindScope(){}

View File

@@ -47,6 +47,7 @@ const char ADVANCED_FIND[] = "Find.Dialog";
const char FIND_IN_DOCUMENT[] = "Find.FindInCurrentDocument"; const char FIND_IN_DOCUMENT[] = "Find.FindInCurrentDocument";
const char FIND_NEXT_SELECTED[]= "Find.FindNextSelected"; const char FIND_NEXT_SELECTED[]= "Find.FindNextSelected";
const char FIND_PREV_SELECTED[]= "Find.FindPreviousSelected"; const char FIND_PREV_SELECTED[]= "Find.FindPreviousSelected";
const char FIND_SELECT_ALL[] = "Find.SelectAll";
const char FIND_NEXT[] = "Find.FindNext"; const char FIND_NEXT[] = "Find.FindNext";
const char FIND_PREVIOUS[] = "Find.FindPrevious"; const char FIND_PREVIOUS[] = "Find.FindPrevious";
const char REPLACE[] = "Find.Replace"; const char REPLACE[] = "Find.Replace";

View File

@@ -825,6 +825,76 @@ public:
QStack<UndoMultiCursor> m_undoCursorStack; QStack<UndoMultiCursor> 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<FileSearchResultList> *m_selectWatcher;
};
QFutureWatcher<FileSearchResultList> *TextEditorWidgetFind::m_selectWatcher = nullptr;
void TextEditorWidgetFind::selectAll(const QString &txt, FindFlags findFlags)
{
if (txt.isEmpty())
return;
cancelCurrentSelectAll();
m_selectWatcher = new QFutureWatcher<FileSearchResultList>();
connect(m_selectWatcher, &QFutureWatcher<Utils::FileSearchResultList>::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<QTextCursor> 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<QString, QString> fileToContentsMap;
fileToContentsMap[fileName] = m_editor->textDocument()->plainText();
FileListIterator *it = new FileListIterator({fileName},
{const_cast<QTextCodec *>(
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) TextEditorWidgetPrivate::TextEditorWidgetPrivate(TextEditorWidget *parent)
: q(parent), : q(parent),
m_marksVisible(false), m_marksVisible(false),
@@ -841,8 +911,7 @@ TextEditorWidgetPrivate::TextEditorWidgetPrivate(TextEditorWidget *parent)
m_autoCompleter(new AutoCompleter) m_autoCompleter(new AutoCompleter)
{ {
auto aggregate = new Aggregation::Aggregate; auto aggregate = new Aggregation::Aggregate;
m_find = new BaseTextFind(q); m_find = new TextEditorWidgetFind(q);
m_find->setMultiTextCursorProvider([this]() { return m_cursors; });
connect(m_find, &BaseTextFind::highlightAllRequested, connect(m_find, &BaseTextFind::highlightAllRequested,
this, &TextEditorWidgetPrivate::highlightSearchResultsSlot); this, &TextEditorWidgetPrivate::highlightSearchResultsSlot);
connect(m_find, &BaseTextFind::findScopeChanged, connect(m_find, &BaseTextFind::findScopeChanged,
@@ -2307,6 +2376,7 @@ void TextEditorWidget::keyPressEvent(QKeyEvent *e)
} else { } else {
d->m_maybeFakeTooltipEvent = false; d->m_maybeFakeTooltipEvent = false;
if (e->key() == Qt::Key_Escape ) { if (e->key() == Qt::Key_Escape ) {
TextEditorWidgetFind::cancelCurrentSelectAll();
if (d->m_snippetOverlay->isVisible()) { if (d->m_snippetOverlay->isVisible()) {
e->accept(); e->accept();
d->m_snippetOverlay->accept(); d->m_snippetOverlay->accept();
@@ -7823,7 +7893,7 @@ void TextEditorWidget::setRefactorMarkers(const RefactorMarkers &markers)
emit requestBlockUpdate(marker.cursor.block()); emit requestBlockUpdate(marker.cursor.block());
} }
bool TextEditorWidget::inFindScope(const QTextCursor &cursor) bool TextEditorWidget::inFindScope(const QTextCursor &cursor) const
{ {
return d->m_find->inScope(cursor); return d->m_find->inScope(cursor);
} }

View File

@@ -564,6 +564,8 @@ public:
void contextHelpItem(const Core::IContext::HelpCallback &callback); void contextHelpItem(const Core::IContext::HelpCallback &callback);
void setContextHelpItem(const Core::HelpItem &item); void setContextHelpItem(const Core::HelpItem &item);
Q_INVOKABLE bool inFindScope(const QTextCursor &cursor) const;
static TextEditorWidget *currentTextEditorWidget(); static TextEditorWidget *currentTextEditorWidget();
static TextEditorWidget *fromEditor(const Core::IEditor *editor); static TextEditorWidget *fromEditor(const Core::IEditor *editor);
@@ -610,8 +612,6 @@ protected:
virtual void slotCursorPositionChanged(); // Used in VcsBase virtual void slotCursorPositionChanged(); // Used in VcsBase
virtual void slotCodeStyleSettingsChanged(const QVariant &); // Used in CppEditor virtual void slotCodeStyleSettingsChanged(const QVariant &); // Used in CppEditor
Q_INVOKABLE bool inFindScope(const QTextCursor &cursor);
private: private:
Internal::TextEditorWidgetPrivate *d; Internal::TextEditorWidgetPrivate *d;
friend class BaseTextEditor; friend class BaseTextEditor;