diff options
-rw-r--r-- | src/quick/items/qquickitem.h | 1 | ||||
-rw-r--r-- | src/quick/items/qquickstateoperations.cpp | 59 | ||||
-rw-r--r-- | tests/auto/quick/qquickstates/data/anchorRewind.qml | 31 | ||||
-rw-r--r-- | tests/auto/quick/qquickstates/tst_qquickstates.cpp | 24 |
4 files changed, 100 insertions, 15 deletions
diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h index 197d891b2a..2fdb0f00c8 100644 --- a/src/quick/items/qquickitem.h +++ b/src/quick/items/qquickitem.h @@ -477,6 +477,7 @@ private: friend class QSGRenderer; friend class QAccessibleQuickItem; friend class QQuickAccessibleAttached; + friend class QQuickAnchorChanges; Q_DISABLE_COPY(QQuickItem) Q_DECLARE_PRIVATE(QQuickItem) }; diff --git a/src/quick/items/qquickstateoperations.cpp b/src/quick/items/qquickstateoperations.cpp index d8380af756..719c682769 100644 --- a/src/quick/items/qquickstateoperations.cpp +++ b/src/quick/items/qquickstateoperations.cpp @@ -1094,6 +1094,7 @@ void QQuickAnchorChanges::reverse() QQuickAnchors::Anchors stateHAnchors = d->anchorSet->d_func()->usedAnchors & QQuickAnchors::Horizontal_Mask; QQuickAnchors::Anchors origHAnchors = targetPrivate->anchors()->usedAnchors() & QQuickAnchors::Horizontal_Mask; + const QRectF oldGeometry(d->target->position(), d->target->size()); bool stateSetWidth = (stateHAnchors && stateHAnchors != QQuickAnchors::LeftAnchor && stateHAnchors != QQuickAnchors::RightAnchor && @@ -1102,8 +1103,11 @@ void QQuickAnchorChanges::reverse() origHAnchors != QQuickAnchors::LeftAnchor && origHAnchors != QQuickAnchors::RightAnchor && origHAnchors != QQuickAnchors::HCenterAnchor); - if (d->origWidth.isValid() && stateSetWidth && !origSetWidth) - d->target->setWidth(d->origWidth.value); + if (d->origWidth.isValid() && stateSetWidth && !origSetWidth && !qt_is_nan(d->origWidth)) { + targetPrivate->widthValidFlag = true; + if (targetPrivate->width != d->origWidth) + targetPrivate->width.setValueBypassingBindings(d->origWidth); + } bool stateSetHeight = (stateVAnchors && stateVAnchors != QQuickAnchors::TopAnchor && @@ -1115,14 +1119,23 @@ void QQuickAnchorChanges::reverse() origVAnchors != QQuickAnchors::BottomAnchor && origVAnchors != QQuickAnchors::VCenterAnchor && origVAnchors != QQuickAnchors::BaselineAnchor); - if (d->origHeight.isValid() && stateSetHeight && !origSetHeight) - d->target->setHeight(d->origHeight.value); + if (d->origHeight.isValid() && stateSetHeight && !origSetHeight && !!qt_is_nan(d->origHeight)) { + targetPrivate->heightValidFlag = true; + if (targetPrivate->height != d->origHeight) + targetPrivate->height.setValueBypassingBindings(d->origHeight); + } + + if (stateHAnchors && !origHAnchors && !qt_is_nan(d->origX) && d->origX != targetPrivate->x) + targetPrivate->x.setValueBypassingBindings(d->origX); - if (stateHAnchors && !origHAnchors) - d->target->setX(d->origX); + if (stateVAnchors && !origVAnchors && !qt_is_nan(d->origY) && d->origY != targetPrivate->y) + targetPrivate->y.setValueBypassingBindings(d->origY); - if (stateVAnchors && !origVAnchors) - d->target->setY(d->origY); + const QRectF newGeometry(d->target->position(), d->target->size()); + if (newGeometry != oldGeometry) { + targetPrivate->dirty(QQuickItemPrivate::Position); + d->target->geometryChange(newGeometry, oldGeometry); + } } QQuickStateActionEvent::EventType QQuickAnchorChanges::type() const @@ -1316,15 +1329,31 @@ void QQuickAnchorChanges::rewind() return; QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(d->target); + const QRectF oldGeometry(d->target->position(), d->target->size()); + + // Restore previous values (but not previous bindings, i.e. anchors). + // Also, don't drop any new bindings. + if (!qt_is_nan(d->rewindX) && d->rewindX != targetPrivate->x) + targetPrivate->x.setValueBypassingBindings(d->rewindX); + if (!qt_is_nan(d->rewindY) && d->rewindY != targetPrivate->y) + targetPrivate->y.setValueBypassingBindings(d->rewindY); + + if (targetPrivate->widthValid() && !qt_is_nan(d->rewindWidth)) { + targetPrivate->widthValidFlag = true; + if (d->rewindWidth != targetPrivate->width) + targetPrivate->width.setValueBypassingBindings(d->rewindWidth); + } - //restore previous values (but not previous bindings, i.e. anchors) - d->target->setX(d->rewindX); - d->target->setY(d->rewindY); - if (targetPrivate->widthValid()) { - d->target->setWidth(d->rewindWidth); + if (targetPrivate->heightValid() && !qt_is_nan(d->rewindHeight)) { + targetPrivate->heightValidFlag = true; + if (d->rewindHeight != targetPrivate->height) + targetPrivate->height.setValueBypassingBindings(d->rewindHeight); } - if (targetPrivate->heightValid()) { - d->target->setHeight(d->rewindHeight); + + const QRectF newGeometry(d->target->position(), d->target->size()); + if (newGeometry != oldGeometry) { + targetPrivate->dirty(QQuickItemPrivate::Position); + d->target->geometryChange(newGeometry, oldGeometry); } } diff --git a/tests/auto/quick/qquickstates/data/anchorRewind.qml b/tests/auto/quick/qquickstates/data/anchorRewind.qml new file mode 100644 index 0000000000..740c94cf42 --- /dev/null +++ b/tests/auto/quick/qquickstates/data/anchorRewind.qml @@ -0,0 +1,31 @@ +import QtQuick + +Item { + width: 400 + height: 400 + Item { + id: outer + anchors.fill: parent + Item { + id: inner + width: parent.width / 2 + height: parent.height / 2 + anchors.left: parent.right + anchors.top: parent.bottom + } + states: [ + State { + when: true + AnchorChanges { + target: inner + anchors.left: outer.left + anchors.top: outer.top + } + } + ] + transitions: Transition { + AnchorAnimation {} + } + } +} + diff --git a/tests/auto/quick/qquickstates/tst_qquickstates.cpp b/tests/auto/quick/qquickstates/tst_qquickstates.cpp index 788b9c68ec..d6814bd057 100644 --- a/tests/auto/quick/qquickstates/tst_qquickstates.cpp +++ b/tests/auto/quick/qquickstates/tst_qquickstates.cpp @@ -206,6 +206,7 @@ private slots: void bindableProperties(); void parentChangeInvolvingBindings(); void deferredProperties(); + void rewindAnchorChange(); }; void tst_qquickstates::initTestCase() @@ -1954,6 +1955,29 @@ void tst_qquickstates::deferredProperties() QCOMPARE(root->height(), 100.0); } +void tst_qquickstates::rewindAnchorChange() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("anchorRewind.qml")); + QVERIFY2(c.isReady(), qPrintable(c.errorString())); + QScopedPointer<QObject> root(c.create()); + QVERIFY(root); + + QQmlContext *context = qmlContext(root.data()); + QVERIFY(context); + + QObject *inner = context->objectForName(QStringLiteral("inner")); + QVERIFY(inner); + + QQuickItem *innerRect = qobject_cast<QQuickItem *>(inner); + QVERIFY(innerRect); + + QTRY_COMPARE(innerRect->x(), 0); + QTRY_COMPARE(innerRect->y(), 0); + QTRY_COMPARE(innerRect->width(), 200); + QTRY_COMPARE(innerRect->height(), 200); +} + QTEST_MAIN(tst_qquickstates) #include "tst_qquickstates.moc" |