Core: Add searchable terminal

Change-Id: Id058fb1a97c967fc253b08edf3910f019e708b50
Reviewed-by: Cristian Adam <cristian.adam@qt.io>
This commit is contained in:
Marcus Tillmanns
2023-07-20 08:34:09 +02:00
parent 68c3103f76
commit 80b23292b1
6 changed files with 96 additions and 59 deletions

View File

@@ -1,5 +1,5 @@
add_qtc_plugin(Core add_qtc_plugin(Core
DEPENDS Qt::PrintSupport Qt::Qml Qt::Sql Qt::Gui Qt::GuiPrivate DEPENDS Qt::PrintSupport Qt::Qml Qt::Sql Qt::Gui Qt::GuiPrivate TerminalLib
PUBLIC_DEPENDS Aggregation ExtensionSystem Utils PUBLIC_DEPENDS Aggregation ExtensionSystem Utils
SOURCES SOURCES
actionmanager/actioncontainer.cpp actionmanager/actioncontainer.cpp
@@ -285,6 +285,8 @@ add_qtc_plugin(Core
statusbarmanager.h statusbarmanager.h
systemsettings.cpp systemsettings.cpp
systemsettings.h systemsettings.h
terminal/searchableterminal.cpp
terminal/searchableterminal.h
textdocument.cpp textdocument.cpp
textdocument.h textdocument.h
themechooser.cpp themechooser.cpp

View File

@@ -1,7 +1,7 @@
// Copyright (C) 2023 The Qt Company Ltd. // Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "terminalsearch.h" #include "searchableterminal.h"
#include <QElapsedTimer> #include <QElapsedTimer>
#include <QLoggingCategory> #include <QLoggingCategory>
@@ -15,7 +15,7 @@ using namespace Utils;
using namespace std::chrono_literals; using namespace std::chrono_literals;
namespace Terminal { namespace Core {
constexpr std::chrono::milliseconds debounceInterval = 100ms; constexpr std::chrono::milliseconds debounceInterval = 100ms;
@@ -115,7 +115,8 @@ QList<TerminalSolution::SearchHit> TerminalSearch::search()
if (it != m_surface->end()) { if (it != m_surface->end()) {
auto hit = TerminalSolution::SearchHit{it.position(), auto hit = TerminalSolution::SearchHit{it.position(),
static_cast<int>(it.position() + searchString.size())}; static_cast<int>(it.position()
+ searchString.size())};
if (m_findFlags.testFlag(FindFlag::FindWholeWords)) { if (m_findFlags.testFlag(FindFlag::FindWholeWords)) {
hit.start++; hit.start++;
hit.end--; hit.end--;
@@ -207,8 +208,8 @@ void TerminalSearch::debouncedUpdateHits()
FindFlags TerminalSearch::supportedFindFlags() const FindFlags TerminalSearch::supportedFindFlags() const
{ {
return FindFlag::FindCaseSensitively | FindFlag::FindBackward return FindFlag::FindCaseSensitively | FindFlag::FindBackward | FindFlag::FindRegularExpression
| FindFlag::FindRegularExpression | FindFlag::FindWholeWords; | FindFlag::FindWholeWords;
} }
void TerminalSearch::resetIncrementalSearch() void TerminalSearch::resetIncrementalSearch()
@@ -273,4 +274,57 @@ void TerminalSearch::highlightAll(const QString &txt, FindFlags findFlags)
setSearchString(txt, findFlags); setSearchString(txt, findFlags);
} }
} // namespace Terminal SearchableTerminal::SearchableTerminal(QWidget *parent)
: TerminalSolution::TerminalView(parent)
{
m_aggregate = new Aggregation::Aggregate(this);
m_aggregate->add(this);
surfaceChanged();
}
SearchableTerminal::~SearchableTerminal() = default;
void SearchableTerminal::surfaceChanged()
{
TerminalView::surfaceChanged();
m_search = TerminalSearchPtr(new TerminalSearch(surface()), [this](TerminalSearch *p) {
m_aggregate->remove(p);
delete p;
});
m_aggregate->add(m_search.get());
connect(m_search.get(), &TerminalSearch::hitsChanged, this, &SearchableTerminal::updateViewport);
connect(m_search.get(), &TerminalSearch::currentHitChanged, this, [this] {
TerminalSolution::SearchHit hit = m_search->currentHit();
if (hit.start >= 0) {
setSelection(Selection{hit.start, hit.end, true}, hit != m_lastSelectedHit);
m_lastSelectedHit = hit;
}
});
}
void SearchableTerminal::selectionChanged(const std::optional<Selection> &newSelection)
{
TerminalView::selectionChanged(newSelection);
if (selection() && selection()->final) {
QString text = textFromSelection();
if (m_search) {
m_search->setCurrentSelection(
SearchHitWithText{{newSelection->start, newSelection->end}, text});
}
}
}
const QList<TerminalSolution::SearchHit> &SearchableTerminal::searchHits() const
{
if (!m_search)
return TerminalSolution::TerminalView::searchHits();
return m_search->hits();
}
} // namespace Core

View File

@@ -3,23 +3,21 @@
#pragma once #pragma once
#include <terminal/terminalsurface.h> #include "../core_global.h"
#include "../find/ifindsupport.h"
#include <aggregation/aggregate.h>
#include <solutions/terminal/terminalview.h> #include <solutions/terminal/terminalview.h>
#include <coreplugin/find/ifindsupport.h> namespace Core {
#include <coreplugin/find/textfindconstants.h>
#include <QTimer>
namespace Terminal {
struct SearchHitWithText : TerminalSolution::SearchHit struct SearchHitWithText : TerminalSolution::SearchHit
{ {
QString text; QString text;
}; };
class TerminalSearch : public Core::IFindSupport class TerminalSearch : public IFindSupport
{ {
Q_OBJECT Q_OBJECT
public: public:
@@ -69,4 +67,23 @@ private:
QTimer m_debounceTimer; QTimer m_debounceTimer;
}; };
} // namespace Terminal class CORE_EXPORT SearchableTerminal : public TerminalSolution::TerminalView
{
public:
SearchableTerminal(QWidget *parent = nullptr);
~SearchableTerminal() override;
protected:
void surfaceChanged() override;
const QList<TerminalSolution::SearchHit> &searchHits() const override;
void selectionChanged(const std::optional<Selection> &newSelection) override;
private:
using TerminalSearchPtr = std::unique_ptr<TerminalSearch, std::function<void(TerminalSearch *)>>;
TerminalSearchPtr m_search;
TerminalSolution::SearchHit m_lastSelectedHit{};
Aggregation::Aggregate *m_aggregate{nullptr};
};
} // namespace Core

View File

@@ -12,7 +12,6 @@ add_qtc_plugin(Terminal
terminalpane.cpp terminalpane.h terminalpane.cpp terminalpane.h
terminalplugin.cpp terminalplugin.cpp
terminalprocessimpl.cpp terminalprocessimpl.h terminalprocessimpl.cpp terminalprocessimpl.h
terminalsearch.cpp terminalsearch.h
terminalsettings.cpp terminalsettings.h terminalsettings.cpp terminalsettings.h
terminaltr.h terminaltr.h
terminalwidget.cpp terminalwidget.h terminalwidget.cpp terminalwidget.h

View File

@@ -49,7 +49,7 @@ using namespace Core;
namespace Terminal { namespace Terminal {
TerminalWidget::TerminalWidget(QWidget *parent, const OpenTerminalParameters &openParameters) TerminalWidget::TerminalWidget(QWidget *parent, const OpenTerminalParameters &openParameters)
: TerminalSolution::TerminalView(parent) : Core::SearchableTerminal(parent)
, m_context(Utils::Id("TerminalWidget_").withSuffix(QString::number((uintptr_t) this))) , m_context(Utils::Id("TerminalWidget_").withSuffix(QString::number((uintptr_t) this)))
, m_openParameters(openParameters) , m_openParameters(openParameters)
{ {
@@ -73,10 +73,6 @@ TerminalWidget::TerminalWidget(QWidget *parent, const OpenTerminalParameters &op
configBlinkTimer(); configBlinkTimer();
setAllowBlinkingCursor(settings().allowBlinkingCursor()); setAllowBlinkingCursor(settings().allowBlinkingCursor());
}); });
m_aggregate = new Aggregation::Aggregate(this);
m_aggregate->add(this);
m_aggregate->add(m_search.get());
} }
void TerminalWidget::setupPty() void TerminalWidget::setupPty()
@@ -278,23 +274,11 @@ void TerminalWidget::resizePty(QSize newSize)
void TerminalWidget::surfaceChanged() void TerminalWidget::surfaceChanged()
{ {
Core::SearchableTerminal::surfaceChanged();
m_shellIntegration.reset(new ShellIntegration()); m_shellIntegration.reset(new ShellIntegration());
setSurfaceIntegration(m_shellIntegration.get()); setSurfaceIntegration(m_shellIntegration.get());
m_search = TerminalSearchPtr(new TerminalSearch(surface()), [this](TerminalSearch *p) {
m_aggregate->remove(p);
delete p;
});
connect(m_search.get(), &TerminalSearch::hitsChanged, this, &TerminalWidget::updateViewport);
connect(m_search.get(), &TerminalSearch::currentHitChanged, this, [this] {
TerminalSolution::SearchHit hit = m_search->currentHit();
if (hit.start >= 0) {
setSelection(Selection{hit.start, hit.end, true}, hit != m_lastSelectedHit);
m_lastSelectedHit = hit;
}
});
connect(m_shellIntegration.get(), connect(m_shellIntegration.get(),
&ShellIntegration::titleChanged, &ShellIntegration::titleChanged,
this, this,
@@ -373,11 +357,6 @@ std::optional<TerminalSolution::TerminalView::Link> TerminalWidget::toLink(const
return std::nullopt; return std::nullopt;
} }
const QList<TerminalSolution::SearchHit> &TerminalWidget::searchHits() const
{
return m_search->hits();
}
void TerminalWidget::onReadyRead(bool forceFlush) void TerminalWidget::onReadyRead(bool forceFlush)
{ {
QByteArray data = m_process->readAllRawStandardOutput(); QByteArray data = m_process->readAllRawStandardOutput();
@@ -429,6 +408,8 @@ void TerminalWidget::restart(const OpenTerminalParameters &openParameters)
void TerminalWidget::selectionChanged(const std::optional<Selection> &newSelection) void TerminalWidget::selectionChanged(const std::optional<Selection> &newSelection)
{ {
Q_UNUSED(newSelection);
updateCopyState(); updateCopyState();
if (selection() && selection()->final) { if (selection() && selection()->final) {
@@ -437,9 +418,6 @@ void TerminalWidget::selectionChanged(const std::optional<Selection> &newSelecti
QClipboard *clipboard = QApplication::clipboard(); QClipboard *clipboard = QApplication::clipboard();
if (clipboard->supportsSelection()) if (clipboard->supportsSelection())
clipboard->setText(text, QClipboard::Selection); clipboard->setText(text, QClipboard::Selection);
m_search->setCurrentSelection(
SearchHitWithText{{newSelection->start, newSelection->end}, text});
} }
} }

View File

@@ -5,14 +5,12 @@
#include "shellintegration.h" #include "shellintegration.h"
#include "shortcutmap.h" #include "shortcutmap.h"
#include "terminalsearch.h"
#include <solutions/terminal/terminalview.h>
#include <aggregation/aggregate.h> #include <aggregation/aggregate.h>
#include <coreplugin/actionmanager/command.h> #include <coreplugin/actionmanager/command.h>
#include <coreplugin/icontext.h> #include <coreplugin/icontext.h>
#include <coreplugin/terminal/searchableterminal.h>
#include <utils/link.h> #include <utils/link.h>
#include <utils/process.h> #include <utils/process.h>
@@ -22,7 +20,7 @@ namespace Terminal {
using RegisteredAction = std::unique_ptr<QAction, std::function<void(QAction *)>>; using RegisteredAction = std::unique_ptr<QAction, std::function<void(QAction *)>>;
class TerminalWidget : public TerminalSolution::TerminalView class TerminalWidget : public Core::SearchableTerminal
{ {
Q_OBJECT Q_OBJECT
public: public:
@@ -31,8 +29,6 @@ public:
void closeTerminal(); void closeTerminal();
TerminalSearch *search() { return m_search.get(); }
void setShellName(const QString &shellName); void setShellName(const QString &shellName);
QString shellName() const; QString shellName() const;
QString title() const; QString title() const;
@@ -80,8 +76,6 @@ protected:
void setClipboard(const QString &text) override; void setClipboard(const QString &text) override;
std::optional<TerminalView::Link> toLink(const QString &text) override; std::optional<TerminalView::Link> toLink(const QString &text) override;
const QList<TerminalSolution::SearchHit> &searchHits() const override;
RegisteredAction registerAction(Utils::Id commandId, const Core::Context &context); RegisteredAction registerAction(Utils::Id commandId, const Core::Context &context);
void registerShortcut(Core::Command *command); void registerShortcut(Core::Command *command);
@@ -95,8 +89,6 @@ private:
QString m_shellName; QString m_shellName;
QString m_title; QString m_title;
TerminalSolution::SearchHit m_lastSelectedHit{};
Utils::Id m_identifier; Utils::Id m_identifier;
Utils::Terminal::OpenTerminalParameters m_openParameters; Utils::Terminal::OpenTerminalParameters m_openParameters;
@@ -104,11 +96,6 @@ private:
Utils::FilePath m_cwd; Utils::FilePath m_cwd;
Utils::CommandLine m_currentCommand; Utils::CommandLine m_currentCommand;
using TerminalSearchPtr = std::unique_ptr<TerminalSearch, std::function<void(TerminalSearch *)>>;
TerminalSearchPtr m_search;
Aggregation::Aggregate *m_aggregate{nullptr};
RegisteredAction m_copy; RegisteredAction m_copy;
RegisteredAction m_paste; RegisteredAction m_paste;
RegisteredAction m_clearSelection; RegisteredAction m_clearSelection;