Merge remote-tracking branch 'origin/master' into api_changes
[profile/ivi/qtbase.git] / src / corelib / tools / qtimeline.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qtimeline.h"
43
44 #include <private/qobject_p.h>
45 #include <QtCore/qcoreevent.h>
46 #include <QtCore/qmath.h>
47 #include <QtCore/qelapsedtimer.h>
48
49 QT_BEGIN_NAMESPACE
50
51 class QTimeLinePrivate : public QObjectPrivate
52 {
53     Q_DECLARE_PUBLIC(QTimeLine)
54 public:
55     inline QTimeLinePrivate()
56         : startTime(0), duration(1000), startFrame(0), endFrame(0),
57           updateInterval(1000 / 25),
58           totalLoopCount(1), currentLoopCount(0), currentTime(0), timerId(0),
59           direction(QTimeLine::Forward), easingCurve(QEasingCurve::InOutSine),
60           state(QTimeLine::NotRunning)
61     { }
62
63     int startTime;
64     int duration;
65     int startFrame;
66     int endFrame;
67     int updateInterval;
68     int totalLoopCount;
69     int currentLoopCount;
70
71     int currentTime;
72     int timerId;
73     QElapsedTimer timer;
74
75     QTimeLine::Direction direction;
76     QEasingCurve easingCurve;
77     QTimeLine::State state;
78     inline void setState(QTimeLine::State newState)
79     {
80         Q_Q(QTimeLine);
81         if (newState != state)
82             emit q->stateChanged(state = newState);
83     }
84
85     void setCurrentTime(int msecs);
86 };
87
88 /*!
89     \internal
90 */
91 void QTimeLinePrivate::setCurrentTime(int msecs)
92 {
93     Q_Q(QTimeLine);
94
95     qreal lastValue = q->currentValue();
96     int lastFrame = q->currentFrame();
97
98     // Determine if we are looping.
99     int elapsed = (direction == QTimeLine::Backward) ? (-msecs +  duration) : msecs;
100     int loopCount = elapsed / duration;
101
102     bool looping = (loopCount != currentLoopCount);
103 #ifdef QTIMELINE_DEBUG
104     qDebug() << "QTimeLinePrivate::setCurrentTime:" << msecs << duration << "with loopCount" << loopCount
105              << "currentLoopCount" << currentLoopCount
106              << "looping" << looping;
107 #endif
108     if (looping)
109         currentLoopCount = loopCount;
110
111     // Normalize msecs to be between 0 and duration, inclusive.
112     currentTime = elapsed % duration;
113     if (direction == QTimeLine::Backward)
114         currentTime = duration - currentTime;
115
116     // Check if we have reached the end of loopcount.
117     bool finished = false;
118     if (totalLoopCount && currentLoopCount >= totalLoopCount) {
119         finished = true;
120         currentTime = (direction == QTimeLine::Backward) ? 0 : duration;
121         currentLoopCount = totalLoopCount - 1;
122     }
123
124     int currentFrame = q->frameForTime(currentTime);
125 #ifdef QTIMELINE_DEBUG
126     qDebug() << "QTimeLinePrivate::setCurrentTime: frameForTime" << currentTime << currentFrame;
127 #endif
128     if (!qFuzzyCompare(lastValue, q->currentValue()))
129         emit q->valueChanged(q->currentValue());
130     if (lastFrame != currentFrame) {
131         const int transitionframe = (direction == QTimeLine::Forward ? endFrame : startFrame);
132         if (looping && !finished && transitionframe != currentFrame) {
133 #ifdef QTIMELINE_DEBUG
134             qDebug() << "QTimeLinePrivate::setCurrentTime: transitionframe";
135 #endif
136             emit q->frameChanged(transitionframe);
137         }
138 #ifdef QTIMELINE_DEBUG
139         else {
140             QByteArray reason;
141             if (!looping)
142                 reason += " not looping";
143             if (finished) {
144                 if (!reason.isEmpty())
145                     reason += " and";
146                 reason += " finished";
147             }
148             if (transitionframe == currentFrame) {
149                 if (!reason.isEmpty())
150                     reason += " and";
151                 reason += " transitionframe is equal to currentFrame: " + QByteArray::number(currentFrame);
152             }
153             qDebug("QTimeLinePrivate::setCurrentTime: not transitionframe because %s",  reason.constData());
154         }
155 #endif
156         emit q->frameChanged(currentFrame);
157     }
158     if (finished && state == QTimeLine::Running) {
159         q->stop();
160         emit q->finished();
161     }
162 }
163
164 /*!
165     \class QTimeLine
166     \brief The QTimeLine class provides a timeline for controlling animations.
167     \since 4.2
168     \ingroup animation
169
170     It's most commonly used to animate a GUI control by calling a slot
171     periodically. You can construct a timeline by passing its duration in
172     milliseconds to QTimeLine's constructor. The timeline's duration describes
173     for how long the animation will run. Then you set a suitable frame range
174     by calling setFrameRange(). Finally connect the frameChanged() signal to a
175     suitable slot in the widget you wish to animate (e.g., setValue() in
176     QProgressBar). When you proceed to calling start(), QTimeLine will enter
177     Running state, and start emitting frameChanged() at regular intervals,
178     causing your widget's connected property's value to grow from the lower
179     end to the upper and of your frame range, at a steady rate. You can
180     specify the update interval by calling setUpdateInterval(). When done,
181     QTimeLine enters NotRunning state, and emits finished().
182
183     Example:
184
185     \snippet doc/src/snippets/code/src_corelib_tools_qtimeline.cpp 0
186
187     You can also use QTimeLine with the
188     \l{Graphics View}{Graphics View framework} for
189     animations. The QGraphicsItemAnimation class implements animation
190     of \l{QGraphicsItem}{QGraphicsItems} with a timeline.
191
192     By default the timeline runs once, from the beginning and towards the end,
193     upon which you must call start() again to restart from the beginning. To
194     make the timeline loop, you can call setLoopCount(), passing the number of
195     times the timeline should run before finishing. The direction can also be
196     changed, causing the timeline to run backward, by calling
197     setDirection(). You can also pause and unpause the timeline while it's
198     running by calling setPaused(). For interactive control, the
199     setCurrentTime() function is provided, which sets the time position of the
200     time line directly. Although most useful in NotRunning state, (e.g.,
201     connected to a valueChanged() signal in a QSlider,) this function can be
202     called at any time.
203
204     The frame interface is useful for standard widgets, but QTimeLine can be
205     used to control any type of animation. The heart of QTimeLine lies in the
206     valueForTime() function, which generates a \e value between 0 and 1 for a
207     given time. This value is typically used to describe the steps of an
208     animation, where 0 is the first step of an animation, and 1 is the last
209     step. When running, QTimeLine generates values between 0 and 1 by calling
210     valueForTime() and emitting valueChanged(). By default, valueForTime()
211     applies an interpolation algorithm to generate these value. You can choose
212     from a set of predefined timeline algorithms by calling
213     setCurveShape().
214
215     Note that by default, QTimeLine uses the EaseInOut curve shape,
216     which provides a value that grows slowly, then grows steadily, and
217     finally grows slowly. For a custom timeline, you can reimplement
218     valueForTime(), in which case QTimeLine's curveShape property is ignored.
219
220     \sa QProgressBar, QProgressDialog, QGraphicsItemAnimation
221 */
222
223 /*!
224     \enum QTimeLine::State
225
226     This enum describes the state of the timeline.
227
228     \value NotRunning The timeline is not running. This is the initial state
229     of QTimeLine, and the state QTimeLine reenters when finished. The current
230     time, frame and value remain unchanged until either setCurrentTime() is
231     called, or the timeline is started by calling start().
232
233     \value Paused The timeline is paused (i.e., temporarily
234     suspended). Calling setPaused(false) will resume timeline activity.
235
236     \value Running The timeline is running. While control is in the event
237     loop, QTimeLine will update its current time at regular intervals,
238     emitting valueChanged() and frameChanged() when appropriate.
239
240     \sa state(), stateChanged()
241 */
242
243 /*!
244     \enum QTimeLine::Direction
245
246     This enum describes the direction of the timeline when in \l Running state.
247
248     \value Forward The current time of the timeline increases with time (i.e.,
249     moves from 0 and towards the end / duration).
250
251     \value Backward The current time of the timeline decreases with time (i.e.,
252     moves from the end / duration and towards 0).
253
254     \sa setDirection()
255 */
256
257 /*!
258     \enum QTimeLine::CurveShape
259
260     This enum describes the default shape of QTimeLine's value curve. The
261     default, shape is EaseInOutCurve. The curve defines the relation
262     between the value and the timeline.
263
264     \value EaseInCurve The value starts growing slowly, then increases in speed.
265     \value EaseOutCurve The value starts growing steadily, then ends slowly.
266     \value EaseInOutCurve The value starts growing slowly, then runs steadily, then grows slowly again.
267     \value LinearCurve The value grows linearly (e.g., if the duration is 1000 ms,
268            the value at time 500 ms is 0.5).
269     \value SineCurve The value grows sinusoidally.
270     \value CosineCurve The value grows cosinusoidally.
271
272     \sa setCurveShape()
273 */
274
275 /*!
276     \fn QTimeLine::valueChanged(qreal value)
277
278     QTimeLine emits this signal at regular intervals when in \l Running state,
279     but only if the current value changes. \a value is the current value. \a value is
280     a number between 0.0 and 1.0
281
282     \sa QTimeLine::setDuration(), QTimeLine::valueForTime(), QTimeLine::updateInterval
283 */
284
285 /*!
286     \fn QTimeLine::frameChanged(int frame)
287
288     QTimeLine emits this signal at regular intervals when in \l Running state,
289     but only if the current frame changes. \a frame is the current frame number.
290
291     \sa QTimeLine::setFrameRange(), QTimeLine::updateInterval
292 */
293
294 /*!
295     \fn QTimeLine::stateChanged(QTimeLine::State newState)
296
297     This signal is emitted whenever QTimeLine's state changes. The new state
298     is \a newState.
299 */
300
301 /*!
302     \fn QTimeLine::finished()
303
304     This signal is emitted when QTimeLine finishes (i.e., reaches the end of
305     its time line), and does not loop.
306 */
307
308 /*!
309     Constructs a timeline with a duration of \a duration milliseconds. \a
310     parent is passed to QObject's constructor. The default duration is 1000
311     milliseconds.
312  */
313 QTimeLine::QTimeLine(int duration, QObject *parent)
314     : QObject(*new QTimeLinePrivate, parent)
315 {
316     setDuration(duration);
317 }
318
319 /*!
320     Destroys the timeline.
321  */
322 QTimeLine::~QTimeLine()
323 {
324     Q_D(QTimeLine);
325
326     if (d->state == Running)
327         stop();
328 }
329
330 /*!
331     Returns the state of the timeline.
332
333     \sa start(), setPaused(), stop()
334 */
335 QTimeLine::State QTimeLine::state() const
336 {
337     Q_D(const QTimeLine);
338     return d->state;
339 }
340
341 /*!
342     \property QTimeLine::loopCount
343     \brief the number of times the timeline should loop before it's finished.
344
345     A loop count of of 0 means that the timeline will loop forever.
346
347     By default, this property contains a value of 1.
348 */
349 int QTimeLine::loopCount() const
350 {
351     Q_D(const QTimeLine);
352     return d->totalLoopCount;
353 }
354 void QTimeLine::setLoopCount(int count)
355 {
356     Q_D(QTimeLine);
357     d->totalLoopCount = count;
358 }
359
360 /*!
361     \property QTimeLine::direction
362     \brief the direction of the timeline when QTimeLine is in \l Running
363     state.
364
365     This direction indicates whether the time moves from 0 towards the
366     timeline duration, or from the value of the duration and towards 0 after
367     start() has been called.
368
369     By default, this property is set to \l Forward.
370 */
371 QTimeLine::Direction QTimeLine::direction() const
372 {
373     Q_D(const QTimeLine);
374     return d->direction;
375 }
376 void QTimeLine::setDirection(Direction direction)
377 {
378     Q_D(QTimeLine);
379     d->direction = direction;
380     d->startTime = d->currentTime;
381     d->timer.start();
382 }
383
384 /*!
385     \property QTimeLine::duration
386     \brief the total duration of the timeline in milliseconds.
387
388     By default, this value is 1000 (i.e., 1 second), but you can change this
389     by either passing a duration to QTimeLine's constructor, or by calling
390     setDuration(). The duration must be larger than 0.
391
392     \note Changing the duration does not cause the current time to be reset
393     to zero or the new duration. You also need to call setCurrentTime() with
394     the desired value.
395 */
396 int QTimeLine::duration() const
397 {
398     Q_D(const QTimeLine);
399     return d->duration;
400 }
401 void QTimeLine::setDuration(int duration)
402 {
403     Q_D(QTimeLine);
404     if (duration <= 0) {
405         qWarning("QTimeLine::setDuration: cannot set duration <= 0");
406         return;
407     }
408     d->duration = duration;
409 }
410
411 /*!
412     Returns the start frame, which is the frame corresponding to the start of
413     the timeline (i.e., the frame for which the current value is 0).
414
415     \sa setStartFrame(), setFrameRange()
416 */
417 int QTimeLine::startFrame() const
418 {
419     Q_D(const QTimeLine);
420     return d->startFrame;
421 }
422
423 /*!
424     Sets the start frame, which is the frame corresponding to the start of the
425     timeline (i.e., the frame for which the current value is 0), to \a frame.
426
427     \sa startFrame(), endFrame(), setFrameRange()
428 */
429 void QTimeLine::setStartFrame(int frame)
430 {
431     Q_D(QTimeLine);
432     d->startFrame = frame;
433 }
434
435 /*!
436     Returns the end frame, which is the frame corresponding to the end of the
437     timeline (i.e., the frame for which the current value is 1).
438
439     \sa setEndFrame(), setFrameRange()
440 */
441 int QTimeLine::endFrame() const
442 {
443     Q_D(const QTimeLine);
444     return d->endFrame;
445 }
446
447 /*!
448     Sets the end frame, which is the frame corresponding to the end of the
449     timeline (i.e., the frame for which the current value is 1), to \a frame.
450
451     \sa endFrame(), startFrame(), setFrameRange()
452 */
453 void QTimeLine::setEndFrame(int frame)
454 {
455     Q_D(QTimeLine);
456     d->endFrame = frame;
457 }
458
459 /*!
460     Sets the timeline's frame counter to start at \a startFrame, and end and
461     \a endFrame. For each time value, QTimeLine will find the corresponding
462     frame when you call currentFrame() or frameForTime() by interpolating,
463     using the return value of valueForTime().
464
465     When in Running state, QTimeLine also emits the frameChanged() signal when
466     the frame changes.
467
468     \sa startFrame(), endFrame(), start(), currentFrame()
469 */
470 void QTimeLine::setFrameRange(int startFrame, int endFrame)
471 {
472     Q_D(QTimeLine);
473     d->startFrame = startFrame;
474     d->endFrame = endFrame;
475 }
476
477 /*!
478     \property QTimeLine::updateInterval
479     \brief the time in milliseconds between each time QTimeLine updates its
480     current time.
481
482     When updating the current time, QTimeLine will emit valueChanged() if the
483     current value changed, and frameChanged() if the frame changed.
484
485     By default, the interval is 40 ms, which corresponds to a rate of 25
486     updates per second.
487 */
488 int QTimeLine::updateInterval() const
489 {
490     Q_D(const QTimeLine);
491     return d->updateInterval;
492 }
493 void QTimeLine::setUpdateInterval(int interval)
494 {
495     Q_D(QTimeLine);
496     d->updateInterval = interval;
497 }
498
499 /*!
500     \property QTimeLine::curveShape
501     \brief the shape of the timeline curve.
502
503     The curve shape describes the relation between the time and value for the
504     base implementation of valueForTime().
505
506     If you have reimplemented valueForTime(), this value is ignored.
507
508     By default, this property is set to \l EaseInOutCurve.
509
510     \sa valueForTime()
511 */
512 QTimeLine::CurveShape QTimeLine::curveShape() const
513 {
514     Q_D(const QTimeLine);
515     switch (d->easingCurve.type()) {
516     default:
517     case QEasingCurve::InOutSine:
518         return EaseInOutCurve;
519     case QEasingCurve::InCurve:
520         return EaseInCurve;
521     case QEasingCurve::OutCurve:
522         return EaseOutCurve;
523     case QEasingCurve::Linear:
524         return LinearCurve;
525     case QEasingCurve::SineCurve:
526         return SineCurve;
527     case QEasingCurve::CosineCurve:
528         return CosineCurve;
529     }
530     return EaseInOutCurve;
531 }
532
533 void QTimeLine::setCurveShape(CurveShape shape)
534 {
535     switch (shape) {
536     default:
537     case EaseInOutCurve:
538         setEasingCurve(QEasingCurve(QEasingCurve::InOutSine));
539         break;
540     case EaseInCurve:
541         setEasingCurve(QEasingCurve(QEasingCurve::InCurve));
542         break;
543     case EaseOutCurve:
544         setEasingCurve(QEasingCurve(QEasingCurve::OutCurve));
545         break;
546     case LinearCurve:
547         setEasingCurve(QEasingCurve(QEasingCurve::Linear));
548         break;
549     case SineCurve:
550         setEasingCurve(QEasingCurve(QEasingCurve::SineCurve));
551         break;
552     case CosineCurve:
553         setEasingCurve(QEasingCurve(QEasingCurve::CosineCurve));
554         break;
555     }
556 }
557
558 /*!
559     \property QTimeLine::easingCurve
560
561     \since 4.6
562
563     Specifies the easing curve that the timeline will use.
564     If both easing curve and curveShape are set, the last set property will
565     override the previous one. (If valueForTime() is reimplemented it will
566     override both)
567 */
568
569 QEasingCurve QTimeLine::easingCurve() const
570 {
571     Q_D(const QTimeLine);
572     return d->easingCurve;
573 }
574
575 void QTimeLine::setEasingCurve(const QEasingCurve& curve)
576 {
577     Q_D(QTimeLine);
578     d->easingCurve = curve;
579 }
580
581 /*!
582     \property QTimeLine::currentTime
583     \brief the current time of the time line.
584
585     When QTimeLine is in Running state, this value is updated continuously as
586     a function of the duration and direction of the timeline. Otherwise, it is
587     value that was current when stop() was called last, or the value set by
588     setCurrentTime().
589
590     By default, this property contains a value of 0.
591 */
592 int QTimeLine::currentTime() const
593 {
594     Q_D(const QTimeLine);
595     return d->currentTime;
596 }
597 void QTimeLine::setCurrentTime(int msec)
598 {
599     Q_D(QTimeLine);
600     d->startTime = 0;
601     d->currentLoopCount = 0;
602     d->timer.restart();
603     d->setCurrentTime(msec);
604 }
605
606 /*!
607     Returns the frame corresponding to the current time.
608
609     \sa currentTime(), frameForTime(), setFrameRange()
610 */
611 int QTimeLine::currentFrame() const
612 {
613     Q_D(const QTimeLine);
614     return frameForTime(d->currentTime);
615 }
616
617 /*!
618     Returns the value corresponding to the current time.
619
620     \sa valueForTime(), currentFrame()
621 */
622 qreal QTimeLine::currentValue() const
623 {
624     Q_D(const QTimeLine);
625     return valueForTime(d->currentTime);
626 }
627
628 /*!
629     Returns the frame corresponding to the time \a msec. This value is
630     calculated using a linear interpolation of the start and end frame, based
631     on the value returned by valueForTime().
632
633     \sa valueForTime(), setFrameRange()
634 */
635 int QTimeLine::frameForTime(int msec) const
636 {
637     Q_D(const QTimeLine);
638     if (d->direction == Forward)
639         return d->startFrame + int((d->endFrame - d->startFrame) * valueForTime(msec));
640     return d->startFrame + qCeil((d->endFrame - d->startFrame) * valueForTime(msec));
641 }
642
643 /*!
644     Returns the timeline value for the time \a msec. The returned value, which
645     varies depending on the curve shape, is always between 0 and 1. If \a msec
646     is 0, the default implementation always returns 0.
647
648     Reimplement this function to provide a custom curve shape for your
649     timeline.
650
651     \sa CurveShape, frameForTime()
652 */
653 qreal QTimeLine::valueForTime(int msec) const
654 {
655     Q_D(const QTimeLine);
656     msec = qMin(qMax(msec, 0), d->duration);
657
658     qreal value = msec / qreal(d->duration);
659     return d->easingCurve.valueForProgress(value);
660 }
661
662 /*!
663     Starts the timeline. QTimeLine will enter Running state, and once it
664     enters the event loop, it will update its current time, frame and value at
665     regular intervals. The default interval is 40 ms (i.e., 25 times per
666     second). You can change the update interval by calling
667     setUpdateInterval().
668
669     The timeline will start from position 0, or the end if going backward.
670     If you want to resume a stopped timeline without restarting, you can call
671     resume() instead.
672
673     \sa resume(), updateInterval(), frameChanged(), valueChanged()
674 */
675 void QTimeLine::start()
676 {
677     Q_D(QTimeLine);
678     if (d->timerId) {
679         qWarning("QTimeLine::start: already running");
680         return;
681     }
682     int curTime = 0;
683     if (d->direction == Backward)
684         curTime = d->duration;
685     d->timerId = startTimer(d->updateInterval);
686     d->startTime = curTime;
687     d->currentLoopCount = 0;
688     d->timer.start();
689     d->setState(Running);
690     d->setCurrentTime(curTime);
691 }
692
693 /*!
694     Resumes the timeline from the current time. QTimeLine will reenter Running
695     state, and once it enters the event loop, it will update its current time,
696     frame and value at regular intervals.
697
698     In contrast to start(), this function does not restart the timeline before
699     it resumes.
700
701     \sa start(), updateInterval(), frameChanged(), valueChanged()
702 */
703 void QTimeLine::resume()
704 {
705     Q_D(QTimeLine);
706     if (d->timerId) {
707         qWarning("QTimeLine::resume: already running");
708         return;
709     }
710     d->timerId = startTimer(d->updateInterval);
711     d->startTime = d->currentTime;
712     d->timer.start();
713     d->setState(Running);
714 }
715
716 /*!
717     Stops the timeline, causing QTimeLine to enter NotRunning state.
718
719     \sa start()
720 */
721 void QTimeLine::stop()
722 {
723     Q_D(QTimeLine);
724     if (d->timerId)
725         killTimer(d->timerId);
726     d->setState(NotRunning);
727     d->timerId = 0;
728 }
729
730 /*!
731     If \a paused is true, the timeline is paused, causing QTimeLine to enter
732     Paused state. No updates will be signaled until either start() or
733     setPaused(false) is called. If \a paused is false, the timeline is resumed
734     and continues where it left.
735
736     \sa state(), start()
737 */
738 void QTimeLine::setPaused(bool paused)
739 {
740     Q_D(QTimeLine);
741     if (d->state == NotRunning) {
742         qWarning("QTimeLine::setPaused: Not running");
743         return;
744     }
745     if (paused && d->state != Paused) {
746         d->startTime = d->currentTime;
747         killTimer(d->timerId);
748         d->timerId = 0;
749         d->setState(Paused);
750     } else if (!paused && d->state == Paused) {
751         d->timerId = startTimer(d->updateInterval);
752         d->setState(Running);
753     }
754 }
755
756 /*!
757     Toggles the direction of the timeline. If the direction was Forward, it
758     becomes Backward, and vice verca.
759
760     \sa setDirection()
761 */
762 void QTimeLine::toggleDirection()
763 {
764     Q_D(QTimeLine);
765     setDirection(d->direction == Forward ? Backward : Forward);
766 }
767
768 /*!
769     \reimp
770 */
771 void QTimeLine::timerEvent(QTimerEvent *event)
772 {
773     Q_D(QTimeLine);
774     if (event->timerId() != d->timerId) {
775         event->ignore();
776         return;
777     }
778     event->accept();
779
780     if (d->direction == Forward) {
781         d->setCurrentTime(d->startTime + d->timer.elapsed());
782     } else {
783         d->setCurrentTime(d->startTime - d->timer.elapsed());
784     }
785 }
786
787 QT_END_NAMESPACE