summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/tools/qtimeline.cpp140
-rw-r--r--src/corelib/tools/qtimeline.h20
-rw-r--r--tests/auto/corelib/tools/qtimeline/CMakeLists.txt2
-rw-r--r--tests/auto/corelib/tools/qtimeline/tst_qtimeline.cpp302
4 files changed, 401 insertions, 63 deletions
diff --git a/src/corelib/tools/qtimeline.cpp b/src/corelib/tools/qtimeline.cpp
index 4609b258fc..8a01dbe685 100644
--- a/src/corelib/tools/qtimeline.cpp
+++ b/src/corelib/tools/qtimeline.cpp
@@ -39,6 +39,7 @@
#include "qtimeline.h"
+#include <private/qproperty_p.h>
#include <private/qobject_p.h>
#include <QtCore/qcoreevent.h>
#include <QtCore/qmath.h>
@@ -50,31 +51,29 @@ class QTimeLinePrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QTimeLine)
public:
- inline QTimeLinePrivate()
- : easingCurve(QEasingCurve::InOutSine),
- startTime(0), duration(1000), startFrame(0), endFrame(0),
- updateInterval(1000 / 25),
- totalLoopCount(1), currentLoopCount(0), currentTime(0), timerId(0),
- direction(QTimeLine::Forward),
- state(QTimeLine::NotRunning)
- { }
-
QElapsedTimer timer;
- QEasingCurve easingCurve;
-
- int startTime;
- int duration;
- int startFrame;
- int endFrame;
- int updateInterval;
- int totalLoopCount;
- int currentLoopCount;
-
- int currentTime;
- int timerId;
-
- QTimeLine::Direction direction;
- QTimeLine::State state;
+ Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(QTimeLinePrivate, QEasingCurve, easingCurve,
+ QEasingCurve::InOutSine)
+
+ int startTime = 0;
+ void setDuration(int duration) { q_func()->setDuration(duration); }
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QTimeLinePrivate, int, duration,
+ &QTimeLinePrivate::setDuration, 1000)
+ int startFrame = 0;
+ int endFrame = 0;
+ Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(QTimeLinePrivate, int, updateInterval, 1000 / 25)
+ Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(QTimeLinePrivate, int, loopCount, 1)
+ int currentLoopCount = 0;
+
+ void setCurrentTimeForwardToQ(int time) { q_func()->setCurrentTime(time); }
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QTimeLinePrivate, int, currentTime,
+ &QTimeLinePrivate::setCurrentTimeForwardToQ, 0)
+ int timerId = 0;
+
+ void setDirection(QTimeLine::Direction direction) { q_func()->setDirection(direction); }
+ Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QTimeLinePrivate, QTimeLine::Direction, direction,
+ &QTimeLinePrivate::setDirection, QTimeLine::Forward)
+ QTimeLine::State state = QTimeLine::NotRunning;
inline void setState(QTimeLine::State newState)
{
Q_Q(QTimeLine);
@@ -91,34 +90,35 @@ public:
void QTimeLinePrivate::setCurrentTime(int msecs)
{
Q_Q(QTimeLine);
+ currentTime.removeBindingUnlessInWrapper();
+ auto previousCurrentTime = currentTime.value();
qreal lastValue = q->currentValue();
int lastFrame = q->currentFrame();
// Determine if we are looping.
int elapsed = (direction == QTimeLine::Backward) ? (-msecs + duration) : msecs;
- int loopCount = elapsed / duration;
+ int loopCountNow = elapsed / duration;
- bool looping = (loopCount != currentLoopCount);
+ bool looping = (loopCountNow != currentLoopCount);
#ifdef QTIMELINE_DEBUG
- qDebug() << "QTimeLinePrivate::setCurrentTime:" << msecs << duration << "with loopCount" << loopCount
- << "currentLoopCount" << currentLoopCount
- << "looping" << looping;
+ qDebug() << "QTimeLinePrivate::setCurrentTime:" << msecs << duration << "with loopCountNow"
+ << loopCountNow << "currentLoopCount" << currentLoopCount << "looping" << looping;
#endif
if (looping)
- currentLoopCount = loopCount;
+ currentLoopCount = loopCountNow;
// Normalize msecs to be between 0 and duration, inclusive.
- currentTime = elapsed % duration;
- if (direction == QTimeLine::Backward)
- currentTime = duration - currentTime;
+ currentTime.setValueBypassingBindings(elapsed % duration);
+ if (direction.value() == QTimeLine::Backward)
+ currentTime.setValueBypassingBindings(duration - currentTime);
// Check if we have reached the end of loopcount.
bool finished = false;
- if (totalLoopCount && currentLoopCount >= totalLoopCount) {
+ if (loopCount && currentLoopCount >= loopCount) {
finished = true;
- currentTime = (direction == QTimeLine::Backward) ? 0 : duration;
- currentLoopCount = totalLoopCount - 1;
+ currentTime.setValueBypassingBindings((direction == QTimeLine::Backward) ? 0 : duration);
+ currentLoopCount = loopCount - 1;
}
int currentFrame = q->frameForTime(currentTime);
@@ -159,6 +159,13 @@ void QTimeLinePrivate::setCurrentTime(int msecs)
q->stop();
emit q->finished(QTimeLine::QPrivateSignal());
}
+ if (currentTime.value() != previousCurrentTime)
+ currentTime.notify();
+}
+QBindable<int> QTimeLine::bindableCurrentTime()
+{
+ Q_D(QTimeLine);
+ return &d->currentTime;
}
/*!
@@ -326,12 +333,19 @@ QTimeLine::State QTimeLine::state() const
int QTimeLine::loopCount() const
{
Q_D(const QTimeLine);
- return d->totalLoopCount;
+ return d->loopCount;
}
+
void QTimeLine::setLoopCount(int count)
{
Q_D(QTimeLine);
- d->totalLoopCount = count;
+ d->loopCount = count;
+}
+
+QBindable<int> QTimeLine::bindableLoopCount()
+{
+ Q_D(QTimeLine);
+ return &d->loopCount;
}
/*!
@@ -343,6 +357,9 @@ void QTimeLine::setLoopCount(int count)
timeline duration, or from the value of the duration and towards 0 after
start() has been called.
+ Any binding of direction will be removed not only by setDirection(),
+ but also by toggleDirection().
+
By default, this property is set to \l Forward.
*/
QTimeLine::Direction QTimeLine::direction() const
@@ -353,9 +370,18 @@ QTimeLine::Direction QTimeLine::direction() const
void QTimeLine::setDirection(Direction direction)
{
Q_D(QTimeLine);
- d->direction = direction;
+ auto previousDirection = d->direction.value();
+ d->direction.setValue(direction);
d->startTime = d->currentTime;
d->timer.start();
+ if (previousDirection != d->direction.value())
+ d->direction.notify();
+}
+
+QBindable<QTimeLine::Direction> QTimeLine::bindableDirection()
+{
+ Q_D(QTimeLine);
+ return &d->direction;
}
/*!
@@ -382,7 +408,18 @@ void QTimeLine::setDuration(int duration)
qWarning("QTimeLine::setDuration: cannot set duration <= 0");
return;
}
- d->duration = duration;
+ if (duration == d->duration) {
+ d->duration.removeBindingUnlessInWrapper();
+ return;
+ }
+ d->duration.setValue(duration);
+ d->duration.notify();
+}
+
+QBindable<int> QTimeLine::bindableDuration()
+{
+ Q_D(QTimeLine);
+ return &d->duration;
}
/*!
@@ -472,6 +509,11 @@ void QTimeLine::setUpdateInterval(int interval)
Q_D(QTimeLine);
d->updateInterval = interval;
}
+QBindable<int> QTimeLine::bindableUpdateInterval()
+{
+ Q_D(QTimeLine);
+ return &d->updateInterval;
+}
/*!
\property QTimeLine::easingCurve
@@ -496,6 +538,12 @@ void QTimeLine::setEasingCurve(const QEasingCurve &curve)
d->easingCurve = curve;
}
+QBindable<QEasingCurve> QTimeLine::bindableEasingCurve()
+{
+ Q_D(QTimeLine);
+ return &d->easingCurve;
+}
+
/*!
\property QTimeLine::currentTime
\brief the current time of the time line.
@@ -505,6 +553,10 @@ void QTimeLine::setEasingCurve(const QEasingCurve &curve)
value that was current when stop() was called last, or the value set by
setCurrentTime().
+ \note You can bind other properties to currentTime, but it is not
+ recommended setting bindings to it. As animation progresses, the currentTime
+ is updated automatically, which cancels its bindings.
+
By default, this property contains a value of 0.
*/
int QTimeLine::currentTime() const
@@ -571,10 +623,10 @@ int QTimeLine::frameForTime(int msec) const
qreal QTimeLine::valueForTime(int msec) const
{
Q_D(const QTimeLine);
- msec = qMin(qMax(msec, 0), d->duration);
+ msec = qBound(0, msec, d->duration.value());
- qreal value = msec / qreal(d->duration);
- return d->easingCurve.valueForProgress(value);
+ qreal value = msec / qreal(d->duration.value());
+ return d->easingCurve.value().valueForProgress(value);
}
/*!
@@ -678,6 +730,8 @@ void QTimeLine::setPaused(bool paused)
Toggles the direction of the timeline. If the direction was Forward, it
becomes Backward, and vice verca.
+ Existing bindings of \l direction are removed.
+
\sa setDirection()
*/
void QTimeLine::toggleDirection()
diff --git a/src/corelib/tools/qtimeline.h b/src/corelib/tools/qtimeline.h
index 193c372c6a..48a06f06df 100644
--- a/src/corelib/tools/qtimeline.h
+++ b/src/corelib/tools/qtimeline.h
@@ -54,12 +54,14 @@ class QTimeLinePrivate;
class Q_CORE_EXPORT QTimeLine : public QObject
{
Q_OBJECT
- Q_PROPERTY(int duration READ duration WRITE setDuration)
- Q_PROPERTY(int updateInterval READ updateInterval WRITE setUpdateInterval)
- Q_PROPERTY(int currentTime READ currentTime WRITE setCurrentTime)
- Q_PROPERTY(Direction direction READ direction WRITE setDirection)
- Q_PROPERTY(int loopCount READ loopCount WRITE setLoopCount)
- Q_PROPERTY(QEasingCurve easingCurve READ easingCurve WRITE setEasingCurve)
+ Q_PROPERTY(int duration READ duration WRITE setDuration BINDABLE bindableDuration)
+ Q_PROPERTY(int updateInterval READ updateInterval WRITE setUpdateInterval
+ BINDABLE bindableUpdateInterval)
+ Q_PROPERTY(int currentTime READ currentTime WRITE setCurrentTime BINDABLE bindableCurrentTime)
+ Q_PROPERTY(Direction direction READ direction WRITE setDirection BINDABLE bindableDirection)
+ Q_PROPERTY(int loopCount READ loopCount WRITE setLoopCount BINDABLE bindableLoopCount)
+ Q_PROPERTY(QEasingCurve easingCurve READ easingCurve WRITE setEasingCurve
+ BINDABLE bindableEasingCurve)
public:
enum State {
NotRunning,
@@ -78,12 +80,15 @@ public:
int loopCount() const;
void setLoopCount(int count);
+ QBindable<int> bindableLoopCount();
Direction direction() const;
void setDirection(Direction direction);
+ QBindable<Direction> bindableDirection();
int duration() const;
void setDuration(int duration);
+ QBindable<int> bindableDuration();
int startFrame() const;
void setStartFrame(int frame);
@@ -93,11 +98,14 @@ public:
int updateInterval() const;
void setUpdateInterval(int interval);
+ QBindable<int> bindableUpdateInterval();
QEasingCurve easingCurve() const;
void setEasingCurve(const QEasingCurve &curve);
+ QBindable<QEasingCurve> bindableEasingCurve();
int currentTime() const;
+ QBindable<int> bindableCurrentTime();
int currentFrame() const;
qreal currentValue() const;
diff --git a/tests/auto/corelib/tools/qtimeline/CMakeLists.txt b/tests/auto/corelib/tools/qtimeline/CMakeLists.txt
index de61529fd2..e3a24e9440 100644
--- a/tests/auto/corelib/tools/qtimeline/CMakeLists.txt
+++ b/tests/auto/corelib/tools/qtimeline/CMakeLists.txt
@@ -7,4 +7,6 @@
qt_internal_add_test(tst_qtimeline
SOURCES
tst_qtimeline.cpp
+ LIBRARIES
+ Qt::TestPrivate
)
diff --git a/tests/auto/corelib/tools/qtimeline/tst_qtimeline.cpp b/tests/auto/corelib/tools/qtimeline/tst_qtimeline.cpp
index 0869af31f7..1ea18d700c 100644
--- a/tests/auto/corelib/tools/qtimeline/tst_qtimeline.cpp
+++ b/tests/auto/corelib/tools/qtimeline/tst_qtimeline.cpp
@@ -27,6 +27,7 @@
****************************************************************************/
#include <QTest>
+#include <QtTest/private/qpropertytesthelper_p.h>
#include <QSignalSpy>
#include <qtimeline.h>
@@ -37,15 +38,20 @@ class tst_QTimeLine : public QObject
private slots:
void range();
void currentTime();
+ void bindableCurrentTime();
void duration();
+ void bindableDuration();
void frameRate();
+ void bindableUpdateInterval();
void value();
void currentFrame();
void loopCount();
+ void bindableLoopCount();
void interpolation();
void reverse_data();
void reverse();
void toggleDirection();
+ void bindableDirection();
void frameChanged();
void stopped();
void finished();
@@ -58,6 +64,7 @@ private slots:
void resume();
void restart();
void setPaused();
+ void automatedBindableTests();
protected slots:
void finishedSlot();
@@ -144,6 +151,55 @@ void tst_QTimeLine::currentTime()
timeLine.stop();
}
+void tst_QTimeLine::bindableCurrentTime()
+{
+ QTimeLine timeLine(2000);
+ QProperty<int> currentTimeObserver([&]() { return timeLine.currentTime(); });
+
+ timeLine.setUpdateInterval((timeLine.duration() / 2) / 33);
+ timeLine.setFrameRange(10, 20);
+ QCOMPARE(timeLine.currentTime(), 0);
+ QCOMPARE(currentTimeObserver.value(), 0);
+ QCOMPARE(currentTimeObserver.value(), timeLine.currentTime());
+
+ timeLine.start();
+ QTRY_COMPARE(timeLine.state(), QTimeLine::Running);
+ QCOMPARE(currentTimeObserver.value(), timeLine.currentTime());
+ QTRY_VERIFY(timeLine.currentTime() > timeLine.duration() / 2 - timeLine.duration() / 4);
+ QVERIFY(timeLine.currentTime() < timeLine.duration() / 2 + timeLine.duration() / 4);
+ QCOMPARE(currentTimeObserver.value(), timeLine.currentTime());
+
+ QTRY_COMPARE(timeLine.state(), QTimeLine::NotRunning);
+ QCOMPARE(timeLine.currentTime(), timeLine.duration());
+ QCOMPARE(currentTimeObserver.value(), timeLine.currentTime());
+
+ QSignalSpy spy(&timeLine, &QTimeLine::valueChanged);
+ QVERIFY(spy.isValid());
+ spy.clear();
+ QProperty<int> referenceCurrentTime(timeLine.duration() / 2);
+ timeLine.bindableCurrentTime().setBinding([&]() { return referenceCurrentTime.value(); });
+ QCOMPARE(spy.count(), 1);
+ // setting it a second time to check that valueChanged() is emitted only once
+ referenceCurrentTime = timeLine.duration() / 2;
+ QCOMPARE(spy.count(), 1);
+
+ spy.clear();
+ QCOMPARE(timeLine.currentTime(), timeLine.duration() / 2);
+ QCOMPARE(currentTimeObserver.value(), timeLine.duration() / 2);
+ timeLine.resume();
+ // Let it update on its own
+ QCOMPARE(timeLine.state(), QTimeLine::Running);
+ QTRY_VERIFY(currentTimeObserver.value() > timeLine.duration() / 2);
+ QVERIFY(currentTimeObserver.value() < timeLine.duration());
+ QTRY_COMPARE(timeLine.state(), QTimeLine::NotRunning);
+ QCOMPARE(currentTimeObserver.value(), timeLine.duration());
+ // the resume above should have broken the connection to referenceCurrentTime, check that:
+ spy.clear();
+ referenceCurrentTime = 0;
+ QCOMPARE(currentTimeObserver.value(), timeLine.duration());
+ QCOMPARE(spy.count(), 0);
+}
+
void tst_QTimeLine::duration()
{
QTimeLine timeLine(200);
@@ -161,6 +217,35 @@ void tst_QTimeLine::duration()
QCOMPARE(timeLine.duration(), 1000);
}
+void tst_QTimeLine::bindableDuration()
+{
+ QTimeLine timeLine(200);
+ QProperty<int> durationObserver;
+ durationObserver.setBinding([&]() { return timeLine.duration(); });
+ QCOMPARE(durationObserver.value(), timeLine.duration());
+
+ timeLine.setFrameRange(10, 20);
+ QCOMPARE(timeLine.duration(), 200);
+
+ QProperty<int> referenceDuration(500);
+ timeLine.bindableDuration().setBinding([&]() { return referenceDuration.value(); });
+ QCOMPARE(durationObserver.value(), referenceDuration.value());
+
+ QCOMPARE(timeLine.duration(), 500);
+
+ timeLine.start();
+ QTRY_COMPARE(timeLine.state(), QTimeLine::Running);
+ QTRY_VERIFY(timeLine.currentTime() > 0);
+ QTRY_COMPARE(timeLine.state(), QTimeLine::NotRunning);
+ QCOMPARE(timeLine.currentTime(), 500);
+ // The duration shouldn't change
+ QCOMPARE(timeLine.duration(), 500);
+
+ referenceDuration = 30;
+ QCOMPARE(timeLine.duration(), 30);
+ QCOMPARE(durationObserver.value(), 30);
+}
+
void tst_QTimeLine::frameRate()
{
QTimeLine timeLine;
@@ -188,6 +273,40 @@ void tst_QTimeLine::frameRate()
QVERIFY2(slowCount < spy.count(), QByteArray::number(spy.count()));
}
+void tst_QTimeLine::bindableUpdateInterval()
+{
+ QTimeLine timeLine;
+ timeLine.setFrameRange(100, 2000);
+
+ QProperty<int> updateIntervalObserver;
+ updateIntervalObserver.setBinding([&]() { return timeLine.updateInterval(); });
+
+ QCOMPARE(updateIntervalObserver.value(), 1000 / 25);
+ QProperty<int> updateIntervalReference(1000 / 60);
+ timeLine.bindableUpdateInterval().setBinding([&]() { return updateIntervalReference.value(); });
+
+ updateIntervalReference = 1000 / 60;
+ QCOMPARE(updateIntervalObserver.value(), 1000 / 60);
+
+ // Default speed
+ updateIntervalReference = 1000 / 33;
+ QSignalSpy spy(&timeLine, &QTimeLine::frameChanged);
+ QVERIFY(spy.isValid());
+ timeLine.start();
+ QTest::qWait(timeLine.duration() * 2);
+ QCOMPARE(timeLine.state(), QTimeLine::NotRunning);
+ int slowCount = spy.count();
+
+ // Faster!!
+ updateIntervalReference = 1000 / 100;
+ spy.clear();
+ timeLine.setCurrentTime(0);
+ timeLine.start();
+ QTest::qWait(timeLine.duration() * 2);
+ QCOMPARE(timeLine.state(), QTimeLine::NotRunning);
+ QVERIFY2(slowCount < spy.count(), QByteArray::number(spy.count()));
+}
+
void tst_QTimeLine::value()
{
QTimeLine timeLine(4500); // Should be at least 5% under 5000ms
@@ -249,7 +368,7 @@ void tst_QTimeLine::loopCount()
timeLine.setLoopCount(0);
QCOMPARE(timeLine.loopCount(), 0);
- // Default speed infiniti looping
+ // Default speed endless looping
QSignalSpy spy(&timeLine, &QTimeLine::frameChanged);
QVERIFY(spy.isValid());
timeLine.start();
@@ -264,7 +383,7 @@ void tst_QTimeLine::loopCount()
QCOMPARE(timeLine.state(), QTimeLine::Running);
timeLine.stop();
- timeLine.setDuration(2500); // ### some platforms have a very low resolution timer
+ timeLine.setDuration(2500); // some platforms have a very low resolution timer
timeLine.setFrameRange(0, 2);
timeLine.setLoopCount(4);
@@ -279,8 +398,8 @@ void tst_QTimeLine::loopCount()
for(int i=0;i<2;i++) {
timeLine.start();
- //we clear te list after the start so we don't catch
- //a frameChanged signal for the frame 0 at the beginning
+ // we clear the list after the start so we don't catch
+ // a frameChanged signal for the frame 0 at the beginning
finishedSpy.clear();
frameChangedSpy.clear();
@@ -288,9 +407,8 @@ void tst_QTimeLine::loopCount()
QCOMPARE(finishedSpy.count(), 1);
QCOMPARE(frameChangedSpy.count(), 11);
- for (int i = 0; i < 11; ++i) {
+ for (int i = 0; i < 11; ++i)
QCOMPARE(frameChangedSpy.at(i).at(0).toInt(), (i+1) % 3);
- }
}
timeLine.setDirection(QTimeLine::Backward);
@@ -304,16 +422,101 @@ void tst_QTimeLine::loopCount()
}
}
+void tst_QTimeLine::bindableLoopCount()
+{
+ QTimeLine timeLine(200);
+ QProperty<int> referenceLoopCount(1);
+ timeLine.bindableLoopCount().setBinding([&]() { return referenceLoopCount.value(); });
+ QProperty<int> loopCountObserver([&]() { return timeLine.loopCount(); });
+
+ QCOMPARE(referenceLoopCount.value(), 1);
+ QCOMPARE(timeLine.loopCount(), 1);
+ QCOMPARE(loopCountObserver.value(), 1);
+
+ timeLine.setFrameRange(10, 20);
+
+ QCOMPARE(referenceLoopCount.value(), 1);
+ QCOMPARE(timeLine.loopCount(), 1);
+ QCOMPARE(loopCountObserver.value(), 1);
+
+ referenceLoopCount = 0;
+
+ QCOMPARE(referenceLoopCount.value(), 0);
+ QCOMPARE(timeLine.loopCount(), 0);
+ QCOMPARE(loopCountObserver.value(), 0);
+
+ // Default speed endless looping
+ QSignalSpy spy(&timeLine, &QTimeLine::frameChanged);
+ QVERIFY(spy.isValid());
+ timeLine.start();
+ QTest::qWait(timeLine.duration());
+ QCOMPARE(timeLine.state(), QTimeLine::Running);
+ // QCOMPARE(timeLine.currentFrame(), 20);
+ QTest::qWait(timeLine.duration() * 6);
+ QCOMPARE(timeLine.state(), QTimeLine::Running);
+ QVERIFY(timeLine.currentTime() >= 0);
+ QVERIFY(timeLine.currentFrame() >= 10);
+ QVERIFY(timeLine.currentFrame() <= 20);
+ QCOMPARE(timeLine.state(), QTimeLine::Running);
+ timeLine.stop();
+
+ timeLine.setDuration(2500); // some platforms have a very low resolution timer
+ timeLine.setFrameRange(0, 2);
+ referenceLoopCount = 4;
+
+ QSignalSpy finishedSpy(&timeLine, &QTimeLine::finished);
+ QSignalSpy frameChangedSpy(&timeLine, &QTimeLine::frameChanged);
+ QVERIFY(finishedSpy.isValid());
+ QVERIFY(frameChangedSpy.isValid());
+ QEventLoop loop;
+ connect(&timeLine, SIGNAL(finished()), &loop, SLOT(quit()));
+
+ for (int i = 0; i < 2; i++) {
+
+ timeLine.start();
+ // we clear the list after the start so we don't catch
+ // a frameChanged signal for the frame 0 at the beginning
+ finishedSpy.clear();
+ frameChangedSpy.clear();
+
+ loop.exec();
+
+ QCOMPARE(finishedSpy.count(), 1);
+ QCOMPARE(frameChangedSpy.count(), 11);
+ for (int i = 0; i < 11; ++i)
+ QCOMPARE(frameChangedSpy.at(i).at(0).toInt(), (i + 1) % 3);
+ }
+
+ timeLine.setDirection(QTimeLine::Backward);
+ timeLine.start();
+ loop.exec();
+
+ QCOMPARE(finishedSpy.count(), 2);
+ QCOMPARE(frameChangedSpy.count(), 22);
+ for (int i = 11; i < 22; ++i)
+ QCOMPARE(frameChangedSpy.at(i).at(0).toInt(), 2 - (i + 2) % 3);
+}
+
void tst_QTimeLine::interpolation()
{
+ // also tests bindableEasingCurve
QTimeLine timeLine(400);
+ QProperty<QEasingCurve> easingCurveObserver([&]() { return timeLine.easingCurve(); });
+
QCOMPARE(timeLine.easingCurve(), QEasingCurve::InOutSine);
+ QCOMPARE(easingCurveObserver.value(), QEasingCurve::InOutSine);
+
timeLine.setFrameRange(100, 200);
- timeLine.setEasingCurve(QEasingCurve::Linear);
+ QProperty<QEasingCurve> referenceEasingCurve(QEasingCurve::Linear);
+ timeLine.bindableEasingCurve().setBinding([&]() { return referenceEasingCurve.value(); });
QCOMPARE(timeLine.easingCurve(), QEasingCurve::Linear);
+ QCOMPARE(easingCurveObserver.value(), QEasingCurve::Linear);
// smooth
- timeLine.setEasingCurve(QEasingCurve::InOutSine);
+ referenceEasingCurve = QEasingCurve::InOutSine;
+ QCOMPARE(timeLine.easingCurve(), QEasingCurve::InOutSine);
+ QCOMPARE(easingCurveObserver.value(), QEasingCurve::InOutSine);
+
timeLine.start();
QTest::qWait(100);
QCOMPARE(timeLine.state(), QTimeLine::Running);
@@ -324,7 +527,11 @@ void tst_QTimeLine::interpolation()
timeLine.setCurrentTime(0);
// linear
- timeLine.setEasingCurve(QEasingCurve::Linear);
+ referenceEasingCurve = QEasingCurve::Linear;
+
+ QCOMPARE(timeLine.easingCurve(), QEasingCurve::Linear);
+ QCOMPARE(easingCurveObserver.value(), QEasingCurve::Linear);
+
timeLine.start();
QTest::qWait(100);
QCOMPARE(timeLine.state(), QTimeLine::Running);
@@ -407,14 +614,38 @@ void tst_QTimeLine::reverse()
void tst_QTimeLine::toggleDirection()
{
- // Note: enum values are cast to int so that QCOMPARE will show
- // the values if they don't match.
QTimeLine timeLine;
- QCOMPARE(int(timeLine.direction()), int(QTimeLine::Forward));
+ QCOMPARE(timeLine.direction(), QTimeLine::Forward);
timeLine.toggleDirection();
- QCOMPARE(int(timeLine.direction()), int(QTimeLine::Backward));
+ QCOMPARE(timeLine.direction(), QTimeLine::Backward);
timeLine.toggleDirection();
- QCOMPARE(int(timeLine.direction()), int(QTimeLine::Forward));
+ QCOMPARE(timeLine.direction(), QTimeLine::Forward);
+}
+
+void tst_QTimeLine::bindableDirection()
+{
+ // Note: enum values are cast to int so that QCOMPARE will show
+ // the values if they don't match.
+ QTimeLine timeLine;
+ QProperty<QTimeLine::Direction> directionObserver([&]() { return timeLine.direction(); });
+ QProperty<QTimeLine::Direction> referenceDirection(QTimeLine::Forward);
+ timeLine.bindableDirection().setBinding([&]() { return referenceDirection.value(); });
+
+ QCOMPARE(referenceDirection.value(), QTimeLine::Forward);
+ QCOMPARE(timeLine.direction(), QTimeLine::Forward);
+ QCOMPARE(directionObserver.value(), QTimeLine::Forward);
+
+ referenceDirection = QTimeLine::Backward;
+
+ QCOMPARE(referenceDirection.value(), QTimeLine::Backward);
+ QCOMPARE(timeLine.direction(), QTimeLine::Backward);
+ QCOMPARE(directionObserver.value(), QTimeLine::Backward);
+
+ referenceDirection = QTimeLine::Forward;
+
+ QCOMPARE(referenceDirection.value(), QTimeLine::Forward);
+ QCOMPARE(timeLine.direction(), QTimeLine::Forward);
+ QCOMPARE(directionObserver.value(), QTimeLine::Forward);
}
void tst_QTimeLine::frameChanged()
@@ -660,6 +891,49 @@ void tst_QTimeLine::setPaused()
}
}
+void tst_QTimeLine::automatedBindableTests()
+{
+ QTimeLine timeLine(200);
+
+ QTestPrivate::testReadWritePropertyBasics(timeLine, 1000, 2000, "duration");
+ if (QTest::currentTestFailed()) {
+ qDebug() << "Failed property test for duration";
+ return;
+ }
+
+ QTestPrivate::testReadWritePropertyBasics(timeLine, 10, 20, "updateInterval");
+ if (QTest::currentTestFailed()) {
+ qDebug() << "Failed property test for updateInterval";
+ return;
+ }
+
+ QTestPrivate::testReadWritePropertyBasics(timeLine, 10, 20, "currentTime");
+ if (QTest::currentTestFailed()) {
+ qDebug() << "Failed property test for currentTime";
+ return;
+ }
+
+ QTestPrivate::testReadWritePropertyBasics(timeLine, QTimeLine::Forward, QTimeLine::Backward,
+ "direction");
+ if (QTest::currentTestFailed()) {
+ qDebug() << "Failed property test for direction";
+ return;
+ }
+
+ QTestPrivate::testReadWritePropertyBasics(timeLine, 4, 5, "loopCount");
+ if (QTest::currentTestFailed()) {
+ qDebug() << "Failed property test for loopCount";
+ return;
+ }
+
+ QTestPrivate::testReadWritePropertyBasics<QTimeLine, QEasingCurve>(
+ timeLine, QEasingCurve::InQuad, QEasingCurve::OutQuad, "easingCurve");
+ if (QTest::currentTestFailed()) {
+ qDebug() << "Failed property test for easingCurve";
+ return;
+ }
+}
+
QTEST_MAIN(tst_QTimeLine)
#include "tst_qtimeline.moc"