From 4ac94480c33caa8c95254fc9db3352a832f55b7e Mon Sep 17 00:00:00 2001 From: Alex Henrie Date: Mon, 24 Aug 2015 21:13:55 -0600 Subject: QGroupBox: Send unhandled mouse events to parent widget Every other subclass of QWidget calls event->ignore() on unhandled events, and QGroupBox's failure to follow this convention prevented it from being used in some specialized applications. Instances of QGroupBox now only absorb mouse press events to their checkboxes (if they have checkboxes) and ignore all other mouse events. Task-number: QTBUG-15519 Change-Id: I6b0c89c92868feddbe3888088703b32cb95d9903 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/widgets/widgets/qgroupbox.cpp | 4 + .../widgets/widgets/qgroupbox/tst_qgroupbox.cpp | 111 +++++++++++++++++++++ 2 files changed, 115 insertions(+) diff --git a/src/widgets/widgets/qgroupbox.cpp b/src/widgets/widgets/qgroupbox.cpp index 0ff5dc8753..f1ebf91ad7 100644 --- a/src/widgets/widgets/qgroupbox.cpp +++ b/src/widgets/widgets/qgroupbox.cpp @@ -707,6 +707,8 @@ void QGroupBox::mousePressEvent(QMouseEvent *event) if (d->checkable && (d->pressedControl & (QStyle::SC_GroupBoxCheckBox | QStyle::SC_GroupBoxLabel))) { d->overCheckBox = true; update(style()->subControlRect(QStyle::CC_GroupBox, &box, QStyle::SC_GroupBoxCheckBox, this)); + } else { + event->ignore(); } } @@ -723,6 +725,8 @@ void QGroupBox::mouseMoveEvent(QMouseEvent *event) if (d->checkable && (d->pressedControl == QStyle::SC_GroupBoxCheckBox || d->pressedControl == QStyle::SC_GroupBoxLabel) && (d->overCheckBox != oldOverCheckBox)) update(style()->subControlRect(QStyle::CC_GroupBox, &box, QStyle::SC_GroupBoxCheckBox, this)); + + event->ignore(); } /*! \reimp */ diff --git a/tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp b/tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp index 53eec99258..d7a03deb45 100644 --- a/tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp +++ b/tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp @@ -73,6 +73,7 @@ private slots: void childrenAreDisabled(); void propagateFocus(); void task_QTBUG_19170_ignoreMouseReleseEvent(); + void task_QTBUG_15519_propagateMouseEvents(); private: bool checked; @@ -80,6 +81,7 @@ private: qint64 clickTimeStamp; qint64 toggleTimeStamp; + static void sendMouseMoveEvent(QWidget *widget, const QPoint &localPos); }; tst_QGroupBox::tst_QGroupBox() @@ -502,5 +504,114 @@ void tst_QGroupBox::task_QTBUG_19170_ignoreMouseReleseEvent() QCOMPARE(box.isChecked(), false); } +class MouseEventTestWidget : public QWidget +{ +public: + bool mousePressed; + bool mouseReleased; + bool mouseMoved; + + void reset() + { + mousePressed = false; + mouseReleased = false; + mouseMoved = false; + } + +protected: + void mousePressEvent(QMouseEvent*) + { + mousePressed = true; + } + + void mouseReleaseEvent(QMouseEvent*) + { + mouseReleased = true; + } + + void mouseMoveEvent(QMouseEvent*) + { + mouseMoved = true; + } +}; + +void tst_QGroupBox::task_QTBUG_15519_propagateMouseEvents() +{ + MouseEventTestWidget parent; + QGroupBox box(&parent); + parent.setMouseTracking(true); + box.setMouseTracking(true); + box.resize(100, 100); + box.setTitle("This is a test for QTBUG-15519"); + box.show(); + + QStyleOptionGroupBox option; + option.initFrom(&box); + option.subControls = QStyle::SubControls(QStyle::SC_All); + QRect checkBoxRect = box.style()->subControlRect(QStyle::CC_GroupBox, &option, + QStyle::SC_GroupBoxCheckBox, &box); + + // Without a checkbox, all mouse events should propagate + + parent.reset(); + QTest::mousePress(&box, Qt::LeftButton, 0, checkBoxRect.center()); + QCOMPARE(parent.mousePressed, true); + + parent.reset(); + QTest::mousePress(&box, Qt::LeftButton, 0, box.rect().center()); + QCOMPARE(parent.mousePressed, true); + + parent.reset(); + QTest::mouseRelease(&box, Qt::LeftButton, 0, checkBoxRect.center()); + QCOMPARE(parent.mouseReleased, true); + + parent.reset(); + QTest::mouseRelease(&box, Qt::LeftButton, 0, box.rect().center()); + QCOMPARE(parent.mouseReleased, true); + + parent.reset(); + sendMouseMoveEvent(&box, checkBoxRect.center()); + QCOMPARE(parent.mouseMoved, true); + + parent.reset(); + sendMouseMoveEvent(&box, box.rect().center()); + QCOMPARE(parent.mouseMoved, true); + + // With a checkbox, presses and releases to the checkbox should not propagate + + box.setCheckable(true); + + parent.reset(); + QTest::mousePress(&box, Qt::LeftButton, 0, checkBoxRect.center()); + QCOMPARE(parent.mousePressed, false); + + parent.reset(); + QTest::mousePress(&box, Qt::LeftButton, 0, box.rect().center()); + QCOMPARE(parent.mousePressed, true); + + parent.reset(); + QTest::mouseRelease(&box, Qt::LeftButton, 0, checkBoxRect.center()); + QCOMPARE(parent.mouseReleased, false); + + parent.reset(); + QTest::mouseRelease(&box, Qt::LeftButton, 0, box.rect().center()); + QCOMPARE(parent.mouseReleased, true); + + parent.reset(); + sendMouseMoveEvent(&box, checkBoxRect.center()); + QCOMPARE(parent.mouseMoved, true); + + parent.reset(); + sendMouseMoveEvent(&box, box.rect().center()); + QCOMPARE(parent.mouseMoved, true); +} + +void tst_QGroupBox::sendMouseMoveEvent(QWidget *widget, const QPoint &localPos) +{ + // Send a MouseMove event without actually moving the pointer + QMouseEvent event(QEvent::MouseMove, localPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier); + QApplication::sendEvent(widget, &event); +} + QTEST_MAIN(tst_QGroupBox) #include "tst_qgroupbox.moc" -- cgit v1.2.3