1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "qkeysequence.h" |
5 | #include "qkeysequence_p.h" |
6 | #include <qpa/qplatformtheme.h> |
7 | #include "private/qguiapplication_p.h" |
8 | |
9 | #include "qdebug.h" |
10 | #include <QtCore/qhashfunctions.h> |
11 | #ifndef QT_NO_DATASTREAM |
12 | # include "qdatastream.h" |
13 | #endif |
14 | #include "qvariant.h" |
15 | |
16 | #if defined(Q_OS_MACOS) |
17 | #include <QtCore/private/qcore_mac_p.h> |
18 | #endif |
19 | |
20 | #include <algorithm> |
21 | #include <q20algorithm.h> |
22 | |
23 | QT_BEGIN_NAMESPACE |
24 | |
25 | using namespace Qt::StringLiterals; |
26 | |
27 | #if defined(Q_OS_MACOS) || defined(Q_QDOC) |
28 | Q_CONSTINIT static bool qt_sequence_no_mnemonics = true; |
29 | struct MacSpecialKey { |
30 | int key; |
31 | ushort macSymbol; |
32 | }; |
33 | |
34 | // Unicode code points for the glyphs associated with these keys |
35 | // Defined by Carbon headers but not anywhere in Cocoa |
36 | static constexpr int kShiftUnicode = 0x21E7; |
37 | static constexpr int kControlUnicode = 0x2303; |
38 | static constexpr int kOptionUnicode = 0x2325; |
39 | static constexpr int kCommandUnicode = 0x2318; |
40 | |
41 | static constexpr MacSpecialKey entries[] = { |
42 | { Qt::Key_Escape, 0x238B }, |
43 | { Qt::Key_Tab, 0x21E5 }, |
44 | { Qt::Key_Backtab, 0x21E4 }, |
45 | { Qt::Key_Backspace, 0x232B }, |
46 | { Qt::Key_Return, 0x21B5 }, |
47 | { Qt::Key_Enter, 0x2324 }, |
48 | { Qt::Key_Delete, 0x2326 }, |
49 | { Qt::Key_Clear, 0x2327 }, |
50 | { Qt::Key_Home, 0x2196 }, |
51 | { Qt::Key_End, 0x2198 }, |
52 | { Qt::Key_Left, 0x2190 }, |
53 | { Qt::Key_Up, 0x2191 }, |
54 | { Qt::Key_Right, 0x2192 }, |
55 | { Qt::Key_Down, 0x2193 }, |
56 | { Qt::Key_PageUp, 0x21DE }, |
57 | { Qt::Key_PageDown, 0x21DF }, |
58 | { Qt::Key_Shift, kShiftUnicode }, |
59 | { Qt::Key_Control, kCommandUnicode }, |
60 | { Qt::Key_Meta, kControlUnicode }, |
61 | { Qt::Key_Alt, kOptionUnicode }, |
62 | { Qt::Key_CapsLock, 0x21EA }, |
63 | { Qt::Key_Eject, 0x23CF }, |
64 | }; |
65 | |
66 | static constexpr bool operator<(const MacSpecialKey &lhs, const MacSpecialKey &rhs) |
67 | { |
68 | return lhs.key < rhs.key; |
69 | } |
70 | |
71 | static constexpr bool operator<(const MacSpecialKey &lhs, int rhs) |
72 | { |
73 | return lhs.key < rhs; |
74 | } |
75 | |
76 | static constexpr bool operator<(int lhs, const MacSpecialKey &rhs) |
77 | { |
78 | return lhs < rhs.key; |
79 | } |
80 | |
81 | static_assert(q20::is_sorted(std::begin(entries), std::end(entries))); |
82 | |
83 | QChar qt_macSymbolForQtKey(int key) |
84 | { |
85 | const auto i = std::lower_bound(std::begin(entries), std::end(entries), key); |
86 | if (i == std::end(entries) || key < *i) |
87 | return QChar(); |
88 | ushort macSymbol = i->macSymbol; |
89 | if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta) |
90 | && (macSymbol == kControlUnicode || macSymbol == kCommandUnicode)) { |
91 | if (macSymbol == kControlUnicode) |
92 | macSymbol = kCommandUnicode; |
93 | else |
94 | macSymbol = kControlUnicode; |
95 | } |
96 | |
97 | return QChar(macSymbol); |
98 | } |
99 | |
100 | static int qtkeyForMacSymbol(const QChar ch) |
101 | { |
102 | const ushort unicode = ch.unicode(); |
103 | for (const MacSpecialKey &entry : entries) { |
104 | if (entry.macSymbol == unicode) { |
105 | int key = entry.key; |
106 | if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta) |
107 | && (unicode == kControlUnicode || unicode == kCommandUnicode)) { |
108 | if (unicode == kControlUnicode) |
109 | key = Qt::Key_Control; |
110 | else |
111 | key = Qt::Key_Meta; |
112 | } |
113 | return key; |
114 | } |
115 | } |
116 | return -1; |
117 | } |
118 | |
119 | #else |
120 | Q_CONSTINIT static bool qt_sequence_no_mnemonics = false; |
121 | #endif |
122 | |
123 | /*! |
124 | \fn void qt_set_sequence_auto_mnemonic(bool b) |
125 | \relates QKeySequence |
126 | |
127 | Specifies whether mnemonics for menu items, labels, etc., should |
128 | be honored or not. On Windows and X11, this feature is |
129 | on by default; on \macos, it is off. When this feature is off |
130 | (that is, when \a b is false), QKeySequence::mnemonic() always |
131 | returns an empty string. |
132 | |
133 | \note This function is not declared in any of Qt's header files. |
134 | To use it in your application, declare the function prototype |
135 | before calling it. |
136 | |
137 | \sa QShortcut |
138 | */ |
139 | void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemonics = !b; } |
140 | |
141 | /*! |
142 | \class QKeySequence |
143 | \brief The QKeySequence class encapsulates a key sequence as used |
144 | by shortcuts. |
145 | |
146 | \ingroup shared |
147 | \inmodule QtGui |
148 | |
149 | |
150 | In its most common form, a key sequence describes a combination of |
151 | keys that must be used together to perform some action. Key sequences |
152 | are used with QAction objects to specify which keyboard shortcuts can |
153 | be used to trigger actions. |
154 | |
155 | Key sequences can be constructed for use as keyboard shortcuts in |
156 | three different ways: |
157 | |
158 | \list |
159 | \li For standard shortcuts, a \l{QKeySequence::StandardKey}{standard key} |
160 | can be used to request the platform-specific key sequence associated |
161 | with each shortcut. |
162 | \li For custom shortcuts, human-readable strings such as "Ctrl+X" can |
163 | be used, and these can be translated into the appropriate shortcuts |
164 | for users of different languages. Translations are made in the |
165 | "QShortcut" context. |
166 | \li For hard-coded shortcuts, integer key codes can be specified with |
167 | a combination of values defined by the Qt::Key and Qt::KeyboardModifier |
168 | enum values. Each key code consists of a single Qt::Key value and zero |
169 | or more modifiers, such as Qt::ShiftModifier, Qt::ControlModifier, |
170 | Qt::AltModifier and Qt::MetaModifier. |
171 | \endlist |
172 | |
173 | For example, \uicontrol{Ctrl P} might be a sequence used as a shortcut for |
174 | printing a document, and can be specified in any of the following |
175 | ways: |
176 | |
177 | \snippet code/src_gui_kernel_qkeysequence.cpp 0 |
178 | |
179 | Note that, for letters, the case used in the specification string |
180 | does not matter. In the above examples, the user does not need to |
181 | hold down the \uicontrol{Shift} key to activate a shortcut specified |
182 | with "Ctrl+P". However, for other keys, the use of \uicontrol{Shift} as |
183 | an unspecified extra modifier key can lead to confusion for users |
184 | of an application whose keyboards have different layouts to those |
185 | used by the developers. See the \l{Keyboard Layout Issues} section |
186 | below for more details. |
187 | |
188 | It is preferable to use standard shortcuts where possible. |
189 | When creating key sequences for non-standard shortcuts, you should use |
190 | human-readable strings in preference to hard-coded integer values. |
191 | |
192 | QKeySequence objects can be cast to a QString to obtain a human-readable |
193 | translated version of the sequence. Similarly, the toString() function |
194 | produces human-readable strings for use in menus. On \macos, the |
195 | appropriate symbols are used to describe keyboard shortcuts using special |
196 | keys on the Macintosh keyboard. |
197 | |
198 | An alternative way to specify hard-coded key codes is to use the Unicode |
199 | code point of the character; for example, 'A' gives the same key sequence |
200 | as Qt::Key_A. |
201 | |
202 | \note On \macos, references to "Ctrl", Qt::CTRL, Qt::Key_Control |
203 | and Qt::ControlModifier correspond to the \uicontrol Command keys on the |
204 | Macintosh keyboard, and references to "Meta", Qt::META, Qt::Key_Meta and |
205 | Qt::MetaModifier correspond to the \uicontrol Control keys. Developers on |
206 | \macos can use the same shortcut descriptions across all platforms, |
207 | and their applications will automatically work as expected on \macos. |
208 | |
209 | \section1 Standard Shortcuts |
210 | |
211 | QKeySequence defines many \l{QKeySequence::StandardKey} {standard |
212 | keyboard shortcuts} to reduce the amount of effort required when |
213 | setting up actions in a typical application. The table below shows |
214 | some common key sequences that are often used for these standard |
215 | shortcuts by applications on four widely-used platforms. Note |
216 | that on \macos, the \uicontrol Ctrl value corresponds to the \uicontrol |
217 | Command keys on the Macintosh keyboard, and the \uicontrol Meta value |
218 | corresponds to the \uicontrol Control keys. |
219 | |
220 | \table |
221 | \header \li StandardKey \li Windows \li \macos \li KDE Plasma \li GNOME |
222 | \row \li HelpContents \li F1 \li Ctrl+? \li F1 \li F1 |
223 | \row \li WhatsThis \li Shift+F1 \li Shift+F1 \li Shift+F1 \li Shift+F1 |
224 | \row \li Open \li Ctrl+O \li Ctrl+O \li Ctrl+O \li Ctrl+O |
225 | \row \li Close \li Ctrl+F4, Ctrl+W \li Ctrl+W, Ctrl+F4 \li Ctrl+W \li Ctrl+W |
226 | \row \li Save \li Ctrl+S \li Ctrl+S \li Ctrl+S \li Ctrl+S |
227 | \row \li Quit \li \li Ctrl+Q \li Ctrl+Q \li Ctrl+Q |
228 | \row \li SaveAs \li \li Ctrl+Shift+S \li \li Ctrl+Shift+S |
229 | \row \li New \li Ctrl+N \li Ctrl+N \li Ctrl+N \li Ctrl+N |
230 | \row \li Delete \li Del \li Del, Meta+D \li Del, Ctrl+D \li Del, Ctrl+D |
231 | \row \li Cut \li Ctrl+X, Shift+Del \li Ctrl+X, Meta+K \li Ctrl+X, F20, Shift+Del \li Ctrl+X, F20, Shift+Del |
232 | \row \li Copy \li Ctrl+C, Ctrl+Ins \li Ctrl+C \li Ctrl+C, F16, Ctrl+Ins \li Ctrl+C, F16, Ctrl+Ins |
233 | \row \li Paste \li Ctrl+V, Shift+Ins \li Ctrl+V, Meta+Y \li Ctrl+V, F18, Shift+Ins \li Ctrl+V, F18, Shift+Ins |
234 | \row \li Preferences \li \li Ctrl+, \li \li |
235 | \row \li Undo \li Ctrl+Z, Alt+Backspace \li Ctrl+Z \li Ctrl+Z, F14 \li Ctrl+Z, F14 |
236 | \row \li Redo \li Ctrl+Y, Shift+Ctrl+Z, Alt+Shift+Backspace \li Ctrl+Shift+Z \li Ctrl+Shift+Z \li Ctrl+Shift+Z |
237 | \row \li Back \li Alt+Left, Backspace \li Ctrl+[ \li Alt+Left \li Alt+Left |
238 | \row \li Forward \li Alt+Right, Shift+Backspace \li Ctrl+] \li Alt+Right \li Alt+Right |
239 | \row \li Refresh \li F5 \li F5 \li F5 \li Ctrl+R, F5 |
240 | \row \li ZoomIn \li Ctrl+Plus \li Ctrl+Plus \li Ctrl+Plus \li Ctrl+Plus |
241 | \row \li ZoomOut \li Ctrl+Minus \li Ctrl+Minus \li Ctrl+Minus \li Ctrl+Minus |
242 | \row \li FullScreen \li F11, Alt+Enter \li Ctrl+Meta+F \li F11, Ctrl+Shift+F \li Ctrl+F11 |
243 | \row \li Print \li Ctrl+P \li Ctrl+P \li Ctrl+P \li Ctrl+P |
244 | \row \li AddTab \li Ctrl+T \li Ctrl+T \li Ctrl+Shift+N, Ctrl+T \li Ctrl+T |
245 | \row \li NextChild \li Ctrl+Tab, Forward, Ctrl+F6 \li Ctrl+}, Forward, Ctrl+Tab \li Ctrl+Tab, Forward, Ctrl+Comma \li Ctrl+Tab, Forward |
246 | \row \li PreviousChild \li Ctrl+Shift+Tab, Back, Ctrl+Shift+F6 \li Ctrl+{, Back, Ctrl+Shift+Tab \li Ctrl+Shift+Tab, Back, Ctrl+Period \li Ctrl+Shift+Tab, Back |
247 | \row \li Find \li Ctrl+F \li Ctrl+F \li Ctrl+F \li Ctrl+F |
248 | \row \li FindNext \li F3, Ctrl+G \li Ctrl+G \li F3 \li Ctrl+G, F3 |
249 | \row \li FindPrevious \li Shift+F3, Ctrl+Shift+G \li Ctrl+Shift+G \li Shift+F3 \li Ctrl+Shift+G, Shift+F3 |
250 | \row \li Replace \li Ctrl+H \li (none) \li Ctrl+R \li Ctrl+H |
251 | \row \li SelectAll \li Ctrl+A \li Ctrl+A \li Ctrl+A \li Ctrl+A |
252 | \row \li Deselect \li \li \li Ctrl+Shift+A \li Ctrl+Shift+A |
253 | \row \li Bold \li Ctrl+B \li Ctrl+B \li Ctrl+B \li Ctrl+B |
254 | \row \li Italic \li Ctrl+I \li Ctrl+I \li Ctrl+I \li Ctrl+I |
255 | \row \li Underline \li Ctrl+U \li Ctrl+U \li Ctrl+U \li Ctrl+U |
256 | \row \li MoveToNextChar \li Right \li Right, Meta+F \li Right \li Right |
257 | \row \li MoveToPreviousChar \li Left \li Left, Meta+B \li Left \li Left |
258 | \row \li MoveToNextWord \li Ctrl+Right \li Alt+Right \li Ctrl+Right \li Ctrl+Right |
259 | \row \li MoveToPreviousWord \li Ctrl+Left \li Alt+Left \li Ctrl+Left \li Ctrl+Left |
260 | \row \li MoveToNextLine \li Down \li Down, Meta+N \li Down \li Down |
261 | \row \li MoveToPreviousLine \li Up \li Up, Meta+P \li Up \li Up |
262 | \row \li MoveToNextPage \li PgDown \li PgDown, Alt+PgDown, Meta+Down, Meta+PgDown, Meta+V \li PgDown \li PgDown |
263 | \row \li MoveToPreviousPage \li PgUp \li PgUp, Alt+PgUp, Meta+Up, Meta+PgUp \li PgUp \li PgUp |
264 | \row \li MoveToStartOfLine \li Home \li Ctrl+Left, Meta+Left \li Home \li Home |
265 | \row \li MoveToEndOfLine \li End \li Ctrl+Right, Meta+Right \li End, Ctrl+E \li End, Ctrl+E |
266 | \row \li MoveToStartOfBlock \li (none) \li Alt+Up, Meta+A \li (none) \li (none) |
267 | \row \li MoveToEndOfBlock \li (none) \li Alt+Down, Meta+E \li (none) \li (none) |
268 | \row \li MoveToStartOfDocument\li Ctrl+Home \li Ctrl+Up, Home \li Ctrl+Home \li Ctrl+Home |
269 | \row \li MoveToEndOfDocument \li Ctrl+End \li Ctrl+Down, End \li Ctrl+End \li Ctrl+End |
270 | \row \li SelectNextChar \li Shift+Right \li Shift+Right \li Shift+Right \li Shift+Right |
271 | \row \li SelectPreviousChar \li Shift+Left \li Shift+Left \li Shift+Left \li Shift+Left |
272 | \row \li SelectNextWord \li Ctrl+Shift+Right \li Alt+Shift+Right \li Ctrl+Shift+Right \li Ctrl+Shift+Right |
273 | \row \li SelectPreviousWord \li Ctrl+Shift+Left \li Alt+Shift+Left \li Ctrl+Shift+Left \li Ctrl+Shift+Left |
274 | \row \li SelectNextLine \li Shift+Down \li Shift+Down \li Shift+Down \li Shift+Down |
275 | \row \li SelectPreviousLine \li Shift+Up \li Shift+Up \li Shift+Up \li Shift+Up |
276 | \row \li SelectNextPage \li Shift+PgDown \li Shift+PgDown \li Shift+PgDown \li Shift+PgDown |
277 | \row \li SelectPreviousPage \li Shift+PgUp \li Shift+PgUp \li Shift+PgUp \li Shift+PgUp |
278 | \row \li SelectStartOfLine \li Shift+Home \li Ctrl+Shift+Left \li Shift+Home \li Shift+Home |
279 | \row \li SelectEndOfLine \li Shift+End \li Ctrl+Shift+Right \li Shift+End \li Shift+End |
280 | \row \li SelectStartOfBlock \li (none) \li Alt+Shift+Up, Meta+Shift+A \li (none) \li (none) |
281 | \row \li SelectEndOfBlock \li (none) \li Alt+Shift+Down, Meta+Shift+E \li (none) \li (none) |
282 | \row \li SelectStartOfDocument\li Ctrl+Shift+Home \li Ctrl+Shift+Up, Shift+Home \li Ctrl+Shift+Home\li Ctrl+Shift+Home |
283 | \row \li SelectEndOfDocument \li Ctrl+Shift+End \li Ctrl+Shift+Down, Shift+End \li Ctrl+Shift+End \li Ctrl+Shift+End |
284 | \row \li DeleteStartOfWord \li Ctrl+Backspace \li Alt+Backspace \li Ctrl+Backspace \li Ctrl+Backspace |
285 | \row \li DeleteEndOfWord \li Ctrl+Del \li (none) \li Ctrl+Del \li Ctrl+Del |
286 | \row \li DeleteEndOfLine \li (none) \li (none) \li Ctrl+K \li Ctrl+K |
287 | \row \li DeleteCompleteLine \li (none) \li (none) \li Ctrl+U \li Ctrl+U |
288 | \row \li InsertParagraphSeparator \li Enter \li Enter \li Enter \li Enter |
289 | \row \li InsertLineSeparator \li Shift+Enter \li Meta+Enter, Meta+O \li Shift+Enter \li Shift+Enter |
290 | \row \li Backspace \li (none) \li Meta+H \li (none) \li (none) |
291 | \row \li Cancel \li Escape \li Escape, Ctrl+. \li Escape \li Escape |
292 | \endtable |
293 | |
294 | Note that, since the key sequences used for the standard shortcuts differ |
295 | between platforms, you still need to test your shortcuts on each platform |
296 | to ensure that you do not unintentionally assign the same key sequence to |
297 | many actions. |
298 | |
299 | \section1 Keyboard Layout Issues |
300 | |
301 | Many key sequence specifications are chosen by developers based on the |
302 | layout of certain types of keyboard, rather than choosing keys that |
303 | represent the first letter of an action's name, such as \uicontrol{Ctrl S} |
304 | ("Ctrl+S") or \uicontrol{Ctrl C} ("Ctrl+C"). |
305 | Additionally, because certain symbols can only be entered with the |
306 | help of modifier keys on certain keyboard layouts, key sequences intended |
307 | for use with one keyboard layout may map to a different key, map to no |
308 | keys at all, or require an additional modifier key to be used on |
309 | different keyboard layouts. |
310 | |
311 | For example, the shortcuts, \uicontrol{Ctrl plus} and \uicontrol{Ctrl minus}, are often |
312 | used as shortcuts for zoom operations in graphics applications, and these |
313 | may be specified as "Ctrl++" and "Ctrl+-" respectively. However, the way |
314 | these shortcuts are specified and interpreted depends on the keyboard layout. |
315 | Users of Norwegian keyboards will note that the \uicontrol{+} and \uicontrol{-} keys |
316 | are not adjacent on the keyboard, but will still be able to activate both |
317 | shortcuts without needing to press the \uicontrol{Shift} key. However, users |
318 | with British keyboards will need to hold down the \uicontrol{Shift} key |
319 | to enter the \uicontrol{+} symbol, making the shortcut effectively the same as |
320 | "Ctrl+Shift+=". |
321 | |
322 | Although some developers might resort to fully specifying all the modifiers |
323 | they use on their keyboards to activate a shortcut, this will also result |
324 | in unexpected behavior for users of different keyboard layouts. |
325 | |
326 | For example, a developer using a British keyboard may decide to specify |
327 | "Ctrl+Shift+=" as the key sequence in order to create a shortcut that |
328 | coincidentally behaves in the same way as \uicontrol{Ctrl plus}. However, the |
329 | \uicontrol{=} key needs to be accessed using the \uicontrol{Shift} key on Norwegian |
330 | keyboard, making the required shortcut effectively \uicontrol{Ctrl Shift Shift =} |
331 | (an impossible key combination). |
332 | |
333 | As a result, both human-readable strings and hard-coded key codes |
334 | can both be problematic to use when specifying a key sequence that |
335 | can be used on a variety of different keyboard layouts. Only the |
336 | use of \l{QKeySequence::StandardKey} {standard shortcuts} |
337 | guarantees that the user will be able to use the shortcuts that |
338 | the developer intended. |
339 | |
340 | Despite this, we can address this issue by ensuring that human-readable |
341 | strings are used, making it possible for translations of key sequences to |
342 | be made for users of different languages. This approach will be successful |
343 | for users whose keyboards have the most typical layout for the language |
344 | they are using. |
345 | |
346 | \section1 GNU Emacs Style Key Sequences |
347 | |
348 | Key sequences similar to those used in \l{http://www.gnu.org/software/emacs/}{GNU Emacs}, allowing up to four |
349 | key codes, can be created by using the multiple argument constructor, |
350 | or by passing a human-readable string of comma-separated key sequences. |
351 | |
352 | For example, the key sequence, \uicontrol{Ctrl X} followed by \uicontrol{Ctrl C}, can |
353 | be specified using either of the following ways: |
354 | |
355 | \snippet code/src_gui_kernel_qkeysequence.cpp 1 |
356 | |
357 | \warning A QApplication instance must have been constructed before a |
358 | QKeySequence is created; otherwise, your application may crash. |
359 | |
360 | \sa QShortcut |
361 | */ |
362 | |
363 | /*! |
364 | \enum QKeySequence::SequenceMatch |
365 | |
366 | \value NoMatch The key sequences are different; not even partially |
367 | matching. |
368 | \value PartialMatch The key sequences match partially, but are not |
369 | the same. |
370 | \value ExactMatch The key sequences are the same. |
371 | */ |
372 | |
373 | /*! |
374 | \enum QKeySequence::SequenceFormat |
375 | |
376 | \value NativeText The key sequence as a platform specific string. |
377 | This means that it will be shown translated and on the Mac it will |
378 | resemble a key sequence from the menu bar. This enum is best used when you |
379 | want to display the string to the user. |
380 | |
381 | \value PortableText The key sequence is given in a "portable" format, |
382 | suitable for reading and writing to a file. In many cases, it will look |
383 | similar to the native text on Windows and X11. |
384 | */ |
385 | |
386 | static constexpr struct { |
387 | int key; |
388 | const char name[25]; |
389 | } keyname[] = { |
390 | //: This and all following "incomprehensible" strings in QShortcut context |
391 | //: are key names. Please use the localized names appearing on actual |
392 | //: keyboards or whatever is commonly used. |
393 | { .key: Qt::Key_Space, QT_TRANSLATE_NOOP("QShortcut" , "Space" ) }, |
394 | { .key: Qt::Key_Escape, QT_TRANSLATE_NOOP("QShortcut" , "Esc" ) }, |
395 | { .key: Qt::Key_Tab, QT_TRANSLATE_NOOP("QShortcut" , "Tab" ) }, |
396 | { .key: Qt::Key_Backtab, QT_TRANSLATE_NOOP("QShortcut" , "Backtab" ) }, |
397 | { .key: Qt::Key_Backspace, QT_TRANSLATE_NOOP("QShortcut" , "Backspace" ) }, |
398 | { .key: Qt::Key_Return, QT_TRANSLATE_NOOP("QShortcut" , "Return" ) }, |
399 | { .key: Qt::Key_Enter, QT_TRANSLATE_NOOP("QShortcut" , "Enter" ) }, |
400 | { .key: Qt::Key_Insert, QT_TRANSLATE_NOOP("QShortcut" , "Ins" ) }, |
401 | { .key: Qt::Key_Delete, QT_TRANSLATE_NOOP("QShortcut" , "Del" ) }, |
402 | { .key: Qt::Key_Pause, QT_TRANSLATE_NOOP("QShortcut" , "Pause" ) }, |
403 | { .key: Qt::Key_Print, QT_TRANSLATE_NOOP("QShortcut" , "Print" ) }, |
404 | { .key: Qt::Key_SysReq, QT_TRANSLATE_NOOP("QShortcut" , "SysReq" ) }, |
405 | { .key: Qt::Key_Home, QT_TRANSLATE_NOOP("QShortcut" , "Home" ) }, |
406 | { .key: Qt::Key_End, QT_TRANSLATE_NOOP("QShortcut" , "End" ) }, |
407 | { .key: Qt::Key_Left, QT_TRANSLATE_NOOP("QShortcut" , "Left" ) }, |
408 | { .key: Qt::Key_Up, QT_TRANSLATE_NOOP("QShortcut" , "Up" ) }, |
409 | { .key: Qt::Key_Right, QT_TRANSLATE_NOOP("QShortcut" , "Right" ) }, |
410 | { .key: Qt::Key_Down, QT_TRANSLATE_NOOP("QShortcut" , "Down" ) }, |
411 | { .key: Qt::Key_PageUp, QT_TRANSLATE_NOOP("QShortcut" , "PgUp" ) }, |
412 | { .key: Qt::Key_PageDown, QT_TRANSLATE_NOOP("QShortcut" , "PgDown" ) }, |
413 | { .key: Qt::Key_CapsLock, QT_TRANSLATE_NOOP("QShortcut" , "CapsLock" ) }, |
414 | { .key: Qt::Key_NumLock, QT_TRANSLATE_NOOP("QShortcut" , "NumLock" ) }, |
415 | { .key: Qt::Key_ScrollLock, QT_TRANSLATE_NOOP("QShortcut" , "ScrollLock" ) }, |
416 | { .key: Qt::Key_Menu, QT_TRANSLATE_NOOP("QShortcut" , "Menu" ) }, |
417 | { .key: Qt::Key_Help, QT_TRANSLATE_NOOP("QShortcut" , "Help" ) }, |
418 | |
419 | // Special keys |
420 | // Includes multimedia, launcher, lan keys ( bluetooth, wireless ) |
421 | // window navigation |
422 | { .key: Qt::Key_Back, QT_TRANSLATE_NOOP("QShortcut" , "Back" ) }, |
423 | { .key: Qt::Key_Forward, QT_TRANSLATE_NOOP("QShortcut" , "Forward" ) }, |
424 | { .key: Qt::Key_Stop, QT_TRANSLATE_NOOP("QShortcut" , "Stop" ) }, |
425 | { .key: Qt::Key_Refresh, QT_TRANSLATE_NOOP("QShortcut" , "Refresh" ) }, |
426 | { .key: Qt::Key_VolumeDown, QT_TRANSLATE_NOOP("QShortcut" , "Volume Down" ) }, |
427 | { .key: Qt::Key_VolumeMute, QT_TRANSLATE_NOOP("QShortcut" , "Volume Mute" ) }, |
428 | { .key: Qt::Key_VolumeUp, QT_TRANSLATE_NOOP("QShortcut" , "Volume Up" ) }, |
429 | { .key: Qt::Key_BassBoost, QT_TRANSLATE_NOOP("QShortcut" , "Bass Boost" ) }, |
430 | { .key: Qt::Key_BassUp, QT_TRANSLATE_NOOP("QShortcut" , "Bass Up" ) }, |
431 | { .key: Qt::Key_BassDown, QT_TRANSLATE_NOOP("QShortcut" , "Bass Down" ) }, |
432 | { .key: Qt::Key_TrebleUp, QT_TRANSLATE_NOOP("QShortcut" , "Treble Up" ) }, |
433 | { .key: Qt::Key_TrebleDown, QT_TRANSLATE_NOOP("QShortcut" , "Treble Down" ) }, |
434 | { .key: Qt::Key_MediaPlay, QT_TRANSLATE_NOOP("QShortcut" , "Media Play" ) }, |
435 | { .key: Qt::Key_MediaStop, QT_TRANSLATE_NOOP("QShortcut" , "Media Stop" ) }, |
436 | { .key: Qt::Key_MediaPrevious, QT_TRANSLATE_NOOP("QShortcut" , "Media Previous" ) }, |
437 | { .key: Qt::Key_MediaNext, QT_TRANSLATE_NOOP("QShortcut" , "Media Next" ) }, |
438 | { .key: Qt::Key_MediaRecord, QT_TRANSLATE_NOOP("QShortcut" , "Media Record" ) }, |
439 | //: Media player pause button |
440 | { .key: Qt::Key_MediaPause, QT_TRANSLATE_NOOP("QShortcut" , "Media Pause" ) }, |
441 | //: Media player button to toggle between playing and paused |
442 | { .key: Qt::Key_MediaTogglePlayPause, QT_TRANSLATE_NOOP("QShortcut" , "Toggle Media Play/Pause" ) }, |
443 | { .key: Qt::Key_HomePage, QT_TRANSLATE_NOOP("QShortcut" , "Home Page" ) }, |
444 | { .key: Qt::Key_Favorites, QT_TRANSLATE_NOOP("QShortcut" , "Favorites" ) }, |
445 | { .key: Qt::Key_Search, QT_TRANSLATE_NOOP("QShortcut" , "Search" ) }, |
446 | { .key: Qt::Key_Standby, QT_TRANSLATE_NOOP("QShortcut" , "Standby" ) }, |
447 | { .key: Qt::Key_OpenUrl, QT_TRANSLATE_NOOP("QShortcut" , "Open URL" ) }, |
448 | { .key: Qt::Key_LaunchMail, QT_TRANSLATE_NOOP("QShortcut" , "Launch Mail" ) }, |
449 | { .key: Qt::Key_LaunchMedia, QT_TRANSLATE_NOOP("QShortcut" , "Launch Media" ) }, |
450 | { .key: Qt::Key_Launch0, QT_TRANSLATE_NOOP("QShortcut" , "Launch (0)" ) }, |
451 | { .key: Qt::Key_Launch1, QT_TRANSLATE_NOOP("QShortcut" , "Launch (1)" ) }, |
452 | { .key: Qt::Key_Launch2, QT_TRANSLATE_NOOP("QShortcut" , "Launch (2)" ) }, |
453 | { .key: Qt::Key_Launch3, QT_TRANSLATE_NOOP("QShortcut" , "Launch (3)" ) }, |
454 | { .key: Qt::Key_Launch4, QT_TRANSLATE_NOOP("QShortcut" , "Launch (4)" ) }, |
455 | { .key: Qt::Key_Launch5, QT_TRANSLATE_NOOP("QShortcut" , "Launch (5)" ) }, |
456 | { .key: Qt::Key_Launch6, QT_TRANSLATE_NOOP("QShortcut" , "Launch (6)" ) }, |
457 | { .key: Qt::Key_Launch7, QT_TRANSLATE_NOOP("QShortcut" , "Launch (7)" ) }, |
458 | { .key: Qt::Key_Launch8, QT_TRANSLATE_NOOP("QShortcut" , "Launch (8)" ) }, |
459 | { .key: Qt::Key_Launch9, QT_TRANSLATE_NOOP("QShortcut" , "Launch (9)" ) }, |
460 | { .key: Qt::Key_LaunchA, QT_TRANSLATE_NOOP("QShortcut" , "Launch (A)" ) }, |
461 | { .key: Qt::Key_LaunchB, QT_TRANSLATE_NOOP("QShortcut" , "Launch (B)" ) }, |
462 | { .key: Qt::Key_LaunchC, QT_TRANSLATE_NOOP("QShortcut" , "Launch (C)" ) }, |
463 | { .key: Qt::Key_LaunchD, QT_TRANSLATE_NOOP("QShortcut" , "Launch (D)" ) }, |
464 | { .key: Qt::Key_LaunchE, QT_TRANSLATE_NOOP("QShortcut" , "Launch (E)" ) }, |
465 | { .key: Qt::Key_LaunchF, QT_TRANSLATE_NOOP("QShortcut" , "Launch (F)" ) }, |
466 | { .key: Qt::Key_LaunchG, QT_TRANSLATE_NOOP("QShortcut" , "Launch (G)" ) }, |
467 | { .key: Qt::Key_LaunchH, QT_TRANSLATE_NOOP("QShortcut" , "Launch (H)" ) }, |
468 | { .key: Qt::Key_MonBrightnessUp, QT_TRANSLATE_NOOP("QShortcut" , "Monitor Brightness Up" ) }, |
469 | { .key: Qt::Key_MonBrightnessDown, QT_TRANSLATE_NOOP("QShortcut" , "Monitor Brightness Down" ) }, |
470 | { .key: Qt::Key_KeyboardLightOnOff, QT_TRANSLATE_NOOP("QShortcut" , "Keyboard Light On/Off" ) }, |
471 | { .key: Qt::Key_KeyboardBrightnessUp, QT_TRANSLATE_NOOP("QShortcut" , "Keyboard Brightness Up" ) }, |
472 | { .key: Qt::Key_KeyboardBrightnessDown, QT_TRANSLATE_NOOP("QShortcut" , "Keyboard Brightness Down" ) }, |
473 | { .key: Qt::Key_PowerOff, QT_TRANSLATE_NOOP("QShortcut" , "Power Off" ) }, |
474 | { .key: Qt::Key_WakeUp, QT_TRANSLATE_NOOP("QShortcut" , "Wake Up" ) }, |
475 | { .key: Qt::Key_Eject, QT_TRANSLATE_NOOP("QShortcut" , "Eject" ) }, |
476 | { .key: Qt::Key_ScreenSaver, QT_TRANSLATE_NOOP("QShortcut" , "Screensaver" ) }, |
477 | { .key: Qt::Key_WWW, QT_TRANSLATE_NOOP("QShortcut" , "WWW" ) }, |
478 | { .key: Qt::Key_Sleep, QT_TRANSLATE_NOOP("QShortcut" , "Sleep" ) }, |
479 | { .key: Qt::Key_LightBulb, QT_TRANSLATE_NOOP("QShortcut" , "LightBulb" ) }, |
480 | { .key: Qt::Key_Shop, QT_TRANSLATE_NOOP("QShortcut" , "Shop" ) }, |
481 | { .key: Qt::Key_History, QT_TRANSLATE_NOOP("QShortcut" , "History" ) }, |
482 | { .key: Qt::Key_AddFavorite, QT_TRANSLATE_NOOP("QShortcut" , "Add Favorite" ) }, |
483 | { .key: Qt::Key_HotLinks, QT_TRANSLATE_NOOP("QShortcut" , "Hot Links" ) }, |
484 | { .key: Qt::Key_BrightnessAdjust, QT_TRANSLATE_NOOP("QShortcut" , "Adjust Brightness" ) }, |
485 | { .key: Qt::Key_Finance, QT_TRANSLATE_NOOP("QShortcut" , "Finance" ) }, |
486 | { .key: Qt::Key_Community, QT_TRANSLATE_NOOP("QShortcut" , "Community" ) }, |
487 | { .key: Qt::Key_AudioRewind, QT_TRANSLATE_NOOP("QShortcut" , "Media Rewind" ) }, |
488 | { .key: Qt::Key_BackForward, QT_TRANSLATE_NOOP("QShortcut" , "Back Forward" ) }, |
489 | { .key: Qt::Key_ApplicationLeft, QT_TRANSLATE_NOOP("QShortcut" , "Application Left" ) }, |
490 | { .key: Qt::Key_ApplicationRight, QT_TRANSLATE_NOOP("QShortcut" , "Application Right" ) }, |
491 | { .key: Qt::Key_Book, QT_TRANSLATE_NOOP("QShortcut" , "Book" ) }, |
492 | { .key: Qt::Key_CD, QT_TRANSLATE_NOOP("QShortcut" , "CD" ) }, |
493 | { .key: Qt::Key_Calculator, QT_TRANSLATE_NOOP("QShortcut" , "Calculator" ) }, |
494 | { .key: Qt::Key_Calendar, QT_TRANSLATE_NOOP("QShortcut" , "Calendar" ) }, |
495 | { .key: Qt::Key_Clear, QT_TRANSLATE_NOOP("QShortcut" , "Clear" ) }, |
496 | { .key: Qt::Key_ClearGrab, QT_TRANSLATE_NOOP("QShortcut" , "Clear Grab" ) }, |
497 | { .key: Qt::Key_Close, QT_TRANSLATE_NOOP("QShortcut" , "Close" ) }, |
498 | { .key: Qt::Key_ContrastAdjust, QT_TRANSLATE_NOOP("QShortcut" , "Adjust contrast" ) }, |
499 | { .key: Qt::Key_Copy, QT_TRANSLATE_NOOP("QShortcut" , "Copy" ) }, |
500 | { .key: Qt::Key_Cut, QT_TRANSLATE_NOOP("QShortcut" , "Cut" ) }, |
501 | { .key: Qt::Key_Display, QT_TRANSLATE_NOOP("QShortcut" , "Display" ) }, |
502 | { .key: Qt::Key_DOS, QT_TRANSLATE_NOOP("QShortcut" , "DOS" ) }, |
503 | { .key: Qt::Key_Documents, QT_TRANSLATE_NOOP("QShortcut" , "Documents" ) }, |
504 | { .key: Qt::Key_Excel, QT_TRANSLATE_NOOP("QShortcut" , "Spreadsheet" ) }, |
505 | { .key: Qt::Key_Explorer, QT_TRANSLATE_NOOP("QShortcut" , "Browser" ) }, |
506 | { .key: Qt::Key_Game, QT_TRANSLATE_NOOP("QShortcut" , "Game" ) }, |
507 | { .key: Qt::Key_Go, QT_TRANSLATE_NOOP("QShortcut" , "Go" ) }, |
508 | { .key: Qt::Key_iTouch, QT_TRANSLATE_NOOP("QShortcut" , "iTouch" ) }, |
509 | { .key: Qt::Key_LogOff, QT_TRANSLATE_NOOP("QShortcut" , "Logoff" ) }, |
510 | { .key: Qt::Key_Market, QT_TRANSLATE_NOOP("QShortcut" , "Market" ) }, |
511 | { .key: Qt::Key_Meeting, QT_TRANSLATE_NOOP("QShortcut" , "Meeting" ) }, |
512 | { .key: Qt::Key_Memo, QT_TRANSLATE_NOOP("QShortcut" , "Memo" ) }, |
513 | { .key: Qt::Key_MenuKB, QT_TRANSLATE_NOOP("QShortcut" , "Keyboard Menu" ) }, |
514 | { .key: Qt::Key_MenuPB, QT_TRANSLATE_NOOP("QShortcut" , "Menu PB" ) }, |
515 | { .key: Qt::Key_MySites, QT_TRANSLATE_NOOP("QShortcut" , "My Sites" ) }, |
516 | { .key: Qt::Key_News, QT_TRANSLATE_NOOP("QShortcut" , "News" ) }, |
517 | { .key: Qt::Key_OfficeHome, QT_TRANSLATE_NOOP("QShortcut" , "Home Office" ) }, |
518 | { .key: Qt::Key_Option, QT_TRANSLATE_NOOP("QShortcut" , "Option" ) }, |
519 | { .key: Qt::Key_Paste, QT_TRANSLATE_NOOP("QShortcut" , "Paste" ) }, |
520 | { .key: Qt::Key_Phone, QT_TRANSLATE_NOOP("QShortcut" , "Phone" ) }, |
521 | { .key: Qt::Key_Reply, QT_TRANSLATE_NOOP("QShortcut" , "Reply" ) }, |
522 | { .key: Qt::Key_Reload, QT_TRANSLATE_NOOP("QShortcut" , "Reload" ) }, |
523 | { .key: Qt::Key_RotateWindows, QT_TRANSLATE_NOOP("QShortcut" , "Rotate Windows" ) }, |
524 | { .key: Qt::Key_RotationPB, QT_TRANSLATE_NOOP("QShortcut" , "Rotation PB" ) }, |
525 | { .key: Qt::Key_RotationKB, QT_TRANSLATE_NOOP("QShortcut" , "Rotation KB" ) }, |
526 | { .key: Qt::Key_Save, QT_TRANSLATE_NOOP("QShortcut" , "Save" ) }, |
527 | { .key: Qt::Key_Send, QT_TRANSLATE_NOOP("QShortcut" , "Send" ) }, |
528 | { .key: Qt::Key_Spell, QT_TRANSLATE_NOOP("QShortcut" , "Spellchecker" ) }, |
529 | { .key: Qt::Key_SplitScreen, QT_TRANSLATE_NOOP("QShortcut" , "Split Screen" ) }, |
530 | { .key: Qt::Key_Support, QT_TRANSLATE_NOOP("QShortcut" , "Support" ) }, |
531 | { .key: Qt::Key_TaskPane, QT_TRANSLATE_NOOP("QShortcut" , "Task Panel" ) }, |
532 | { .key: Qt::Key_Terminal, QT_TRANSLATE_NOOP("QShortcut" , "Terminal" ) }, |
533 | { .key: Qt::Key_ToDoList, QT_TRANSLATE_NOOP("QShortcut" , "To-do list" ) }, |
534 | { .key: Qt::Key_Tools, QT_TRANSLATE_NOOP("QShortcut" , "Tools" ) }, |
535 | { .key: Qt::Key_Travel, QT_TRANSLATE_NOOP("QShortcut" , "Travel" ) }, |
536 | { .key: Qt::Key_Video, QT_TRANSLATE_NOOP("QShortcut" , "Video" ) }, |
537 | { .key: Qt::Key_Word, QT_TRANSLATE_NOOP("QShortcut" , "Word Processor" ) }, |
538 | { .key: Qt::Key_Xfer, QT_TRANSLATE_NOOP("QShortcut" , "XFer" ) }, |
539 | { .key: Qt::Key_ZoomIn, QT_TRANSLATE_NOOP("QShortcut" , "Zoom In" ) }, |
540 | { .key: Qt::Key_ZoomOut, QT_TRANSLATE_NOOP("QShortcut" , "Zoom Out" ) }, |
541 | { .key: Qt::Key_Away, QT_TRANSLATE_NOOP("QShortcut" , "Away" ) }, |
542 | { .key: Qt::Key_Messenger, QT_TRANSLATE_NOOP("QShortcut" , "Messenger" ) }, |
543 | { .key: Qt::Key_WebCam, QT_TRANSLATE_NOOP("QShortcut" , "WebCam" ) }, |
544 | { .key: Qt::Key_MailForward, QT_TRANSLATE_NOOP("QShortcut" , "Mail Forward" ) }, |
545 | { .key: Qt::Key_Pictures, QT_TRANSLATE_NOOP("QShortcut" , "Pictures" ) }, |
546 | { .key: Qt::Key_Music, QT_TRANSLATE_NOOP("QShortcut" , "Music" ) }, |
547 | { .key: Qt::Key_Battery, QT_TRANSLATE_NOOP("QShortcut" , "Battery" ) }, |
548 | { .key: Qt::Key_Bluetooth, QT_TRANSLATE_NOOP("QShortcut" , "Bluetooth" ) }, |
549 | { .key: Qt::Key_WLAN, QT_TRANSLATE_NOOP("QShortcut" , "Wireless" ) }, |
550 | { .key: Qt::Key_UWB, QT_TRANSLATE_NOOP("QShortcut" , "Ultra Wide Band" ) }, |
551 | { .key: Qt::Key_AudioForward, QT_TRANSLATE_NOOP("QShortcut" , "Media Fast Forward" ) }, |
552 | { .key: Qt::Key_AudioRepeat, QT_TRANSLATE_NOOP("QShortcut" , "Audio Repeat" ) }, |
553 | { .key: Qt::Key_AudioRandomPlay, QT_TRANSLATE_NOOP("QShortcut" , "Audio Random Play" ) }, |
554 | { .key: Qt::Key_Subtitle, QT_TRANSLATE_NOOP("QShortcut" , "Subtitle" ) }, |
555 | { .key: Qt::Key_AudioCycleTrack, QT_TRANSLATE_NOOP("QShortcut" , "Audio Cycle Track" ) }, |
556 | { .key: Qt::Key_Time, QT_TRANSLATE_NOOP("QShortcut" , "Time" ) }, |
557 | { .key: Qt::Key_Hibernate, QT_TRANSLATE_NOOP("QShortcut" , "Hibernate" ) }, |
558 | { .key: Qt::Key_View, QT_TRANSLATE_NOOP("QShortcut" , "View" ) }, |
559 | { .key: Qt::Key_TopMenu, QT_TRANSLATE_NOOP("QShortcut" , "Top Menu" ) }, |
560 | { .key: Qt::Key_PowerDown, QT_TRANSLATE_NOOP("QShortcut" , "Power Down" ) }, |
561 | { .key: Qt::Key_Suspend, QT_TRANSLATE_NOOP("QShortcut" , "Suspend" ) }, |
562 | |
563 | { .key: Qt::Key_MicMute, QT_TRANSLATE_NOOP("QShortcut" , "Microphone Mute" ) }, |
564 | |
565 | { .key: Qt::Key_Red, QT_TRANSLATE_NOOP("QShortcut" , "Red" ) }, |
566 | { .key: Qt::Key_Green, QT_TRANSLATE_NOOP("QShortcut" , "Green" ) }, |
567 | { .key: Qt::Key_Yellow, QT_TRANSLATE_NOOP("QShortcut" , "Yellow" ) }, |
568 | { .key: Qt::Key_Blue, QT_TRANSLATE_NOOP("QShortcut" , "Blue" ) }, |
569 | |
570 | { .key: Qt::Key_ChannelUp, QT_TRANSLATE_NOOP("QShortcut" , "Channel Up" ) }, |
571 | { .key: Qt::Key_ChannelDown, QT_TRANSLATE_NOOP("QShortcut" , "Channel Down" ) }, |
572 | |
573 | { .key: Qt::Key_Guide, QT_TRANSLATE_NOOP("QShortcut" , "Guide" ) }, |
574 | { .key: Qt::Key_Info, QT_TRANSLATE_NOOP("QShortcut" , "Info" ) }, |
575 | { .key: Qt::Key_Settings, QT_TRANSLATE_NOOP("QShortcut" , "Settings" ) }, |
576 | |
577 | { .key: Qt::Key_MicVolumeUp, QT_TRANSLATE_NOOP("QShortcut" , "Microphone Volume Up" ) }, |
578 | { .key: Qt::Key_MicVolumeDown, QT_TRANSLATE_NOOP("QShortcut" , "Microphone Volume Down" ) }, |
579 | |
580 | { .key: Qt::Key_New, QT_TRANSLATE_NOOP("QShortcut" , "New" ) }, |
581 | { .key: Qt::Key_Open, QT_TRANSLATE_NOOP("QShortcut" , "Open" ) }, |
582 | { .key: Qt::Key_Find, QT_TRANSLATE_NOOP("QShortcut" , "Find" ) }, |
583 | { .key: Qt::Key_Undo, QT_TRANSLATE_NOOP("QShortcut" , "Undo" ) }, |
584 | { .key: Qt::Key_Redo, QT_TRANSLATE_NOOP("QShortcut" , "Redo" ) }, |
585 | |
586 | // -------------------------------------------------------------- |
587 | // More consistent namings |
588 | { .key: Qt::Key_Print, QT_TRANSLATE_NOOP("QShortcut" , "Print Screen" ) }, |
589 | { .key: Qt::Key_PageUp, QT_TRANSLATE_NOOP("QShortcut" , "Page Up" ) }, |
590 | { .key: Qt::Key_PageDown, QT_TRANSLATE_NOOP("QShortcut" , "Page Down" ) }, |
591 | { .key: Qt::Key_CapsLock, QT_TRANSLATE_NOOP("QShortcut" , "Caps Lock" ) }, |
592 | { .key: Qt::Key_NumLock, QT_TRANSLATE_NOOP("QShortcut" , "Num Lock" ) }, |
593 | { .key: Qt::Key_NumLock, QT_TRANSLATE_NOOP("QShortcut" , "Number Lock" ) }, |
594 | { .key: Qt::Key_ScrollLock, QT_TRANSLATE_NOOP("QShortcut" , "Scroll Lock" ) }, |
595 | { .key: Qt::Key_Insert, QT_TRANSLATE_NOOP("QShortcut" , "Insert" ) }, |
596 | { .key: Qt::Key_Delete, QT_TRANSLATE_NOOP("QShortcut" , "Delete" ) }, |
597 | { .key: Qt::Key_Escape, QT_TRANSLATE_NOOP("QShortcut" , "Escape" ) }, |
598 | { .key: Qt::Key_SysReq, QT_TRANSLATE_NOOP("QShortcut" , "System Request" ) }, |
599 | |
600 | // -------------------------------------------------------------- |
601 | // Keypad navigation keys |
602 | { .key: Qt::Key_Select, QT_TRANSLATE_NOOP("QShortcut" , "Select" ) }, |
603 | { .key: Qt::Key_Yes, QT_TRANSLATE_NOOP("QShortcut" , "Yes" ) }, |
604 | { .key: Qt::Key_No, QT_TRANSLATE_NOOP("QShortcut" , "No" ) }, |
605 | |
606 | // -------------------------------------------------------------- |
607 | // Device keys |
608 | { .key: Qt::Key_Context1, QT_TRANSLATE_NOOP("QShortcut" , "Context1" ) }, |
609 | { .key: Qt::Key_Context2, QT_TRANSLATE_NOOP("QShortcut" , "Context2" ) }, |
610 | { .key: Qt::Key_Context3, QT_TRANSLATE_NOOP("QShortcut" , "Context3" ) }, |
611 | { .key: Qt::Key_Context4, QT_TRANSLATE_NOOP("QShortcut" , "Context4" ) }, |
612 | //: Button to start a call (note: a separate button is used to end the call) |
613 | { .key: Qt::Key_Call, QT_TRANSLATE_NOOP("QShortcut" , "Call" ) }, |
614 | //: Button to end a call (note: a separate button is used to start the call) |
615 | { .key: Qt::Key_Hangup, QT_TRANSLATE_NOOP("QShortcut" , "Hangup" ) }, |
616 | //: Button that will hang up if we're in call, or make a call if we're not. |
617 | { .key: Qt::Key_ToggleCallHangup, QT_TRANSLATE_NOOP("QShortcut" , "Toggle Call/Hangup" ) }, |
618 | { .key: Qt::Key_Flip, QT_TRANSLATE_NOOP("QShortcut" , "Flip" ) }, |
619 | //: Button to trigger voice dialing |
620 | { .key: Qt::Key_VoiceDial, QT_TRANSLATE_NOOP("QShortcut" , "Voice Dial" ) }, |
621 | //: Button to redial the last number called |
622 | { .key: Qt::Key_LastNumberRedial, QT_TRANSLATE_NOOP("QShortcut" , "Last Number Redial" ) }, |
623 | //: Button to trigger the camera shutter (take a picture) |
624 | { .key: Qt::Key_Camera, QT_TRANSLATE_NOOP("QShortcut" , "Camera Shutter" ) }, |
625 | //: Button to focus the camera |
626 | { .key: Qt::Key_CameraFocus, QT_TRANSLATE_NOOP("QShortcut" , "Camera Focus" ) }, |
627 | |
628 | // -------------------------------------------------------------- |
629 | // Japanese keyboard support |
630 | { .key: Qt::Key_Kanji, QT_TRANSLATE_NOOP("QShortcut" , "Kanji" ) }, |
631 | { .key: Qt::Key_Muhenkan, QT_TRANSLATE_NOOP("QShortcut" , "Muhenkan" ) }, |
632 | { .key: Qt::Key_Henkan, QT_TRANSLATE_NOOP("QShortcut" , "Henkan" ) }, |
633 | { .key: Qt::Key_Romaji, QT_TRANSLATE_NOOP("QShortcut" , "Romaji" ) }, |
634 | { .key: Qt::Key_Hiragana, QT_TRANSLATE_NOOP("QShortcut" , "Hiragana" ) }, |
635 | { .key: Qt::Key_Katakana, QT_TRANSLATE_NOOP("QShortcut" , "Katakana" ) }, |
636 | { .key: Qt::Key_Hiragana_Katakana,QT_TRANSLATE_NOOP("QShortcut" , "Hiragana Katakana" ) }, |
637 | { .key: Qt::Key_Zenkaku, QT_TRANSLATE_NOOP("QShortcut" , "Zenkaku" ) }, |
638 | { .key: Qt::Key_Hankaku, QT_TRANSLATE_NOOP("QShortcut" , "Hankaku" ) }, |
639 | { .key: Qt::Key_Zenkaku_Hankaku, QT_TRANSLATE_NOOP("QShortcut" , "Zenkaku Hankaku" ) }, |
640 | { .key: Qt::Key_Touroku, QT_TRANSLATE_NOOP("QShortcut" , "Touroku" ) }, |
641 | { .key: Qt::Key_Massyo, QT_TRANSLATE_NOOP("QShortcut" , "Massyo" ) }, |
642 | { .key: Qt::Key_Kana_Lock, QT_TRANSLATE_NOOP("QShortcut" , "Kana Lock" ) }, |
643 | { .key: Qt::Key_Kana_Shift, QT_TRANSLATE_NOOP("QShortcut" , "Kana Shift" ) }, |
644 | { .key: Qt::Key_Eisu_Shift, QT_TRANSLATE_NOOP("QShortcut" , "Eisu Shift" ) }, |
645 | { .key: Qt::Key_Eisu_toggle, QT_TRANSLATE_NOOP("QShortcut" , "Eisu toggle" ) }, |
646 | { .key: Qt::Key_Codeinput, QT_TRANSLATE_NOOP("QShortcut" , "Code input" ) }, |
647 | { .key: Qt::Key_MultipleCandidate,QT_TRANSLATE_NOOP("QShortcut" , "Multiple Candidate" ) }, |
648 | { .key: Qt::Key_PreviousCandidate,QT_TRANSLATE_NOOP("QShortcut" , "Previous Candidate" ) }, |
649 | |
650 | // -------------------------------------------------------------- |
651 | // Korean keyboard support |
652 | { .key: Qt::Key_Hangul, QT_TRANSLATE_NOOP("QShortcut" , "Hangul" ) }, |
653 | { .key: Qt::Key_Hangul_Start, QT_TRANSLATE_NOOP("QShortcut" , "Hangul Start" ) }, |
654 | { .key: Qt::Key_Hangul_End, QT_TRANSLATE_NOOP("QShortcut" , "Hangul End" ) }, |
655 | { .key: Qt::Key_Hangul_Hanja, QT_TRANSLATE_NOOP("QShortcut" , "Hangul Hanja" ) }, |
656 | { .key: Qt::Key_Hangul_Jamo, QT_TRANSLATE_NOOP("QShortcut" , "Hangul Jamo" ) }, |
657 | { .key: Qt::Key_Hangul_Romaja, QT_TRANSLATE_NOOP("QShortcut" , "Hangul Romaja" ) }, |
658 | { .key: Qt::Key_Hangul_Jeonja, QT_TRANSLATE_NOOP("QShortcut" , "Hangul Jeonja" ) }, |
659 | { .key: Qt::Key_Hangul_Banja, QT_TRANSLATE_NOOP("QShortcut" , "Hangul Banja" ) }, |
660 | { .key: Qt::Key_Hangul_PreHanja, QT_TRANSLATE_NOOP("QShortcut" , "Hangul PreHanja" ) }, |
661 | { .key: Qt::Key_Hangul_PostHanja,QT_TRANSLATE_NOOP("QShortcut" , "Hangul PostHanja" ) }, |
662 | { .key: Qt::Key_Hangul_Special, QT_TRANSLATE_NOOP("QShortcut" , "Hangul Special" ) }, |
663 | |
664 | // -------------------------------------------------------------- |
665 | // Miscellaneous keys |
666 | { .key: Qt::Key_Cancel, QT_TRANSLATE_NOOP("QShortcut" , "Cancel" ) }, |
667 | { .key: Qt::Key_Printer, QT_TRANSLATE_NOOP("QShortcut" , "Printer" ) }, |
668 | { .key: Qt::Key_Execute, QT_TRANSLATE_NOOP("QShortcut" , "Execute" ) }, |
669 | { .key: Qt::Key_Play, QT_TRANSLATE_NOOP("QShortcut" , "Play" ) }, |
670 | { .key: Qt::Key_Zoom, QT_TRANSLATE_NOOP("QShortcut" , "Zoom" ) }, |
671 | { .key: Qt::Key_Exit, QT_TRANSLATE_NOOP("QShortcut" , "Exit" ) }, |
672 | { .key: Qt::Key_TouchpadToggle, QT_TRANSLATE_NOOP("QShortcut" , "Touchpad Toggle" ) }, |
673 | { .key: Qt::Key_TouchpadOn, QT_TRANSLATE_NOOP("QShortcut" , "Touchpad On" ) }, |
674 | { .key: Qt::Key_TouchpadOff, QT_TRANSLATE_NOOP("QShortcut" , "Touchpad Off" ) }, |
675 | { .key: Qt::Key_Shift, QT_TRANSLATE_NOOP("QShortcut" , "Shift" ) }, |
676 | { .key: Qt::Key_Control, QT_TRANSLATE_NOOP("QShortcut" , "Control" ) }, |
677 | { .key: Qt::Key_Alt, QT_TRANSLATE_NOOP("QShortcut" , "Alt" ) }, |
678 | { .key: Qt::Key_Meta, QT_TRANSLATE_NOOP("QShortcut" , "Meta" ) }, |
679 | |
680 | }; |
681 | static constexpr int numKeyNames = sizeof keyname / sizeof *keyname; |
682 | |
683 | /*! |
684 | \enum QKeySequence::StandardKey |
685 | \since 4.2 |
686 | |
687 | This enum represent standard key bindings. They can be used to |
688 | assign platform dependent keyboard shortcuts to a QAction. |
689 | |
690 | Note that the key bindings are platform dependent. The currently |
691 | bound shortcuts can be queried using keyBindings(). |
692 | |
693 | \value AddTab Add new tab. |
694 | \value Back Navigate back. |
695 | \value Backspace Delete previous character. |
696 | \value Bold Bold text. |
697 | \value Close Close document/tab. |
698 | \value Copy Copy. |
699 | \value Cut Cut. |
700 | \value Delete Delete. |
701 | \value DeleteEndOfLine Delete end of line. |
702 | \value DeleteEndOfWord Delete word from the end of the cursor. |
703 | \value DeleteStartOfWord Delete the beginning of a word up to the cursor. |
704 | \value DeleteCompleteLine Delete the entire line. |
705 | \value Find Find in document. |
706 | \value FindNext Find next result. |
707 | \value FindPrevious Find previous result. |
708 | \value Forward Navigate forward. |
709 | \value HelpContents Open help contents. |
710 | \value InsertLineSeparator Insert a new line. |
711 | \value InsertParagraphSeparator Insert a new paragraph. |
712 | \value Italic Italic text. |
713 | \value MoveToEndOfBlock Move cursor to end of block. This shortcut is only used on the \macos. |
714 | \value MoveToEndOfDocument Move cursor to end of document. |
715 | \value MoveToEndOfLine Move cursor to end of line. |
716 | \value MoveToNextChar Move cursor to next character. |
717 | \value MoveToNextLine Move cursor to next line. |
718 | \value MoveToNextPage Move cursor to next page. |
719 | \value MoveToNextWord Move cursor to next word. |
720 | \value MoveToPreviousChar Move cursor to previous character. |
721 | \value MoveToPreviousLine Move cursor to previous line. |
722 | \value MoveToPreviousPage Move cursor to previous page. |
723 | \value MoveToPreviousWord Move cursor to previous word. |
724 | \value MoveToStartOfBlock Move cursor to start of a block. This shortcut is only used on \macos. |
725 | \value MoveToStartOfDocument Move cursor to start of document. |
726 | \value MoveToStartOfLine Move cursor to start of line. |
727 | \value New Create new document. |
728 | \value NextChild Navigate to next tab or child window. |
729 | \value Open Open document. |
730 | \value Paste Paste. |
731 | \value Preferences Open the preferences dialog. |
732 | \value PreviousChild Navigate to previous tab or child window. |
733 | \value Print Print document. |
734 | \value Quit Quit the application. |
735 | \value Redo Redo. |
736 | \value Refresh Refresh or reload current document. |
737 | \value Replace Find and replace. |
738 | \value SaveAs Save document after prompting the user for a file name. |
739 | \value Save Save document. |
740 | \value SelectAll Select all text. |
741 | \value Deselect Deselect text. Since 5.1 |
742 | \value SelectEndOfBlock Extend selection to the end of a text block. This shortcut is only used on \macos. |
743 | \value SelectEndOfDocument Extend selection to end of document. |
744 | \value SelectEndOfLine Extend selection to end of line. |
745 | \value SelectNextChar Extend selection to next character. |
746 | \value SelectNextLine Extend selection to next line. |
747 | \value SelectNextPage Extend selection to next page. |
748 | \value SelectNextWord Extend selection to next word. |
749 | \value SelectPreviousChar Extend selection to previous character. |
750 | \value SelectPreviousLine Extend selection to previous line. |
751 | \value SelectPreviousPage Extend selection to previous page. |
752 | \value SelectPreviousWord Extend selection to previous word. |
753 | \value SelectStartOfBlock Extend selection to the start of a text block. This shortcut is only used on \macos. |
754 | \value SelectStartOfDocument Extend selection to start of document. |
755 | \value SelectStartOfLine Extend selection to start of line. |
756 | \value Underline Underline text. |
757 | \value Undo Undo. |
758 | \value UnknownKey Unbound key. |
759 | \value WhatsThis Activate "what's this". |
760 | \value ZoomIn Zoom in. |
761 | \value ZoomOut Zoom out. |
762 | \value FullScreen Toggle the window state to/from full screen. |
763 | \value Cancel Cancel the current operation. |
764 | */ |
765 | |
766 | /*! |
767 | \fn QKeySequence &QKeySequence::operator=(QKeySequence &&other) |
768 | |
769 | Move-assigns \a other to this QKeySequence instance. |
770 | |
771 | \since 5.2 |
772 | */ |
773 | |
774 | /*! |
775 | \since 4.2 |
776 | |
777 | Constructs a QKeySequence object for the given \a key. |
778 | The result will depend on the currently running platform. |
779 | |
780 | The resulting object will be based on the first element in the |
781 | list of key bindings for the \a key. |
782 | */ |
783 | QKeySequence::QKeySequence(StandardKey key) |
784 | { |
785 | const QList <QKeySequence> bindings = keyBindings(key); |
786 | //pick only the first/primary shortcut from current bindings |
787 | if (bindings.size() > 0) { |
788 | d = bindings.first().d; |
789 | d->ref.ref(); |
790 | } |
791 | else |
792 | d = new QKeySequencePrivate(); |
793 | } |
794 | |
795 | |
796 | /*! |
797 | Constructs an empty key sequence. |
798 | */ |
799 | QKeySequence::QKeySequence() |
800 | { |
801 | Q_CONSTINIT static QKeySequencePrivate shared_empty; |
802 | d = &shared_empty; |
803 | d->ref.ref(); |
804 | } |
805 | |
806 | /*! |
807 | Creates a key sequence from the \a key string, based on \a format. |
808 | |
809 | For example "Ctrl+O" gives CTRL+'O'. The strings "Ctrl", |
810 | "Shift", "Alt" and "Meta" are recognized, as well as their |
811 | translated equivalents in the "QShortcut" context (using |
812 | QObject::tr()). |
813 | |
814 | Up to four key codes may be entered by separating them with |
815 | commas, e.g. "Alt+X,Ctrl+S,Q". |
816 | |
817 | This constructor is typically used with \l{QObject::tr()}{tr}(), so |
818 | that shortcut keys can be replaced in translations: |
819 | |
820 | \snippet code/src_gui_kernel_qkeysequence.cpp 2 |
821 | |
822 | Note the "File|Open" translator comment. It is by no means |
823 | necessary, but it provides some context for the human translator. |
824 | */ |
825 | QKeySequence::QKeySequence(const QString &key, QKeySequence::SequenceFormat format) |
826 | { |
827 | d = new QKeySequencePrivate(); |
828 | assign(str: key, format); |
829 | } |
830 | |
831 | static_assert(QKeySequencePrivate::MaxKeyCount == 4, "Change docs and ctor impl below" ); |
832 | /*! |
833 | Constructs a key sequence with up to 4 keys \a k1, \a k2, |
834 | \a k3 and \a k4. |
835 | |
836 | The key codes are listed in Qt::Key and can be combined with |
837 | modifiers (see Qt::KeyboardModifier) such as Qt::ShiftModifier, |
838 | Qt::ControlModifier, Qt::AltModifier, or Qt::MetaModifier. |
839 | */ |
840 | QKeySequence::QKeySequence(int k1, int k2, int k3, int k4) |
841 | { |
842 | d = new QKeySequencePrivate(); |
843 | d->key[0] = k1; |
844 | d->key[1] = k2; |
845 | d->key[2] = k3; |
846 | d->key[3] = k4; |
847 | } |
848 | |
849 | /*! |
850 | Constructs a key sequence with up to 4 keys \a k1, \a k2, |
851 | \a k3 and \a k4. |
852 | |
853 | \sa QKeyCombination |
854 | */ |
855 | QKeySequence::QKeySequence(QKeyCombination k1, QKeyCombination k2, QKeyCombination k3, QKeyCombination k4) |
856 | : QKeySequence(k1.toCombined(), k2.toCombined(), k3.toCombined(), k4.toCombined()) |
857 | { |
858 | } |
859 | |
860 | /*! |
861 | Copy constructor. Makes a copy of \a keysequence. |
862 | */ |
863 | QKeySequence::QKeySequence(const QKeySequence& keysequence) |
864 | : d(keysequence.d) |
865 | { |
866 | d->ref.ref(); |
867 | } |
868 | |
869 | /*! |
870 | \since 4.2 |
871 | |
872 | Returns a list of key bindings for the given \a key. |
873 | The result of calling this function will vary based on the target platform. |
874 | The first element of the list indicates the primary shortcut for the given platform. |
875 | If the result contains more than one result, these can |
876 | be considered alternative shortcuts on the same platform for the given \a key. |
877 | */ |
878 | QList<QKeySequence> QKeySequence::keyBindings(StandardKey key) |
879 | { |
880 | return QGuiApplicationPrivate::platformTheme()->keyBindings(key); |
881 | } |
882 | |
883 | /*! |
884 | Destroys the key sequence. |
885 | */ |
886 | QKeySequence::~QKeySequence() |
887 | { |
888 | if (!d->ref.deref()) |
889 | delete d; |
890 | } |
891 | |
892 | /*! |
893 | \internal |
894 | KeySequences should never be modified, but rather just created. |
895 | Internally though we do need to modify to keep pace in event |
896 | delivery. |
897 | */ |
898 | |
899 | void QKeySequence::setKey(QKeyCombination key, int index) |
900 | { |
901 | Q_ASSERT_X(index >= 0 && index < QKeySequencePrivate::MaxKeyCount, "QKeySequence::setKey" , "index out of range" ); |
902 | qAtomicDetach(d); |
903 | d->key[index] = key.toCombined(); |
904 | } |
905 | |
906 | static_assert(QKeySequencePrivate::MaxKeyCount == 4, "Change docs below" ); |
907 | /*! |
908 | Returns the number of keys in the key sequence. |
909 | The maximum is 4. |
910 | */ |
911 | int QKeySequence::count() const |
912 | { |
913 | return int(std::distance(first: d->key, last: std::find(first: d->key, last: d->key + QKeySequencePrivate::MaxKeyCount, val: 0))); |
914 | } |
915 | |
916 | |
917 | /*! |
918 | Returns \c true if the key sequence is empty; otherwise returns |
919 | false. |
920 | */ |
921 | bool QKeySequence::isEmpty() const |
922 | { |
923 | return !d->key[0]; |
924 | } |
925 | |
926 | |
927 | /*! |
928 | Returns the shortcut key sequence for the mnemonic in \a text, |
929 | or an empty key sequence if no mnemonics are found. |
930 | |
931 | For example, mnemonic("E&xit") returns \c{Qt::ALT+Qt::Key_X}, |
932 | mnemonic("&Quit") returns \c{ALT+Key_Q}, and mnemonic("Quit") |
933 | returns an empty QKeySequence. |
934 | */ |
935 | QKeySequence QKeySequence::mnemonic(const QString &text) |
936 | { |
937 | QKeySequence ret; |
938 | |
939 | if (qt_sequence_no_mnemonics) |
940 | return ret; |
941 | |
942 | bool found = false; |
943 | qsizetype p = 0; |
944 | while (p >= 0) { |
945 | p = text.indexOf(c: u'&', from: p) + 1; |
946 | if (p <= 0 || p >= (int)text.size()) |
947 | break; |
948 | if (text.at(i: p) != u'&') { |
949 | QChar c = text.at(i: p); |
950 | if (c.isPrint()) { |
951 | if (!found) { |
952 | c = c.toUpper(); |
953 | ret = QKeySequence(QKeyCombination(Qt::ALT, Qt::Key(c.unicode()))); |
954 | #ifdef QT_NO_DEBUG |
955 | return ret; |
956 | #else |
957 | found = true; |
958 | } else { |
959 | qWarning(msg: "QKeySequence::mnemonic: \"%s\" contains multiple occurrences of '&'" , qPrintable(text)); |
960 | #endif |
961 | } |
962 | } |
963 | } |
964 | p++; |
965 | } |
966 | return ret; |
967 | } |
968 | |
969 | /*! |
970 | \fn int QKeySequence::assign(const QString &keys) |
971 | |
972 | Adds the given \a keys to the key sequence. \a keys may |
973 | contain up to four key codes, provided they are separated by a |
974 | comma; for example, "Alt+X,Ctrl+S,Z". The return value is the |
975 | number of key codes added. |
976 | \a keys should be in NativeText format. |
977 | */ |
978 | int QKeySequence::assign(const QString &ks) |
979 | { |
980 | return assign(str: ks, format: NativeText); |
981 | } |
982 | |
983 | /*! |
984 | \fn int QKeySequence::assign(const QString &keys, QKeySequence::SequenceFormat format) |
985 | \since 4.7 |
986 | |
987 | Adds the given \a keys to the key sequence (based on \a format). |
988 | \a keys may contain up to four key codes, provided they are |
989 | separated by a comma; for example, "Alt+X,Ctrl+S,Z". The return |
990 | value is the number of key codes added. |
991 | */ |
992 | int QKeySequence::assign(const QString &ks, QKeySequence::SequenceFormat format) |
993 | { |
994 | QString keyseq = ks; |
995 | int n = 0; |
996 | qsizetype p = 0, diff = 0; |
997 | |
998 | // Run through the whole string, but stop |
999 | // if we have MaxKeyCount keys before the end. |
1000 | while (keyseq.size() && n < QKeySequencePrivate::MaxKeyCount) { |
1001 | // We MUST use something to separate each sequence, and space |
1002 | // does not cut it, since some of the key names have space |
1003 | // in them.. (Let's hope no one translate with a comma in it:) |
1004 | p = keyseq.indexOf(c: u','); |
1005 | if (-1 != p) { |
1006 | if (p == keyseq.size() - 1) { // Last comma 'Ctrl+,' |
1007 | p = -1; |
1008 | } else { |
1009 | if (u',' == keyseq.at(i: p+1)) // e.g. 'Ctrl+,, Shift+,,' |
1010 | p++; |
1011 | if (u' ' == keyseq.at(i: p+1)) { // Space after comma |
1012 | diff = 1; |
1013 | p++; |
1014 | } else { |
1015 | diff = 0; |
1016 | } |
1017 | } |
1018 | } |
1019 | QString part = keyseq.left(n: -1 == p ? keyseq.size() : p - diff); |
1020 | keyseq = keyseq.right(n: -1 == p ? 0 : keyseq.size() - (p + 1)); |
1021 | d->key[n] = QKeySequencePrivate::decodeString(accel: std::move(part), format); |
1022 | ++n; |
1023 | } |
1024 | return n; |
1025 | } |
1026 | |
1027 | struct QModifKeyName { |
1028 | QModifKeyName() { } |
1029 | QModifKeyName(int q, QChar n) : qt_key(q), name(n) { } |
1030 | QModifKeyName(int q, const QString &n) : qt_key(q), name(n) { } |
1031 | int qt_key; |
1032 | QString name; |
1033 | }; |
1034 | Q_DECLARE_TYPEINFO(QModifKeyName, Q_RELOCATABLE_TYPE); |
1035 | |
1036 | Q_GLOBAL_STATIC(QList<QModifKeyName>, globalModifs) |
1037 | Q_GLOBAL_STATIC(QList<QModifKeyName>, globalPortableModifs) |
1038 | |
1039 | /*! |
1040 | Constructs a single key from the string \a str. |
1041 | */ |
1042 | int QKeySequence::decodeString(const QString &str) |
1043 | { |
1044 | return QKeySequencePrivate::decodeString(accel: str, format: NativeText); |
1045 | } |
1046 | |
1047 | int QKeySequencePrivate::decodeString(QString accel, QKeySequence::SequenceFormat format) |
1048 | { |
1049 | Q_ASSERT(!accel.isEmpty()); |
1050 | |
1051 | int ret = 0; |
1052 | accel = std::move(accel).toLower(); |
1053 | bool nativeText = (format == QKeySequence::NativeText); |
1054 | |
1055 | QList<QModifKeyName> *gmodifs; |
1056 | if (nativeText) { |
1057 | gmodifs = globalModifs(); |
1058 | if (gmodifs->isEmpty()) { |
1059 | #if defined(Q_OS_MACOS) |
1060 | const bool dontSwap = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta); |
1061 | if (dontSwap) |
1062 | *gmodifs << QModifKeyName(Qt::META, QChar(kCommandUnicode)); |
1063 | else |
1064 | *gmodifs << QModifKeyName(Qt::CTRL, QChar(kCommandUnicode)); |
1065 | *gmodifs << QModifKeyName(Qt::ALT, QChar(kOptionUnicode)); |
1066 | if (dontSwap) |
1067 | *gmodifs << QModifKeyName(Qt::CTRL, QChar(kControlUnicode)); |
1068 | else |
1069 | *gmodifs << QModifKeyName(Qt::META, QChar(kControlUnicode)); |
1070 | *gmodifs << QModifKeyName(Qt::SHIFT, QChar(kShiftUnicode)); |
1071 | #endif |
1072 | *gmodifs << QModifKeyName(Qt::CTRL, u"ctrl+"_s ) |
1073 | << QModifKeyName(Qt::SHIFT, u"shift+"_s ) |
1074 | << QModifKeyName(Qt::ALT, u"alt+"_s ) |
1075 | << QModifKeyName(Qt::META, u"meta+"_s ) |
1076 | << QModifKeyName(Qt::KeypadModifier, u"num+"_s ); |
1077 | } |
1078 | } else { |
1079 | gmodifs = globalPortableModifs(); |
1080 | if (gmodifs->isEmpty()) { |
1081 | *gmodifs << QModifKeyName(Qt::CTRL, u"ctrl+"_s ) |
1082 | << QModifKeyName(Qt::SHIFT, u"shift+"_s ) |
1083 | << QModifKeyName(Qt::ALT, u"alt+"_s ) |
1084 | << QModifKeyName(Qt::META, u"meta+"_s ) |
1085 | << QModifKeyName(Qt::KeypadModifier, u"num+"_s ); |
1086 | } |
1087 | } |
1088 | |
1089 | |
1090 | QList<QModifKeyName> modifs; |
1091 | if (nativeText) { |
1092 | modifs << QModifKeyName(Qt::CTRL, QCoreApplication::translate(context: "QShortcut" , key: "Ctrl" ).toLower().append(c: u'+')) |
1093 | << QModifKeyName(Qt::SHIFT, QCoreApplication::translate(context: "QShortcut" , key: "Shift" ).toLower().append(c: u'+')) |
1094 | << QModifKeyName(Qt::ALT, QCoreApplication::translate(context: "QShortcut" , key: "Alt" ).toLower().append(c: u'+')) |
1095 | << QModifKeyName(Qt::META, QCoreApplication::translate(context: "QShortcut" , key: "Meta" ).toLower().append(c: u'+')) |
1096 | << QModifKeyName(Qt::KeypadModifier, QCoreApplication::translate(context: "QShortcut" , key: "Num" ).toLower().append(c: u'+')); |
1097 | } |
1098 | modifs += *gmodifs; // Test non-translated ones last |
1099 | |
1100 | QString sl = accel; |
1101 | #if defined(Q_OS_MACOS) |
1102 | for (int i = 0; i < modifs.size(); ++i) { |
1103 | const QModifKeyName &mkf = modifs.at(i); |
1104 | if (sl.contains(mkf.name)) { |
1105 | ret |= mkf.qt_key; |
1106 | accel.remove(mkf.name); |
1107 | sl = accel; |
1108 | } |
1109 | } |
1110 | if (accel.isEmpty()) // Incomplete, like for "Meta+Shift+" |
1111 | return Qt::Key_unknown; |
1112 | #endif |
1113 | |
1114 | qsizetype i = 0; |
1115 | qsizetype lastI = 0; |
1116 | while ((i = sl.indexOf(c: u'+', from: i + 1)) != -1) { |
1117 | const QStringView sub = QStringView{sl}.mid(pos: lastI, n: i - lastI + 1); |
1118 | // If we get here the shortcuts contains at least one '+'. We break up |
1119 | // along the following strategy: |
1120 | // Meta+Ctrl++ ( "Meta+", "Ctrl+", "+" ) |
1121 | // Super+Shift+A ( "Super+", "Shift+" ) |
1122 | // 4+3+2=1 ( "4+", "3+" ) |
1123 | // In other words, everything we try to handle HAS to be a modifier |
1124 | // except for a single '+' at the end of the string. |
1125 | |
1126 | // Only '+' can have length 1. |
1127 | if (sub.size() == 1) { |
1128 | // Make sure we only encounter a single '+' at the end of the accel |
1129 | if (accel.lastIndexOf(c: u'+') != accel.size()-1) |
1130 | return Qt::Key_unknown; |
1131 | } else { |
1132 | // Identify the modifier |
1133 | bool validModifier = false; |
1134 | for (int j = 0; j < modifs.size(); ++j) { |
1135 | const QModifKeyName &mkf = modifs.at(i: j); |
1136 | if (sub == mkf.name) { |
1137 | ret |= mkf.qt_key; |
1138 | validModifier = true; |
1139 | break; // Shortcut, since if we find an other it would/should just be a dup |
1140 | } |
1141 | } |
1142 | |
1143 | if (!validModifier) |
1144 | return Qt::Key_unknown; |
1145 | } |
1146 | lastI = i + 1; |
1147 | } |
1148 | |
1149 | qsizetype p = accel.lastIndexOf(c: u'+', from: accel.size() - 2); // -2 so that Ctrl++ works |
1150 | QStringView accelRef(accel); |
1151 | if (p > 0) |
1152 | accelRef = accelRef.mid(pos: p + 1); |
1153 | |
1154 | int fnum = 0; |
1155 | if (accelRef.size() == 1) { |
1156 | #if defined(Q_OS_MACOS) |
1157 | int qtKey = qtkeyForMacSymbol(accelRef.at(0)); |
1158 | if (qtKey != -1) { |
1159 | ret |= qtKey; |
1160 | } else |
1161 | #endif |
1162 | { |
1163 | ret |= accelRef.at(n: 0).toUpper().unicode(); |
1164 | } |
1165 | } else if (accelRef.at(n: 0) == u'f' && (fnum = accelRef.mid(pos: 1).toInt()) >= 1 && fnum <= 35) { |
1166 | ret |= Qt::Key_F1 + fnum - 1; |
1167 | } else { |
1168 | // For NativeText, check the translation table first, |
1169 | // if we don't find anything then try it out with just the untranlated stuff. |
1170 | // PortableText will only try the untranlated table. |
1171 | bool found = false; |
1172 | for (int tran = 0; tran < 2; ++tran) { |
1173 | if (!nativeText) |
1174 | ++tran; |
1175 | for (int i = 0; i < numKeyNames; ++i) { |
1176 | QString keyName(tran == 0 |
1177 | ? QCoreApplication::translate(context: "QShortcut" , key: keyname[i].name) |
1178 | : QString::fromLatin1(ba: keyname[i].name)); |
1179 | if (accelRef == std::move(keyName).toLower()) { |
1180 | ret |= keyname[i].key; |
1181 | found = true; |
1182 | break; |
1183 | } |
1184 | } |
1185 | if (found) |
1186 | break; |
1187 | } |
1188 | // We couldn't translate the key. |
1189 | if (!found) |
1190 | return Qt::Key_unknown; |
1191 | } |
1192 | return ret; |
1193 | } |
1194 | |
1195 | /*! |
1196 | Creates a shortcut string for \a key. For example, |
1197 | Qt::CTRL+Qt::Key_O gives "Ctrl+O". The strings, "Ctrl", "Shift", etc. are |
1198 | translated (using QObject::tr()) in the "QShortcut" context. |
1199 | */ |
1200 | QString QKeySequence::encodeString(int key) |
1201 | { |
1202 | return QKeySequencePrivate::encodeString(key, format: NativeText); |
1203 | } |
1204 | |
1205 | static inline void addKey(QString &str, const QString &theKey, QKeySequence::SequenceFormat format) |
1206 | { |
1207 | if (!str.isEmpty()) { |
1208 | if (format == QKeySequence::NativeText) { |
1209 | //: Key separator in shortcut string |
1210 | str += QCoreApplication::translate(context: "QShortcut" , key: "+" ); |
1211 | } else { |
1212 | str += u'+'; |
1213 | } |
1214 | } |
1215 | |
1216 | str += theKey; |
1217 | } |
1218 | |
1219 | QString QKeySequencePrivate::encodeString(int key, QKeySequence::SequenceFormat format) |
1220 | { |
1221 | bool nativeText = (format == QKeySequence::NativeText); |
1222 | QString s; |
1223 | |
1224 | // Handle -1 (Invalid Key) and Qt::Key_unknown gracefully |
1225 | if (key == -1 || key == Qt::Key_unknown) |
1226 | return s; |
1227 | |
1228 | #if defined(Q_OS_MACOS) |
1229 | if (nativeText) { |
1230 | // On OS X the order (by default) is Meta, Alt, Shift, Control. |
1231 | // If the AA_MacDontSwapCtrlAndMeta is enabled, then the order |
1232 | // is Ctrl, Alt, Shift, Meta. The macSymbolForQtKey does this swap |
1233 | // for us, which means that we have to adjust our order here. |
1234 | // The upshot is a lot more infrastructure to keep the number of |
1235 | // if tests down and the code relatively clean. |
1236 | static constexpr int ModifierOrder[] = { Qt::META, Qt::ALT, Qt::SHIFT, Qt::CTRL, 0 }; |
1237 | static constexpr int QtKeyOrder[] = { Qt::Key_Meta, Qt::Key_Alt, Qt::Key_Shift, Qt::Key_Control, 0 }; |
1238 | static constexpr int DontSwapModifierOrder[] = { Qt::CTRL, Qt::ALT, Qt::SHIFT, Qt::META, 0 }; |
1239 | static constexpr int DontSwapQtKeyOrder[] = { Qt::Key_Control, Qt::Key_Alt, Qt::Key_Shift, Qt::Key_Meta, 0 }; |
1240 | const int *modifierOrder; |
1241 | const int *qtkeyOrder; |
1242 | if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { |
1243 | modifierOrder = DontSwapModifierOrder; |
1244 | qtkeyOrder = DontSwapQtKeyOrder; |
1245 | } else { |
1246 | modifierOrder = ModifierOrder; |
1247 | qtkeyOrder = QtKeyOrder; |
1248 | } |
1249 | |
1250 | for (int i = 0; modifierOrder[i] != 0; ++i) { |
1251 | if (key & modifierOrder[i]) |
1252 | s += qt_macSymbolForQtKey(qtkeyOrder[i]); |
1253 | } |
1254 | } else |
1255 | #endif |
1256 | { |
1257 | // On other systems the order is Meta, Control, Alt, Shift |
1258 | if ((key & Qt::META) == Qt::META) |
1259 | s = nativeText ? QCoreApplication::translate(context: "QShortcut" , key: "Meta" ) : QString::fromLatin1(ba: "Meta" ); |
1260 | if ((key & Qt::CTRL) == Qt::CTRL) |
1261 | addKey(str&: s, theKey: nativeText ? QCoreApplication::translate(context: "QShortcut" , key: "Ctrl" ) : QString::fromLatin1(ba: "Ctrl" ), format); |
1262 | if ((key & Qt::ALT) == Qt::ALT) |
1263 | addKey(str&: s, theKey: nativeText ? QCoreApplication::translate(context: "QShortcut" , key: "Alt" ) : QString::fromLatin1(ba: "Alt" ), format); |
1264 | if ((key & Qt::SHIFT) == Qt::SHIFT) |
1265 | addKey(str&: s, theKey: nativeText ? QCoreApplication::translate(context: "QShortcut" , key: "Shift" ) : QString::fromLatin1(ba: "Shift" ), format); |
1266 | } |
1267 | if ((key & Qt::KeypadModifier) == Qt::KeypadModifier) |
1268 | addKey(str&: s, theKey: nativeText ? QCoreApplication::translate(context: "QShortcut" , key: "Num" ) : QString::fromLatin1(ba: "Num" ), format); |
1269 | |
1270 | QString p = keyName(key, format); |
1271 | |
1272 | #if defined(Q_OS_MACOS) |
1273 | if (nativeText) |
1274 | s += p; |
1275 | else |
1276 | #endif |
1277 | addKey(str&: s, theKey: p, format); |
1278 | return s; |
1279 | } |
1280 | |
1281 | /*! |
1282 | \internal |
1283 | Returns the text representation of the key \a key, which can be used i.e. |
1284 | when the sequence is serialized. This does not take modifiers into account |
1285 | (see encodeString() for a version that does). |
1286 | |
1287 | This static method is used by encodeString() and by the D-Bus menu exporter. |
1288 | */ |
1289 | QString QKeySequencePrivate::keyName(int key, QKeySequence::SequenceFormat format) |
1290 | { |
1291 | bool nativeText = (format == QKeySequence::NativeText); |
1292 | key &= ~(Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier | Qt::KeypadModifier); |
1293 | QString p; |
1294 | |
1295 | if (key && key < Qt::Key_Escape && key != Qt::Key_Space) { |
1296 | if (!QChar::requiresSurrogates(ucs4: key)) { |
1297 | p = QChar::fromUcs2(c: key).toUpper(); |
1298 | } else { |
1299 | p += QChar(QChar::highSurrogate(ucs4: key)); |
1300 | p += QChar(QChar::lowSurrogate(ucs4: key)); |
1301 | } |
1302 | } else if (key >= Qt::Key_F1 && key <= Qt::Key_F35) { |
1303 | p = nativeText ? QCoreApplication::translate(context: "QShortcut" , key: "F%1" ).arg(a: key - Qt::Key_F1 + 1) |
1304 | : QString::fromLatin1(ba: "F%1" ).arg(a: key - Qt::Key_F1 + 1); |
1305 | } else if (key) { |
1306 | int i=0; |
1307 | #if defined(Q_OS_MACOS) |
1308 | if (nativeText) { |
1309 | QChar ch = qt_macSymbolForQtKey(key); |
1310 | if (!ch.isNull()) |
1311 | p = ch; |
1312 | else |
1313 | goto NonSymbol; |
1314 | } else |
1315 | #endif |
1316 | { |
1317 | #if defined(Q_OS_MACOS) |
1318 | NonSymbol: |
1319 | #endif |
1320 | while (i < numKeyNames) { |
1321 | if (key == keyname[i].key) { |
1322 | p = nativeText ? QCoreApplication::translate(context: "QShortcut" , key: keyname[i].name) |
1323 | : QString::fromLatin1(ba: keyname[i].name); |
1324 | break; |
1325 | } |
1326 | ++i; |
1327 | } |
1328 | // If we can't find the actual translatable keyname, |
1329 | // fall back on the unicode representation of it... |
1330 | // Or else characters like Qt::Key_aring may not get displayed |
1331 | // (Really depends on you locale) |
1332 | if (i >= numKeyNames) { |
1333 | if (!QChar::requiresSurrogates(ucs4: key)) { |
1334 | p = QChar::fromUcs2(c: key).toUpper(); |
1335 | } else { |
1336 | p += QChar(QChar::highSurrogate(ucs4: key)); |
1337 | p += QChar(QChar::lowSurrogate(ucs4: key)); |
1338 | } |
1339 | } |
1340 | } |
1341 | } |
1342 | return p; |
1343 | } |
1344 | /*! |
1345 | Matches the sequence with \a seq. Returns ExactMatch if |
1346 | successful, PartialMatch if \a seq matches incompletely, |
1347 | and NoMatch if the sequences have nothing in common. |
1348 | Returns NoMatch if \a seq is shorter. |
1349 | */ |
1350 | QKeySequence::SequenceMatch QKeySequence::matches(const QKeySequence &seq) const |
1351 | { |
1352 | uint userN = count(), |
1353 | seqN = seq.count(); |
1354 | |
1355 | if (userN > seqN) |
1356 | return NoMatch; |
1357 | |
1358 | // If equal in length, we have a potential ExactMatch sequence, |
1359 | // else we already know it can only be partial. |
1360 | SequenceMatch match = (userN == seqN ? ExactMatch : PartialMatch); |
1361 | |
1362 | for (uint i = 0; i < userN; ++i) { |
1363 | QKeyCombination userKey = (*this)[i], |
1364 | sequenceKey = seq[i]; |
1365 | if (userKey != sequenceKey) |
1366 | return NoMatch; |
1367 | } |
1368 | return match; |
1369 | } |
1370 | |
1371 | /*! |
1372 | Returns the key sequence as a QVariant |
1373 | */ |
1374 | QKeySequence::operator QVariant() const |
1375 | { |
1376 | return QVariant::fromValue(value: *this); |
1377 | } |
1378 | |
1379 | /*! |
1380 | Returns a reference to the element at position \a index in the key |
1381 | sequence. This can only be used to read an element. |
1382 | */ |
1383 | QKeyCombination QKeySequence::operator[](uint index) const |
1384 | { |
1385 | Q_ASSERT_X(index < QKeySequencePrivate::MaxKeyCount, "QKeySequence::operator[]" , "index out of range" ); |
1386 | return QKeyCombination::fromCombined(combined: d->key[index]); |
1387 | } |
1388 | |
1389 | |
1390 | /*! |
1391 | Assignment operator. Assigns the \a other key sequence to this |
1392 | object. |
1393 | */ |
1394 | QKeySequence &QKeySequence::operator=(const QKeySequence &other) |
1395 | { |
1396 | qAtomicAssign(d, x: other.d); |
1397 | return *this; |
1398 | } |
1399 | |
1400 | /*! |
1401 | \fn void QKeySequence::swap(QKeySequence &other) |
1402 | \since 4.8 |
1403 | |
1404 | Swaps key sequence \a other with this key sequence. This operation is very |
1405 | fast and never fails. |
1406 | */ |
1407 | |
1408 | /*! |
1409 | \fn bool QKeySequence::operator!=(const QKeySequence &other) const |
1410 | |
1411 | Returns \c true if this key sequence is not equal to the \a other |
1412 | key sequence; otherwise returns \c false. |
1413 | */ |
1414 | |
1415 | |
1416 | /*! |
1417 | Returns \c true if this key sequence is equal to the \a other |
1418 | key sequence; otherwise returns \c false. |
1419 | */ |
1420 | bool QKeySequence::operator==(const QKeySequence &other) const |
1421 | { |
1422 | return (d->key[0] == other.d->key[0] && |
1423 | d->key[1] == other.d->key[1] && |
1424 | d->key[2] == other.d->key[2] && |
1425 | d->key[3] == other.d->key[3]); |
1426 | } |
1427 | |
1428 | /*! |
1429 | \since 5.6 |
1430 | \relates QKeySequence |
1431 | |
1432 | Calculates the hash value of \a key, using |
1433 | \a seed to seed the calculation. |
1434 | */ |
1435 | size_t qHash(const QKeySequence &key, size_t seed) noexcept |
1436 | { |
1437 | return qHashRange(first: key.d->key, last: key.d->key + QKeySequencePrivate::MaxKeyCount, seed); |
1438 | } |
1439 | |
1440 | /*! |
1441 | Provides an arbitrary comparison of this key sequence and |
1442 | \a other key sequence. All that is guaranteed is that the |
1443 | operator returns \c false if both key sequences are equal and |
1444 | that (ks1 \< ks2) == !( ks2 \< ks1) if the key sequences |
1445 | are not equal. |
1446 | |
1447 | This function is useful in some circumstances, for example |
1448 | if you want to use QKeySequence objects as keys in a QMap. |
1449 | |
1450 | \sa operator==(), operator!=(), operator>(), operator<=(), operator>=() |
1451 | */ |
1452 | bool QKeySequence::operator< (const QKeySequence &other) const |
1453 | { |
1454 | return std::lexicographical_compare(first1: d->key, last1: d->key + QKeySequencePrivate::MaxKeyCount, |
1455 | first2: other.d->key, last2: other.d->key + QKeySequencePrivate::MaxKeyCount); |
1456 | } |
1457 | |
1458 | /*! |
1459 | \fn bool QKeySequence::operator> (const QKeySequence &other) const |
1460 | |
1461 | Returns \c true if this key sequence is larger than the \a other key |
1462 | sequence; otherwise returns \c false. |
1463 | |
1464 | \sa operator==(), operator!=(), operator<(), operator<=(), operator>=() |
1465 | */ |
1466 | |
1467 | /*! |
1468 | \fn bool QKeySequence::operator<= (const QKeySequence &other) const |
1469 | |
1470 | Returns \c true if this key sequence is smaller or equal to the |
1471 | \a other key sequence; otherwise returns \c false. |
1472 | |
1473 | \sa operator==(), operator!=(), operator<(), operator>(), operator>=() |
1474 | */ |
1475 | |
1476 | /*! |
1477 | \fn bool QKeySequence::operator>= (const QKeySequence &other) const |
1478 | |
1479 | Returns \c true if this key sequence is larger or equal to the |
1480 | \a other key sequence; otherwise returns \c false. |
1481 | |
1482 | \sa operator==(), operator!=(), operator<(), operator>(), operator<=() |
1483 | */ |
1484 | |
1485 | /*! |
1486 | \internal |
1487 | */ |
1488 | bool QKeySequence::isDetached() const |
1489 | { |
1490 | return d->ref.loadRelaxed() == 1; |
1491 | } |
1492 | |
1493 | /*! |
1494 | \since 4.1 |
1495 | |
1496 | Return a string representation of the key sequence, |
1497 | based on \a format. |
1498 | |
1499 | For example, the value Qt::CTRL+Qt::Key_O results in "Ctrl+O". |
1500 | If the key sequence has multiple key codes, each is separated |
1501 | by commas in the string returned, such as "Alt+X, Ctrl+Y, Z". |
1502 | The strings, "Ctrl", "Shift", etc. are translated using |
1503 | QObject::tr() in the "QShortcut" context. |
1504 | |
1505 | If the key sequence has no keys, an empty string is returned. |
1506 | |
1507 | On \macos, the string returned resembles the sequence that is |
1508 | shown in the menu bar if \a format is |
1509 | QKeySequence::NativeText; otherwise, the string uses the |
1510 | "portable" format, suitable for writing to a file. |
1511 | |
1512 | \sa fromString() |
1513 | */ |
1514 | QString QKeySequence::toString(SequenceFormat format) const |
1515 | { |
1516 | QString finalString; |
1517 | // A standard string, with no translation or anything like that. In some ways it will |
1518 | // look like our latin case on Windows and X11 |
1519 | int end = count(); |
1520 | for (int i = 0; i < end; ++i) { |
1521 | finalString += d->encodeString(key: d->key[i], format); |
1522 | finalString += ", "_L1 ; |
1523 | } |
1524 | finalString.truncate(pos: finalString.size() - 2); |
1525 | return finalString; |
1526 | } |
1527 | |
1528 | /*! |
1529 | \since 4.1 |
1530 | |
1531 | Return a QKeySequence from the string \a str based on \a format. |
1532 | |
1533 | \sa toString() |
1534 | */ |
1535 | QKeySequence QKeySequence::fromString(const QString &str, SequenceFormat format) |
1536 | { |
1537 | return QKeySequence(str, format); |
1538 | } |
1539 | |
1540 | /*! |
1541 | \since 5.1 |
1542 | |
1543 | Return a list of QKeySequence from the string \a str based on \a format. |
1544 | |
1545 | \sa fromString() |
1546 | \sa listToString() |
1547 | */ |
1548 | QList<QKeySequence> QKeySequence::listFromString(const QString &str, SequenceFormat format) |
1549 | { |
1550 | QList<QKeySequence> result; |
1551 | |
1552 | const QStringList strings = str.split(sep: "; "_L1 ); |
1553 | result.reserve(asize: strings.size()); |
1554 | for (const QString &string : strings) { |
1555 | result << fromString(str: string, format); |
1556 | } |
1557 | |
1558 | return result; |
1559 | } |
1560 | |
1561 | /*! |
1562 | \since 5.1 |
1563 | |
1564 | Return a string representation of \a list based on \a format. |
1565 | |
1566 | \sa toString() |
1567 | \sa listFromString() |
1568 | */ |
1569 | QString QKeySequence::listToString(const QList<QKeySequence> &list, SequenceFormat format) |
1570 | { |
1571 | QString result; |
1572 | |
1573 | for (const QKeySequence &sequence : list) { |
1574 | result += sequence.toString(format); |
1575 | result += "; "_L1 ; |
1576 | } |
1577 | result.truncate(pos: result.size() - 2); |
1578 | |
1579 | return result; |
1580 | } |
1581 | |
1582 | /***************************************************************************** |
1583 | QKeySequence stream functions |
1584 | *****************************************************************************/ |
1585 | #if !defined(QT_NO_DATASTREAM) |
1586 | /*! |
1587 | \fn QDataStream &operator<<(QDataStream &stream, const QKeySequence &sequence) |
1588 | \relates QKeySequence |
1589 | |
1590 | Writes the key \a sequence to the \a stream. |
1591 | |
1592 | \sa{Serializing Qt Data Types}{Format of the QDataStream operators} |
1593 | */ |
1594 | QDataStream &operator<<(QDataStream &s, const QKeySequence &keysequence) |
1595 | { |
1596 | static_assert(QKeySequencePrivate::MaxKeyCount == 4, "Forgot to adapt QDataStream &operator<<(QDataStream &s, const QKeySequence &keysequence) to new QKeySequence::MaxKeyCount" ); |
1597 | const bool extended = s.version() >= 5 && keysequence.count() > 1; |
1598 | s << quint32(extended ? 4 : 1) << quint32(keysequence.d->key[0]); |
1599 | if (extended) { |
1600 | s << quint32(keysequence.d->key[1]) |
1601 | << quint32(keysequence.d->key[2]) |
1602 | << quint32(keysequence.d->key[3]); |
1603 | } |
1604 | return s; |
1605 | } |
1606 | |
1607 | |
1608 | /*! |
1609 | \fn QDataStream &operator>>(QDataStream &stream, QKeySequence &sequence) |
1610 | \relates QKeySequence |
1611 | |
1612 | Reads a key sequence from the \a stream into the key \a sequence. |
1613 | |
1614 | \sa{Serializing Qt Data Types}{Format of the QDataStream operators} |
1615 | */ |
1616 | QDataStream &operator>>(QDataStream &s, QKeySequence &keysequence) |
1617 | { |
1618 | const quint32 MaxKeys = QKeySequencePrivate::MaxKeyCount; |
1619 | quint32 c; |
1620 | s >> c; |
1621 | quint32 keys[MaxKeys] = {0}; |
1622 | for (uint i = 0; i < qMin(a: c, b: MaxKeys); ++i) { |
1623 | if (s.atEnd()) { |
1624 | qWarning(msg: "Premature EOF while reading QKeySequence" ); |
1625 | return s; |
1626 | } |
1627 | s >> keys[i]; |
1628 | } |
1629 | qAtomicDetach(d&: keysequence.d); |
1630 | std::copy(first: keys, last: keys + MaxKeys, QT_MAKE_CHECKED_ARRAY_ITERATOR(keysequence.d->key, MaxKeys)); |
1631 | return s; |
1632 | } |
1633 | |
1634 | #endif //QT_NO_DATASTREAM |
1635 | |
1636 | #ifndef QT_NO_DEBUG_STREAM |
1637 | QDebug operator<<(QDebug dbg, const QKeySequence &p) |
1638 | { |
1639 | QDebugStateSaver saver(dbg); |
1640 | dbg.nospace() << "QKeySequence(" << p.toString() << ')'; |
1641 | return dbg; |
1642 | } |
1643 | #endif |
1644 | |
1645 | /*! |
1646 | \typedef QKeySequence::DataPtr |
1647 | \internal |
1648 | */ |
1649 | |
1650 | /*! |
1651 | \fn DataPtr &QKeySequence::data_ptr() |
1652 | \internal |
1653 | */ |
1654 | |
1655 | QT_END_NAMESPACE |
1656 | |
1657 | #include "moc_qkeysequence.cpp" |
1658 | |