~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/gui/kernel/qkeysequence.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
 
4
**
 
5
** This file is part of the gui module of the Qt Toolkit.
 
6
**
 
7
** This file may be distributed under the terms of the Q Public License
 
8
** as defined by Trolltech AS of Norway and appearing in the file
 
9
** LICENSE.QPL included in the packaging of this file.
 
10
**
 
11
** This file may be distributed and/or modified under the terms of the
 
12
** GNU General Public License version 2 as published by the Free Software
 
13
** Foundation and appearing in the file LICENSE.GPL included in the
 
14
** packaging of this file.
 
15
**
 
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
 
17
**   information about Qt Commercial License Agreements.
 
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
 
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
 
20
**
 
21
** Contact info@trolltech.com if any conditions of this licensing are
 
22
** not clear to you.
 
23
**
 
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
26
**
 
27
****************************************************************************/
 
28
 
 
29
#include "qkeysequence.h"
 
30
 
 
31
#include "qshortcut.h"
 
32
#include "qdebug.h"
 
33
#ifndef QT_NO_REGEXP
 
34
# include "qregexp.h"
 
35
#endif
 
36
#ifndef QT_NO_DATASTREAM
 
37
# include "qdatastream.h"
 
38
#endif
 
39
#include "qvariant.h"
 
40
 
 
41
#ifdef Q_WS_MAC
 
42
# include <private/qt_mac_p.h>
 
43
# define QMAC_CTRL QChar(kCommandUnicode)
 
44
# define QMAC_META QChar(kControlUnicode)
 
45
# define QMAC_ALT  QChar(kOptionUnicode)
 
46
# define QMAC_SHIFT QChar(kShiftUnicode)
 
47
#endif
 
48
 
 
49
#ifdef Q_WS_MAC
 
50
static bool qt_sequence_no_mnemonics = true;
 
51
#else
 
52
static bool qt_sequence_no_mnemonics = false;
 
53
#endif
 
54
void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemonics = !b; }
 
55
 
 
56
/*!
 
57
    \class QKeySequence
 
58
    \brief The QKeySequence class encapsulates a key sequence as used
 
59
    by shortcuts.
 
60
 
 
61
    \ingroup misc
 
62
    \mainclass
 
63
 
 
64
    A key sequence consists of up to four keyboard codes, each
 
65
    optionally combined with modifiers, such as \c Qt::SHIFT, \c Qt::CTRL, \c
 
66
    Qt::ALT or \c Qt::META. For example, \c{Qt::CTRL + Qt::Key_P}
 
67
    might be a sequence used as a shortcut for printing a document.
 
68
    Valid codes for keys and modifiers are listed in Qt::Key and
 
69
    Qt::Modifier. As an alternative, use the unicode code point of the
 
70
    character; for example, \c{'A'} gives the same key sequence
 
71
    as \c Qt::Key_A.
 
72
 
 
73
    Key sequences can be constructed either from an integer key code,
 
74
    or from a human readable translatable string such as
 
75
    "Ctrl+X,Alt+Space". A key sequence can be cast to a QString to
 
76
    obtain a human readable translated version of the sequence.
 
77
    Translations are done in the "QShortcut" context.
 
78
 
 
79
    In code that does not inherit the Qt namespace class, you must
 
80
    include the namespace when writing keycodes; for example,
 
81
    instead of Qt::ALT+Qt::Key_Q you would write Qt::ALT+Qt::Key_Q.
 
82
 
 
83
    \sa QShortcut
 
84
*/
 
85
 
 
86
/*!
 
87
    \enum QKeySequence::SequenceMatch
 
88
 
 
89
    \value NoMatch The key sequences are different; not even partially
 
90
    matching.
 
91
    \value PartialMatch The key sequences match partially, but are not
 
92
    the same.
 
93
    \value ExactMatch The key sequences are the same.
 
94
    \omitvalue Identical
 
95
*/
 
