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 | #include <QDialog> |
30 | #include <QMainWindow> |
31 | #include <QtTest/QtTest> |
32 | |
33 | #include <qapplication.h> |
34 | #include <qevent.h> |
35 | #include <qaction.h> |
36 | #include <qmenu.h> |
37 | #include <qpa/qplatformtheme.h> |
38 | #include <qpa/qplatformintegration.h> |
39 | #include <private/qguiapplication_p.h> |
40 | |
41 | class tst_QAction : public QObject |
42 | { |
43 | Q_OBJECT |
44 | |
45 | public: |
46 | tst_QAction(); |
47 | |
48 | void updateState(QActionEvent *e); |
49 | |
50 | private slots: |
51 | void init(); |
52 | void cleanup(); |
53 | void getSetCheck(); |
54 | void setText_data(); |
55 | void setText(); |
56 | void setIconText_data() { setText_data(); } |
57 | void setIconText(); |
58 | void setUnknownFont(); |
59 | void actionEvent(); |
60 | void setStandardKeys(); |
61 | void alternateShortcuts(); |
62 | void enabledVisibleInteraction(); |
63 | void task200823_tooltip(); |
64 | void task229128TriggeredSignalWithoutActiongroup(); |
65 | void task229128TriggeredSignalWhenInActiongroup(); |
66 | void repeat(); |
67 | void setData(); |
68 | void keysequence(); // QTBUG-53381 |
69 | void disableShortcutsWithBlockedWidgets_data(); |
70 | void disableShortcutsWithBlockedWidgets(); |
71 | void shortcutFromKeyEvent(); // QTBUG-48325 |
72 | |
73 | private: |
74 | QEvent::Type m_lastEventType; |
75 | const int m_keyboardScheme; |
76 | QAction *m_lastAction; |
77 | }; |
78 | |
79 | tst_QAction::tst_QAction() |
80 | : m_keyboardScheme(QGuiApplicationPrivate::platformTheme()->themeHint(hint: QPlatformTheme::KeyboardScheme).toInt()) |
81 | { |
82 | } |
83 | |
84 | void tst_QAction::init() |
85 | { |
86 | m_lastEventType = QEvent::None; |
87 | m_lastAction = nullptr; |
88 | } |
89 | |
90 | void tst_QAction::cleanup() |
91 | { |
92 | QVERIFY(QApplication::topLevelWidgets().isEmpty()); |
93 | } |
94 | |
95 | // Testing get/set functions |
96 | void tst_QAction::getSetCheck() |
97 | { |
98 | QAction obj1(nullptr); |
99 | // QActionGroup * QAction::actionGroup() |
100 | // void QAction::setActionGroup(QActionGroup *) |
101 | QActionGroup *var1 = new QActionGroup(nullptr); |
102 | obj1.setActionGroup(var1); |
103 | QCOMPARE(var1, obj1.actionGroup()); |
104 | obj1.setActionGroup(nullptr); |
105 | QCOMPARE(obj1.actionGroup(), nullptr); |
106 | delete var1; |
107 | |
108 | // QMenu * QAction::menu() |
109 | // void QAction::setMenu(QMenu *) |
110 | QMenu *var2 = new QMenu(nullptr); |
111 | obj1.setMenu(var2); |
112 | QCOMPARE(var2, obj1.menu()); |
113 | obj1.setMenu(nullptr); |
114 | QCOMPARE(obj1.menu(), nullptr); |
115 | delete var2; |
116 | |
117 | QCOMPARE(obj1.priority(), QAction::NormalPriority); |
118 | obj1.setPriority(QAction::LowPriority); |
119 | QCOMPARE(obj1.priority(), QAction::LowPriority); |
120 | } |
121 | |
122 | class MyWidget : public QWidget |
123 | { |
124 | Q_OBJECT |
125 | public: |
126 | explicit MyWidget(tst_QAction *tst, QWidget *parent = nullptr) : QWidget(parent), m_test(tst) |
127 | { setWindowTitle(QTest::currentTestFunction()); } |
128 | |
129 | protected: |
130 | void actionEvent(QActionEvent *e) override { m_test->updateState(e); } |
131 | |
132 | private: |
133 | tst_QAction *m_test; |
134 | }; |
135 | |
136 | void tst_QAction::setText_data() |
137 | { |
138 | QTest::addColumn<QString>(name: "text" ); |
139 | QTest::addColumn<QString>(name: "iconText" ); |
140 | QTest::addColumn<QString>(name: "textFromIconText" ); |
141 | |
142 | //next we fill it with data |
143 | QTest::newRow(dataTag: "Normal" ) << "Action" << "Action" << "Action" ; |
144 | QTest::newRow(dataTag: "Ampersand" ) << "Search && Destroy" << "Search & Destroy" << "Search && Destroy" ; |
145 | QTest::newRow(dataTag: "Mnemonic and ellipsis" ) << "O&pen File ..." << "Open File" << "Open File" ; |
146 | } |
147 | |
148 | void tst_QAction::setText() |
149 | { |
150 | QFETCH(QString, text); |
151 | |
152 | QAction action(nullptr); |
153 | action.setText(text); |
154 | |
155 | QCOMPARE(action.text(), text); |
156 | |
157 | QFETCH(QString, iconText); |
158 | QCOMPARE(action.iconText(), iconText); |
159 | } |
160 | |
161 | void tst_QAction::setIconText() |
162 | { |
163 | QFETCH(QString, iconText); |
164 | |
165 | QAction action(nullptr); |
166 | action.setIconText(iconText); |
167 | QCOMPARE(action.iconText(), iconText); |
168 | |
169 | QFETCH(QString, textFromIconText); |
170 | QCOMPARE(action.text(), textFromIconText); |
171 | } |
172 | |
173 | void tst_QAction::setUnknownFont() // QTBUG-42728 |
174 | { |
175 | QAction action(nullptr); |
176 | QFont font("DoesNotExist" , 11); |
177 | action.setFont(font); |
178 | |
179 | QMenu ; |
180 | menu.addAction(action: &action); // should not crash |
181 | } |
182 | |
183 | void tst_QAction::updateState(QActionEvent *e) |
184 | { |
185 | if (!e) { |
186 | m_lastEventType = QEvent::None; |
187 | m_lastAction = nullptr; |
188 | } else { |
189 | m_lastEventType = e->type(); |
190 | m_lastAction = e->action(); |
191 | } |
192 | } |
193 | |
194 | void tst_QAction::actionEvent() |
195 | { |
196 | QAction a(nullptr); |
197 | a.setText("action text" ); |
198 | |
199 | // add action |
200 | MyWidget testWidget(this); |
201 | testWidget.show(); |
202 | QApplication::setActiveWindow(&testWidget); |
203 | testWidget.addAction(action: &a); |
204 | qApp->processEvents(); |
205 | |
206 | QCOMPARE(m_lastEventType, QEvent::ActionAdded); |
207 | QCOMPARE(m_lastAction, &a); |
208 | |
209 | // change action |
210 | a.setText("new action text" ); |
211 | qApp->processEvents(); |
212 | |
213 | QCOMPARE(m_lastEventType, QEvent::ActionChanged); |
214 | QCOMPARE(m_lastAction, &a); |
215 | |
216 | // remove action |
217 | testWidget.removeAction(action: &a); |
218 | qApp->processEvents(); |
219 | |
220 | QCOMPARE(m_lastEventType, QEvent::ActionRemoved); |
221 | QCOMPARE(m_lastAction, &a); |
222 | } |
223 | |
224 | //basic testing of standard keys |
225 | void tst_QAction::setStandardKeys() |
226 | { |
227 | QAction act(nullptr); |
228 | act.setShortcut(QKeySequence("CTRL+L" )); |
229 | QList<QKeySequence> list; |
230 | act.setShortcuts(list); |
231 | act.setShortcuts(QKeySequence::Copy); |
232 | QCOMPARE(act.shortcut(), act.shortcuts().constFirst()); |
233 | |
234 | QList<QKeySequence> expected; |
235 | const QKeySequence ctrlC = QKeySequence(QStringLiteral("CTRL+C" )); |
236 | const QKeySequence ctrlInsert = QKeySequence(QStringLiteral("CTRL+INSERT" )); |
237 | switch (m_keyboardScheme) { |
238 | case QPlatformTheme::MacKeyboardScheme: |
239 | expected << ctrlC; |
240 | break; |
241 | case QPlatformTheme::WindowsKeyboardScheme: |
242 | expected << ctrlC << ctrlInsert; |
243 | break; |
244 | default: // X11 |
245 | expected << ctrlC << ctrlInsert << QKeySequence(QStringLiteral("F16" )); |
246 | break; |
247 | } |
248 | |
249 | QCOMPARE(act.shortcuts(), expected); |
250 | } |
251 | |
252 | |
253 | void tst_QAction::alternateShortcuts() |
254 | { |
255 | //test the alternate shortcuts (by adding more than 1 shortcut) |
256 | |
257 | MyWidget testWidget(this); |
258 | testWidget.show(); |
259 | QApplication::setActiveWindow(&testWidget); |
260 | |
261 | { |
262 | QAction act(&testWidget); |
263 | testWidget.addAction(action: &act); |
264 | QList<QKeySequence> shlist = QList<QKeySequence>() << QKeySequence("CTRL+P" ) << QKeySequence("CTRL+A" ); |
265 | act.setShortcuts(shlist); |
266 | |
267 | QSignalSpy spy(&act, &QAction::triggered); |
268 | |
269 | act.setAutoRepeat(true); |
270 | QTest::keyClick(widget: &testWidget, key: Qt::Key_A, modifier: Qt::ControlModifier); |
271 | QCOMPARE(spy.count(), 1); //act should have been triggered |
272 | |
273 | act.setAutoRepeat(false); |
274 | QTest::keyClick(widget: &testWidget, key: Qt::Key_A, modifier: Qt::ControlModifier); |
275 | QCOMPARE(spy.count(), 2); //act should have been triggered a 2nd time |
276 | |
277 | //end of the scope of the action, it will be destroyed and removed from wid |
278 | //This action should also unregister its shortcuts |
279 | } |
280 | |
281 | |
282 | //this tests a crash (if the action did not unregister its alternate shortcuts) |
283 | QTest::keyClick(widget: &testWidget, key: Qt::Key_A, modifier: Qt::ControlModifier); |
284 | } |
285 | |
286 | void tst_QAction::keysequence() |
287 | { |
288 | MyWidget testWidget(this); |
289 | testWidget.show(); |
290 | QApplication::setActiveWindow(&testWidget); |
291 | |
292 | { |
293 | QAction act(&testWidget); |
294 | testWidget.addAction(action: &act); |
295 | |
296 | QKeySequence ks(QKeySequence::SelectAll); |
297 | |
298 | act.setShortcut(ks); |
299 | |
300 | QSignalSpy spy(&act, &QAction::triggered); |
301 | |
302 | act.setAutoRepeat(true); |
303 | QTest::keySequence(widget: &testWidget, keySequence: ks); |
304 | QCoreApplication::processEvents(); |
305 | QCOMPARE(spy.count(), 1); // act should have been triggered |
306 | |
307 | act.setAutoRepeat(false); |
308 | QTest::keySequence(widget: &testWidget, keySequence: ks); |
309 | QCoreApplication::processEvents(); |
310 | QCOMPARE(spy.count(), 2); //act should have been triggered a 2nd time |
311 | |
312 | // end of the scope of the action, it will be destroyed and removed from widget |
313 | // This action should also unregister its shortcuts |
314 | } |
315 | |
316 | // this tests a crash (if the action did not unregister its alternate shortcuts) |
317 | QTest::keyClick(widget: &testWidget, key: Qt::Key_A, modifier: Qt::ControlModifier); |
318 | } |
319 | |
320 | void tst_QAction::enabledVisibleInteraction() |
321 | { |
322 | MyWidget testWidget(this); |
323 | testWidget.show(); |
324 | QApplication::setActiveWindow(&testWidget); |
325 | |
326 | QAction act(nullptr); |
327 | // check defaults |
328 | QVERIFY(act.isEnabled()); |
329 | QVERIFY(act.isVisible()); |
330 | |
331 | // !visible => !enabled |
332 | act.setVisible(false); |
333 | QVERIFY(!act.isEnabled()); |
334 | act.setVisible(true); |
335 | QVERIFY(act.isEnabled()); |
336 | act.setEnabled(false); |
337 | QVERIFY(act.isVisible()); |
338 | |
339 | // check if shortcut is disabled if not visible |
340 | testWidget.addAction(action: &act); |
341 | act.setShortcut(QKeySequence("Ctrl+T" )); |
342 | QSignalSpy spy(&act, SIGNAL(triggered())); |
343 | act.setEnabled(true); |
344 | act.setVisible(false); |
345 | QTest::keyClick(widget: &testWidget, key: Qt::Key_T, modifier: Qt::ControlModifier); |
346 | QCOMPARE(spy.count(), 0); //act is not visible, so don't trigger |
347 | act.setVisible(false); |
348 | act.setEnabled(true); |
349 | QTest::keyClick(widget: &testWidget, key: Qt::Key_T, modifier: Qt::ControlModifier); |
350 | QCOMPARE(spy.count(), 0); //act is not visible, so don't trigger |
351 | act.setVisible(true); |
352 | act.setEnabled(true); |
353 | QTest::keyClick(widget: &testWidget, key: Qt::Key_T, modifier: Qt::ControlModifier); |
354 | QCOMPARE(spy.count(), 1); //act is visible and enabled, so trigger |
355 | } |
356 | |
357 | void tst_QAction::task200823_tooltip() |
358 | { |
359 | const QScopedPointer<QAction> action(new QAction("foo" , nullptr)); |
360 | QString shortcut("ctrl+o" ); |
361 | action->setShortcut(shortcut); |
362 | |
363 | // we want a non-standard tooltip that shows the shortcut |
364 | action->setToolTip(action->text() + QLatin1String(" (" ) + action->shortcut().toString() + QLatin1Char(')')); |
365 | |
366 | QString ref = QLatin1String("foo (" ) + QKeySequence(shortcut).toString() + QLatin1Char(')'); |
367 | QCOMPARE(action->toolTip(), ref); |
368 | } |
369 | |
370 | void tst_QAction::task229128TriggeredSignalWithoutActiongroup() |
371 | { |
372 | // test without a group |
373 | const QScopedPointer<QAction> actionWithoutGroup(new QAction("Test" , nullptr)); |
374 | QSignalSpy spyWithoutGroup(actionWithoutGroup.data(), QOverload<bool>::of(ptr: &QAction::triggered)); |
375 | QCOMPARE(spyWithoutGroup.count(), 0); |
376 | actionWithoutGroup->trigger(); |
377 | // signal should be emitted |
378 | QCOMPARE(spyWithoutGroup.count(), 1); |
379 | |
380 | // it is now a checkable checked action |
381 | actionWithoutGroup->setCheckable(true); |
382 | actionWithoutGroup->setChecked(true); |
383 | spyWithoutGroup.clear(); |
384 | QCOMPARE(spyWithoutGroup.count(), 0); |
385 | actionWithoutGroup->trigger(); |
386 | // signal should be emitted |
387 | QCOMPARE(spyWithoutGroup.count(), 1); |
388 | } |
389 | |
390 | void tst_QAction::task229128TriggeredSignalWhenInActiongroup() |
391 | { |
392 | QActionGroup ag(nullptr); |
393 | QAction *action = new QAction("Test" , &ag); |
394 | QAction *checkedAction = new QAction("Test 2" , &ag); |
395 | ag.addAction(a: action); |
396 | action->setCheckable(true); |
397 | ag.addAction(a: checkedAction); |
398 | checkedAction->setCheckable(true); |
399 | checkedAction->setChecked(true); |
400 | |
401 | QSignalSpy actionSpy(checkedAction, QOverload<bool>::of(ptr: &QAction::triggered)); |
402 | QSignalSpy actionGroupSpy(&ag, QOverload<QAction*>::of(ptr: &QActionGroup::triggered)); |
403 | QCOMPARE(actionGroupSpy.count(), 0); |
404 | QCOMPARE(actionSpy.count(), 0); |
405 | checkedAction->trigger(); |
406 | // check that both the group and the action have emitted the signal |
407 | QCOMPARE(actionGroupSpy.count(), 1); |
408 | QCOMPARE(actionSpy.count(), 1); |
409 | } |
410 | |
411 | void tst_QAction::repeat() |
412 | { |
413 | if (QGuiApplication::platformName().startsWith(s: QLatin1String("wayland" ), cs: Qt::CaseInsensitive)) |
414 | QSKIP("Wayland: This fails. Figure out why." ); |
415 | |
416 | MyWidget testWidget(this); |
417 | testWidget.show(); |
418 | QApplication::setActiveWindow(&testWidget); |
419 | QVERIFY(QTest::qWaitForWindowActive(&testWidget)); |
420 | |
421 | QAction act(&testWidget); |
422 | testWidget.addAction(action: &act); |
423 | act.setShortcut(QKeySequence(Qt::Key_F)); |
424 | QSignalSpy spy(&act, SIGNAL(triggered())); |
425 | |
426 | act.setAutoRepeat(true); |
427 | QTest::keyPress(widget: &testWidget, key: Qt::Key_F); |
428 | QTest::keyRelease(widget: &testWidget, key: Qt::Key_F); |
429 | QCOMPARE(spy.count(), 1); |
430 | |
431 | spy.clear(); |
432 | QTest::keyPress(widget: &testWidget, key: Qt::Key_F); |
433 | // repeat event |
434 | QTest::simulateEvent(widget: &testWidget, press: true, code: Qt::Key_F, modifier: Qt::NoModifier, text: QString("f" ), repeat: true); |
435 | QTest::simulateEvent(widget: &testWidget, press: true, code: Qt::Key_F, modifier: Qt::NoModifier, text: QString("f" ), repeat: true); |
436 | QTest::keyRelease(widget: &testWidget, key: Qt::Key_F); |
437 | QCOMPARE(spy.count(), 3); |
438 | |
439 | spy.clear(); |
440 | act.setAutoRepeat(false); |
441 | QTest::keyPress(widget: &testWidget, key: Qt::Key_F); |
442 | QTest::simulateEvent(widget: &testWidget, press: true, code: Qt::Key_F, modifier: Qt::NoModifier, text: QString("f" ), repeat: true); |
443 | QTest::simulateEvent(widget: &testWidget, press: true, code: Qt::Key_F, modifier: Qt::NoModifier, text: QString("f" ), repeat: true); |
444 | QTest::keyRelease(widget: &testWidget, key: Qt::Key_F); |
445 | QCOMPARE(spy.count(), 1); |
446 | |
447 | spy.clear(); |
448 | act.setAutoRepeat(true); |
449 | QTest::keyPress(widget: &testWidget, key: Qt::Key_F); |
450 | QTest::simulateEvent(widget: &testWidget, press: true, code: Qt::Key_F, modifier: Qt::NoModifier, text: QString("f" ), repeat: true); |
451 | QTest::keyRelease(widget: &testWidget, key: Qt::Key_F); |
452 | QCOMPARE(spy.count(), 2); |
453 | } |
454 | |
455 | void tst_QAction::setData() // QTBUG-62006 |
456 | { |
457 | QAction act(nullptr); |
458 | QSignalSpy spy(&act, &QAction::changed); |
459 | QCOMPARE(act.data(), QVariant()); |
460 | QCOMPARE(spy.count(), 0); |
461 | act.setData(QVariant()); |
462 | QCOMPARE(spy.count(), 0); |
463 | |
464 | act.setData(-1); |
465 | QCOMPARE(spy.count(), 1); |
466 | act.setData(-1); |
467 | QCOMPARE(spy.count(), 1); |
468 | } |
469 | |
470 | void tst_QAction::disableShortcutsWithBlockedWidgets_data() |
471 | { |
472 | QTest::addColumn<Qt::ShortcutContext>(name: "shortcutContext" ); |
473 | QTest::addColumn<Qt::WindowModality>(name: "windowModality" ); |
474 | |
475 | QTest::newRow(dataTag: "application modal dialog should block window shortcut." ) |
476 | << Qt::WindowShortcut << Qt::ApplicationModal; |
477 | |
478 | QTest::newRow(dataTag: "application modal dialog should block application shortcut." ) |
479 | << Qt::ApplicationShortcut << Qt::ApplicationModal; |
480 | |
481 | QTest::newRow(dataTag: "window modal dialog should block application shortcut." ) |
482 | << Qt::ApplicationShortcut << Qt::WindowModal; |
483 | |
484 | QTest::newRow(dataTag: "window modal dialog should block window shortcut." ) |
485 | << Qt::WindowShortcut << Qt::WindowModal; |
486 | } |
487 | |
488 | |
489 | void tst_QAction::disableShortcutsWithBlockedWidgets() |
490 | { |
491 | if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(cap: QPlatformIntegration::WindowActivation)) |
492 | QSKIP("Window activation is not supported" ); |
493 | |
494 | QMainWindow window; |
495 | |
496 | QFETCH(Qt::ShortcutContext, shortcutContext); |
497 | QAction action(&window); |
498 | window.addAction(action: &action); |
499 | action.setShortcut(QKeySequence(Qt::Key_1)); |
500 | action.setShortcutContext(shortcutContext); |
501 | |
502 | window.show(); |
503 | QVERIFY(QTest::qWaitForWindowExposed(&window)); |
504 | |
505 | QDialog dialog(&window); |
506 | QFETCH(Qt::WindowModality, windowModality); |
507 | dialog.setWindowModality(windowModality); |
508 | |
509 | dialog.show(); |
510 | QVERIFY(QTest::qWaitForWindowExposed(&dialog)); |
511 | |
512 | QApplication::setActiveWindow(&window); |
513 | QVERIFY(QTest::qWaitForWindowActive(&window)); |
514 | |
515 | QSignalSpy spy(&action, &QAction::triggered); |
516 | QTest::keyPress(widget: &window, key: Qt::Key_1); |
517 | QCOMPARE(spy.count(), 0); |
518 | } |
519 | |
520 | class ShortcutOverrideWidget : public QWidget |
521 | { |
522 | public: |
523 | using QWidget::QWidget; |
524 | int shortcutOverrideCount = 0; |
525 | protected: |
526 | bool event(QEvent *e) override |
527 | { |
528 | if (e->type() == QEvent::ShortcutOverride) |
529 | ++shortcutOverrideCount; |
530 | return QWidget::event(event: e); |
531 | } |
532 | }; |
533 | |
534 | // Test that a key press event sent with sendEvent() still gets handled as a possible |
535 | // ShortcutOverride event first before passing it on as a normal KeyEvent. |
536 | void tst_QAction::shortcutFromKeyEvent() |
537 | { |
538 | if (QGuiApplication::platformName().startsWith(s: QLatin1String("wayland" ), cs: Qt::CaseInsensitive)) |
539 | QSKIP("Wayland: This fails. Figure out why." ); |
540 | |
541 | ShortcutOverrideWidget testWidget; |
542 | QAction action; |
543 | action.setShortcut(Qt::Key_1); |
544 | testWidget.addAction(action: &action); |
545 | testWidget.show(); |
546 | QSignalSpy spy(&action, &QAction::triggered); |
547 | QVERIFY(spy.isValid()); |
548 | QVERIFY(QTest::qWaitForWindowActive(&testWidget)); |
549 | QCOMPARE(testWidget.shortcutOverrideCount, 0); |
550 | |
551 | // Don't use the QTest::keyPress approach as this will take the |
552 | // shortcut route for us |
553 | QKeyEvent e(QEvent::KeyPress, Qt::Key_1, Qt::NoModifier); |
554 | QApplication::sendEvent(receiver: &testWidget, event: &e); |
555 | QCOMPARE(spy.count(), 1); |
556 | QCOMPARE(testWidget.shortcutOverrideCount, 1); |
557 | } |
558 | |
559 | QTEST_MAIN(tst_QAction) |
560 | #include "tst_qaction.moc" |
561 | |