forked from qt-creator/qt-creator
Core: Add searchable terminal
Change-Id: Id058fb1a97c967fc253b08edf3910f019e708b50 Reviewed-by: Cristian Adam <cristian.adam@qt.io>
This commit is contained in:
@@ -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
|
||||||
|
@@ -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
|
@@ -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
|
@@ -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
|
||||||
|
@@ -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});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user