diff options
-rw-r--r-- | src/corelib/tools/qtimeline.cpp | 140 | ||||
-rw-r--r-- | src/corelib/tools/qtimeline.h | 20 | ||||
-rw-r--r-- | tests/auto/corelib/tools/qtimeline/CMakeLists.txt | 2 | ||||
-rw-r--r-- | tests/auto/corelib/tools/qtimeline/tst_qtimeline.cpp | 302 |
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" |