1/*
2 * Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com)
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17#ifndef QCONSOLE_H
18#define QCONSOLE_H
19
20#include <QAbstractScrollArea>
21#include <QVector>
22#include <memory>
23
24struct ConsoleLine {
25 QString text;
26 QStringList fragments;
27 int maxColumns;
28};
29
30enum class ConsoleCaretType {
31 ctVerticalLine,ctHorizontalLine,ctBlock,ctHalfBlock
32};
33
34using PConsoleLine = std::shared_ptr<ConsoleLine>;
35
36using ConsoleLineList = QVector<PConsoleLine>;
37
38/**
39 * @brief The RowColumn struct
40 * column and row are 0-based
41 */
42struct RowColumn {
43 int column;
44 int row;
45};
46
47/**
48 * @brief The LineChar struct
49 * line and ch are 0-based
50 */
51struct LineChar {
52 int ch;
53 int line;
54};
55
56class QConsole;
57class ConsoleLines : public QObject{
58 Q_OBJECT
59public:
60 explicit ConsoleLines(QConsole* console);
61 void addLine(const QString& line);
62 void RemoveLastLine();
63 void changeLastLine(const QString& newLine);
64 QString getLastLine();
65 QString getLine(int line);
66 QChar getChar(int line,int ch);
67 QChar getChar(const LineChar& lineChar);
68 /**
69 * @brief getRows
70 * @param startRow 1-based
71 * @param endRow 1-based
72 * @return
73 */
74 QStringList getRows(int startRow, int endRow);
75
76 LineChar rowColumnToLineChar(const RowColumn& rowColumn);
77 LineChar rowColumnToLineChar(int row ,int column);
78 RowColumn lineCharToRowColumn(const LineChar& lineChar);
79 RowColumn lineCharToRowColumn(int line, int ch);
80 int rows() const;
81 int lines() const;
82 bool layouting() const;
83 int maxLines() const;
84 void setMaxLines(int maxLines);
85 void clear();
86
87 int getMaxLines() const;
88public slots:
89 void layout();
90signals:
91 void layoutStarted();
92 void layoutFinished();
93 void needRelayout();
94 void rowsAdded(int rowCount);
95 void lastRowsRemoved(int rowCount);
96 void lastRowsChanged(int rowCount);
97private:
98 int breakLine(const QString& line, QStringList& fragments);
99private:
100 ConsoleLineList mLines;
101 int mRows;
102 bool mLayouting;
103 bool mNeedRelayout;
104 int mOldTabSize;
105 QConsole* mConsole;
106 int mMaxLines;
107};
108
109
110class QConsole : public QAbstractScrollArea
111{
112 Q_OBJECT
113public:
114 explicit QConsole(QWidget* parent = nullptr);
115 int historySize() const;
116 void setHistorySize(int historySize);
117
118 int tabSize() const;
119
120 int columnsPerRow() const;
121
122 int rowsInWindow() const;
123 int charColumns(QChar ch, int columnsBefore) const;
124
125 void invalidate();
126 void invalidateRows(int startRow,int endRow);
127 void invalidateRect(const QRect& rect);
128
129 void addLine(const QString& line);
130 void addText(const QString& text);
131 void removeLastLine();
132 void changeLastLine(const QString& line);
133 QString getLastLine();
134 void clear();
135 void copy();
136 void paste();
137 void selectAll();
138 QString selText();
139
140signals:
141 void commandInput(const QString& command);
142private:
143 ConsoleLines mContents;
144 QStringList mCommandHistory;
145 int mHistorySize;
146 int mHistoryIndex;
147 QString mCommand;
148 QString mCurrentEditableLine;
149// bool mIndex;
150 int mRowHeight;
151 int mTopRow; // 1-based
152 int mRowsInWindow;
153 int mColumnsPerRow;
154 int mColumnWidth;
155 bool mReadonly;
156 LineChar mSelectionBegin;
157 LineChar mSelectionEnd;
158 int mCaretChar;
159 QColor mBackground;
160 QColor mForeground;
161 QColor mSelectionBackground;
162 QColor mSelectionForeground;
163 QColor mInactiveSelectionBackground;
164 QColor mInactiveSelectionForeground;
165 int mTabSize;
166 std::shared_ptr<QImage> mContentImage;
167 int mBlinkTimerId;
168 int mBlinkStatus;
169 QTimer* mScrollTimer;
170 int mScrollDeltaY;
171private:
172 void fontChanged();
173 void recalcCharExtent();
174 void sizeOrFontChanged(bool bFont);
175 int clientWidth();
176 int clientHeight();
177 /**
178 * @brief setTopRow
179 * @param value 1-based
180 */
181 void setTopRow(int value);
182 int maxScrollHeight();
183 void updateScrollbars();
184 void paintRows(QPainter& painter, int row1,int row2);
185 void ensureCaretVisible();
186 void showCaret();
187 void hideCaret();
188 void updateCaret();
189 LineChar caretPos();
190 RowColumn caretRowColumn();
191 QPoint rowColumnToPixels(const RowColumn& rowColumn);
192 QRect getCaretRect();
193 void paintCaret(QPainter &painter, const QRect rcClip);
194 void textInputed(const QString& text);
195 void loadCommandFromHistory();
196 LineChar selectionBegin();
197 LineChar selectionEnd();
198 void setCaretChar(int newCaretChar, bool resetSelection);
199 bool caretInSelection();
200 QString removeSelection();
201 bool hasSelection();
202 int computeScrollY(int Y);
203 RowColumn pixelsToNearestRowColumn(int x,int y);
204 QString lineBreak();
205
206
207private slots:
208 void doScrolled();
209 void contentsLayouted();
210 void contentsRowsAdded(int rowCount);
211 void contentsLastRowsRemoved(int rowCount);
212 void contentsLastRowsChanged(int rowCount);
213 void scrollTimerHandler();
214
215 // QWidget interface
216protected:
217 void mousePressEvent(QMouseEvent *event) override;
218 void mouseReleaseEvent(QMouseEvent *event) override;
219 void mouseMoveEvent(QMouseEvent *event) override;
220 void keyPressEvent(QKeyEvent *event) override;
221 void focusInEvent(QFocusEvent *event) override;
222 void focusOutEvent(QFocusEvent *event) override;
223 void paintEvent(QPaintEvent *event) override;
224 bool event(QEvent *event) override;
225
226
227 // QWidget interface
228protected:
229 void resizeEvent(QResizeEvent *event) override;
230
231 // QObject interface
232protected:
233 void timerEvent(QTimerEvent *event) override;
234
235 // QWidget interface
236protected:
237 void inputMethodEvent(QInputMethodEvent *event) override;
238 void wheelEvent(QWheelEvent *event) override;
239};
240
241
242#endif // QCONSOLE_H
243