Port of QTimeLine to new property system

The six properties duration, updateInterval, currentTime,
direction, loopCount and easingCurve have been ported to the
new property system and are now bindable.
Drive-by renamed a local variable to avoid shadowing.

Task-number: QTBUG-85520
Change-Id: Ibabf106f5200d2dd4329a1e1f96112eccc29d6b1
Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
bb10
Andreas Buhr 2020-12-07 11:13:17 +01:00
parent 6ec3fa2842
commit 6a3cc36e4a
4 changed files with 398 additions and 60 deletions

View File

@ -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;
Q_OBJECT_BINDABLE_PROPERTY_WITH_ARGS(QTimeLinePrivate, QEasingCurve, easingCurve,
QEasingCurve::InOutSine)
int startTime;
int duration;
int startFrame;
int endFrame;
int updateInterval;
int totalLoopCount;
int currentLoopCount;
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;
int currentTime;
int timerId;
void setCurrentTimeForwardToQ(int time) { q_func()->setCurrentTime(time); }
Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QTimeLinePrivate, int, currentTime,
&QTimeLinePrivate::setCurrentTimeForwardToQ, 0)
int timerId = 0;
QTimeLine::Direction direction;
QTimeLine::State state;
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()

View File

@ -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;

View File

@ -7,4 +7,6 @@
qt_internal_add_test(tst_qtimeline
SOURCES
tst_qtimeline.cpp
LIBRARIES
Qt::TestPrivate
)

View File

@ -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);
@ -406,15 +613,39 @@ void tst_QTimeLine::reverse()
}
void tst_QTimeLine::toggleDirection()
{
QTimeLine timeLine;
QCOMPARE(timeLine.direction(), QTimeLine::Forward);
timeLine.toggleDirection();
QCOMPARE(timeLine.direction(), QTimeLine::Backward);
timeLine.toggleDirection();
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;
QCOMPARE(int(timeLine.direction()), int(QTimeLine::Forward));
timeLine.toggleDirection();
QCOMPARE(int(timeLine.direction()), int(QTimeLine::Backward));
timeLine.toggleDirection();
QCOMPARE(int(timeLine.direction()), int(QTimeLine::Forward));
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"