From 92dff998b3bf73ee0ad9d636454379869318975f Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Wed, 12 Dec 2018 21:45:03 +0100 Subject: Expose the target value in Behaviors So that nested animation can use it. Change-Id: Ief40cda1dfe1ad9a38cf0d18fbf34456dc36e2ee Reviewed-by: Simon Hausmann --- src/quick/util/qquickbehavior.cpp | 24 +++++++++-- src/quick/util/qquickbehavior_p.h | 4 ++ src/quick/util/qquickutilmodule.cpp | 2 + .../qquickbehaviors/data/ItemWithInnerBehavior.qml | 1 + tests/auto/quick/qquickbehaviors/data/aliased.qml | 1 + tests/auto/quick/qquickbehaviors/data/oneway.qml | 20 +++++++++ .../auto/quick/qquickbehaviors/qquickbehaviors.pro | 2 +- .../quick/qquickbehaviors/tst_qquickbehaviors.cpp | 49 ++++++++++++++++++++++ 8 files changed, 98 insertions(+), 5 deletions(-) create mode 100644 tests/auto/quick/qquickbehaviors/data/oneway.qml diff --git a/src/quick/util/qquickbehavior.cpp b/src/quick/util/qquickbehavior.cpp index d024c0099b..76d464e7f8 100644 --- a/src/quick/util/qquickbehavior.cpp +++ b/src/quick/util/qquickbehavior.cpp @@ -171,9 +171,28 @@ void QQuickBehavior::setEnabled(bool enabled) emit enabledChanged(); } +/*! + \qmlproperty Variant QtQuick::Behavior::targetValue + + This property holds the target value of the property being controlled by the Behavior. + This value is set by the Behavior before the animation is started. + + \since QtQuick 2.13 +*/ +QVariant QQuickBehavior::targetValue() const +{ + Q_D(const QQuickBehavior); + return d->targetValue; +} + void QQuickBehavior::write(const QVariant &value) { Q_D(QQuickBehavior); + const bool targetValueHasChanged = d->targetValue != value; + if (targetValueHasChanged) { + d->targetValue = value; + emit targetValueChanged(); // emitting the signal here should allow + } // d->enabled to change if scripted by the user. bool bypass = !d->enabled || !d->finalized || QQmlEnginePrivate::designerMode(); if (!bypass) qmlExecuteDeferred(this); @@ -181,16 +200,13 @@ void QQuickBehavior::write(const QVariant &value) if (d->animationInstance) d->animationInstance->stop(); QQmlPropertyPrivate::write(d->property, value, QQmlPropertyData::BypassInterceptor | QQmlPropertyData::DontRemoveBinding); - d->targetValue = value; return; } bool behaviorActive = d->animation->isRunning(); - if (behaviorActive && value == d->targetValue) + if (behaviorActive && !targetValueHasChanged) return; - d->targetValue = value; - if (d->animationInstance && (d->animationInstance->duration() != -1 || d->animationInstance->isRenderThreadProxy()) diff --git a/src/quick/util/qquickbehavior_p.h b/src/quick/util/qquickbehavior_p.h index f939597d15..80a51d77af 100644 --- a/src/quick/util/qquickbehavior_p.h +++ b/src/quick/util/qquickbehavior_p.h @@ -69,6 +69,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickBehavior : public QObject, public QQmlPropert Q_CLASSINFO("DefaultProperty", "animation") Q_PROPERTY(QQuickAbstractAnimation *animation READ animation WRITE setAnimation) Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) + Q_PROPERTY(QVariant targetValue READ targetValue NOTIFY targetValueChanged REVISION 13) Q_CLASSINFO("DeferredPropertyNames", "animation") public: @@ -84,8 +85,11 @@ public: bool enabled() const; void setEnabled(bool enabled); + QVariant targetValue() const; + Q_SIGNALS: void enabledChanged(); + void targetValueChanged(); private Q_SLOTS: void componentFinalized(); diff --git a/src/quick/util/qquickutilmodule.cpp b/src/quick/util/qquickutilmodule.cpp index 31d4d4c437..5147ebc6f6 100644 --- a/src/quick/util/qquickutilmodule.cpp +++ b/src/quick/util/qquickutilmodule.cpp @@ -135,4 +135,6 @@ void QQuickUtilModule::defineModule() qmlRegisterUncreatableType("QtQuick", 2, 12, "Animation", QQuickAbstractAnimation::tr("Animation is an abstract class")); + // 5.13 + qmlRegisterType("QtQuick", 2, 13, "Behavior"); } diff --git a/tests/auto/quick/qquickbehaviors/data/ItemWithInnerBehavior.qml b/tests/auto/quick/qquickbehaviors/data/ItemWithInnerBehavior.qml index 09983645ef..0ac7f87c42 100644 --- a/tests/auto/quick/qquickbehaviors/data/ItemWithInnerBehavior.qml +++ b/tests/auto/quick/qquickbehaviors/data/ItemWithInnerBehavior.qml @@ -5,6 +5,7 @@ Item { property bool someValue Behavior on someValue { + objectName: "behavior" ScriptAction { script: { parent.behaviorTriggered = true }} } } diff --git a/tests/auto/quick/qquickbehaviors/data/aliased.qml b/tests/auto/quick/qquickbehaviors/data/aliased.qml index e65e035d83..1840cdd22e 100644 --- a/tests/auto/quick/qquickbehaviors/data/aliased.qml +++ b/tests/auto/quick/qquickbehaviors/data/aliased.qml @@ -17,6 +17,7 @@ Rectangle { anchors.fill: parent value: accelerating ? 400 : 0 Behavior on value { + objectName: "behavior" NumberAnimation { duration: 500 } diff --git a/tests/auto/quick/qquickbehaviors/data/oneway.qml b/tests/auto/quick/qquickbehaviors/data/oneway.qml new file mode 100644 index 0000000000..0b438b80f6 --- /dev/null +++ b/tests/auto/quick/qquickbehaviors/data/oneway.qml @@ -0,0 +1,20 @@ +import QtQuick 2.0 +Rectangle { + width: 400 + height: 400 + Rectangle { + id: rect + objectName: "MyRectOneWay" + width: 100; height: 100; color: "green" + Behavior on x { + id: behavior + objectName: "MyBehaviorOneWay"; + enabled: (behavior.targetValue === 0) + NumberAnimation { + id: ani + objectName: "MyAnimationOneWay"; + duration: 200; + } + } + } +} diff --git a/tests/auto/quick/qquickbehaviors/qquickbehaviors.pro b/tests/auto/quick/qquickbehaviors/qquickbehaviors.pro index 51bc42c390..fd64eb1d40 100644 --- a/tests/auto/quick/qquickbehaviors/qquickbehaviors.pro +++ b/tests/auto/quick/qquickbehaviors/qquickbehaviors.pro @@ -7,5 +7,5 @@ include (../../shared/util.pri) macx:CONFIG -= app_bundle TESTDATA = data/* - +DISTFILES = $$files(data/*) QT += core-private gui-private qml-private quick-private testlib diff --git a/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp b/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp index fa9eba095d..6367f327da 100644 --- a/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp +++ b/tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp @@ -73,6 +73,7 @@ private slots: void disabledWriteWhileRunning(); void aliasedProperty(); void innerBehaviorOverwritten(); + void oneWay(); }; void tst_qquickbehaviors::simpleBehavior() @@ -516,6 +517,7 @@ void tst_qquickbehaviors::disabledWriteWhileRunning() myRect->setProperty("x", 200); QCOMPARE(myAnimation->isRunning(), true); QTRY_VERIFY(myRect->x() != qreal(0) && myRect->x() != qreal(200)); + QCOMPARE(myBehavior->targetValue(), 200); // grabbed before starting the animation // set disabled while animation is in progress myBehavior->setProperty("enabled", false); @@ -526,6 +528,7 @@ void tst_qquickbehaviors::disabledWriteWhileRunning() myRect->setProperty("x", 100); QCOMPARE(myAnimation->isRunning(), false); QCOMPARE(myRect->x(), qreal(100)); + QCOMPARE(myBehavior->targetValue(), 100); QTest::qWait(200); QCOMPARE(myRect->x(), qreal(100)); } @@ -546,17 +549,20 @@ void tst_qquickbehaviors::disabledWriteWhileRunning() // initial values QCOMPARE(myBehavior->enabled(), true); + QCOMPARE(myBehavior->targetValue(), QVariant()); QCOMPARE(myAnimation->isRunning(), false); QCOMPARE(myRect->x(), qreal(0)); // start animation myRect->setProperty("x", 200); QCOMPARE(myAnimation->isRunning(), true); + QCOMPARE(myBehavior->targetValue(), 200); QTRY_VERIFY(myRect->x() != qreal(0) && myRect->x() != qreal(200)); //set second value myRect->setProperty("x", 300); QCOMPARE(myAnimation->isRunning(), true); + QCOMPARE(myBehavior->targetValue(), 300); QTRY_VERIFY(myRect->x() != qreal(0) && myRect->x() != qreal(200)); // set disabled while animation is in progress @@ -568,6 +574,7 @@ void tst_qquickbehaviors::disabledWriteWhileRunning() myRect->setProperty("x", 100); QCOMPARE(myAnimation->isRunning(), false); QCOMPARE(myRect->x(), qreal(100)); + QCOMPARE(myBehavior->targetValue(), 100); QTest::qWait(200); QCOMPARE(myRect->x(), qreal(100)); } @@ -580,7 +587,12 @@ void tst_qquickbehaviors::aliasedProperty() QScopedPointer rect(qobject_cast(c.create())); QVERIFY2(!rect.isNull(), qPrintable(c.errorString())); + QQuickBehavior* behavior = + qobject_cast(rect->findChild("behavior")); + QSignalSpy targetValueSpy(behavior, SIGNAL(targetValueChanged())); QQuickItemPrivate::get(rect.data())->setState("moved"); + QCOMPARE(behavior->targetValue(), 400); + QCOMPARE(targetValueSpy.count(), 1); QScopedPointer acc(qobject_cast(rect->findChild("acc"))); QScopedPointer range(qobject_cast(acc->findChild("range"))); QTRY_VERIFY(acc->property("value").toDouble() > 0); @@ -595,7 +607,44 @@ void tst_qquickbehaviors::innerBehaviorOverwritten() QQmlEngine engine; QQmlComponent c(&engine, testFileUrl("overwrittenbehavior.qml")); QScopedPointer item(qobject_cast(c.create())); + QQuickBehavior* behavior = + qobject_cast(item->findChild("behavior")); QVERIFY(item->property("behaviorTriggered").toBool()); + QCOMPARE(behavior->targetValue(), true); +} + +void tst_qquickbehaviors::oneWay() +{ + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("oneway.qml")); + QScopedPointer rect(qobject_cast(c.create()));; + QVERIFY2(!rect.isNull(), qPrintable(c.errorString())); + QQuickBehavior* behavior = + qobject_cast(rect->findChild("MyBehaviorOneWay")); + QCOMPARE(behavior->enabled(), false); + QCOMPARE(behavior->targetValue(), QVariant()); + + QSignalSpy targetValueSpy(behavior, SIGNAL(targetValueChanged())); + QQuickRectangle *myRect = qobject_cast(rect->findChild("MyRectOneWay")); + myRect->setProperty("x", 100); + QCOMPARE(behavior->targetValue(), 100); + QCOMPARE(targetValueSpy.count(), 1); + QCOMPARE(behavior->enabled(), false); + qreal x = myRect->x(); + QCOMPARE(x, qreal(100)); //should change immediately + QQuickNumberAnimation *myAnimation = + qobject_cast(behavior->findChild("MyAnimationOneWay")); + QCOMPARE(myAnimation->isRunning(), false); + + myRect->setProperty("x", 0); + QCOMPARE(behavior->targetValue(), 0); + QCOMPARE(targetValueSpy.count(), 2); + QCOMPARE(behavior->enabled(), true); + QCOMPARE(myAnimation->isRunning(), true); + QVERIFY(myRect->x() > 0.0); + QTRY_VERIFY(myRect->x() < 100.0); + QTRY_COMPARE(myRect->x(), qreal(0)); + QCOMPARE(myAnimation->isRunning(), false); } QTEST_MAIN(tst_qquickbehaviors) -- cgit v1.2.3