2021-12-26 23:18:28 +08:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com)
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
2021-07-01 20:24:47 +08:00
|
|
|
#ifndef QCONSOLE_H
|
|
|
|
#define QCONSOLE_H
|
|
|
|
|
|
|
|
#include <QAbstractScrollArea>
|
|
|
|
#include <QVector>
|
2022-01-04 16:50:54 +08:00
|
|
|
#include <memory>
|
2021-07-01 20:24:47 +08:00
|
|
|
|
|
|
|
struct ConsoleLine {
|
|
|
|
QString text;
|
|
|
|
QStringList fragments;
|
|
|
|
int maxColumns;
|
|
|
|
};
|
|
|
|
|
|
|
|
enum class ConsoleCaretType {
|
|
|
|
ctVerticalLine,ctHorizontalLine,ctBlock,ctHalfBlock
|
|
|
|
};
|
|
|
|
|
|
|
|
using PConsoleLine = std::shared_ptr<ConsoleLine>;
|
|
|
|
|
|
|
|
using ConsoleLineList = QVector<PConsoleLine>;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief The RowColumn struct
|
|
|
|
* column and row are 0-based
|
|
|
|
*/
|
|
|
|
struct RowColumn {
|
|
|
|
int column;
|
|
|
|
int row;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief The LineChar struct
|
|
|
|
* line and ch are 0-based
|
|
|
|
*/
|
|
|
|
struct LineChar {
|
|
|
|
int ch;
|
|
|
|
int line;
|
|
|
|
};
|
|
|
|
|
|
|
|
class QConsole;
|
|
|
|
class ConsoleLines : public QObject{
|
|
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
explicit ConsoleLines(QConsole* console);
|
|
|
|
void addLine(const QString& line);
|
|
|
|
void RemoveLastLine();
|
|
|
|
void changeLastLine(const QString& newLine);
|
|
|
|
QString getLastLine();
|
|
|
|
QString getLine(int line);
|
|
|
|
QChar getChar(int line,int ch);
|
|
|
|
QChar getChar(const LineChar& lineChar);
|
|
|
|
/**
|
|
|
|
* @brief getRows
|
|
|
|
* @param startRow 1-based
|
|
|
|
* @param endRow 1-based
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
QStringList getRows(int startRow, int endRow);
|
|
|
|
|
|
|
|
LineChar rowColumnToLineChar(const RowColumn& rowColumn);
|
|
|
|
LineChar rowColumnToLineChar(int row ,int column);
|
|
|
|
RowColumn lineCharToRowColumn(const LineChar& lineChar);
|
|
|
|
RowColumn lineCharToRowColumn(int line, int ch);
|
|
|
|
int rows() const;
|
|
|
|
int lines() const;
|
|
|
|
bool layouting() const;
|
|
|
|
int maxLines() const;
|
|
|
|
void setMaxLines(int maxLines);
|
2021-07-23 13:22:05 +08:00
|
|
|
void clear();
|
2021-07-01 20:24:47 +08:00
|
|
|
|
|
|
|
int getMaxLines() const;
|
|
|
|
public slots:
|
|
|
|
void layout();
|
|
|
|
signals:
|
|
|
|
void layoutStarted();
|
|
|
|
void layoutFinished();
|
|
|
|
void needRelayout();
|
|
|
|
void rowsAdded(int rowCount);
|
|
|
|
void lastRowsRemoved(int rowCount);
|
|
|
|
void lastRowsChanged(int rowCount);
|
|
|
|
private:
|
|
|
|
int breakLine(const QString& line, QStringList& fragments);
|
|
|
|
private:
|
|
|
|
ConsoleLineList mLines;
|
|
|
|
int mRows;
|
|
|
|
bool mLayouting;
|
|
|
|
bool mNeedRelayout;
|
|
|
|
int mOldTabSize;
|
|
|
|
QConsole* mConsole;
|
|
|
|
int mMaxLines;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class QConsole : public QAbstractScrollArea
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
explicit QConsole(QWidget* parent = nullptr);
|
|
|
|
int historySize() const;
|
|
|
|
void setHistorySize(int historySize);
|
|
|
|
|
|
|
|
int tabSize() const;
|
|
|
|
|
|
|
|
int columnsPerRow() const;
|
|
|
|
|
|
|
|
int rowsInWindow() const;
|
|
|
|
int charColumns(QChar ch, int columnsBefore) const;
|
|
|
|
|
|
|
|
void invalidate();
|
|
|
|
void invalidateRows(int startRow,int endRow);
|
|
|
|
void invalidateRect(const QRect& rect);
|
|
|
|
|
|
|
|
void addLine(const QString& line);
|
2021-07-26 11:47:54 +08:00
|
|
|
void addText(const QString& text);
|
2021-07-01 20:24:47 +08:00
|
|
|
void removeLastLine();
|
|
|
|
void changeLastLine(const QString& line);
|
|
|
|
QString getLastLine();
|
2021-07-23 13:22:05 +08:00
|
|
|
void clear();
|
2021-10-02 17:01:08 +08:00
|
|
|
void copy();
|
|
|
|
void paste();
|
|
|
|
void selectAll();
|
|
|
|
QString selText();
|
2021-07-01 20:24:47 +08:00
|
|
|
|
|
|
|
signals:
|
|
|
|
void commandInput(const QString& command);
|
|
|
|
private:
|
|
|
|
ConsoleLines mContents;
|
|
|
|
QStringList mCommandHistory;
|
|
|
|
int mHistorySize;
|
|
|
|
int mHistoryIndex;
|
|
|
|
QString mCommand;
|
|
|
|
QString mCurrentEditableLine;
|
|
|
|
// bool mIndex;
|
|
|
|
int mRowHeight;
|
|
|
|
int mTopRow; // 1-based
|
|
|
|
int mRowsInWindow;
|
|
|
|
int mColumnsPerRow;
|
|
|
|
int mColumnWidth;
|
|
|
|
bool mReadonly;
|
|
|
|
LineChar mSelectionBegin;
|
|
|
|
LineChar mSelectionEnd;
|
|
|
|
int mCaretChar;
|
|
|
|
QColor mBackground;
|
|
|
|
QColor mForeground;
|
|
|
|
QColor mSelectionBackground;
|
|
|
|
QColor mSelectionForeground;
|
|
|
|
QColor mInactiveSelectionBackground;
|
|
|
|
QColor mInactiveSelectionForeground;
|
|
|
|
int mTabSize;
|
|
|
|
std::shared_ptr<QImage> mContentImage;
|
|
|
|
int mBlinkTimerId;
|
|
|
|
int mBlinkStatus;
|
|
|
|
QTimer* mScrollTimer;
|
|
|
|
int mScrollDeltaY;
|
|
|
|
private:
|
|
|
|
void fontChanged();
|
|
|
|
void recalcCharExtent();
|
|
|
|
void sizeOrFontChanged(bool bFont);
|
|
|
|
int clientWidth();
|
|
|
|
int clientHeight();
|
|
|
|
/**
|
|
|
|
* @brief setTopRow
|
|
|
|
* @param value 1-based
|
|
|
|
*/
|
|
|
|
void setTopRow(int value);
|
|
|
|
int maxScrollHeight();
|
|
|
|
void updateScrollbars();
|
|
|
|
void paintRows(QPainter& painter, int row1,int row2);
|
|
|
|
void ensureCaretVisible();
|
|
|
|
void showCaret();
|
|
|
|
void hideCaret();
|
|
|
|
void updateCaret();
|
|
|
|
LineChar caretPos();
|
|
|
|
RowColumn caretRowColumn();
|
|
|
|
QPoint rowColumnToPixels(const RowColumn& rowColumn);
|
|
|
|
QRect getCaretRect();
|
|
|
|
void paintCaret(QPainter &painter, const QRect rcClip);
|
|
|
|
void textInputed(const QString& text);
|
|
|
|
void loadCommandFromHistory();
|
|
|
|
LineChar selectionBegin();
|
|
|
|
LineChar selectionEnd();
|
|
|
|
void setCaretChar(int newCaretChar, bool resetSelection);
|
|
|
|
bool caretInSelection();
|
|
|
|
QString removeSelection();
|
|
|
|
bool hasSelection();
|
2024-03-13 20:10:31 +08:00
|
|
|
int computeScrollY(int y);
|
2021-07-01 20:24:47 +08:00
|
|
|
RowColumn pixelsToNearestRowColumn(int x,int y);
|
2021-10-02 17:01:08 +08:00
|
|
|
QString lineBreak();
|
2021-07-01 20:24:47 +08:00
|
|
|
|
|
|
|
|
|
|
|
private slots:
|
|
|
|
void doScrolled();
|
|
|
|
void contentsLayouted();
|
|
|
|
void contentsRowsAdded(int rowCount);
|
|
|
|
void contentsLastRowsRemoved(int rowCount);
|
|
|
|
void contentsLastRowsChanged(int rowCount);
|
|
|
|
void scrollTimerHandler();
|
|
|
|
|
|
|
|
// QWidget interface
|
|
|
|
protected:
|
|
|
|
void mousePressEvent(QMouseEvent *event) override;
|
|
|
|
void mouseReleaseEvent(QMouseEvent *event) override;
|
|
|
|
void mouseMoveEvent(QMouseEvent *event) override;
|
|
|
|
void keyPressEvent(QKeyEvent *event) override;
|
|
|
|
void focusInEvent(QFocusEvent *event) override;
|
|
|
|
void focusOutEvent(QFocusEvent *event) override;
|
|
|
|
void paintEvent(QPaintEvent *event) override;
|
|
|
|
bool event(QEvent *event) override;
|
|
|
|
|
|
|
|
|
|
|
|
// QWidget interface
|
|
|
|
protected:
|
|
|
|
void resizeEvent(QResizeEvent *event) override;
|
|
|
|
|
|
|
|
// QObject interface
|
|
|
|
protected:
|
|
|
|
void timerEvent(QTimerEvent *event) override;
|
|
|
|
|
|
|
|
// QWidget interface
|
|
|
|
protected:
|
|
|
|
void inputMethodEvent(QInputMethodEvent *event) override;
|
|
|
|
void wheelEvent(QWheelEvent *event) override;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#endif // QCONSOLE_H
|