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 | |
34 | #include <qapplication.h> |
35 | #include <qpainter.h> |
36 | #include <qstyleoption.h> |
37 | #include <qkeysequence.h> |
38 | #include <qevent.h> |
39 | #include <qgridlayout.h> |
40 | #include <qabstractbutton.h> |
41 | |
42 | #include <private/qguiapplication_p.h> |
43 | #include <qpa/qplatformintegration.h> |
44 | |
45 | class tst_QAbstractButton : public QObject |
46 | { |
47 | Q_OBJECT |
48 | |
49 | private slots: |
50 | void initTestCase(); |
51 | void cleanupTestCase(); |
52 | void init(); |
53 | |
54 | void setAutoRepeat_data(); |
55 | void setAutoRepeat(); |
56 | |
57 | void pressed(); |
58 | void released(); |
59 | void setText(); |
60 | void setIcon(); |
61 | |
62 | void setShortcut(); |
63 | |
64 | void animateClick(); |
65 | |
66 | void isCheckable(); |
67 | void setDown(); |
68 | void isChecked(); |
69 | void toggled(); |
70 | void setEnabled(); |
71 | void shortcutEvents(); |
72 | void stopRepeatTimer(); |
73 | |
74 | void mouseReleased(); // QTBUG-53244 |
75 | #ifdef QT_KEYPAD_NAVIGATION |
76 | void keyNavigation(); |
77 | #endif |
78 | |
79 | protected slots: |
80 | void onClicked(); |
81 | void onToggled( bool on ); |
82 | void onPressed(); |
83 | void onReleased(); |
84 | void resetValues(); |
85 | |
86 | private: |
87 | uint click_count; |
88 | uint toggle_count; |
89 | uint press_count; |
90 | uint release_count; |
91 | |
92 | QAbstractButton *testWidget; |
93 | }; |
94 | |
95 | // QAbstractButton is an abstract class in 4.0 |
96 | class MyButton : public QAbstractButton |
97 | { |
98 | public: |
99 | MyButton(QWidget *p = 0) : QAbstractButton(p) {} |
100 | void paintEvent(QPaintEvent *) |
101 | { |
102 | QPainter p(this); |
103 | QRect r = rect(); |
104 | p.fillRect(r, c: isDown() ? Qt::black : (isChecked() ? Qt::lightGray : Qt::white)); |
105 | p.setPen(isDown() ? Qt::white : Qt::black); |
106 | p.drawRect(r); |
107 | p.drawText(r, flags: Qt::AlignCenter | Qt::TextShowMnemonic, text: text()); |
108 | if (hasFocus()) { |
109 | r.adjust(dx1: 2, dy1: 2, dx2: -2, dy2: -2); |
110 | QStyleOptionFocusRect opt; |
111 | opt.rect = r; |
112 | opt.palette = palette(); |
113 | opt.state = QStyle::State_None; |
114 | style()->drawPrimitive(pe: QStyle::PE_FrameFocusRect, opt: &opt, p: &p, w: this); |
115 | #ifdef Q_OS_MAC |
116 | p.setPen(Qt::red); |
117 | p.drawRect(r); |
118 | #endif |
119 | } |
120 | } |
121 | QSize sizeHint() const |
122 | { |
123 | QSize sh(8, 8); |
124 | if (!text().isEmpty()) |
125 | sh += fontMetrics().boundingRect(text: text()).size(); |
126 | return sh; |
127 | } |
128 | |
129 | void resetTimerEvents() { timerEvents = 0; } |
130 | int timerEventCount() const { return timerEvents; } |
131 | |
132 | private: |
133 | |
134 | int timerEvents; |
135 | |
136 | void timerEvent(QTimerEvent *event) |
137 | { |
138 | ++timerEvents; |
139 | QAbstractButton::timerEvent(e: event); |
140 | } |
141 | }; |
142 | |
143 | void tst_QAbstractButton::initTestCase() |
144 | { |
145 | testWidget = new MyButton(0); |
146 | testWidget->setObjectName("testObject" ); |
147 | testWidget->resize( w: 200, h: 200 ); |
148 | testWidget->show(); |
149 | |
150 | connect( sender: testWidget, SIGNAL(clicked()), receiver: this, SLOT(onClicked()) ); |
151 | connect( sender: testWidget, SIGNAL(pressed()), receiver: this, SLOT(onPressed()) ); |
152 | connect( sender: testWidget, SIGNAL(released()), receiver: this, SLOT(onReleased()) ); |
153 | connect( sender: testWidget, SIGNAL(toggled(bool)), receiver: this, SLOT(onToggled(bool)) ); |
154 | } |
155 | |
156 | void tst_QAbstractButton::cleanupTestCase() |
157 | { |
158 | delete testWidget; |
159 | } |
160 | |
161 | void tst_QAbstractButton::init() |
162 | { |
163 | testWidget->setText("Test" ); |
164 | testWidget->setEnabled( true ); |
165 | testWidget->setDown( false ); |
166 | testWidget->setAutoRepeat( false ); |
167 | QKeySequence seq; |
168 | testWidget->setShortcut( seq ); |
169 | |
170 | toggle_count = 0; |
171 | press_count = 0; |
172 | release_count = 0; |
173 | click_count = 0; |
174 | } |
175 | |
176 | void tst_QAbstractButton::resetValues() |
177 | { |
178 | toggle_count = 0; |
179 | press_count = 0; |
180 | release_count = 0; |
181 | click_count = 0; |
182 | } |
183 | |
184 | void tst_QAbstractButton::onClicked() |
185 | { |
186 | click_count++; |
187 | } |
188 | |
189 | void tst_QAbstractButton::onToggled( bool /*on*/ ) |
190 | { |
191 | toggle_count++; |
192 | } |
193 | |
194 | void tst_QAbstractButton::onPressed() |
195 | { |
196 | press_count++; |
197 | } |
198 | |
199 | void tst_QAbstractButton::onReleased() |
200 | { |
201 | release_count++; |
202 | } |
203 | |
204 | void tst_QAbstractButton::setAutoRepeat_data() |
205 | { |
206 | QTest::addColumn<int>(name: "mode" ); |
207 | QTest::newRow(dataTag: "mode 0" ) << 0; |
208 | QTest::newRow(dataTag: "mode 1" ) << 1; |
209 | QTest::newRow(dataTag: "mode 2" ) << 2; |
210 | QTest::newRow(dataTag: "mode 3" ) << 3; |
211 | QTest::newRow(dataTag: "mode 4" ) << 4; |
212 | QTest::newRow(dataTag: "mode 5" ) << 5; |
213 | QTest::newRow(dataTag: "mode 6" ) << 6; |
214 | } |
215 | |
216 | #define REPEAT_DELAY 1000 |
217 | |
218 | int test_count = 0; |
219 | int last_mode = 0; |
220 | |
221 | void tst_QAbstractButton::setAutoRepeat() |
222 | { |
223 | QFETCH( int, mode ); |
224 | |
225 | //FIXME: temp code to check that the test fails consistenly |
226 | //retest( 3 ); |
227 | |
228 | switch (mode) |
229 | { |
230 | case 0: |
231 | QVERIFY( !testWidget->isCheckable() ); |
232 | break; |
233 | case 1: |
234 | // check if we can toggle the mode |
235 | testWidget->setAutoRepeat( true ); |
236 | QVERIFY( testWidget->autoRepeat() ); |
237 | |
238 | testWidget->setAutoRepeat( false ); |
239 | QVERIFY( !testWidget->autoRepeat() ); |
240 | break; |
241 | case 2: |
242 | // check that the button is down if we press space and not in autorepeat |
243 | testWidget->setDown( false ); |
244 | testWidget->setAutoRepeat( false ); |
245 | QTest::keyPress( widget: testWidget, key: Qt::Key_Space ); |
246 | |
247 | QTest::qWait( REPEAT_DELAY ); |
248 | |
249 | QVERIFY( release_count == 0 ); |
250 | QVERIFY( testWidget->isDown() ); |
251 | QVERIFY( toggle_count == 0 ); |
252 | QVERIFY( press_count == 1 ); |
253 | QVERIFY( click_count == 0 ); |
254 | |
255 | QTest::keyRelease( widget: testWidget, key: Qt::Key_Space ); |
256 | QVERIFY( click_count == 1 ); |
257 | QVERIFY( release_count == 1 ); |
258 | break; |
259 | case 3: |
260 | // check that the button is down if we press space while in autorepeat |
261 | testWidget->setDown(false); |
262 | testWidget->setAutoRepeat(true); |
263 | QTest::keyPress(widget: testWidget, key: Qt::Key_Space); |
264 | QTest::qWait(REPEAT_DELAY); |
265 | QVERIFY(testWidget->isDown()); |
266 | QTest::keyRelease(widget: testWidget, key: Qt::Key_Space); |
267 | QCOMPARE(release_count, press_count); |
268 | QCOMPARE(toggle_count, uint(0)); |
269 | QCOMPARE(press_count, click_count); |
270 | QVERIFY(click_count > 1); |
271 | break; |
272 | case 4: |
273 | // check that pressing ENTER has no effect when autorepeat is false |
274 | testWidget->setDown( false ); |
275 | testWidget->setAutoRepeat( false ); |
276 | QTest::keyPress( widget: testWidget, key: Qt::Key_Enter ); |
277 | |
278 | QTest::qWait( REPEAT_DELAY ); |
279 | |
280 | QVERIFY( !testWidget->isDown() ); |
281 | QVERIFY( toggle_count == 0 ); |
282 | QVERIFY( press_count == 0 ); |
283 | QVERIFY( release_count == 0 ); |
284 | QVERIFY( click_count == 0 ); |
285 | QTest::keyRelease( widget: testWidget, key: Qt::Key_Enter ); |
286 | |
287 | QVERIFY( click_count == 0 ); |
288 | break; |
289 | case 5: |
290 | // check that pressing ENTER has no effect when autorepeat is true |
291 | testWidget->setDown( false ); |
292 | testWidget->setAutoRepeat( true ); |
293 | QTest::keyPress( widget: testWidget, key: Qt::Key_Enter ); |
294 | |
295 | QTest::qWait( REPEAT_DELAY ); |
296 | |
297 | QVERIFY( !testWidget->isDown() ); |
298 | QVERIFY( toggle_count == 0 ); |
299 | QVERIFY( press_count == 0 ); |
300 | QVERIFY( release_count == 0 ); |
301 | QVERIFY( click_count == 0 ); |
302 | |
303 | QTest::keyRelease( widget: testWidget, key: Qt::Key_Enter ); |
304 | |
305 | QVERIFY( click_count == 0 ); |
306 | break; |
307 | case 6: |
308 | // verify autorepeat is off by default. |
309 | MyButton tmp( 0); |
310 | tmp.setObjectName("tmp" ); |
311 | QVERIFY( !tmp.autoRepeat() ); |
312 | break; |
313 | } |
314 | } |
315 | |
316 | void tst_QAbstractButton::pressed() |
317 | { |
318 | // pressed/released signals expected for a QAbstractButton |
319 | QTest::keyPress( widget: testWidget, key: ' ' ); |
320 | QCOMPARE( press_count, (uint)1 ); |
321 | } |
322 | |
323 | void tst_QAbstractButton::released() |
324 | { |
325 | // pressed/released signals expected for a QAbstractButton |
326 | QTest::keyPress( widget: testWidget, key: ' ' ); |
327 | QTest::keyRelease( widget: testWidget, key: ' ' ); |
328 | QCOMPARE( release_count, (uint)1 ); |
329 | } |
330 | |
331 | void tst_QAbstractButton::setText() |
332 | { |
333 | testWidget->setText("" ); |
334 | QCOMPARE( testWidget->text(), QString("" ) ); |
335 | testWidget->setText("simple" ); |
336 | QCOMPARE( testWidget->text(), QString("simple" ) ); |
337 | testWidget->setText("&ersand" ); |
338 | QCOMPARE( testWidget->text(), QString("&ersand" ) ); |
339 | #ifndef Q_OS_MAC // no mneonics on Mac. |
340 | QCOMPARE( testWidget->shortcut(), QKeySequence("ALT+A" )); |
341 | #endif |
342 | testWidget->setText("te&st" ); |
343 | QCOMPARE( testWidget->text(), QString("te&st" ) ); |
344 | #ifndef Q_OS_MAC // no mneonics on Mac. |
345 | QCOMPARE( testWidget->shortcut(), QKeySequence("ALT+S" )); |
346 | #endif |
347 | testWidget->setText("foo" ); |
348 | QCOMPARE( testWidget->text(), QString("foo" ) ); |
349 | #ifndef Q_OS_MAC // no mneonics on Mac. |
350 | QCOMPARE( testWidget->shortcut(), QKeySequence()); |
351 | #endif |
352 | } |
353 | |
354 | void tst_QAbstractButton::setIcon() |
355 | { |
356 | const char *test1_xpm[] = { |
357 | "12 8 2 1" , |
358 | ". c None" , |
359 | "c c #ff0000" , |
360 | ".........ccc" , |
361 | "........ccc." , |
362 | ".......ccc.." , |
363 | "ccc...ccc..." , |
364 | ".ccc.ccc...." , |
365 | "..ccccc....." , |
366 | "...ccc......" , |
367 | "....c......." , |
368 | }; |
369 | |
370 | QPixmap p(test1_xpm); |
371 | testWidget->setIcon( p ); |
372 | QCOMPARE( testWidget->icon().pixmap(12, 8), p ); |
373 | |
374 | // Test for #14793 |
375 | |
376 | const char *test2_xpm[] = { |
377 | "12 8 2 1" , |
378 | ". c None" , |
379 | "c c #ff0000" , |
380 | "ccc......ccc" , |
381 | ".ccc....ccc." , |
382 | "..ccc..ccc.." , |
383 | "....cc.cc..." , |
384 | ".....ccc...." , |
385 | "....cc.cc..." , |
386 | "...ccc.ccc.." , |
387 | "..ccc...ccc." , |
388 | }; |
389 | |
390 | int currentHeight = testWidget->height(); |
391 | int currentWidth = testWidget->width(); |
392 | |
393 | QPixmap p2( test2_xpm ); |
394 | for ( int a = 0; a<5; a++ ) |
395 | testWidget->setIcon( p2 ); |
396 | |
397 | QCOMPARE( testWidget->icon().pixmap(12, 8), p2 ); |
398 | |
399 | QCOMPARE( testWidget->height(), currentHeight ); |
400 | QCOMPARE( testWidget->width(), currentWidth ); |
401 | } |
402 | |
403 | void tst_QAbstractButton::setEnabled() |
404 | { |
405 | testWidget->setEnabled( false ); |
406 | QVERIFY( !testWidget->isEnabled() ); |
407 | // QTEST( testWidget, "disabled" ); |
408 | |
409 | testWidget->setEnabled( true ); |
410 | QVERIFY( testWidget->isEnabled() ); |
411 | // QTEST( testWidget, "enabled" ); |
412 | } |
413 | |
414 | void tst_QAbstractButton::isCheckable() |
415 | { |
416 | QVERIFY( !testWidget->isCheckable() ); |
417 | } |
418 | |
419 | void tst_QAbstractButton::setDown() |
420 | { |
421 | testWidget->setDown( false ); |
422 | QVERIFY( !testWidget->isDown() ); |
423 | |
424 | testWidget->setDown( true ); |
425 | QTest::qWait(ms: 300); |
426 | QVERIFY( testWidget->isDown() ); |
427 | |
428 | testWidget->setDown( true ); |
429 | |
430 | // add some debugging stuff |
431 | QWidget *grab = QWidget::keyboardGrabber(); |
432 | if (grab != 0 && grab != testWidget) |
433 | qDebug( msg: "testWidget != keyboardGrabber" ); |
434 | grab = qApp->focusWidget(); |
435 | if (grab != 0 && grab != testWidget) |
436 | qDebug( msg: "testWidget != focusWidget" ); |
437 | |
438 | QTest::keyClick( widget: testWidget, key: Qt::Key_Escape ); |
439 | QVERIFY( !testWidget->isDown() ); |
440 | } |
441 | |
442 | void tst_QAbstractButton::isChecked() |
443 | { |
444 | testWidget->setDown( false ); |
445 | QVERIFY( !testWidget->isChecked() ); |
446 | |
447 | testWidget->setDown( true ); |
448 | QVERIFY( !testWidget->isChecked() ); |
449 | |
450 | testWidget->setDown( false ); |
451 | testWidget->toggle(); |
452 | QVERIFY( testWidget->isChecked() == testWidget->isCheckable() ); |
453 | } |
454 | |
455 | void tst_QAbstractButton::toggled() |
456 | { |
457 | testWidget->toggle(); |
458 | QVERIFY( toggle_count == 0 ); |
459 | |
460 | QTest::mousePress( widget: testWidget, button: Qt::LeftButton ); |
461 | QVERIFY( toggle_count == 0 ); |
462 | QVERIFY( click_count == 0 ); |
463 | |
464 | QTest::mouseRelease( widget: testWidget, button: Qt::LeftButton ); |
465 | QVERIFY( click_count == 1 ); |
466 | |
467 | testWidget->setCheckable(true); |
468 | testWidget->toggle(); |
469 | testWidget->toggle(); |
470 | QCOMPARE(int(toggle_count), 2); |
471 | testWidget->setCheckable(false); |
472 | } |
473 | |
474 | void tst_QAbstractButton::setShortcut() |
475 | { |
476 | if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(cap: QPlatformIntegration::WindowActivation)) |
477 | QSKIP("Window activation is not supported" ); |
478 | |
479 | QKeySequence seq( Qt::Key_A ); |
480 | testWidget->setShortcut( seq ); |
481 | QApplication::setActiveWindow(testWidget); |
482 | testWidget->activateWindow(); |
483 | // must be active to get shortcuts |
484 | QVERIFY(QTest::qWaitForWindowActive(testWidget)); |
485 | |
486 | QTest::keyClick( widget: testWidget, key: 'A' ); |
487 | QTest::qWait(ms: 300); // Animate click takes time |
488 | QCOMPARE(click_count, (uint)1); |
489 | QCOMPARE(press_count, (uint)1); // Press is part of a click |
490 | QCOMPARE(release_count,(uint)1); // Release is part of a click |
491 | |
492 | QVERIFY( toggle_count == 0 ); |
493 | |
494 | // resetValues(); |
495 | // QTest::keyPress( testWidget, 'A' ); |
496 | // QTest::qWait(10000); |
497 | // QTest::keyRelease( testWidget, 'A' ); |
498 | // QCOMPARE(click_count, (uint)1); |
499 | // QCOMPARE(press_count, (uint)1); |
500 | // QCOMPARE(release_count,(uint)1); |
501 | |
502 | // qDebug() << click_count; |
503 | |
504 | } |
505 | |
506 | void tst_QAbstractButton::animateClick() |
507 | { |
508 | testWidget->animateClick(); |
509 | QVERIFY( testWidget->isDown() ); |
510 | qApp->processEvents(); |
511 | QVERIFY( testWidget->isDown() ); |
512 | QTRY_VERIFY( !testWidget->isDown() ); |
513 | } |
514 | |
515 | void tst_QAbstractButton::shortcutEvents() |
516 | { |
517 | MyButton button; |
518 | QSignalSpy pressedSpy(&button, SIGNAL(pressed())); |
519 | QSignalSpy releasedSpy(&button, SIGNAL(released())); |
520 | QSignalSpy clickedSpy(&button, SIGNAL(clicked(bool))); |
521 | |
522 | for (int i = 0; i < 4; ++i) { |
523 | QKeySequence sequence; |
524 | // Default shortcutId for QAbstractButton is 0, so the shortcut event will work. |
525 | QShortcutEvent event(sequence, /*shortcutId*/ 0); |
526 | QApplication::sendEvent(receiver: &button, event: &event); |
527 | if (i < 2) |
528 | QTest::qWait(ms: 500); |
529 | } |
530 | |
531 | QTest::qWait(ms: 1000); // ensure animate timer is expired |
532 | |
533 | QCOMPARE(pressedSpy.count(), 3); |
534 | QCOMPARE(releasedSpy.count(), 3); |
535 | QCOMPARE(clickedSpy.count(), 3); |
536 | } |
537 | |
538 | void tst_QAbstractButton::stopRepeatTimer() |
539 | { |
540 | MyButton button; |
541 | button.setAutoRepeat(true); |
542 | |
543 | // Mouse trigger case: |
544 | button.resetTimerEvents(); |
545 | QTest::mousePress(widget: &button, button: Qt::LeftButton); |
546 | QTest::qWait(ms: 1000); |
547 | QVERIFY(button.timerEventCount() > 0); |
548 | |
549 | QTest::mouseRelease(widget: &button, button: Qt::LeftButton); |
550 | button.resetTimerEvents(); |
551 | QTest::qWait(ms: 1000); |
552 | QCOMPARE(button.timerEventCount(), 0); |
553 | |
554 | // Key trigger case: |
555 | button.resetTimerEvents(); |
556 | QTest::keyPress(widget: &button, key: Qt::Key_Space); |
557 | QTest::qWait(ms: 1000); |
558 | QVERIFY(button.timerEventCount() > 0); |
559 | |
560 | QTest::keyRelease(widget: &button, key: Qt::Key_Space); |
561 | button.resetTimerEvents(); |
562 | QTest::qWait(ms: 1000); |
563 | QCOMPARE(button.timerEventCount(), 0); |
564 | } |
565 | |
566 | void tst_QAbstractButton::mouseReleased() // QTBUG-53244 |
567 | { |
568 | MyButton button(nullptr); |
569 | button.setObjectName("button" ); |
570 | button.setGeometry(ax: 0, ay: 0, aw: 20, ah: 20); |
571 | QSignalSpy spyPress(&button, &QAbstractButton::pressed); |
572 | QSignalSpy spyRelease(&button, &QAbstractButton::released); |
573 | |
574 | QTest::mousePress(widget: &button, button: Qt::LeftButton); |
575 | QCOMPARE(spyPress.count(), 1); |
576 | QCOMPARE(button.isDown(), true); |
577 | QCOMPARE(spyRelease.count(), 0); |
578 | |
579 | QTest::mouseClick(widget: &button, button: Qt::RightButton); |
580 | QCOMPARE(spyPress.count(), 1); |
581 | QCOMPARE(button.isDown(), true); |
582 | QCOMPARE(spyRelease.count(), 0); |
583 | |
584 | QPointF posOutOfWidget = QPointF(30, 30); |
585 | QMouseEvent me(QEvent::MouseMove, |
586 | posOutOfWidget, Qt::NoButton, |
587 | Qt::MouseButtons(Qt::LeftButton), |
588 | Qt::NoModifier); // mouse press and move |
589 | |
590 | qApp->sendEvent(receiver: &button, event: &me); |
591 | // should emit released signal once mouse is dragging out of boundary |
592 | QCOMPARE(spyPress.count(), 1); |
593 | QCOMPARE(button.isDown(), false); |
594 | QCOMPARE(spyRelease.count(), 1); |
595 | } |
596 | |
597 | #ifdef QT_KEYPAD_NAVIGATION |
598 | void tst_QAbstractButton::keyNavigation() |
599 | { |
600 | QApplication::setNavigationMode(Qt::NavigationModeKeypadDirectional); |
601 | |
602 | QWidget widget; |
603 | QGridLayout *layout = new QGridLayout(&widget); |
604 | QAbstractButton *buttons[3][3]; |
605 | for(int y = 0; y < 3; y++) { |
606 | for(int x = 0; x < 3; x++) { |
607 | buttons[y][x] = new MyButton(&widget); |
608 | buttons[y][x]->setFocusPolicy(Qt::StrongFocus); |
609 | layout->addWidget(buttons[y][x], y, x); |
610 | } |
611 | } |
612 | |
613 | widget.show(); |
614 | qApp->setActiveWindow(&widget); |
615 | widget.activateWindow(); |
616 | QVERIFY(QTest::qWaitForWindowActive(&widget)); |
617 | |
618 | buttons[1][1]->setFocus(); |
619 | QTest::qWait(400); |
620 | QVERIFY(buttons[1][1]->hasFocus()); |
621 | QTest::keyPress(buttons[1][1], Qt::Key_Up); |
622 | QTest::qWait(100); |
623 | QVERIFY(buttons[0][1]->hasFocus()); |
624 | QTest::keyPress(buttons[0][1], Qt::Key_Down); |
625 | QTest::qWait(100); |
626 | QVERIFY(buttons[1][1]->hasFocus()); |
627 | QTest::keyPress(buttons[1][1], Qt::Key_Left); |
628 | QTest::qWait(100); |
629 | QVERIFY(buttons[1][0]->hasFocus()); |
630 | QTest::keyPress(buttons[1][0], Qt::Key_Down); |
631 | QTest::qWait(100); |
632 | QVERIFY(buttons[2][0]->hasFocus()); |
633 | QTest::keyPress(buttons[2][0], Qt::Key_Right); |
634 | QTest::qWait(100); |
635 | QVERIFY(buttons[2][1]->hasFocus()); |
636 | QTest::keyPress(buttons[2][1], Qt::Key_Right); |
637 | QTest::qWait(100); |
638 | QVERIFY(buttons[2][2]->hasFocus()); |
639 | QTest::keyPress(buttons[2][2], Qt::Key_Up); |
640 | QTest::qWait(100); |
641 | QVERIFY(buttons[1][2]->hasFocus()); |
642 | QTest::keyPress(buttons[1][2], Qt::Key_Up); |
643 | QTest::qWait(100); |
644 | QVERIFY(buttons[0][2]->hasFocus()); |
645 | buttons[0][1]->hide(); |
646 | QTest::keyPress(buttons[0][2], Qt::Key_Left); |
647 | QTest::qWait(100); |
648 | QTest::keyPress(buttons[0][2], Qt::Key_Left); |
649 | QEXPECT_FAIL("" , "QTBUG-22286" ,Abort); |
650 | QVERIFY(buttons[0][0]->hasFocus()); |
651 | } |
652 | #endif |
653 | |
654 | QTEST_MAIN(tst_QAbstractButton) |
655 | #include "tst_qabstractbutton.moc" |
656 | |