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