96
 
 
97
static struct {
 
98
    int key;
 
99
    const char* name;
 
100
} keyname[] = {
 
101
    { Qt::Key_Space,        QT_TRANSLATE_NOOP("QShortcut", "Space") },
 
102
    { Qt::Key_Escape,       QT_TRANSLATE_NOOP("QShortcut", "Esc") },
 
103
    { Qt::Key_Tab,          QT_TRANSLATE_NOOP("QShortcut", "Tab") },
 
104
    { Qt::Key_Backtab,      QT_TRANSLATE_NOOP("QShortcut", "Backtab") },
 
105
    { Qt::Key_Backspace,    QT_TRANSLATE_NOOP("QShortcut", "Backspace") },
 
106
    { Qt::Key_Return,       QT_TRANSLATE_NOOP("QShortcut", "Return") },
 
107
    { Qt::Key_Enter,        QT_TRANSLATE_NOOP("QShortcut", "Enter") },
 
108
    { Qt::Key_Insert,       QT_TRANSLATE_NOOP("QShortcut", "Ins") },
 
109
    { Qt::Key_Delete,       QT_TRANSLATE_NOOP("QShortcut", "Del") },
 
110
    { Qt::Key_Pause,        QT_TRANSLATE_NOOP("QShortcut", "Pause") },
 
111
    { Qt::Key_Print,        QT_TRANSLATE_NOOP("QShortcut", "Print") },
 
112
    { Qt::Key_SysReq,       QT_TRANSLATE_NOOP("QShortcut", "SysReq") },
 
113
    { Qt::Key_Home,         QT_TRANSLATE_NOOP("QShortcut", "Home") },
 
114
    { Qt::Key_End,          QT_TRANSLATE_NOOP("QShortcut", "End") },
 
115
    { Qt::Key_Left,         QT_TRANSLATE_NOOP("QShortcut", "Left") },
 
116
    { Qt::Key_Up,           QT_TRANSLATE_NOOP("QShortcut", "Up") },
 
117
    { Qt::Key_Right,        QT_TRANSLATE_NOOP("QShortcut", "Right") },
 
118
    { Qt::Key_Down,         QT_TRANSLATE_NOOP("QShortcut", "Down") },
 
119
    { Qt::Key_PageUp,       QT_TRANSLATE_NOOP("QShortcut", "PgUp") },
 
120
    { Qt::Key_PageDown,     QT_TRANSLATE_NOOP("QShortcut", "PgDown") },
 
121
    { Qt::Key_CapsLock,     QT_TRANSLATE_NOOP("QShortcut", "CapsLock") },
 
122
    { Qt::Key_NumLock,      QT_TRANSLATE_NOOP("QShortcut", "NumLock") },
 
123
    { Qt::Key_ScrollLock,   QT_TRANSLATE_NOOP("QShortcut", "ScrollLock") },
 
124
    { Qt::Key_Menu,         QT_TRANSLATE_NOOP("QShortcut", "Menu") },
 
125
    { Qt::Key_Help,         QT_TRANSLATE_NOOP("QShortcut", "Help") },
 
126
 
 
127
    // Multimedia keys
 
128
    { Qt::Key_Back,         QT_TRANSLATE_NOOP("QShortcut", "Back") },
 
129
    { Qt::Key_Forward,      QT_TRANSLATE_NOOP("QShortcut", "Forward") },
 
130
    { Qt::Key_Stop,         QT_TRANSLATE_NOOP("QShortcut", "Stop") },
 
131
    { Qt::Key_Refresh,      QT_TRANSLATE_NOOP("QShortcut", "Refresh") },
 
132
    { Qt::Key_VolumeDown,   QT_TRANSLATE_NOOP("QShortcut", "Volume Down") },
 
133
    { Qt::Key_VolumeMute,   QT_TRANSLATE_NOOP("QShortcut", "Volume Mute") },
 
134
    { Qt::Key_VolumeUp,     QT_TRANSLATE_NOOP("QShortcut", "Volume Up") },
 
135
    { Qt::Key_BassBoost,    QT_TRANSLATE_NOOP("QShortcut", "Bass Boost") },
 
136
    { Qt::Key_BassUp,       QT_TRANSLATE_NOOP("QShortcut", "Bass Up") },
 
137
    { Qt::Key_BassDown,     QT_TRANSLATE_NOOP("QShortcut", "Bass Down") },
 
138
    { Qt::Key_TrebleUp,     QT_TRANSLATE_NOOP("QShortcut", "Treble Up") },
 
139
    { Qt::Key_TrebleDown,   QT_TRANSLATE_NOOP("QShortcut", "Treble Down") },
 
140
    { Qt::Key_MediaPlay,    QT_TRANSLATE_NOOP("QShortcut", "Media Play") },
 
141
    { Qt::Key_MediaStop,    QT_TRANSLATE_NOOP("QShortcut", "Media Stop") },
 
142
    { Qt::Key_MediaPrevious,QT_TRANSLATE_NOOP("QShortcut", "Media Previous") },
 
143
    { Qt::Key_MediaNext,    QT_TRANSLATE_NOOP("QShortcut", "Media Next") },
 
144
    { Qt::Key_MediaRecord,  QT_TRANSLATE_NOOP("QShortcut", "Media Record") },
 
145
    { Qt::Key_HomePage,     QT_TRANSLATE_NOOP("QShortcut", "Home") },
 
146
    { Qt::Key_Favorites,    QT_TRANSLATE_NOOP("QShortcut", "Favorites") },
 
147
    { Qt::Key_Search,       QT_TRANSLATE_NOOP("QShortcut", "Search") },
 
148
    { Qt::Key_Standby,      QT_TRANSLATE_NOOP("QShortcut", "Standby") },
 
149
    { Qt::Key_OpenUrl,      QT_TRANSLATE_NOOP("QShortcut", "Open URL") },
 
150
    { Qt::Key_LaunchMail,   QT_TRANSLATE_NOOP("QShortcut", "Launch Mail") },
 
151
    { Qt::Key_LaunchMedia,  QT_TRANSLATE_NOOP("QShortcut", "Launch Media") },
 
152
    { Qt::Key_Launch0,      QT_TRANSLATE_NOOP("QShortcut", "Launch (0)") },
 
153
    { Qt::Key_Launch1,      QT_TRANSLATE_NOOP("QShortcut", "Launch (1)") },
 
154
    { Qt::Key_Launch2,      QT_TRANSLATE_NOOP("QShortcut", "Launch (2)") },
 
155
    { Qt::Key_Launch3,      QT_TRANSLATE_NOOP("QShortcut", "Launch (3)") },
 
156
    { Qt::Key_Launch4,      QT_TRANSLATE_NOOP("QShortcut", "Launch (4)") },
 
157
    { Qt::Key_Launch5,      QT_TRANSLATE_NOOP("QShortcut", "Launch (5)") },
 
158
    { Qt::Key_Launch6,      QT_TRANSLATE_NOOP("QShortcut", "Launch (6)") },
 
159
    { Qt::Key_Launch7,      QT_TRANSLATE_NOOP("QShortcut", "Launch (7)") },
 
160
    { Qt::Key_Launch8,      QT_TRANSLATE_NOOP("QShortcut", "Launch (8)") },
 
161
    { Qt::Key_Launch9,      QT_TRANSLATE_NOOP("QShortcut", "Launch (9)") },
 
162
    { Qt::Key_LaunchA,      QT_TRANSLATE_NOOP("QShortcut", "Launch (A)") },
 
163
    { Qt::Key_LaunchB,      QT_TRANSLATE_NOOP("QShortcut", "Launch (B)") },
 
164
    { Qt::Key_LaunchC,      QT_TRANSLATE_NOOP("QShortcut", "Launch (C)") },
 
165
    { Qt::Key_LaunchD,      QT_TRANSLATE_NOOP("QShortcut", "Launch (D)") },
 
166
    { Qt::Key_LaunchE,      QT_TRANSLATE_NOOP("QShortcut", "Launch (E)") },
 
167
    { Qt::Key_LaunchF,      QT_TRANSLATE_NOOP("QShortcut", "Launch (F)") },
 
168
 
 
169
    // --------------------------------------------------------------
 
170
    // More consistent namings
 
171
    { Qt::Key_Print,        QT_TRANSLATE_NOOP("QShortcut", "Print Screen") },
 
172
    { Qt::Key_PageUp,       QT_TRANSLATE_NOOP("QShortcut", "Page Up") },
 
173
    { Qt::Key_PageDown,     QT_TRANSLATE_NOOP("QShortcut", "Page Down") },
 
174
    { Qt::Key_CapsLock,     QT_TRANSLATE_NOOP("QShortcut", "Caps Lock") },
 
175
    { Qt::Key_NumLock,      QT_TRANSLATE_NOOP("QShortcut", "Num Lock") },
 
176
    { Qt::Key_NumLock,      QT_TRANSLATE_NOOP("QShortcut", "Number Lock") },
 
177
    { Qt::Key_ScrollLock,   QT_TRANSLATE_NOOP("QShortcut", "Scroll Lock") },
 
178
    { Qt::Key_Insert,       QT_TRANSLATE_NOOP("QShortcut", "Insert") },
 
179
    { Qt::Key_Delete,       QT_TRANSLATE_NOOP("QShortcut", "Delete") },
 
180
    { Qt::Key_Escape,       QT_TRANSLATE_NOOP("QShortcut", "Escape") },
 
181
    { Qt::Key_SysReq,       QT_TRANSLATE_NOOP("QShortcut", "System Request") },
 
182
 
 
183
    { 0, 0 }
 
184
};
 
