aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ-P Nurmi <jpnurmi@qt.io>2016-09-19 15:43:36 +0200
committerJ-P Nurmi <jpnurmi@qt.io>2016-09-19 16:37:07 +0000
commit6ed4918f131ff235bcab3efe849f5b67406ef350 (patch)
treed541a058763935002e8d523a3938bac852c9fd75
parente5079c1828dd0fe2e90347f20da40da033fbec5a (diff)
QQuickSwitch: fix event handling
Switch implemented custom event handling for the indicator, and used QQuickAbstractButton's event handling for the background. This lead to inconsistent signals depending on whether interacting with the handle or the background. This change gets rid of the child mouse event filter for the indicator and makes QQuickSwitch fully utilize the base class event handlers. Change-Id: I773e2eb939cbbf4bc9086cdf2b34e876597ea08e Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
-rw-r--r--src/quicktemplates2/qquickswitch.cpp123
-rw-r--r--src/quicktemplates2/qquickswitch_p.h6
-rw-r--r--tests/auto/controls/data/tst_switch.qml70
3 files changed, 108 insertions, 91 deletions
diff --git a/src/quicktemplates2/qquickswitch.cpp b/src/quicktemplates2/qquickswitch.cpp
index beb9a764..27043c8b 100644
--- a/src/quicktemplates2/qquickswitch.cpp
+++ b/src/quicktemplates2/qquickswitch.cpp
@@ -90,97 +90,28 @@ class QQuickSwitchPrivate : public QQuickAbstractButtonPrivate
public:
QQuickSwitchPrivate() : position(0) { }
- qreal positionAt(const QPoint &point) const;
-
- bool handleMousePressEvent(QQuickItem *child, QMouseEvent *event);
- bool handleMouseMoveEvent(QQuickItem *child, QMouseEvent *event);
- bool handleMouseReleaseEvent(QQuickItem *child, QMouseEvent *event);
- bool handleMouseUngrabEvent(QQuickItem *child);
+ qreal positionAt(const QPointF &point) const;
qreal position;
- QPoint pressPoint;
};
-qreal QQuickSwitchPrivate::positionAt(const QPoint &point) const
+qreal QQuickSwitchPrivate::positionAt(const QPointF &point) const
{
Q_Q(const QQuickSwitch);
- qreal pos = point.x() / indicator->width();
+ qreal pos = 0.0;
+ if (indicator)
+ pos = indicator->mapFromItem(q, point).x() / indicator->width();
if (q->isMirrored())
return 1.0 - pos;
return pos;
}
-bool QQuickSwitchPrivate::handleMousePressEvent(QQuickItem *child, QMouseEvent *event)
-{
- Q_Q(QQuickSwitch);
- Q_UNUSED(child);
- if ((focusPolicy & Qt::ClickFocus) == Qt::ClickFocus && !QGuiApplication::styleHints()->setFocusOnTouchRelease())
- q->forceActiveFocus(Qt::MouseFocusReason);
-
- pressPoint = event->pos();
- q->setPressed(true);
- emit q->pressed();
- event->accept();
- return true;
-}
-
-bool QQuickSwitchPrivate::handleMouseMoveEvent(QQuickItem *child, QMouseEvent *event)
-{
- Q_Q(QQuickSwitch);
- if (!child->keepMouseGrab())
- child->setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(event->pos().x() - pressPoint.x(), Qt::XAxis, event));
- if (child->keepMouseGrab()) {
- q->setPosition(positionAt(event->pos()));
- event->accept();
- }
- return true;
-}
-
-bool QQuickSwitchPrivate::handleMouseReleaseEvent(QQuickItem *child, QMouseEvent *event)
-{
- Q_Q(QQuickSwitch);
- if ((focusPolicy & Qt::ClickFocus) == Qt::ClickFocus && QGuiApplication::styleHints()->setFocusOnTouchRelease())
- q->forceActiveFocus(Qt::MouseFocusReason);
-
- pressPoint = QPoint();
- q->setPressed(false);
- if (child->keepMouseGrab()) {
- bool wasChecked = checked;
- q->setChecked(position > 0.5);
- q->setPosition(checked ? 1.0 : 0.0);
- child->setKeepMouseGrab(false);
- if (wasChecked != checked) {
- emit q->released();
- emit q->clicked();
- }
- event->accept();
- } else {
- q->toggle();
- emit q->released();
- emit q->clicked();
- event->accept();
- }
- return true;
-}
-
-bool QQuickSwitchPrivate::handleMouseUngrabEvent(QQuickItem *child)
-{
- Q_Q(QQuickSwitch);
- Q_UNUSED(child);
- pressPoint = QPoint();
- q->setChecked(position > 0.5);
- q->setPosition(checked ? 1.0 : 0.0);
- q->setPressed(false);
- return true;
-}
-
QQuickSwitch::QQuickSwitch(QQuickItem *parent) :
QQuickAbstractButton(*(new QQuickSwitchPrivate), parent)
{
Q_D(QQuickSwitch);
d->keepPressed = true;
setCheckable(true);
- setFiltersChildMouseEvents(true);
}
/*!
@@ -221,30 +152,42 @@ qreal QQuickSwitch::visualPosition() const
return d->position;
}
+void QQuickSwitch::mousePressEvent(QMouseEvent *event)
+{
+ QQuickAbstractButton::mousePressEvent(event);
+}
+
+void QQuickSwitch::mouseMoveEvent(QMouseEvent *event)
+{
+ Q_D(QQuickSwitch);
+ QQuickAbstractButton::mouseMoveEvent(event);
+
+ const QPointF movePoint = event->localPos();
+ if (!keepMouseGrab())
+ setKeepMouseGrab(QQuickWindowPrivate::dragOverThreshold(movePoint.x() - d->pressPoint.x(), Qt::XAxis, event));
+ if (keepMouseGrab())
+ setPosition(d->positionAt(movePoint));
+}
+
+void QQuickSwitch::mouseReleaseEvent(QMouseEvent *event)
+{
+ QQuickAbstractButton::mouseReleaseEvent(event);
+ setKeepMouseGrab(false);
+}
+
void QQuickSwitch::mirrorChange()
{
QQuickAbstractButton::mirrorChange();
emit visualPositionChanged();
}
-bool QQuickSwitch::childMouseEventFilter(QQuickItem *child, QEvent *event)
+void QQuickSwitch::nextCheckState()
{
Q_D(QQuickSwitch);
- if (child == indicator()) {
- switch (event->type()) {
- case QEvent::MouseButtonPress:
- return d->handleMousePressEvent(child, static_cast<QMouseEvent *>(event));
- case QEvent::MouseMove:
- return d->handleMouseMoveEvent(child, static_cast<QMouseEvent *>(event));
- case QEvent::MouseButtonRelease:
- return d->handleMouseReleaseEvent(child, static_cast<QMouseEvent *>(event));
- case QEvent::UngrabMouse:
- return d->handleMouseUngrabEvent(child);
- default:
- return false;
- }
- }
- return false;
+ if (keepMouseGrab())
+ setChecked(d->position > 0.5);
+ else
+ QQuickAbstractButton::nextCheckState();
}
void QQuickSwitch::checkStateSet()
diff --git a/src/quicktemplates2/qquickswitch_p.h b/src/quicktemplates2/qquickswitch_p.h
index bfbcceed..27a065b4 100644
--- a/src/quicktemplates2/qquickswitch_p.h
+++ b/src/quicktemplates2/qquickswitch_p.h
@@ -73,9 +73,13 @@ Q_SIGNALS:
void visualPositionChanged();
protected:
+ void mousePressEvent(QMouseEvent *event) override;
+ void mouseMoveEvent(QMouseEvent *event) override;
+ void mouseReleaseEvent(QMouseEvent *event) override;
+
void mirrorChange() override;
- bool childMouseEventFilter(QQuickItem *child, QEvent *event) override;
+ void nextCheckState() override;
void checkStateSet() override;
private:
diff --git a/tests/auto/controls/data/tst_switch.qml b/tests/auto/controls/data/tst_switch.qml
index 1b77ff42..f854526c 100644
--- a/tests/auto/controls/data/tst_switch.qml
+++ b/tests/auto/controls/data/tst_switch.qml
@@ -200,6 +200,76 @@ TestCase {
control.destroy()
}
+ function test_drag() {
+ var control = swtch.createObject(testCase, {leftPadding: 100, rightPadding: 100})
+ verify(control)
+
+ var spy = signalSequenceSpy.createObject(control, {target: control})
+ compare(control.position, 0.0)
+ compare(control.checked, false)
+ compare(control.pressed, false)
+
+ // press-drag-release inside the indicator
+ spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": false }],
+ "pressed"]
+ mousePress(control.indicator, 0)
+ compare(control.position, 0.0)
+ compare(control.checked, false)
+ compare(control.pressed, true)
+ verify(spy.success)
+
+ mouseMove(control.indicator, control.width)
+ compare(control.position, 1.0)
+ compare(control.checked, false)
+ compare(control.pressed, true)
+
+ spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": false }],
+ ["checkedChanged", { "pressed": false, "checked": true }],
+ "released",
+ "clicked"]
+ mouseRelease(control.indicator, control.indicator.width)
+ compare(control.position, 1.0)
+ compare(control.checked, true)
+ compare(control.pressed, false)
+ verify(spy.success)
+
+ // press-drag-release outside the indicator
+ spy.expectedSequence = [["pressedChanged", { "pressed": true, "checked": true }],
+ "pressed"]
+ mousePress(control, 0)
+ compare(control.position, 1.0)
+ compare(control.checked, true)
+ compare(control.pressed, true)
+ verify(spy.success)
+
+ mouseMove(control, control.width - control.rightPadding)
+ compare(control.position, 1.0)
+ compare(control.checked, true)
+ compare(control.pressed, true)
+
+ mouseMove(control, control.width / 2)
+ compare(control.position, 0.5)
+ compare(control.checked, true)
+ compare(control.pressed, true)
+
+ mouseMove(control, control.leftPadding)
+ compare(control.position, 0.0)
+ compare(control.checked, true)
+ compare(control.pressed, true)
+
+ spy.expectedSequence = [["pressedChanged", { "pressed": false, "checked": true }],
+ ["checkedChanged", { "pressed": false, "checked": false }],
+ "released",
+ "clicked"]
+ mouseRelease(control, control.width)
+ compare(control.position, 0.0)
+ compare(control.checked, false)
+ compare(control.pressed, false)
+ verify(spy.success)
+
+ control.destroy()
+ }
+
function test_keys() {
var control = swtch.createObject(testCase)
verify(control)