diff --git a/src/quick/doc/snippets/pointerHandlers/images/album-cover.jpg b/src/quick/doc/snippets/pointerHandlers/images/album-cover.jpg new file mode 100644 index 0000000000..48bd6231ba Binary files /dev/null and b/src/quick/doc/snippets/pointerHandlers/images/album-cover.jpg differ diff --git a/src/quick/doc/snippets/pointerHandlers/pinchHandlerNullTarget.qml b/src/quick/doc/snippets/pointerHandlers/pinchHandlerNullTarget.qml index f844ce9c98..6884e39e6a 100644 --- a/src/quick/doc/snippets/pointerHandlers/pinchHandlerNullTarget.qml +++ b/src/quick/doc/snippets/pointerHandlers/pinchHandlerNullTarget.qml @@ -1,22 +1,31 @@ // Copyright (C) 2017 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause //![0] -import QtQuick 2.12 +import QtQuick -Item { - width: 640 - height: 480 +Window { + width: 320; height: 240 + visible: true + title: handler.persistentRotation.toFixed(1) + "° " + + handler.persistentTranslation.x.toFixed(1) + ", " + + handler.persistentTranslation.y.toFixed(1) + " " + + (handler.persistentScale * 100).toFixed(1) + "%" PinchHandler { id: handler target: null + persistentScale: 0.25 + onTranslationChanged: (delta) => { + image.x -= delta.x + image.y -= delta.y + } } - Text { - color: handler.active ? "darkgreen" : "black" - text: handler.rotation.toFixed(1) + " degrees\n" + - handler.translation.x.toFixed(1) + ", " + handler.translation.y.toFixed(1) + "\n" + - (handler.scale * 100).toFixed(1) + "%" + Image { + id: image + source: "images/album-cover.jpg" + scale: handler.persistentScale + x: -600; y: -450 } } //![0] diff --git a/src/quick/doc/snippets/pointerHandlers/pinchHandlerScaleOrRotationChanged.qml b/src/quick/doc/snippets/pointerHandlers/pinchHandlerScaleOrRotationChanged.qml new file mode 100644 index 0000000000..3baa93eb7c --- /dev/null +++ b/src/quick/doc/snippets/pointerHandlers/pinchHandlerScaleOrRotationChanged.qml @@ -0,0 +1,17 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +//![0] +import QtQuick + +Rectangle { + width: 100; height: 100 + color: "lightsteelblue" + + PinchHandler { + id: handler + target: null + onRotationChanged: (delta) => parent.rotation += delta // add + onScaleChanged: (delta) => parent.scale *= delta // multiply + } +} +//![0] diff --git a/src/quick/handlers/qquickdraghandler.cpp b/src/quick/handlers/qquickdraghandler.cpp index b34ca0e7cf..6b7c046c6c 100644 --- a/src/quick/handlers/qquickdraghandler.cpp +++ b/src/quick/handlers/qquickdraghandler.cpp @@ -290,7 +290,7 @@ void QQuickDragHandler::setPersistentTranslation(const QVector2D &trans) m_xAxis.updateValue(m_xAxis.activeValue(), trans.x()); m_yAxis.updateValue(m_yAxis.activeValue(), trans.y()); - emit translationChanged(); + emit translationChanged({}); } void QQuickDragHandler::setActiveTranslation(const QVector2D &trans) @@ -304,7 +304,7 @@ void QQuickDragHandler::setActiveTranslation(const QVector2D &trans) qCDebug(lcDragHandler) << "translation: delta" << delta << "active" << trans << "accumulated" << persistentTranslation(); - emit translationChanged(); + emit translationChanged(delta); } /*! diff --git a/src/quick/handlers/qquickdraghandler_p.h b/src/quick/handlers/qquickdraghandler_p.h index 925783ec98..f67e0ccf72 100644 --- a/src/quick/handlers/qquickdraghandler_p.h +++ b/src/quick/handlers/qquickdraghandler_p.h @@ -65,7 +65,7 @@ public: void enforceConstraints(); Q_SIGNALS: - void translationChanged(); + void translationChanged(QVector2D delta); Q_REVISION(2, 14) void snapModeChanged(); protected: diff --git a/src/quick/handlers/qquickpinchhandler.cpp b/src/quick/handlers/qquickpinchhandler.cpp index f11d8357eb..8380ef28ae 100644 --- a/src/quick/handlers/qquickpinchhandler.cpp +++ b/src/quick/handlers/qquickpinchhandler.cpp @@ -96,6 +96,78 @@ void QQuickPinchHandler::setMaximumScale(qreal maximumScale) emit maximumScaleChanged(); } +/*! + \readonly + \qmlproperty real QtQuick::PinchHandler::activeScale + + The scale factor while the pinch gesture is being performed. + It is 1.0 when the gesture begins, increases as the touchpoints are spread + apart, and decreases as the touchpoints are brought together. + If \l target is not null, its \l {Item::scale}{scale} will be automatically + multiplied by this value. + Otherwise, bindings can be used to do arbitrary things with this value. + + \sa QtQuick::PinchHandler::scaleAxis.activeValue +*/ + +void QQuickPinchHandler::setActiveScale(qreal scale) +{ + if (scale == activeScale()) + return; + + qreal delta = scale / m_scaleAxis.activeValue(); + m_scaleAxis.updateValue(scale, m_scaleAxis.m_startValue * scale, delta); + emit scaleChanged(delta); +} + +/*! + \qmlsignal QtQuick::PinchHandler::scaleChanged(qreal delta) + + The \c scaleChanged signal is emitted when \l activeScale (and therefore + \l persistentScale) changes. The \a delta value gives the multiplicative + change in scale. For example, if the user moves fingers to change the pinch + distance so that \c activeScale changes from 2 to 2.5, \c + scaleChanged(1.25) will be emitted. You can use that to incrementally + change the scale of an item: + + \snippet pointerHandlers/pinchHandlerScaleOrRotationChanged.qml 0 + + \note If you set the \l persistentScale property directly, \c delta is \c 1. +*/ + +/*! + \readonly + \qmlproperty QVector2D QtQuick::PinchHandler::scale + \deprecated [6.5] Use persistentScale +*/ + +/*! + \readonly + \qmlproperty real QtQuick::PinchHandler::persistentScale + + The scale factor that will automatically be set on the \l target if it is not null. + Otherwise, bindings can be used to do arbitrary things with this value. + While the pinch gesture is being performed, it is continuously multiplied by + \l activeScale; after the gesture ends, it stays the same; and when the next + pinch gesture begins, it begins to be multiplied by activeScale again. + + It's possible to set this property, as a way of synchronizing the basis + scale with a scale that was set in some other way, for example by another + handler. If you set this property directly, \c activeScale does not change, + and \c scaleChanged(1) is emitted. + + \sa QtQuick::PinchHandler::scaleAxis.persistentValue +*/ + +void QQuickPinchHandler::setPersistentScale(qreal rot) +{ + if (rot == persistentScale()) + return; + + m_scaleAxis.updateValue(m_scaleAxis.activeValue(), rot); + emit scaleChanged(1); +} + /*! \qmlproperty real QtQuick::PinchHandler::minimumRotation @@ -126,6 +198,136 @@ void QQuickPinchHandler::setMaximumRotation(qreal maximumRotation) emit maximumRotationChanged(); } +/*! + \qmlsignal QtQuick::PinchHandler::rotationChanged(qreal delta) + + The \c rotationChanged signal is emitted when \l activeRotation (and + therefore \l persistentRotation) changes. The \a delta value gives the + additive change in rotation. For example, if the user moves fingers to + change the pinch distance so that \c activeRotation changes from 10 to 30 + degrees, \c rotationChanged(20) will be emitted. You can use that to + incrementally change the rotation of an item: + + \snippet pointerHandlers/pinchHandlerScaleOrRotationChanged.qml 0 + + \note If you set the \l persistentRotation property directly, \c delta is \c 0. +*/ + +/*! + \readonly + \qmlproperty QVector2D QtQuick::PinchHandler::rotation + \deprecated [6.5] Use activeRotation +*/ + +/*! + \readonly + \qmlproperty real QtQuick::PinchHandler::activeRotation + + The rotation of the pinch gesture in degrees, with positive values clockwise. + It is \c 0 when the gesture begins. If \l target is not null, this will be + automatically added to its \l {Item::rotation}{rotation}. Otherwise, + bindings can be used to do arbitrary things with this value. + + \sa QtQuick::PinchHandler::rotationAxis.activeValue +*/ + +void QQuickPinchHandler::setActiveRotation(qreal rot) +{ + if (rot == activeRotation()) + return; + + qreal delta = rot - m_rotationAxis.activeValue(); + m_rotationAxis.updateValue(rot, m_rotationAxis.m_startValue + rot, delta); + emit rotationChanged(delta); +} + +/*! + \readonly + \qmlproperty real QtQuick::PinchHandler::persistentRotation + + The rotation to be applied to the \l target if it is not null. + Otherwise, bindings can be used to do arbitrary things with this value. + While the pinch gesture is being performed, \l activeRotation is continuously + added; after the gesture ends, it stays the same; and when the next + pinch gesture begins, it begins to be modified by activeRotation again. + + \sa QtQuick::PinchHandler::rotationAxis.persistentValue + + It's possible to set this property, as a way of synchronizing the basis + rotation with a rotation that was set in some other way, for example by + another handler. If you set this property directly, \c activeRotation does + not change, and \c rotationChanged(0) is emitted. +*/ + +void QQuickPinchHandler::setPersistentRotation(qreal rot) +{ + if (rot == persistentRotation()) + return; + + m_rotationAxis.updateValue(m_rotationAxis.activeValue(), rot); + emit rotationChanged(0); +} + +/*! + \qmlsignal QtQuick::PinchHandler::translationChanged(QVector2D delta) + + The \c translationChanged signal is emitted when \l activeTranslation (and + therefore \l persistentTranslation) changes. The \a delta vector gives the + change in translation. You can use that to incrementally change the + position of an item: + + \snippet pointerHandlers/pinchHandlerNullTarget.qml 0 + + \note If you set the \l persistentTranslation property directly, + \c delta is \c {0, 0}. +*/ + +/*! + \readonly + \qmlproperty QVector2D QtQuick::PinchHandler::translation + \deprecated [6.5] Use activeTranslation +*/ +/*! + \readonly + \qmlproperty QPointF QtQuick::PinchHandler::activeTranslation + + The translation of the cluster of points while the pinch gesture is being + performed. It is \c {0, 0} when the gesture begins, and increases as the + event point(s) are dragged downward and to the right. After the gesture + ends, it stays the same; and when the next pinch gesture begins, it is + reset to \c {0, 0} again. + + \note On some touchpads, such as on a \macos trackpad, native gestures do + not generate any translation values, and this property stays at \c (0, 0). +*/ + +/*! + \qmlproperty QPointF QtQuick::PinchHandler::persistentTranslation + + The translation to be applied to the \l target if it is not \c null. + Otherwise, bindings can be used to do arbitrary things with this value. + While the pinch gesture is being performed, \l activeTranslation is + continuously added to it; after the gesture ends, it stays the same. + + It's possible to set this property, as a way of synchronizing the basis + translation with a translation that was set in some other way, for example + by another handler. If you set this property directly, \c activeTranslation + does not change, and \c translationChanged({0, 0}) is emitted. + + \note On some touchpads, such as on a \macos trackpad, native gestures do + not generate any translation values, and this property stays at \c (0, 0). +*/ + +void QQuickPinchHandler::setPersistentTranslation(const QPointF &trans) +{ + if (trans == persistentTranslation()) + return; + + m_xAxis.updateValue(m_xAxis.activeValue(), trans.x()); + m_yAxis.updateValue(m_yAxis.activeValue(), trans.y()); + emit translationChanged({}); +} + bool QQuickPinchHandler::wantsPointerEvent(QPointerEvent *event) { if (!QQuickMultiPointHandler::wantsPointerEvent(event)) @@ -221,7 +423,7 @@ bool QQuickPinchHandler::wantsPointerEvent(QPointerEvent *event) \c maximum is the maximum acceptable scale. If \c enabled is true, scaling is allowed. \c activeValue is the same as \l {QtQuick::PinchHandler::activeScale}. - \c persistentValue is the same as \l {QtQuick::PinchHandler::scale}. + \c persistentValue is the same as \l {QtQuick::PinchHandler::persistentScale}. The \c activeValueChanged signal is emitted when \c activeValue (and therefore \c persistentValue) changes, to provide the multiplier for the incremental change. @@ -249,8 +451,8 @@ bool QQuickPinchHandler::wantsPointerEvent(QPointerEvent *event) \c minimum is the minimum acceptable rotation. \c maximum is the maximum acceptable rotation. If \c enabled is true, rotation is allowed. - \c activeValue is the same as \l {QtQuick::PinchHandler::rotation}. - \c persistentValue holds the accumulated value across multiple gestures. + \c activeValue is the same as \l {QtQuick::PinchHandler::activeRotation}. + \c persistentValue is the same as \l {QtQuick::PinchHandler::persistentRotation}. The \c activeValueChanged signal is emitted when \c activeValue (and therefore \c persistentValue) changes, to provide the increment by which it changed. @@ -324,11 +526,10 @@ void QQuickPinchHandler::handlePointerEventImpl(QPointerEvent *event) emit updated(); return; case Qt::ZoomNativeGesture: - m_scaleAxis.updateValue(1 + gesture->value(), m_scaleAxis.m_startValue * (1 + gesture->value())); + setActiveScale(1 + gesture->value()); break; case Qt::RotateNativeGesture: - m_rotationAxis.updateValue(m_rotationAxis.m_activeValue + gesture->value(), - m_rotationAxis.m_startValue + m_rotationAxis.m_activeValue + gesture->value()); + setActiveRotation(m_rotationAxis.activeValue() + gesture->value()); break; default: // Nothing of interest (which is unexpected, because wantsPointerEvent() should have returned false) @@ -461,17 +662,14 @@ void QQuickPinchHandler::handlePointerEventImpl(QPointerEvent *event) activeScale = dist / m_startDistance; activeScale = qBound(m_scaleAxis.minimum() / m_scaleAxis.m_startValue, activeScale, m_scaleAxis.maximum() / m_scaleAxis.m_startValue); - m_scaleAxis.updateValue(activeScale, m_scaleAxis.m_startValue * activeScale, - activeScale / m_scaleAxis.activeValue()); + setActiveScale(activeScale); } // 2. rotate if (m_rotationAxis.enabled()) { QVector newAngles = angles(centroid().scenePosition()); const qreal angleDelta = averageAngleDelta(m_startAngles, newAngles); - m_rotationAxis.updateValue(m_rotationAxis.m_activeValue + angleDelta, - m_rotationAxis.m_startValue + m_rotationAxis.m_activeValue + angleDelta, - angleDelta); + setActiveRotation(m_rotationAxis.m_activeValue + angleDelta); m_startAngles = std::move(newAngles); } @@ -484,10 +682,10 @@ void QQuickPinchHandler::handlePointerEventImpl(QPointerEvent *event) const QPointF centroidParentPos = target()->parentItem()->mapFromScene(centroid().scenePosition()); // 3. Drag/translate const QPointF centroidStartParentPos = target()->parentItem()->mapFromScene(centroid().sceneGrabPosition()); - auto activeTranslation = QVector2D(centroidParentPos - centroidStartParentPos); + auto activeTranslation = centroidParentPos - centroidStartParentPos; // apply rotation + scaling around the centroid - then apply translation. QPointF pos = QQuickItemPrivate::get(target())->adjustedPosForTransform(centroidParentPos, - startPos(), activeTranslation, + startPos(), QVector2D(activeTranslation), m_scaleAxis.m_startValue, m_scaleAxis.persistentValue() / m_scaleAxis.m_startValue, m_rotationAxis.m_startValue, @@ -502,18 +700,22 @@ void QQuickPinchHandler::handlePointerEventImpl(QPointerEvent *event) else pos.ry() -= qreal(activeTranslation.y()); - m_xAxis.updateValue(activeTranslation.x(), pos.x(), activeTranslation.x() - m_xAxis.activeValue()); - m_yAxis.updateValue(activeTranslation.y(), pos.y(), activeTranslation.y() - m_yAxis.activeValue()); + const QVector2D delta(activeTranslation.x() - m_xAxis.activeValue(), + activeTranslation.y() - m_yAxis.activeValue()); + m_xAxis.updateValue(activeTranslation.x(), pos.x(), delta.x()); + m_yAxis.updateValue(activeTranslation.y(), pos.y(), delta.y()); + emit translationChanged(delta); target()->setPosition(QPointF(m_xAxis.persistentValue(), m_yAxis.persistentValue())); target()->setRotation(m_rotationAxis.persistentValue()); target()->setScale(m_scaleAxis.persistentValue()); } else { auto activeTranslation = centroid().scenePosition() - centroid().scenePressPosition(); auto accumulated = QPointF(m_xAxis.m_startValue, m_yAxis.m_startValue) + activeTranslation; - m_xAxis.updateValue(activeTranslation.x(), accumulated.x(), - activeTranslation.x() - m_xAxis.activeValue()); - m_yAxis.updateValue(activeTranslation.y(), accumulated.y(), - activeTranslation.y() - m_yAxis.activeValue()); + const QVector2D delta(activeTranslation.x() - m_xAxis.activeValue(), + activeTranslation.y() - m_yAxis.activeValue()); + m_xAxis.updateValue(activeTranslation.x(), accumulated.x(), delta.x()); + m_yAxis.updateValue(activeTranslation.y(), accumulated.y(), delta.y()); + emit translationChanged(delta); } qCDebug(lcPinchHandler) << "centroid" << centroid().scenePressPosition() << "->" << centroid().scenePosition() @@ -538,50 +740,6 @@ QPointF QQuickPinchHandler::startPos() The \l target will be rotated around this point. */ -/*! - \readonly - \qmlproperty real QtQuick::PinchHandler::scale - - The scale factor that will automatically be set on the \l target if it is not null. - Otherwise, bindings can be used to do arbitrary things with this value. - While the pinch gesture is being performed, it is continuously multiplied by - \l activeScale; after the gesture ends, it stays the same; and when the next - pinch gesture begins, it begins to be multiplied by activeScale again. -*/ - -/*! - \readonly - \qmlproperty real QtQuick::PinchHandler::activeScale - - The scale factor while the pinch gesture is being performed. - It is 1.0 when the gesture begins, increases as the touchpoints are spread - apart, and decreases as the touchpoints are brought together. - If \l target is not null, its \l {Item::scale}{scale} will be automatically - multiplied by this value. - Otherwise, bindings can be used to do arbitrary things with this value. -*/ - -/*! - \readonly - \qmlproperty real QtQuick::PinchHandler::rotation - - The rotation of the pinch gesture in degrees, with positive values clockwise. - It is 0 when the gesture begins. If \l target is not null, this will be - automatically applied to its \l {Item::rotation}{rotation}. Otherwise, - bindings can be used to do arbitrary things with this value. -*/ - -/*! - \readonly - \qmlproperty QVector2D QtQuick::PinchHandler::translation - - The translation of the gesture \l centroid. It is \c (0, 0) when the - gesture begins. - - \note On some touchpads, such as on a \macos trackpad, native gestures do - not generate any translation values, and this property stays at \c (0, 0). -*/ - QT_END_NAMESPACE #include "moc_qquickpinchhandler_p.cpp" diff --git a/src/quick/handlers/qquickpinchhandler_p.h b/src/quick/handlers/qquickpinchhandler_p.h index e788b490eb..c8fa6988b4 100644 --- a/src/quick/handlers/qquickpinchhandler_p.h +++ b/src/quick/handlers/qquickpinchhandler_p.h @@ -28,45 +28,73 @@ using namespace Qt::StringLiterals; class Q_QUICK_PRIVATE_EXPORT QQuickPinchHandler : public QQuickMultiPointHandler { Q_OBJECT + + Q_PROPERTY(QQuickDragAxis *scaleAxis READ scaleAxis CONSTANT) Q_PROPERTY(qreal minimumScale READ minimumScale WRITE setMinimumScale NOTIFY minimumScaleChanged) Q_PROPERTY(qreal maximumScale READ maximumScale WRITE setMaximumScale NOTIFY maximumScaleChanged) +#if QT_DEPRECATED_SINCE(6, 5) + Q_PROPERTY(qreal scale READ scale NOTIFY updated) +#endif + Q_PROPERTY(qreal activeScale READ activeScale NOTIFY scaleChanged) + Q_PROPERTY(qreal persistentScale READ persistentScale WRITE setPersistentScale NOTIFY scaleChanged) + + Q_PROPERTY(QQuickDragAxis *rotationAxis READ rotationAxis CONSTANT) Q_PROPERTY(qreal minimumRotation READ minimumRotation WRITE setMinimumRotation NOTIFY minimumRotationChanged) Q_PROPERTY(qreal maximumRotation READ maximumRotation WRITE setMaximumRotation NOTIFY maximumRotationChanged) - Q_PROPERTY(qreal scale READ scale NOTIFY updated) - Q_PROPERTY(qreal activeScale READ activeScale NOTIFY updated) +#if QT_DEPRECATED_SINCE(6, 5) Q_PROPERTY(qreal rotation READ rotation NOTIFY updated) - Q_PROPERTY(QVector2D translation READ translation NOTIFY updated) +#endif + Q_PROPERTY(qreal activeRotation READ activeRotation NOTIFY rotationChanged) + Q_PROPERTY(qreal persistentRotation READ persistentRotation WRITE setPersistentRotation NOTIFY rotationChanged) + Q_PROPERTY(QQuickDragAxis * xAxis READ xAxis CONSTANT) Q_PROPERTY(QQuickDragAxis * yAxis READ yAxis CONSTANT) - Q_PROPERTY(QQuickDragAxis * scaleAxis READ scaleAxis CONSTANT) - Q_PROPERTY(QQuickDragAxis * rotationAxis READ rotationAxis CONSTANT) +#if QT_DEPRECATED_SINCE(6, 5) + Q_PROPERTY(QVector2D translation READ translation NOTIFY updated) +#endif + Q_PROPERTY(QPointF activeTranslation READ activeTranslation NOTIFY translationChanged REVISION(6, 5)) + Q_PROPERTY(QPointF persistentTranslation READ persistentTranslation WRITE setPersistentTranslation NOTIFY translationChanged REVISION(6, 5)) + QML_NAMED_ELEMENT(PinchHandler) QML_ADDED_IN_VERSION(2, 12) public: explicit QQuickPinchHandler(QQuickItem *parent = nullptr); - qreal minimumScale() const { return m_scaleAxis.minimum(); } - void setMinimumScale(qreal minimumScale); - - qreal maximumScale() const { return m_scaleAxis.maximum(); } - void setMaximumScale(qreal maximumScale); - - qreal minimumRotation() const { return m_rotationAxis.minimum(); } - void setMinimumRotation(qreal minimumRotation); - - qreal maximumRotation() const { return m_rotationAxis.maximum(); } - void setMaximumRotation(qreal maximumRotation); - - QVector2D translation() const { return QVector2D(QPointF(m_xAxis.activeValue(), m_yAxis.activeValue())); } - qreal scale() const { return m_scaleAxis.m_accumulatedValue; } - qreal activeScale() const { return m_scaleAxis.m_activeValue; } - qreal rotation() const { return m_rotationAxis.m_accumulatedValue; } - QQuickDragAxis *xAxis() { return &m_xAxis; } QQuickDragAxis *yAxis() { return &m_yAxis; } +#if QT_DEPRECATED_SINCE(6, 5) + QVector2D translation() const { return QVector2D(activeTranslation()); } +#endif + QPointF activeTranslation() const { return QPointF(m_xAxis.activeValue(), m_yAxis.activeValue()); } + QPointF persistentTranslation() const { return QPointF(m_xAxis.persistentValue(), m_yAxis.persistentValue()); } + void setPersistentTranslation(const QPointF &trans); + QQuickDragAxis *scaleAxis() { return &m_scaleAxis; } + qreal minimumScale() const { return m_scaleAxis.minimum(); } + void setMinimumScale(qreal minimumScale); + qreal maximumScale() const { return m_scaleAxis.maximum(); } + void setMaximumScale(qreal maximumScale); +#if QT_DEPRECATED_SINCE(6, 5) + qreal scale() const { return persistentScale(); } +#endif + qreal activeScale() const { return m_scaleAxis.activeValue(); } + void setActiveScale(qreal scale); + qreal persistentScale() const { return m_scaleAxis.persistentValue(); } + void setPersistentScale(qreal scale); + QQuickDragAxis *rotationAxis() { return &m_rotationAxis; } + qreal minimumRotation() const { return m_rotationAxis.minimum(); } + void setMinimumRotation(qreal minimumRotation); + qreal maximumRotation() const { return m_rotationAxis.maximum(); } + void setMaximumRotation(qreal maximumRotation); +#if QT_DEPRECATED_SINCE(6, 5) + qreal rotation() const { return activeRotation(); } +#endif + qreal activeRotation() const { return m_rotationAxis.activeValue(); } + void setActiveRotation(qreal rot); + qreal persistentRotation() const { return m_rotationAxis.persistentValue(); } + void setPersistentRotation(qreal rot); Q_SIGNALS: void minimumScaleChanged(); @@ -74,6 +102,9 @@ Q_SIGNALS: void minimumRotationChanged(); void maximumRotationChanged(); void updated(); + Q_REVISION(6, 5) void scaleChanged(qreal delta); + Q_REVISION(6, 5) void rotationChanged(qreal delta); + Q_REVISION(6, 5) void translationChanged(QVector2D delta); protected: bool wantsPointerEvent(QPointerEvent *event) override; diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp index 7a0206c04f..05b764029a 100644 --- a/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp +++ b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp @@ -273,7 +273,7 @@ void tst_FlickableInterop::touchDragSlider() QQuickFlickable *flickable = window->rootObject()->findChild(); QVERIFY(flickable); QSignalSpy tappedSpy(knob->parent(), SIGNAL(tapped())); - QSignalSpy translationChangedSpy(drag, SIGNAL(translationChanged())); + QSignalSpy translationChangedSpy(drag, &QQuickDragHandler::translationChanged); // Drag the slider in the allowed (vertical) direction tappedSpy.clear(); @@ -353,7 +353,7 @@ void tst_FlickableInterop::mouseDragSlider() QQuickFlickable *flickable = window->rootObject()->findChild(); QVERIFY(flickable); QSignalSpy tappedSpy(knob->parent(), SIGNAL(tapped())); - QSignalSpy translationChangedSpy(drag, SIGNAL(translationChanged())); + QSignalSpy translationChangedSpy(drag, &QQuickDragHandler::translationChanged); // Drag the slider tappedSpy.clear(); @@ -411,7 +411,7 @@ void tst_FlickableInterop::touchDragFlickableBehindSlider() QQuickFlickable *flickable = window->rootObject()->findChild(); QVERIFY(flickable); QSignalSpy tappedSpy(knob->parent(), SIGNAL(tapped())); - QSignalSpy translationChangedSpy(drag, SIGNAL(translationChanged())); + QSignalSpy translationChangedSpy(drag, &QQuickDragHandler::translationChanged); // Button is no longer pressed if touchpoint goes beyond dragThreshold, // because Flickable steals the grab @@ -457,7 +457,7 @@ void tst_FlickableInterop::mouseDragFlickableBehindSlider() QQuickFlickable *flickable = window->rootObject()->findChild(); QVERIFY(flickable); QSignalSpy tappedSpy(knob->parent(), SIGNAL(tapped())); - QSignalSpy translationChangedSpy(drag, SIGNAL(translationChanged())); + QSignalSpy translationChangedSpy(drag, &QQuickDragHandler::translationChanged); // Button is no longer pressed if touchpoint goes beyond dragThreshold, // because Flickable steals the grab diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp index 8c56594b11..0fa547e424 100644 --- a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp +++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp @@ -141,7 +141,7 @@ void tst_DragHandler::touchDrag() dragHandler->setDragThreshold(dragThreshold); } - QSignalSpy translationChangedSpy(dragHandler, SIGNAL(translationChanged())); + QSignalSpy translationChangedSpy(dragHandler, &QQuickDragHandler::translationChanged); QSignalSpy centroidChangedSpy(dragHandler, SIGNAL(centroidChanged())); QSignalSpy xDeltaSpy(dragHandler->xAxis(), &QQuickDragAxis::activeValueChanged); @@ -189,6 +189,8 @@ void tst_DragHandler::touchDrag() QCOMPARE(dragHandler->activeTranslation().x(), dragThreshold + 20); QCOMPARE(dragHandler->persistentTranslation().y(), 0); QCOMPARE(dragHandler->activeTranslation().y(), 0); + QCOMPARE(translationChangedSpy.size(), 1); + QCOMPARE(translationChangedSpy.first().first().value(), QVector2D(dragThreshold + 20, 0)); QVERIFY(dragHandler->centroid().velocity().x() > 0); QCOMPARE(centroidChangedSpy.size(), 4); QTest::touchEvent(window, touchDevice).release(1, p1, window); @@ -285,7 +287,7 @@ void tst_DragHandler::mouseDrag() QVERIFY(dragHandler); dragHandler->setAcceptedButtons(acceptedButtons); // QTBUG-76875 - QSignalSpy translationChangedSpy(dragHandler, SIGNAL(translationChanged())); + QSignalSpy translationChangedSpy(dragHandler, &QQuickDragHandler::translationChanged); QSignalSpy centroidChangedSpy(dragHandler, SIGNAL(centroidChanged())); QSignalSpy xDeltaSpy(dragHandler->xAxis(), &QQuickDragAxis::activeValueChanged); @@ -352,9 +354,11 @@ void tst_DragHandler::mouseDrag() QTest::mouseRelease(window, static_cast(int(dragButton)), Qt::NoModifier, p1); QTRY_VERIFY(!dragHandler->active()); QCOMPARE(dragHandler->centroid().pressedButtons(), Qt::NoButton); - if (shouldDrag) - QCOMPARE(ball->mapToScene(ballCenter).toPoint(), p1); QCOMPARE(translationChangedSpy.size(), shouldDrag ? 1 : 0); + if (shouldDrag) { + QCOMPARE(ball->mapToScene(ballCenter).toPoint(), p1); + QCOMPARE(translationChangedSpy.first().first().value(), QVector2D(dragThreshold + 20, 0)); + } QCOMPARE(xDeltaSpy.size(), shouldDrag ? 1 : 0); QCOMPARE(centroidChangedSpy.size(), shouldDrag ? 5 : 0); #if QT_CONFIG(cursor) @@ -390,7 +394,7 @@ void tst_DragHandler::mouseDragThreshold() dragHandler->setDragThreshold(dragThreshold); } - QSignalSpy translationChangedSpy(dragHandler, SIGNAL(translationChanged())); + QSignalSpy translationChangedSpy(dragHandler, &QQuickDragHandler::translationChanged); QSignalSpy centroidChangedSpy(dragHandler, SIGNAL(centroidChanged())); QSignalSpy xDeltaSpy(dragHandler->xAxis(), &QQuickDragAxis::activeValueChanged); @@ -416,6 +420,8 @@ void tst_DragHandler::mouseDragThreshold() QTest::mouseMove(window, p1); QTRY_VERIFY(dragHandler->active()); QCOMPARE(translationChangedSpy.size(), dragThreshold ? 0 : 1); + if (!dragThreshold) + QCOMPARE(translationChangedSpy.first().first().value(), QVector2D(2, 0)); QCOMPARE(xDeltaSpy.size(), dragThreshold ? 0 : 1); QCOMPARE(centroidChangedSpy.size(), 3); #if QT_DEPRECATED_SINCE(6, 2) @@ -442,6 +448,9 @@ QT_WARNING_POP #endif QCOMPARE(dragHandler->activeTranslation().x(), dragThreshold + (dragThreshold ? 20 : 21)); QCOMPARE(dragHandler->activeTranslation().y(), 0.0); + QCOMPARE(translationChangedSpy.size(), dragThreshold ? 1 : 2); + QCOMPARE(translationChangedSpy.first().first().value(), + QVector2D(dragThreshold ? dragThreshold + 20 : 2, 0)); QVERIFY(dragHandler->centroid().velocity().x() > 0); QCOMPARE(centroidChangedSpy.size(), 4); QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1); @@ -586,7 +595,7 @@ void tst_DragHandler::touchDragMulti() QVERIFY(ball1); QQuickDragHandler *dragHandler1 = ball1->findChild(); QVERIFY(dragHandler1); - QSignalSpy translationChangedSpy1(dragHandler1, SIGNAL(translationChanged())); + QSignalSpy translationChangedSpy1(dragHandler1, &QQuickDragHandler::translationChanged); QSignalSpy centroidChangedSpy1(dragHandler1, SIGNAL(centroidChanged())); QSignalSpy xDeltaSpy1(dragHandler1->xAxis(), &QQuickDragAxis::activeValueChanged); @@ -594,7 +603,7 @@ void tst_DragHandler::touchDragMulti() QVERIFY(ball2); QQuickDragHandler *dragHandler2 = ball2->findChild(); QVERIFY(dragHandler2); - QSignalSpy translationChangedSpy2(dragHandler2, SIGNAL(translationChanged())); + QSignalSpy translationChangedSpy2(dragHandler2, &QQuickDragHandler::translationChanged); QSignalSpy centroidChangedSpy2(dragHandler1, SIGNAL(centroidChanged())); QSignalSpy yDeltaSpy2(dragHandler2->yAxis(), &QQuickDragAxis::activeValueChanged); @@ -702,6 +711,10 @@ QT_WARNING_POP QCOMPARE(xDeltaSpy1.first().first().toReal(), dragThreshold + 20); QCOMPARE(yDeltaSpy2.size(), 1); QCOMPARE(yDeltaSpy2.first().first().toReal(), dragThreshold + 20); + QCOMPARE(translationChangedSpy1.size(), 1); + QCOMPARE(translationChangedSpy1.first().first().value(), QVector2D(dragThreshold + 20, 0)); + QCOMPARE(translationChangedSpy2.size(), 1); + QCOMPARE(translationChangedSpy2.first().first().value(), QVector2D(0, dragThreshold + 20)); touchSeq.release(1, p1, window).stationary(2).commit(); QQuickTouchUtils::flush(window); QTRY_VERIFY(!dragHandler1->active()); diff --git a/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp b/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp index 28484b33a8..340ab4b184 100644 --- a/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp +++ b/tests/auto/quick/pointerhandlers/qquickpinchhandler/tst_qquickpinchhandler.cpp @@ -225,6 +225,7 @@ void tst_QQuickPinchHandler::scale() QQuickItem *blackRect = (hasTarget ? pinchHandler->target() : pinchHandler->parentItem()); QVERIFY(blackRect != nullptr); QSignalSpy grabChangedSpy(pinchHandler, SIGNAL(grabChanged(QPointingDevice::GrabTransition, QEventPoint))); + QSignalSpy scaleChangedSpy(pinchHandler, &QQuickPinchHandler::scaleChanged); if (lcPointerTests().isDebugEnabled()) QTest::qWait(500); QPoint p0(80, 80); @@ -263,6 +264,7 @@ void tst_QQuickPinchHandler::scale() // move the same point even further and observe the change in scale for (int i = 0; i < 2; ++i) { + qreal lastScale = pinchHandler->activeScale(); p1 += pd; pinchSequence.stationary(0).move(1, p1, &window).commit(); QQuickTouchUtils::flush(&window); @@ -270,13 +272,18 @@ void tst_QQuickPinchHandler::scale() line.setP2(p1); qreal expectedScale = line.length() / startLength; qCDebug(lcPointerTests) << "pinchScale" << root->property("pinchScale").toReal() - << "expected" << expectedScale << "; target scale" << blackRect->scale(); + << "expected" << expectedScale << "; target scale" << blackRect->scale() + << "increments" << scaleChangedSpy.size() + << "multiplier" << scaleChangedSpy.last().first().toReal(); QVERIFY(qFloatDistance(root->property("pinchScale").toReal(), expectedScale) < 10); QVERIFY(qFloatDistance(blackRect->scale(), expectedScale) < 10); QCOMPARE(pinchHandler->scale(), root->property("pinchScale").toReal()); QCOMPARE(pinchHandler->scale(), pinchHandler->activeScale()); // in sync for the first gesture QCOMPARE(pinchHandler->scaleAxis()->persistentValue(), pinchHandler->activeScale()); QCOMPARE(pinchHandler->scaleAxis()->activeValue(), pinchHandler->activeScale()); + const qreal expectedIncrement = pinchHandler->activeScale() / lastScale; + QCOMPARE(scaleChangedSpy.size(), i + 1); + QCOMPARE(scaleChangedSpy.last().first().toReal(), expectedIncrement); QPointF expectedCentroid = p0 + (p1 - p0) / 2; QCOMPARE(pinchHandler->centroid().scenePosition(), expectedCentroid); } @@ -315,15 +322,21 @@ void tst_QQuickPinchHandler::scale() line.setP2(p1); qreal expectedActiveScale = line.length() / startLength; qCDebug(lcPointerTests) << i << "activeScale" << pinchHandler->activeScale() - << "expected" << expectedActiveScale << "; scale" << pinchHandler->scale(); + << "expected" << expectedActiveScale << "; scale" << pinchHandler->scale() + << "increments" << scaleChangedSpy.size() + << "multiplier" << scaleChangedSpy.last().first().toReal(); QVERIFY(qFloatDistance(pinchHandler->activeScale(), expectedActiveScale) < 10); QCOMPARE(pinchHandler->scale(), root->property("pinchScale").toReal()); QCOMPARE(pinchHandler->scaleAxis()->persistentValue(), root->property("pinchScale").toReal()); QCOMPARE_NE(pinchHandler->scale(), pinchHandler->activeScale()); // not in sync anymore QCOMPARE(pinchHandler->scaleAxis()->activeValue(), pinchHandler->activeScale()); + const qreal expectedIncrement = pinchHandler->scale() / lastScale; + QCOMPARE(scaleChangedSpy.size(), i + 3); + QCOMPARE(scaleChangedSpy.last().first().toReal(), expectedIncrement); } // scale beyond maximumScale + lastScale = pinchHandler->activeScale(); p1 = QPoint(310, 310); pinchSequence.stationary(0).move(1, p1, &window).commit(); QQuickTouchUtils::flush(&window); @@ -331,6 +344,9 @@ void tst_QQuickPinchHandler::scale() QCOMPARE(blackRect->scale(), qreal(4)); QCOMPARE(pinchHandler->scale(), qreal(4)); // limited by maximumScale QCOMPARE(pinchHandler->scaleAxis()->persistentValue(), 4); + const qreal expectedIncrement = pinchHandler->activeScale() / lastScale; + QCOMPARE(scaleChangedSpy.size(), 5); + QCOMPARE(scaleChangedSpy.last().first().toReal(), expectedIncrement); pinchSequence.release(0, p0, &window).release(1, p1, &window).commit(); QQuickTouchUtils::flush(&window); QCOMPARE(pinchHandler->active(), false); @@ -530,6 +546,7 @@ void tst_QQuickPinchHandler::pan() QQuickPinchHandler *pinchHandler = window->rootObject()->findChild("pinchHandler"); QVERIFY(pinchHandler != nullptr); + QSignalSpy translationChangedSpy(pinchHandler, &QQuickPinchHandler::translationChanged); QQuickItem *root = qobject_cast(window->rootObject()); QVERIFY(root != nullptr); @@ -578,6 +595,8 @@ void tst_QQuickPinchHandler::pan() // blackrect starts at 50,50 QCOMPARE(blackRect->x(), 50.0); QCOMPARE(blackRect->y(), 50.0); + QCOMPARE(translationChangedSpy.size(), 1); + QCOMPARE(translationChangedSpy.first().first().value(), QVector2D(0, 0)); p0 += QPoint(10, 0); p1 += QPoint(10, 0); @@ -586,6 +605,8 @@ void tst_QQuickPinchHandler::pan() QCOMPARE(pinchHandler->centroid().scenePosition(), QPointF(90 + dragThreshold + 11, 90)); QCOMPARE(blackRect->x(), 60.0); QCOMPARE(blackRect->y(), 50.0); + QCOMPARE(translationChangedSpy.size(), 2); + QCOMPARE(translationChangedSpy.last().first().value(), QVector2D(10, 0)); p0 += QPoint(0, 10); p1 += QPoint(0, 10); @@ -594,6 +615,8 @@ void tst_QQuickPinchHandler::pan() QCOMPARE(pinchHandler->centroid().scenePosition(), QPointF(90 + dragThreshold + 11, 90 + 10)); QCOMPARE(blackRect->x(), 60.0); QCOMPARE(blackRect->y(), 60.0); + QCOMPARE(translationChangedSpy.size(), 3); + QCOMPARE(translationChangedSpy.last().first().value(), QVector2D(0, 10)); p0 += QPoint(10, 10); p1 += QPoint(10, 10); @@ -603,6 +626,8 @@ void tst_QQuickPinchHandler::pan() QCOMPARE(pinchHandler->centroid().scenePosition(), QPointF(90 + dragThreshold + 21, 90 + 20)); QCOMPARE(blackRect->x(), 70.0); QCOMPARE(blackRect->y(), 70.0); + QCOMPARE(translationChangedSpy.size(), 4); + QCOMPARE(translationChangedSpy.last().first().value(), QVector2D(10, 10)); } // pan x beyond bound @@ -613,6 +638,8 @@ void tst_QQuickPinchHandler::pan() QCOMPARE(blackRect->x(), 140.0); QCOMPARE(blackRect->y(), 170.0); + QCOMPARE(translationChangedSpy.size(), 5); + QCOMPARE(translationChangedSpy.last().first().value(), QVector2D(100, 100)); QTest::touchEvent(window, touchscreen).release(0, p0, window).release(1, p1, window); QQuickTouchUtils::flush(window);