185
 
 
186
 
 
187
class QKeySequencePrivate
 
188
{
 
189
public:
 
190
    inline QKeySequencePrivate()
 
191
    {
 
192
        ref = 1;
 
193
        key[0] = key[1] = key[2] = key[3] =  0;
 
194
    }
 
195
    inline QKeySequencePrivate(const QKeySequencePrivate &copy)
 
196
    {
 
197
        ref = 1;
 
198
        key[0] = copy.key[0];
 
199
        key[1] = copy.key[1];
 
200
        key[2] = copy.key[2];
 
201
        key[3] = copy.key[3];
 
202
    }
 
203
    QAtomic ref;
 
204
    int key[4];
 
205
};
 
206
 
 
207
 
 
208
/*!
 
209
    Constructs an empty key sequence.
 
210
*/
 
211
QKeySequence::QKeySequence()
 
212
{
 
213
    d = new QKeySequencePrivate();
 
214
}
 
215
 
 
216
/*!
 
217
    Creates a key sequence from the \a key string. For example
 
218
    "Ctrl+O" gives CTRL+'O'. The strings "Ctrl",
 
219
    "Shift", "Alt" and "Meta" are recognized, as well as their
 
220
    translated equivalents in the "QShortcut" context (using
 
221
    QObject::tr()).
 
222
 
 
223
    Up to four key codes may be entered by separating them with
 
224
    commas, e.g. "Alt+X,Ctrl+S,Q".
 
225
 
 
226
    This contructor is typically used with \link QObject::tr() tr
 
227
    \endlink(), so that shortcut keys can be replaced in
 
228
    translations:
 
229
 
 
230
    \code
 
231
        QMenu *file = new QMenu(this);
 
232
        file->addAction(tr("&Open..."), this, SLOT(open()),
 
233
                          QKeySequence(tr("Ctrl+O", "File|Open")));
 
234
    \endcode
 
235
 
 
236
    Note the \c "File|Open" translator comment. It is by no means
 
237
    necessary, but it provides some context for the human translator.
 
238
*/
 
