forked from qt-creator/qt-creator
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:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -73,6 +73,13 @@
|
||||
<item>
|
||||
<widget class="QToolButton" name="findNextButton"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="selectAllButton">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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(){}
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -825,6 +825,76 @@ public:
|
||||
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)
|
||||
: 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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user