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 SYNEDITKEYSTROKE_H |
18 | #define SYNEDITKEYSTROKE_H |
19 | |
20 | #include <QKeySequence> |
21 | #include <QList> |
22 | #include <memory> |
23 | #include "MiscClasses.h" |
24 | #include "qt_utils/utils.h" |
25 | |
26 | namespace QSynedit { |
27 | //**************************************************************************** |
28 | // NOTE! If you add an editor command, you must also update the |
29 | // EditorCommandStrs constant array in implementation section below, or the |
30 | // command will not show up in the IDE. |
31 | //**************************************************************************** |
32 | |
33 | // "Editor Commands". Key strokes are translated from a table into these |
34 | // I used constants instead of a set so that additional commands could be |
35 | // added in descendants (you can't extend a set) |
36 | |
37 | // There are two ranges of editor commands: the ecViewXXX commands are always |
38 | // valid, while the ecEditXXX commands are ignored when the editor is in |
39 | // read-only mode |
40 | |
41 | enum class EditCommand { |
42 | ecNone = 0, // Nothing. Useful for user event to handle command |
43 | ecViewCommandFirst = 0, |
44 | ecViewCommandLast = 500, |
45 | ecEditCommandFirst = 501, |
46 | ecEditCommandLast = 1000, |
47 | |
48 | ecLeft = 1, // Move cursor left one char |
49 | ecRight = 2, // Move cursor right one char |
50 | ecUp = 3, // Move cursor up one line |
51 | ecDown = 4, // Move cursor down one line |
52 | ecWordLeft = 5, // Move cursor left one word |
53 | ecWordRight = 6, // Move cursor right one word |
54 | ecLineStart = 7, // Move cursor to beginning of line |
55 | ecLineEnd = 8, // Move cursor to end of line |
56 | ecPageUp = 9, // Move cursor up one page |
57 | ecPageDown = 10, // Move cursor down one page |
58 | ecPageLeft = 11, // Move cursor right one page |
59 | ecPageRight = 12, // Move cursor left one page |
60 | ecPageTop = 13, // Move cursor to top of page |
61 | ecPageBottom = 14, // Move cursor to bottom of page |
62 | ecEditorStart = 15, // Move cursor to absolute beginning |
63 | ecEditorEnd = 16, // Move cursor to absolute end |
64 | ecGotoXY = 17, // Move cursor to specific coordinates, Data = PPoint |
65 | |
66 | //****************************************************************************** |
67 | // Maybe the command processor should just take a boolean that signifies if |
68 | // selection is affected or not? |
69 | //****************************************************************************** |
70 | |
71 | ecSelection = 100, // Add this to ecXXX command to get equivalent |
72 | // command, but with selection enabled. This is not |
73 | // a command itself. |
74 | // Same as commands above, except they affect selection, too |
75 | ecSelLeft = ecLeft + ecSelection, |
76 | ecSelRight = ecRight + ecSelection, |
77 | ecSelUp = ecUp + ecSelection, |
78 | ecSelDown = ecDown + ecSelection, |
79 | ecSelWordLeft = ecWordLeft + ecSelection, |
80 | ecSelWordRight = ecWordRight + ecSelection, |
81 | ecSelLineStart = ecLineStart + ecSelection, |
82 | ecSelLineEnd = ecLineEnd + ecSelection, |
83 | ecSelPageUp = ecPageUp + ecSelection, |
84 | ecSelPageDown = ecPageDown + ecSelection, |
85 | ecSelPageLeft = ecPageLeft + ecSelection, |
86 | ecSelPageRight = ecPageRight + ecSelection, |
87 | ecSelPageTop = ecPageTop + ecSelection, |
88 | ecSelPageBottom = ecPageBottom + ecSelection, |
89 | ecSelEditorStart = ecEditorStart + ecSelection, |
90 | ecSelEditorEnd = ecEditorEnd + ecSelection, |
91 | ecSelGotoXY = ecGotoXY + ecSelection, // Data = PPoint |
92 | |
93 | |
94 | ecCopy = 201, // Copy selection to clipboard |
95 | ecSelWord = 202, |
96 | ecSelectAll = 203, // Select entire contents of editor, cursor to end |
97 | ecExpandSelection = 204, // expand selection |
98 | ecShrinkSelection = 205, // shrink selection |
99 | |
100 | ecScrollUp = 211, // Scroll up one line leaving cursor position unchanged. |
101 | ecScrollDown = 212, // Scroll down one line leaving cursor position unchanged. |
102 | ecScrollLeft = 213, // Scroll left one char leaving cursor position unchanged. |
103 | ecScrollRight = 214, // Scroll right one char leaving cursor position unchanged. |
104 | |
105 | ecInsertMode = 221, // Set insert mode |
106 | ecOverwriteMode = 222, // Set overwrite mode |
107 | ecToggleMode = 223, // Toggle ins/ovr mode |
108 | |
109 | ecNormalSelect = 231, // Normal selection mode |
110 | ecColumnSelect = 232, // Column selection mode |
111 | ecLineSelect = 233, // Line selection mode |
112 | |
113 | ecMatchBracket = 250, // Go to matching bracket |
114 | |
115 | ecContextHelp = 490, // Help on Word, Data = Word |
116 | |
117 | ecDeleteLastChar = 501, // Delete last char (i.e. backspace key) |
118 | ecDeleteChar = 502, // Delete char at cursor (i.e. delete key) |
119 | ecDeleteWordEnd = 503, // Delete from cursor to end of word |
120 | ecDeleteWordStart = 504, // Delete from cursor to start of word |
121 | ecDeleteBOL = 505, // Delete from cursor to beginning of line |
122 | ecDeleteEOL = 506, // Delete from cursor to end of line |
123 | ecDeleteLine = 507, // Delete current line |
124 | ecClearAll = 508, // Delete everything |
125 | ecLineBreak = 509, // Break line at current position, move caret to new line |
126 | ecInsertLine = 510, // Break line at current position, leave caret |
127 | ecChar = 511, // Insert a character at current position |
128 | ecDuplicateLine = 512, // Duplicate current line |
129 | ecMoveSelUp = 513, // Move selection up |
130 | ecMoveSelDown = 514, // Move selection down |
131 | ecImeStr = 550, // Insert character(s) from IME |
132 | ecDeleteWord = 551, // Delete current Word |
133 | |
134 | ecUndo = 601, // Perform undo if available |
135 | ecRedo = 602, // Perform redo if available |
136 | ecCut = 603, // Cut selection to clipboard |
137 | ecPaste = 604, // Paste clipboard to current position |
138 | |
139 | ecBlockIndent = 610, // Indent selection |
140 | ecBlockUnindent = 611, // Unindent selection |
141 | ecTab = 612, // Tab key |
142 | ecShiftTab = 613, // Shift+Tab key |
143 | ecComment = 614, |
144 | ecUncomment = 615, |
145 | ecToggleComment = 616, |
146 | ecToggleBlockComment = 617, |
147 | |
148 | ecUpperCase = 620, // apply to the current or previous word |
149 | ecLowerCase = 621, |
150 | ecToggleCase = 622, |
151 | ecTitleCase = 623, |
152 | ecUpperCaseBlock = 625, // apply to current selection, or current char if no selection |
153 | ecLowerCaseBlock = 626, |
154 | ecToggleCaseBlock = 627, |
155 | |
156 | ecString = 630, //Insert a whole string |
157 | ecZoomOut = 631, //Increase Font Size |
158 | ecZoomIn = 632, //Decrease Font Size |
159 | |
160 | ecLineBreakAtBegin = 651, //add a line break at the begin of the line |
161 | ecLineBreakAtEnd = 652, |
162 | |
163 | //### Code Folding ### |
164 | ecCollapse = 700, |
165 | ecUncollapse = 701, |
166 | ecCollapseLevel = 702, |
167 | ecUncollapseLevel = 703, |
168 | ecCollapseAll = 704, |
169 | ecUncollapseAll = 705, |
170 | //### End Code Folding ### |
171 | |
172 | ecUserFirst = 1001, // Start of user-defined commands |
173 | |
174 | |
175 | |
176 | }; |
177 | |
178 | class KeyError: public BaseError { |
179 | public: |
180 | explicit KeyError(const QString& reason); |
181 | }; |
182 | |
183 | class EditKeyStroke |
184 | { |
185 | public: |
186 | explicit EditKeyStroke(); |
187 | QKeySequence keySequence() const; |
188 | void setKeySequence(QKeySequence& keySequence); |
189 | int key() const; |
190 | void setKey(int key); |
191 | |
192 | Qt::KeyboardModifiers keyModifiers() const; |
193 | void setKeyModifiers(const Qt::KeyboardModifiers &keyModifiers); |
194 | |
195 | int key2() const; |
196 | void setKey2(int key2); |
197 | |
198 | Qt::KeyboardModifiers keyModifiers2() const; |
199 | void setKeyModifiers2(const Qt::KeyboardModifiers &keyModifiers2); |
200 | |
201 | EditCommand command() const; |
202 | void setCommand(const EditCommand &command); |
203 | |
204 | private: |
205 | int mKey; // Virtual keycode, i.e. VK_xxx |
206 | Qt::KeyboardModifiers mKeyModifiers; |
207 | int mKey2; |
208 | Qt::KeyboardModifiers mKeyModifiers2; |
209 | EditCommand mCommand; |
210 | |
211 | }; |
212 | |
213 | using PEditKeyStroke = std::shared_ptr<EditKeyStroke>; |
214 | using EditKeyStrokeList = QList<PEditKeyStroke>; |
215 | |
216 | class EditKeyStrokes { |
217 | public: |
218 | PEditKeyStroke add(EditCommand command, int key, Qt::KeyboardModifiers modifiers); |
219 | PEditKeyStroke findCommand(EditCommand command); |
220 | PEditKeyStroke findKeycode(int key, Qt::KeyboardModifiers modifiers); |
221 | PEditKeyStroke findKeycode2(int key, Qt::KeyboardModifiers modifiers, |
222 | int key2, Qt::KeyboardModifiers modifiers2); |
223 | PEditKeyStroke findKeySequence(const QKeySequence& keySeq); |
224 | void clear(); |
225 | void resetDefaults(); |
226 | void (); |
227 | private: |
228 | EditKeyStrokeList mList; |
229 | }; |
230 | |
231 | } |
232 | |
233 | #endif // SYNEDITKEYSTROKE_H |
234 | |