239
QKeySequence::QKeySequence(const QString &key)
 
240
{
 
241
    d = new QKeySequencePrivate();
 
242
    assign(key);
 
243
}
 
244
 
 
245
/*!
 
246
    Constructs a key sequence with up to 4 keys \a k1, \a k2,
 
247
    \a k3 and \a k4.
 
248
 
 
249
    The key codes are listed in Qt::Key and can be combined with
 
250
    modifiers (see Qt::Modifier) such as \c Qt::SHIFT, \c Qt::CTRL, \c Qt::ALT
 
251
    or \c Qt::META.
 
252
*/
 
253
QKeySequence::QKeySequence(int k1, int k2, int k3, int k4)
 
254
{
 
255
    d = new QKeySequencePrivate();
 
256
    d->key[0] = k1;
 
257
    d->key[1] = k2;
 
258
    d->key[2] = k3;
 
259
    d->key[3] = k4;
 
260
}
 
261
 
 
262
/*!
 
263
    Copy constructor. Makes a copy of \a keysequence.
 
264
 */
 
265
QKeySequence::QKeySequence(const QKeySequence& keysequence)
 
266
    : d(keysequence.d)
 
267
{
 
268
    d->ref.ref();
 
269
}
 
270
 
 
271
 
 
272
/*!
 
273
    Destroys the key sequence.
 
274
 */
 
275
QKeySequence::~QKeySequence()
 
276
{
 
277
    if (!d->ref.deref())
 
278
        delete d;
 
279
}
 
280
 
 
281
/*!
 
282
    \internal
 
283
    KeySequences should never be modified, but rather just created.
 
284
    Internally though we do need to modify to keep pace in event
 
285
    delivery.
 
286
*/
 
287
 
 
288
void QKeySequence::setKey(int key, int index)
 
289
{
 
290
    Q_ASSERT_X(index >= 0 && index < 4, "QKeySequence::setKey", "index out of range");
 
291
    qAtomicDetach(d);
 
292
    d->key[index] = key;
 
293
}
 
294
 
 
295
/*!
 
296
    Returns the number of keys in the key sequence.
 
297
    The maximum is 4.
 
298
 */
 
299
uint QKeySequence::count() const
 
300
{
 
301
    if (!d->key[0])
 
302
        return 0;
 
303
    if (!d->key[1])
 
304
        return 1;
 
305
    if (!d->key[2])
 
306
        return 2;
 
307
    if (!d->key[3])
 
308
        return 3;
 
309
    return 4;
 
310
}
 
311
 
 
312
 
 
313
/*!
 
314
    Returns true if the key sequence is empty; otherwise returns
 
315
    false.
 
316
*/
 
317
bool QKeySequence::isEmpty() const
 
318
{
 
319
    return !d->key[0];
 
320
}
 
321
 
 
322
 
 
323
/*!
 
324
    Returns the shortcut key sequence for the mnemonic in \a text,
 
325
    or an empty key sequence if no mnemonics are found.
 
326
 
 
327
    For example, mnemonic("E&amp;xit") returns Qt::ALT+Qt::Key_X,
 
328
    mnemonic("&amp;Quit") returns ALT+Key_Q, and mnemonic("Quit")
 
329
    returns an empty QKeySequence.
 
330
 
 
331
    We provide a \link accelerators.html list of common mnemonics
 
332
    \endlink in English. At the time of writing, Microsoft and Open
 
333
    Group do not appear to have issued equivalent recommendations for
 
334
    other languages.
 
335
*/
 
336
QKeySequence QKeySequence::mnemonic(const QString &text)
 
