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 | |
32 | |
33 | #include "qpushbutton.h" |
34 | #include <qapplication.h> |
35 | |
36 | #include <qpushbutton.h> |
37 | #include <qmenu.h> |
38 | #include <qtimer.h> |
39 | #include <QDialog> |
40 | #include <QGridLayout> |
41 | #include <QStyleFactory> |
42 | #include <QTabWidget> |
43 | |
44 | class tst_QPushButton : public QObject |
45 | { |
46 | Q_OBJECT |
47 | |
48 | private slots: |
49 | void initTestCase(); |
50 | void cleanupTestCase(); |
51 | void init(); |
52 | |
53 | void getSetCheck(); |
54 | void autoRepeat(); |
55 | void pressed(); |
56 | void setAccel(); |
57 | void isCheckable(); |
58 | void setDown(); |
59 | void popupCrash(); |
60 | void isChecked(); |
61 | void animateClick(); |
62 | void toggle(); |
63 | void clicked(); |
64 | void toggled(); |
65 | void defaultAndAutoDefault(); |
66 | void sizeHint_data(); |
67 | void sizeHint(); |
68 | void taskQTBUG_20191_shortcutWithKeypadModifer(); |
69 | void emitReleasedAfterChange(); |
70 | void hitButton(); |
71 | void iconOnlyStyleSheet(); |
72 | |
73 | protected slots: |
74 | void resetCounters(); |
75 | void onClicked(); |
76 | void onToggled( bool on ); |
77 | void onPressed(); |
78 | void onReleased(); |
79 | void helperSlotDelete(); |
80 | |
81 | private: |
82 | uint click_count; |
83 | uint toggle_count; |
84 | uint press_count; |
85 | uint release_count; |
86 | |
87 | QPushButton *testWidget; |
88 | }; |
89 | |
90 | // Testing get/set functions |
91 | void tst_QPushButton::getSetCheck() |
92 | { |
93 | QPushButton obj1; |
94 | // QMenu* QPushButton::menu() |
95 | // void QPushButton::setMenu(QMenu*) |
96 | QMenu *var1 = new QMenu; |
97 | obj1.setMenu(var1); |
98 | QCOMPARE(var1, obj1.menu()); |
99 | obj1.setMenu((QMenu *)0); |
100 | QCOMPARE((QMenu *)0, obj1.menu()); |
101 | delete var1; |
102 | } |
103 | |
104 | void tst_QPushButton::initTestCase() |
105 | { |
106 | // Create the test class |
107 | testWidget = new QPushButton( "&Start" , 0 ); |
108 | testWidget->setObjectName("testWidget" ); |
109 | testWidget->resize( w: 200, h: 200 ); |
110 | testWidget->show(); |
111 | |
112 | connect( sender: testWidget, SIGNAL(clicked()), receiver: this, SLOT(onClicked()) ); |
113 | connect( sender: testWidget, SIGNAL(pressed()), receiver: this, SLOT(onPressed()) ); |
114 | connect( sender: testWidget, SIGNAL(released()), receiver: this, SLOT(onReleased()) ); |
115 | connect( sender: testWidget, SIGNAL(toggled(bool)), receiver: this, SLOT(onToggled(bool)) ); |
116 | } |
117 | |
118 | void tst_QPushButton::cleanupTestCase() |
119 | { |
120 | delete testWidget; |
121 | testWidget = 0; |
122 | } |
123 | |
124 | void tst_QPushButton::init() |
125 | { |
126 | testWidget->setAutoRepeat( false ); |
127 | testWidget->setDown( false ); |
128 | testWidget->setText("Test" ); |
129 | testWidget->setEnabled( true ); |
130 | QKeySequence seq; |
131 | testWidget->setShortcut( seq ); |
132 | |
133 | resetCounters(); |
134 | } |
135 | |
136 | void tst_QPushButton::resetCounters() |
137 | { |
138 | toggle_count = 0; |
139 | press_count = 0; |
140 | release_count = 0; |
141 | click_count = 0; |
142 | } |
143 | |
144 | void tst_QPushButton::onClicked() |
145 | { |
146 | click_count++; |
147 | } |
148 | |
149 | void tst_QPushButton::onToggled( bool /*on*/ ) |
150 | { |
151 | toggle_count++; |
152 | } |
153 | |
154 | void tst_QPushButton::onPressed() |
155 | { |
156 | press_count++; |
157 | } |
158 | |
159 | void tst_QPushButton::onReleased() |
160 | { |
161 | release_count++; |
162 | } |
163 | |
164 | void tst_QPushButton::autoRepeat() |
165 | { |
166 | // If this changes, this test must be completely revised. |
167 | QVERIFY( !testWidget->isCheckable() ); |
168 | |
169 | // verify autorepeat is off by default. |
170 | QPushButton tmp( 0 ); |
171 | tmp.setObjectName("tmp" ); |
172 | QVERIFY( !tmp.autoRepeat() ); |
173 | |
174 | // check if we can toggle the mode |
175 | testWidget->setAutoRepeat( true ); |
176 | QVERIFY( testWidget->autoRepeat() ); |
177 | |
178 | testWidget->setAutoRepeat( false ); |
179 | QVERIFY( !testWidget->autoRepeat() ); |
180 | |
181 | resetCounters(); |
182 | |
183 | // check that the button is down if we press space and not in autorepeat |
184 | testWidget->setDown( false ); |
185 | testWidget->setAutoRepeat( false ); |
186 | QTest::keyPress( widget: testWidget, key: Qt::Key_Space ); |
187 | |
188 | QTRY_VERIFY( testWidget->isDown() ); |
189 | QVERIFY( toggle_count == 0 ); |
190 | QVERIFY( press_count == 1 ); |
191 | QVERIFY( release_count == 0 ); |
192 | QVERIFY( click_count == 0 ); |
193 | |
194 | QTest::keyRelease( widget: testWidget, key: Qt::Key_Space ); |
195 | resetCounters(); |
196 | |
197 | // check that the button is down if we press space while in autorepeat |
198 | // we can't actually confirm how many times it is fired, more than 1 is enough. |
199 | |
200 | testWidget->setDown( false ); |
201 | testWidget->setAutoRepeat( true ); |
202 | QTest::keyPress( widget: testWidget, key: Qt::Key_Space ); |
203 | QTRY_VERIFY(press_count > 3); |
204 | QVERIFY( testWidget->isDown() ); |
205 | QVERIFY( toggle_count == 0 ); |
206 | QTest::keyRelease( widget: testWidget, key: Qt::Key_Space ); |
207 | QCOMPARE(press_count, release_count); |
208 | QCOMPARE(release_count, click_count); |
209 | |
210 | // #### shouldn't I check here to see if multiple signals have been fired??? |
211 | |
212 | // check that pressing ENTER has no effect |
213 | resetCounters(); |
214 | testWidget->setDown( false ); |
215 | testWidget->setAutoRepeat( false ); |
216 | QTest::keyPress( widget: testWidget, key: Qt::Key_Enter ); |
217 | |
218 | QTest::qWait( ms: 300 ); |
219 | |
220 | QVERIFY( !testWidget->isDown() ); |
221 | QVERIFY( toggle_count == 0 ); |
222 | QVERIFY( press_count == 0 ); |
223 | QVERIFY( release_count == 0 ); |
224 | QVERIFY( click_count == 0 ); |
225 | QTest::keyRelease( widget: testWidget, key: Qt::Key_Enter ); |
226 | |
227 | // check that pressing ENTER has no effect |
228 | resetCounters(); |
229 | testWidget->setDown( false ); |
230 | testWidget->setAutoRepeat( true ); |
231 | QTest::keyClick( widget: testWidget, key: Qt::Key_Enter ); |
232 | QTest::qWait( ms: 300 ); |
233 | QVERIFY( !testWidget->isDown() ); |
234 | QVERIFY( toggle_count == 0 ); |
235 | QVERIFY( press_count == 0 ); |
236 | QVERIFY( release_count == 0 ); |
237 | QVERIFY( click_count == 0 ); |
238 | } |
239 | |
240 | void tst_QPushButton::pressed() |
241 | { |
242 | QTest::keyPress( widget: testWidget, key: ' ' ); |
243 | QCOMPARE( press_count, (uint)1 ); |
244 | QCOMPARE( release_count, (uint)0 ); |
245 | |
246 | QTest::keyRelease( widget: testWidget, key: ' ' ); |
247 | QCOMPARE( press_count, (uint)1 ); |
248 | QCOMPARE( release_count, (uint)1 ); |
249 | |
250 | QTest::keyPress( widget: testWidget,key: Qt::Key_Enter ); |
251 | QCOMPARE( press_count, (uint)1 ); |
252 | QCOMPARE( release_count, (uint)1 ); |
253 | |
254 | testWidget->setAutoDefault(true); |
255 | QTest::keyPress( widget: testWidget,key: Qt::Key_Enter ); |
256 | QCOMPARE( press_count, (uint)2 ); |
257 | QCOMPARE( release_count, (uint)2 ); |
258 | testWidget->setAutoDefault(false); |
259 | |
260 | } |
261 | |
262 | void tst_QPushButton::isCheckable() |
263 | { |
264 | QVERIFY( !testWidget->isCheckable() ); |
265 | } |
266 | |
267 | void tst_QPushButton::setDown() |
268 | { |
269 | testWidget->setDown( false ); |
270 | QVERIFY( !testWidget->isDown() ); |
271 | |
272 | testWidget->setDown( true ); |
273 | QVERIFY( testWidget->isDown() ); |
274 | |
275 | testWidget->setDown( true ); |
276 | QTest::keyClick( widget: testWidget, key: Qt::Key_Escape ); |
277 | QVERIFY( !testWidget->isDown() ); |
278 | } |
279 | |
280 | void tst_QPushButton::isChecked() |
281 | { |
282 | testWidget->setDown( false ); |
283 | QVERIFY( !testWidget->isChecked() ); |
284 | |
285 | testWidget->setDown( true ); |
286 | QVERIFY( !testWidget->isChecked() ); |
287 | |
288 | testWidget->setDown( false ); |
289 | testWidget->toggle(); |
290 | QVERIFY( testWidget->isChecked() == testWidget->isCheckable() ); |
291 | } |
292 | |
293 | void tst_QPushButton::toggle() |
294 | { |
295 | // the pushbutton shouldn't toggle the button. |
296 | testWidget->toggle(); |
297 | QVERIFY( testWidget->isChecked() == false ); |
298 | } |
299 | |
300 | void tst_QPushButton::toggled() |
301 | { |
302 | // the pushbutton shouldn't send a toggled signal when we call the toggle slot. |
303 | QVERIFY( !testWidget->isCheckable() ); |
304 | |
305 | testWidget->toggle(); |
306 | QVERIFY( toggle_count == 0 ); |
307 | |
308 | // do it again, just to be sure |
309 | resetCounters(); |
310 | testWidget->toggle(); |
311 | QVERIFY( toggle_count == 0 ); |
312 | |
313 | // finally check that we can toggle using the mouse |
314 | resetCounters(); |
315 | QTest::mousePress( widget: testWidget, button: Qt::LeftButton ); |
316 | QVERIFY( toggle_count == 0 ); |
317 | QVERIFY( click_count == 0 ); |
318 | |
319 | QTest::mouseRelease( widget: testWidget, button: Qt::LeftButton ); |
320 | QVERIFY( click_count == 1 ); |
321 | } |
322 | |
323 | /* |
324 | If we press an accelerator key we ONLY get a pressed signal and |
325 | NOT a released or clicked signal. |
326 | */ |
327 | |
328 | void tst_QPushButton::setAccel() |
329 | { |
330 | if (QGuiApplication::platformName().startsWith(s: QLatin1String("wayland" ), cs: Qt::CaseInsensitive)) |
331 | QSKIP("Wayland: This fails. Figure out why." ); |
332 | |
333 | testWidget->setText("&AccelTest" ); |
334 | QKeySequence seq( Qt::ALT + Qt::Key_A ); |
335 | testWidget->setShortcut( seq ); |
336 | |
337 | // The shortcut will not be activated unless the button is in a active |
338 | // window and has focus |
339 | QApplication::setActiveWindow(testWidget); |
340 | testWidget->setFocus(); |
341 | QVERIFY(QTest::qWaitForWindowActive(testWidget)); |
342 | QTest::keyClick( widget: testWidget, key: 'A', modifier: Qt::AltModifier ); |
343 | QTRY_VERIFY( click_count == 1 ); |
344 | QVERIFY( press_count == 1 ); |
345 | QVERIFY( release_count == 1 ); |
346 | QVERIFY( toggle_count == 0 ); |
347 | |
348 | // wait 200 ms because setAccel uses animateClick. |
349 | // if we don't wait this may screw up a next test. |
350 | QTest::qWait(ms: 200); |
351 | QTRY_VERIFY( !testWidget->isDown() ); |
352 | } |
353 | |
354 | void tst_QPushButton::animateClick() |
355 | { |
356 | QVERIFY( !testWidget->isDown() ); |
357 | testWidget->animateClick(); |
358 | QVERIFY( testWidget->isDown() ); |
359 | QTest::qWait( ms: 200 ); |
360 | QVERIFY( !testWidget->isDown() ); |
361 | |
362 | QVERIFY( click_count == 1 ); |
363 | QVERIFY( press_count == 1 ); |
364 | QVERIFY( release_count == 1 ); |
365 | QVERIFY( toggle_count == 0 ); |
366 | } |
367 | |
368 | void tst_QPushButton::clicked() |
369 | { |
370 | QTest::mousePress( widget: testWidget, button: Qt::LeftButton ); |
371 | QVERIFY( press_count == 1 ); |
372 | QVERIFY( release_count == 0 ); |
373 | |
374 | QTest::mouseRelease( widget: testWidget, button: Qt::LeftButton ); |
375 | QCOMPARE( press_count, (uint)1 ); |
376 | QCOMPARE( release_count, (uint)1 ); |
377 | |
378 | press_count = 0; |
379 | release_count = 0; |
380 | testWidget->setDown(false); |
381 | for (uint i=0; i<10; i++) |
382 | QTest::mouseClick( widget: testWidget, button: Qt::LeftButton ); |
383 | QCOMPARE( press_count, (uint)10 ); |
384 | QCOMPARE( release_count, (uint)10 ); |
385 | } |
386 | |
387 | QPushButton *pb = 0; |
388 | void tst_QPushButton::helperSlotDelete() |
389 | { |
390 | delete pb; |
391 | pb = 0; |
392 | } |
393 | |
394 | void tst_QPushButton::() |
395 | { |
396 | pb = new QPushButton("foo" ); |
397 | QMenu * = new QMenu("bar" , pb); |
398 | pb->setMenu(menu); |
399 | QTimer::singleShot(msec: 1000, receiver: this, SLOT(helperSlotDelete())); |
400 | pb->show(); |
401 | pb->click(); |
402 | } |
403 | |
404 | void tst_QPushButton::defaultAndAutoDefault() |
405 | { |
406 | { |
407 | // Adding buttons directly to QDialog |
408 | QDialog dialog; |
409 | |
410 | QPushButton button1(&dialog); |
411 | QVERIFY(button1.autoDefault()); |
412 | QVERIFY(!button1.isDefault()); |
413 | |
414 | QPushButton button2(&dialog); |
415 | QVERIFY(button2.autoDefault()); |
416 | QVERIFY(!button2.isDefault()); |
417 | |
418 | button1.setDefault(true); |
419 | QVERIFY(button1.autoDefault()); |
420 | QVERIFY(button1.isDefault()); |
421 | QVERIFY(button2.autoDefault()); |
422 | QVERIFY(!button2.isDefault()); |
423 | |
424 | dialog.show(); |
425 | QVERIFY(dialog.isVisible()); |
426 | |
427 | QObject::connect(sender: &button1, SIGNAL(clicked()), receiver: &dialog, SLOT(hide())); |
428 | QKeyEvent event(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier); |
429 | QApplication::sendEvent(receiver: &dialog, event: &event); |
430 | QVERIFY(!dialog.isVisible()); |
431 | } |
432 | |
433 | { |
434 | // Adding buttons to QDialog through a layout |
435 | QDialog dialog; |
436 | |
437 | QPushButton button3; |
438 | button3.setAutoDefault(false); |
439 | |
440 | QPushButton button1; |
441 | QVERIFY(!button1.autoDefault()); |
442 | QVERIFY(!button1.isDefault()); |
443 | |
444 | QPushButton button2; |
445 | QVERIFY(!button2.autoDefault()); |
446 | QVERIFY(!button2.isDefault()); |
447 | |
448 | button1.setDefault(true); |
449 | QVERIFY(!button1.autoDefault()); |
450 | QVERIFY(button1.isDefault()); |
451 | QVERIFY(!button2.autoDefault()); |
452 | QVERIFY(!button2.isDefault()); |
453 | |
454 | QGridLayout layout; |
455 | layout.addWidget(&button3, row: 0, column: 3); |
456 | layout.addWidget(&button2, row: 0, column: 2); |
457 | layout.addWidget(&button1, row: 0, column: 1); |
458 | dialog.setLayout(&layout); |
459 | button3.setFocus(); |
460 | QVERIFY(button1.autoDefault()); |
461 | QVERIFY(button1.isDefault()); |
462 | QVERIFY(button2.autoDefault()); |
463 | QVERIFY(!button2.isDefault()); |
464 | |
465 | dialog.show(); |
466 | QVERIFY(dialog.isVisible()); |
467 | |
468 | QObject::connect(sender: &button1, SIGNAL(clicked()), receiver: &dialog, SLOT(hide())); |
469 | QKeyEvent event(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier); |
470 | QApplication::sendEvent(receiver: &dialog, event: &event); |
471 | QVERIFY(!dialog.isVisible()); |
472 | } |
473 | |
474 | { |
475 | // autoDefault behavior. |
476 | QDialog dialog; |
477 | QPushButton button2(&dialog); |
478 | QPushButton button1(&dialog); |
479 | dialog.show(); |
480 | QVERIFY(dialog.isVisible()); |
481 | |
482 | // No default button is set, and button2 is the first autoDefault button |
483 | // that is next in the tab order |
484 | QObject::connect(sender: &button2, SIGNAL(clicked()), receiver: &dialog, SLOT(hide())); |
485 | QKeyEvent event(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier); |
486 | QApplication::sendEvent(receiver: &dialog, event: &event); |
487 | QVERIFY(!dialog.isVisible()); |
488 | |
489 | // Reparenting |
490 | QVERIFY(button2.autoDefault()); |
491 | button2.setParent(0); |
492 | QVERIFY(!button2.autoDefault()); |
493 | button2.setAutoDefault(false); |
494 | button2.setParent(&dialog); |
495 | QVERIFY(!button2.autoDefault()); |
496 | |
497 | button1.setAutoDefault(true); |
498 | button1.setParent(0); |
499 | QVERIFY(button1.autoDefault()); |
500 | } |
501 | } |
502 | |
503 | void tst_QPushButton::sizeHint_data() |
504 | { |
505 | QTest::addColumn<QString>(name: "stylename" ); |
506 | #if !defined(QT_NO_STYLE_WINDOWS) |
507 | QTest::newRow(dataTag: "windows" ) << QString::fromLatin1(str: "windows" ); |
508 | #endif |
509 | #if defined(Q_OS_MAC) && !defined(QT_NO_STYLE_MAC) |
510 | QTest::newRow("macintosh" ) << QString::fromLatin1("macintosh" ); |
511 | #endif |
512 | #if !defined(QT_NO_STYLE_FUSION) |
513 | QTest::newRow(dataTag: "fusion" ) << QString::fromLatin1(str: "fusion" ); |
514 | #endif |
515 | #if defined(Q_OS_WIN) && !defined(QT_NO_STYLE_WINDOWSVISTA) && !defined(Q_OS_WINRT) |
516 | QTest::newRow("windowsvista" ) << QString::fromLatin1("windowsvista" ); |
517 | #endif |
518 | } |
519 | |
520 | void tst_QPushButton::sizeHint() |
521 | { |
522 | QFETCH(QString, stylename); |
523 | |
524 | QStyle *style = QStyleFactory::create(stylename); |
525 | if (!style) |
526 | QFAIL(qPrintable(QString::fromLatin1("Cannot create style: %1" ).arg(stylename))); |
527 | QApplication::setStyle(style); |
528 | |
529 | // Test 1 |
530 | { |
531 | QPushButton *button = new QPushButton("123" ); |
532 | QSize initSizeHint = button->sizeHint(); |
533 | |
534 | QDialog *dialog = new QDialog; |
535 | QWidget *widget = new QWidget(dialog); |
536 | button->setParent(widget); |
537 | button->sizeHint(); |
538 | |
539 | widget->setParent(0); |
540 | delete dialog; |
541 | button->setDefault(false); |
542 | QCOMPARE(button->sizeHint(), initSizeHint); |
543 | delete button; |
544 | } |
545 | |
546 | // Test 2 |
547 | { |
548 | QWidget *tab1 = new QWidget; |
549 | QHBoxLayout *layout1 = new QHBoxLayout(tab1); |
550 | QPushButton *button1_1 = new QPushButton("123" ); |
551 | QPushButton *button1_2 = new QPushButton("123" ); |
552 | layout1->addWidget(button1_1); |
553 | layout1->addWidget(button1_2); |
554 | |
555 | QWidget *tab2 = new QWidget; |
556 | QHBoxLayout *layout2 = new QHBoxLayout(tab2); |
557 | QPushButton *button2_1 = new QPushButton("123" ); |
558 | QPushButton *button2_2 = new QPushButton("123" ); |
559 | layout2->addWidget(button2_1); |
560 | layout2->addWidget(button2_2); |
561 | |
562 | QDialog *dialog = new QDialog; |
563 | QTabWidget *tabWidget = new QTabWidget; |
564 | tabWidget->addTab(widget: tab1, "1" ); |
565 | tabWidget->addTab(widget: tab2, "2" ); |
566 | QVBoxLayout *mainLayout = new QVBoxLayout(dialog); |
567 | mainLayout->addWidget(tabWidget); |
568 | dialog->showNormal(); |
569 | tabWidget->setCurrentWidget(tab2); |
570 | tabWidget->setCurrentWidget(tab1); |
571 | |
572 | QTRY_COMPARE(button1_2->size(), button2_2->size()); |
573 | } |
574 | } |
575 | |
576 | void tst_QPushButton::taskQTBUG_20191_shortcutWithKeypadModifer() |
577 | { |
578 | // setup a dialog with two buttons |
579 | QPushButton *button1 = new QPushButton("5" ); |
580 | QPushButton *button2 = new QPushButton("5 + KeypadModifier" ); |
581 | QVBoxLayout *layout = new QVBoxLayout(); |
582 | layout->addWidget(button1); |
583 | layout->addWidget(button2); |
584 | QDialog dialog; |
585 | dialog.setLayout(layout); |
586 | dialog.show(); |
587 | QVERIFY(QTest::qWaitForWindowExposed(&dialog)); |
588 | QApplication::setActiveWindow(&dialog); |
589 | |
590 | // add shortcut '5' to button1 and test with keyboard and keypad '5' keys |
591 | QSignalSpy spy1(button1, SIGNAL(clicked())); |
592 | button1->setShortcut(Qt::Key_5); |
593 | QTest::keyClick(widget: &dialog, key: Qt::Key_5); |
594 | QTest::qWait(ms: 300); |
595 | QTest::keyClick(widget: &dialog, key: Qt::Key_5, modifier: Qt::KeypadModifier); |
596 | QTest::qWait(ms: 300); |
597 | QCOMPARE(spy1.count(), 2); |
598 | |
599 | // add shortcut 'keypad 5' to button2 |
600 | spy1.clear(); |
601 | QSignalSpy spy2(button2, SIGNAL(clicked())); |
602 | button2->setShortcut(Qt::Key_5 + Qt::KeypadModifier); |
603 | QTest::keyClick(widget: &dialog, key: Qt::Key_5); |
604 | QTest::qWait(ms: 300); |
605 | QTest::keyClick(widget: &dialog, key: Qt::Key_5, modifier: Qt::KeypadModifier); |
606 | QTest::qWait(ms: 300); |
607 | QCOMPARE(spy1.count(), 1); |
608 | QCOMPARE(spy2.count(), 1); |
609 | |
610 | // remove shortcut from button1 |
611 | spy1.clear(); |
612 | spy2.clear(); |
613 | button1->setShortcut(QKeySequence()); |
614 | QTest::keyClick(widget: &dialog, key: Qt::Key_5); |
615 | QTest::qWait(ms: 300); |
616 | QTest::keyClick(widget: &dialog, key: Qt::Key_5, modifier: Qt::KeypadModifier); |
617 | QTest::qWait(ms: 300); |
618 | QCOMPARE(spy1.count(), 0); |
619 | QCOMPARE(spy2.count(), 1); |
620 | } |
621 | |
622 | void tst_QPushButton::emitReleasedAfterChange() |
623 | { |
624 | QPushButton *button1 = new QPushButton("A" ); |
625 | QPushButton *button2 = new QPushButton("B" ); |
626 | QVBoxLayout *layout = new QVBoxLayout(); |
627 | layout->addWidget(button1); |
628 | layout->addWidget(button2); |
629 | QDialog dialog; |
630 | dialog.setLayout(layout); |
631 | dialog.show(); |
632 | QVERIFY(QTest::qWaitForWindowExposed(&dialog)); |
633 | QApplication::setActiveWindow(&dialog); |
634 | button1->setFocus(); |
635 | |
636 | QSignalSpy spy(button1, SIGNAL(released())); |
637 | QTest::mousePress(widget: button1, button: Qt::LeftButton); |
638 | QVERIFY(button1->isDown()); |
639 | QTest::keyClick(widget: &dialog, key: Qt::Key_Tab); |
640 | QVERIFY(!button1->isDown()); |
641 | QCOMPARE(spy.count(), 1); |
642 | spy.clear(); |
643 | |
644 | QCOMPARE(spy.count(), 0); |
645 | button1->setFocus(); |
646 | QTest::mousePress(widget: button1, button: Qt::LeftButton); |
647 | QVERIFY(button1->isDown()); |
648 | button1->setEnabled(false); |
649 | QVERIFY(!button1->isDown()); |
650 | QCOMPARE(spy.count(), 1); |
651 | } |
652 | |
653 | /* |
654 | Test that QPushButton::hitButton returns true for points that |
655 | are certainly inside the bevel, also when a style sheet is set. |
656 | */ |
657 | void tst_QPushButton::hitButton() |
658 | { |
659 | class PushButton : public QPushButton |
660 | { |
661 | public: |
662 | PushButton(const QString &text = {}) |
663 | : QPushButton(text) |
664 | {} |
665 | |
666 | bool hitButton(const QPoint &point) const override |
667 | { |
668 | return QPushButton::hitButton(pos: point); |
669 | } |
670 | }; |
671 | |
672 | QDialog dialog; |
673 | QVBoxLayout *layout = new QVBoxLayout; |
674 | PushButton *button1 = new PushButton("Ok" ); |
675 | PushButton *button2 = new PushButton("Cancel" ); |
676 | button2->setStyleSheet("QPushButton {" |
677 | "padding: 5px;" |
678 | "margin: 5px;" |
679 | "border-radius: 4px;" |
680 | "border: 1px solid black; }" |
681 | ); |
682 | |
683 | layout->addWidget(button1); |
684 | layout->addWidget(button2); |
685 | |
686 | dialog.setLayout(layout); |
687 | dialog.show(); |
688 | QVERIFY(QTest::qWaitForWindowExposed(&dialog)); |
689 | |
690 | const QPoint button1Center = button1->rect().center(); |
691 | QVERIFY(button1->hitButton(button1Center)); |
692 | |
693 | const QPoint button2Center = button2->rect().center(); |
694 | QVERIFY(button2->hitButton(button2Center)); |
695 | QVERIFY(button2->hitButton(QPoint(6, 6))); |
696 | QVERIFY(!button2->hitButton(QPoint(2, 2))); |
697 | } |
698 | |
699 | /* |
700 | Test that a style sheet with only icon doesn't crash. |
701 | QTBUG-91735 |
702 | */ |
703 | void tst_QPushButton::iconOnlyStyleSheet() |
704 | { |
705 | QIcon icon(":/qt-project.org/styles/commonstyle/images/dvd-32.png" ); |
706 | QVERIFY(!icon.isNull()); |
707 | QPushButton pb; |
708 | pb.setStyleSheet("QPushButton {" |
709 | "icon: url(:/qt-project.org/styles/commonstyle/images/dvd-32.png);" |
710 | "border: red;" |
711 | "}" ); |
712 | pb.show(); |
713 | QVERIFY(QTest::qWaitForWindowExposed(&pb)); |
714 | } |
715 | |
716 | QTEST_MAIN(tst_QPushButton) |
717 | #include "tst_qpushbutton.moc" |
718 | |