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 <QLineEdit> |
32 | #include <QStyle> |
33 | #include <QStyleOptionGroupBox> |
34 | #include <QVBoxLayout> |
35 | #include <QRadioButton> |
36 | #include <QDialog> |
37 | |
38 | #include "qgroupbox.h" |
39 | |
40 | class tst_QGroupBox : public QObject |
41 | { |
42 | Q_OBJECT |
43 | |
44 | public: |
45 | tst_QGroupBox(); |
46 | virtual ~tst_QGroupBox(); |
47 | |
48 | public slots: |
49 | void toggledHelperSlot(bool on); |
50 | void init(); |
51 | void clickTimestampSlot(); |
52 | void toggleTimestampSlot(); |
53 | |
54 | private slots: |
55 | void setTitle_data(); |
56 | void setTitle(); |
57 | void setCheckable_data(); |
58 | void setCheckable(); |
59 | void setChecked_data(); |
60 | void setChecked(); |
61 | void enabledPropagation(); |
62 | void enabledChildPropagation(); |
63 | void sizeHint(); |
64 | void toggled(); |
65 | void clicked_data(); |
66 | void clicked(); |
67 | void toggledVsClicked(); |
68 | void childrenAreDisabled(); |
69 | void propagateFocus(); |
70 | void task_QTBUG_19170_ignoreMouseReleaseEvent(); |
71 | void task_QTBUG_15519_propagateMouseEvents(); |
72 | |
73 | private: |
74 | bool checked; |
75 | qint64 timeStamp; |
76 | qint64 clickTimeStamp; |
77 | qint64 toggleTimeStamp; |
78 | |
79 | static void sendMouseMoveEvent(QWidget *widget, const QPoint &localPos); |
80 | }; |
81 | |
82 | tst_QGroupBox::tst_QGroupBox() |
83 | { |
84 | checked = true; |
85 | } |
86 | |
87 | tst_QGroupBox::~tst_QGroupBox() |
88 | { |
89 | |
90 | } |
91 | |
92 | void tst_QGroupBox::init() |
93 | { |
94 | checked = true; |
95 | } |
96 | |
97 | void tst_QGroupBox::setTitle_data() |
98 | { |
99 | QTest::addColumn<QString>(name: "title" ); |
100 | QTest::addColumn<QString>(name: "expectedTitle" ); |
101 | QTest::newRow( dataTag: "empty_title" ) << QString("" ) << QString("" ); |
102 | QTest::newRow( dataTag: "normal_title" ) << QString("Whatisthematrix" ) << QString("Whatisthematrix" ); |
103 | QTest::newRow( dataTag: "special_chars_title" ) << QString("<>%&#/()=" ) << QString("<>%&#/()=" ); |
104 | QTest::newRow( dataTag: "spaces_title" ) << QString(" Hello " ) << QString(" Hello " ); |
105 | } |
106 | |
107 | void tst_QGroupBox::setCheckable_data() |
108 | { |
109 | QTest::addColumn<bool>(name: "checkable" ); |
110 | QTest::addColumn<bool>(name: "expectedCheckable" ); |
111 | QTest::newRow( dataTag: "checkable_true" ) << true << true; |
112 | QTest::newRow( dataTag: "checkable_false" ) << false << false; |
113 | } |
114 | |
115 | void tst_QGroupBox::setChecked_data() |
116 | { |
117 | QTest::addColumn<bool>(name: "checkable" ); |
118 | QTest::addColumn<bool>(name: "checked" ); |
119 | QTest::addColumn<bool>(name: "expectedChecked" ); |
120 | QTest::newRow( dataTag: "checkable_false_checked_true" ) << false << true << false; |
121 | QTest::newRow( dataTag: "checkable_true_checked_true" ) << true << true << true; |
122 | QTest::newRow( dataTag: "checkable_true_checked_false" ) << true << false << false; |
123 | } |
124 | |
125 | void tst_QGroupBox::setTitle() |
126 | { |
127 | QFETCH( QString, title ); |
128 | QFETCH( QString, expectedTitle ); |
129 | |
130 | QGroupBox groupBox; |
131 | |
132 | groupBox.setTitle( title ); |
133 | |
134 | QCOMPARE( groupBox.title() , expectedTitle ); |
135 | } |
136 | |
137 | void tst_QGroupBox::setCheckable() |
138 | { |
139 | QFETCH( bool, checkable ); |
140 | QFETCH( bool, expectedCheckable ); |
141 | |
142 | QGroupBox groupBox; |
143 | |
144 | groupBox.setCheckable( checkable ); |
145 | QCOMPARE( groupBox.isCheckable() , expectedCheckable ); |
146 | } |
147 | |
148 | |
149 | void tst_QGroupBox::setChecked() |
150 | { |
151 | QFETCH( bool, checkable ); |
152 | QFETCH( bool, checked ); |
153 | QFETCH( bool, expectedChecked ); |
154 | |
155 | QGroupBox groupBox; |
156 | |
157 | groupBox.setCheckable( checkable ); |
158 | groupBox.setChecked( checked ); |
159 | QCOMPARE( groupBox.isChecked(), expectedChecked ); |
160 | } |
161 | |
162 | void tst_QGroupBox::enabledPropagation() |
163 | { |
164 | QGroupBox *testWidget = new QGroupBox(0); |
165 | testWidget->setCheckable(true); |
166 | testWidget->setChecked(true); |
167 | QWidget* childWidget = new QWidget( testWidget ); |
168 | childWidget->show(); |
169 | QVERIFY( testWidget->isEnabled() ); |
170 | QVERIFY( childWidget->isEnabled() ); |
171 | |
172 | testWidget->setEnabled( false ); |
173 | QVERIFY( !testWidget->isEnabled() ); |
174 | QVERIFY( !childWidget->isEnabled() ); |
175 | |
176 | testWidget->setDisabled( false ); |
177 | QVERIFY( testWidget->isEnabled() ); |
178 | QVERIFY( childWidget->isEnabled() ); |
179 | |
180 | QWidget* grandChildWidget = new QWidget( childWidget ); |
181 | QVERIFY( grandChildWidget->isEnabled() ); |
182 | |
183 | testWidget->setDisabled( true ); |
184 | QVERIFY( !testWidget->isEnabled() ); |
185 | QVERIFY( !childWidget->isEnabled() ); |
186 | QVERIFY( !grandChildWidget->isEnabled() ); |
187 | |
188 | grandChildWidget->setEnabled( false ); |
189 | testWidget->setEnabled( true ); |
190 | QVERIFY( testWidget->isEnabled() ); |
191 | QVERIFY( childWidget->isEnabled() ); |
192 | QVERIFY( !grandChildWidget->isEnabled() ); |
193 | |
194 | grandChildWidget->setEnabled( true ); |
195 | testWidget->setEnabled( false ); |
196 | childWidget->setDisabled( true ); |
197 | testWidget->setEnabled( true ); |
198 | QVERIFY( testWidget->isEnabled() ); |
199 | QVERIFY( !childWidget->isEnabled() ); |
200 | QVERIFY( !grandChildWidget->isEnabled() ); |
201 | |
202 | // Reset state |
203 | testWidget->setEnabled( true ); |
204 | childWidget->setEnabled( true ); |
205 | grandChildWidget->setEnabled( true ); |
206 | |
207 | // Now check when it's disabled |
208 | testWidget->setChecked(false); |
209 | QVERIFY( testWidget->isEnabled() ); |
210 | QVERIFY( !childWidget->isEnabled() ); |
211 | |
212 | testWidget->setEnabled( false ); |
213 | QVERIFY( !testWidget->isEnabled() ); |
214 | QVERIFY( !childWidget->isEnabled() ); |
215 | |
216 | testWidget->setDisabled( false ); |
217 | QVERIFY( testWidget->isEnabled() ); |
218 | QVERIFY( !childWidget->isEnabled() ); |
219 | |
220 | QVERIFY( !grandChildWidget->isEnabled() ); |
221 | |
222 | testWidget->setDisabled( true ); |
223 | QVERIFY( !testWidget->isEnabled() ); |
224 | QVERIFY( !childWidget->isEnabled() ); |
225 | QVERIFY( !grandChildWidget->isEnabled() ); |
226 | |
227 | grandChildWidget->setEnabled( false ); |
228 | testWidget->setEnabled( true ); |
229 | QVERIFY( testWidget->isEnabled() ); |
230 | QVERIFY( !childWidget->isEnabled() ); |
231 | QVERIFY( !grandChildWidget->isEnabled() ); |
232 | |
233 | grandChildWidget->setEnabled( true ); |
234 | testWidget->setEnabled( false ); |
235 | childWidget->setDisabled( true ); |
236 | testWidget->setEnabled( true ); |
237 | QVERIFY( testWidget->isEnabled() ); |
238 | QVERIFY( !childWidget->isEnabled() ); |
239 | QVERIFY( !grandChildWidget->isEnabled() ); |
240 | |
241 | // Reset state |
242 | testWidget->setEnabled( true ); |
243 | childWidget->setEnabled( true ); |
244 | grandChildWidget->setEnabled( true ); |
245 | |
246 | // Finally enable it again |
247 | testWidget->setChecked(true); |
248 | QVERIFY( testWidget->isEnabled() ); |
249 | QVERIFY( childWidget->isEnabled() ); |
250 | |
251 | testWidget->setEnabled( false ); |
252 | QVERIFY( !testWidget->isEnabled() ); |
253 | QVERIFY( !childWidget->isEnabled() ); |
254 | |
255 | testWidget->setDisabled( false ); |
256 | QVERIFY( testWidget->isEnabled() ); |
257 | QVERIFY( childWidget->isEnabled() ); |
258 | QVERIFY( grandChildWidget->isEnabled() ); |
259 | |
260 | testWidget->setDisabled( true ); |
261 | QVERIFY( !testWidget->isEnabled() ); |
262 | QVERIFY( !childWidget->isEnabled() ); |
263 | QVERIFY( !grandChildWidget->isEnabled() ); |
264 | |
265 | grandChildWidget->setEnabled( false ); |
266 | testWidget->setEnabled( true ); |
267 | QVERIFY( testWidget->isEnabled() ); |
268 | QVERIFY( childWidget->isEnabled() ); |
269 | QVERIFY( !grandChildWidget->isEnabled() ); |
270 | |
271 | grandChildWidget->setEnabled( true ); |
272 | testWidget->setEnabled( false ); |
273 | childWidget->setDisabled( true ); |
274 | testWidget->setEnabled( true ); |
275 | QVERIFY( testWidget->isEnabled() ); |
276 | QVERIFY( !childWidget->isEnabled() ); |
277 | QVERIFY( !grandChildWidget->isEnabled() ); |
278 | |
279 | delete testWidget; |
280 | } |
281 | |
282 | void tst_QGroupBox::enabledChildPropagation() |
283 | { |
284 | QGroupBox testWidget; |
285 | testWidget.setCheckable(true); |
286 | testWidget.setChecked(true); |
287 | // The value of isChecked() should be reflected in the isEnabled() of newly |
288 | // added child widgets, but not in top level widgets. |
289 | QWidget *childWidget = new QWidget(&testWidget); |
290 | QVERIFY(childWidget->isEnabled()); |
291 | QDialog *dialog = new QDialog(&testWidget); |
292 | QVERIFY(dialog->isEnabled()); |
293 | testWidget.setChecked(false); |
294 | childWidget = new QWidget(&testWidget); |
295 | QVERIFY(!childWidget->isEnabled()); |
296 | dialog = new QDialog(&testWidget); |
297 | QVERIFY(dialog->isEnabled()); |
298 | |
299 | // children that are enabled after adding should still be disabled before |
300 | // they are shown |
301 | childWidget->setEnabled(true); |
302 | testWidget.show(); |
303 | QVERIFY(!childWidget->isEnabled()); |
304 | } |
305 | |
306 | void tst_QGroupBox::sizeHint() |
307 | { |
308 | QGroupBox testWidget1(0); |
309 | testWidget1.setTitle("&0&0&0&0&0&0&0&0&0&0" ); |
310 | |
311 | QGroupBox testWidget2(0); |
312 | testWidget2.setTitle("0000000000" ); |
313 | |
314 | QCOMPARE(testWidget1.sizeHint().width(), testWidget2.sizeHint().width()); |
315 | |
316 | // if the above fails one should maybe test to see like underneath. |
317 | // QVERIFY((QABS(testWidget1->sizeHint().width() - testWidget2->sizeHint().width()) < 10)); |
318 | } |
319 | |
320 | void tst_QGroupBox::toggledHelperSlot(bool on) |
321 | { |
322 | checked = on; |
323 | } |
324 | |
325 | |
326 | void tst_QGroupBox::toggled() |
327 | { |
328 | QGroupBox testWidget1(0); |
329 | testWidget1.setCheckable(true); |
330 | connect(sender: &testWidget1, SIGNAL(toggled(bool)), receiver: this, SLOT(toggledHelperSlot(bool))); |
331 | QLineEdit *edit = new QLineEdit(&testWidget1); |
332 | QVERIFY(checked); |
333 | testWidget1.setChecked(true); |
334 | QVERIFY(checked); |
335 | QVERIFY(edit->isEnabled()); |
336 | testWidget1.setChecked(false); |
337 | QVERIFY(!checked); |
338 | QVERIFY(!edit->isEnabled()); |
339 | } |
340 | |
341 | void tst_QGroupBox::clicked_data() |
342 | { |
343 | QTest::addColumn<bool>(name: "checkable" ); |
344 | QTest::addColumn<bool>(name: "initialCheck" ); |
345 | QTest::addColumn<int>(name: "areaToHit" ); |
346 | QTest::addColumn<int>(name: "clickedCount" ); |
347 | QTest::addColumn<bool>(name: "finalCheck" ); |
348 | |
349 | QTest::newRow(dataTag: "hit nothing, not checkable" ) << false << false << int(QStyle::SC_None) << 0 << false; |
350 | QTest::newRow(dataTag: "hit frame, not checkable" ) << false << false << int(QStyle::SC_GroupBoxFrame) << 0 << false; |
351 | QTest::newRow(dataTag: "hit content, not checkable" ) << false << false << int(QStyle::SC_GroupBoxContents) << 0 << false; |
352 | QTest::newRow(dataTag: "hit label, not checkable" ) << false << false << int(QStyle::SC_GroupBoxLabel) << 0 << false; |
353 | QTest::newRow(dataTag: "hit checkbox, not checkable" ) << false << false << int(QStyle::SC_GroupBoxCheckBox) << 0 << false; |
354 | |
355 | QTest::newRow(dataTag: "hit nothing, checkable" ) << true << true << int(QStyle::SC_None) << 0 << true; |
356 | QTest::newRow(dataTag: "hit frame, checkable" ) << true << true << int(QStyle::SC_GroupBoxFrame) << 0 << true; |
357 | QTest::newRow(dataTag: "hit content, checkable" ) << true << true << int(QStyle::SC_GroupBoxContents) << 0 << true; |
358 | QTest::newRow(dataTag: "hit label, checkable" ) << true << true << int(QStyle::SC_GroupBoxLabel) << 1 << false; |
359 | QTest::newRow(dataTag: "hit checkbox, checkable" ) << true << true << int(QStyle::SC_GroupBoxCheckBox) << 1 << false; |
360 | |
361 | QTest::newRow(dataTag: "hit nothing, checkable, but unchecked" ) << true << false << int(QStyle::SC_None) << 0 << false; |
362 | QTest::newRow(dataTag: "hit frame, checkable, but unchecked" ) << true << false << int(QStyle::SC_GroupBoxFrame) << 0 << false; |
363 | QTest::newRow(dataTag: "hit content, checkable, but unchecked" ) << true << false << int(QStyle::SC_GroupBoxContents) << 0 << false; |
364 | QTest::newRow(dataTag: "hit label, checkable, but unchecked" ) << true << false << int(QStyle::SC_GroupBoxLabel) << 1 << true; |
365 | QTest::newRow(dataTag: "hit checkbox, checkable, but unchecked" ) << true << false << int(QStyle::SC_GroupBoxCheckBox) << 1 << true; |
366 | } |
367 | |
368 | void tst_QGroupBox::clicked() |
369 | { |
370 | QFETCH(bool, checkable); |
371 | QFETCH(bool, initialCheck); |
372 | QFETCH(int, areaToHit); |
373 | QGroupBox testWidget(QLatin1String("Testing Clicked" )); |
374 | testWidget.setCheckable(checkable); |
375 | testWidget.setChecked(initialCheck); |
376 | QCOMPARE(testWidget.isChecked(), initialCheck); |
377 | testWidget.resize(w: 200, h: 200); |
378 | QSignalSpy spy(&testWidget, SIGNAL(clicked(bool))); |
379 | |
380 | QStyleOptionGroupBox option; |
381 | option.initFrom(w: &testWidget); |
382 | option.subControls = checkable ? QStyle::SubControls(QStyle::SC_All) : QStyle::SubControls(QStyle::SC_All & ~QStyle::SC_GroupBoxCheckBox); |
383 | option.text = testWidget.title(); |
384 | option.textAlignment = testWidget.alignment(); |
385 | |
386 | QRect rect = testWidget.style()->subControlRect(cc: QStyle::CC_GroupBox, opt: &option, |
387 | sc: QStyle::SubControl(areaToHit), widget: &testWidget); |
388 | |
389 | if (rect.isValid()) |
390 | QTest::mouseClick(widget: &testWidget, button: Qt::LeftButton, stateKey: {}, pos: rect.center()); |
391 | else |
392 | QTest::mouseClick(widget: &testWidget, button: Qt::LeftButton); |
393 | |
394 | QTEST(spy.count(), "clickedCount" ); |
395 | if (spy.count() > 0) |
396 | QTEST(spy.at(0).at(0).toBool(), "finalCheck" ); |
397 | QTEST(testWidget.isChecked(), "finalCheck" ); |
398 | } |
399 | |
400 | void tst_QGroupBox::toggledVsClicked() |
401 | { |
402 | timeStamp = clickTimeStamp = toggleTimeStamp = 0; |
403 | QGroupBox groupBox; |
404 | groupBox.setCheckable(true); |
405 | QSignalSpy toggleSpy(&groupBox, SIGNAL(toggled(bool))); |
406 | QSignalSpy clickSpy(&groupBox, SIGNAL(clicked(bool))); |
407 | |
408 | groupBox.setChecked(!groupBox.isChecked()); |
409 | QCOMPARE(clickSpy.count(), 0); |
410 | QCOMPARE(toggleSpy.count(), 1); |
411 | if (toggleSpy.count() > 0) |
412 | QCOMPARE(toggleSpy.at(0).at(0).toBool(), groupBox.isChecked()); |
413 | |
414 | connect(sender: &groupBox, SIGNAL(clicked(bool)), receiver: this, SLOT(clickTimestampSlot())); |
415 | connect(sender: &groupBox, SIGNAL(toggled(bool)), receiver: this, SLOT(toggleTimestampSlot())); |
416 | |
417 | QStyleOptionGroupBox option; |
418 | option.initFrom(w: &groupBox); |
419 | option.subControls = QStyle::SubControls(QStyle::SC_All); |
420 | QRect rect = groupBox.style()->subControlRect(cc: QStyle::CC_GroupBox, opt: &option, |
421 | sc: QStyle::SC_GroupBoxCheckBox, widget: &groupBox); |
422 | |
423 | QTest::mouseClick(widget: &groupBox, button: Qt::LeftButton, stateKey: {}, pos: rect.center()); |
424 | QCOMPARE(clickSpy.count(), 1); |
425 | QCOMPARE(toggleSpy.count(), 2); |
426 | QVERIFY(toggleTimeStamp < clickTimeStamp); |
427 | } |
428 | |
429 | void tst_QGroupBox::clickTimestampSlot() |
430 | { |
431 | clickTimeStamp = ++timeStamp; |
432 | } |
433 | |
434 | void tst_QGroupBox::toggleTimestampSlot() |
435 | { |
436 | toggleTimeStamp = ++timeStamp; |
437 | } |
438 | |
439 | void tst_QGroupBox::childrenAreDisabled() |
440 | { |
441 | QGroupBox box; |
442 | box.setCheckable(true); |
443 | box.setChecked(false); |
444 | |
445 | QVBoxLayout *layout = new QVBoxLayout; |
446 | layout->addWidget(new QRadioButton); |
447 | layout->addWidget(new QRadioButton); |
448 | layout->addWidget(new QRadioButton); |
449 | box.setLayout(layout); |
450 | |
451 | foreach (QObject *object, box.children()) { |
452 | if (QWidget *widget = qobject_cast<QWidget *>(o: object)) { |
453 | QVERIFY(!widget->isEnabled()); |
454 | QVERIFY(!widget->testAttribute(Qt::WA_ForceDisabled)); |
455 | } |
456 | } |
457 | |
458 | box.setChecked(true); |
459 | foreach (QObject *object, box.children()) { |
460 | if (QWidget *widget = qobject_cast<QWidget *>(o: object)) { |
461 | QVERIFY(widget->isEnabled()); |
462 | QVERIFY(!widget->testAttribute(Qt::WA_ForceDisabled)); |
463 | } |
464 | } |
465 | |
466 | box.setChecked(false); |
467 | foreach (QObject *object, box.children()) { |
468 | if (QWidget *widget = qobject_cast<QWidget *>(o: object)) { |
469 | QVERIFY(!widget->isEnabled()); |
470 | QVERIFY(!widget->testAttribute(Qt::WA_ForceDisabled)); |
471 | } |
472 | } |
473 | } |
474 | |
475 | void tst_QGroupBox::propagateFocus() |
476 | { |
477 | if (QGuiApplication::platformName().startsWith(s: QLatin1String("wayland" ), cs: Qt::CaseInsensitive)) |
478 | QSKIP("Wayland: This fails. Figure out why." ); |
479 | |
480 | QGroupBox box; |
481 | QLineEdit lineEdit(&box); |
482 | box.show(); |
483 | QApplication::setActiveWindow(&box); |
484 | QVERIFY(QTest::qWaitForWindowActive(&box)); |
485 | box.setFocus(); |
486 | QTRY_COMPARE(qApp->focusWidget(), static_cast<QWidget*>(&lineEdit)); |
487 | } |
488 | |
489 | void tst_QGroupBox::task_QTBUG_19170_ignoreMouseReleaseEvent() |
490 | { |
491 | QGroupBox box; |
492 | box.setCheckable(true); |
493 | box.setChecked(false); |
494 | box.setTitle("This is a test for QTBUG-19170" ); |
495 | box.show(); |
496 | |
497 | QStyleOptionGroupBox option; |
498 | option.initFrom(w: &box); |
499 | option.subControls = QStyle::SubControls(QStyle::SC_All); |
500 | QRect rect = box.style()->subControlRect(cc: QStyle::CC_GroupBox, opt: &option, |
501 | sc: QStyle::SC_GroupBoxCheckBox, widget: &box); |
502 | |
503 | QTest::mouseClick(widget: &box, button: Qt::LeftButton, stateKey: {}, pos: rect.center()); |
504 | QCOMPARE(box.isChecked(), true); |
505 | |
506 | box.setChecked(false); |
507 | QTest::mouseRelease(widget: &box, button: Qt::LeftButton, stateKey: {}, pos: rect.center()); |
508 | QCOMPARE(box.isChecked(), false); |
509 | } |
510 | |
511 | class MouseEventTestWidget : public QWidget |
512 | { |
513 | public: |
514 | bool mousePressed; |
515 | bool mouseReleased; |
516 | bool mouseMoved; |
517 | |
518 | void reset() |
519 | { |
520 | mousePressed = false; |
521 | mouseReleased = false; |
522 | mouseMoved = false; |
523 | } |
524 | |
525 | protected: |
526 | void mousePressEvent(QMouseEvent*) |
527 | { |
528 | mousePressed = true; |
529 | } |
530 | |
531 | void mouseReleaseEvent(QMouseEvent*) |
532 | { |
533 | mouseReleased = true; |
534 | } |
535 | |
536 | void mouseMoveEvent(QMouseEvent*) |
537 | { |
538 | mouseMoved = true; |
539 | } |
540 | }; |
541 | |
542 | void tst_QGroupBox::task_QTBUG_15519_propagateMouseEvents() |
543 | { |
544 | MouseEventTestWidget parent; |
545 | QGroupBox box(&parent); |
546 | parent.setMouseTracking(true); |
547 | box.setMouseTracking(true); |
548 | box.resize(w: 100, h: 100); |
549 | box.setTitle("This is a test for QTBUG-15519" ); |
550 | box.show(); |
551 | |
552 | QStyleOptionGroupBox option; |
553 | option.initFrom(w: &box); |
554 | option.subControls = QStyle::SubControls(QStyle::SC_All); |
555 | QRect checkBoxRect = box.style()->subControlRect(cc: QStyle::CC_GroupBox, opt: &option, |
556 | sc: QStyle::SC_GroupBoxCheckBox, widget: &box); |
557 | |
558 | // Without a checkbox, all mouse events should propagate |
559 | |
560 | parent.reset(); |
561 | QTest::mousePress(widget: &box, button: Qt::LeftButton, stateKey: {}, pos: checkBoxRect.center()); |
562 | QCOMPARE(parent.mousePressed, true); |
563 | |
564 | parent.reset(); |
565 | QTest::mousePress(widget: &box, button: Qt::LeftButton, stateKey: {}, pos: box.rect().center()); |
566 | QCOMPARE(parent.mousePressed, true); |
567 | |
568 | parent.reset(); |
569 | QTest::mouseRelease(widget: &box, button: Qt::LeftButton, stateKey: {}, pos: checkBoxRect.center()); |
570 | QCOMPARE(parent.mouseReleased, true); |
571 | |
572 | parent.reset(); |
573 | QTest::mouseRelease(widget: &box, button: Qt::LeftButton, stateKey: {}, pos: box.rect().center()); |
574 | QCOMPARE(parent.mouseReleased, true); |
575 | |
576 | parent.reset(); |
577 | sendMouseMoveEvent(widget: &box, localPos: checkBoxRect.center()); |
578 | QCOMPARE(parent.mouseMoved, true); |
579 | |
580 | parent.reset(); |
581 | sendMouseMoveEvent(widget: &box, localPos: box.rect().center()); |
582 | QCOMPARE(parent.mouseMoved, true); |
583 | |
584 | // With a checkbox, presses and releases to the checkbox should not propagate |
585 | |
586 | box.setCheckable(true); |
587 | |
588 | parent.reset(); |
589 | QTest::mousePress(widget: &box, button: Qt::LeftButton, stateKey: {}, pos: checkBoxRect.center()); |
590 | QCOMPARE(parent.mousePressed, false); |
591 | |
592 | parent.reset(); |
593 | QTest::mousePress(widget: &box, button: Qt::LeftButton, stateKey: {}, pos: box.rect().center()); |
594 | QCOMPARE(parent.mousePressed, true); |
595 | |
596 | parent.reset(); |
597 | QTest::mouseRelease(widget: &box, button: Qt::LeftButton, stateKey: {}, pos: checkBoxRect.center()); |
598 | QCOMPARE(parent.mouseReleased, false); |
599 | |
600 | parent.reset(); |
601 | QTest::mouseRelease(widget: &box, button: Qt::LeftButton, stateKey: {}, pos: box.rect().center()); |
602 | QCOMPARE(parent.mouseReleased, true); |
603 | |
604 | parent.reset(); |
605 | sendMouseMoveEvent(widget: &box, localPos: checkBoxRect.center()); |
606 | QCOMPARE(parent.mouseMoved, true); |
607 | |
608 | parent.reset(); |
609 | sendMouseMoveEvent(widget: &box, localPos: box.rect().center()); |
610 | QCOMPARE(parent.mouseMoved, true); |
611 | } |
612 | |
613 | void tst_QGroupBox::sendMouseMoveEvent(QWidget *widget, const QPoint &localPos) |
614 | { |
615 | // Send a MouseMove event without actually moving the pointer |
616 | QMouseEvent event(QEvent::MouseMove, localPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier); |
617 | QApplication::sendEvent(receiver: widget, event: &event); |
618 | } |
619 | |
620 | QTEST_MAIN(tst_QGroupBox) |
621 | #include "tst_qgroupbox.moc" |
622 | |