337
{
 
338
    if(qt_sequence_no_mnemonics)
 
339
        return QKeySequence();
 
340
 
 
341
    int p = 0;
 
342
    while (p >= 0) {
 
343
        p = text.indexOf('&', p) + 1;
 
344
        if (p <= 0 || p >= (int)text.length())
 
345
            break;
 
346
        if (text.at(p) != '&') {
 
347
            QChar c = text.at(p);
 
348
            if (c.isPrint()) {
 
349
                c = c.toUpper();
 
350
                return QKeySequence(c.unicode() + Qt::ALT);
 
351
            }
 
352
        }
 
353
        p++;
 
354
    }
 
355
    return QKeySequence();
 
356
}
 
357
 
 
358
/*!
 
359
    \fn int QKeySequence::assign(const QString &keys)
 
360
 
 
361
    Adds the given \a keys to the key sequence. \a keys may
 
362
    contain up to four key codes, provided they are separated by a
 
363
    comma; for example, "Alt+X,Ctrl+S,Z". The return value is the
 
364
    number of key codes added.
 
365
*/
 
366
int QKeySequence::assign(const QString &ks)
 
367
{
 
368
    QString keyseq = ks;
 
369
    QString part;
 
370
    int n = 0;
 
371
    int p = 0, diff = 0;
 
372
 
 
373
    // Run through the whole string, but stop
 
374
    // if we have 4 keys before the end.
 
375
    while (keyseq.length() && n < 4) {
 
376
        // We MUST use something to seperate each sequence, and space
 
377
        // does not cut it, since some of the key names have space
 
378
        // in them.. (Let's hope no one translate with a comma in it:)
 
379
        p = keyseq.indexOf(',');
 
380
        if (-1 != p) {
 
381
            if (',' == keyseq[p+1]) // e.g. 'Ctrl+,, Shift+,,'
 
382
                p++;
 
383
            if (' ' == keyseq[p+1]) { // Space after comma
 
384
                diff = 1;
 
385
                p++;
 
386
            } else {
 
387
                diff = 0;
 
388
            }
 
389
        }
 
390
        part = keyseq.left(-1 == p ? keyseq.length() : p - diff);
 
391
        keyseq = keyseq.right(-1 == p ? 0 : keyseq.length() - (p + 1));
 
392
        d->key[n] = decodeString(part);
 
393
        ++n;
 
394
    }
 
395
    return n;
 
396
}
 
397
 
 
398
struct ModifKeyName {
 
399
    ModifKeyName() { }
 
400
    ModifKeyName(int q, QChar n) : qt_key(q), name(n) { }
 
401
    ModifKeyName(int q, const QString &n) : qt_key(q), name(n) { }
 
402
    int qt_key;
 
403
    QString name;
 
404
};
 
405
 
 
406
Q_GLOBAL_STATIC(QList<ModifKeyName>, globalModifs)
 
407
 
 
408
/*!
 
409
  Constructs a single key from the string \a str.
 
410
*/
 
411
int QKeySequence::decodeString(const QString &str)
 
412
{
 
413
    int ret = 0;
 
414
    QString accel = str.toLower();
 
415
 
 
416
    QList<ModifKeyName> *gmodifs = globalModifs();
 
417
    if (!gmodifs) return ret;
 
418
 
 
419
    if (gmodifs->isEmpty()) {
 
420
#ifdef QMAC_CTRL
 
421
        *gmodifs << ModifKeyName(Qt::CTRL, QMAC_CTRL);
 
422
#endif
 
423
#ifdef QMAC_ALT
 
424
        *gmodifs << ModifKeyName(Qt::ALT, QMAC_ALT);
 
425
#endif
 
426
#ifdef QMAC_META
 
427
        *gmodifs << ModifKeyName(Qt::META, QMAC_META);
 
428
#endif
 
429
#ifdef QMAC_SHIFT
 
430
        *gmodifs << ModifKeyName(Qt::SHIFT, QMAC_SHIFT);
 
431
#endif
 
432
        *gmodifs << ModifKeyName(Qt::CTRL, "ctrl+")
 
433
                 << ModifKeyName(Qt::SHIFT, "shift+")
 
434
                 << ModifKeyName(Qt::ALT, "alt+")
 
435
                 << ModifKeyName(Qt::META, "meta+");
 
436
    }
 
437
 
 
438
    QList<ModifKeyName> modifs = *gmodifs;
 
439
    modifs << ModifKeyName(Qt::CTRL, QShortcut::tr("Ctrl").toLower().append(QLatin1Char('+')))
 
440
           << ModifKeyName(Qt::SHIFT, QShortcut::tr("Shift").toLower().append(QLatin1Char('+')))
 
441
           << ModifKeyName(Qt::ALT, QShortcut::tr("Alt").toLower().append(QLatin1Char('+')))
 
442
           << ModifKeyName(Qt::ALT, QShortcut::tr("Meta").toLower().append(QLatin1Char('+')));
 
443
 
 
444
 
 
445
 
 
446
    QString sl = accel;
 
447
    for (int i = 0; i < modifs.size(); ++i) {
 
448
        const ModifKeyName &mkf = modifs.at(i);
 
449
        if (sl.contains(mkf.name)) {
 
450
            ret |= mkf.qt_key;
 
451
            accel.remove(mkf.name);
 
452
            sl = accel;
 
453
        }
 
454
    }
 
455
 
 
456
    int p = accel.lastIndexOf('+', str.length() - 2); // -2 so that Ctrl++ works
 
457
    if(p > 0)
 
458
        accel = accel.mid(p + 1);
 
459
 
 
460
    int fnum = 0;
 
461
    if (accel.length() == 1) {
 
462
        ret |= accel[0].toUpper().unicode();
 
463
    } else if (accel[0] == 'f' && (fnum = accel.mid(1).toInt())) {
 
464
        ret |= Qt::Key_F1 + fnum - 1;
 
465
    } else {
 
466
        // Check through translation table for the correct key name
 
467
        // ...or fall back on english table.
 
468
        bool found = false;
 
469
        for (int tran = 0; tran < 2; ++tran) {
 
470
            for (int i = 0; keyname[i].name; ++i) {
 
471
                QString keyName(tran
 
472
                                ? QShortcut::tr(keyname[i].name)
 
473
                                : QString::fromLatin1(keyname[i].name));
 
474
                if (accel == keyName.toLower()) {
 
475
                    ret |= keyname[i].key;
 
476
                    found = true;
 
477
                    break;
 
478
                }
 
479
            }
 
480
            if(found)
 
481
                break;
 
482
        }
 
483
    }
 
484
    return ret;
 
485
}
 
