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 <qapplication.h> |
32 | #include <qtextedit.h> |
33 | #include <qlineedit.h> |
34 | #include <qcompleter.h> |
35 | #include <qpushbutton.h> |
36 | #include <qmainwindow.h> |
37 | #include <qstatusbar.h> |
38 | #include <qboxlayout.h> |
39 | #include <qdebug.h> |
40 | #include <qstring.h> |
41 | #include <qshortcut.h> |
42 | #include <qscreen.h> |
43 | |
44 | QT_BEGIN_NAMESPACE |
45 | class QMainWindow; |
46 | class QTextEdit; |
47 | QT_END_NAMESPACE |
48 | |
49 | class tst_QShortcut : public QObject |
50 | { |
51 | Q_OBJECT |
52 | public: |
53 | |
54 | enum Action { |
55 | SetupAccel, |
56 | TestAccel, |
57 | ClearAll, |
58 | TestEnd |
59 | }; |
60 | Q_ENUM(Action) |
61 | |
62 | enum Widget { |
63 | NoWidget, |
64 | TriggerSlot1, |
65 | TriggerSlot2, |
66 | TriggerSlot3, |
67 | TriggerSlot4, |
68 | TriggerSlot5, |
69 | TriggerSlot6, |
70 | TriggerSlot7, |
71 | }; |
72 | Q_ENUM(Widget) |
73 | |
74 | enum Result { |
75 | NoResult, |
76 | Slot1Triggered, |
77 | Slot2Triggered, |
78 | Slot3Triggered, |
79 | Slot4Triggered, |
80 | Slot5Triggered, |
81 | Slot6Triggered, |
82 | Slot7Triggered, |
83 | SentKeyEvent, |
84 | Ambiguous |
85 | } currentResult = NoResult; |
86 | Q_ENUM(Result) |
87 | |
88 | public slots: |
89 | void slotTrig1() { currentResult = Slot1Triggered; } |
90 | void slotTrig2() { currentResult = Slot2Triggered; } |
91 | void slotTrig3() { currentResult = Slot3Triggered; } |
92 | void slotTrig4() { currentResult = Slot4Triggered; } |
93 | void slotTrig5() { currentResult = Slot5Triggered; } |
94 | void slotTrig6() { currentResult = Slot6Triggered; } |
95 | void slotTrig7() { currentResult = Slot7Triggered; } |
96 | void ambigSlot1() { currentResult = Ambiguous; ambigResult = Slot1Triggered; } |
97 | void ambigSlot2() { currentResult = Ambiguous; ambigResult = Slot2Triggered; } |
98 | void ambigSlot3() { currentResult = Ambiguous; ambigResult = Slot3Triggered; } |
99 | void ambigSlot4() { currentResult = Ambiguous; ambigResult = Slot4Triggered; } |
100 | void ambigSlot5() { currentResult = Ambiguous; ambigResult = Slot5Triggered; } |
101 | void ambigSlot6() { currentResult = Ambiguous; ambigResult = Slot6Triggered; } |
102 | void ambigSlot7() { currentResult = Ambiguous; ambigResult = Slot7Triggered; } |
103 | |
104 | private slots: |
105 | void cleanup(); |
106 | void pmf_connect(); |
107 | void number_data(); |
108 | void number(); |
109 | void text_data(); |
110 | void text(); |
111 | void disabledItems(); |
112 | void ambiguousItems(); |
113 | void ambiguousRotation(); |
114 | void keypressConsumption(); |
115 | void unicodeCompare(); |
116 | void context(); |
117 | void duplicatedShortcutOverride(); |
118 | void shortcutToFocusProxy(); |
119 | void deleteLater(); |
120 | |
121 | protected: |
122 | static Qt::KeyboardModifiers toButtons( int key ); |
123 | void defElements(); |
124 | |
125 | QShortcut *setupShortcut(QWidget *parent, const QString &name, const QKeySequence &ks, |
126 | Qt::ShortcutContext context = Qt::WindowShortcut); |
127 | QShortcut *setupShortcut(QWidget *parent, const QString &name, Widget testWidget, |
128 | const QKeySequence &ks, Qt::ShortcutContext context = Qt::WindowShortcut); |
129 | |
130 | static void sendKeyEvents(QWidget *w, int k1, QChar c1 = 0, int k2 = 0, QChar c2 = 0, |
131 | int k3 = 0, QChar c3 = 0, int k4 = 0, QChar c4 = 0); |
132 | |
133 | void testElement(); |
134 | |
135 | Result ambigResult; |
136 | }; |
137 | |
138 | class TestEdit : public QTextEdit |
139 | { |
140 | Q_OBJECT |
141 | public: |
142 | TestEdit(QWidget *parent, const char *name) |
143 | : QTextEdit(parent) |
144 | { |
145 | setObjectName(name); |
146 | } |
147 | |
148 | protected: |
149 | bool event(QEvent *e) override |
150 | { |
151 | // Make testedit allow any Ctrl+Key as shortcut |
152 | if (e->type() == QEvent::ShortcutOverride) { |
153 | QKeyEvent *ke = static_cast<QKeyEvent*>(e); |
154 | if (ke->modifiers() == Qt::ControlModifier |
155 | && ke->key() > Qt::Key_Any |
156 | && ke->key() < Qt::Key_ydiaeresis) { |
157 | ke->ignore(); |
158 | return true; |
159 | } |
160 | } |
161 | |
162 | // If keypress not processed as normal, check for |
163 | // Ctrl+Key event, and input custom string for |
164 | // result comparison. |
165 | if (e->type() == QEvent::KeyPress) { |
166 | QKeyEvent *ke = static_cast<QKeyEvent*>(e); |
167 | if (ke->modifiers() && ke->key() > Qt::Key_Any |
168 | && ke->key() < Qt::Key_ydiaeresis) { |
169 | const QChar c = QLatin1Char(char(ke->key())); |
170 | if (ke->modifiers() == Qt::ControlModifier) |
171 | insertPlainText(text: QLatin1String("<Ctrl+" ) + c + QLatin1Char('>')); |
172 | else if (ke->modifiers() == Qt::AltModifier) |
173 | insertPlainText(text: QLatin1String("<Alt+" ) + c + QLatin1Char('>')); |
174 | else if (ke->modifiers() == Qt::ShiftModifier) |
175 | insertPlainText(text: QLatin1String("<Shift+" ) + c + QLatin1Char('>')); |
176 | return true; |
177 | } |
178 | } |
179 | return QTextEdit::event(e); |
180 | } |
181 | }; |
182 | |
183 | class MainWindow : public QMainWindow |
184 | { |
185 | public: |
186 | MainWindow(); |
187 | |
188 | TestEdit *testEdit() const { return m_testEdit; } |
189 | |
190 | private: |
191 | TestEdit *m_testEdit; |
192 | }; |
193 | |
194 | MainWindow::MainWindow() |
195 | { |
196 | setWindowFlags(Qt::X11BypassWindowManagerHint); |
197 | m_testEdit = new TestEdit(this, "test_edit" ); |
198 | setCentralWidget(m_testEdit); |
199 | setFixedSize(w: 200, h: 200); |
200 | } |
201 | |
202 | void tst_QShortcut::cleanup() |
203 | { |
204 | QVERIFY(QApplication::topLevelWidgets().size() <= 1); // The data driven tests keep a widget around |
205 | } |
206 | |
207 | void tst_QShortcut::pmf_connect() |
208 | { |
209 | class MyObject : public QObject |
210 | { |
211 | public: |
212 | using QObject::QObject; |
213 | void onActivated() { ++activated; } |
214 | void onAmbiguous() { ++ambiguous; } |
215 | void reset() { activated = 0; ambiguous = 0; } |
216 | int activated = 0; |
217 | int ambiguous = 0; |
218 | } myObject; |
219 | QWidget parent; |
220 | |
221 | auto runCheck = [&myObject](QShortcut *sc, int activated, int ambiguous) |
222 | { |
223 | myObject.reset(); |
224 | sc->activated(); |
225 | sc->activatedAmbiguously(); |
226 | delete sc; |
227 | QCOMPARE(myObject.activated, activated); |
228 | QCOMPARE(myObject.ambiguous, ambiguous); |
229 | }; |
230 | |
231 | runCheck(new QShortcut(QKeySequence(), &parent, |
232 | [&myObject]() { ++myObject.activated; }), |
233 | 1, 0); |
234 | runCheck(new QShortcut(QKeySequence(), &parent, |
235 | &myObject, &MyObject::onActivated), |
236 | 1, 0); |
237 | runCheck(new QShortcut(QKeySequence(), &parent, |
238 | &myObject, &MyObject::onActivated, &MyObject::onAmbiguous), |
239 | 1, 1); |
240 | runCheck(new QShortcut(QKeySequence(), &parent, &myObject, |
241 | &MyObject::onActivated, &myObject, &MyObject::onAmbiguous), |
242 | 1, 1); |
243 | } |
244 | |
245 | |
246 | Qt::KeyboardModifiers tst_QShortcut::toButtons( int key ) |
247 | { |
248 | Qt::KeyboardModifiers result = Qt::NoModifier; |
249 | if ( key & Qt::SHIFT ) |
250 | result |= Qt::ShiftModifier; |
251 | if ( key & Qt::CTRL ) |
252 | result |= Qt::ControlModifier; |
253 | if ( key & Qt::META ) |
254 | result |= Qt::MetaModifier; |
255 | if ( key & Qt::ALT ) |
256 | result |= Qt::AltModifier; |
257 | return result; |
258 | } |
259 | |
260 | void tst_QShortcut::defElements() |
261 | { |
262 | QTest::addColumn<tst_QShortcut::Action>(name: "action" ); |
263 | QTest::addColumn<tst_QShortcut::Widget>(name: "testWidget" ); |
264 | QTest::addColumn<QString>(name: "txt" ); |
265 | QTest::addColumn<int>(name: "k1" ); |
266 | QTest::addColumn<int>(name: "c1" ); |
267 | QTest::addColumn<int>(name: "k2" ); |
268 | QTest::addColumn<int>(name: "c2" ); |
269 | QTest::addColumn<int>(name: "k3" ); |
270 | QTest::addColumn<int>(name: "c3" ); |
271 | QTest::addColumn<int>(name: "k4" ); |
272 | QTest::addColumn<int>(name: "c4" ); |
273 | QTest::addColumn<tst_QShortcut::Result>(name: "result" ); |
274 | } |
275 | |
276 | void tst_QShortcut::number() |
277 | { |
278 | // We expect a failure on these tests, until QtTestKeyboard is |
279 | // fixed to do real platform dependent keyboard simulations |
280 | if (QTest::currentDataTag() == QString("N006a:Shift+Tab - [BackTab]" ) |
281 | || QTest::currentDataTag() == QString("N006b:Shift+Tab - [Shift+BackTab]" )) |
282 | QEXPECT_FAIL("" , "FLAW IN QTESTKEYBOARD: Keyboard events not passed through " |
283 | "platform dependent key handling code" , Continue); |
284 | testElement(); |
285 | } |
286 | void tst_QShortcut::text() |
287 | { |
288 | testElement(); |
289 | } |
290 | // ------------------------------------------------------------------ |
291 | // Number Elements -------------------------------------------------- |
292 | // ------------------------------------------------------------------ |
293 | void tst_QShortcut::number_data() |
294 | { |
295 | defElements(); |
296 | |
297 | // Clear all |
298 | QTest::newRow(dataTag: "N00 - clear" ) << ClearAll << NoWidget <<QString()<<0<<0<<0<<0<<0<<0<<0<<0<<NoResult; |
299 | |
300 | //=========================================== |
301 | // [Shift + key] on non-shift shortcuts testing |
302 | //=========================================== |
303 | |
304 | /* Testing Single Sequences |
305 | Shift + Qt::Key_M on Qt::Key_M |
306 | Qt::Key_M on Qt::Key_M |
307 | Shift + Qt::Key_Plus on Qt::Key_Pluss |
308 | Qt::Key_Plus on Qt::Key_Pluss |
309 | */ |
310 | QTest::newRow(dataTag: "N001 - slot1" ) << SetupAccel << TriggerSlot1 << QString() << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
311 | //commented out because the behaviour changed, those tests should be updated |
312 | //QTest::newRow("N001:Shift + M - [M]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
313 | QTest::newRow(dataTag: "N001:M - [M]" ) << TestAccel << NoWidget << QString() << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
314 | QTest::newRow(dataTag: "N001 - slot2" ) << SetupAccel << TriggerSlot2 << QString() << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
315 | //commented out because the behaviour changed, those tests should be updated |
316 | //QTest::newRow("N001:Shift++ [+]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; |
317 | QTest::newRow(dataTag: "N001:+ [+]" ) << TestAccel << NoWidget << QString() << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; |
318 | QTest::newRow(dataTag: "N001 - clear" ) << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all |
319 | |
320 | /* Testing Single Sequences |
321 | Shift + Qt::Key_M on Shift + Qt::Key_M |
322 | Qt::Key_M on Shift + Qt::Key_M |
323 | Shift + Qt::Key_Plus on Shift + Qt::Key_Pluss |
324 | Qt::Key_Plus on Shift + Qt::Key_Pluss |
325 | */ |
326 | QTest::newRow(dataTag: "N002 - slot1" ) << SetupAccel << TriggerSlot1 << QString() << int(Qt::SHIFT + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
327 | QTest::newRow(dataTag: "N002:Shift+M - [Shift+M]" ) << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
328 | QTest::newRow(dataTag: "N002:M - [Shift+M]" ) << TestAccel << NoWidget << QString() << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
329 | QTest::newRow(dataTag: "N002 - slot2" ) << SetupAccel << TriggerSlot2 << QString() << int(Qt::SHIFT + Qt::Key_Plus) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
330 | QTest::newRow(dataTag: "N002:Shift++ [Shift++]" ) << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; |
331 | QTest::newRow(dataTag: "N002:+ [Shift++]" ) << TestAccel << NoWidget << QString() << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
332 | QTest::newRow(dataTag: "N002 - clear" ) << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all |
333 | |
334 | /* Testing Single Sequences |
335 | Shift + Qt::Key_F1 on Qt::Key_F1 |
336 | Qt::Key_F1 on Qt::Key_F1 |
337 | */ |
338 | QTest::newRow(dataTag: "N003 - slot1" ) << SetupAccel << TriggerSlot1 << QString() << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
339 | //commented out because the behaviour changed, those tests should be updated |
340 | //QTest::newRow("N003:Shift+F1 - [F1]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
341 | QTest::newRow(dataTag: "N003:F1 - [F1]" ) << TestAccel << NoWidget << QString() << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
342 | QTest::newRow(dataTag: "N003 - clear" ) << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all |
343 | /* Testing Single Sequences |
344 | Shift + Qt::Key_F1 on Shift + Qt::Key_F1 |
345 | Qt::Key_F1 on Shift + Qt::Key_F1 |
346 | */ |
347 | |
348 | QTest::newRow(dataTag: "N004 - slot1" ) << SetupAccel << TriggerSlot1 << QString() << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
349 | QTest::newRow(dataTag: "N004:Shift+F1 - [Shift+F1]" ) << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
350 | QTest::newRow(dataTag: "N004:F1 - [Shift+F1]" ) << TestAccel << NoWidget << QString() << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
351 | QTest::newRow(dataTag: "N004 - clear" ) << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all |
352 | |
353 | /* Testing Single Sequences |
354 | Qt::Key_Tab on Qt::Key_Tab |
355 | Shift + Qt::Key_Tab on Qt::Key_Tab |
356 | Qt::Key_Backtab on Qt::Key_Tab |
357 | Shift + Qt::Key_Backtab on Qt::Key_Tab |
358 | */ |
359 | QTest::newRow(dataTag: "N005a - slot1" ) << SetupAccel << TriggerSlot1 << QString() << int(Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
360 | QTest::newRow(dataTag: "N005a:Tab - [Tab]" ) << TestAccel << NoWidget << QString() << int(Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
361 | //commented out because the behaviour changed, those tests should be updated |
362 | //QTest::newRow("N005a:Shift+Tab - [Tab]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
363 | // (Shift+)BackTab != Tab, but Shift+BackTab == Shift+Tab |
364 | QTest::newRow(dataTag: "N005a:Backtab - [Tab]" ) << TestAccel << NoWidget << QString() << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
365 | QTest::newRow(dataTag: "N005a:Shift+Backtab - [Tab]" ) << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
366 | QTest::newRow(dataTag: "N005a - clear" ) << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all |
367 | |
368 | /* Testing Single Sequences |
369 | Qt::Key_Tab on Shift + Qt::Key_Tab |
370 | Shift + Qt::Key_Tab on Shift + Qt::Key_Tab |
371 | Qt::Key_Backtab on Shift + Qt::Key_Tab |
372 | Shift + Qt::Key_Backtab on Shift + Qt::Key_Tab |
373 | */ |
374 | QTest::newRow(dataTag: "N005b - slot1" ) << SetupAccel << TriggerSlot1 << QString() << int(Qt::SHIFT + Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
375 | QTest::newRow(dataTag: "N005b:Tab - [Shift+Tab]" ) << TestAccel << NoWidget << QString() << int(Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
376 | QTest::newRow(dataTag: "N005b:Shift+Tab - [Shift+Tab]" ) << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
377 | QTest::newRow(dataTag: "N005b:BackTab - [Shift+Tab]" ) << TestAccel << NoWidget << QString() << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
378 | QTest::newRow(dataTag: "N005b:Shift+BackTab - [Shift+Tab]" ) << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
379 | QTest::newRow(dataTag: "N005b - clear" ) << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all |
380 | |
381 | /* Testing Single Sequences |
382 | Qt::Key_Tab on Qt::Key_Backtab |
383 | Shift + Qt::Key_Tab on Qt::Key_Backtab |
384 | Qt::Key_Backtab on Qt::Key_Backtab |
385 | Shift + Qt::Key_Backtab on Qt::Key_Backtab |
386 | */ |
387 | QTest::newRow(dataTag: "N006a - slot1" ) << SetupAccel << TriggerSlot1 << QString() << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
388 | QTest::newRow(dataTag: "N006a:Tab - [BackTab]" ) << TestAccel << NoWidget << QString() << int(Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
389 | // This should work, since platform dependent code will transform the |
390 | // Shift+Tab into a Shift+BackTab, which should trigger the shortcut |
391 | QTest::newRow(dataTag: "N006a:Shift+Tab - [BackTab]" ) << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; //XFAIL |
392 | QTest::newRow(dataTag: "N006a:BackTab - [BackTab]" ) << TestAccel << NoWidget << QString() << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
393 | //commented out because the behaviour changed, those tests should be updated |
394 | //QTest::newRow("N006a:Shift+BackTab - [BackTab]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
395 | QTest::newRow(dataTag: "N006a - clear" ) << ClearAll << NoWidget<< QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all |
396 | |
397 | /* Testing Single Sequences |
398 | Qt::Key_Tab on Shift + Qt::Key_Backtab |
399 | Shift + Qt::Key_Tab on Shift + Qt::Key_Backtab |
400 | Qt::Key_Backtab on Shift + Qt::Key_Backtab |
401 | Shift + Qt::Key_Backtab on Shift + Qt::Key_Backtab |
402 | */ |
403 | QTest::newRow(dataTag: "N006b - slot1" ) << SetupAccel << TriggerSlot1 << QString() << int(Qt::SHIFT + Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
404 | QTest::newRow(dataTag: "N006b:Tab - [Shift+BackTab]" ) << TestAccel << NoWidget << QString() << int(Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
405 | QTest::newRow(dataTag: "N006b:Shift+Tab - [Shift+BackTab]" ) << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Tab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
406 | QTest::newRow(dataTag: "N006b:BackTab - [Shift+BackTab]" ) << TestAccel << NoWidget << QString() << int(Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
407 | QTest::newRow(dataTag: "N006b:Shift+BackTab - [Shift+BackTab]" ) << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Backtab) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; //XFAIL |
408 | QTest::newRow(dataTag: "N006b - clear" ) << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all |
409 | |
410 | //=========================================== |
411 | // [Shift + key] and [key] on shortcuts with |
412 | // and without modifiers |
413 | //=========================================== |
414 | |
415 | /* Testing Single Sequences |
416 | Qt::Key_F1 |
417 | Shift + Qt::Key_F1 |
418 | */ |
419 | QTest::newRow(dataTag: "N007 - slot1" ) << SetupAccel << TriggerSlot1 << QString() << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
420 | QTest::newRow(dataTag: "N007 - slot2" ) << SetupAccel << TriggerSlot2 << QString() << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
421 | QTest::newRow(dataTag: "N007:F1" ) << TestAccel << NoWidget << QString() << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
422 | QTest::newRow(dataTag: "N007:Shift + F1" ) << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; |
423 | QTest::newRow(dataTag: "N007 - clear" ) << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all |
424 | |
425 | /* Testing Single Sequences |
426 | Qt::Key_M |
427 | Shift + Qt::Key_M |
428 | Ctrl + Qt::Key_M |
429 | Alt + Qt::Key_M |
430 | */ |
431 | QTest::newRow(dataTag: "N01 - slot1" ) << SetupAccel << TriggerSlot1 << QString() << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
432 | QTest::newRow(dataTag: "N02 - slot2" ) << SetupAccel << TriggerSlot2 << QString() << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
433 | QTest::newRow(dataTag: "N03 - slot1" ) << SetupAccel << TriggerSlot1 << QString() << int(Qt::CTRL + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
434 | QTest::newRow(dataTag: "N04 - slot2" ) << SetupAccel << TriggerSlot2 << QString() << int(Qt::ALT + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
435 | QTest::newRow(dataTag: "N:Qt::Key_M" ) << TestAccel << NoWidget << QString() << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
436 | QTest::newRow(dataTag: "N:Shift+Qt::Key_M" ) << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; |
437 | QTest::newRow(dataTag: "N:Ctrl+Qt::Key_M" ) << TestAccel << NoWidget << QString() << int(Qt::CTRL + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
438 | QTest::newRow(dataTag: "N:Alt+Qt::Key_M" ) << TestAccel << NoWidget << QString() << int(Qt::ALT + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; |
439 | |
440 | /* Testing Single Sequence Ambiguity |
441 | Qt::Key_M on shortcut2 |
442 | */ |
443 | QTest::newRow(dataTag: "N05 - slot2" ) << SetupAccel << TriggerSlot2 << QString() << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
444 | QTest::newRow(dataTag: "N:Qt::Key_M on slot" ) << TestAccel << NoWidget << QString() << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Ambiguous; |
445 | QTest::newRow(dataTag: "N05 - clear" ) << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all |
446 | |
447 | /* Testing Single Specialkeys |
448 | Qt::Key_aring |
449 | Qt::Key_Aring |
450 | Qt::UNICODE_ACCEL + Qt::Key_K |
451 | */ |
452 | QTest::newRow(dataTag: "N06 - slot1" ) << SetupAccel << TriggerSlot1 << QString() << int(Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
453 | QTest::newRow(dataTag: "N07 - slot2" ) << SetupAccel << TriggerSlot2 << QString() << int(Qt::SHIFT+Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
454 | QTest::newRow(dataTag: "N08 - slot2" ) << SetupAccel << TriggerSlot1 << QString() << int(Qt::UNICODE_ACCEL + Qt::Key_K) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
455 | |
456 | QTest::newRow(dataTag: "N:Qt::Key_aring" ) << TestAccel << NoWidget << QString() << int(Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
457 | QTest::newRow(dataTag: "N:Qt::Key_Aring" ) << TestAccel << NoWidget << QString() << int(Qt::SHIFT+Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; |
458 | QTest::newRow(dataTag: "N:Qt::Key_aring - Text Form" ) << TestAccel << NoWidget << QString() << 0 << 0xC5 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
459 | QTest::newRow(dataTag: "N:Qt::Key_Aring - Text Form" ) << TestAccel << NoWidget << QString() << int(Qt::SHIFT+0) << 0xC5 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; |
460 | QTest::newRow(dataTag: "N:Qt::UNICODE_ACCEL + Qt::Key_K" )<< TestAccel << NoWidget << QString() << int(Qt::UNICODE_ACCEL + Qt::Key_K) << int('k') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
461 | QTest::newRow(dataTag: "N09 - clear" ) << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all |
462 | |
463 | /* Testing Multiple Sequences |
464 | Qt::Key_M |
465 | Qt::Key_I, Qt::Key_M |
466 | Shift+Qt::Key_I, Qt::Key_M |
467 | */ |
468 | QTest::newRow(dataTag: "N10 - slot1" ) << SetupAccel << TriggerSlot1 << QString() << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
469 | QTest::newRow(dataTag: "N11 - slot2" ) << SetupAccel << TriggerSlot2 << QString() << int(Qt::Key_I) << 0 << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << NoResult; |
470 | QTest::newRow(dataTag: "N12 - slot1" ) << SetupAccel << TriggerSlot1 << QString() << int(Qt::SHIFT + Qt::Key_I) << 0 << int(Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << NoResult; |
471 | |
472 | QTest::newRow(dataTag: "N:Qt::Key_M (2)" ) << TestAccel << NoWidget << QString() << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
473 | QTest::newRow(dataTag: "N:Qt::Key_I, Qt::Key_M" ) << TestAccel << NoWidget << QString() << int(Qt::Key_I) << int('i') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot2Triggered; |
474 | QTest::newRow(dataTag: "N:Shift+Qt::Key_I, Qt::Key_M" ) << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_I) << int('I') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot1Triggered; |
475 | QTest::newRow(dataTag: "N:end" ) << TestEnd << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
476 | } |
477 | |
478 | // ------------------------------------------------------------------ |
479 | // Text Elements ---------------------------------------------------- |
480 | // ------------------------------------------------------------------ |
481 | void tst_QShortcut::text_data() |
482 | { |
483 | defElements(); |
484 | // Clear all |
485 | QTest::newRow(dataTag: "T00 - clear" ) << ClearAll << NoWidget <<QString()<<0<<0<<0<<0<<0<<0<<0<<0<< NoResult; |
486 | |
487 | //=========================================== |
488 | // [Shift + key] on non-shift shortcuts testing |
489 | //=========================================== |
490 | |
491 | /* Testing Single Sequences |
492 | Shift + Qt::Key_M on Qt::Key_M |
493 | Qt::Key_M on Qt::Key_M |
494 | Shift + Qt::Key_Plus on Qt::Key_Pluss |
495 | Qt::Key_Plus on Qt::Key_Pluss |
496 | */ |
497 | QTest::newRow(dataTag: "T001 - slot1" ) << SetupAccel << TriggerSlot1 << QString("M" ) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
498 | //commented out because the behaviour changed, those tests should be updated |
499 | //QTest::newRow("T001:Shift+M - [M]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
500 | QTest::newRow(dataTag: "T001:M - [M]" ) << TestAccel << NoWidget << QString() << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
501 | QTest::newRow(dataTag: "T001 - slot2" ) << SetupAccel << TriggerSlot2 << QString("+" ) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
502 | //commented out because the behaviour changed, those tests should be updated |
503 | //QTest::newRow("T001:Shift++ [+]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; |
504 | QTest::newRow(dataTag: "T001:+ [+]" ) << TestAccel << NoWidget << QString() << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; |
505 | QTest::newRow(dataTag: "T001 - clear" ) << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all |
506 | |
507 | /* Testing Single Sequences |
508 | Shift + Qt::Key_M on Shift + Qt::Key_M |
509 | Qt::Key_M on Shift + Qt::Key_M |
510 | Shift + Qt::Key_Plus on Shift + Qt::Key_Pluss |
511 | Qt::Key_Plus on Shift + Qt::Key_Pluss |
512 | Shift + Ctrl + Qt::Key_Plus on Ctrl + Qt::Key_Pluss |
513 | Ctrl + Qt::Key_Plus on Ctrl + Qt::Key_Pluss |
514 | */ |
515 | QTest::newRow(dataTag: "T002 - slot1" ) << SetupAccel << TriggerSlot1 << QString("Shift+M" ) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
516 | QTest::newRow(dataTag: "T002:Shift+M - [Shift+M]" ) << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
517 | QTest::newRow(dataTag: "T002:M - [Shift+M]" ) << TestAccel << NoWidget << QString() << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
518 | QTest::newRow(dataTag: "T002 - slot2" ) << SetupAccel << TriggerSlot2 << QString("Shift++" ) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
519 | QTest::newRow(dataTag: "T002:Shift++ [Shift++]" ) << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; |
520 | QTest::newRow(dataTag: "T002:+ [Shift++]" ) << TestAccel << NoWidget << QString() << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
521 | QTest::newRow(dataTag: "T002 - clear" ) << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all |
522 | |
523 | /* Testing Single Sequences |
524 | Shift + Ctrl + Qt::Key_Plus on Ctrl + Qt::Key_Plus |
525 | Ctrl + Qt::Key_Plus on Ctrl + Qt::Key_Plus |
526 | Qt::Key_Plus on Ctrl + Qt::Key_Plus |
527 | */ |
528 | QTest::newRow(dataTag: "T002b - slot1" ) << SetupAccel << TriggerSlot1 << QString("Ctrl++" ) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
529 | //commented out because the behaviour changed, those tests should be updated |
530 | //QTest::newRow("T002b:Shift+Ctrl++ [Ctrl++]")<< TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::CTRL + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
531 | QTest::newRow(dataTag: "T002b:Ctrl++ [Ctrl++]" ) << TestAccel << NoWidget << QString() << int(Qt::CTRL + Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
532 | QTest::newRow(dataTag: "T002b:+ [Ctrl++]" ) << TestAccel << NoWidget << QString() << int(Qt::Key_Plus) << int('+') << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
533 | QTest::newRow(dataTag: "T002b - clear" ) << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all |
534 | |
535 | /* Testing Single Sequences |
536 | Shift + Qt::Key_F1 on Qt::Key_F1 |
537 | Qt::Key_F1 on Qt::Key_F1 |
538 | */ |
539 | QTest::newRow(dataTag: "T003 - slot1" ) << SetupAccel << TriggerSlot1 << QString("F1" ) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
540 | //commented out because the behaviour changed, those tests should be updated |
541 | //QTest::newRow("T003:Shift+F1 - [F1]") << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
542 | QTest::newRow(dataTag: "T003:F1 - [F1]" ) << TestAccel << NoWidget << QString() << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
543 | QTest::newRow(dataTag: "T003 - clear" ) << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all |
544 | |
545 | /* Testing Single Sequences |
546 | Shift + Qt::Key_F1 on Shift + Qt::Key_F1 |
547 | Qt::Key_F1 on Shift + Qt::Key_F1 |
548 | */ |
549 | QTest::newRow(dataTag: "T004 - slot1" ) << SetupAccel << TriggerSlot1 << QString("Shift+F1" ) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
550 | QTest::newRow(dataTag: "T004:Shift+F1 - [Shift+F1]" ) << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
551 | QTest::newRow(dataTag: "T004:F1 - [Shift+F1]" ) << TestAccel << NoWidget << QString() << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
552 | QTest::newRow(dataTag: "T004 - clear" ) << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all |
553 | |
554 | //=========================================== |
555 | // [Shift + key] and [key] on shortcuts with |
556 | // and without modifiers |
557 | //=========================================== |
558 | |
559 | /* Testing Single Sequences |
560 | Qt::Key_F1 |
561 | Shift + Qt::Key_F1 |
562 | */ |
563 | QTest::newRow(dataTag: "T007 - slot1" ) << SetupAccel << TriggerSlot1 << QString("F1" ) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
564 | QTest::newRow(dataTag: "T007 - slot2" ) << SetupAccel << TriggerSlot2 << QString("Shift+F1" ) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
565 | QTest::newRow(dataTag: "T007:F1" ) << TestAccel << NoWidget << QString() << int(Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
566 | QTest::newRow(dataTag: "T007:Shift + F1" ) << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_F1) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; |
567 | QTest::newRow(dataTag: "T007 - clear" ) << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all |
568 | |
569 | /* Testing Single Sequences |
570 | Qt::Key_M |
571 | Shift + Qt::Key_M |
572 | Ctrl + Qt::Key_M |
573 | Alt + Qt::Key_M |
574 | */ |
575 | QTest::newRow(dataTag: "T01 - slot1" ) << SetupAccel << TriggerSlot1 << QString("M" ) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
576 | QTest::newRow(dataTag: "T02 - slot2" ) << SetupAccel << TriggerSlot2 << QString("Shift+M" ) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
577 | QTest::newRow(dataTag: "T03 - slot1" ) << SetupAccel << TriggerSlot1 << QString("Ctrl+M" ) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
578 | QTest::newRow(dataTag: "T04 - slot2" ) << SetupAccel << TriggerSlot2 << QString("Alt+M" ) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
579 | |
580 | QTest::newRow(dataTag: "T:Qt::Key_M" ) << TestAccel << NoWidget << QString() << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
581 | QTest::newRow(dataTag: "T:Shift + Qt::Key_M" ) << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_M) << int('M') << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; |
582 | QTest::newRow(dataTag: "T:Ctrl + Qt::Key_M" ) << TestAccel << NoWidget << QString() << int(Qt::CTRL + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
583 | QTest::newRow(dataTag: "T:Alt + Qt::Key_M" ) << TestAccel << NoWidget << QString() << int(Qt::ALT + Qt::Key_M) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; |
584 | |
585 | /* Testing Single Sequence Ambiguity |
586 | Qt::Key_M on shortcut2 |
587 | */ |
588 | QTest::newRow(dataTag: "T05 - slot2" ) << SetupAccel << TriggerSlot2 << QString("M" ) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
589 | QTest::newRow(dataTag: "T:Qt::Key_M on TriggerSlot2" ) << TestAccel << NoWidget << QString() << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Ambiguous; |
590 | QTest::newRow(dataTag: "T06 - clear" ) << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all |
591 | |
592 | /* Testing Single Specialkeys |
593 | Qt::Key_aring |
594 | Qt::Key_Aring |
595 | Qt::UNICODE_ACCEL + Qt::Key_K |
596 | */ |
597 | /* see comments above on the #ifdef'ery */ |
598 | QTest::newRow(dataTag: "T06 - slot1" ) << SetupAccel << TriggerSlot1 << QString::fromLatin1(str: "\x0C5" )<< 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
599 | QTest::newRow(dataTag: "T07 - slot2" ) << SetupAccel << TriggerSlot2 << QString::fromLatin1(str: "Shift+\x0C5" )<< 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
600 | QTest::newRow(dataTag: "T08 - slot2" ) << SetupAccel << TriggerSlot1 << QString("K" ) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
601 | QTest::newRow(dataTag: "T:Qt::Key_aring" ) << TestAccel << NoWidget << QString() << int(Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
602 | QTest::newRow(dataTag: "T:Qt::Key_Aring" ) << TestAccel << NoWidget << QString() << int(Qt::SHIFT+Qt::Key_Aring) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; |
603 | QTest::newRow(dataTag: "T:Qt::Key_aring - Text Form" ) << TestAccel << NoWidget << QString() << 0 << 0xC5 << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
604 | QTest::newRow(dataTag: "T:Qt::Key_Aring - Text Form" ) << TestAccel << NoWidget << QString() << int(Qt::SHIFT+0) << 0xC5 << 0 << 0 << 0 << 0 << 0 << 0 << Slot2Triggered; |
605 | QTest::newRow(dataTag: "T:Qt::UNICODE_ACCEL + Qt::Key_K" )<< TestAccel << NoWidget << QString() << int(Qt::UNICODE_ACCEL + Qt::Key_K) << int('k') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
606 | QTest::newRow(dataTag: "T09 - clear" ) << ClearAll << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; // Clear all |
607 | |
608 | /* Testing Multiple Sequences |
609 | Qt::Key_M |
610 | Qt::Key_I, Qt::Key_M |
611 | Shift+Qt::Key_I, Qt::Key_M |
612 | */ |
613 | QTest::newRow(dataTag: "T10 - slot1" ) << SetupAccel << TriggerSlot1 << QString("M" ) << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
614 | QTest::newRow(dataTag: "T11 - slot2" ) << SetupAccel << TriggerSlot2 << QString("I, M" )<< 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
615 | QTest::newRow(dataTag: "T12 - slot1" ) << SetupAccel << TriggerSlot1 << QString("Shift+I, M" )<< 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
616 | QTest::newRow(dataTag: "T:Qt::Key_M (2)" ) << TestAccel << NoWidget << QString() << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << 0 << 0 << Slot1Triggered; |
617 | QTest::newRow(dataTag: "T:Qt::Key_I, Qt::Key_M" ) << TestAccel << NoWidget << QString() << int(Qt::Key_I) << int('i') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot2Triggered; |
618 | QTest::newRow(dataTag: "T:Shift+Qt::Key_I, Qt::Key_M" ) << TestAccel << NoWidget << QString() << int(Qt::SHIFT + Qt::Key_I) << int('I') << int(Qt::Key_M) << int('m') << 0 << 0 << 0 << 0 << Slot1Triggered; |
619 | QTest::newRow(dataTag: "T:end" ) << TestEnd << NoWidget << QString() << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << NoResult; |
620 | } |
621 | |
622 | class ButtonWidget : public QWidget |
623 | { |
624 | public: |
625 | ButtonWidget(); |
626 | |
627 | QPushButton *pushButton1() const { return m_pb1; } |
628 | QPushButton *pushButton2() const { return m_pb2; } |
629 | |
630 | private: |
631 | QPushButton *m_pb1; |
632 | QPushButton *m_pb2; |
633 | }; |
634 | |
635 | ButtonWidget::ButtonWidget() |
636 | { |
637 | // Setup two identical shortcuts on different pushbuttons |
638 | QString name = QLatin1String("pushbutton-1" ); |
639 | m_pb1 = new QPushButton(name, this); |
640 | m_pb1->setObjectName(name); |
641 | name = QLatin1String("pushbutton-2" ); |
642 | m_pb2 = new QPushButton(name, this); |
643 | m_pb2->setObjectName(name); |
644 | auto hLayout = new QHBoxLayout(this); |
645 | hLayout->addWidget(m_pb1); |
646 | hLayout->addWidget(m_pb2); |
647 | hLayout->addStretch(); |
648 | } |
649 | |
650 | // ------------------------------------------------------------------ |
651 | // Disabled Elements ------------------------------------------------ |
652 | // ------------------------------------------------------------------ |
653 | void tst_QShortcut::disabledItems() |
654 | { |
655 | if (QGuiApplication::platformName().startsWith(s: QLatin1String("wayland" ), cs: Qt::CaseInsensitive)) |
656 | QSKIP("Wayland: This fails. Figure out why." ); |
657 | |
658 | ButtonWidget mainW; |
659 | mainW.setWindowTitle(QTest::currentTestFunction()); |
660 | mainW.show(); |
661 | mainW.activateWindow(); |
662 | QVERIFY(QTest::qWaitForWindowActive(&mainW)); |
663 | |
664 | /* Testing Disabled Shortcuts |
665 | Qt::Key_M on slot1 |
666 | Shift + Qt::Key_M on slot1 |
667 | Qt::Key_M on slot2 (disabled) |
668 | Shift + Qt::Key_M on slot2 (disabled) |
669 | */ |
670 | |
671 | // Setup two identical shortcuts on different pushbuttons |
672 | auto pb1 = mainW.pushButton1(); |
673 | auto pb2 = mainW.pushButton2(); |
674 | const int shiftM = Qt::SHIFT + Qt::Key_M; |
675 | QShortcut *cut1 = setupShortcut(parent: pb1, name: "shortcut1-pb1" , testWidget: TriggerSlot1, |
676 | ks: QKeySequence(Qt::Key_M)); |
677 | QShortcut *cut2 = setupShortcut(parent: pb1, name: "shortcut2-pb1" , testWidget: TriggerSlot1, |
678 | ks: QKeySequence(shiftM)); |
679 | QShortcut *cut3 = setupShortcut(parent: pb2, name: "shortcut3-pb2" , testWidget: TriggerSlot2, |
680 | ks: QKeySequence(Qt::Key_M)); |
681 | QShortcut *cut4 = setupShortcut(parent: pb2, name: "shortcut4-pb2" , testWidget: TriggerSlot2, |
682 | ks: QKeySequence(shiftM)); |
683 | |
684 | cut3->setEnabled(false); |
685 | cut4->setEnabled(false); |
686 | |
687 | currentResult = NoResult; |
688 | sendKeyEvents(w: &mainW, k1: Qt::Key_M, c1: 'm'); |
689 | QCOMPARE(currentResult, Slot1Triggered); |
690 | |
691 | currentResult = NoResult; |
692 | sendKeyEvents(w: &mainW, k1: shiftM, c1: 'M'); |
693 | QCOMPARE(currentResult, Slot1Triggered); |
694 | |
695 | cut2->setEnabled(false); |
696 | cut4->setEnabled(true); |
697 | |
698 | /* Testing Disabled Shortcuts |
699 | Qt::Key_M on slot1 |
700 | Shift + Qt::Key_M on slot1 (disabled) |
701 | Qt::Key_M on slot2 (disabled) |
702 | Shift + Qt::Key_M on slot2 |
703 | */ |
704 | currentResult = NoResult; |
705 | sendKeyEvents(w: &mainW, k1: Qt::Key_M, c1: 'm' ); |
706 | QCOMPARE( currentResult, Slot1Triggered ); |
707 | |
708 | currentResult = NoResult; |
709 | sendKeyEvents(w: &mainW, k1: shiftM, c1: 'M' ); |
710 | QCOMPARE( currentResult, Slot2Triggered ); |
711 | |
712 | |
713 | /* Testing Disabled Accel |
714 | Qt::Key_F5 on slot1 |
715 | Shift + Qt::Key_F5 on slot2 (disabled) |
716 | */ |
717 | qDeleteAll(c: mainW.findChildren<QShortcut *>()); |
718 | const int shiftF5 = Qt::SHIFT + Qt::Key_F5; |
719 | cut1 = setupShortcut(parent: pb1, name: "shortcut1-pb1" , testWidget: TriggerSlot1, ks: QKeySequence(Qt::Key_F5)); |
720 | cut4 = setupShortcut(parent: pb2, name: "shortcut4-pb2" , testWidget: TriggerSlot2, ks: QKeySequence(shiftF5)); |
721 | |
722 | cut1->setEnabled(true); |
723 | cut4->setEnabled(false); |
724 | |
725 | currentResult = NoResult; |
726 | sendKeyEvents(w: &mainW, k1: Qt::Key_F5, c1: 0 ); |
727 | QCOMPARE( currentResult, Slot1Triggered ); |
728 | |
729 | currentResult = NoResult; |
730 | sendKeyEvents(w: &mainW, k1: shiftF5, c1: 0 ); |
731 | QCOMPARE( currentResult, NoResult ); |
732 | } |
733 | // ------------------------------------------------------------------ |
734 | // Ambiguous Elements ----------------------------------------------- |
735 | // ------------------------------------------------------------------ |
736 | void tst_QShortcut::ambiguousRotation() |
737 | { |
738 | if (QGuiApplication::platformName().startsWith(s: QLatin1String("wayland" ), cs: Qt::CaseInsensitive)) |
739 | QSKIP("Wayland: This fails. Figure out why." ); |
740 | |
741 | MainWindow mainW; |
742 | const QString name = QLatin1String(QTest::currentTestFunction()); |
743 | mainW.setWindowTitle(name); |
744 | mainW.show(); |
745 | mainW.activateWindow(); |
746 | QVERIFY(QTest::qWaitForWindowActive(&mainW)); |
747 | |
748 | /* Testing Shortcut rotation scheme |
749 | Ctrl + Qt::Key_A on slot1 (disabled) |
750 | Ctrl + Qt::Key_A on slot2 (disabled) |
751 | Ctrl + Qt::Key_A on slot3 |
752 | Ctrl + Qt::Key_A on slot4 |
753 | Ctrl + Qt::Key_A on slot5 (disabled) |
754 | Ctrl + Qt::Key_A on slot6 |
755 | Ctrl + Qt::Key_A on slot7 (disabled) |
756 | */ |
757 | const int ctrlA = Qt::CTRL + Qt::Key_A; |
758 | QKeySequence ctrlA_Sequence(ctrlA); |
759 | QShortcut *cut1 = setupShortcut(parent: &mainW, name, testWidget: TriggerSlot1, ks: ctrlA_Sequence); |
760 | QShortcut *cut2 = setupShortcut(parent: &mainW, name, testWidget: TriggerSlot2, ks: ctrlA_Sequence); |
761 | QShortcut *cut3 = setupShortcut(parent: &mainW, name, testWidget: TriggerSlot3, ks: ctrlA_Sequence); |
762 | QShortcut *cut4 = setupShortcut(parent: &mainW, name, testWidget: TriggerSlot4, ks: ctrlA_Sequence); |
763 | QShortcut *cut5 = setupShortcut(parent: &mainW, name, testWidget: TriggerSlot5, ks: ctrlA_Sequence); |
764 | QShortcut *cut6 = setupShortcut(parent: &mainW, name, testWidget: TriggerSlot6, ks: ctrlA_Sequence); |
765 | QShortcut *cut7 = setupShortcut(parent: &mainW, name, testWidget: TriggerSlot7, ks: ctrlA_Sequence); |
766 | |
767 | cut1->setEnabled(false); |
768 | cut2->setEnabled(false); |
769 | cut5->setEnabled(false); |
770 | cut7->setEnabled(false); |
771 | |
772 | // Test proper rotation |
773 | // Start on first |
774 | // Go to last |
775 | // Go back to first |
776 | // Continue... |
777 | currentResult = NoResult; |
778 | ambigResult = NoResult; |
779 | sendKeyEvents(w: &mainW, k1: ctrlA); |
780 | QCOMPARE(currentResult, Ambiguous); |
781 | QCOMPARE(ambigResult, Slot3Triggered); |
782 | |
783 | currentResult = NoResult; |
784 | ambigResult = NoResult; |
785 | sendKeyEvents(w: &mainW, k1: ctrlA); |
786 | QCOMPARE(currentResult, Ambiguous); |
787 | QCOMPARE(ambigResult, Slot4Triggered); |
788 | |
789 | currentResult = NoResult; |
790 | ambigResult = NoResult; |
791 | sendKeyEvents(w: &mainW, k1: ctrlA); |
792 | QCOMPARE(currentResult, Ambiguous); |
793 | QCOMPARE(ambigResult, Slot6Triggered); |
794 | |
795 | currentResult = NoResult; |
796 | ambigResult = NoResult; |
797 | sendKeyEvents(w: &mainW, k1: ctrlA); |
798 | QCOMPARE(currentResult, Ambiguous); |
799 | QCOMPARE(ambigResult, Slot3Triggered); |
800 | |
801 | currentResult = NoResult; |
802 | ambigResult = NoResult; |
803 | sendKeyEvents(w: &mainW, k1: ctrlA); |
804 | QCOMPARE(currentResult, Ambiguous); |
805 | QCOMPARE(ambigResult, Slot4Triggered); |
806 | |
807 | currentResult = NoResult; |
808 | ambigResult = NoResult; |
809 | sendKeyEvents(w: &mainW, k1: ctrlA); |
810 | QCOMPARE(currentResult, Ambiguous); |
811 | QCOMPARE(ambigResult, Slot6Triggered); |
812 | |
813 | /* Testing Shortcut rotation scheme |
814 | Ctrl + Qt::Key_A on slot1 |
815 | Ctrl + Qt::Key_A on slot2 |
816 | Ctrl + Qt::Key_A on slot3 (disabled) |
817 | Ctrl + Qt::Key_A on slot4 (disabled) |
818 | Ctrl + Qt::Key_A on slot5 |
819 | Ctrl + Qt::Key_A on slot6 (disabled) |
820 | Ctrl + Qt::Key_A on slot7 |
821 | */ |
822 | |
823 | cut1->setEnabled(true); |
824 | cut2->setEnabled(true); |
825 | cut5->setEnabled(true); |
826 | cut7->setEnabled(true); |
827 | |
828 | cut3->setEnabled(false); |
829 | cut4->setEnabled(false); |
830 | cut6->setEnabled(false); |
831 | |
832 | currentResult = NoResult; |
833 | ambigResult = NoResult; |
834 | sendKeyEvents(w: &mainW, k1: ctrlA); |
835 | QCOMPARE(currentResult, Ambiguous); |
836 | QCOMPARE(ambigResult, Slot1Triggered); |
837 | |
838 | currentResult = NoResult; |
839 | ambigResult = NoResult; |
840 | sendKeyEvents(w: &mainW, k1: ctrlA); |
841 | QCOMPARE(currentResult, Ambiguous); |
842 | QCOMPARE(ambigResult, Slot2Triggered); |
843 | |
844 | currentResult = NoResult; |
845 | ambigResult = NoResult; |
846 | sendKeyEvents(w: &mainW, k1: ctrlA); |
847 | QCOMPARE(currentResult, Ambiguous); |
848 | QCOMPARE(ambigResult, Slot5Triggered); |
849 | |
850 | currentResult = NoResult; |
851 | ambigResult = NoResult; |
852 | sendKeyEvents(w: &mainW, k1: ctrlA); |
853 | QCOMPARE(currentResult, Ambiguous); |
854 | QCOMPARE(ambigResult, Slot7Triggered); |
855 | |
856 | currentResult = NoResult; |
857 | ambigResult = NoResult; |
858 | sendKeyEvents(w: &mainW, k1: ctrlA); |
859 | QCOMPARE(currentResult, Ambiguous); |
860 | QCOMPARE(ambigResult, Slot1Triggered); |
861 | |
862 | currentResult = NoResult; |
863 | ambigResult = NoResult; |
864 | sendKeyEvents(w: &mainW, k1: ctrlA); |
865 | QCOMPARE(currentResult, Ambiguous); |
866 | QCOMPARE(ambigResult, Slot2Triggered); |
867 | |
868 | currentResult = NoResult; |
869 | ambigResult = NoResult; |
870 | sendKeyEvents(w: &mainW, k1: ctrlA); |
871 | QCOMPARE(currentResult, Ambiguous); |
872 | QCOMPARE(ambigResult, Slot5Triggered); |
873 | |
874 | currentResult = NoResult; |
875 | ambigResult = NoResult; |
876 | sendKeyEvents(w: &mainW, k1: ctrlA); |
877 | QCOMPARE(currentResult, Ambiguous); |
878 | QCOMPARE(ambigResult, Slot7Triggered); |
879 | } |
880 | |
881 | void tst_QShortcut::ambiguousItems() |
882 | { |
883 | if (QGuiApplication::platformName().startsWith(s: QLatin1String("wayland" ), cs: Qt::CaseInsensitive)) |
884 | QSKIP("Wayland: This fails. Figure out why." ); |
885 | |
886 | ButtonWidget mainW; |
887 | mainW.setWindowTitle(QTest::currentTestFunction()); |
888 | mainW.show(); |
889 | mainW.activateWindow(); |
890 | QVERIFY(QTest::qWaitForWindowActive(&mainW)); |
891 | |
892 | /* Testing Ambiguous Shortcuts |
893 | Qt::Key_M on Pushbutton 1 |
894 | Qt::Key_M on Pushbutton 2 |
895 | */ |
896 | |
897 | // Setup two identical shortcuts on different pushbuttons |
898 | auto pb1 = mainW.pushButton1(); |
899 | auto pb2 = mainW.pushButton2(); |
900 | |
901 | setupShortcut(parent: pb1, name: "shortcut1-pb1" , testWidget: TriggerSlot1, ks: QKeySequence(Qt::Key_M)); |
902 | setupShortcut(parent: pb2, name: "shortcut2-pb2" , testWidget: TriggerSlot2, ks: QKeySequence(Qt::Key_M)); |
903 | |
904 | currentResult = NoResult; |
905 | sendKeyEvents(w: &mainW, k1: Qt::Key_M, c1: 'm' ); |
906 | QCOMPARE( currentResult, Ambiguous ); |
907 | QCOMPARE( ambigResult, Slot1Triggered ); |
908 | |
909 | currentResult = NoResult; |
910 | sendKeyEvents(w: &mainW, k1: Qt::Key_M, c1: 'm' ); |
911 | QCOMPARE( currentResult, Ambiguous ); |
912 | QCOMPARE( ambigResult, Slot2Triggered ); |
913 | |
914 | currentResult = NoResult; |
915 | sendKeyEvents(w: &mainW, k1: Qt::Key_M, c1: 'm' ); |
916 | QCOMPARE( currentResult, Ambiguous ); |
917 | QCOMPARE( ambigResult, Slot1Triggered ); |
918 | } |
919 | |
920 | |
921 | // ------------------------------------------------------------------ |
922 | // Unicode and non-unicode Elements --------------------------------- |
923 | // ------------------------------------------------------------------ |
924 | void tst_QShortcut::unicodeCompare() |
925 | { |
926 | if (QGuiApplication::platformName().startsWith(s: QLatin1String("wayland" ), cs: Qt::CaseInsensitive)) |
927 | QSKIP("Wayland: This fails. Figure out why." ); |
928 | |
929 | ButtonWidget mainW; |
930 | mainW.setWindowTitle(QTest::currentTestFunction()); |
931 | mainW.show(); |
932 | mainW.activateWindow(); |
933 | QVERIFY(QTest::qWaitForWindowActive(&mainW)); |
934 | |
935 | /* Testing Unicode/non-Unicode Shortcuts |
936 | Qt::Key_M on Pushbutton 1 |
937 | Qt::Key_M on Pushbutton 2 |
938 | */ |
939 | auto pb1 = mainW.pushButton1(); |
940 | auto pb2 = mainW.pushButton2(); |
941 | |
942 | QKeySequence ks1("Ctrl+M" ); // Unicode |
943 | QKeySequence ks2(Qt::CTRL+Qt::Key_M); // non-Unicode |
944 | setupShortcut(parent: pb1, name: "shortcut1-pb1" , testWidget: TriggerSlot1, ks: ks1); |
945 | setupShortcut(parent: pb2, name: "shortcut2-pb2" , testWidget: TriggerSlot2, ks: ks2); |
946 | |
947 | currentResult = NoResult; |
948 | sendKeyEvents(w: &mainW, k1: Qt::CTRL + Qt::Key_M, c1: 0); |
949 | QCOMPARE( currentResult, Ambiguous ); |
950 | // They _are_ ambiguous, so the QKeySequence operator== |
951 | // should indicate the same |
952 | QVERIFY( ks1 == ks2 ); |
953 | QVERIFY( !(ks1 != ks2) ); |
954 | } |
955 | |
956 | // ------------------------------------------------------------------ |
957 | // Keypress consumption verification -------------------------------- |
958 | // ------------------------------------------------------------------ |
959 | void tst_QShortcut::keypressConsumption() |
960 | { |
961 | if (QGuiApplication::platformName().startsWith(s: QLatin1String("wayland" ), cs: Qt::CaseInsensitive)) |
962 | QSKIP("Wayland: This fails. Figure out why." ); |
963 | |
964 | MainWindow mainW; |
965 | mainW.setWindowTitle(QTest::currentTestFunction()); |
966 | mainW.show(); |
967 | mainW.activateWindow(); |
968 | QVERIFY(QTest::qWaitForWindowActive(&mainW)); |
969 | auto edit = mainW.testEdit(); |
970 | |
971 | const int ctrlI = Qt::CTRL + Qt::Key_I; |
972 | QShortcut *cut1 = setupShortcut(parent: edit, name: "shortcut1-line" , testWidget: TriggerSlot1, ks: QKeySequence(ctrlI, Qt::Key_A)); |
973 | QShortcut *cut2 = setupShortcut(parent: edit, name: "shortcut1-line" , testWidget: TriggerSlot2, ks: QKeySequence(ctrlI, Qt::Key_B)); |
974 | |
975 | currentResult = NoResult; |
976 | ambigResult = NoResult; |
977 | sendKeyEvents(w: edit, k1: ctrlI, c1: 0); // Send key to edit |
978 | QCOMPARE( currentResult, NoResult ); |
979 | QCOMPARE( ambigResult, NoResult ); |
980 | QCOMPARE(edit->toPlainText(), QString()); |
981 | |
982 | // Make sure next keypress is eaten (failing multiple keysequence) |
983 | sendKeyEvents(w: edit, k1: Qt::Key_C, c1: 'c'); // Send key to edit |
984 | QCOMPARE( currentResult, NoResult ); |
985 | QCOMPARE( ambigResult, NoResult ); |
986 | QCOMPARE(edit->toPlainText(), QString()); |
987 | |
988 | // Next keypress should be normal |
989 | sendKeyEvents(w: edit, k1: Qt::Key_C, c1: 'c'); // Send key to edit |
990 | QCOMPARE( currentResult, NoResult ); |
991 | QCOMPARE( ambigResult, NoResult ); |
992 | QCOMPARE(edit->toPlainText(), QString("c" )); |
993 | |
994 | currentResult = NoResult; |
995 | ambigResult = NoResult; |
996 | edit->clear(); |
997 | QCOMPARE(edit->toPlainText().size(), 0); |
998 | |
999 | cut1->setEnabled(false); |
1000 | cut2->setEnabled(false); |
1001 | |
1002 | // Make sure keypresses is passed on, since all multiple keysequences |
1003 | // with Ctrl+I are disabled |
1004 | sendKeyEvents(w: edit, k1: Qt::CTRL + Qt::Key_I, c1: 0); // Send key to edit |
1005 | QCOMPARE( currentResult, NoResult ); |
1006 | QCOMPARE( ambigResult, NoResult ); |
1007 | QVERIFY(edit->toPlainText().endsWith("<Ctrl+I>" )); |
1008 | |
1009 | sendKeyEvents(w: edit, k1: Qt::Key_A, c1: 'a'); // Send key to edit |
1010 | QCOMPARE( currentResult, NoResult ); |
1011 | QCOMPARE( ambigResult, NoResult ); |
1012 | QVERIFY(edit->toPlainText().endsWith("<Ctrl+I>a" )); |
1013 | |
1014 | qDeleteAll(c: mainW.findChildren<QShortcut *>()); |
1015 | edit->clear(); |
1016 | QCOMPARE(edit->toPlainText().size(), 0); |
1017 | |
1018 | auto cut = setupShortcut(parent: edit, name: QLatin1String("first" ), ks: QKeySequence(Qt::CTRL + Qt::Key_A)); |
1019 | connect(sender: cut, signal: &QShortcut::activated, context: edit, slot: [this, edit] () { |
1020 | this->sendKeyEvents(w: edit, k1: Qt::CTRL + Qt::Key_B, c1: 0); |
1021 | this->currentResult = tst_QShortcut::SentKeyEvent; |
1022 | }); |
1023 | |
1024 | // Verify reentrancy when a non-shortcut is triggered as part |
1025 | // of shortcut processing. |
1026 | currentResult = NoResult; |
1027 | ambigResult = NoResult; |
1028 | sendKeyEvents(w: edit, k1: Qt::CTRL + Qt::Key_A, c1: 0); |
1029 | QCOMPARE(currentResult, SentKeyEvent); |
1030 | QCOMPARE(ambigResult, NoResult); |
1031 | QCOMPARE(edit->toPlainText(), QLatin1String("<Ctrl+B>" )); |
1032 | } |
1033 | |
1034 | // ------------------------------------------------------------------ |
1035 | // Context Validation ----------------------------------------------- |
1036 | // ------------------------------------------------------------------ |
1037 | void tst_QShortcut::context() |
1038 | { |
1039 | const QString name = QLatin1String(QTest::currentTestFunction()); |
1040 | MainWindow mainW; |
1041 | mainW.setWindowTitle(name + QLatin1String("_Helper" )); |
1042 | mainW.show(); |
1043 | auto edit = mainW.testEdit(); |
1044 | |
1045 | QWidget myBox; |
1046 | myBox.setWindowTitle(name); |
1047 | auto other1 = new TestEdit(&myBox, "test_edit_other1" ); |
1048 | auto other2 = new TestEdit(&myBox, "test_edit_other2" ); |
1049 | auto layout = new QHBoxLayout(&myBox); |
1050 | layout->addWidget(other1); |
1051 | layout->addWidget(other2); |
1052 | myBox.show(); |
1053 | QVERIFY(QTest::qWaitForWindowExposed(&myBox)); |
1054 | |
1055 | setupShortcut(parent: other1, name: "ActiveWindow" , testWidget: TriggerSlot1, ks: QKeySequence("Alt+1" ), context: Qt::WindowShortcut); |
1056 | setupShortcut(parent: other2, name: "Focus" , testWidget: TriggerSlot2, ks: QKeySequence("Alt+2" ), context: Qt::WidgetShortcut); |
1057 | setupShortcut(parent: edit, name: "Application" , testWidget: TriggerSlot3, ks: QKeySequence("Alt+3" ), context: Qt::ApplicationShortcut); |
1058 | |
1059 | currentResult = NoResult; |
1060 | ambigResult = NoResult; |
1061 | edit->clear(); |
1062 | other1->clear(); |
1063 | other2->clear(); |
1064 | |
1065 | // edit doesn't have focus, so ActiveWindow context should work |
1066 | // ..but Focus context shouldn't.. |
1067 | // Changing focus to edit should make focus context work |
1068 | // Application context should always work |
1069 | |
1070 | |
1071 | // Focus on 'other1' edit, so Active Window context should trigger |
1072 | other1->activateWindow(); // <--- |
1073 | QApplication::setActiveWindow(other1); |
1074 | QCOMPARE(QApplication::activeWindow(), other1->window()); |
1075 | QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(other1)); |
1076 | |
1077 | currentResult = NoResult; |
1078 | ambigResult = NoResult; |
1079 | edit->clear(); |
1080 | other1->clear(); |
1081 | other2->clear(); |
1082 | |
1083 | QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(other1)); |
1084 | sendKeyEvents(w: other1, k1: Qt::ALT+Qt::Key_1); |
1085 | QCOMPARE(currentResult, Slot1Triggered); |
1086 | QCOMPARE(ambigResult, NoResult); |
1087 | QCOMPARE(edit->toPlainText(), QString()); |
1088 | QCOMPARE(other1->toPlainText(), QString()); |
1089 | QCOMPARE(other2->toPlainText(), QString()); |
1090 | |
1091 | // ..but not Focus context on 'other2'.. |
1092 | currentResult = NoResult; |
1093 | ambigResult = NoResult; |
1094 | edit->clear(); |
1095 | other1->clear(); |
1096 | other2->clear(); |
1097 | |
1098 | sendKeyEvents(w: other1, k1: Qt::ALT+Qt::Key_2); |
1099 | QCOMPARE(currentResult, NoResult); |
1100 | QCOMPARE(ambigResult, NoResult); |
1101 | QCOMPARE(edit->toPlainText(), QString()); |
1102 | QCOMPARE(other1->toPlainText(), QString("<Alt+2>" )); |
1103 | QCOMPARE(other2->toPlainText(), QString()); |
1104 | |
1105 | // ..however, application global context on 'edit' should.. |
1106 | currentResult = NoResult; |
1107 | ambigResult = NoResult; |
1108 | edit->clear(); |
1109 | other1->clear(); |
1110 | other2->clear(); |
1111 | |
1112 | sendKeyEvents(w: other1, k1: Qt::ALT+Qt::Key_3); |
1113 | QCOMPARE(currentResult, Slot3Triggered); |
1114 | QCOMPARE(ambigResult, NoResult); |
1115 | QCOMPARE(edit->toPlainText(), QString()); |
1116 | QCOMPARE(other1->toPlainText(), QString()); |
1117 | QCOMPARE(other2->toPlainText(), QString()); |
1118 | |
1119 | // Changing focus to 'other2' should make the Focus context there work |
1120 | other2->activateWindow(); |
1121 | other2->setFocus(); // ### |
1122 | QTRY_COMPARE(QApplication::activeWindow(), other2->window()); |
1123 | QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(other2)); |
1124 | |
1125 | currentResult = NoResult; |
1126 | ambigResult = NoResult; |
1127 | edit->clear(); |
1128 | other1->clear(); |
1129 | other2->clear(); |
1130 | |
1131 | sendKeyEvents(w: other2, k1: Qt::ALT+Qt::Key_2); |
1132 | QCOMPARE(currentResult, Slot2Triggered); |
1133 | QCOMPARE(ambigResult, NoResult); |
1134 | QCOMPARE(edit->toPlainText(), QString()); |
1135 | QCOMPARE(other1->toPlainText(), QString()); |
1136 | QCOMPARE(other2->toPlainText(), QString()); |
1137 | } |
1138 | |
1139 | // QTBUG-38986, do not generate duplicated QEvent::ShortcutOverride in event processing. |
1140 | class OverrideCountingWidget : public QWidget |
1141 | { |
1142 | public: |
1143 | using QWidget::QWidget; |
1144 | |
1145 | int overrideCount = 0; |
1146 | |
1147 | bool event(QEvent *e) override |
1148 | { |
1149 | if (e->type() == QEvent::ShortcutOverride) |
1150 | overrideCount++; |
1151 | return QWidget::event(event: e); |
1152 | } |
1153 | }; |
1154 | |
1155 | void tst_QShortcut::duplicatedShortcutOverride() |
1156 | { |
1157 | if (QGuiApplication::platformName().startsWith(s: QLatin1String("wayland" ), cs: Qt::CaseInsensitive)) |
1158 | QSKIP("Wayland: This fails. Figure out why." ); |
1159 | |
1160 | OverrideCountingWidget w; |
1161 | w.setWindowTitle(Q_FUNC_INFO); |
1162 | w.resize(w: 200, h: 200); |
1163 | w.move(QGuiApplication::primaryScreen()->availableGeometry().center() - QPoint(100, 100)); |
1164 | w.show(); |
1165 | QApplication::setActiveWindow(&w); |
1166 | QVERIFY(QTest::qWaitForWindowActive(&w)); |
1167 | QTest::keyPress(window: w.windowHandle(), key: Qt::Key_A); |
1168 | QCoreApplication::processEvents(); |
1169 | QCOMPARE(w.overrideCount, 1); |
1170 | } |
1171 | |
1172 | QShortcut *tst_QShortcut::setupShortcut(QWidget *parent, const QString &name, const QKeySequence &ks, Qt::ShortcutContext context) |
1173 | { |
1174 | // Set up shortcut for next test |
1175 | auto cut = new QShortcut(ks, parent, nullptr, nullptr, context); |
1176 | cut->setObjectName(name); |
1177 | return cut; |
1178 | } |
1179 | |
1180 | QShortcut *tst_QShortcut::setupShortcut(QWidget *parent, const QString &name, Widget testWidget, |
1181 | const QKeySequence &ks, Qt::ShortcutContext context) |
1182 | { |
1183 | // Set up shortcut for next test |
1184 | auto cut = setupShortcut(parent, name, ks, context); |
1185 | |
1186 | switch (testWidget) { |
1187 | case TriggerSlot1: |
1188 | connect(sender: cut, signal: &QShortcut::activated, receiver: this, slot: &tst_QShortcut::slotTrig1); |
1189 | connect(sender: cut, signal: &QShortcut::activatedAmbiguously, receiver: this, slot: &tst_QShortcut::ambigSlot1); |
1190 | break; |
1191 | case TriggerSlot2: |
1192 | connect(sender: cut, signal: &QShortcut::activated, receiver: this, slot: &tst_QShortcut::slotTrig2); |
1193 | connect(sender: cut, signal: &QShortcut::activatedAmbiguously, receiver: this, slot: &tst_QShortcut::ambigSlot2); |
1194 | break; |
1195 | case TriggerSlot3: |
1196 | connect(sender: cut, signal: &QShortcut::activated, receiver: this, slot: &tst_QShortcut::slotTrig3); |
1197 | connect(sender: cut, signal: &QShortcut::activatedAmbiguously, receiver: this, slot: &tst_QShortcut::ambigSlot3); |
1198 | break; |
1199 | case TriggerSlot4: |
1200 | connect(sender: cut, signal: &QShortcut::activated, receiver: this, slot: &tst_QShortcut::slotTrig4); |
1201 | connect(sender: cut, signal: &QShortcut::activatedAmbiguously, receiver: this, slot: &tst_QShortcut::ambigSlot4); |
1202 | break; |
1203 | case TriggerSlot5: |
1204 | connect(sender: cut, signal: &QShortcut::activated, receiver: this, slot: &tst_QShortcut::slotTrig5); |
1205 | connect(sender: cut, signal: &QShortcut::activatedAmbiguously, receiver: this, slot: &tst_QShortcut::ambigSlot5); |
1206 | break; |
1207 | case TriggerSlot6: |
1208 | connect(sender: cut, signal: &QShortcut::activated, receiver: this, slot: &tst_QShortcut::slotTrig6); |
1209 | connect(sender: cut, signal: &QShortcut::activatedAmbiguously, receiver: this, slot: &tst_QShortcut::ambigSlot6); |
1210 | break; |
1211 | case TriggerSlot7: |
1212 | connect(sender: cut, signal: &QShortcut::activated, receiver: this, slot: &tst_QShortcut::slotTrig7); |
1213 | connect(sender: cut, signal: &QShortcut::activatedAmbiguously, receiver: this, slot: &tst_QShortcut::ambigSlot7); |
1214 | break; |
1215 | case NoWidget: |
1216 | break; |
1217 | } |
1218 | return cut; |
1219 | } |
1220 | |
1221 | void tst_QShortcut::sendKeyEvents(QWidget *w, int k1, QChar c1, int k2, QChar c2, int k3, QChar c3, int k4, QChar c4) |
1222 | { |
1223 | Qt::KeyboardModifiers b1 = toButtons( key: k1 ); |
1224 | Qt::KeyboardModifiers b2 = toButtons( key: k2 ); |
1225 | Qt::KeyboardModifiers b3 = toButtons( key: k3 ); |
1226 | Qt::KeyboardModifiers b4 = toButtons( key: k4 ); |
1227 | k1 &= ~Qt::MODIFIER_MASK; |
1228 | k2 &= ~Qt::MODIFIER_MASK; |
1229 | k3 &= ~Qt::MODIFIER_MASK; |
1230 | k4 &= ~Qt::MODIFIER_MASK; |
1231 | |
1232 | |
1233 | if (k1 || c1.toLatin1()) { |
1234 | QString c(c1.unicode() == QChar::Null ? QString() : QString(c1)); |
1235 | QTest::sendKeyEvent(action: QTest::Press, widget: w, code: static_cast<Qt::Key>(k1), text: c, modifier: b1); |
1236 | QTest::sendKeyEvent(action: QTest::Release, widget: w, code: static_cast<Qt::Key>(k1), text: c, modifier: b1); |
1237 | } |
1238 | |
1239 | if (k2 || c2.toLatin1()) { |
1240 | QString c(c2.unicode() == QChar::Null ? QString() : QString(c2)); |
1241 | QTest::sendKeyEvent(action: QTest::Press, widget: w, code: static_cast<Qt::Key>(k2), text: c, modifier: b2); |
1242 | QTest::sendKeyEvent(action: QTest::Release, widget: w, code: static_cast<Qt::Key>(k2), text: c, modifier: b2); |
1243 | } |
1244 | |
1245 | if (k3 || c3.toLatin1()) { |
1246 | QString c(c3.unicode() == QChar::Null ? QString() : QString(c3)); |
1247 | QTest::sendKeyEvent(action: QTest::Press, widget: w, code: static_cast<Qt::Key>(k3), text: c, modifier: b3); |
1248 | QTest::sendKeyEvent(action: QTest::Release, widget: w, code: static_cast<Qt::Key>(k3), text: c, modifier: b3); |
1249 | } |
1250 | |
1251 | if (k4 || c4.toLatin1()) { |
1252 | QString c(c4.unicode() == QChar::Null ? QString() : QString(c4)); |
1253 | QTest::sendKeyEvent(action: QTest::Press, widget: w, code: static_cast<Qt::Key>(k4), text: c, modifier: b4); |
1254 | QTest::sendKeyEvent(action: QTest::Release, widget: w, code: static_cast<Qt::Key>(k4), text: c, modifier: b4); |
1255 | } |
1256 | } |
1257 | |
1258 | void tst_QShortcut::testElement() |
1259 | { |
1260 | if (QGuiApplication::platformName().startsWith(s: QLatin1String("wayland" ), cs: Qt::CaseInsensitive)) |
1261 | QSKIP("Wayland: This fails. Figure out why." ); |
1262 | |
1263 | static QScopedPointer<MainWindow> mainW; |
1264 | |
1265 | currentResult = NoResult; |
1266 | QFETCH(tst_QShortcut::Action, action); |
1267 | QFETCH(tst_QShortcut::Widget, testWidget); |
1268 | QFETCH(QString, txt); |
1269 | QFETCH(int, k1); |
1270 | QFETCH(int, c1); |
1271 | QFETCH(int, k2); |
1272 | QFETCH(int, c2); |
1273 | QFETCH(int, k3); |
1274 | QFETCH(int, c3); |
1275 | QFETCH(int, k4); |
1276 | QFETCH(int, c4); |
1277 | QFETCH(tst_QShortcut::Result, result); |
1278 | |
1279 | if (mainW.isNull()) { |
1280 | mainW.reset(other: new MainWindow); |
1281 | mainW->setWindowTitle(QTest::currentTestFunction()); |
1282 | mainW->show(); |
1283 | mainW->activateWindow(); |
1284 | QVERIFY(QTest::qWaitForWindowActive(mainW.data())); |
1285 | } |
1286 | |
1287 | switch (action) { |
1288 | case ClearAll: |
1289 | qDeleteAll(c: mainW->findChildren<QShortcut *>()); |
1290 | break; |
1291 | case SetupAccel: |
1292 | setupShortcut(parent: mainW.data(), name: txt, testWidget, ks: txt.isEmpty() |
1293 | ? QKeySequence(k1, k2, k3, k4) : QKeySequence::fromString(str: txt)); |
1294 | break; |
1295 | case TestAccel: |
1296 | sendKeyEvents(w: mainW.data(), k1, c1, k2, c2, k3, c3, k4, c4); |
1297 | QCOMPARE(currentResult, result); |
1298 | break; |
1299 | case TestEnd: |
1300 | mainW.reset(); |
1301 | break; |
1302 | } |
1303 | } |
1304 | |
1305 | void tst_QShortcut::shortcutToFocusProxy() |
1306 | { |
1307 | if (QGuiApplication::platformName().startsWith(s: QLatin1String("wayland" ), cs: Qt::CaseInsensitive)) |
1308 | QSKIP("Wayland: This fails. Figure out why." ); |
1309 | |
1310 | QLineEdit le; |
1311 | QCompleter completer; |
1312 | QStringListModel *slm = new QStringListModel(QStringList() << "a0" << "a1" << "a2" , &completer); |
1313 | completer.setModel(slm); |
1314 | completer.setCompletionMode(QCompleter::PopupCompletion); |
1315 | le.setCompleter(&completer); |
1316 | QShortcut *shortcut = new QShortcut(QKeySequence(Qt::ALT + Qt::Key_S), &le); |
1317 | QObject::connect(sender: shortcut, signal: &QShortcut::activated, receiver: &le, slot: &QLineEdit::clear); |
1318 | le.setFocus(); |
1319 | le.show(); |
1320 | |
1321 | QVERIFY(QTest::qWaitForWindowActive(&le)); |
1322 | QCOMPARE(QApplication::focusWidget(), &le); |
1323 | QTest::keyEvent(action: QTest::Press, widget: QApplication::focusWidget(), key: Qt::Key_A); |
1324 | |
1325 | QCOMPARE(le.text(), QString::fromLocal8Bit("a" )); |
1326 | QTest::keyEvent(action: QTest::Press, widget: QApplication::focusWidget(), key: Qt::Key_Alt); |
1327 | QTest::keyEvent(action: QTest::Press, widget: QApplication::focusWidget(), key: Qt::Key_S, modifier: Qt::AltModifier); |
1328 | QCOMPARE(le.text(), QString()); |
1329 | } |
1330 | |
1331 | void tst_QShortcut::deleteLater() |
1332 | { |
1333 | QWidget w; |
1334 | QPointer<QShortcut> sc(new QShortcut(QKeySequence(Qt::Key_1), &w)); |
1335 | sc->deleteLater(); |
1336 | QTRY_VERIFY(!sc); |
1337 | } |
1338 | |
1339 | |
1340 | QTEST_MAIN(tst_QShortcut) |
1341 | #include "tst_qshortcut.moc" |
1342 | |