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