486
 
 
487
 
 
488
/*!
 
489
    Creates a shortcut string for \a key. For example,
 
490
    Qt::CTRL+Qt::Key_O gives "Ctrl+O". The strings, "Ctrl", "Shift", etc. are
 
491
    translated (using QObject::tr()) in the "QShortcut" context.
 
492
 */
 
493
QString QKeySequence::encodeString(int key)
 
494
{
 
495
    QString s;
 
496
#if defined(Q_OS_MAC) && !defined(QWS)
 
497
    // On MAC the order is Meta, Alt, Shift, Control.
 
498
    if ((key & Qt::META) == Qt::META)
 
499
        s += QMAC_META;
 
500
    if ((key & Qt::ALT) == Qt::ALT)
 
501
        s += QMAC_ALT;
 
502
    if ((key & Qt::SHIFT) == Qt::SHIFT)
 
503
        s += QMAC_SHIFT;
 
504
    if ((key & Qt::CTRL) == Qt::CTRL)
 
505
        s += QMAC_CTRL;
 
506
#else
 
507
    // On other systems the order is Meta, Control, Alt, Shift
 
508
    if ((key & Qt::META) == Qt::META)
 
509
        s += QShortcut::tr("Meta");
 
510
    if ((key & Qt::CTRL) == Qt::CTRL) {
 
511
        if (!s.isEmpty())
 
512
            s += QShortcut::tr("+");
 
513
        s += QShortcut::tr("Ctrl");
 
514
    }
 
515
    if ((key & Qt::ALT) == Qt::ALT) {
 
516
        if (!s.isEmpty())
 
517
            s += QShortcut::tr("+");
 
518
        s += QShortcut::tr("Alt");
 
519
    }
 
520
    if ((key & Qt::SHIFT) == Qt::SHIFT) {
 
521
        if (!s.isEmpty())
 
522
            s += QShortcut::tr("+");
 
523
        s += QShortcut::tr("Shift");
 
524
    }
 
525
#endif
 
526
 
 
527
 
 
528
    key &= ~(Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier);
 
529
    QString p;
 
530
 
 
531
    if (key && key < Qt::Key_Escape) {
 
532
        if (key < 0x10000) {
 
533
            p = QChar(key & 0xffff).toUpper();
 
534
        } else {
 
535
            p = QChar((key-0x10000)/0x400+0xd800);
 
536
            p += QChar((key-0x10000)%400+0xdc00);
 
537
        }
 
538
    } else if (key >= Qt::Key_F1 && key <= Qt::Key_F35) {
 
539
        p = QShortcut::tr("F%1").arg(key - Qt::Key_F1 + 1);
 
540
    } else if (key > Qt::Key_Space && key <= Qt::Key_AsciiTilde) {
 
541
        p.sprintf("%c", key);
 
542
    } else if (key) {
 
543
        int i=0;
 
544
        while (keyname[i].name) {
 
545
            if (key == keyname[i].key) {
 
546
                p = QShortcut::tr(keyname[i].name);
 
547
                break;
 
548
            }
 
549
            ++i;
 
550
        }
 
551
        // If we can't find the actual translatable keyname,
 
552
        // fall back on the unicode representation of it...
 
553
        // Or else characters like Qt::Key_aring may not get displayed
 
554
        // (Really depends on you locale)
 
555
        if (!keyname[i].name) {
 
556
            if (key < 0x10000) {
 
557
                p = QChar(key & 0xffff).toUpper();
 
558
            } else {
 
559
                p = QChar((key-0x10000)/0x400+0xd800);
 
560
                p += QChar((key-0x10000)%400+0xdc00);
 
561
            }
 
562
        }
 
563
    }
 
564
 
 
565
#ifndef Q_OS_MAC
 
566
    if (!s.isEmpty())
 
567
        s += QShortcut::tr("+");
 
568
#endif
 
569
 
 
570
    s += p;
 
571
    return s;
 
572
}
 
