1bf872fea6e6a1411d07ad791ebbce4f2e6dc94f
[profile/ivi/qtdeclarative.git] / src / qtquick1 / util / qdeclarativetimeline.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "QtQuick1/private/qdeclarativetimeline_p_p.h"
43
44 #include <QDebug>
45 #include <QMutex>
46 #include <QThread>
47 #include <QWaitCondition>
48 #include <QEvent>
49 #include <QCoreApplication>
50 #include <QEasingCurve>
51 #include <QTime>
52
53 QT_BEGIN_NAMESPACE
54
55
56
57 struct Update {
58     Update(QDeclarative1TimeLineValue *_g, qreal _v)
59         : g(_g), v(_v) {}
60     Update(const QDeclarative1TimeLineCallback &_e)
61         : g(0), v(0), e(_e) {}
62
63     QDeclarative1TimeLineValue *g;
64     qreal v;
65     QDeclarative1TimeLineCallback e;
66 };
67
68 struct QDeclarative1TimeLinePrivate
69 {
70     QDeclarative1TimeLinePrivate(QDeclarative1TimeLine *);
71
72     struct Op {
73         enum Type {
74             Pause,
75             Set,
76             Move,
77             MoveBy,
78             Accel,
79             AccelDistance,
80             Execute
81         };
82         Op() {}
83         Op(Type t, int l, qreal v, qreal v2, int o, 
84            const QDeclarative1TimeLineCallback &ev = QDeclarative1TimeLineCallback(), const QEasingCurve &es = QEasingCurve())
85             : type(t), length(l), value(v), value2(v2), order(o), event(ev),
86               easing(es) {}
87         Op(const Op &o)
88             : type(o.type), length(o.length), value(o.value), value2(o.value2),
89               order(o.order), event(o.event), easing(o.easing) {}
90         Op &operator=(const Op &o) {
91             type = o.type; length = o.length; value = o.value; 
92             value2 = o.value2; order = o.order; event = o.event; 
93             easing = o.easing;
94             return *this;
95         }
96
97         Type type;
98         int length;
99         qreal value;
100         qreal value2;
101
102         int order;
103         QDeclarative1TimeLineCallback event;
104         QEasingCurve easing;
105     };
106     struct TimeLine
107     {
108         TimeLine() : length(0), consumedOpLength(0), base(0.) {}
109         QList<Op> ops;
110         int length;
111         int consumedOpLength;
112         qreal base;
113     };
114
115     int length;
116     int syncPoint;
117     typedef QHash<QDeclarative1TimeLineObject *, TimeLine> Ops;
118     Ops ops;
119     QDeclarative1TimeLine *q;
120
121     void add(QDeclarative1TimeLineObject &, const Op &);
122     qreal value(const Op &op, int time, qreal base, bool *) const;
123
124     int advance(int);
125
126     bool clockRunning;
127     int prevTime;
128
129     int order;
130
131     QDeclarative1TimeLine::SyncMode syncMode;
132     int syncAdj;
133     QList<QPair<int, Update> > *updateQueue;
134 };
135
136 QDeclarative1TimeLinePrivate::QDeclarative1TimeLinePrivate(QDeclarative1TimeLine *parent)
137 : length(0), syncPoint(0), q(parent), clockRunning(false), prevTime(0), order(0), syncMode(QDeclarative1TimeLine::LocalSync), syncAdj(0), updateQueue(0)
138 {
139 }
140
141 void QDeclarative1TimeLinePrivate::add(QDeclarative1TimeLineObject &g, const Op &o)
142 {
143     if (g._t && g._t != q) {
144         qWarning() << "QDeclarative1TimeLine: Cannot modify a QDeclarative1TimeLineValue owned by"
145                    << "another timeline.";
146         return;
147     }
148     g._t = q;
149
150     Ops::Iterator iter = ops.find(&g);
151     if (iter == ops.end()) {
152         iter = ops.insert(&g, TimeLine());
153         if (syncPoint > 0)
154             q->pause(g, syncPoint);
155     }
156     if (!iter->ops.isEmpty() &&
157        o.type == Op::Pause &&
158        iter->ops.last().type == Op::Pause) {
159         iter->ops.last().length += o.length;
160         iter->length += o.length;
161     } else {
162         iter->ops.append(o);
163         iter->length += o.length;
164     }
165
166     if (iter->length > length)
167         length = iter->length;
168
169     if (!clockRunning) {
170         q->stop();
171         prevTime = 0;
172         clockRunning = true;
173
174         if (syncMode == QDeclarative1TimeLine::LocalSync)  {
175             syncAdj = -1;
176         } else {
177             syncAdj = 0;
178         }
179         q->start();
180 /*        q->tick(0);
181         if (syncMode == QDeclarative1TimeLine::LocalSync)  {
182             syncAdj = -1;
183         } else {
184             syncAdj = 0;
185         }
186         */
187     }
188 }
189
190 qreal QDeclarative1TimeLinePrivate::value(const Op &op, int time, qreal base, bool *changed) const
191 {
192     Q_ASSERT(time >= 0);
193     Q_ASSERT(time <= op.length);
194     *changed = true;
195
196     switch(op.type) {
197         case Op::Pause:
198             *changed = false;
199             return base;
200         case Op::Set:
201             return op.value;
202         case Op::Move:
203             if (time == 0) {
204                 return base;
205             } else if (time == (op.length)) {
206                 return op.value;
207             } else {
208                 qreal delta = op.value - base;
209                 qreal pTime = (qreal)(time) / (qreal)op.length;
210                 if (op.easing.type() == QEasingCurve::Linear)
211                     return base + delta * pTime;
212                 else
213                     return base + delta * op.easing.valueForProgress(pTime);
214             }
215         case Op::MoveBy:
216             if (time == 0) {
217                 return base;
218             } else if (time == (op.length)) {
219                 return base + op.value;
220             } else {
221                 qreal delta = op.value;
222                 qreal pTime = (qreal)(time) / (qreal)op.length;
223                 if (op.easing.type() == QEasingCurve::Linear)
224                     return base + delta * pTime;
225                 else
226                     return base + delta * op.easing.valueForProgress(pTime);
227             }
228         case Op::Accel:
229             if (time == 0) {
230                 return base;
231             } else {
232                 qreal t = (qreal)(time) / 1000.0f;
233                 qreal delta = op.value * t + 0.5f * op.value2 * t * t;
234                 return base + delta;
235             }
236         case Op::AccelDistance:
237             if (time == 0) {
238                 return base;
239             } else if (time == (op.length)) {
240                 return base + op.value2;
241             } else {
242                 qreal t = (qreal)(time) / 1000.0f;
243                 qreal accel = -1.0f * 1000.0f * op.value / (qreal)op.length;
244                 qreal delta = op.value * t + 0.5f * accel * t * t;
245                 return base + delta;
246
247             }
248         case Op::Execute:
249             op.event.d0(op.event.d1);
250             *changed = false;
251             return -1;
252     }
253
254     return base;
255 }
256
257 /*!
258     \internal
259     \class QDeclarative1TimeLine
260     \brief The QDeclarative1TimeLine class provides a timeline for controlling animations.
261
262     QDeclarative1TimeLine is similar to QTimeLine except:
263     \list
264     \i It updates QDeclarative1TimeLineValue instances directly, rather than maintaining a single
265     current value.
266
267     For example, the following animates a simple value over 200 milliseconds:
268     \code
269     QDeclarative1TimeLineValue v(<starting value>);
270     QDeclarative1TimeLine tl;
271     tl.move(v, 100., 200);
272     tl.start()
273     \endcode
274
275     If your program needs to know when values are changed, it can either
276     connect to the QDeclarative1TimeLine's updated() signal, or inherit from QDeclarative1TimeLineValue
277     and reimplement the QDeclarative1TimeLineValue::setValue() method.
278
279     \i Supports multiple QDeclarative1TimeLineValue, arbitrary start and end values and allows
280     animations to be strung together for more complex effects.
281
282     For example, the following animation moves the x and y coordinates of
283     an object from wherever they are to the position (100, 100) in 50
284     milliseconds and then further animates them to (100, 200) in 50
285     milliseconds:
286
287     \code
288     QDeclarative1TimeLineValue x(<starting value>);
289     QDeclarative1TimeLineValue y(<starting value>);
290
291     QDeclarative1TimeLine tl;
292     tl.start();
293
294     tl.move(x, 100., 50);
295     tl.move(y, 100., 50);
296     tl.move(y, 200., 50);
297     \endcode
298
299     \i All QDeclarative1TimeLine instances share a single, synchronized clock.
300
301     Actions scheduled within the same event loop tick are scheduled
302     synchronously against each other, regardless of the wall time between the
303     scheduling.  Synchronized scheduling applies both to within the same
304     QDeclarative1TimeLine and across separate QDeclarative1TimeLine's within the same process.
305
306     \endlist
307
308     Currently easing functions are not supported.
309 */
310
311
312 /*!
313     Construct a new QDeclarative1TimeLine with the specified \a parent.
314 */
315 QDeclarative1TimeLine::QDeclarative1TimeLine(QObject *parent)
316 : QAbstractAnimation(parent)
317 {
318     d = new QDeclarative1TimeLinePrivate(this);
319 }
320
321 /*!
322     Destroys the time line.  Any inprogress animations are canceled, but not
323     completed.
324 */
325 QDeclarative1TimeLine::~QDeclarative1TimeLine()
326 {
327     for (QDeclarative1TimeLinePrivate::Ops::Iterator iter = d->ops.begin();
328             iter != d->ops.end();
329             ++iter)
330         iter.key()->_t = 0;
331
332     delete d; d = 0;
333 }
334
335 /*!
336     \enum QDeclarative1TimeLine::SyncMode
337  */
338
339 /*!
340     Return the timeline's synchronization mode.
341  */
342 QDeclarative1TimeLine::SyncMode QDeclarative1TimeLine::syncMode() const
343 {
344     return d->syncMode;
345 }
346
347 /*!
348     Set the timeline's synchronization mode to \a syncMode.
349  */
350 void QDeclarative1TimeLine::setSyncMode(SyncMode syncMode)
351 {
352     d->syncMode = syncMode;
353 }
354
355 /*!
356     Pause \a obj for \a time milliseconds.
357 */
358 void QDeclarative1TimeLine::pause(QDeclarative1TimeLineObject &obj, int time)
359 {
360     if (time <= 0) return;
361     QDeclarative1TimeLinePrivate::Op op(QDeclarative1TimeLinePrivate::Op::Pause, time, 0., 0., d->order++);
362     d->add(obj, op);
363 }
364
365 /*!
366     Execute the \a event.
367  */
368 void QDeclarative1TimeLine::callback(const QDeclarative1TimeLineCallback &callback)
369 {
370     QDeclarative1TimeLinePrivate::Op op(QDeclarative1TimeLinePrivate::Op::Execute, 0, 0, 0., d->order++, callback);
371     d->add(*callback.callbackObject(), op);
372 }
373
374 /*!
375     Set the \a value of \a timeLineValue.
376 */
377 void QDeclarative1TimeLine::set(QDeclarative1TimeLineValue &timeLineValue, qreal value)
378 {
379     QDeclarative1TimeLinePrivate::Op op(QDeclarative1TimeLinePrivate::Op::Set, 0, value, 0., d->order++);
380     d->add(timeLineValue, op);
381 }
382
383 /*!
384     Decelerate \a timeLineValue from the starting \a velocity to zero at the
385     given \a acceleration rate.  Although the \a acceleration is technically
386     a deceleration, it should always be positive.  The QDeclarative1TimeLine will ensure
387     that the deceleration is in the opposite direction to the initial velocity.
388 */
389 int QDeclarative1TimeLine::accel(QDeclarative1TimeLineValue &timeLineValue, qreal velocity, qreal acceleration)
390 {
391     if (acceleration == 0.0f)
392         return -1;
393
394     if ((velocity > 0.0f) == (acceleration > 0.0f))
395         acceleration = acceleration * -1.0f;
396
397     int time = static_cast<int>(-1000 * velocity / acceleration);
398
399     QDeclarative1TimeLinePrivate::Op op(QDeclarative1TimeLinePrivate::Op::Accel, time, velocity, acceleration, d->order++);
400     d->add(timeLineValue, op);
401
402     return time;
403 }
404
405 /*!
406     \overload
407
408     Decelerate \a timeLineValue from the starting \a velocity to zero at the
409     given \a acceleration rate over a maximum distance of maxDistance.
410
411     If necessary, QDeclarative1TimeLine will reduce the acceleration to ensure that the
412     entire operation does not require a move of more than \a maxDistance.
413     \a maxDistance should always be positive.
414 */
415 int QDeclarative1TimeLine::accel(QDeclarative1TimeLineValue &timeLineValue, qreal velocity, qreal acceleration, qreal maxDistance)
416 {
417     if (maxDistance == 0.0f || acceleration == 0.0f)
418         return -1;
419
420     Q_ASSERT(acceleration > 0.0f && maxDistance > 0.0f);
421
422     qreal maxAccel = (velocity * velocity) / (2.0f * maxDistance);
423     if (maxAccel > acceleration)
424         acceleration = maxAccel;
425
426     if ((velocity > 0.0f) == (acceleration > 0.0f))
427         acceleration = acceleration * -1.0f;
428
429     int time = static_cast<int>(-1000 * velocity / acceleration);
430
431     QDeclarative1TimeLinePrivate::Op op(QDeclarative1TimeLinePrivate::Op::Accel, time, velocity, acceleration, d->order++);
432     d->add(timeLineValue, op);
433
434     return time;
435 }
436
437 /*!
438     Decelerate \a timeLineValue from the starting \a velocity to zero over the given
439     \a distance.  This is like accel(), but the QDeclarative1TimeLine calculates the exact
440     deceleration to use.
441
442     \a distance should be positive.
443 */
444 int QDeclarative1TimeLine::accelDistance(QDeclarative1TimeLineValue &timeLineValue, qreal velocity, qreal distance)
445 {
446     if (distance == 0.0f || velocity == 0.0f)
447         return -1;
448
449     Q_ASSERT((distance >= 0.0f) == (velocity >= 0.0f));
450
451     int time = static_cast<int>(1000 * (2.0f * distance) / velocity);
452
453     QDeclarative1TimeLinePrivate::Op op(QDeclarative1TimeLinePrivate::Op::AccelDistance, time, velocity, distance, d->order++);
454     d->add(timeLineValue, op);
455
456     return time;
457 }
458
459 /*!
460     Linearly change the \a timeLineValue from its current value to the given
461     \a destination value over \a time milliseconds.
462 */
463 void QDeclarative1TimeLine::move(QDeclarative1TimeLineValue &timeLineValue, qreal destination, int time)
464 {
465     if (time <= 0) return;
466     QDeclarative1TimeLinePrivate::Op op(QDeclarative1TimeLinePrivate::Op::Move, time, destination, 0.0f, d->order++);
467     d->add(timeLineValue, op);
468 }
469
470 /*!
471     Change the \a timeLineValue from its current value to the given \a destination
472     value over \a time milliseconds using the \a easing curve.
473  */
474 void QDeclarative1TimeLine::move(QDeclarative1TimeLineValue &timeLineValue, qreal destination, const QEasingCurve &easing, int time)
475 {
476     if (time <= 0) return;
477     QDeclarative1TimeLinePrivate::Op op(QDeclarative1TimeLinePrivate::Op::Move, time, destination, 0.0f, d->order++, QDeclarative1TimeLineCallback(), easing);
478     d->add(timeLineValue, op);
479 }
480
481 /*!
482     Linearly change the \a timeLineValue from its current value by the \a change amount
483     over \a time milliseconds.
484 */
485 void QDeclarative1TimeLine::moveBy(QDeclarative1TimeLineValue &timeLineValue, qreal change, int time)
486 {
487     if (time <= 0) return;
488     QDeclarative1TimeLinePrivate::Op op(QDeclarative1TimeLinePrivate::Op::MoveBy, time, change, 0.0f, d->order++);
489     d->add(timeLineValue, op);
490 }
491
492 /*!
493     Change the \a timeLineValue from its current value by the \a change amount over
494     \a time milliseconds using the \a easing curve.
495  */
496 void QDeclarative1TimeLine::moveBy(QDeclarative1TimeLineValue &timeLineValue, qreal change, const QEasingCurve &easing, int time)
497 {
498     if (time <= 0) return;
499     QDeclarative1TimeLinePrivate::Op op(QDeclarative1TimeLinePrivate::Op::MoveBy, time, change, 0.0f, d->order++, QDeclarative1TimeLineCallback(), easing);
500     d->add(timeLineValue, op);
501 }
502
503 /*!
504     Cancel (but don't complete) all scheduled actions for \a timeLineValue.
505 */
506 void QDeclarative1TimeLine::reset(QDeclarative1TimeLineValue &timeLineValue)
507 {
508     if (!timeLineValue._t)
509         return;
510     if (timeLineValue._t != this) {
511         qWarning() << "QDeclarative1TimeLine: Cannot reset a QDeclarative1TimeLineValue owned by another timeline.";
512         return;
513     }
514     remove(&timeLineValue);
515     timeLineValue._t = 0;
516 }
517
518 int QDeclarative1TimeLine::duration() const
519 {
520     return -1;
521 }
522
523 /*!
524     Synchronize the end point of \a timeLineValue to the endpoint of \a syncTo
525     within this timeline.
526
527     Following operations on \a timeLineValue in this timeline will be scheduled after
528     all the currently scheduled actions on \a syncTo are complete.  In
529     pseudo-code this is equivalent to:
530     \code
531     QDeclarative1TimeLine::pause(timeLineValue, min(0, length_of(syncTo) - length_of(timeLineValue)))
532     \endcode
533 */
534 void QDeclarative1TimeLine::sync(QDeclarative1TimeLineValue &timeLineValue, QDeclarative1TimeLineValue &syncTo)
535 {
536     QDeclarative1TimeLinePrivate::Ops::Iterator iter = d->ops.find(&syncTo);
537     if (iter == d->ops.end())
538         return;
539     int length = iter->length;
540
541     iter = d->ops.find(&timeLineValue);
542     if (iter == d->ops.end()) {
543         pause(timeLineValue, length);
544     } else {
545         int glength = iter->length;
546         pause(timeLineValue, length - glength);
547     }
548 }
549
550 /*!
551     Synchronize the end point of \a timeLineValue to the endpoint of the longest
552     action cursrently scheduled in the timeline.
553
554     In pseudo-code, this is equivalent to:
555     \code
556     QDeclarative1TimeLine::pause(timeLineValue, length_of(timeline) - length_of(timeLineValue))
557     \endcode
558 */
559 void QDeclarative1TimeLine::sync(QDeclarative1TimeLineValue &timeLineValue)
560 {
561     QDeclarative1TimeLinePrivate::Ops::Iterator iter = d->ops.find(&timeLineValue);
562     if (iter == d->ops.end()) {
563         pause(timeLineValue, d->length);
564     } else {
565         pause(timeLineValue, d->length - iter->length);
566     }
567 }
568
569 /*
570     Synchronize all currently and future scheduled values in this timeline to
571     the longest action currently scheduled.
572
573     For example:
574     \code
575     value1->setValue(0.);
576     value2->setValue(0.);
577     value3->setValue(0.);
578     QDeclarative1TimeLine tl;
579     ...
580     tl.move(value1, 10, 200);
581     tl.move(value2, 10, 100);
582     tl.sync();
583     tl.move(value2, 20, 100);
584     tl.move(value3, 20, 100);
585     \endcode
586
587     will result in:
588
589     \table
590     \header \o \o 0ms \o 50ms \o 100ms \o 150ms \o 200ms \o 250ms \o 300ms
591     \row \o value1 \o 0 \o 2.5 \o 5.0 \o 7.5 \o 10 \o 10 \o 10
592     \row \o value2 \o 0 \o 5.0 \o 10.0 \o 10.0 \o 10.0 \o 15.0 \o 20.0
593     \row \o value2 \o 0 \o 0 \o 0 \o 0 \o 0 \o 10.0 \o 20.0
594     \endtable
595 */
596
597 /*void QDeclarative1TimeLine::sync()
598 {
599     for (QDeclarative1TimeLinePrivate::Ops::Iterator iter = d->ops.begin();
600             iter != d->ops.end();
601             ++iter)
602         pause(*iter.key(), d->length - iter->length);
603     d->syncPoint = d->length;
604 }*/
605
606 /*! 
607     \internal 
608
609     Temporary hack.
610  */
611 void QDeclarative1TimeLine::setSyncPoint(int sp)
612 {
613     d->syncPoint = sp;
614 }
615
616 /*! 
617     \internal 
618  
619     Temporary hack.
620  */
621 int QDeclarative1TimeLine::syncPoint() const
622 {
623     return d->syncPoint;
624 }
625
626 /*!
627     Returns true if the timeline is active.  An active timeline is one where
628     QDeclarative1TimeLineValue actions are still pending.
629 */
630 bool QDeclarative1TimeLine::isActive() const
631 {
632     return !d->ops.isEmpty();
633 }
634
635 /*!
636     Completes the timeline.  All queued actions are played to completion, and then discarded.  For example,
637     \code
638     QDeclarative1TimeLineValue v(0.);
639     QDeclarative1TimeLine tl;
640     tl.move(v, 100., 1000.);
641     // 500 ms passes
642     // v.value() == 50.
643     tl.complete();
644     // v.value() == 100.
645     \endcode
646 */
647 void QDeclarative1TimeLine::complete()
648 {
649     d->advance(d->length);
650 }
651
652 /*!
653     Resets the timeline.  All queued actions are discarded and QDeclarative1TimeLineValue's retain their current value. For example,
654     \code
655     QDeclarative1TimeLineValue v(0.);
656     QDeclarative1TimeLine tl;
657     tl.move(v, 100., 1000.);
658     // 500 ms passes
659     // v.value() == 50.
660     tl.clear();
661     // v.value() == 50.
662     \endcode
663 */
664 void QDeclarative1TimeLine::clear()
665 {
666     for (QDeclarative1TimeLinePrivate::Ops::ConstIterator iter = d->ops.begin(); iter != d->ops.end(); ++iter)
667         iter.key()->_t = 0;
668     d->ops.clear();
669     d->length = 0;
670     d->syncPoint = 0;
671     //XXX need stop here?
672 }
673
674 int QDeclarative1TimeLine::time() const
675 {
676     return d->prevTime;
677 }
678
679 /*!
680     \fn void QDeclarative1TimeLine::updated()
681
682     Emitted each time the timeline modifies QDeclarative1TimeLineValues.  Even if multiple
683     QDeclarative1TimeLineValues are changed, this signal is only emitted once for each clock tick.
684 */
685
686 void QDeclarative1TimeLine::updateCurrentTime(int v)
687 {
688     if (d->syncAdj == -1)
689         d->syncAdj = v;
690     v -= d->syncAdj;
691
692     int timeChanged = v - d->prevTime;
693 #if 0
694     if (!timeChanged)
695         return;
696 #endif
697     d->prevTime = v;
698     d->advance(timeChanged);
699     emit updated();
700
701     // Do we need to stop the clock?
702     if (d->ops.isEmpty()) {
703         stop();
704         d->prevTime = 0;
705         d->clockRunning = false;
706         emit completed();
707     } /*else if (pauseTime > 0) {
708         GfxClock::cancelClock();
709         d->prevTime = 0;
710         GfxClock::pauseFor(pauseTime);
711         d->syncAdj = 0;
712         d->clockRunning = false;
713     }*/ else if (/*!GfxClock::isActive()*/ state() != Running) {
714         stop();
715         d->prevTime = 0;
716         d->clockRunning = true;
717         d->syncAdj = 0;
718         start();
719     }
720 }
721
722 bool operator<(const QPair<int, Update> &lhs,
723                const QPair<int, Update> &rhs)
724 {
725     return lhs.first < rhs.first;
726 }
727
728 int QDeclarative1TimeLinePrivate::advance(int t)
729 {
730     int pauseTime = -1;
731
732     // XXX - surely there is a more efficient way?
733     do {
734         pauseTime = -1;
735         // Minimal advance time
736         int advanceTime = t;
737         for (Ops::Iterator iter = ops.begin(); iter != ops.end(); ++iter) {
738             TimeLine &tl = *iter;
739             Op &op = tl.ops.first();
740             int length = op.length - tl.consumedOpLength;
741                 
742             if (length < advanceTime) {
743                 advanceTime = length;
744                 if (advanceTime == 0)
745                     break;
746             }
747         }
748         t -= advanceTime;
749
750         // Process until then.  A zero length advance time will only process 
751         // sets.
752         QList<QPair<int, Update> > updates;
753
754         for (Ops::Iterator iter = ops.begin(); iter != ops.end(); ) {
755             QDeclarative1TimeLineValue *v = static_cast<QDeclarative1TimeLineValue *>(iter.key());
756             TimeLine &tl = *iter;
757             Q_ASSERT(!tl.ops.isEmpty());
758
759             do {
760                 Op &op = tl.ops.first();
761                 if (advanceTime == 0 && op.length != 0)
762                     continue;
763
764                 if (tl.consumedOpLength == 0 && 
765                    op.type != Op::Pause && 
766                    op.type != Op::Execute)
767                     tl.base = v->value();
768
769                 if ((tl.consumedOpLength + advanceTime) == op.length) {
770                     if (op.type == Op::Execute) {
771                         updates << qMakePair(op.order, Update(op.event));
772                     } else {
773                         bool changed = false;
774                         qreal val = value(op, op.length, tl.base, &changed);
775                         if (changed)
776                             updates << qMakePair(op.order, Update(v, val));
777                     }
778                     tl.length -= qMin(advanceTime, tl.length);
779                     tl.consumedOpLength = 0;
780                     tl.ops.removeFirst();
781                 } else {
782                     tl.consumedOpLength += advanceTime;
783                     bool changed = false;
784                     qreal val = value(op, tl.consumedOpLength, tl.base, &changed);
785                     if (changed)
786                         updates << qMakePair(op.order, Update(v, val));
787                     tl.length -= qMin(advanceTime, tl.length);
788                     break;
789                 }
790
791             } while(!tl.ops.isEmpty() && advanceTime == 0 && tl.ops.first().length == 0);
792
793
794             if (tl.ops.isEmpty()) {
795                 iter = ops.erase(iter);
796                 v->_t = 0;
797             } else {
798                 if (tl.ops.first().type == Op::Pause && pauseTime != 0) {
799                     int opPauseTime = tl.ops.first().length - tl.consumedOpLength;
800                     if (pauseTime == -1 || opPauseTime < pauseTime)
801                         pauseTime = opPauseTime;
802                 } else {
803                     pauseTime = 0;
804                 }
805                 ++iter;
806             }
807         }
808
809         length -= qMin(length, advanceTime);
810         syncPoint -= advanceTime;
811
812         qSort(updates.begin(), updates.end());
813         updateQueue = &updates;
814         for (int ii = 0; ii < updates.count(); ++ii) {
815             const Update &v = updates.at(ii).second;
816             if (v.g) {
817                 v.g->setValue(v.v);
818             } else {
819                 v.e.d0(v.e.d1);
820             }
821         }
822         updateQueue = 0;
823     } while(t);
824
825     return pauseTime;
826 }
827
828 void QDeclarative1TimeLine::remove(QDeclarative1TimeLineObject *v)
829 {
830     QDeclarative1TimeLinePrivate::Ops::Iterator iter = d->ops.find(v);
831     Q_ASSERT(iter != d->ops.end());
832
833     int len = iter->length;
834     d->ops.erase(iter);
835     if (len == d->length) {
836         // We need to recalculate the length
837         d->length = 0;
838         for (QDeclarative1TimeLinePrivate::Ops::Iterator iter = d->ops.begin();
839                 iter != d->ops.end();
840                 ++iter) {
841
842             if (iter->length > d->length)
843                 d->length = iter->length;
844
845         }
846     }
847     if (d->ops.isEmpty()) {
848         stop();
849         d->clockRunning = false;
850     } else if (/*!GfxClock::isActive()*/ state() != Running) {
851         stop();
852         d->prevTime = 0;
853         d->clockRunning = true;
854
855         if (d->syncMode == QDeclarative1TimeLine::LocalSync) {
856             d->syncAdj = -1;
857         } else {
858             d->syncAdj = 0;
859         }
860         start();
861     }
862
863     if (d->updateQueue) {
864         for (int ii = 0; ii < d->updateQueue->count(); ++ii) {
865             if (d->updateQueue->at(ii).second.g == v ||
866                d->updateQueue->at(ii).second.e.callbackObject() == v) {
867                 d->updateQueue->removeAt(ii);
868                 --ii;
869             }
870         }
871     }
872
873
874 }
875
876 /*!
877     \internal
878     \class QDeclarative1TimeLineValue
879     \brief The QDeclarative1TimeLineValue class provides a value that can be modified by QDeclarative1TimeLine.
880 */
881
882 /*!
883     \fn QDeclarative1TimeLineValue::QDeclarative1TimeLineValue(qreal value = 0)
884
885     Construct a new QDeclarative1TimeLineValue with an initial \a value.
886 */
887
888 /*!
889     \fn qreal QDeclarative1TimeLineValue::value() const
890
891     Return the current value.
892 */
893
894 /*!
895     \fn void QDeclarative1TimeLineValue::setValue(qreal value)
896
897     Set the current \a value.
898 */
899
900 /*!
901     \fn QDeclarative1TimeLine *QDeclarative1TimeLineValue::timeLine() const
902
903     If a QDeclarative1TimeLine is operating on this value, return a pointer to it,
904     otherwise return null.
905 */
906
907
908 QDeclarative1TimeLineObject::QDeclarative1TimeLineObject()
909 : _t(0)
910 {
911 }
912
913 QDeclarative1TimeLineObject::~QDeclarative1TimeLineObject()
914 {
915     if (_t) {
916         _t->remove(this);
917         _t = 0;
918     }
919 }
920
921 QDeclarative1TimeLineCallback::QDeclarative1TimeLineCallback()
922 : d0(0), d1(0), d2(0)
923 {
924 }
925
926 QDeclarative1TimeLineCallback::QDeclarative1TimeLineCallback(QDeclarative1TimeLineObject *b, Callback f, void *d)
927 : d0(f), d1(d), d2(b)
928 {
929 }
930
931 QDeclarative1TimeLineCallback::QDeclarative1TimeLineCallback(const QDeclarative1TimeLineCallback &o)
932 : d0(o.d0), d1(o.d1), d2(o.d2)
933 {
934 }
935
936 QDeclarative1TimeLineCallback &QDeclarative1TimeLineCallback::operator=(const QDeclarative1TimeLineCallback &o)
937 {
938     d0 = o.d0;
939     d1 = o.d1;
940     d2 = o.d2;
941     return *this;
942 }
943
944 QDeclarative1TimeLineObject *QDeclarative1TimeLineCallback::callbackObject() const
945 {
946     return d2;
947 }
948
949
950
951 QT_END_NAMESPACE