-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcodeeditor.h
183 lines (139 loc) · 6.08 KB
/
codeeditor.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/*===========================================================================
CLIPSEditor, editor for CLIPS (C Language Integrated Production System)
Copyright (C) 2012-2017 Novikov Artem Gennadievich
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 <http://www.gnu.org/licenses/>
===========================================================================*/
#ifndef CODEEDITOR_H
#define CODEEDITOR_H
#include <QtWidgets>
#include "config.h"
#include "highlighter.h"
#define FOLDBOXRECT(cy) QRect(markWidth + lineNumWidth + foldBoxIndent, cy - foldBoxWidth / 2, foldBoxWidth, foldBoxWidth)
#define FULLRESIZE resizeEvent(new QResizeEvent(QSize(0, 0), size()))
#define FONTWIDTH fontMetrics().width(QLatin1Char('X'))
#define BLOCKMARK reinterpret_cast<CodeEditor::Bookmark*>(block.userData())
class Highlighter;
class CodeEditor : public QPlainTextEdit
{
Q_OBJECT
public:
// при добавлении флага, смотреть метод setBlockState(), поскольку
// previousBlockState и previousState перезаписывают статус, также как
// и contentsChange()
enum BlockState {
End = 1, // 00000001 конец блока
Begin = 2, // 00000010 начало блока
String = 4, // 00000100 признак незавершенной сторки (нет пары для ")
Comment = 8, // 00001000 строка является внешним комментарием
Nested = 16, // 00010000 признак вложенности
Folded = 32, // 00100000 блок свернут
Error = 64, // 01000000 строка содержит ошибку
Rehighlight = 128, // 10000000 блок необходимо переподсветить
//Bookmark = 256, // 100000000 закладка
Empty = -1 // 1111.... новый/пустой блок
};
// позиция последнего значащего бита, после которого идет значение вложенности,
// равно велечине последнего элемента BlockState << 1
const static int StateShift = 8;
enum SearchFlag { // QTextDocument::FindFlag
Backward = 1,
MatchCase = 2,
WholeWords = 4,
RegExp = 8
};
struct Bookmark : public QTextBlockUserData
{
Bookmark(CodeEditor* editor, QTextBlock block)
: editor(editor), block(block), num(block.blockNumber()) { setActive(); }
void setActive(bool active = true)
{
if (active)
emit editor->addBookmark(this);
else emit editor->removeBookmark(this);
isActive = active == true;
editor->extraArea->update();
}
void check()
{
qDebug() << num << block.blockNumber();// << currentBlock.blockNumber();
if (block.blockNumber() != num) {
if (isActive)
emit editor->moveBookmark(this, num);
num = block.blockNumber();
}
}
~Bookmark() { emit editor->removeBookmark(this); }
bool isActive;
int num;
QTextBlock block;
CodeEditor* editor;
};
public:
CodeEditor(Config*);
QString wordHelp();
bool search(QString, int);
bool replace(QString, QString, int);
void replaceAll(QString, QString, int);
signals:
void addBookmark(CodeEditor::Bookmark*);
void moveBookmark(CodeEditor::Bookmark*, int);
void removeBookmark(CodeEditor::Bookmark*);
private slots:
void foldAll() { foldUnfoldAll(); }
void unfoldAll() { foldUnfoldAll(false); }
void deleteSelected() { textCursor().removeSelectedText(); }
void toggleComment();
void toUpperCase() { convertCase(); }
void toLowerCase() { convertCase(false); }
void blockCountChanged(int count) { lineNumDigits = qMax(2, QString::number(count).length()); } // 2 - разряда
void contentsChange(int, int, int);
void performCompletion();
void insertCompletion(const QString&);
void ensureCursorVisible();
void reconfig(int = (Config::Init | Config::Editor));
private:
void resizeEvent(QResizeEvent*);
void paintEvent(QPaintEvent*);
void keyPressEvent(QKeyEvent*);
void mouseMoveEvent(QMouseEvent*);
void mousePressEvent(QMouseEvent*);
void contextMenuEvent(QContextMenuEvent*);
bool eventFilter(QObject*, QEvent*);
void extraAreaPaintEvent();
void extraAreaMouseEvent(QMouseEvent*);
int setBlockState(QTextBlock&);
QTextBlock findBlockByY(int);
void foldUnfold(QTextBlock&);
void foldUnfoldAll(bool = true);
void convertCase(bool toUpper = true)
{
textCursor().insertText(toUpper ? textCursor().selectedText().toUpper() :
textCursor().selectedText().toLower());
}
Highlighter* highlighter;
QCompleter* completer;
QTextBlock pointedBlock;
QWidget* extraArea;
int lineNumDigits;
int lineNumWidth;
int foldBoxWidth;
int foldBoxIndent;
int foldBoxLength;
int markWidth; // от размера шрифта
Config* config;
QMenu* menu;
QImage mark;
QList<QKeySequence> shortcuts;
};
// конвертация в QVariant
Q_DECLARE_METATYPE(CodeEditor::Bookmark*)
#endif // CODEEDITOR_H