573
 
 
574
/*!
 
575
    Matches the sequence with \a seq. Returns \c ExactMatch if
 
576
    successful, \c PartialMatch if \a seq matches incompletely,
 
577
    and \c NoMatch if the sequences have nothing in common.
 
578
    Returns \c NoMatch if \a seq is shorter.
 
579
*/
 
580
QKeySequence::SequenceMatch QKeySequence::matches(const QKeySequence &seq) const
 
581
{
 
582
    uint userN = count(),
 
583
          seqN = seq.count();
 
584
 
 
585
    if (userN > seqN)
 
586
        return NoMatch;
 
587
 
 
588
    // If equal in length, we have a potential ExactMatch sequence,
 
589
    // else we already know it can only be partial.
 
590
    SequenceMatch match = (userN == seqN ? ExactMatch : PartialMatch);
 
591
 
 
592
    for (uint i = 0; i < userN; ++i) {
 
593
        int userKey = (*this)[i],
 
594
            sequenceKey = seq[i];
 
595
        if (userKey != sequenceKey)
 
596
            return NoMatch;
 
597
    }
 
598
    return match;
 
599
}
 
600
 
 
601
 
 
602
/*!
 
603
    Creates a shortcut string for the key sequence.
 
604
 
 
605
    For example, the value Qt::CTRL+Qt::Key_O results in "Ctrl+O".
 
606
    If the key sequence has multiple key codes, each is separated
 
607
    by commas in the string returned, such as "Alt+X, Ctrl+Y, Z".
 
608
    The strings, "Ctrl", "Shift", etc. are translated using
 
609
    QObject::tr() in the "QShortcut" scope.
 
610
 
 
611
    If the key sequence has no keys, an empty string is returned.
 
612
 
 
613
    On Mac OS X, the string returned resembles the sequence that is
 
614
    shown in the menubar.
 
615
*/
 
616
QKeySequence::operator QString() const
 
617
{
 
618
    QString complete;
 
619
    int end = count();
 
620
    int i = 0;
 
621
    while (i < end) {
 
622
        complete += encodeString(d->key[i]);
 
623
        i++;
 
624
        if (i != end)
 
625
            complete += ", ";
 
626
    }
 
627
    return complete;
 
628
}
 
629
 
 
630
/*!
 
631
   Returns the key sequence as a QVariant
 
632
*/
 
633
QKeySequence::operator QVariant() const
 
634
{
 
635
    return QVariant(QVariant::KeySequence, this);
 
636
}
 
637
 
 
638
/*!
 
639
    \obsolete
 
640
    For backward compatibility: returns the first keycode
 
641
    as integer. If the key sequence is empty, 0 is returned.
 
642
 */
 
643
QKeySequence::operator int () const
 
644
{
 
645
    if (1 <= count())
 
646
        return d->key[0];
 
647
    return 0;
 
648
}
 
649
 
 
650
 
 
651
/*!
 
652
    Returns a reference to the element at position \a index in the key
 
653
    sequence. This can only be used to read an element.
 
654
 */
 
655
int QKeySequence::operator[](uint index) const
 
656
{
 
657
    Q_ASSERT_X(index < 4, "QKeySequence::operator[]", "index out of range");
 
658
    return d->key[index];
 
659
}
 
660
 
 
661
 
 
662
/*!
 
663
    Assignment operator. Assigns the \a other key sequence to this
 
664
    object.
 
665
 */
 
666
QKeySequence &QKeySequence::operator=(const QKeySequence &other)
 
667
{
 
668
    qAtomicAssign(d, other.d);
 
669
    return *this;
 
670
}
 
671
 
 
672
/*!
 
673
    \fn bool QKeySequence::operator!=(const QKeySequence &other) const
 
674
 
 
675
    Returns true if this key sequence is not equal to the \a other
 
676
    key sequence; otherwise returns false.
 
677
*/
 
678
 
 
679
 
 
680
/*!
 
681
    Returns true if this key sequence is equal to the \a other
 
682
    key sequence; otherwise returns false.
 
683
 */
 
684
bool QKeySequence::operator==(const QKeySequence &other) const
 
