diff options
-rw-r--r-- | src/quicktemplates2/qquickswitch.cpp | 123 | ||||
-rw-r--r-- | src/quicktemplates2/qquickswitch_p.h | 6 | ||||
-rw-r--r-- | tests/auto/controls/data/tst_switch.qml | 70 |
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) |