blob: a93d72755257d612e0b567d7a24111ad1f87e8a2 [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "private/qdeclarativetimeline_p_p.h"
#include <QDebug>
#include <QMutex>
#include <QThread>
#include <QWaitCondition>
#include <QEvent>
#include <QCoreApplication>
#include <QEasingCurve>
#include <QTime>
QT_BEGIN_NAMESPACE
struct Update {
Update(QDeclarativeTimeLineValue *_g, qreal _v)
: g(_g), v(_v) {}
Update(const QDeclarativeTimeLineCallback &_e)
: g(0), v(0), e(_e) {}
QDeclarativeTimeLineValue *g;
qreal v;
QDeclarativeTimeLineCallback e;
};
struct QDeclarativeTimeLinePrivate
{
QDeclarativeTimeLinePrivate(QDeclarativeTimeLine *);
struct Op {
enum Type {
Pause,
Set,
Move,
MoveBy,
Accel,
AccelDistance,
Execute
};
Op() {}
Op(Type t, int l, qreal v, qreal v2, int o,
const QDeclarativeTimeLineCallback &ev = QDeclarativeTimeLineCallback(), const QEasingCurve &es = QEasingCurve())
: type(t), length(l), value(v), value2(v2), order(o), event(ev),
easing(es) {}
Op(const Op &o)
: type(o.type), length(o.length), value(o.value), value2(o.value2),
order(o.order), event(o.event), easing(o.easing) {}
Op &operator=(const Op &o) {
type = o.type; length = o.length; value = o.value;
value2 = o.value2; order = o.order; event = o.event;
easing = o.easing;
return *this;
}
Type type;
int length;
qreal value;
qreal value2;
int order;
QDeclarativeTimeLineCallback event;
QEasingCurve easing;
};
struct TimeLine
{
TimeLine() : length(0), consumedOpLength(0), base(0.) {}
QList<Op> ops;
int length;
int consumedOpLength;
qreal base;
};
int length;
int syncPoint;
typedef QHash<QDeclarativeTimeLineObject *, TimeLine> Ops;
Ops ops;
QDeclarativeTimeLine *q;
void add(QDeclarativeTimeLineObject &, const Op &);
qreal value(const Op &op, int time, qreal base, bool *) const;
int advance(int);
bool clockRunning;
int prevTime;
int order;
QDeclarativeTimeLine::SyncMode syncMode;
int syncAdj;
QList<QPair<int, Update> > *updateQueue;
};
QDeclarativeTimeLinePrivate::QDeclarativeTimeLinePrivate(QDeclarativeTimeLine *parent)
: length(0), syncPoint(0), q(parent), clockRunning(false), prevTime(0), order(0), syncMode(QDeclarativeTimeLine::LocalSync), syncAdj(0), updateQueue(0)
{
}
void QDeclarativeTimeLinePrivate::add(QDeclarativeTimeLineObject &g, const Op &o)
{
if (g._t && g._t != q) {
qWarning() << "QDeclarativeTimeLine: Cannot modify a QDeclarativeTimeLineValue owned by"
<< "another timeline.";
return;
}
g._t = q;
Ops::Iterator iter = ops.find(&g);
if (iter == ops.end()) {
iter = ops.insert(&g, TimeLine());
if (syncPoint > 0)
q->pause(g, syncPoint);
}
if (!iter->ops.isEmpty() &&
o.type == Op::Pause &&
iter->ops.last().type == Op::Pause) {
iter->ops.last().length += o.length;
iter->length += o.length;
} else {
iter->ops.append(o);
iter->length += o.length;
}
if (iter->length > length)
length = iter->length;
if (!clockRunning) {
q->stop();
prevTime = 0;
clockRunning = true;
if (syncMode == QDeclarativeTimeLine::LocalSync) {
syncAdj = -1;
} else {
syncAdj = 0;
}
q->start();
/* q->tick(0);
if (syncMode == QDeclarativeTimeLine::LocalSync) {
syncAdj = -1;
} else {
syncAdj = 0;
}
*/
}
}
qreal QDeclarativeTimeLinePrivate::value(const Op &op, int time, qreal base, bool *changed) const
{
Q_ASSERT(time >= 0);
Q_ASSERT(time <= op.length);
*changed = true;
switch(op.type) {
case Op::Pause:
*changed = false;
return base;
case Op::Set:
return op.value;
case Op::Move:
if (time == 0) {
return base;
} else if (time == (op.length)) {
return op.value;
} else {
qreal delta = op.value - base;
qreal pTime = (qreal)(time) / (qreal)op.length;
if (op.easing.type() == QEasingCurve::Linear)
return base + delta * pTime;
else
return base + delta * op.easing.valueForProgress(pTime);
}
case Op::MoveBy:
if (time == 0) {
return base;
} else if (time == (op.length)) {
return base + op.value;
} else {
qreal delta = op.value;
qreal pTime = (qreal)(time) / (qreal)op.length;
if (op.easing.type() == QEasingCurve::Linear)
return base + delta * pTime;
else
return base + delta * op.easing.valueForProgress(pTime);
}
case Op::Accel:
if (time == 0) {
return base;
} else {
qreal t = (qreal)(time) / 1000.0f;
qreal delta = op.value * t + 0.5f * op.value2 * t * t;
return base + delta;
}
case Op::AccelDistance:
if (time == 0) {
return base;
} else if (time == (op.length)) {
return base + op.value2;
} else {
qreal t = (qreal)(time) / 1000.0f;
qreal accel = -1.0f * 1000.0f * op.value / (qreal)op.length;
qreal delta = op.value * t + 0.5f * accel * t * t;
return base + delta;
}
case Op::Execute:
op.event.d0(op.event.d1);
*changed = false;
return -1;
}
return base;
}
/*!
\internal
\class QDeclarativeTimeLine
\brief The QDeclarativeTimeLine class provides a timeline for controlling animations.
QDeclarativeTimeLine is similar to QTimeLine except:
\list
\i It updates QDeclarativeTimeLineValue instances directly, rather than maintaining a single
current value.
For example, the following animates a simple value over 200 milliseconds:
\code
QDeclarativeTimeLineValue v(<starting value>);
QDeclarativeTimeLine tl;
tl.move(v, 100., 200);
tl.start()
\endcode
If your program needs to know when values are changed, it can either
connect to the QDeclarativeTimeLine's updated() signal, or inherit from QDeclarativeTimeLineValue
and reimplement the QDeclarativeTimeLineValue::setValue() method.
\i Supports multiple QDeclarativeTimeLineValue, arbitrary start and end values and allows
animations to be strung together for more complex effects.
For example, the following animation moves the x and y coordinates of
an object from wherever they are to the position (100, 100) in 50
milliseconds and then further animates them to (100, 200) in 50
milliseconds:
\code
QDeclarativeTimeLineValue x(<starting value>);
QDeclarativeTimeLineValue y(<starting value>);
QDeclarativeTimeLine tl;
tl.start();
tl.move(x, 100., 50);
tl.move(y, 100., 50);
tl.move(y, 200., 50);
\endcode
\i All QDeclarativeTimeLine instances share a single, synchronized clock.
Actions scheduled within the same event loop tick are scheduled
synchronously against each other, regardless of the wall time between the
scheduling. Synchronized scheduling applies both to within the same
QDeclarativeTimeLine and across separate QDeclarativeTimeLine's within the same process.
\endlist
Currently easing functions are not supported.
*/
/*!
Construct a new QDeclarativeTimeLine with the specified \a parent.
*/
QDeclarativeTimeLine::QDeclarativeTimeLine(QObject *parent)
: QAbstractAnimation(parent)
{
d = new QDeclarativeTimeLinePrivate(this);
}
/*!
Destroys the time line. Any inprogress animations are canceled, but not
completed.
*/
QDeclarativeTimeLine::~QDeclarativeTimeLine()
{
for (QDeclarativeTimeLinePrivate::Ops::Iterator iter = d->ops.begin();
iter != d->ops.end();
++iter)
iter.key()->_t = 0;
delete d; d = 0;
}
/*!
\enum QDeclarativeTimeLine::SyncMode
*/
/*!
Return the timeline's synchronization mode.
*/
QDeclarativeTimeLine::SyncMode QDeclarativeTimeLine::syncMode() const
{
return d->syncMode;
}
/*!
Set the timeline's synchronization mode to \a syncMode.
*/
void QDeclarativeTimeLine::setSyncMode(SyncMode syncMode)
{
d->syncMode = syncMode;
}
/*!
Pause \a obj for \a time milliseconds.
*/
void QDeclarativeTimeLine::pause(QDeclarativeTimeLineObject &obj, int time)
{
if (time <= 0) return;
QDeclarativeTimeLinePrivate::Op op(QDeclarativeTimeLinePrivate::Op::Pause, time, 0., 0., d->order++);
d->add(obj, op);
}
/*!
Execute the \a event.
*/
void QDeclarativeTimeLine::callback(const QDeclarativeTimeLineCallback &callback)
{
QDeclarativeTimeLinePrivate::Op op(QDeclarativeTimeLinePrivate::Op::Execute, 0, 0, 0., d->order++, callback);
d->add(*callback.callbackObject(), op);
}
/*!
Set the \a value of \a timeLineValue.
*/
void QDeclarativeTimeLine::set(QDeclarativeTimeLineValue &timeLineValue, qreal value)
{
QDeclarativeTimeLinePrivate::Op op(QDeclarativeTimeLinePrivate::Op::Set, 0, value, 0., d->order++);
d->add(timeLineValue, op);
}
/*!
Decelerate \a timeLineValue from the starting \a velocity to zero at the
given \a acceleration rate. Although the \a acceleration is technically
a deceleration, it should always be positive. The QDeclarativeTimeLine will ensure
that the deceleration is in the opposite direction to the initial velocity.
*/
int QDeclarativeTimeLine::accel(QDeclarativeTimeLineValue &timeLineValue, qreal velocity, qreal acceleration)
{
if (acceleration == 0.0f)
return -1;
if ((velocity > 0.0f) == (acceleration > 0.0f))
acceleration = acceleration * -1.0f;
int time = static_cast<int>(-1000 * velocity / acceleration);
QDeclarativeTimeLinePrivate::Op op(QDeclarativeTimeLinePrivate::Op::Accel, time, velocity, acceleration, d->order++);
d->add(timeLineValue, op);
return time;
}
/*!
\overload
Decelerate \a timeLineValue from the starting \a velocity to zero at the
given \a acceleration rate over a maximum distance of maxDistance.
If necessary, QDeclarativeTimeLine will reduce the acceleration to ensure that the
entire operation does not require a move of more than \a maxDistance.
\a maxDistance should always be positive.
*/
int QDeclarativeTimeLine::accel(QDeclarativeTimeLineValue &timeLineValue, qreal velocity, qreal acceleration, qreal maxDistance)
{
if (maxDistance == 0.0f || acceleration == 0.0f)
return -1;
Q_ASSERT(acceleration > 0.0f && maxDistance > 0.0f);
qreal maxAccel = (velocity * velocity) / (2.0f * maxDistance);
if (maxAccel > acceleration)
acceleration = maxAccel;
if ((velocity > 0.0f) == (acceleration > 0.0f))
acceleration = acceleration * -1.0f;
int time = static_cast<int>(-1000 * velocity / acceleration);
QDeclarativeTimeLinePrivate::Op op(QDeclarativeTimeLinePrivate::Op::Accel, time, velocity, acceleration, d->order++);
d->add(timeLineValue, op);
return time;
}
/*!
Decelerate \a timeLineValue from the starting \a velocity to zero over the given
\a distance. This is like accel(), but the QDeclarativeTimeLine calculates the exact
deceleration to use.
\a distance should be positive.
*/
int QDeclarativeTimeLine::accelDistance(QDeclarativeTimeLineValue &timeLineValue, qreal velocity, qreal distance)
{
if (distance == 0.0f || velocity == 0.0f)
return -1;
Q_ASSERT((distance >= 0.0f) == (velocity >= 0.0f));
int time = static_cast<int>(1000 * (2.0f * distance) / velocity);
QDeclarativeTimeLinePrivate::Op op(QDeclarativeTimeLinePrivate::Op::AccelDistance, time, velocity, distance, d->order++);
d->add(timeLineValue, op);
return time;
}
/*!
Linearly change the \a timeLineValue from its current value to the given
\a destination value over \a time milliseconds.
*/
void QDeclarativeTimeLine::move(QDeclarativeTimeLineValue &timeLineValue, qreal destination, int time)
{
if (time <= 0) return;
QDeclarativeTimeLinePrivate::Op op(QDeclarativeTimeLinePrivate::Op::Move, time, destination, 0.0f, d->order++);
d->add(timeLineValue, op);
}
/*!
Change the \a timeLineValue from its current value to the given \a destination
value over \a time milliseconds using the \a easing curve.
*/
void QDeclarativeTimeLine::move(QDeclarativeTimeLineValue &timeLineValue, qreal destination, const QEasingCurve &easing, int time)
{
if (time <= 0) return;
QDeclarativeTimeLinePrivate::Op op(QDeclarativeTimeLinePrivate::Op::Move, time, destination, 0.0f, d->order++, QDeclarativeTimeLineCallback(), easing);
d->add(timeLineValue, op);
}
/*!
Linearly change the \a timeLineValue from its current value by the \a change amount
over \a time milliseconds.
*/
void QDeclarativeTimeLine::moveBy(QDeclarativeTimeLineValue &timeLineValue, qreal change, int time)
{
if (time <= 0) return;
QDeclarativeTimeLinePrivate::Op op(QDeclarativeTimeLinePrivate::Op::MoveBy, time, change, 0.0f, d->order++);
d->add(timeLineValue, op);
}
/*!
Change the \a timeLineValue from its current value by the \a change amount over
\a time milliseconds using the \a easing curve.
*/
void QDeclarativeTimeLine::moveBy(QDeclarativeTimeLineValue &timeLineValue, qreal change, const QEasingCurve &easing, int time)
{
if (time <= 0) return;
QDeclarativeTimeLinePrivate::Op op(QDeclarativeTimeLinePrivate::Op::MoveBy, time, change, 0.0f, d->order++, QDeclarativeTimeLineCallback(), easing);
d->add(timeLineValue, op);
}
/*!
Cancel (but don't complete) all scheduled actions for \a timeLineValue.
*/
void QDeclarativeTimeLine::reset(QDeclarativeTimeLineValue &timeLineValue)
{
if (!timeLineValue._t)
return;
if (timeLineValue._t != this) {
qWarning() << "QDeclarativeTimeLine: Cannot reset a QDeclarativeTimeLineValue owned by another timeline.";
return;
}
remove(&timeLineValue);
timeLineValue._t = 0;
}
int QDeclarativeTimeLine::duration() const
{
return -1;
}
/*!
Synchronize the end point of \a timeLineValue to the endpoint of \a syncTo
within this timeline.
Following operations on \a timeLineValue in this timeline will be scheduled after
all the currently scheduled actions on \a syncTo are complete. In
pseudo-code this is equivalent to:
\code
QDeclarativeTimeLine::pause(timeLineValue, min(0, length_of(syncTo) - length_of(timeLineValue)))
\endcode
*/
void QDeclarativeTimeLine::sync(QDeclarativeTimeLineValue &timeLineValue, QDeclarativeTimeLineValue &syncTo)
{
QDeclarativeTimeLinePrivate::Ops::Iterator iter = d->ops.find(&syncTo);
if (iter == d->ops.end())
return;
int length = iter->length;
iter = d->ops.find(&timeLineValue);
if (iter == d->ops.end()) {
pause(timeLineValue, length);
} else {
int glength = iter->length;
pause(timeLineValue, length - glength);
}
}
/*!
Synchronize the end point of \a timeLineValue to the endpoint of the longest
action cursrently scheduled in the timeline.
In pseudo-code, this is equivalent to:
\code
QDeclarativeTimeLine::pause(timeLineValue, length_of(timeline) - length_of(timeLineValue))
\endcode
*/
void QDeclarativeTimeLine::sync(QDeclarativeTimeLineValue &timeLineValue)
{
QDeclarativeTimeLinePrivate::Ops::Iterator iter = d->ops.find(&timeLineValue);
if (iter == d->ops.end()) {
pause(timeLineValue, d->length);
} else {
pause(timeLineValue, d->length - iter->length);
}
}
/*
Synchronize all currently and future scheduled values in this timeline to
the longest action currently scheduled.
For example:
\code
value1->setValue(0.);
value2->setValue(0.);
value3->setValue(0.);
QDeclarativeTimeLine tl;
...
tl.move(value1, 10, 200);
tl.move(value2, 10, 100);
tl.sync();
tl.move(value2, 20, 100);
tl.move(value3, 20, 100);
\endcode
will result in:
\table
\header \o \o 0ms \o 50ms \o 100ms \o 150ms \o 200ms \o 250ms \o 300ms
\row \o value1 \o 0 \o 2.5 \o 5.0 \o 7.5 \o 10 \o 10 \o 10
\row \o value2 \o 0 \o 5.0 \o 10.0 \o 10.0 \o 10.0 \o 15.0 \o 20.0
\row \o value2 \o 0 \o 0 \o 0 \o 0 \o 0 \o 10.0 \o 20.0
\endtable
*/
/*void QDeclarativeTimeLine::sync()
{
for (QDeclarativeTimeLinePrivate::Ops::Iterator iter = d->ops.begin();
iter != d->ops.end();
++iter)
pause(*iter.key(), d->length - iter->length);
d->syncPoint = d->length;
}*/
/*!
\internal
Temporary hack.
*/
void QDeclarativeTimeLine::setSyncPoint(int sp)
{
d->syncPoint = sp;
}
/*!
\internal
Temporary hack.
*/
int QDeclarativeTimeLine::syncPoint() const
{
return d->syncPoint;
}
/*!
Returns true if the timeline is active. An active timeline is one where
QDeclarativeTimeLineValue actions are still pending.
*/
bool QDeclarativeTimeLine::isActive() const
{
return !d->ops.isEmpty();
}
/*!
Completes the timeline. All queued actions are played to completion, and then discarded. For example,
\code
QDeclarativeTimeLineValue v(0.);
QDeclarativeTimeLine tl;
tl.move(v, 100., 1000.);
// 500 ms passes
// v.value() == 50.
tl.complete();
// v.value() == 100.
\endcode
*/
void QDeclarativeTimeLine::complete()
{
d->advance(d->length);
}
/*!
Resets the timeline. All queued actions are discarded and QDeclarativeTimeLineValue's retain their current value. For example,
\code
QDeclarativeTimeLineValue v(0.);
QDeclarativeTimeLine tl;
tl.move(v, 100., 1000.);
// 500 ms passes
// v.value() == 50.
tl.clear();
// v.value() == 50.
\endcode
*/
void QDeclarativeTimeLine::clear()
{
for (QDeclarativeTimeLinePrivate::Ops::ConstIterator iter = d->ops.begin(); iter != d->ops.end(); ++iter)
iter.key()->_t = 0;
d->ops.clear();
d->length = 0;
d->syncPoint = 0;
//XXX need stop here?
}
int QDeclarativeTimeLine::time() const
{
return d->prevTime;
}
/*!
\fn void QDeclarativeTimeLine::updated()
Emitted each time the timeline modifies QDeclarativeTimeLineValues. Even if multiple
QDeclarativeTimeLineValues are changed, this signal is only emitted once for each clock tick.
*/
void QDeclarativeTimeLine::updateCurrentTime(int v)
{
if (d->syncAdj == -1)
d->syncAdj = v;
v -= d->syncAdj;
int timeChanged = v - d->prevTime;
#if 0
if (!timeChanged)
return;
#endif
d->prevTime = v;
d->advance(timeChanged);
emit updated();
// Do we need to stop the clock?
if (d->ops.isEmpty()) {
stop();
d->prevTime = 0;
d->clockRunning = false;
emit completed();
} /*else if (pauseTime > 0) {
GfxClock::cancelClock();
d->prevTime = 0;
GfxClock::pauseFor(pauseTime);
d->syncAdj = 0;
d->clockRunning = false;
}*/ else if (/*!GfxClock::isActive()*/ state() != Running) {
stop();
d->prevTime = 0;
d->clockRunning = true;
d->syncAdj = 0;
start();
}
}
bool operator<(const QPair<int, Update> &lhs,
const QPair<int, Update> &rhs)
{
return lhs.first < rhs.first;
}
int QDeclarativeTimeLinePrivate::advance(int t)
{
int pauseTime = -1;
// XXX - surely there is a more efficient way?
do {
pauseTime = -1;
// Minimal advance time
int advanceTime = t;
for (Ops::Iterator iter = ops.begin(); iter != ops.end(); ++iter) {
TimeLine &tl = *iter;
Op &op = tl.ops.first();
int length = op.length - tl.consumedOpLength;
if (length < advanceTime) {
advanceTime = length;
if (advanceTime == 0)
break;
}
}
t -= advanceTime;
// Process until then. A zero length advance time will only process
// sets.
QList<QPair<int, Update> > updates;
for (Ops::Iterator iter = ops.begin(); iter != ops.end(); ) {
QDeclarativeTimeLineValue *v = static_cast<QDeclarativeTimeLineValue *>(iter.key());
TimeLine &tl = *iter;
Q_ASSERT(!tl.ops.isEmpty());
do {
Op &op = tl.ops.first();
if (advanceTime == 0 && op.length != 0)
continue;
if (tl.consumedOpLength == 0 &&
op.type != Op::Pause &&
op.type != Op::Execute)
tl.base = v->value();
if ((tl.consumedOpLength + advanceTime) == op.length) {
if (op.type == Op::Execute) {
updates << qMakePair(op.order, Update(op.event));
} else {
bool changed = false;
qreal val = value(op, op.length, tl.base, &changed);
if (changed)
updates << qMakePair(op.order, Update(v, val));
}
tl.length -= qMin(advanceTime, tl.length);
tl.consumedOpLength = 0;
tl.ops.removeFirst();
} else {
tl.consumedOpLength += advanceTime;
bool changed = false;
qreal val = value(op, tl.consumedOpLength, tl.base, &changed);
if (changed)
updates << qMakePair(op.order, Update(v, val));
tl.length -= qMin(advanceTime, tl.length);
break;
}
} while(!tl.ops.isEmpty() && advanceTime == 0 && tl.ops.first().length == 0);
if (tl.ops.isEmpty()) {
iter = ops.erase(iter);
v->_t = 0;
} else {
if (tl.ops.first().type == Op::Pause && pauseTime != 0) {
int opPauseTime = tl.ops.first().length - tl.consumedOpLength;
if (pauseTime == -1 || opPauseTime < pauseTime)
pauseTime = opPauseTime;
} else {
pauseTime = 0;
}
++iter;
}
}
length -= qMin(length, advanceTime);
syncPoint -= advanceTime;
qSort(updates.begin(), updates.end());
updateQueue = &updates;
for (int ii = 0; ii < updates.count(); ++ii) {
const Update &v = updates.at(ii).second;
if (v.g) {
v.g->setValue(v.v);
} else {
v.e.d0(v.e.d1);
}
}
updateQueue = 0;
} while(t);
return pauseTime;
}
void QDeclarativeTimeLine::remove(QDeclarativeTimeLineObject *v)
{
QDeclarativeTimeLinePrivate::Ops::Iterator iter = d->ops.find(v);
Q_ASSERT(iter != d->ops.end());
int len = iter->length;
d->ops.erase(iter);
if (len == d->length) {
// We need to recalculate the length
d->length = 0;
for (QDeclarativeTimeLinePrivate::Ops::Iterator iter = d->ops.begin();
iter != d->ops.end();
++iter) {
if (iter->length > d->length)
d->length = iter->length;
}
}
if (d->ops.isEmpty()) {
stop();
d->clockRunning = false;
} else if (/*!GfxClock::isActive()*/ state() != Running) {
stop();
d->prevTime = 0;
d->clockRunning = true;
if (d->syncMode == QDeclarativeTimeLine::LocalSync) {
d->syncAdj = -1;
} else {
d->syncAdj = 0;
}
start();
}
if (d->updateQueue) {
for (int ii = 0; ii < d->updateQueue->count(); ++ii) {
if (d->updateQueue->at(ii).second.g == v ||
d->updateQueue->at(ii).second.e.callbackObject() == v) {
d->updateQueue->removeAt(ii);
--ii;
}
}
}
}
/*!
\internal
\class QDeclarativeTimeLineValue
\brief The QDeclarativeTimeLineValue class provides a value that can be modified by QDeclarativeTimeLine.
*/
/*!
\fn QDeclarativeTimeLineValue::QDeclarativeTimeLineValue(qreal value = 0)
Construct a new QDeclarativeTimeLineValue with an initial \a value.
*/
/*!
\fn qreal QDeclarativeTimeLineValue::value() const
Return the current value.
*/
/*!
\fn void QDeclarativeTimeLineValue::setValue(qreal value)
Set the current \a value.
*/
/*!
\fn QDeclarativeTimeLine *QDeclarativeTimeLineValue::timeLine() const
If a QDeclarativeTimeLine is operating on this value, return a pointer to it,
otherwise return null.
*/
QDeclarativeTimeLineObject::QDeclarativeTimeLineObject()
: _t(0)
{
}
QDeclarativeTimeLineObject::~QDeclarativeTimeLineObject()
{
if (_t) {
_t->remove(this);
_t = 0;
}
}
QDeclarativeTimeLineCallback::QDeclarativeTimeLineCallback()
: d0(0), d1(0), d2(0)
{
}
QDeclarativeTimeLineCallback::QDeclarativeTimeLineCallback(QDeclarativeTimeLineObject *b, Callback f, void *d)
: d0(f), d1(d), d2(b)
{
}
QDeclarativeTimeLineCallback::QDeclarativeTimeLineCallback(const QDeclarativeTimeLineCallback &o)
: d0(o.d0), d1(o.d1), d2(o.d2)
{
}
QDeclarativeTimeLineCallback &QDeclarativeTimeLineCallback::operator=(const QDeclarativeTimeLineCallback &o)
{
d0 = o.d0;
d1 = o.d1;
d2 = o.d2;
return *this;
}
QDeclarativeTimeLineObject *QDeclarativeTimeLineCallback::callbackObject() const
{
return d2;
}
QT_END_NAMESPACE