685
{
 
686
    return (d->key[0] == other.d->key[0] &&
 
687
            d->key[1] == other.d->key[1] &&
 
688
            d->key[2] == other.d->key[2] &&
 
689
            d->key[3] == other.d->key[3]);
 
690
}
 
691
 
 
692
 
 
693
/*!
 
694
    Provides an arbitrary comparison of this key sequence and
 
695
    \a other key sequence. All that is guaranteed is that the
 
696
    operator returns false if both key sequences are equal and
 
697
    that (ks1 \< ks2) == !( ks2 \< ks1) if the key sequences
 
698
    are not equal.
 
699
 
 
700
    This function is useful in some circumstances, for example
 
701
    if you want to use QKeySequence objects as keys in a QMap.
 
702
 
 
703
    \sa operator==() operator!=() operator>() operator<=() operator>=()
 
704
*/
 
705
bool QKeySequence::operator< (const QKeySequence &other) const
 
706
{
 
707
    for (int i = 0; i < 4; ++i)
 
708
        if (d->key[i] != other.d->key[i])
 
709
            return d->key[i] < other.d->key[i];
 
710
    return false;
 
711
}
 
712
 
 
713
/*!
 
714
    \fn bool QKeySequence::operator> (const QKeySequence &other) const
 
715
 
 
716
    Returns true if this key sequence is larger than the \a other key
 
717
    sequence; otherwise returns false.
 
718
 
 
719
    \sa operator==() operator!=() operator<() operator<=() operator>=()
 
720
*/
 
721
 
 
722
/*!
 
723
    \fn bool QKeySequence::operator<= (const QKeySequence &other) const
 
724
 
 
725
    Returns true if this key sequence is smaller or equal to the
 
726
    \a other key sequence; otherwise returns false.
 
727
 
 
728
    \sa operator==() operator!=() operator<() operator>() operator>=()
 
729
*/
 
730
 
 
731
/*!
 
732
    \fn bool QKeySequence::operator>= (const QKeySequence &other) const
 
733
 
 
734
    Returns true if this key sequence is larger or equal to the
 
735
    \a other key sequence; otherwise returns false.
 
736
 
 
737
    \sa operator==() operator!=() operator<() operator>() operator<=()
 
738
*/
 
739
 
 
740
/*!
 
741
    \internal
 
742
*/
 
743
bool QKeySequence::isDetached() const
 
744
{
 
745
    return d->ref == 1;
 
746
}
 
747
 
 
748
/*****************************************************************************
 
749
  QKeySequence stream functions
 
750
 *****************************************************************************/
 
751
#if !defined(QT_NO_DATASTREAM) && !defined(QT_NO_IMAGEIO)
 
752
/*!
 
753
    \fn QDataStream &operator<<(QDataStream &stream, const QKeySequence &sequence)
 
754
    \relates QKeySequence
 
755
 
 
756
    Writes the key \a sequence to the \a stream.
 
757
 
 
758
    \sa \link datastreamformat.html Format of the QDataStream operators \endlink
 
759
*/
 
760
QDataStream &operator<<(QDataStream &s, const QKeySequence &keysequence)
 
761
{
 
762
    QList<quint32> list;
 
763
    list << keysequence.d->key[0];
 
764
 
 
765
    if (s.version() >= 5 && keysequence.count() > 1) {
 
766
        list << keysequence.d->key[1];
 
767
        list << keysequence.d->key[2];
 
768
        list << keysequence.d->key[3];
 
769
    }
 
770
    s << list;
 
771
    return s;
 
772
}
 
773
 
 
774
 
 
775
/*!
 
776
    \fn QDataStream &operator>>(QDataStream &stream, QKeySequence &sequence)
 
777
    \relates QKeySequence
 
778
 
 
779
    Reads a key sequence from the \a stream into the key \a sequence.
 
780
 
 
781
    \sa \link datastreamformat.html Format of the QDataStream operators \endlink
 
782
*/
 
783
QDataStream &operator>>(QDataStream &s, QKeySequence &keysequence)
 
784
{
 
785
    QList<quint32> list;
 
786
    s >> list;
 
787
    for (int i = 0; i < 4; ++i)
 
788
        keysequence.d->key[i] = list.value(i);
 
789
    return s;
 
790
}
 
791
 
 
792
#endif //QT_NO_DATASTREAM
 
793
 
 
794
#ifndef QT_NO_DEBUG_STREAM
 
795
QDebug operator<<(QDebug dbg, const QKeySequence &p)
 
796
{
 
797
#ifndef Q_BROKEN_DEBUG_STREAM
 
798
    dbg.nospace() << "QKeySequence(" << QString(p) << ')';
 
799
    return dbg.space();
 
800
#else
 
801
    qWarning("This compiler doesn't support streaming QKeySequence to QDebug");
 
802
    return dbg;
 
803
    Q_UNUSED(p);
 
804
#endif
 
805
}
 
806
#endif