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) <ogoffart@woboq.com>
This commit is contained in:
Alex Henrie 2015-08-24 21:13:55 -06:00
parent 9129d2714a
commit 4ac94480c3
2 changed files with 115 additions and 0 deletions

View File

@ -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 */

View File

@ -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"