src/corelib/tools/qtimeline.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtCore module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    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/qdatetime.h>
       
    46 #include <QtCore/qcoreevent.h>
       
    47 #include <QtCore/qmath.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     QTime 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 (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