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
parent
6ec3fa2842
commit
6a3cc36e4a
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,4 +7,6 @@
|
|||
qt_internal_add_test(tst_qtimeline
|
||||
SOURCES
|
||||
tst_qtimeline.cpp
|
||||
LIBRARIES
|
||||
Qt::TestPrivate
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Reference in New Issue