From 6ed4918f131ff235bcab3efe849f5b67406ef350 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Mon, 19 Sep 2016 15:43:36 +0200 Subject: 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 --- src/quicktemplates2/qquickswitch.cpp | 123 ++++++++++------------------------- src/quicktemplates2/qquickswitch_p.h | 6 +- 2 files changed, 38 insertions(+), 91 deletions(-) (limited to 'src') 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(event)); - case QEvent::MouseMove: - return d->handleMouseMoveEvent(child, static_cast(event)); - case QEvent::MouseButtonRelease: - return d->handleMouseReleaseEvent(child, static_cast(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: -- cgit v1.2.3