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