2023-02-23 12:47:39 +01:00
|
|
|
// Copyright (C) 2022 The Qt Company Ltd.
|
|
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
2023-03-24 12:53:21 +01:00
|
|
|
#include "terminalsearch.h"
|
2023-03-03 17:18:56 +01:00
|
|
|
#include "terminalsurface.h"
|
2023-02-23 12:47:39 +01:00
|
|
|
|
2023-03-24 12:53:21 +01:00
|
|
|
#include <aggregation/aggregate.h>
|
|
|
|
|
|
2023-03-06 12:25:26 +01:00
|
|
|
#include <utils/link.h>
|
2023-03-01 08:15:58 +01:00
|
|
|
#include <utils/qtcprocess.h>
|
2023-02-23 12:47:39 +01:00
|
|
|
#include <utils/terminalhooks.h>
|
|
|
|
|
|
|
|
|
|
#include <QAbstractScrollArea>
|
|
|
|
|
#include <QAction>
|
|
|
|
|
#include <QTextLayout>
|
|
|
|
|
#include <QTimer>
|
|
|
|
|
|
2023-03-03 08:11:07 +01:00
|
|
|
#include <chrono>
|
2023-02-23 12:47:39 +01:00
|
|
|
#include <memory>
|
|
|
|
|
|
|
|
|
|
namespace Terminal {
|
|
|
|
|
|
|
|
|
|
class TerminalWidget : public QAbstractScrollArea
|
|
|
|
|
{
|
2023-03-03 17:18:56 +01:00
|
|
|
friend class CellIterator;
|
2023-02-23 12:47:39 +01:00
|
|
|
Q_OBJECT
|
|
|
|
|
public:
|
|
|
|
|
TerminalWidget(QWidget *parent = nullptr,
|
|
|
|
|
const Utils::Terminal::OpenTerminalParameters &openParameters = {});
|
2023-03-24 12:53:21 +01:00
|
|
|
~TerminalWidget() override;
|
2023-02-23 12:47:39 +01:00
|
|
|
|
|
|
|
|
void setFont(const QFont &font);
|
|
|
|
|
|
2023-03-23 11:04:54 +01:00
|
|
|
void copyToClipboard();
|
2023-02-23 12:47:39 +01:00
|
|
|
void pasteFromClipboard();
|
2023-04-06 10:34:33 +02:00
|
|
|
void copyLinkToClipboard();
|
2023-02-23 12:47:39 +01:00
|
|
|
|
|
|
|
|
void clearSelection();
|
|
|
|
|
|
|
|
|
|
void zoomIn();
|
|
|
|
|
void zoomOut();
|
|
|
|
|
|
2023-03-23 14:51:24 +01:00
|
|
|
void moveCursorWordLeft();
|
|
|
|
|
void moveCursorWordRight();
|
|
|
|
|
|
2023-02-23 12:47:39 +01:00
|
|
|
void clearContents();
|
|
|
|
|
|
2023-03-24 12:53:21 +01:00
|
|
|
TerminalSearch *search() { return m_search.get(); }
|
|
|
|
|
|
2023-02-23 12:47:39 +01:00
|
|
|
struct Selection
|
|
|
|
|
{
|
2023-03-03 17:18:56 +01:00
|
|
|
int start;
|
|
|
|
|
int end;
|
2023-03-17 11:01:49 +01:00
|
|
|
bool final{false};
|
2023-03-03 17:18:56 +01:00
|
|
|
|
|
|
|
|
bool operator!=(const Selection &other) const
|
|
|
|
|
{
|
2023-03-17 11:01:49 +01:00
|
|
|
return start != other.start || end != other.end || final != other.final;
|
2023-03-03 17:18:56 +01:00
|
|
|
}
|
2023-03-06 18:37:45 +01:00
|
|
|
|
|
|
|
|
bool operator==(const Selection &other) const { return !operator!=(other); }
|
2023-03-03 17:18:56 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct LinkSelection : public Selection
|
|
|
|
|
{
|
2023-03-06 12:25:26 +01:00
|
|
|
Utils::Link link;
|
2023-03-03 17:18:56 +01:00
|
|
|
|
|
|
|
|
bool operator!=(const LinkSelection &other) const
|
|
|
|
|
{
|
2023-03-06 12:25:26 +01:00
|
|
|
return link != other.link || Selection::operator!=(other);
|
2023-03-03 17:18:56 +01:00
|
|
|
}
|
2023-02-23 12:47:39 +01:00
|
|
|
};
|
|
|
|
|
|
2023-03-07 17:55:38 +01:00
|
|
|
void setShellName(const QString &shellName);
|
2023-03-02 16:59:03 +01:00
|
|
|
QString shellName() const;
|
|
|
|
|
|
2023-03-10 13:55:17 +01:00
|
|
|
Utils::FilePath cwd() const;
|
|
|
|
|
Utils::CommandLine currentCommand() const;
|
2023-03-07 17:55:38 +01:00
|
|
|
std::optional<Utils::Id> identifier() const;
|
|
|
|
|
QProcess::ProcessState processState() const;
|
|
|
|
|
|
|
|
|
|
void restart(const Utils::Terminal::OpenTerminalParameters &openParameters);
|
2023-03-10 13:55:17 +01:00
|
|
|
|
2023-02-23 12:47:39 +01:00
|
|
|
signals:
|
|
|
|
|
void started(qint64 pid);
|
2023-03-10 13:55:17 +01:00
|
|
|
void cwdChanged(const Utils::FilePath &cwd);
|
|
|
|
|
void commandChanged(const Utils::CommandLine &cmd);
|
2023-02-23 12:47:39 +01:00
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
void paintEvent(QPaintEvent *event) override;
|
|
|
|
|
void keyPressEvent(QKeyEvent *event) override;
|
2023-04-06 10:34:33 +02:00
|
|
|
void keyReleaseEvent(QKeyEvent *event) override;
|
2023-02-23 12:47:39 +01:00
|
|
|
void resizeEvent(QResizeEvent *event) override;
|
|
|
|
|
void wheelEvent(QWheelEvent *event) override;
|
|
|
|
|
void focusInEvent(QFocusEvent *event) override;
|
|
|
|
|
void focusOutEvent(QFocusEvent *event) override;
|
|
|
|
|
void inputMethodEvent(QInputMethodEvent *event) override;
|
|
|
|
|
|
|
|
|
|
void mousePressEvent(QMouseEvent *event) override;
|
|
|
|
|
void mouseMoveEvent(QMouseEvent *event) override;
|
|
|
|
|
void mouseReleaseEvent(QMouseEvent *event) override;
|
|
|
|
|
void mouseDoubleClickEvent(QMouseEvent *event) override;
|
|
|
|
|
|
|
|
|
|
void showEvent(QShowEvent *event) override;
|
|
|
|
|
|
|
|
|
|
bool event(QEvent *event) override;
|
|
|
|
|
|
|
|
|
|
protected:
|
2023-03-01 10:48:05 +01:00
|
|
|
void onReadyRead(bool forceFlush);
|
2023-03-03 17:18:56 +01:00
|
|
|
void setupSurface();
|
2023-02-23 12:47:39 +01:00
|
|
|
void setupFont();
|
|
|
|
|
void setupPty();
|
|
|
|
|
void setupColors();
|
2023-03-02 15:21:50 +01:00
|
|
|
void setupActions();
|
2023-02-23 12:47:39 +01:00
|
|
|
|
|
|
|
|
void writeToPty(const QByteArray &data);
|
|
|
|
|
|
2023-03-03 17:18:56 +01:00
|
|
|
int paintCell(QPainter &p,
|
|
|
|
|
const QRectF &cellRect,
|
|
|
|
|
QPoint gridPos,
|
|
|
|
|
const Internal::TerminalCell &cell,
|
2023-03-24 12:53:21 +01:00
|
|
|
QFont &f,
|
|
|
|
|
QList<SearchHit>::const_iterator &searchIt) const;
|
2023-03-03 17:18:56 +01:00
|
|
|
void paintCells(QPainter &painter, QPaintEvent *event) const;
|
|
|
|
|
void paintCursor(QPainter &painter) const;
|
|
|
|
|
void paintPreedit(QPainter &painter) const;
|
2023-03-24 12:53:21 +01:00
|
|
|
bool paintFindMatches(QPainter &painter,
|
|
|
|
|
QList<SearchHit>::const_iterator &searchIt,
|
|
|
|
|
const QRectF &cellRect,
|
|
|
|
|
const QPoint gridPos) const;
|
|
|
|
|
bool paintSelection(QPainter &painter, const QRectF &cellRect, const QPoint gridPos) const;
|
2023-03-03 17:18:56 +01:00
|
|
|
void paintDebugSelection(QPainter &painter, const Selection &selection) const;
|
2023-02-23 12:47:39 +01:00
|
|
|
|
|
|
|
|
qreal topMargin() const;
|
|
|
|
|
|
|
|
|
|
QPoint viewportToGlobal(QPoint p) const;
|
2023-03-03 10:37:38 +01:00
|
|
|
QPoint globalToViewport(QPoint p) const;
|
2023-03-03 17:18:56 +01:00
|
|
|
QPoint globalToGrid(QPointF p) const;
|
|
|
|
|
QPointF gridToGlobal(QPoint p, bool bottom = false, bool right = false) const;
|
|
|
|
|
QRect gridToViewport(QRect rect) const;
|
|
|
|
|
|
|
|
|
|
void updateViewport();
|
2023-03-24 12:53:21 +01:00
|
|
|
void updateViewportRect(const QRect &rect);
|
2023-02-23 12:47:39 +01:00
|
|
|
|
|
|
|
|
int textLineFromPixel(int y) const;
|
|
|
|
|
std::optional<int> textPosFromPoint(const QTextLayout &textLayout, QPoint p) const;
|
|
|
|
|
|
|
|
|
|
std::optional<QTextLayout::FormatRange> selectionToFormatRange(
|
|
|
|
|
TerminalWidget::Selection selection, const QTextLayout &layout, int rowOffset) const;
|
|
|
|
|
|
2023-04-06 10:34:33 +02:00
|
|
|
bool checkLinkAt(const QPoint &pos);
|
2023-03-03 17:18:56 +01:00
|
|
|
|
|
|
|
|
struct TextAndOffsets
|
|
|
|
|
{
|
|
|
|
|
int start;
|
|
|
|
|
int end;
|
|
|
|
|
std::u32string text;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
TextAndOffsets textAt(const QPoint &pos) const;
|
|
|
|
|
|
2023-02-23 12:47:39 +01:00
|
|
|
void applySizeChange();
|
|
|
|
|
void updateScrollBars();
|
|
|
|
|
|
2023-03-01 10:48:05 +01:00
|
|
|
void flushVTerm(bool force);
|
|
|
|
|
|
2023-03-24 12:53:21 +01:00
|
|
|
bool setSelection(const std::optional<Selection> &selection, bool scroll = true);
|
2023-03-17 11:01:49 +01:00
|
|
|
QString textFromSelection() const;
|
2023-03-02 15:21:50 +01:00
|
|
|
|
2023-03-05 23:55:37 +01:00
|
|
|
void configBlinkTimer();
|
|
|
|
|
|
2023-03-22 15:39:55 +01:00
|
|
|
QColor toQColor(std::variant<int, QColor> color) const;
|
|
|
|
|
|
2023-03-23 11:04:54 +01:00
|
|
|
void updateCopyState();
|
|
|
|
|
|
2023-02-23 12:47:39 +01:00
|
|
|
private:
|
2023-03-01 08:15:58 +01:00
|
|
|
std::unique_ptr<Utils::QtcProcess> m_process;
|
2023-03-03 17:18:56 +01:00
|
|
|
std::unique_ptr<Internal::TerminalSurface> m_surface;
|
2023-03-10 13:55:17 +01:00
|
|
|
std::unique_ptr<ShellIntegration> m_shellIntegration;
|
2023-02-23 12:47:39 +01:00
|
|
|
|
2023-03-02 16:59:03 +01:00
|
|
|
QString m_shellName;
|
2023-03-07 17:55:38 +01:00
|
|
|
Utils::Id m_identifier;
|
2023-03-02 16:59:03 +01:00
|
|
|
|
2023-02-23 12:47:39 +01:00
|
|
|
QFont m_font;
|
|
|
|
|
QSizeF m_cellSize;
|
|
|
|
|
|
|
|
|
|
bool m_ignoreScroll{false};
|
|
|
|
|
|
|
|
|
|
QString m_preEditString;
|
|
|
|
|
|
|
|
|
|
std::optional<Selection> m_selection;
|
2023-03-03 17:18:56 +01:00
|
|
|
std::optional<LinkSelection> m_linkSelection;
|
2023-02-23 12:47:39 +01:00
|
|
|
|
|
|
|
|
struct
|
|
|
|
|
{
|
2023-03-03 17:18:56 +01:00
|
|
|
QPoint start;
|
|
|
|
|
QPoint end;
|
|
|
|
|
} m_activeMouseSelect;
|
2023-02-23 12:47:39 +01:00
|
|
|
|
2023-03-01 10:48:05 +01:00
|
|
|
QTimer m_flushDelayTimer;
|
2023-02-23 12:47:39 +01:00
|
|
|
|
2023-03-09 22:33:47 +01:00
|
|
|
QTimer m_scrollTimer;
|
|
|
|
|
int m_scrollDirection{0};
|
|
|
|
|
|
2023-03-24 12:53:21 +01:00
|
|
|
std::array<QColor, 20> m_currentColors;
|
2023-02-23 12:47:39 +01:00
|
|
|
|
|
|
|
|
Utils::Terminal::OpenTerminalParameters m_openParameters;
|
2023-03-01 10:48:05 +01:00
|
|
|
|
2023-03-03 08:11:07 +01:00
|
|
|
std::chrono::system_clock::time_point m_lastFlush;
|
|
|
|
|
std::chrono::system_clock::time_point m_lastDoubleClick;
|
2023-03-01 16:03:18 +01:00
|
|
|
bool m_selectLineMode{false};
|
2023-03-05 23:55:37 +01:00
|
|
|
|
|
|
|
|
Internal::Cursor m_cursor;
|
|
|
|
|
QTimer m_cursorBlinkTimer;
|
|
|
|
|
bool m_cursorBlinkState{true};
|
2023-03-10 13:55:17 +01:00
|
|
|
|
|
|
|
|
Utils::FilePath m_cwd;
|
|
|
|
|
Utils::CommandLine m_currentCommand;
|
2023-03-24 12:53:21 +01:00
|
|
|
|
2023-03-28 10:48:59 +02:00
|
|
|
using TerminalSearchPtr = std::unique_ptr<TerminalSearch, std::function<void(TerminalSearch *)>>;
|
|
|
|
|
TerminalSearchPtr m_search;
|
2023-03-24 12:53:21 +01:00
|
|
|
|
|
|
|
|
Aggregation::Aggregate *m_aggregate{nullptr};
|
|
|
|
|
SearchHit m_lastSelectedHit{};
|
2023-02-23 12:47:39 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
} // namespace Terminal
|