aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaolo Angelelli <paolo.angelelli@qt.io>2018-12-12 21:45:03 +0100
committerPaolo Angelelli <paolo.angelelli@qt.io>2018-12-21 19:33:19 +0000
commit92dff998b3bf73ee0ad9d636454379869318975f (patch)
tree0a74f43a415594af31352f540fa2496888f508e8
parentfd9d88e3a9f24eb84d029fb9324b4f03ae58ffeb (diff)
Expose the target value in Behaviors
So that nested animation can use it. Change-Id: Ief40cda1dfe1ad9a38cf0d18fbf34456dc36e2ee Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/quick/util/qquickbehavior.cpp24
-rw-r--r--src/quick/util/qquickbehavior_p.h4
-rw-r--r--src/quick/util/qquickutilmodule.cpp2
-rw-r--r--tests/auto/quick/qquickbehaviors/data/ItemWithInnerBehavior.qml1
-rw-r--r--tests/auto/quick/qquickbehaviors/data/aliased.qml1
-rw-r--r--tests/auto/quick/qquickbehaviors/data/oneway.qml20
-rw-r--r--tests/auto/quick/qquickbehaviors/qquickbehaviors.pro2
-rw-r--r--tests/auto/quick/qquickbehaviors/tst_qquickbehaviors.cpp49
8 files changed, 98 insertions, 5 deletions
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<QQuickAbstractAnimation, 12>("QtQuick", 2, 12, "Animation",
QQuickAbstractAnimation::tr("Animation is an abstract class"));
+ // 5.13
+ qmlRegisterType<QQuickBehavior, 13>("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<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));
QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
+ QQuickBehavior* behavior =
+ qobject_cast<QQuickBehavior*>(rect->findChild<QQuickBehavior*>("behavior"));
+ QSignalSpy targetValueSpy(behavior, SIGNAL(targetValueChanged()));
QQuickItemPrivate::get(rect.data())->setState("moved");
+ QCOMPARE(behavior->targetValue(), 400);
+ QCOMPARE(targetValueSpy.count(), 1);
QScopedPointer<QQuickRectangle> acc(qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("acc")));
QScopedPointer<QQuickRectangle> range(qobject_cast<QQuickRectangle*>(acc->findChild<QQuickRectangle*>("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<QQuickItem> item(qobject_cast<QQuickItem*>(c.create()));
+ QQuickBehavior* behavior =
+ qobject_cast<QQuickBehavior*>(item->findChild<QQuickBehavior*>("behavior"));
QVERIFY(item->property("behaviorTriggered").toBool());
+ QCOMPARE(behavior->targetValue(), true);
+}
+
+void tst_qquickbehaviors::oneWay()
+{
+ QQmlEngine engine;
+ QQmlComponent c(&engine, testFileUrl("oneway.qml"));
+ QScopedPointer<QQuickRectangle> rect(qobject_cast<QQuickRectangle*>(c.create()));;
+ QVERIFY2(!rect.isNull(), qPrintable(c.errorString()));
+ QQuickBehavior* behavior =
+ qobject_cast<QQuickBehavior*>(rect->findChild<QQuickBehavior*>("MyBehaviorOneWay"));
+ QCOMPARE(behavior->enabled(), false);
+ QCOMPARE(behavior->targetValue(), QVariant());
+
+ QSignalSpy targetValueSpy(behavior, SIGNAL(targetValueChanged()));
+ QQuickRectangle *myRect = qobject_cast<QQuickRectangle*>(rect->findChild<QQuickRectangle*>("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<QQuickNumberAnimation*>(behavior->findChild<QQuickNumberAnimation*>("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)