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
58QT_BEGIN_NAMESPACE
59
60#if defined(Q_OS_MACOS) || defined(Q_CLANG_QDOC)
61static bool qt_sequence_no_mnemonics = true;
62struct 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
69static const int kShiftUnicode = 0x21E7;
70static const int kControlUnicode = 0x2303;
71static const int kOptionUnicode = 0x2325;
72static const int kCommandUnicode = 0x2318;
73
74static const int NumEntries = 21;
75static 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
98static bool operator<(const MacSpecialKey &entry, int key)
99{
100 return entry.key < key;
101}
102
103static bool operator<(int key, const MacSpecialKey &entry)
104{
105 return key < entry.key;
106}
107
108static const MacSpecialKey * const MacSpecialKeyEntriesEnd = entries + NumEntries;
109
110QChar 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
127static 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
148static 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*/
167void 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
413static 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};
704static 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*/
806QKeySequence::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*/
822QKeySequence::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*/
848QKeySequence::QKeySequence(const QString &key, QKeySequence::SequenceFormat format)
849{
850 d = new QKeySequencePrivate();
851 assign(key, format);
852}
853
854static_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*/
863QKeySequence::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*/
878QKeySequence::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 */
886QKeySequence::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*/
901QList<QKeySequence> QKeySequence::keyBindings(StandardKey key)
902{
903 return QGuiApplicationPrivate::platformTheme()->keyBindings(key);
904}
905
906/*!
907 Destroys the key sequence.
908 */
909QKeySequence::~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
922void 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
929static_assert(QKeySequencePrivate::MaxKeyCount == 4, "Change docs below");
930/*!
931 Returns the number of keys in the key sequence.
932 The maximum is 4.
933 */
934int 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*/
944bool 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*/
963QKeySequence 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*/
1006int 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*/
1020int 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
1055struct 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};
1062Q_DECLARE_TYPEINFO(QModifKeyName, Q_MOVABLE_TYPE);
1063
1064Q_GLOBAL_STATIC(QList<QModifKeyName>, globalModifs)
1065Q_GLOBAL_STATIC(QList<QModifKeyName>, globalPortableModifs)
1066
1067/*!
1068 Constructs a single key from the string \a str.
1069*/
1070int QKeySequence::decodeString(const QString &str)
1071{
1072 return QKeySequencePrivate::decodeString(str, NativeText);
1073}
1074
1075int 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 */
1228QString QKeySequence::encodeString(int key)
1229{
1230 return QKeySequencePrivate::encodeString(key, NativeText);
1231}
1232
1233static 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
1247QString 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*/
1317QString 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)
1346NonSymbol:
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*/
1378QKeySequence::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*/
1402QKeySequence::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 */
1411QKeyCombination 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 */
1422QKeySequence &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 */
1448bool 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*/
1462size_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*/
1479bool 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*/
1515bool 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*/
1541QString 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*/
1562QKeySequence 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*/
1575QList<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*/
1596QString 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*/
1621QDataStream &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*/
1643QDataStream &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
1664QDebug 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
1682QT_END_NAMESPACE
1683