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