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