KTextEditor

keyparser.cpp
1/*
2 SPDX-FileCopyrightText: 2008 Erlend Hamberg <ehamberg@gmail.com>
3 SPDX-FileCopyrightText: 2008 Evgeniy Ivanov <powerfox@kde.ru>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "definitions.h"
9#include <QKeyEvent>
10#include <QStringList>
11#include <vimode/keyevent.h>
12#include <vimode/keyparser.h>
13
14using namespace KateVi;
15
16KeyParser *KeyParser::m_instance = nullptr;
17
18KeyParser::KeyParser()
19{
20 initKeyTables();
21}
22
23KeyParser *KeyParser::self()
24{
25 if (m_instance == nullptr) {
26 m_instance = new KeyParser();
27 }
28
29 return m_instance;
30}
31
32void KeyParser::initKeyTables()
33{
34 m_qt2katevi = {
35 {Qt::Key_Escape, QStringLiteral("esc")},
36 {Qt::Key_Tab, QStringLiteral("tab")},
37 {Qt::Key_Backtab, QStringLiteral("backtab")},
38 {Qt::Key_Backspace, QStringLiteral("backspace")},
39 {Qt::Key_Return, QStringLiteral("return")},
40 {Qt::Key_Enter, QStringLiteral("enter")},
41 {Qt::Key_Insert, QStringLiteral("insert")},
42 {Qt::Key_Delete, QStringLiteral("delete")},
43 {Qt::Key_Pause, QStringLiteral("pause")},
44 {Qt::Key_Print, QStringLiteral("print")},
45 {Qt::Key_SysReq, QStringLiteral("sysreq")},
46 {Qt::Key_Clear, QStringLiteral("clear")},
47 {Qt::Key_Home, QStringLiteral("home")},
48 {Qt::Key_End, QStringLiteral("end")},
49 {Qt::Key_Left, QStringLiteral("left")},
50 {Qt::Key_Up, QStringLiteral("up")},
51 {Qt::Key_Right, QStringLiteral("right")},
52 {Qt::Key_Down, QStringLiteral("down")},
53 {Qt::Key_PageUp, QStringLiteral("pageup")},
54 {Qt::Key_PageDown, QStringLiteral("pagedown")},
55 {Qt::Key_Shift, QStringLiteral("shift")},
56 {Qt::Key_Control, QStringLiteral("control")},
57 {Qt::Key_Meta, QStringLiteral("meta")},
58 {Qt::Key_Alt, QStringLiteral("alt")},
59 {Qt::Key_AltGr, QStringLiteral("altgr")},
60 {Qt::Key_CapsLock, QStringLiteral("capslock")},
61 {Qt::Key_NumLock, QStringLiteral("numlock")},
62 {Qt::Key_ScrollLock, QStringLiteral("scrolllock")},
63 {Qt::Key_F1, QStringLiteral("f1")},
64 {Qt::Key_F2, QStringLiteral("f2")},
65 {Qt::Key_F3, QStringLiteral("f3")},
66 {Qt::Key_F4, QStringLiteral("f4")},
67 {Qt::Key_F5, QStringLiteral("f5")},
68 {Qt::Key_F6, QStringLiteral("f6")},
69 {Qt::Key_F7, QStringLiteral("f7")},
70 {Qt::Key_F8, QStringLiteral("f8")},
71 {Qt::Key_F9, QStringLiteral("f9")},
72 {Qt::Key_F10, QStringLiteral("f10")},
73 {Qt::Key_F11, QStringLiteral("f11")},
74 {Qt::Key_F12, QStringLiteral("f12")},
75 {Qt::Key_F13, QStringLiteral("f13")},
76 {Qt::Key_F14, QStringLiteral("f14")},
77 {Qt::Key_F15, QStringLiteral("f15")},
78 {Qt::Key_F16, QStringLiteral("f16")},
79 {Qt::Key_F17, QStringLiteral("f17")},
80 {Qt::Key_F18, QStringLiteral("f18")},
81 {Qt::Key_F19, QStringLiteral("f19")},
82 {Qt::Key_F20, QStringLiteral("f20")},
83 {Qt::Key_F21, QStringLiteral("f21")},
84 {Qt::Key_F22, QStringLiteral("f22")},
85 {Qt::Key_F23, QStringLiteral("f23")},
86 {Qt::Key_F24, QStringLiteral("f24")},
87 {Qt::Key_F25, QStringLiteral("f25")},
88 {Qt::Key_F26, QStringLiteral("f26")},
89 {Qt::Key_F27, QStringLiteral("f27")},
90 {Qt::Key_F28, QStringLiteral("f28")},
91 {Qt::Key_F29, QStringLiteral("f29")},
92 {Qt::Key_F30, QStringLiteral("f30")},
93 {Qt::Key_F31, QStringLiteral("f31")},
94 {Qt::Key_F32, QStringLiteral("f32")},
95 {Qt::Key_F33, QStringLiteral("f33")},
96 {Qt::Key_F34, QStringLiteral("f34")},
97 {Qt::Key_F35, QStringLiteral("f35")},
98 {Qt::Key_Super_L, QStringLiteral("super_l")},
99 {Qt::Key_Super_R, QStringLiteral("super_r")},
100 {Qt::Key_Menu, QStringLiteral("menu")},
101 {Qt::Key_Hyper_L, QStringLiteral("hyper_l")},
102 {Qt::Key_Hyper_R, QStringLiteral("hyper_r")},
103 {Qt::Key_Help, QStringLiteral("help")},
104 {Qt::Key_Direction_L, QStringLiteral("direction_l")},
105 {Qt::Key_Direction_R, QStringLiteral("direction_r")},
106 {Qt::Key_Multi_key, QStringLiteral("multi_key")},
107 {Qt::Key_Codeinput, QStringLiteral("codeinput")},
108 {Qt::Key_SingleCandidate, QStringLiteral("singlecandidate")},
109 {Qt::Key_MultipleCandidate, QStringLiteral("multiplecandidate")},
110 {Qt::Key_PreviousCandidate, QStringLiteral("previouscandidate")},
111 {Qt::Key_Mode_switch, QStringLiteral("mode_switch")},
112 {Qt::Key_Kanji, QStringLiteral("kanji")},
113 {Qt::Key_Muhenkan, QStringLiteral("muhenkan")},
114 {Qt::Key_Henkan, QStringLiteral("henkan")},
115 {Qt::Key_Romaji, QStringLiteral("romaji")},
116 {Qt::Key_Hiragana, QStringLiteral("hiragana")},
117 {Qt::Key_Katakana, QStringLiteral("katakana")},
118 {Qt::Key_Hiragana_Katakana, QStringLiteral("hiragana_katakana")},
119 {Qt::Key_Zenkaku, QStringLiteral("zenkaku")},
120 {Qt::Key_Hankaku, QStringLiteral("hankaku")},
121 {Qt::Key_Zenkaku_Hankaku, QStringLiteral("zenkaku_hankaku")},
122 {Qt::Key_Touroku, QStringLiteral("touroku")},
123 {Qt::Key_Massyo, QStringLiteral("massyo")},
124 {Qt::Key_Kana_Lock, QStringLiteral("kana_lock")},
125 {Qt::Key_Kana_Shift, QStringLiteral("kana_shift")},
126 {Qt::Key_Eisu_Shift, QStringLiteral("eisu_shift")},
127 {Qt::Key_Eisu_toggle, QStringLiteral("eisu_toggle")},
128 {Qt::Key_Hangul, QStringLiteral("hangul")},
129 {Qt::Key_Hangul_Start, QStringLiteral("hangul_start")},
130 {Qt::Key_Hangul_End, QStringLiteral("hangul_end")},
131 {Qt::Key_Hangul_Hanja, QStringLiteral("hangul_hanja")},
132 {Qt::Key_Hangul_Jamo, QStringLiteral("hangul_jamo")},
133 {Qt::Key_Hangul_Romaja, QStringLiteral("hangul_romaja")},
134 {Qt::Key_Hangul_Jeonja, QStringLiteral("hangul_jeonja")},
135 {Qt::Key_Hangul_Banja, QStringLiteral("hangul_banja")},
136 {Qt::Key_Hangul_PreHanja, QStringLiteral("hangul_prehanja")},
137 {Qt::Key_Hangul_PostHanja, QStringLiteral("hangul_posthanja")},
138 {Qt::Key_Hangul_Special, QStringLiteral("hangul_special")},
139 {Qt::Key_Dead_Grave, QStringLiteral("dead_grave")},
140 {Qt::Key_Dead_Acute, QStringLiteral("dead_acute")},
141 {Qt::Key_Dead_Circumflex, QStringLiteral("dead_circumflex")},
142 {Qt::Key_Dead_Tilde, QStringLiteral("dead_tilde")},
143 {Qt::Key_Dead_Macron, QStringLiteral("dead_macron")},
144 {Qt::Key_Dead_Breve, QStringLiteral("dead_breve")},
145 {Qt::Key_Dead_Abovedot, QStringLiteral("dead_abovedot")},
146 {Qt::Key_Dead_Diaeresis, QStringLiteral("dead_diaeresis")},
147 {Qt::Key_Dead_Abovering, QStringLiteral("dead_abovering")},
148 {Qt::Key_Dead_Doubleacute, QStringLiteral("dead_doubleacute")},
149 {Qt::Key_Dead_Caron, QStringLiteral("dead_caron")},
150 {Qt::Key_Dead_Cedilla, QStringLiteral("dead_cedilla")},
151 {Qt::Key_Dead_Ogonek, QStringLiteral("dead_ogonek")},
152 {Qt::Key_Dead_Iota, QStringLiteral("dead_iota")},
153 {Qt::Key_Dead_Voiced_Sound, QStringLiteral("dead_voiced_sound")},
154 {Qt::Key_Dead_Semivoiced_Sound, QStringLiteral("dead_semivoiced_sound")},
155 {Qt::Key_Dead_Belowdot, QStringLiteral("dead_belowdot")},
156 {Qt::Key_Dead_Hook, QStringLiteral("dead_hook")},
157 {Qt::Key_Dead_Horn, QStringLiteral("dead_horn")},
158 {Qt::Key_Back, QStringLiteral("back")},
159 {Qt::Key_Forward, QStringLiteral("forward")},
160 {Qt::Key_Stop, QStringLiteral("stop")},
161 {Qt::Key_Refresh, QStringLiteral("refresh")},
162 {Qt::Key_VolumeDown, QStringLiteral("volumedown")},
163 {Qt::Key_VolumeMute, QStringLiteral("volumemute")},
164 {Qt::Key_VolumeUp, QStringLiteral("volumeup")},
165 {Qt::Key_BassBoost, QStringLiteral("bassboost")},
166 {Qt::Key_BassUp, QStringLiteral("bassup")},
167 {Qt::Key_BassDown, QStringLiteral("bassdown")},
168 {Qt::Key_TrebleUp, QStringLiteral("trebleup")},
169 {Qt::Key_TrebleDown, QStringLiteral("trebledown")},
170 {Qt::Key_MediaPlay, QStringLiteral("mediaplay")},
171 {Qt::Key_MediaStop, QStringLiteral("mediastop")},
172 {Qt::Key_MediaPrevious, QStringLiteral("mediaprevious")},
173 {Qt::Key_MediaNext, QStringLiteral("medianext")},
174 {Qt::Key_MediaRecord, QStringLiteral("mediarecord")},
175 {Qt::Key_HomePage, QStringLiteral("homepage")},
176 {Qt::Key_Favorites, QStringLiteral("favorites")},
177 {Qt::Key_Search, QStringLiteral("search")},
178 {Qt::Key_Standby, QStringLiteral("standby")},
179 {Qt::Key_OpenUrl, QStringLiteral("openurl")},
180 {Qt::Key_LaunchMail, QStringLiteral("launchmail")},
181 {Qt::Key_LaunchMedia, QStringLiteral("launchmedia")},
182 {Qt::Key_Launch0, QStringLiteral("launch0")},
183 {Qt::Key_Launch1, QStringLiteral("launch1")},
184 {Qt::Key_Launch2, QStringLiteral("launch2")},
185 {Qt::Key_Launch3, QStringLiteral("launch3")},
186 {Qt::Key_Launch4, QStringLiteral("launch4")},
187 {Qt::Key_Launch5, QStringLiteral("launch5")},
188 {Qt::Key_Launch6, QStringLiteral("launch6")},
189 {Qt::Key_Launch7, QStringLiteral("launch7")},
190 {Qt::Key_Launch8, QStringLiteral("launch8")},
191 {Qt::Key_Launch9, QStringLiteral("launch9")},
192 {Qt::Key_LaunchA, QStringLiteral("launcha")},
193 {Qt::Key_LaunchB, QStringLiteral("launchb")},
194 {Qt::Key_LaunchC, QStringLiteral("launchc")},
195 {Qt::Key_LaunchD, QStringLiteral("launchd")},
196 {Qt::Key_LaunchE, QStringLiteral("launche")},
197 {Qt::Key_LaunchF, QStringLiteral("launchf")},
198 {Qt::Key_MediaLast, QStringLiteral("medialast")},
199 {Qt::Key_unknown, QStringLiteral("unknown")},
200 {Qt::Key_Call, QStringLiteral("call")},
201 {Qt::Key_Context1, QStringLiteral("context1")},
202 {Qt::Key_Context2, QStringLiteral("context2")},
203 {Qt::Key_Context3, QStringLiteral("context3")},
204 {Qt::Key_Context4, QStringLiteral("context4")},
205 {Qt::Key_Flip, QStringLiteral("flip")},
206 {Qt::Key_Hangup, QStringLiteral("hangup")},
207 {Qt::Key_No, QStringLiteral("no")},
208 {Qt::Key_Select, QStringLiteral("select")},
209 {Qt::Key_Yes, QStringLiteral("yes")},
210 {Qt::Key_Execute, QStringLiteral("execute")},
211 {Qt::Key_Printer, QStringLiteral("printer")},
212 {Qt::Key_Play, QStringLiteral("play")},
213 {Qt::Key_Sleep, QStringLiteral("sleep")},
214 {Qt::Key_Zoom, QStringLiteral("zoom")},
215 {Qt::Key_Cancel, QStringLiteral("cancel")},
216 };
217
218 for (QHash<int, QString>::const_iterator i = m_qt2katevi.constBegin(); i != m_qt2katevi.constEnd(); ++i) {
219 m_katevi2qt.insert(i.value(), i.key());
220 }
221 m_katevi2qt.insert(QStringLiteral("cr"), Qt::Key_Enter);
222
223 m_nameToKeyCode = {
224 {QStringLiteral("invalid"), -1},
225 {QStringLiteral("esc"), 1},
226 {QStringLiteral("tab"), 2},
227 {QStringLiteral("backtab"), 3},
228 {QStringLiteral("backspace"), 4},
229 {QStringLiteral("return"), 5},
230 {QStringLiteral("enter"), 6},
231 {QStringLiteral("insert"), 7},
232 {QStringLiteral("delete"), 8},
233 {QStringLiteral("pause"), 9},
234 {QStringLiteral("print"), 10},
235 {QStringLiteral("sysreq"), 11},
236 {QStringLiteral("clear"), 12},
237 {QStringLiteral("home"), 13},
238 {QStringLiteral("end"), 14},
239 {QStringLiteral("left"), 15},
240 {QStringLiteral("up"), 16},
241 {QStringLiteral("right"), 17},
242 {QStringLiteral("down"), 18},
243 {QStringLiteral("pageup"), 19},
244 {QStringLiteral("pagedown"), 20},
245 {QStringLiteral("shift"), 21},
246 {QStringLiteral("control"), 22},
247 {QStringLiteral("meta"), 23},
248 {QStringLiteral("alt"), 24},
249 {QStringLiteral("altgr"), 25},
250 {QStringLiteral("capslock"), 26},
251 {QStringLiteral("numlock"), 27},
252 {QStringLiteral("scrolllock"), 28},
253 {QStringLiteral("f1"), 29},
254 {QStringLiteral("f2"), 30},
255 {QStringLiteral("f3"), 31},
256 {QStringLiteral("f4"), 32},
257 {QStringLiteral("f5"), 33},
258 {QStringLiteral("f6"), 34},
259 {QStringLiteral("f7"), 35},
260 {QStringLiteral("f8"), 36},
261 {QStringLiteral("f9"), 37},
262 {QStringLiteral("f10"), 38},
263 {QStringLiteral("f11"), 39},
264 {QStringLiteral("f12"), 40},
265 {QStringLiteral("f13"), 41},
266 {QStringLiteral("f14"), 42},
267 {QStringLiteral("f15"), 43},
268 {QStringLiteral("f16"), 44},
269 {QStringLiteral("f17"), 45},
270 {QStringLiteral("f18"), 46},
271 {QStringLiteral("f19"), 47},
272 {QStringLiteral("f20"), 48},
273 {QStringLiteral("f21"), 49},
274 {QStringLiteral("f22"), 50},
275 {QStringLiteral("f23"), 51},
276 {QStringLiteral("f24"), 52},
277 {QStringLiteral("f25"), 53},
278 {QStringLiteral("f26"), 54},
279 {QStringLiteral("f27"), 55},
280 {QStringLiteral("f28"), 56},
281 {QStringLiteral("f29"), 57},
282 {QStringLiteral("f30"), 58},
283 {QStringLiteral("f31"), 59},
284 {QStringLiteral("f32"), 60},
285 {QStringLiteral("f33"), 61},
286 {QStringLiteral("f34"), 62},
287 {QStringLiteral("f35"), 63},
288 {QStringLiteral("super_l"), 64},
289 {QStringLiteral("super_r"), 65},
290 {QStringLiteral("menu"), 66},
291 {QStringLiteral("hyper_l"), 67},
292 {QStringLiteral("hyper_r"), 68},
293 {QStringLiteral("help"), 69},
294 {QStringLiteral("direction_l"), 70},
295 {QStringLiteral("direction_r"), 71},
296 {QStringLiteral("multi_key"), 172},
297 {QStringLiteral("codeinput"), 173},
298 {QStringLiteral("singlecandidate"), 174},
299 {QStringLiteral("multiplecandidate"), 175},
300 {QStringLiteral("previouscandidate"), 176},
301 {QStringLiteral("mode_switch"), 177},
302 {QStringLiteral("kanji"), 178},
303 {QStringLiteral("muhenkan"), 179},
304 {QStringLiteral("henkan"), 180},
305 {QStringLiteral("romaji"), 181},
306 {QStringLiteral("hiragana"), 182},
307 {QStringLiteral("katakana"), 183},
308 {QStringLiteral("hiragana_katakana"), 184},
309 {QStringLiteral("zenkaku"), 185},
310 {QStringLiteral("hankaku"), 186},
311 {QStringLiteral("zenkaku_hankaku"), 187},
312 {QStringLiteral("touroku"), 188},
313 {QStringLiteral("massyo"), 189},
314 {QStringLiteral("kana_lock"), 190},
315 {QStringLiteral("kana_shift"), 191},
316 {QStringLiteral("eisu_shift"), 192},
317 {QStringLiteral("eisu_toggle"), 193},
318 {QStringLiteral("hangul"), 194},
319 {QStringLiteral("hangul_start"), 195},
320 {QStringLiteral("hangul_end"), 196},
321 {QStringLiteral("hangul_hanja"), 197},
322 {QStringLiteral("hangul_jamo"), 198},
323 {QStringLiteral("hangul_romaja"), 199},
324 {QStringLiteral("hangul_jeonja"), 200},
325 {QStringLiteral("hangul_banja"), 201},
326 {QStringLiteral("hangul_prehanja"), 202},
327 {QStringLiteral("hangul_posthanja"), 203},
328 {QStringLiteral("hangul_special"), 204},
329 {QStringLiteral("dead_grave"), 205},
330 {QStringLiteral("dead_acute"), 206},
331 {QStringLiteral("dead_circumflex"), 207},
332 {QStringLiteral("dead_tilde"), 208},
333 {QStringLiteral("dead_macron"), 209},
334 {QStringLiteral("dead_breve"), 210},
335 {QStringLiteral("dead_abovedot"), 211},
336 {QStringLiteral("dead_diaeresis"), 212},
337 {QStringLiteral("dead_abovering"), 213},
338 {QStringLiteral("dead_doubleacute"), 214},
339 {QStringLiteral("dead_caron"), 215},
340 {QStringLiteral("dead_cedilla"), 216},
341 {QStringLiteral("dead_ogonek"), 217},
342 {QStringLiteral("dead_iota"), 218},
343 {QStringLiteral("dead_voiced_sound"), 219},
344 {QStringLiteral("dead_semivoiced_sound"), 220},
345 {QStringLiteral("dead_belowdot"), 221},
346 {QStringLiteral("dead_hook"), 222},
347 {QStringLiteral("dead_horn"), 223},
348 {QStringLiteral("back"), 224},
349 {QStringLiteral("forward"), 225},
350 {QStringLiteral("stop"), 226},
351 {QStringLiteral("refresh"), 227},
352 {QStringLiteral("volumedown"), 228},
353 {QStringLiteral("volumemute"), 229},
354 {QStringLiteral("volumeup"), 230},
355 {QStringLiteral("bassboost"), 231},
356 {QStringLiteral("bassup"), 232},
357 {QStringLiteral("bassdown"), 233},
358 {QStringLiteral("trebleup"), 234},
359 {QStringLiteral("trebledown"), 235},
360 {QStringLiteral("mediaplay"), 236},
361 {QStringLiteral("mediastop"), 237},
362 {QStringLiteral("mediaprevious"), 238},
363 {QStringLiteral("medianext"), 239},
364 {QStringLiteral("mediarecord"), 240},
365 {QStringLiteral("homepage"), 241},
366 {QStringLiteral("favorites"), 242},
367 {QStringLiteral("search"), 243},
368 {QStringLiteral("standby"), 244},
369 {QStringLiteral("openurl"), 245},
370 {QStringLiteral("launchmail"), 246},
371 {QStringLiteral("launchmedia"), 247},
372 {QStringLiteral("launch0"), 248},
373 {QStringLiteral("launch1"), 249},
374 {QStringLiteral("launch2"), 250},
375 {QStringLiteral("launch3"), 251},
376 {QStringLiteral("launch4"), 252},
377 {QStringLiteral("launch5"), 253},
378 {QStringLiteral("launch6"), 254},
379 {QStringLiteral("launch7"), 255},
380 {QStringLiteral("launch8"), 256},
381 {QStringLiteral("launch9"), 257},
382 {QStringLiteral("launcha"), 258},
383 {QStringLiteral("launchb"), 259},
384 {QStringLiteral("launchc"), 260},
385 {QStringLiteral("launchd"), 261},
386 {QStringLiteral("launche"), 262},
387 {QStringLiteral("launchf"), 263},
388 {QStringLiteral("medialast"), 264},
389 {QStringLiteral("unknown"), 265},
390 {QStringLiteral("call"), 266},
391 {QStringLiteral("context1"), 267},
392 {QStringLiteral("context2"), 268},
393 {QStringLiteral("context3"), 269},
394 {QStringLiteral("context4"), 270},
395 {QStringLiteral("flip"), 271},
396 {QStringLiteral("hangup"), 272},
397 {QStringLiteral("no"), 273},
398 {QStringLiteral("select"), 274},
399 {QStringLiteral("yes"), 275},
400 {QStringLiteral("execute"), 276},
401 {QStringLiteral("printer"), 277},
402 {QStringLiteral("play"), 278},
403 {QStringLiteral("sleep"), 279},
404 {QStringLiteral("zoom"), 280},
405 {QStringLiteral("cancel"), 281},
406
407 {QStringLiteral("a"), 282},
408 {QStringLiteral("b"), 283},
409 {QStringLiteral("c"), 284},
410 {QStringLiteral("d"), 285},
411 {QStringLiteral("e"), 286},
412 {QStringLiteral("f"), 287},
413 {QStringLiteral("g"), 288},
414 {QStringLiteral("h"), 289},
415 {QStringLiteral("i"), 290},
416 {QStringLiteral("j"), 291},
417 {QStringLiteral("k"), 292},
418 {QStringLiteral("l"), 293},
419 {QStringLiteral("m"), 294},
420 {QStringLiteral("n"), 295},
421 {QStringLiteral("o"), 296},
422 {QStringLiteral("p"), 297},
423 {QStringLiteral("q"), 298},
424 {QStringLiteral("r"), 299},
425 {QStringLiteral("s"), 300},
426 {QStringLiteral("t"), 301},
427 {QStringLiteral("u"), 302},
428 {QStringLiteral("v"), 303},
429 {QStringLiteral("w"), 304},
430 {QStringLiteral("x"), 305},
431 {QStringLiteral("y"), 306},
432 {QStringLiteral("z"), 307},
433 {QStringLiteral("`"), 308},
434 {QStringLiteral("!"), 309},
435 {QStringLiteral("\""), 310},
436 {QStringLiteral("$"), 311},
437 {QStringLiteral("%"), 312},
438 {QStringLiteral("^"), 313},
439 {QStringLiteral("&"), 314},
440 {QStringLiteral("*"), 315},
441 {QStringLiteral("("), 316},
442 {QStringLiteral(")"), 317},
443 {QStringLiteral("-"), 318},
444 {QStringLiteral("_"), 319},
445 {QStringLiteral("="), 320},
446 {QStringLiteral("+"), 321},
447 {QStringLiteral("["), 322},
448 {QStringLiteral("]"), 323},
449 {QStringLiteral("{"), 324},
450 {QStringLiteral("}"), 325},
451 {QStringLiteral(":"), 326},
452 {QStringLiteral(";"), 327},
453 {QStringLiteral("@"), 328},
454 {QStringLiteral("'"), 329},
455 {QStringLiteral("#"), 330},
456 {QStringLiteral("~"), 331},
457 {QStringLiteral("\\"), 332},
458 {QStringLiteral("|"), 333},
459 {QStringLiteral(","), 334},
460 {QStringLiteral("."), 335},
461 // { QLatin1String( ">" ), 336 },
462 {QStringLiteral("/"), 337},
463 {QStringLiteral("?"), 338},
464 {QStringLiteral(" "), 339},
465 // { QLatin1String( "<" ), 341 },
466 {QStringLiteral("0"), 340},
467 {QStringLiteral("1"), 341},
468 {QStringLiteral("2"), 342},
469 {QStringLiteral("3"), 343},
470 {QStringLiteral("4"), 344},
471 {QStringLiteral("5"), 345},
472 {QStringLiteral("6"), 346},
473 {QStringLiteral("7"), 347},
474 {QStringLiteral("8"), 348},
475 {QStringLiteral("9"), 349},
476 {QStringLiteral("cr"), 350},
477 {QStringLiteral("leader"), 351},
478 {QStringLiteral("nop"), 352},
479 };
480
481 for (QHash<QString, int>::const_iterator i = m_nameToKeyCode.constBegin(); i != m_nameToKeyCode.constEnd(); ++i) {
482 m_keyCodeToName.insert(i.value(), i.key());
483 }
484}
485
486QString KeyParser::qt2vi(int key) const
487{
488 auto it = m_qt2katevi.constFind(key);
489 if (it != m_qt2katevi.cend()) {
490 return it.value();
491 }
492 return QStringLiteral("invalid");
493}
494
495int KeyParser::vi2qt(const QString &keypress) const
496{
497 auto it = m_katevi2qt.constFind(keypress);
498 if (it != m_katevi2qt.cend()) {
499 return it.value();
500 }
501 return -1;
502}
503
504int KeyParser::encoded2qt(const QString &keypress) const
505{
506 QString key = KeyParser::self()->decodeKeySequence(keypress);
507
508 if (key.length() > 2 && key.at(0) == QLatin1Char('<') && key.at(key.length() - 1) == QLatin1Char('>')) {
509 key = key.mid(1, key.length() - 2);
510 }
511 auto it = m_katevi2qt.constFind(key);
512 if (it != m_katevi2qt.cend())
513 return it.value();
514 return -1;
515}
516
517const QString KeyParser::encodeKeySequence(const QString &keys) const
518{
519 QString encodedSequence;
520 unsigned int keyCodeTemp = 0;
521
522 const QStringView keysView(keys);
523 bool insideTag = false;
524 QChar c;
525 for (int i = 0; i < keys.length(); i++) {
526 c = keys.at(i);
527 if (insideTag) {
528 if (c == QLatin1Char('>')) {
529 QChar code(0xE000 + keyCodeTemp);
530 encodedSequence.append(code);
531 keyCodeTemp = 0;
532 insideTag = false;
533 continue;
534 } else {
535 // contains modifiers
536 if (keysView.mid(i).indexOf(QLatin1Char('-')) != -1 && keysView.mid(i).indexOf(QLatin1Char('-')) < keysView.mid(i).indexOf(QLatin1Char('>'))) {
537 // Perform something similar to a split on '-', except that we want to keep the occurrences of '-'
538 // e.g. <c-s-a> will equate to the list of tokens "c-", "s-", "a".
539 // A straight split on '-' would give us "c", "s", "a", in which case we lose the piece of information that
540 // 'a' is just the 'a' key, not the 'alt' modifier.
541 const QString untilClosing = keys.mid(i, keysView.mid(i).indexOf(QLatin1Char('>'))).toLower();
542 QStringList tokens;
543 int currentPos = 0;
544 int nextHypen = -1;
545 while ((nextHypen = untilClosing.indexOf(QLatin1Char('-'), currentPos)) != -1) {
546 tokens << untilClosing.mid(currentPos, nextHypen - currentPos + 1);
547 currentPos = nextHypen + 1;
548 }
549 tokens << untilClosing.mid(currentPos);
550
551 for (const QString &str : std::as_const(tokens)) {
552 if (str == QLatin1String("s-") && (keyCodeTemp & 0x01) != 0x1) {
553 keyCodeTemp += 0x1;
554 } else if (str == QLatin1String("c-") && (keyCodeTemp & 0x02) != 0x2) {
555 keyCodeTemp += 0x2;
556 } else if (str == QLatin1String("a-") && (keyCodeTemp & 0x04) != 0x4) {
557 keyCodeTemp += 0x4;
558 } else if (str == QLatin1String("m-") && (keyCodeTemp & 0x08) != 0x8) {
559 keyCodeTemp += 0x8;
560 } else {
561 if (m_nameToKeyCode.contains(str) || (str.length() == 1 && str.at(0).isLetterOrNumber())) {
562 if (m_nameToKeyCode.contains(str)) {
563 keyCodeTemp += m_nameToKeyCode.value(str) * 0x10;
564 } else {
565 keyCodeTemp += str.at(0).unicode() * 0x10;
566 }
567 } else {
568 int endOfBlock = keys.indexOf(QLatin1Char('>'));
569 if (endOfBlock -= -1) {
570 endOfBlock = keys.length() - 1;
571 }
572 encodedSequence.clear();
573 encodedSequence.append(QChar::fromUcs4(m_nameToKeyCode.value(QStringLiteral("invalid"))));
574 break;
575 }
576 }
577 }
578 } else {
579 const QString str = keys.mid(i, keys.indexOf(QLatin1Char('>'), i) - i).toLower();
580 if (keys.indexOf(QLatin1Char('>'), i) != -1 && (m_nameToKeyCode.contains(str) || (str.length() == 1 && str.at(0).isLetterOrNumber()))) {
581 if (m_nameToKeyCode.contains(str)) {
582 keyCodeTemp += m_nameToKeyCode.value(str) * 0x10;
583 } else {
584 keyCodeTemp += str.at(0).unicode() * 0x10;
585 }
586 } else {
587 int endOfBlock = keys.indexOf(QLatin1Char('>'));
588 if (endOfBlock -= -1) {
589 endOfBlock = keys.length() - 1;
590 }
591 encodedSequence.clear();
592 keyCodeTemp = m_nameToKeyCode.value(QStringLiteral("invalid")) * 0x10;
593 }
594 }
595 i += keysView.mid(i, keysView.mid(i).indexOf(QLatin1Char('>'))).length() - 1;
596 }
597 } else {
598 if (c == QLatin1Char('<')) {
599 // If there's no closing '>', or if there is an opening '<' before the next '>', interpret as a literal '<'
600 // If we are <space>, encode as a literal " ".
601 const QStringView rest = keysView.mid(i);
602 if (rest.indexOf(QLatin1Char('>'), 1) != -1 && rest.mid(1, rest.indexOf(QLatin1Char('>'), 1) - 1) == QLatin1String("space")) {
603 encodedSequence.append(QLatin1Char(' '));
604 i += rest.indexOf(QLatin1Char('>'), 1);
605 continue;
606 } else if (rest.indexOf(QLatin1Char('>'), 1) == -1
607 || (rest.indexOf(QLatin1Char('<'), 1) < rest.indexOf(QLatin1Char('>'), 1) && rest.indexOf(QLatin1Char('<'), 1) != -1)) {
608 encodedSequence.append(c);
609 continue;
610 }
611 insideTag = true;
612 continue;
613 } else {
614 encodedSequence.append(c);
615 }
616 }
617 }
618
619 return encodedSequence;
620}
621
622const QString KeyParser::decodeKeySequence(const QString &keys) const
623{
624 QString ret;
625 ret.reserve(keys.length());
626
627 for (int i = 0; i < keys.length(); i++) {
628 QChar c = keys.at(i);
629 int keycode = c.unicode();
630
631 if ((keycode & 0xE000) != 0xE000) {
632 ret.append(c);
633 } else {
634 ret.append(QLatin1Char('<'));
635
636 if ((keycode & 0x1) == 0x1) {
637 ret.append(QLatin1String("s-"));
638 // keycode -= 0x1;
639 }
640 if ((keycode & 0x2) == 0x2) {
641 ret.append(QLatin1String("c-"));
642 // keycode -= 0x2;
643 }
644 if ((keycode & 0x4) == 0x4) {
645 ret.append(QLatin1String("a-"));
646 // keycode -= 0x4;
647 }
648 if ((keycode & 0x8) == 0x8) {
649 ret.append(QLatin1String("m-"));
650 // keycode -= 0x8;
651 }
652
653 if ((keycode & 0xE000) == 0xE000) {
654 ret.append(m_keyCodeToName.value((keycode - 0xE000) / 0x10));
655 } else {
656 ret.append(QChar::fromUcs4(keycode));
657 }
658 ret.append(QLatin1Char('>'));
659 }
660 }
661
662 return ret;
663}
664
665const QChar KeyParser::KeyEventToQChar(const QKeyEvent &keyEvent)
666{
667 return KeyEventToQChar(keyEvent.key(), keyEvent.text(), keyEvent.modifiers());
668}
669
670const QChar KeyParser::KeyEventToQChar(const KeyEvent &keyEvent)
671{
672 return KeyEventToQChar(keyEvent.key(), keyEvent.text(), keyEvent.modifiers());
673}
674
675const QChar KeyParser::KeyEventToQChar(int keyCode, const QString &text, Qt::KeyboardModifiers mods) const
676{
677 // If previous key press was AltGr, return key value right away and don't go
678 // down the "handle modifiers" code path. AltGr is really confusing...
679 if (mods & Qt::GroupSwitchModifier) {
680 return (!text.isEmpty()) ? text.at(0) : QChar();
681 }
682
683 if (text.isEmpty() || (text.length() == 1 && text.at(0) < QChar(0x20)) || keyCode == Qt::Key_Delete
684 || (mods != Qt::NoModifier && mods != Qt::ShiftModifier && mods != Qt::KeypadModifier)) {
686 keyPress.reserve(11);
687
688 keyPress.append(QLatin1Char('<'));
689 keyPress.append((mods & Qt::ShiftModifier) ? QStringLiteral("s-") : QString());
690 keyPress.append((mods & CONTROL_MODIFIER) ? QStringLiteral("c-") : QString());
691 keyPress.append((mods & Qt::AltModifier) ? QStringLiteral("a-") : QString());
692 keyPress.append((mods & META_MODIFIER) ? QStringLiteral("m-") : QString());
693 keyPress.append(keyCode <= 0xFF ? QChar(keyCode) : qt2vi(keyCode));
694 keyPress.append(QLatin1Char('>'));
695
696 return encodeKeySequence(keyPress).at(0);
697 } else {
698 return text.at(0);
699 }
700}
QEvent wrapper for copying/storing key events.
Definition keyevent.h:19
for encoding keypresses w/ modifiers into an internal QChar representation and back again to a descri...
Definition keyparser.h:28
R fromUcs4(char32_t c)
bool isLetterOrNumber(char32_t ucs4)
char16_t & unicode()
const_iterator cend() const const
const_iterator constBegin() const const
const_iterator constEnd() const const
const_iterator constFind(const Key &key) const const
bool contains(const Key &key) const const
iterator insert(const Key &key, const T &value)
T value(const Key &key) const const
QString & append(QChar ch)
const QChar at(qsizetype position) const const
void clear()
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
qsizetype length() const const
QString mid(qsizetype position, qsizetype n) const const
void reserve(qsizetype size)
QString toLower() const const
QStringView mid(qsizetype start, qsizetype length) const const
qsizetype indexOf(QChar c, qsizetype from, Qt::CaseSensitivity cs) const const
Key_Escape
typedef KeyboardModifiers
void keyEvent(KeyAction action, QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier, int delay)
void keyPress(QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier, int delay)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:15:44 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.