1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 1997 Stefan Taferner <taferner@alpin.or.at>
4 SPDX-FileCopyrightText: 2000 Nicolas Hadacek <haadcek@kde.org>
5 SPDX-FileCopyrightText: 2001, 2002 Ellis Whitehead <ellis@kde.org>
6
7 SPDX-License-Identifier: LGPL-2.0-or-later
8*/
9
10#include "kstandardshortcut.h"
11#include "kstandardshortcutwatcher.h"
12
13#include "kconfig.h"
14#include "kconfigwatcher.h"
15#include "ksharedconfig.h"
16#include <kconfiggroup.h>
17
18#include <QCoreApplication>
19#include <QDebug>
20#include <QKeySequence>
21
22namespace KStandardShortcut
23{
24struct KStandardShortcutInfo {
25 // The standard shortcut id. @see StandardShortcut
26 StandardShortcut id;
27
28 /*
29 * Unique name for the given accel. The name is used to save the user
30 * settings. It's not representable. Use description for that.
31 * @warning NEVER EVER CHANGE IT OR TRANSLATE IT!
32 */
33 const char *name;
34
35 //! Localized label for user-visible display, including translation context.
36 struct {
37 const char *text;
38 const char *context;
39 } description;
40
41 // The keys for this shortcut
42 int cutDefault, cutDefault2;
43
44 // A shortcut that is created with @a cutDefault and @cutDefault2
45 QList<QKeySequence> cut;
46
47 // If this struct is initialized. If not initialized @cut is not valid
48 bool isInitialized;
49
50 // Category of this Shortcut
51 Category category;
52};
53
54#define CTRL(x) QKeyCombination(Qt::CTRL | Qt::Key_##x).toCombined()
55#define SHIFT(x) QKeyCombination(Qt::SHIFT | Qt::Key_##x).toCombined()
56#define CTRLALT(x) QKeyCombination(Qt::CTRL | Qt::ALT | Qt::Key_##x).toCombined()
57#define CTRLSHIFT(x) QKeyCombination(Qt::CTRL | Qt::SHIFT | Qt::Key_##x).toCombined()
58#define ALT(x) QKeyCombination(Qt::ALT | Qt::Key_##x).toCombined()
59#define ALTSHIFT(x) QKeyCombination(Qt::ALT | Qt::SHIFT | Qt::Key_##x).toCombined()
60#define CTRLMETA(x) QKeyCombination(Qt::CTRL | Qt::META | Qt::Key_##x).toCombined()
61
62/* Array of predefined KStandardShortcutInfo objects, which cover all
63 the "standard" accelerators. Each enum value from StandardShortcut
64 should appear in this table.
65*/
66// STUFF WILL BREAK IF YOU DON'T READ THIS!!!
67// Read the comments of the big enum in kstandardshortcut.h before you change anything!
68// clazy:exclude-next-line=non-pod-global-static
69static KStandardShortcutInfo g_infoStandardShortcut[] = {
70 // Group File,
71 {.id: AccelNone, .name: nullptr, .description: {.text: nullptr, .context: nullptr}, .cutDefault: 0, .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::InvalidCategory},
72 {.id: Open, .name: "Open", QT_TRANSLATE_NOOP3("KStandardShortcut", "Open", "@action"), CTRL(O), .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::File},
73 {.id: New, .name: "New", QT_TRANSLATE_NOOP3("KStandardShortcut", "New", "@action"), CTRL(N), .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::File},
74 {.id: Close, .name: "Close", QT_TRANSLATE_NOOP3("KStandardShortcut", "Close", "@action"), CTRL(W), CTRL(Escape), .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::File},
75 {.id: Save, .name: "Save", QT_TRANSLATE_NOOP3("KStandardShortcut", "Save", "@action"), CTRL(S), .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::File},
76 {.id: Print, .name: "Print", QT_TRANSLATE_NOOP3("KStandardShortcut", "Print", "@action"), CTRL(P), .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::File},
77 {.id: Quit, .name: "Quit", QT_TRANSLATE_NOOP3("KStandardShortcut", "Quit", "@action"), CTRL(Q), .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Navigation},
78
79 // Group Edit
80 {.id: Undo, .name: "Undo", QT_TRANSLATE_NOOP3("KStandardShortcut", "Undo", "@action"), CTRL(Z), .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Edit},
81 {.id: Redo, .name: "Redo", QT_TRANSLATE_NOOP3("KStandardShortcut", "Redo", "@action"), CTRLSHIFT(Z), .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Edit},
82 // Both "Cut" and "Delete" use Shift+Delete, but this is okay; see
83 // https://commits.kde.org/kxmlgui/8eabbf6725386e716b7536c71a9181dfe5d959f0
84 {.id: Cut, .name: "Cut", QT_TRANSLATE_NOOP3("KStandardShortcut", "Cut", "@action"), CTRL(X), SHIFT(Delete), .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Edit},
85 {.id: Copy, .name: "Copy", QT_TRANSLATE_NOOP3("KStandardShortcut", "Copy", "@action"), CTRL(C), CTRL(Insert), .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Edit},
86 {.id: Paste, .name: "Paste", QT_TRANSLATE_NOOP3("KStandardShortcut", "Paste", "@action"), CTRL(V), SHIFT(Insert), .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Edit},
87 {.id: PasteSelection,
88 .name: "Paste Selection",
89 QT_TRANSLATE_NOOP3("KStandardShortcut", "Paste Selection", "@action"),
90 CTRLSHIFT(Insert),
91 .cutDefault2: 0,
92 .cut: QList<QKeySequence>(),
93 .isInitialized: false,
94 .category: Category::Edit},
95
96 {.id: SelectAll, .name: "SelectAll", QT_TRANSLATE_NOOP3("KStandardShortcut", "Select All", "@action"), CTRL(A), .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Edit},
97 {.id: Deselect, .name: "Deselect", QT_TRANSLATE_NOOP3("KStandardShortcut", "Deselect", "@action"), CTRLSHIFT(A), .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Edit},
98 {.id: DeleteWordBack,
99 .name: "DeleteWordBack",
100 QT_TRANSLATE_NOOP3("KStandardShortcut", "Delete Word Backwards", "@action"),
101#if defined(Q_OS_MACOS)
102 ALT(Backspace),
103#else
104 CTRL(Backspace),
105#endif
106 .cutDefault2: 0,
107 .cut: QList<QKeySequence>(),
108 .isInitialized: false,
109 .category: Category::Edit},
110 {.id: DeleteWordForward,
111 .name: "DeleteWordForward",
112 QT_TRANSLATE_NOOP3("KStandardShortcut", "Delete Word Forward", "@action"),
113#if defined(Q_OS_MACOS)
114 ALT(Delete),
115#else
116 CTRL(Delete),
117#endif
118 .cutDefault2: 0,
119 .cut: QList<QKeySequence>(),
120 .isInitialized: false,
121 .category: Category::Edit},
122
123 {.id: Find, .name: "Find", QT_TRANSLATE_NOOP3("KStandardShortcut", "Find", "@action"), CTRL(F), .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Edit},
124 {.id: FindNext, .name: "FindNext", QT_TRANSLATE_NOOP3("KStandardShortcut", "Find Next", "@action"), .cutDefault: Qt::Key_F3, .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Edit},
125 {.id: FindPrev, .name: "FindPrev", QT_TRANSLATE_NOOP3("KStandardShortcut", "Find Prev", "@action"), SHIFT(F3), .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Edit},
126 {.id: Replace, .name: "Replace", QT_TRANSLATE_NOOP3("KStandardShortcut", "Replace", "@action"), CTRL(R), .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Edit},
127
128 // Group Navigation
129 {.id: Home,
130 .name: "Home",
131 QT_TRANSLATE_NOOP3("KStandardShortcut", "Home", "@action Go to main page"),
132 ALT(Home),
133 .cutDefault2: Qt::Key_HomePage,
134 .cut: QList<QKeySequence>(),
135 .isInitialized: false,
136 .category: Category::Navigation},
137 {.id: Begin,
138 .name: "Begin",
139 QT_TRANSLATE_NOOP3("KStandardShortcut", "Begin", "@action Beginning of document"),
140#if defined(Q_OS_MACOS)
141 CTRL(Up),
142#else
143 CTRL(Home),
144#endif
145 .cutDefault2: 0,
146 .cut: QList<QKeySequence>(),
147 .isInitialized: false,
148 .category: Category::Navigation},
149 {.id: End,
150 .name: "End",
151 QT_TRANSLATE_NOOP3("KStandardShortcut", "End", "@action End of document"),
152#if defined(Q_OS_MACOS)
153 CTRL(Down),
154#else
155 CTRL(End),
156#endif
157 .cutDefault2: 0,
158 .cut: QList<QKeySequence>(),
159 .isInitialized: false,
160 .category: Category::Navigation},
161 {.id: Prior, .name: "Prior", QT_TRANSLATE_NOOP3("KStandardShortcut", "Prior", "@action"), .cutDefault: Qt::Key_PageUp, .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Navigation},
162 {.id: Next,
163 .name: "Next",
164 QT_TRANSLATE_NOOP3("KStandardShortcut", "Next", "@action Opposite to Prior"),
165 .cutDefault: Qt::Key_PageDown,
166 .cutDefault2: 0,
167 .cut: QList<QKeySequence>(),
168 .isInitialized: false,
169 .category: Category::Navigation},
170
171 {.id: Up, .name: "Up", QT_TRANSLATE_NOOP3("KStandardShortcut", "Up", "@action"), ALT(Up), .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Navigation},
172 {.id: Back, .name: "Back", QT_TRANSLATE_NOOP3("KStandardShortcut", "Back", "@action"), ALT(Left), .cutDefault2: Qt::Key_Back, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Navigation},
173 {.id: Forward,
174 .name: "Forward",
175 QT_TRANSLATE_NOOP3("KStandardShortcut", "Forward", "@action"),
176 ALT(Right),
177 .cutDefault2: Qt::Key_Forward,
178 .cut: QList<QKeySequence>(),
179 .isInitialized: false,
180 .category: Category::Navigation},
181 {.id: Reload,
182 .name: "Reload",
183 QT_TRANSLATE_NOOP3("KStandardShortcut", "Reload", "@action"),
184 .cutDefault: Qt::Key_F5,
185 .cutDefault2: Qt::Key_Refresh,
186 .cut: QList<QKeySequence>(),
187 .isInitialized: false,
188 .category: Category::Navigation},
189
190 {.id: BeginningOfLine,
191 .name: "BeginningOfLine",
192 QT_TRANSLATE_NOOP3("KStandardShortcut", "Beginning of Line", "@action"),
193#if defined(Q_OS_MACOS)
194 CTRL(Left),
195#else
196 .cutDefault: Qt::Key_Home,
197#endif
198 .cutDefault2: 0,
199 .cut: QList<QKeySequence>(),
200 .isInitialized: false,
201 .category: Category::Navigation},
202 {.id: EndOfLine,
203 .name: "EndOfLine",
204 QT_TRANSLATE_NOOP3("KStandardShortcut", "End of Line", "@action"),
205#if defined(Q_OS_MACOS)
206 CTRL(Right),
207#else
208 .cutDefault: Qt::Key_End,
209#endif
210 .cutDefault2: 0,
211 .cut: QList<QKeySequence>(),
212 .isInitialized: false,
213 .category: Category::Navigation},
214 {.id: GotoLine, .name: "GotoLine", QT_TRANSLATE_NOOP3("KStandardShortcut", "Go to Line", "@action"), CTRL(G), .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Navigation},
215 {.id: BackwardWord,
216 .name: "BackwardWord",
217 QT_TRANSLATE_NOOP3("KStandardShortcut", "Backward Word", "@action"),
218#if defined(Q_OS_MACOS)
219 ALT(Left),
220#else
221 CTRL(Left),
222#endif
223 .cutDefault2: 0,
224 .cut: QList<QKeySequence>(),
225 .isInitialized: false,
226 .category: Category::Navigation},
227 {.id: ForwardWord,
228 .name: "ForwardWord",
229 QT_TRANSLATE_NOOP3("KStandardShortcut", "Forward Word", "@action"),
230#if defined(Q_OS_MACOS)
231 ALT(Right),
232#else
233 CTRL(Right),
234#endif
235 .cutDefault2: 0,
236 .cut: QList<QKeySequence>(),
237 .isInitialized: false,
238 .category: Category::Navigation},
239
240 {.id: AddBookmark,
241 .name: "AddBookmark",
242 QT_TRANSLATE_NOOP3("KStandardShortcut", "Add Bookmark", "@action"),
243 CTRL(B),
244 .cutDefault2: 0,
245 .cut: QList<QKeySequence>(),
246 .isInitialized: false,
247 .category: Category::Navigation},
248 {.id: ZoomIn, .name: "ZoomIn", QT_TRANSLATE_NOOP3("KStandardShortcut", "Zoom In", "@action"), CTRL(Plus), CTRL(Equal), .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::View},
249 {.id: ZoomOut, .name: "ZoomOut", QT_TRANSLATE_NOOP3("KStandardShortcut", "Zoom Out", "@action"), CTRL(Minus), .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::View},
250 {.id: FullScreen,
251 .name: "FullScreen",
252 QT_TRANSLATE_NOOP3("KStandardShortcut", "Full Screen Mode", "@action"),
253#if defined(Q_OS_MACOS)
254 CTRLMETA(F),
255#else
256 CTRLSHIFT(F),
257#endif
258 .cutDefault2: 0,
259 .cut: QList<QKeySequence>(),
260 .isInitialized: false,
261 .category: Category::View},
262
263 {.id: ShowMenubar, .name: "ShowMenubar", QT_TRANSLATE_NOOP3("KStandardShortcut", "Show Menu Bar", "@action"), CTRL(M), .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::View},
264 {.id: TabNext,
265 .name: "Activate Next Tab",
266 QT_TRANSLATE_NOOP3("KStandardShortcut", "Activate Next Tab", "@action"),
267 CTRL(PageDown),
268 CTRL(BracketRight),
269 .cut: QList<QKeySequence>(),
270 .isInitialized: false,
271 .category: Category::Navigation},
272 {.id: TabPrev,
273 .name: "Activate Previous Tab",
274 QT_TRANSLATE_NOOP3("KStandardShortcut", "Activate Previous Tab", "@action"),
275 CTRL(PageUp),
276 CTRL(BracketLeft),
277 .cut: QList<QKeySequence>(),
278 .isInitialized: false,
279 .category: Category::Navigation},
280
281 // Group Help
282 {.id: Help, .name: "Help", QT_TRANSLATE_NOOP3("KStandardShortcut", "Help", "@action"), .cutDefault: Qt::Key_F1, .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Help},
283 {.id: WhatsThis, .name: "WhatsThis", QT_TRANSLATE_NOOP3("KStandardShortcut", "What's This", "@action"), SHIFT(F1), .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Help},
284
285 // Group TextCompletion
286 {.id: TextCompletion,
287 .name: "TextCompletion",
288 QT_TRANSLATE_NOOP3("KStandardShortcut", "Text Completion", "@action"),
289 CTRL(E),
290 .cutDefault2: 0,
291 .cut: QList<QKeySequence>(),
292 .isInitialized: false,
293 .category: Category::Edit},
294 {.id: PrevCompletion,
295 .name: "PrevCompletion",
296 QT_TRANSLATE_NOOP3("KStandardShortcut", "Previous Completion Match", "@action"),
297 CTRL(Up),
298 .cutDefault2: 0,
299 .cut: QList<QKeySequence>(),
300 .isInitialized: false,
301 .category: Category::Edit},
302 {.id: NextCompletion,
303 .name: "NextCompletion",
304 QT_TRANSLATE_NOOP3("KStandardShortcut", "Next Completion Match", "@action"),
305 CTRL(Down),
306 .cutDefault2: 0,
307 .cut: QList<QKeySequence>(),
308 .isInitialized: false,
309 .category: Category::Edit},
310 {.id: SubstringCompletion,
311 .name: "SubstringCompletion",
312 QT_TRANSLATE_NOOP3("KStandardShortcut", "Substring Completion", "@action"),
313 CTRL(T),
314 .cutDefault2: 0,
315 .cut: QList<QKeySequence>(),
316 .isInitialized: false,
317 .category: Category::Edit},
318
319 {.id: RotateUp,
320 .name: "RotateUp",
321 QT_TRANSLATE_NOOP3("KStandardShortcut", "Previous Item in List", "@action"),
322 .cutDefault: Qt::Key_Up,
323 .cutDefault2: 0,
324 .cut: QList<QKeySequence>(),
325 .isInitialized: false,
326 .category: Category::Navigation},
327 {.id: RotateDown,
328 .name: "RotateDown",
329 QT_TRANSLATE_NOOP3("KStandardShortcut", "Next Item in List", "@action"),
330 .cutDefault: Qt::Key_Down,
331 .cutDefault2: 0,
332 .cut: QList<QKeySequence>(),
333 .isInitialized: false,
334 .category: Category::Navigation},
335
336 {.id: OpenRecent, .name: "OpenRecent", QT_TRANSLATE_NOOP3("KStandardShortcut", "Open Recent", "@action"), .cutDefault: 0, .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::File},
337 {.id: SaveAs, .name: "SaveAs", QT_TRANSLATE_NOOP3("KStandardShortcut", "Save As", "@action"), CTRLSHIFT(S), .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::File},
338 {.id: Revert, .name: "Revert", QT_TRANSLATE_NOOP3("KStandardShortcut", "Revert", "@action"), .cutDefault: 0, .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Edit},
339 {.id: PrintPreview, .name: "PrintPreview", QT_TRANSLATE_NOOP3("KStandardShortcut", "Print Preview", "@action"), .cutDefault: 0, .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::File},
340 {.id: Mail, .name: "Mail", QT_TRANSLATE_NOOP3("KStandardShortcut", "Mail", "@action"), .cutDefault: 0, .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Help},
341 {.id: Clear, .name: "Clear", QT_TRANSLATE_NOOP3("KStandardShortcut", "Clear", "@action"), .cutDefault: 0, .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Edit},
342 {.id: ActualSize,
343 .name: "ActualSize",
344 QT_TRANSLATE_NOOP3("KStandardShortcut", "Zoom to Actual Size", "@action"),
345 CTRL(0),
346 .cutDefault2: 0,
347 .cut: QList<QKeySequence>(),
348 .isInitialized: false,
349 .category: Category::View},
350 {.id: FitToPage, .name: "FitToPage", QT_TRANSLATE_NOOP3("KStandardShortcut", "Fit To Page", "@action"), .cutDefault: 0, .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::View},
351 {.id: FitToWidth, .name: "FitToWidth", QT_TRANSLATE_NOOP3("KStandardShortcut", "Fit To Width", "@action"), .cutDefault: 0, .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::View},
352 {.id: FitToHeight, .name: "FitToHeight", QT_TRANSLATE_NOOP3("KStandardShortcut", "Fit To Height", "@action"), .cutDefault: 0, .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::View},
353 {.id: Zoom, .name: "Zoom", QT_TRANSLATE_NOOP3("KStandardShortcut", "Zoom", "@action"), .cutDefault: 0, .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::View},
354 {.id: Goto, .name: "Goto", QT_TRANSLATE_NOOP3("KStandardShortcut", "Goto", "@action"), .cutDefault: 0, .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Navigation},
355 {.id: GotoPage, .name: "GotoPage", QT_TRANSLATE_NOOP3("KStandardShortcut", "Goto Page", "@action"), .cutDefault: 0, .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Navigation},
356 {.id: DocumentBack,
357 .name: "DocumentBack",
358 QT_TRANSLATE_NOOP3("KStandardShortcut", "Document Back", "@action"),
359 ALTSHIFT(Left),
360 .cutDefault2: 0,
361 .cut: QList<QKeySequence>(),
362 .isInitialized: false,
363 .category: Category::Navigation},
364 {.id: DocumentForward,
365 .name: "DocumentForward",
366 QT_TRANSLATE_NOOP3("KStandardShortcut", "Document Forward", "@action"),
367 ALTSHIFT(Right),
368 .cutDefault2: 0,
369 .cut: QList<QKeySequence>(),
370 .isInitialized: false,
371 .category: Category::Navigation},
372 {.id: EditBookmarks,
373 .name: "EditBookmarks",
374 QT_TRANSLATE_NOOP3("KStandardShortcut", "Edit Bookmarks", "@action"),
375 .cutDefault: 0,
376 .cutDefault2: 0,
377 .cut: QList<QKeySequence>(),
378 .isInitialized: false,
379 .category: Category::Navigation},
380 {.id: Spelling, .name: "Spelling", QT_TRANSLATE_NOOP3("KStandardShortcut", "Spelling", "@action"), .cutDefault: 0, .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Edit},
381 {.id: ShowToolbar, .name: "ShowToolbar", QT_TRANSLATE_NOOP3("KStandardShortcut", "Show Toolbar", "@action"), .cutDefault: 0, .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::View},
382 {.id: ShowStatusbar, .name: "ShowStatusbar", QT_TRANSLATE_NOOP3("KStandardShortcut", "Show Statusbar", "@action"), .cutDefault: 0, .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::View},
383 {.id: KeyBindings,
384 .name: "KeyBindings",
385 QT_TRANSLATE_NOOP3("KStandardShortcut", "Key Bindings", "@action"),
386 CTRLALT(Comma),
387 .cutDefault2: 0,
388 .cut: QList<QKeySequence>(),
389 .isInitialized: false,
390 .category: Category::Settings},
391 {.id: Preferences,
392 .name: "Preferences",
393 QT_TRANSLATE_NOOP3("KStandardShortcut", "Configure Application", "@action"),
394 CTRLSHIFT(Comma),
395 .cutDefault2: 0,
396 .cut: QList<QKeySequence>(),
397 .isInitialized: false,
398 .category: Category::Settings},
399 {.id: ConfigureToolbars,
400 .name: "ConfigureToolbars",
401 QT_TRANSLATE_NOOP3("KStandardShortcut", "Configure Toolbars", "@action"),
402 .cutDefault: 0,
403 .cutDefault2: 0,
404 .cut: QList<QKeySequence>(),
405 .isInitialized: false,
406 .category: Category::Settings},
407 {.id: ConfigureNotifications,
408 .name: "ConfigureNotifications",
409 QT_TRANSLATE_NOOP3("KStandardShortcut", "Configure Notifications", "@action"),
410 .cutDefault: 0,
411 .cutDefault2: 0,
412 .cut: QList<QKeySequence>(),
413 .isInitialized: false,
414 .category: Category::Settings},
415 {.id: ReportBug, .name: "ReportBug", QT_TRANSLATE_NOOP3("KStandardShortcut", "Report Bug", "@action"), .cutDefault: 0, .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Help},
416 {.id: SwitchApplicationLanguage,
417 .name: "SwitchApplicationLanguage",
418 QT_TRANSLATE_NOOP3("KStandardShortcut", "Configure Language…", "@action"),
419 .cutDefault: 0,
420 .cutDefault2: 0,
421 .cut: QList<QKeySequence>(),
422 .isInitialized: false,
423 .category: Category::Settings},
424 {.id: AboutApp, .name: "AboutApp", QT_TRANSLATE_NOOP3("KStandardShortcut", "About Application", "@action"), .cutDefault: 0, .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Help},
425 {.id: AboutKDE, .name: "AboutKDE", QT_TRANSLATE_NOOP3("KStandardShortcut", "About KDE", "@action"), .cutDefault: 0, .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Help},
426 // Both "Cut" and "Delete" use Shift+Delete, but this is okay; see
427 // https://commits.kde.org/kxmlgui/8eabbf6725386e716b7536c71a9181dfe5d959f0
428 {.id: DeleteFile, .name: "DeleteFile", QT_TRANSLATE_NOOP3("KStandardShortcut", "Delete", "@action"), SHIFT(Delete), .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::File},
429 {.id: RenameFile, .name: "RenameFile", QT_TRANSLATE_NOOP3("KStandardShortcut", "Rename", "@action"), .cutDefault: Qt::Key_F2, .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::File},
430 {.id: MoveToTrash,
431 .name: "MoveToTrash",
432 QT_TRANSLATE_NOOP3("KStandardShortcut", "Move to Trash", "@action"),
433 .cutDefault: Qt::Key_Delete,
434 .cutDefault2: 0,
435 .cut: QList<QKeySequence>(),
436 .isInitialized: false,
437 .category: Category::File},
438 {.id: Donate, .name: "Donate", QT_TRANSLATE_NOOP3("KStandardShortcut", "Donate", "@action"), .cutDefault: 0, .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::Help},
439 {.id: ShowHideHiddenFiles,
440 .name: "ShowHideHiddenFiles",
441 QT_TRANSLATE_NOOP3("KStandardShortcut", "Show/Hide Hidden Files", "@action"),
442 CTRL(H),
443 ALT(Period),
444 .cut: QList<QKeySequence>(),
445 .isInitialized: false,
446 .category: Category::View},
447 {.id: CreateFolder,
448 .name: "CreateFolder",
449 QT_TRANSLATE_NOOP3("KStandardShortcut", "Create Folder", "@action"),
450 CTRLSHIFT(N),
451 .cutDefault2: 0,
452 .cut: QList<QKeySequence>(),
453 .isInitialized: false,
454 .category: Category::File},
455 {.id: OpenMainMenu,
456 .name: "OpenMainMenu",
457 QT_TRANSLATE_NOOP3("KStandardShortcut", "Open Main Menu", "@action referring to the menu bar or a hamburger menu"),
458 .cutDefault: Qt::Key_F10,
459 .cutDefault2: 0,
460 .cut: QList<QKeySequence>(),
461 .isInitialized: false,
462 .category: Category::View},
463 {.id: OpenContextMenu,
464 .name: "OpenContextMenu",
465 QT_TRANSLATE_NOOP3("KStandardShortcut", "Open Context Menu", "@action"),
466 .cutDefault: Qt::Key_Menu,
467 SHIFT(F10),
468 .cut: QList<QKeySequence>(),
469 .isInitialized: false,
470 .category: Category::View},
471
472 // dummy entry to catch simple off-by-one errors. Insert new entries before this line.
473 {.id: AccelNone, .name: nullptr, .description: {.text: nullptr, .context: nullptr}, .cutDefault: 0, .cutDefault2: 0, .cut: QList<QKeySequence>(), .isInitialized: false, .category: Category::InvalidCategory}};
474
475/* Search for the KStandardShortcutInfo object associated with the given @p id.
476 Return a dummy entry with no name and an empty shortcut if @p id is invalid.
477*/
478static KStandardShortcutInfo *guardedStandardShortcutInfo(StandardShortcut id)
479{
480 if (id >= static_cast<int>(sizeof(g_infoStandardShortcut) / sizeof(KStandardShortcutInfo)) || id < 0) {
481 qWarning() << "KStandardShortcut: id not found!";
482 return &g_infoStandardShortcut[AccelNone];
483 } else {
484 return &g_infoStandardShortcut[id];
485 }
486}
487
488// Sanitize the list for duplicates. For some reason some
489// people have kdeglobals entries like
490// Close=Ctrl+W; Ctrl+Esc; Ctrl+W; Ctrl+Esc;
491// having the same shortcut more than once in the shortcut
492// declaration is clearly bogus so fix it
493static void sanitizeShortcutList(QList<QKeySequence> *list)
494{
495 for (int i = 0; i < list->size(); ++i) {
496 const QKeySequence &ks = list->at(i);
497 int other = list->indexOf(t: ks, from: i + 1);
498 while (other != -1) {
499 list->removeAt(i: other);
500 other = list->indexOf(t: ks, from: other);
501 }
502 }
503}
504
505/* Initialize the accelerator @p id by checking if it is overridden
506 in the configuration file (and if it isn't, use the default).
507 On X11, if QApplication was initialized with GUI disabled,
508 the default will always be used.
509*/
510void initialize(StandardShortcut id)
511{
512 KStandardShortcutInfo *info = guardedStandardShortcutInfo(id);
513
514 // All three are needed.
515 if (info->id != AccelNone) {
516 Q_ASSERT(info->description.text);
517 Q_ASSERT(info->description.context);
518 Q_ASSERT(info->name);
519 }
520
521 KConfigGroup cg(KSharedConfig::openConfig(), QStringLiteral("Shortcuts"));
522
523 if (cg.hasKey(key: info->name)) {
524 QString s = cg.readEntry(key: info->name);
525 if (s != QLatin1String("none")) {
526 info->cut = QKeySequence::listFromString(str: s);
527 sanitizeShortcutList(list: &info->cut);
528 } else {
529 info->cut = QList<QKeySequence>();
530 }
531 } else {
532 info->cut = hardcodedDefaultShortcut(id);
533 }
534
535 info->isInitialized = true;
536}
537
538void saveShortcut(StandardShortcut id, const QList<QKeySequence> &newShortcut)
539{
540 KStandardShortcutInfo *info = guardedStandardShortcutInfo(id);
541 // If the action has no standard shortcut associated there is nothing to
542 // save
543 if (info->id == AccelNone) {
544 return;
545 }
546
547 KConfigGroup cg(KSharedConfig::openConfig(), QStringLiteral("Shortcuts"));
548
549 info->cut = newShortcut;
550 bool sameAsDefault = (newShortcut == hardcodedDefaultShortcut(id));
551
552 if (sameAsDefault) {
553 // If the shortcut is the equal to the hardcoded one we remove it from
554 // kdeglobal if necessary and return.
555 if (cg.hasKey(key: info->name)) {
556 cg.deleteEntry(key: info->name, pFlags: KConfig::Global | KConfig::Persistent | KConfig::Notify);
557 cg.sync();
558 }
559
560 return;
561 }
562
563 // Write the changed shortcut to kdeglobals
564 sanitizeShortcutList(list: &info->cut);
565 cg.writeEntry(key: info->name, value: QKeySequence::listToString(list: info->cut), pFlags: KConfig::Global | KConfig::Persistent | KConfig::Notify);
566 cg.sync();
567}
568
569QString name(StandardShortcut id)
570{
571 return QString::fromLatin1(ba: guardedStandardShortcutInfo(id)->name);
572}
573
574QString label(StandardShortcut id)
575{
576 KStandardShortcutInfo *info = guardedStandardShortcutInfo(id);
577 return QCoreApplication::translate(context: "KStandardShortcut", key: info->description.text, disambiguation: info->description.context);
578}
579
580// TODO: Add psWhatsThis entry to KStandardShortcutInfo
581QString whatsThis(StandardShortcut /*id*/)
582{
583 // KStandardShortcutInfo* info = guardedStandardShortcutInfo( id );
584 // if( info && info->whatsThis )
585 // return i18n(info->whatsThis);
586 // else
587 return QString();
588}
589
590const QList<QKeySequence> &shortcut(StandardShortcut id)
591{
592 KStandardShortcutInfo *info = guardedStandardShortcutInfo(id);
593
594 if (!info->isInitialized) {
595 initialize(id);
596 }
597
598 return info->cut;
599}
600
601StandardShortcut find(const QKeySequence &seq)
602{
603 if (!seq.isEmpty()) {
604 for (const KStandardShortcutInfo &shortcutInfo : g_infoStandardShortcut) {
605 const StandardShortcut id = shortcutInfo.id;
606 if (id != AccelNone) {
607 if (!shortcutInfo.isInitialized) {
608 initialize(id);
609 }
610 if (shortcutInfo.cut.contains(t: seq)) {
611 return id;
612 }
613 }
614 }
615 }
616 return AccelNone;
617}
618
619StandardShortcut findByName(const QString &name)
620{
621 for (const KStandardShortcutInfo &shortcutInfo : g_infoStandardShortcut) {
622 if (QLatin1StringView(shortcutInfo.name) == name) {
623 return shortcutInfo.id;
624 }
625 }
626 return AccelNone;
627}
628
629QList<QKeySequence> hardcodedDefaultShortcut(StandardShortcut id)
630{
631 QList<QKeySequence> cut;
632 KStandardShortcutInfo *info = guardedStandardShortcutInfo(id);
633
634 if (info->cutDefault != 0) {
635 cut << info->cutDefault;
636 }
637
638 if (info->cutDefault2 != 0) {
639 if (cut.isEmpty()) {
640 cut << QKeySequence();
641 }
642
643 cut << info->cutDefault2;
644 }
645
646 return cut;
647}
648
649Category category(StandardShortcut id)
650{
651 return guardedStandardShortcutInfo(id)->category;
652}
653
654const QList<QKeySequence> &open()
655{
656 return shortcut(id: Open);
657}
658const QList<QKeySequence> &openNew()
659{
660 return shortcut(id: New);
661}
662const QList<QKeySequence> &close()
663{
664 return shortcut(id: Close);
665}
666const QList<QKeySequence> &save()
667{
668 return shortcut(id: Save);
669}
670const QList<QKeySequence> &print()
671{
672 return shortcut(id: Print);
673}
674const QList<QKeySequence> &quit()
675{
676 return shortcut(id: Quit);
677}
678const QList<QKeySequence> &cut()
679{
680 return shortcut(id: Cut);
681}
682const QList<QKeySequence> &copy()
683{
684 return shortcut(id: Copy);
685}
686const QList<QKeySequence> &paste()
687{
688 return shortcut(id: Paste);
689}
690const QList<QKeySequence> &pasteSelection()
691{
692 return shortcut(id: PasteSelection);
693}
694const QList<QKeySequence> &deleteWordBack()
695{
696 return shortcut(id: DeleteWordBack);
697}
698const QList<QKeySequence> &deleteWordForward()
699{
700 return shortcut(id: DeleteWordForward);
701}
702const QList<QKeySequence> &undo()
703{
704 return shortcut(id: Undo);
705}
706const QList<QKeySequence> &redo()
707{
708 return shortcut(id: Redo);
709}
710const QList<QKeySequence> &find()
711{
712 return shortcut(id: Find);
713}
714const QList<QKeySequence> &findNext()
715{
716 return shortcut(id: FindNext);
717}
718const QList<QKeySequence> &findPrev()
719{
720 return shortcut(id: FindPrev);
721}
722const QList<QKeySequence> &replace()
723{
724 return shortcut(id: Replace);
725}
726const QList<QKeySequence> &home()
727{
728 return shortcut(id: Home);
729}
730const QList<QKeySequence> &begin()
731{
732 return shortcut(id: Begin);
733}
734const QList<QKeySequence> &end()
735{
736 return shortcut(id: End);
737}
738const QList<QKeySequence> &beginningOfLine()
739{
740 return shortcut(id: BeginningOfLine);
741}
742const QList<QKeySequence> &endOfLine()
743{
744 return shortcut(id: EndOfLine);
745}
746const QList<QKeySequence> &prior()
747{
748 return shortcut(id: Prior);
749}
750const QList<QKeySequence> &next()
751{
752 return shortcut(id: Next);
753}
754const QList<QKeySequence> &backwardWord()
755{
756 return shortcut(id: BackwardWord);
757}
758const QList<QKeySequence> &forwardWord()
759{
760 return shortcut(id: ForwardWord);
761}
762const QList<QKeySequence> &gotoLine()
763{
764 return shortcut(id: GotoLine);
765}
766const QList<QKeySequence> &addBookmark()
767{
768 return shortcut(id: AddBookmark);
769}
770const QList<QKeySequence> &tabNext()
771{
772 return shortcut(id: TabNext);
773}
774const QList<QKeySequence> &tabPrev()
775{
776 return shortcut(id: TabPrev);
777}
778const QList<QKeySequence> &fullScreen()
779{
780 return shortcut(id: FullScreen);
781}
782const QList<QKeySequence> &zoomIn()
783{
784 return shortcut(id: ZoomIn);
785}
786const QList<QKeySequence> &zoomOut()
787{
788 return shortcut(id: ZoomOut);
789}
790const QList<QKeySequence> &help()
791{
792 return shortcut(id: Help);
793}
794const QList<QKeySequence> &completion()
795{
796 return shortcut(id: TextCompletion);
797}
798const QList<QKeySequence> &prevCompletion()
799{
800 return shortcut(id: PrevCompletion);
801}
802const QList<QKeySequence> &nextCompletion()
803{
804 return shortcut(id: NextCompletion);
805}
806const QList<QKeySequence> &rotateUp()
807{
808 return shortcut(id: RotateUp);
809}
810const QList<QKeySequence> &rotateDown()
811{
812 return shortcut(id: RotateDown);
813}
814const QList<QKeySequence> &substringCompletion()
815{
816 return shortcut(id: SubstringCompletion);
817}
818const QList<QKeySequence> &whatsThis()
819{
820 return shortcut(id: WhatsThis);
821}
822const QList<QKeySequence> &reload()
823{
824 return shortcut(id: Reload);
825}
826const QList<QKeySequence> &selectAll()
827{
828 return shortcut(id: SelectAll);
829}
830const QList<QKeySequence> &up()
831{
832 return shortcut(id: Up);
833}
834const QList<QKeySequence> &back()
835{
836 return shortcut(id: Back);
837}
838const QList<QKeySequence> &forward()
839{
840 return shortcut(id: Forward);
841}
842const QList<QKeySequence> &showMenubar()
843{
844 return shortcut(id: ShowMenubar);
845}
846const QList<QKeySequence> &deleteFile()
847{
848 return shortcut(id: DeleteFile);
849}
850const QList<QKeySequence> &renameFile()
851{
852 return shortcut(id: RenameFile);
853}
854const QList<QKeySequence> &createFolder()
855{
856 return shortcut(id: CreateFolder);
857}
858const QList<QKeySequence> &moveToTrash()
859{
860 return shortcut(id: MoveToTrash);
861}
862const QList<QKeySequence> &preferences()
863{
864 return shortcut(id: Preferences);
865}
866const QList<QKeySequence> &showHideHiddenFiles()
867{
868 return shortcut(id: ShowHideHiddenFiles);
869}
870const QList<QKeySequence> &openMainMenu()
871{
872 return shortcut(id: OpenMainMenu);
873}
874const QList<QKeySequence> &openContextMenu()
875{
876 return shortcut(id: OpenContextMenu);
877}
878}
879

source code of kconfig/src/gui/kstandardshortcut.cpp