1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29
30#include <QtTest/QtTest>
31#include <qkeysequence.h>
32#include <qpa/qplatformtheme.h>
33#include <qpa/qplatformtheme_p.h>
34#include <private/qguiapplication_p.h>
35#include <QTranslator>
36#include <QLibraryInfo>
37
38#ifdef Q_OS_MAC
39struct MacSpecialKey {
40 int key;
41 ushort macSymbol;
42};
43
44// Unicode code points for the glyphs associated with these keys
45// Defined by Carbon headers but not anywhere in Cocoa
46static const int kShiftUnicode = 0x21E7;
47static const int kControlUnicode = 0x2303;
48static const int kOptionUnicode = 0x2325;
49static const int kCommandUnicode = 0x2318;
50
51static const int NumEntries = 21;
52static const MacSpecialKey entries[NumEntries] = {
53 { Qt::Key_Escape, 0x238B },
54 { Qt::Key_Tab, 0x21E5 },
55 { Qt::Key_Backtab, 0x21E4 },
56 { Qt::Key_Backspace, 0x232B },
57 { Qt::Key_Return, 0x21B5 },
58 { Qt::Key_Enter, 0x21B5 },
59 { Qt::Key_Delete, 0x2326 },
60 { Qt::Key_Home, 0x2196 },
61 { Qt::Key_End, 0x2198 },
62 { Qt::Key_Left, 0x2190 },
63 { Qt::Key_Up, 0x2191 },
64 { Qt::Key_Right, 0x2192 },
65 { Qt::Key_Down, 0x2193 },
66 { Qt::Key_PageUp, 0x21DE },
67 { Qt::Key_PageDown, 0x21DF },
68 { Qt::Key_Shift, kShiftUnicode },
69 { Qt::Key_Control, kCommandUnicode },
70 { Qt::Key_Meta, kControlUnicode },
71 { Qt::Key_Alt, kOptionUnicode },
72 { Qt::Key_CapsLock, 0x21EA },
73};
74
75static bool operator<(const MacSpecialKey &entry, int key)
76{
77 return entry.key < key;
78}
79
80static bool operator<(int key, const MacSpecialKey &entry)
81{
82 return key < entry.key;
83}
84
85static const MacSpecialKey * const MacSpecialKeyEntriesEnd = entries + NumEntries;
86
87static QChar macSymbolForQtKey(int key)
88{
89 const MacSpecialKey *i = std::lower_bound(entries, MacSpecialKeyEntriesEnd, key);
90 if (i == MacSpecialKeyEntriesEnd)
91 return QChar();
92 return QChar(i->macSymbol);
93}
94
95#endif
96
97class tst_QKeySequence : public QObject
98{
99 Q_OBJECT
100
101public:
102 tst_QKeySequence();
103 virtual ~tst_QKeySequence();
104
105private slots:
106 void swap();
107 void operatorQString_data();
108 void operatorQString();
109 void compareConstructors_data();
110 void compareConstructors();
111 void symetricConstructors_data();
112 void symetricConstructors();
113 void checkMultipleNames();
114 void checkMultipleCodes();
115 void mnemonic_data();
116 void mnemonic();
117 void toString_data();
118 void toString();
119 void toStringFromKeycode_data();
120 void toStringFromKeycode();
121 void streamOperators_data();
122 void streamOperators();
123 void parseString_data();
124 void parseString();
125 void fromString_data();
126 void fromString();
127 void listToString_data();
128 void listToString();
129 void listFromString_data();
130 void listFromString();
131#ifdef QT_BUILD_INTERNAL
132 void ensureSorted();
133#endif
134 void standardKeys_data();
135 void standardKeys();
136 void keyBindings();
137 void translated_data();
138 void translated();
139 void i18nKeys_data();
140 void i18nKeys();
141
142
143 void initTestCase();
144private:
145 int m_keyboardScheme;
146 QTranslator *ourTranslator;
147 QTranslator *qtTranslator;
148#ifdef Q_OS_MAC
149 static const QString MacCtrl;
150 static const QString MacMeta;
151 static const QString MacAlt;
152 static const QString MacShift;
153#endif
154
155
156};
157
158#ifdef Q_OS_MAC
159const QString tst_QKeySequence::MacCtrl = QString(QChar(0x2318));
160const QString tst_QKeySequence::MacMeta = QString(QChar(0x2303));
161const QString tst_QKeySequence::MacAlt = QString(QChar(0x2325));
162const QString tst_QKeySequence::MacShift = QString(QChar(0x21E7));
163#endif
164
165tst_QKeySequence::tst_QKeySequence() : m_keyboardScheme(QPlatformTheme::WindowsKeyboardScheme)
166{
167 if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
168 m_keyboardScheme = theme->themeHint(hint: QPlatformTheme::KeyboardScheme).toInt();
169}
170
171tst_QKeySequence::~tst_QKeySequence()
172{
173
174}
175
176void tst_QKeySequence::initTestCase()
177{
178 ourTranslator = new QTranslator(this);
179 ourTranslator->load(filename: ":/keys_de");
180 qtTranslator = new QTranslator(this);
181 qtTranslator->load(filename: ":/qt_de");
182}
183
184void tst_QKeySequence::swap()
185{
186 QKeySequence ks1(Qt::CTRL+Qt::Key_O);
187 QKeySequence ks2(Qt::CTRL+Qt::Key_L);
188 ks1.swap(other&: ks2);
189 QCOMPARE(ks1[0], int(Qt::CTRL+Qt::Key_L));
190 QCOMPARE(ks2[0], int(Qt::CTRL+Qt::Key_O));
191}
192
193void tst_QKeySequence::operatorQString_data()
194{
195 QTest::addColumn<int>(name: "modifiers");
196 QTest::addColumn<int>(name: "keycode");
197 QTest::addColumn<QString>(name: "keystring");
198
199 QTest::newRow( dataTag: "No modifier" ) << 0 << int(Qt::Key_Aring | Qt::UNICODE_ACCEL) << QString::fromLatin1( str: "\x0c5" );
200
201#ifndef Q_OS_MAC
202 QTest::newRow( dataTag: "Ctrl+Left" ) << int(Qt::CTRL) << int(Qt::Key_Left) << QString( "Ctrl+Left" );
203 QTest::newRow( dataTag: "Ctrl+," ) << int(Qt::CTRL) << int(Qt::Key_Comma) << QString( "Ctrl+," );
204 QTest::newRow( dataTag: "Alt+Left" ) << int(Qt::ALT) << int(Qt::Key_Left) << QString( "Alt+Left" );
205 QTest::newRow( dataTag: "Alt+Shift+Left" ) << int(Qt::ALT | Qt::SHIFT) << int(Qt::Key_Left) << QString( "Alt+Shift+Left" );
206 QTest::newRow( dataTag: "Ctrl" ) << int(Qt::CTRL) << int(Qt::Key_Aring | Qt::UNICODE_ACCEL) << QString::fromLatin1( str: "Ctrl+\x0c5" );
207 QTest::newRow( dataTag: "Alt" ) << int(Qt::ALT) << int(Qt::Key_Aring | Qt::UNICODE_ACCEL) << QString::fromLatin1( str: "Alt+\x0c5" );
208 QTest::newRow( dataTag: "Shift" ) << int(Qt::SHIFT) << int(Qt::Key_Aring | Qt::UNICODE_ACCEL) << QString::fromLatin1( str: "Shift+\x0c5" );
209 QTest::newRow( dataTag: "Meta" ) << int(Qt::META) << int(Qt::Key_Aring | Qt::UNICODE_ACCEL) << QString::fromLatin1( str: "Meta+\x0c5" );
210#else
211 QTest::newRow( "Ctrl+Left" ) << int(Qt::CTRL) << int(Qt::Key_Left) << MacCtrl + macSymbolForQtKey(Qt::Key_Left);
212 QTest::newRow( "Ctrl+," ) << int(Qt::CTRL) << int(Qt::Key_Comma) << MacCtrl + ",";
213 QTest::newRow( "Alt+Left" ) << int(Qt::ALT) << int(Qt::Key_Left) << MacAlt + macSymbolForQtKey(Qt::Key_Left);
214 QTest::newRow( "Alt+Shift+Left" ) << int(Qt::ALT | Qt::SHIFT) << int(Qt::Key_Left) << MacAlt + MacShift + macSymbolForQtKey(Qt::Key_Left);
215 QTest::newRow( "Ctrl" ) << int(Qt::CTRL) << int(Qt::Key_Aring | Qt::UNICODE_ACCEL) << MacCtrl + QLatin1String("\x0c5");
216 QTest::newRow( "Alt" ) << int(Qt::ALT) << int(Qt::Key_Aring | Qt::UNICODE_ACCEL) << MacAlt + QLatin1String("\x0c5");
217 QTest::newRow( "Shift" ) << int(Qt::SHIFT) << int(Qt::Key_Aring | Qt::UNICODE_ACCEL) << MacShift + QLatin1String("\x0c5");
218 QTest::newRow( "Meta" ) << int(Qt::META) << int(Qt::Key_Aring | Qt::UNICODE_ACCEL) << MacMeta + QLatin1String("\x0c5");
219#endif
220}
221
222void tst_QKeySequence::symetricConstructors_data()
223{
224 QTest::addColumn<int>(name: "modifiers");
225 QTest::addColumn<int>(name: "keycode");
226
227 QTest::newRow( dataTag: "No modifier" ) << 0 << int(Qt::Key_Aring | Qt::UNICODE_ACCEL);
228 QTest::newRow( dataTag: "Ctrl" ) << int(Qt::CTRL) << int(Qt::Key_Aring | Qt::UNICODE_ACCEL);
229 QTest::newRow( dataTag: "Alt" ) << int(Qt::ALT) << int(Qt::Key_Aring | Qt::UNICODE_ACCEL);
230 QTest::newRow( dataTag: "Shift" ) << int(Qt::SHIFT) << int(Qt::Key_Aring | Qt::UNICODE_ACCEL);
231 QTest::newRow( dataTag: "Meta" ) << int(Qt::META) << int(Qt::Key_Aring | Qt::UNICODE_ACCEL);
232}
233
234void tst_QKeySequence::compareConstructors_data()
235{
236 operatorQString_data();
237}
238
239// operator QString()
240void tst_QKeySequence::operatorQString()
241{
242 QKeySequence seq;
243 QFETCH( int, modifiers );
244 QFETCH( int, keycode );
245 QFETCH( QString, keystring );
246
247 seq = QKeySequence( modifiers | keycode );
248
249 QCOMPARE( seq.toString(QKeySequence::NativeText), keystring );
250}
251
252// this verifies that the constructors can handle the same strings in and out
253void tst_QKeySequence::symetricConstructors()
254{
255 QFETCH( int, modifiers );
256 QFETCH( int, keycode );
257
258 QKeySequence seq1( modifiers | keycode );
259 QKeySequence seq2( seq1.toString(format: QKeySequence::NativeText) );
260
261 QVERIFY( seq1 == seq2 );
262}
263
264/* Compares QKeySequence constructurs with int or QString arguments
265 We don't do this for 3.0 since it doesn't support unicode accelerators */
266void tst_QKeySequence::compareConstructors()
267{
268 QFETCH( int, modifiers );
269 QFETCH( int, keycode );
270 QFETCH( QString, keystring );
271
272 QKeySequence qstringSeq( keystring );
273 QKeySequence intSeq( modifiers | keycode );
274
275 QVERIFY( qstringSeq == intSeq );
276}
277
278void tst_QKeySequence::checkMultipleNames()
279{
280 QKeySequence oldK( "Ctrl+Page Up" );
281 QKeySequence newK( "Ctrl+PgUp" );
282 QVERIFY( oldK == newK );
283}
284
285//TODO: could test third constructor, or test fromString on all constructor-data
286void tst_QKeySequence::checkMultipleCodes()
287{
288 QKeySequence seq1("Alt+d, l");
289 QKeySequence seq2 = QKeySequence::fromString(str: "Alt+d, l");
290 QVERIFY( seq1 == seq2 );
291
292 QKeySequence seq3("Alt+d,l");
293 QKeySequence seq4 = QKeySequence::fromString(str: "Alt+d,l");
294 QVERIFY( seq3 == seq4 );
295}
296
297/*
298* We must ensure that the keyBindings data are always sorted by standardKey
299* so that we can safely perform binary searches.
300*/
301#ifdef QT_BUILD_INTERNAL
302void tst_QKeySequence::ensureSorted()
303{
304 uint N = QPlatformThemePrivate::numberOfKeyBindings;
305 uint val = QPlatformThemePrivate::keyBindings[0].standardKey;
306 for ( uint i = 1 ; i < N ; ++i) {
307 uint nextval = QPlatformThemePrivate::keyBindings[i].standardKey;
308 if (nextval < val)
309 qDebug() << "Data not sorted at index " << i;
310 QVERIFY(nextval >= val);
311 val = nextval;
312 }
313}
314#endif
315
316void tst_QKeySequence::standardKeys_data()
317{
318 QTest::addColumn<int>(name: "standardKey");
319 QTest::addColumn<QString>(name: "expected");
320 QTest::newRow(dataTag: "unknownkey") << (int)QKeySequence::UnknownKey<< QString("");
321 QTest::newRow(dataTag: "copy") << (int)QKeySequence::Copy << QString("CTRL+C");
322 QTest::newRow(dataTag: "cut") << (int)QKeySequence::Cut << QString("CTRL+X");
323 QTest::newRow(dataTag: "paste") << (int)QKeySequence::Paste << QString("CTRL+V");
324 QTest::newRow(dataTag: "delete") << (int)QKeySequence::Delete<< QString("DEL");
325 QTest::newRow(dataTag: "open") << (int)QKeySequence::Open << QString("CTRL+O");
326 QTest::newRow(dataTag: "find") << (int)QKeySequence::Find<< QString("CTRL+F");
327 if (m_keyboardScheme == QPlatformTheme::WindowsKeyboardScheme) {
328 QTest::newRow(dataTag: "addTab") << (int)QKeySequence::AddTab<< QString("CTRL+T");
329 QTest::newRow(dataTag: "findNext") << (int)QKeySequence::FindNext<< QString("F3");
330 QTest::newRow(dataTag: "findPrevious") << (int)QKeySequence::FindPrevious << QString("SHIFT+F3");
331 QTest::newRow(dataTag: "close") << (int)QKeySequence::Close<< QString("CTRL+F4");
332 QTest::newRow(dataTag: "replace") << (int)QKeySequence::Replace<< QString("CTRL+H");
333 }
334 QTest::newRow(dataTag: "bold") << (int)QKeySequence::Bold << QString("CTRL+B");
335 QTest::newRow(dataTag: "italic") << (int)QKeySequence::Italic << QString("CTRL+I");
336 QTest::newRow(dataTag: "underline") << (int)QKeySequence::Underline << QString("CTRL+U");
337 QTest::newRow(dataTag: "selectall") << (int)QKeySequence::SelectAll << QString("CTRL+A");
338 QTest::newRow(dataTag: "print") << (int)QKeySequence::Print << QString("CTRL+P");
339 QTest::newRow(dataTag: "movenextchar") << (int)QKeySequence::MoveToNextChar<< QString("RIGHT");
340 QTest::newRow(dataTag: "zoomIn") << (int)QKeySequence::ZoomIn<< QString("CTRL++");
341 QTest::newRow(dataTag: "zoomOut") << (int)QKeySequence::ZoomOut<< QString("CTRL+-");
342 QTest::newRow(dataTag: "whatsthis") << (int)QKeySequence::WhatsThis<< QString("SHIFT+F1");
343
344#if defined(Q_OS_MAC)
345 QTest::newRow("help") << (int)QKeySequence::HelpContents<< QString("Ctrl+?");
346 QTest::newRow("nextChild") << (int)QKeySequence::NextChild << QString("CTRL+}");
347 QTest::newRow("previousChild") << (int)QKeySequence::PreviousChild << QString("CTRL+{");
348 QTest::newRow("MoveToEndOfBlock") << (int)QKeySequence::MoveToEndOfBlock << QString("ALT+DOWN");
349 QTest::newRow("forward") << (int)QKeySequence::Forward << QString("CTRL+]");
350 QTest::newRow("backward") << (int)QKeySequence::Back << QString("CTRL+[");
351 QTest::newRow("SelectEndOfDocument") << (int)QKeySequence::SelectEndOfDocument<< QString("CTRL+SHIFT+DOWN"); //mac only
352#else
353 QTest::newRow(dataTag: "help") << (int)QKeySequence::HelpContents<< QString("F1");
354 QTest::newRow(dataTag: "nextChild") << (int)QKeySequence::NextChild<< QString("CTRL+Tab");
355 QTest::newRow(dataTag: "previousChild") << (int)QKeySequence::PreviousChild<< QString("CTRL+SHIFT+BACKTAB");
356 QTest::newRow(dataTag: "forward") << (int)QKeySequence::Forward << QString("ALT+RIGHT");
357 QTest::newRow(dataTag: "backward") << (int)QKeySequence::Back << QString("ALT+LEFT");
358 QTest::newRow(dataTag: "MoveToEndOfBlock") << (int)QKeySequence::MoveToEndOfBlock<< QString(""); //mac only
359 QTest::newRow(dataTag: "SelectEndOfDocument") << (int)QKeySequence::SelectEndOfDocument<< QString("CTRL+SHIFT+END"); //mac only
360#endif
361}
362
363void tst_QKeySequence::standardKeys()
364{
365 QFETCH(int, standardKey);
366 QFETCH(QString, expected);
367 QKeySequence actualKeySequence((QKeySequence::StandardKey)standardKey);
368 QKeySequence expectedKeySequence(expected);
369 QVERIFY2(actualKeySequence == expectedKeySequence,
370 qPrintable(QString::fromLatin1("Key mismatch, expected '%1', got '%2' for standard key %3").
371 arg(expected, actualKeySequence.toString()).arg(standardKey)));
372}
373
374void tst_QKeySequence::keyBindings()
375{
376 const QList<QKeySequence> bindings =
377 QKeySequence::keyBindings(key: QKeySequence::Copy);
378
379 QList<QKeySequence> expected;
380 const QKeySequence ctrlC = QKeySequence(QStringLiteral("CTRL+C"));
381 const QKeySequence ctrlInsert = QKeySequence(QStringLiteral("CTRL+INSERT"));
382 switch (m_keyboardScheme) {
383 case QPlatformTheme::MacKeyboardScheme:
384 expected << ctrlC;
385 break;
386 case QPlatformTheme::WindowsKeyboardScheme:
387 expected << ctrlC << ctrlInsert;
388 break;
389 default: // X11
390 expected << ctrlC << ctrlInsert << QKeySequence(QStringLiteral("F16"));
391 break;
392 }
393 QCOMPARE(bindings, expected);
394}
395
396void tst_QKeySequence::mnemonic_data()
397{
398#ifdef Q_OS_MAC
399 QSKIP("Test not applicable to OS X");
400#endif
401 QTest::addColumn<QString>(name: "string");
402 QTest::addColumn<QString>(name: "key");
403 QTest::addColumn<bool>(name: "warning");
404
405 QTest::newRow(dataTag: "1") << QString::fromLatin1(str: "&bonjour") << QString::fromLatin1(str: "ALT+B") << false;
406 QTest::newRow(dataTag: "2") << QString::fromLatin1(str: "&&bonjour") << QString() << false;
407 QTest::newRow(dataTag: "3") << QString::fromLatin1(str: "&&bon&jour") << QString::fromLatin1(str: "ALT+J") << false;
408 QTest::newRow(dataTag: "4") << QString::fromLatin1(str: "&&bon&jo&ur") << QString::fromLatin1(str: "ALT+J") << true;
409 QTest::newRow(dataTag: "5") << QString::fromLatin1(str: "b&on&&jour") << QString::fromLatin1(str: "ALT+O") << false;
410 QTest::newRow(dataTag: "6") << QString::fromLatin1(str: "bonjour") << QString() << false;
411 QTest::newRow(dataTag: "7") << QString::fromLatin1(str: "&&&bonjour") << QString::fromLatin1(str: "ALT+B") << false;
412 QTest::newRow(dataTag: "8") << QString::fromLatin1(str: "bonjour&&&") << QString() << false;
413 QTest::newRow(dataTag: "9") << QString::fromLatin1(str: "bo&&nj&o&&u&r") << QString::fromLatin1(str: "ALT+O") << true;
414 QTest::newRow(dataTag: "10") << QString::fromLatin1(str: "BON&JOUR") << QString::fromLatin1(str: "ALT+J") << false;
415 QTest::newRow(dataTag: "11") << QString::fromUtf8(str: "bonjour") << QString() << false;
416}
417
418void tst_QKeySequence::mnemonic()
419{
420#ifndef Q_OS_MAC
421 QFETCH(QString, string);
422 QFETCH(QString, key);
423 QFETCH(bool, warning);
424
425#ifdef QT_NO_DEBUG
426 Q_UNUSED(warning)
427#else
428 if (warning) {
429 QString str = QString::fromLatin1(str: "QKeySequence::mnemonic: \"%1\" contains multiple occurrences of '&'").arg(a: string);
430 QTest::ignoreMessage(type: QtWarningMsg, qPrintable(str));
431 // qWarning(qPrintable(str));
432 }
433#endif
434 QKeySequence seq = QKeySequence::mnemonic(text: string);
435 QKeySequence res = QKeySequence(key);
436
437 QCOMPARE(seq, res);
438#endif
439}
440
441void tst_QKeySequence::toString_data()
442{
443 QTest::addColumn<QString>(name: "strSequence");
444 QTest::addColumn<QString>(name: "neutralString");
445 QTest::addColumn<QString>(name: "platformString");
446
447
448#ifndef Q_OS_MAC
449 QTest::newRow(dataTag: "Ctrl+Left") << QString("Ctrl+Left") << QString("Ctrl+Left") << QString("Ctrl+Left");
450 QTest::newRow(dataTag: "Alt+Left") << QString("Alt+Left") << QString("Alt+Left") << QString("Alt+Left");
451 QTest::newRow(dataTag: "Alt+Shift+Left") << QString("Alt+Shift+Left") << QString("Alt+Shift+Left") << QString("Alt+Shift+Left");
452 QTest::newRow(dataTag: "Ctrl") << QString::fromLatin1(str: "Ctrl+\x0c5") << QString::fromLatin1(str: "Ctrl+\x0c5") << QString::fromLatin1(str: "Ctrl+\x0c5");
453 QTest::newRow(dataTag: "Alt") << QString::fromLatin1(str: "Alt+\x0c5") << QString::fromLatin1(str: "Alt+\x0c5") << QString::fromLatin1(str: "Alt+\x0c5");
454 QTest::newRow(dataTag: "Shift") << QString::fromLatin1(str: "Shift+\x0c5") << QString::fromLatin1(str: "Shift+\x0c5") << QString::fromLatin1(str: "Shift+\x0c5");
455 QTest::newRow(dataTag: "Meta") << QString::fromLatin1(str: "Meta+\x0c5") << QString::fromLatin1(str: "Meta+\x0c5") << QString::fromLatin1(str: "Meta+\x0c5");
456 QTest::newRow(dataTag: "Ctrl+Plus") << QString("Ctrl++") << QString("Ctrl++") << QString("Ctrl++");
457 QTest::newRow(dataTag: "Ctrl+,") << QString("Ctrl+,") << QString("Ctrl+,") << QString("Ctrl+,");
458 QTest::newRow(dataTag: "Ctrl+,,Ctrl+,") << QString("Ctrl+,,Ctrl+,") << QString("Ctrl+,, Ctrl+,") << QString("Ctrl+,, Ctrl+,");
459 QTest::newRow(dataTag: "MultiKey") << QString("Alt+X, Ctrl+Y, Z") << QString("Alt+X, Ctrl+Y, Z")
460 << QString("Alt+X, Ctrl+Y, Z");
461
462 QTest::newRow(dataTag: "Invalid") << QString("Ctrly") << QString("") << QString("");
463#else
464 /*
465 QTest::newRow("Ctrl+Left") << MacCtrl + "Left" << QString("Ctrl+Left") << MacCtrl + macSymbolForQtKey(Qt::Key_Left);
466 QTest::newRow("Alt+Left") << MacAlt + "Left" << QString("Alt+Left") << MacAlt + macSymbolForQtKey(Qt::Key_Left);
467 QTest::newRow("Alt+Shift+Left") << MacAlt + MacShift + "Left" << QString("Alt+Shift+Left")
468 << MacAlt + MacShift + macSymbolForQtKey(Qt::Key_Left);
469 */
470 QTest::newRow("Ctrl+Right,Left") << MacCtrl + "Right, Left" << QString("Ctrl+Right, Left") << MacCtrl + macSymbolForQtKey(Qt::Key_Right) + QString(", ") + macSymbolForQtKey(Qt::Key_Left);
471 QTest::newRow("Ctrl") << MacCtrl + QLatin1String("\x0c5") << QString::fromLatin1("Ctrl+\x0c5") << MacCtrl + QLatin1String("\x0c5");
472 QTest::newRow("Alt") << MacAlt + QLatin1String("\x0c5") << QString::fromLatin1("Alt+\x0c5") << MacAlt + QLatin1String("\x0c5");
473 QTest::newRow("Shift") << MacShift + QLatin1String("\x0c5") << QString::fromLatin1("Shift+\x0c5") << MacShift + QLatin1String("\x0c5");
474 QTest::newRow("Meta") << MacMeta + QLatin1String("\x0c5") << QString::fromLatin1("Meta+\x0c5") << MacMeta + QLatin1String("\x0c5");
475 QTest::newRow("Ctrl+Plus") << MacCtrl + "+" << QString("Ctrl++") << MacCtrl + "+";
476 QTest::newRow("Ctrl+,") << MacCtrl + "," << QString("Ctrl+,") << MacCtrl + ",";
477 QTest::newRow("Ctrl+,,Ctrl+,") << MacCtrl + ",, " + MacCtrl + "," << QString("Ctrl+,, Ctrl+,") << MacCtrl + ",, " + MacCtrl + ",";
478 QTest::newRow("MultiKey") << MacAlt + "X, " + MacCtrl + "Y, Z" << QString("Alt+X, Ctrl+Y, Z")
479 << MacAlt + "X, " + MacCtrl + "Y, Z";
480 QTest::newRow("Invalid") << QString("Ctrly") << QString("") << QString("");
481#endif
482}
483
484void tst_QKeySequence::toString()
485{
486 QFETCH(QString, strSequence);
487 QFETCH(QString, neutralString);
488 QFETCH(QString, platformString);
489
490 QKeySequence ks1(strSequence);
491
492 QCOMPARE(ks1.toString(QKeySequence::NativeText), platformString);
493 QCOMPARE(ks1.toString(QKeySequence::PortableText), neutralString);
494
495}
496
497void tst_QKeySequence::toStringFromKeycode_data()
498{
499 QTest::addColumn<QKeySequence>(name: "keycode");
500 QTest::addColumn<QString>(name: "expectedString");
501
502 QTest::newRow(dataTag: "A") << QKeySequence(Qt::Key_A) << "A";
503 QTest::newRow(dataTag: "-1") << QKeySequence(-1) << "";
504 QTest::newRow(dataTag: "Unknown") << QKeySequence(Qt::Key_unknown) << "";
505 QTest::newRow(dataTag: "Ctrl+Num+Ins") << QKeySequence(Qt::ControlModifier | Qt::KeypadModifier | Qt::Key_Insert) << "Ctrl+Num+Ins";
506 QTest::newRow(dataTag: "Ctrl+Num+Del") << QKeySequence(Qt::ControlModifier | Qt::KeypadModifier | Qt::Key_Delete) << "Ctrl+Num+Del";
507 QTest::newRow(dataTag: "Ctrl+Alt+Num+Del") << QKeySequence(Qt::ControlModifier | Qt::AltModifier | Qt::KeypadModifier | Qt::Key_Delete) << "Ctrl+Alt+Num+Del";
508 QTest::newRow(dataTag: "Ctrl+Ins") << QKeySequence(Qt::ControlModifier | Qt::Key_Insert) << "Ctrl+Ins";
509 QTest::newRow(dataTag: "Ctrl+Num+Ins(1)") << QKeySequence(Qt::Key_Insert | Qt::KeypadModifier | Qt::ControlModifier) << "Ctrl+Num+Ins";
510}
511
512void tst_QKeySequence::toStringFromKeycode()
513{
514 QFETCH(QKeySequence, keycode);
515 QFETCH(QString, expectedString);
516
517 QCOMPARE(QKeySequence(keycode).toString(), expectedString);
518}
519
520void tst_QKeySequence::streamOperators_data()
521{
522 operatorQString_data();
523}
524
525void tst_QKeySequence::streamOperators()
526{
527 QFETCH( int, modifiers );
528 QFETCH( int, keycode );
529
530 QByteArray data;
531 QKeySequence refK( modifiers | keycode );
532 QKeySequence orgK( "Ctrl+A" );
533 QKeySequence copyOrgK = orgK;
534 QVERIFY( copyOrgK == orgK );
535
536 QDataStream in(&data, QIODevice::WriteOnly);
537 in << refK;
538 QDataStream out(&data, QIODevice::ReadOnly);
539 out >> orgK;
540
541 QVERIFY( orgK == refK );
542
543 // check if detached
544 QVERIFY( orgK != copyOrgK );
545}
546
547
548void tst_QKeySequence::parseString_data()
549{
550 QTest::addColumn<QString>(name: "strSequence");
551 QTest::addColumn<QKeySequence>(name: "keycode");
552
553 // Valid
554 QTest::newRow(dataTag: "A") << "A" << QKeySequence(Qt::Key_A);
555 QTest::newRow(dataTag: "a") << "a" << QKeySequence(Qt::Key_A);
556 QTest::newRow(dataTag: "Ctrl+Left") << "Ctrl+Left" << QKeySequence(Qt::CTRL + Qt::Key_Left);
557 QTest::newRow(dataTag: "CTRL+LEFT") << "CTRL+LEFT" << QKeySequence(Qt::CTRL + Qt::Key_Left);
558 QTest::newRow(dataTag: "Meta+A") << "Meta+a" << QKeySequence(Qt::META + Qt::Key_A);
559 QTest::newRow(dataTag: "mEtA+A") << "mEtA+a" << QKeySequence(Qt::META + Qt::Key_A);
560 QTest::newRow(dataTag: "Ctrl++") << "Ctrl++" << QKeySequence(Qt::CTRL + Qt::Key_Plus);
561
562 // Invalid modifiers
563 QTest::newRow(dataTag: "Win+A") << "Win+a" << QKeySequence(Qt::Key_unknown);
564 QTest::newRow(dataTag: "Super+Meta+A") << "Super+Meta+A" << QKeySequence(Qt::Key_unknown);
565
566 // Invalid Keys
567 QTest::newRow(dataTag: "Meta+Trolls") << "Meta+Trolls" << QKeySequence(Qt::Key_unknown);
568 QTest::newRow(dataTag: "Meta+Period") << "Meta+Period" << QKeySequence(Qt::Key_unknown);
569 QTest::newRow(dataTag: "Meta+Ypsilon") << "Meta+Ypsilon" << QKeySequence(Qt::Key_unknown);
570
571 // Garbage
572 QTest::newRow(dataTag: "4+3=2") << "4+3=2" << QKeySequence(Qt::Key_unknown);
573 QTest::newRow(dataTag: "Alabama") << "Alabama" << QKeySequence(Qt::Key_unknown);
574 QTest::newRow(dataTag: "Simon+G") << "Simon+G" << QKeySequence(Qt::Key_unknown);
575 QTest::newRow(dataTag: "Shift+++2") << "Shift+++2" << QKeySequence(Qt::Key_unknown);
576
577 // Wrong order
578 QTest::newRow(dataTag: "A+Meta") << "a+Meta" << QKeySequence(Qt::Key_unknown);
579 QTest::newRow(dataTag: "Meta+++Shift") << "Meta+++Shift" << QKeySequence(Qt::Key_unknown);
580 QTest::newRow(dataTag: "Meta+a+Shift") << "Meta+a+Shift" << QKeySequence(Qt::Key_unknown);
581
582 // Only Modifiers - currently not supported
583 //QTest::newRow("Meta+Shift") << "Meta+Shift" << QKeySequence(Qt::META + Qt::SHIFT);
584 //QTest::newRow("Ctrl") << "Ctrl" << QKeySequence(Qt::CTRL);
585 //QTest::newRow("Shift") << "Shift" << QKeySequence(Qt::SHIFT);
586
587 // Only Keys
588 QTest::newRow(dataTag: "a") << "a" << QKeySequence(Qt::Key_A);
589 QTest::newRow(dataTag: "A") << "A" << QKeySequence(Qt::Key_A);
590
591 // Incomplete
592 QTest::newRow(dataTag: "Meta+Shift+") << "Meta+Shift+" << QKeySequence(Qt::Key_unknown);
593}
594
595void tst_QKeySequence::parseString()
596{
597 QFETCH( QString, strSequence );
598 QFETCH( QKeySequence, keycode );
599
600 QCOMPARE( QKeySequence(strSequence).toString(), keycode.toString() );
601 QVERIFY( QKeySequence(strSequence) == keycode );
602}
603
604void tst_QKeySequence::fromString_data()
605{
606 toString_data();
607}
608
609void tst_QKeySequence::fromString()
610{
611 QFETCH(QString, strSequence);
612 QFETCH(QString, neutralString);
613 QFETCH(QString, platformString);
614
615 if (strSequence == "Ctrly") // Key_Unknown gives empty string
616 return;
617
618 QKeySequence ks1(strSequence);
619 QKeySequence ks2 = QKeySequence::fromString(str: ks1.toString());
620 QKeySequence ks3 = QKeySequence::fromString(str: neutralString, format: QKeySequence::PortableText);
621 QKeySequence ks4 = QKeySequence::fromString(str: platformString, format: QKeySequence::NativeText);
622
623
624 // assume the transitive property exists here.
625 QCOMPARE(ks2, ks1);
626 QCOMPARE(ks3, ks1);
627 QCOMPARE(ks4, ks1);
628}
629
630void tst_QKeySequence::listToString_data()
631{
632 QTest::addColumn<QString>(name: "strSequences");
633 QTest::addColumn<QList<QKeySequence> >(name: "sequences");
634
635 QList<QKeySequence> sequences;
636
637 sequences << QKeySequence(Qt::CTRL + Qt::Key_Left)
638 << QKeySequence(Qt::META + Qt::Key_A);
639 QTest::newRow(dataTag: "Ctrl+Left; Meta+A") << "Ctrl+Left; Meta+A" << sequences;
640
641 sequences.clear();
642 sequences << QKeySequence(Qt::CTRL + Qt::Key_Semicolon)
643 << QKeySequence(Qt::META + Qt::Key_A);
644 QTest::newRow(dataTag: "Ctrl+;; Meta+A") << "Ctrl+;; Meta+A" << sequences;
645
646 sequences.clear();
647 sequences << QKeySequence(Qt::Key_Semicolon)
648 << QKeySequence(Qt::META + Qt::Key_A);
649 QTest::newRow(dataTag: ";; Meta+A") << ";; Meta+A" << sequences;
650
651 sequences.clear();
652 sequences << QKeySequence(Qt::CTRL + Qt::Key_Left)
653 << QKeySequence(Qt::META + Qt::Key_Semicolon);
654 QTest::newRow(dataTag: "Ctrl+Left; Meta+;") << "Ctrl+Left; Meta+;" << sequences;
655
656 sequences.clear();
657 sequences << QKeySequence(Qt::CTRL + Qt::Key_Left)
658 << QKeySequence();
659 QTest::newRow(dataTag: "Ctrl+Left; ") << "Ctrl+Left; " << sequences;
660
661 sequences.clear();
662 sequences << QKeySequence(Qt::CTRL + Qt::Key_Left)
663 << QKeySequence()
664 << QKeySequence(Qt::META + Qt::Key_A);
665 QTest::newRow(dataTag: "Ctrl+Left; ; Meta+A") << "Ctrl+Left; ; Meta+A" << sequences;
666}
667
668void tst_QKeySequence::listToString()
669{
670 QFETCH(QList<QKeySequence>, sequences);
671 QFETCH(QString, strSequences);
672
673 QCOMPARE(QKeySequence::listToString(sequences), strSequences);
674}
675
676void tst_QKeySequence::listFromString_data()
677{
678 QTest::addColumn<QString>(name: "strSequences");
679 QTest::addColumn<QList<QKeySequence> >(name: "sequences");
680
681 QList<QKeySequence> sequences;
682
683 sequences << QKeySequence(Qt::CTRL + Qt::Key_Left)
684 << QKeySequence(Qt::META + Qt::Key_A);
685 QTest::newRow(dataTag: "Ctrl+Left; Meta+A") << "Ctrl+Left; Meta+A" << sequences;
686
687 sequences.clear();
688 sequences << QKeySequence(Qt::CTRL + Qt::Key_Semicolon)
689 << QKeySequence(Qt::META + Qt::Key_A);
690 QTest::newRow(dataTag: "Ctrl+;; Meta+A") << "Ctrl+;; Meta+A" << sequences;
691
692 sequences.clear();
693 sequences << QKeySequence(Qt::Key_Semicolon)
694 << QKeySequence(Qt::META + Qt::Key_A);
695 QTest::newRow(dataTag: ";; Meta+A") << ";; Meta+A" << sequences;
696
697 sequences.clear();
698 sequences << QKeySequence(Qt::CTRL + Qt::Key_Left)
699 << QKeySequence(Qt::META + Qt::Key_Semicolon);
700 QTest::newRow(dataTag: "Ctrl+Left; Meta+;") << "Ctrl+Left; Meta+;" << sequences;
701
702 sequences.clear();
703 sequences << QKeySequence(Qt::CTRL + Qt::Key_Left)
704 << QKeySequence();
705 QTest::newRow(dataTag: "Ctrl+Left; ") << "Ctrl+Left; " << sequences;
706
707 sequences.clear();
708 sequences << QKeySequence(Qt::CTRL + Qt::Key_Left)
709 << QKeySequence()
710 << QKeySequence(Qt::META + Qt::Key_A);
711 QTest::newRow(dataTag: "Ctrl+Left; ; Meta+A") << "Ctrl+Left; ; Meta+A" << sequences;
712
713 sequences.clear();
714 sequences << QKeySequence(Qt::CTRL + Qt::Key_Left)
715 << QKeySequence(Qt::Key_unknown)
716 << QKeySequence(Qt::META + Qt::Key_A);
717 QTest::newRow(dataTag: "Ctrl+Left; 4+3=2; Meta+A") << "Ctrl+Left; 4+3=2; Meta+A" << sequences;
718}
719
720void tst_QKeySequence::listFromString()
721{
722 QFETCH(QList<QKeySequence>, sequences);
723 QFETCH(QString, strSequences);
724
725 QCOMPARE(QKeySequence::listFromString(strSequences), sequences);
726}
727
728void tst_QKeySequence::translated_data()
729{
730#if defined (Q_OS_DARWIN)
731 QSKIP("Test not applicable");
732#endif
733
734 qApp->installTranslator(messageFile: ourTranslator);
735 qApp->installTranslator(messageFile: qtTranslator);
736
737 QTest::addColumn<QString>(name: "transKey");
738 QTest::addColumn<QString>(name: "compKey");
739
740 QTest::newRow(dataTag: "Shift++") << tr(s: "Shift++") << QString("Umschalt++");
741 QTest::newRow(dataTag: "Ctrl++") << tr(s: "Ctrl++") << QString("Strg++");
742 QTest::newRow(dataTag: "Alt++") << tr(s: "Alt++") << QString("Alt++");
743 QTest::newRow(dataTag: "Meta++") << tr(s: "Meta++") << QString("Meta++");
744
745 QTest::newRow(dataTag: "Shift+,, Shift++") << tr(s: "Shift+,, Shift++") << QString("Umschalt+,, Umschalt++");
746 QTest::newRow(dataTag: "Shift+,, Ctrl++") << tr(s: "Shift+,, Ctrl++") << QString("Umschalt+,, Strg++");
747 QTest::newRow(dataTag: "Shift+,, Alt++") << tr(s: "Shift+,, Alt++") << QString("Umschalt+,, Alt++");
748 QTest::newRow(dataTag: "Shift+,, Meta++") << tr(s: "Shift+,, Meta++") << QString("Umschalt+,, Meta++");
749
750 QTest::newRow(dataTag: "Ctrl+,, Shift++") << tr(s: "Ctrl+,, Shift++") << QString("Strg+,, Umschalt++");
751 QTest::newRow(dataTag: "Ctrl+,, Ctrl++") << tr(s: "Ctrl+,, Ctrl++") << QString("Strg+,, Strg++");
752 QTest::newRow(dataTag: "Ctrl+,, Alt++") << tr(s: "Ctrl+,, Alt++") << QString("Strg+,, Alt++");
753 QTest::newRow(dataTag: "Ctrl+,, Meta++") << tr(s: "Ctrl+,, Meta++") << QString("Strg+,, Meta++");
754
755 qApp->removeTranslator(messageFile: ourTranslator);
756 qApp->removeTranslator(messageFile: qtTranslator);
757}
758
759void tst_QKeySequence::translated()
760{
761#if !defined (Q_OS_DARWIN)
762 QFETCH(QString, transKey);
763 QFETCH(QString, compKey);
764
765 qApp->installTranslator(messageFile: ourTranslator);
766 qApp->installTranslator(messageFile: qtTranslator);
767
768 QKeySequence ks1(transKey);
769 QCOMPARE(ks1.toString(QKeySequence::NativeText), compKey);
770
771 qApp->removeTranslator(messageFile: ourTranslator);
772 qApp->removeTranslator(messageFile: qtTranslator);
773#endif
774}
775
776void tst_QKeySequence::i18nKeys_data()
777{
778 QTest::addColumn<int>(name: "keycode");
779 QTest::addColumn<QString>(name: "keystring");
780
781 // Japanese keyboard support
782 QTest::newRow(dataTag: "Kanji") << (int)Qt::Key_Kanji << QString("Kanji");
783 QTest::newRow(dataTag: "Muhenkan") << (int)Qt::Key_Muhenkan << QString("Muhenkan");
784 QTest::newRow(dataTag: "Henkan") << (int)Qt::Key_Henkan << QString("Henkan");
785 QTest::newRow(dataTag: "Romaji") << (int)Qt::Key_Romaji << QString("Romaji");
786 QTest::newRow(dataTag: "Hiragana") << (int)Qt::Key_Hiragana << QString("Hiragana");
787 QTest::newRow(dataTag: "Katakana") << (int)Qt::Key_Katakana << QString("Katakana");
788 QTest::newRow(dataTag: "Hiragana Katakana") << (int)Qt::Key_Hiragana_Katakana << QString("Hiragana Katakana");
789 QTest::newRow(dataTag: "Zenkaku") << (int)Qt::Key_Zenkaku << QString("Zenkaku");
790 QTest::newRow(dataTag: "Hankaku") << (int)Qt::Key_Hankaku << QString("Hankaku");
791 QTest::newRow(dataTag: "Zenkaku Hankaku") << (int)Qt::Key_Zenkaku_Hankaku << QString("Zenkaku Hankaku");
792 QTest::newRow(dataTag: "Touroku") << (int)Qt::Key_Touroku << QString("Touroku");
793 QTest::newRow(dataTag: "Massyo") << (int)Qt::Key_Massyo << QString("Massyo");
794 QTest::newRow(dataTag: "Kana Lock") << (int)Qt::Key_Kana_Lock << QString("Kana Lock");
795 QTest::newRow(dataTag: "Kana Shift") << (int)Qt::Key_Kana_Shift << QString("Kana Shift");
796 QTest::newRow(dataTag: "Eisu Shift") << (int)Qt::Key_Eisu_Shift << QString("Eisu Shift");
797 QTest::newRow(dataTag: "Eisu_toggle") << (int)Qt::Key_Eisu_toggle << QString("Eisu toggle");
798 QTest::newRow(dataTag: "Code input") << (int)Qt::Key_Codeinput << QString("Code input");
799 QTest::newRow(dataTag: "Multiple Candidate") << (int)Qt::Key_MultipleCandidate << QString("Multiple Candidate");
800 QTest::newRow(dataTag: "Previous Candidate") << (int)Qt::Key_PreviousCandidate << QString("Previous Candidate");
801
802 // Korean keyboard support
803 QTest::newRow(dataTag: "Hangul") << (int)Qt::Key_Hangul << QString("Hangul");
804 QTest::newRow(dataTag: "Hangul Start") << (int)Qt::Key_Hangul_Start << QString("Hangul Start");
805 QTest::newRow(dataTag: "Hangul End") << (int)Qt::Key_Hangul_End << QString("Hangul End");
806 QTest::newRow(dataTag: "Hangul Hanja") << (int)Qt::Key_Hangul_Hanja << QString("Hangul Hanja");
807 QTest::newRow(dataTag: "Hangul Jamo") << (int)Qt::Key_Hangul_Jamo << QString("Hangul Jamo");
808 QTest::newRow(dataTag: "Hangul Romaja") << (int)Qt::Key_Hangul_Romaja << QString("Hangul Romaja");
809 QTest::newRow(dataTag: "Hangul Jeonja") << (int)Qt::Key_Hangul_Jeonja << QString("Hangul Jeonja");
810 QTest::newRow(dataTag: "Hangul Banja") << (int)Qt::Key_Hangul_Banja << QString("Hangul Banja");
811 QTest::newRow(dataTag: "Hangul PreHanja") << (int)Qt::Key_Hangul_PreHanja << QString("Hangul PreHanja");
812 QTest::newRow(dataTag: "Hangul PostHanja") << (int)Qt::Key_Hangul_PostHanja << QString("Hangul PostHanja");
813 QTest::newRow(dataTag: "Hangul Special") << (int)Qt::Key_Hangul_Special << QString("Hangul Special");
814}
815
816void tst_QKeySequence::i18nKeys()
817{
818 QFETCH(int, keycode);
819 QFETCH(QString, keystring);
820 QKeySequence seq(keycode);
821
822 QCOMPARE(seq, QKeySequence(keystring));
823 QCOMPARE(seq.toString(), keystring);
824}
825
826QTEST_MAIN(tst_QKeySequence)
827#include "tst_qkeysequence.moc"
828

source code of qtbase/tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp