src/corelib/animation/qvariantanimation.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 "qvariantanimation.h"
       
    43 #include "qvariantanimation_p.h"
       
    44 
       
    45 #include <QtCore/qrect.h>
       
    46 #include <QtCore/qline.h>
       
    47 #include <QtCore/qmutex.h>
       
    48 #include <private/qmutexpool_p.h>
       
    49 
       
    50 #ifndef QT_NO_ANIMATION
       
    51 
       
    52 QT_BEGIN_NAMESPACE
       
    53 
       
    54 /*!
       
    55     \class QVariantAnimation
       
    56     \ingroup animation
       
    57     \brief The QVariantAnimation class provides an abstract base class for animations.
       
    58     \since 4.6
       
    59 
       
    60     This class is part of \l{The Animation Framework}. It serves as a
       
    61     base class for property and item animations, with functions for
       
    62     shared functionality.
       
    63 
       
    64     QVariantAnimation cannot be used directly as it is an abstract
       
    65     class; it has a pure virtual method called updateCurrentValue().
       
    66     The class performs interpolation over
       
    67     \l{QVariant}s, but leaves using the interpolated values to its
       
    68     subclasses. Currently, Qt provides QPropertyAnimation, which
       
    69     animates Qt \l{Qt's Property System}{properties}. See the
       
    70     QPropertyAnimation class description if you wish to animate such
       
    71     properties.
       
    72 
       
    73     You can then set start and end values for the property by calling
       
    74     setStartValue() and setEndValue(), and finally call start() to
       
    75     start the animation. QVariantAnimation will interpolate the
       
    76     property of the target object and emit valueChanged(). To react to
       
    77     a change in the current value you have to reimplement the
       
    78     updateCurrentValue() virtual function.
       
    79 
       
    80     It is also possible to set values at specified steps situated
       
    81     between the start and end value. The interpolation will then
       
    82     touch these points at the specified steps. Note that the start and
       
    83     end values are defined as the key values at 0.0 and 1.0.
       
    84 
       
    85     There are two ways to affect how QVariantAnimation interpolates
       
    86     the values. You can set an easing curve by calling
       
    87     setEasingCurve(), and configure the duration by calling
       
    88     setDuration(). You can change how the QVariants are interpolated
       
    89     by creating a subclass of QVariantAnimation, and reimplementing
       
    90     the virtual interpolated() function.
       
    91 
       
    92     Subclassing QVariantAnimation can be an alternative if you have
       
    93     \l{QVariant}s that you do not wish to declare as Qt properties.
       
    94     Note, however, that you in most cases will be better off declaring
       
    95     your QVariant as a property.
       
    96 
       
    97     Not all QVariant types are supported. Below is a list of currently
       
    98     supported QVariant types:
       
    99 
       
   100     \list
       
   101         \o \l{QMetaType::}{Int}
       
   102         \o \l{QMetaType::}{Double}
       
   103         \o \l{QMetaType::}{Float}
       
   104         \o \l{QMetaType::}{QLine}
       
   105         \o \l{QMetaType::}{QLineF}
       
   106         \o \l{QMetaType::}{QPoint}
       
   107         \o \l{QMetaType::}{QSize}
       
   108         \o \l{QMetaType::}{QSizeF}
       
   109         \o \l{QMetaType::}{QRect}
       
   110         \o \l{QMetaType::}{QRectF}
       
   111     \endlist
       
   112 
       
   113     If you need to interpolate other variant types, including custom
       
   114     types, you have to implement interpolation for these yourself.
       
   115     You do this by reimplementing interpolated(), which returns
       
   116     interpolation values for the value being interpolated.
       
   117 
       
   118     \omit We need some snippets around here. \endomit
       
   119 
       
   120     \sa QPropertyAnimation, QAbstractAnimation, {The Animation Framework}
       
   121 */
       
   122 
       
   123 /*!
       
   124     \fn void QVariantAnimation::valueChanged(const QVariant &value)
       
   125 
       
   126     QVariantAnimation emits this signal whenever the current \a value changes.
       
   127 
       
   128     \sa currentValue, startValue, endValue
       
   129 */
       
   130 
       
   131 /*!
       
   132     \fn void QVariantAnimation::updateCurrentValue(const QVariant &value) = 0;
       
   133 
       
   134     This pure virtual function is called every time the animation's current
       
   135     value changes. The \a value argument is the new current value.
       
   136 
       
   137     \sa currentValue
       
   138 */
       
   139 
       
   140 static bool animationValueLessThan(const QVariantAnimation::KeyValue &p1, const QVariantAnimation::KeyValue &p2)
       
   141 {
       
   142     return p1.first < p2.first;
       
   143 }
       
   144 
       
   145 static QVariant defaultInterpolator(const void *, const void *, qreal)
       
   146 {
       
   147     return QVariant();
       
   148 }
       
   149 
       
   150 template<> Q_INLINE_TEMPLATE QRect _q_interpolate(const QRect &f, const QRect &t, qreal progress)
       
   151 {
       
   152     QRect ret;
       
   153     ret.setCoords(_q_interpolate(f.left(), t.left(), progress),
       
   154                   _q_interpolate(f.top(), t.top(), progress),
       
   155                   _q_interpolate(f.right(), t.right(), progress),
       
   156                   _q_interpolate(f.bottom(), t.bottom(), progress));
       
   157     return ret;
       
   158 }
       
   159 
       
   160 template<> Q_INLINE_TEMPLATE QRectF _q_interpolate(const QRectF &f, const QRectF &t, qreal progress)
       
   161 {
       
   162     qreal x1, y1, w1, h1;
       
   163     f.getRect(&x1, &y1, &w1, &h1);
       
   164     qreal x2, y2, w2, h2;
       
   165     t.getRect(&x2, &y2, &w2, &h2);
       
   166     return QRectF(_q_interpolate(x1, x2, progress), _q_interpolate(y1, y2, progress),
       
   167                   _q_interpolate(w1, w2, progress), _q_interpolate(h1, h2, progress));
       
   168 }
       
   169 
       
   170 template<> Q_INLINE_TEMPLATE QLine _q_interpolate(const QLine &f, const QLine &t, qreal progress)
       
   171 {
       
   172     return QLine( _q_interpolate(f.p1(), t.p1(), progress), _q_interpolate(f.p2(), t.p2(), progress));
       
   173 }
       
   174 
       
   175 template<> Q_INLINE_TEMPLATE QLineF _q_interpolate(const QLineF &f, const QLineF &t, qreal progress)
       
   176 {
       
   177     return QLineF( _q_interpolate(f.p1(), t.p1(), progress), _q_interpolate(f.p2(), t.p2(), progress));
       
   178 }
       
   179 
       
   180 QVariantAnimationPrivate::QVariantAnimationPrivate() : duration(250), interpolator(&defaultInterpolator)
       
   181 { }
       
   182 
       
   183 void QVariantAnimationPrivate::convertValues(int t)
       
   184 {
       
   185     //this ensures that all the keyValues are of type t
       
   186     for (int i = 0; i < keyValues.count(); ++i) {
       
   187         QVariantAnimation::KeyValue &pair = keyValues[i];
       
   188         pair.second.convert(static_cast<QVariant::Type>(t));
       
   189     }
       
   190     //we also need update to the current interval if needed
       
   191     currentInterval.start.second.convert(static_cast<QVariant::Type>(t));
       
   192     currentInterval.end.second.convert(static_cast<QVariant::Type>(t));
       
   193 
       
   194     //... and the interpolator
       
   195     updateInterpolator();
       
   196 }
       
   197 
       
   198 void QVariantAnimationPrivate::updateInterpolator()
       
   199 {
       
   200     int type = currentInterval.start.second.userType();
       
   201     if (type == currentInterval.end.second.userType())
       
   202         interpolator = getInterpolator(type);
       
   203     else
       
   204         interpolator = 0;
       
   205     
       
   206     //we make sure that the interpolator is always set to something
       
   207     if (!interpolator)
       
   208         interpolator = &defaultInterpolator;
       
   209 }
       
   210 
       
   211 /*!
       
   212     \internal
       
   213     The goal of this function is to update the currentInterval member. As a consequence, we also
       
   214     need to update the currentValue.
       
   215     Set \a force to true to always recalculate the interval.
       
   216 */
       
   217 void QVariantAnimationPrivate::recalculateCurrentInterval(bool force/*=false*/)
       
   218 {
       
   219     // can't interpolate if we don't have at least 2 values
       
   220     if ((keyValues.count() + (defaultStartEndValue.isValid() ? 1 : 0)) < 2)
       
   221         return;
       
   222 
       
   223     const qreal progress = easing.valueForProgress(((duration == 0) ? qreal(1) : qreal(currentTime) / qreal(duration)));
       
   224 
       
   225     //0 and 1 are still the boundaries
       
   226     if (force || (currentInterval.start.first > 0 && progress < currentInterval.start.first)
       
   227         || (currentInterval.end.first < 1 && progress > currentInterval.end.first)) {
       
   228         //let's update currentInterval
       
   229         QVariantAnimation::KeyValues::const_iterator it = qLowerBound(keyValues.constBegin(),
       
   230                                                                       keyValues.constEnd(),
       
   231                                                                       qMakePair(progress, QVariant()),
       
   232                                                                       animationValueLessThan);
       
   233         if (it == keyValues.constBegin()) {
       
   234             //the item pointed to by it is the start element in the range    
       
   235             if (it->first == 0 && keyValues.count() > 1) {
       
   236                 currentInterval.start = *it;
       
   237                 currentInterval.end = *(it+1);
       
   238             } else {
       
   239                 currentInterval.start = qMakePair(qreal(0), defaultStartEndValue);
       
   240                 currentInterval.end = *it;
       
   241             }
       
   242         } else if (it == keyValues.constEnd()) {
       
   243             --it; //position the iterator on the last item
       
   244             if (it->first == 1 && keyValues.count() > 1) {
       
   245                 //we have an end value (item with progress = 1)
       
   246                 currentInterval.start = *(it-1);
       
   247                 currentInterval.end = *it;
       
   248             } else {
       
   249                 //we use the default end value here
       
   250                 currentInterval.start = *it;
       
   251                 currentInterval.end = qMakePair(qreal(1), defaultStartEndValue);
       
   252             }
       
   253         } else {
       
   254             currentInterval.start = *(it-1);
       
   255             currentInterval.end = *it;
       
   256         }
       
   257 
       
   258         // update all the values of the currentInterval
       
   259         updateInterpolator();
       
   260     }
       
   261     setCurrentValueForProgress(progress);
       
   262 }
       
   263 
       
   264 void QVariantAnimationPrivate::setCurrentValueForProgress(const qreal progress)
       
   265 {
       
   266     Q_Q(QVariantAnimation);
       
   267 
       
   268     const qreal startProgress = currentInterval.start.first;
       
   269     const qreal endProgress = currentInterval.end.first;
       
   270     const qreal localProgress = (progress - startProgress) / (endProgress - startProgress);
       
   271 
       
   272     QVariant ret = q->interpolated(currentInterval.start.second,
       
   273                                    currentInterval.end.second,
       
   274                                    localProgress);
       
   275     qSwap(currentValue, ret);
       
   276     q->updateCurrentValue(currentValue);
       
   277     static QBasicAtomicInt changedSignalIndex = Q_BASIC_ATOMIC_INITIALIZER(0);
       
   278     if (!changedSignalIndex) {
       
   279         //we keep the mask so that we emit valueChanged only when needed (for performance reasons)
       
   280         changedSignalIndex.testAndSetRelaxed(0, signalIndex("valueChanged(QVariant)"));
       
   281     }
       
   282     if (isSignalConnected(changedSignalIndex) && currentValue != ret) {
       
   283         //the value has changed
       
   284         emit q->valueChanged(currentValue);
       
   285     }
       
   286 }
       
   287 
       
   288 QVariant QVariantAnimationPrivate::valueAt(qreal step) const
       
   289 {
       
   290     QVariantAnimation::KeyValues::const_iterator result =
       
   291         qBinaryFind(keyValues.begin(), keyValues.end(), qMakePair(step, QVariant()), animationValueLessThan);
       
   292     if (result != keyValues.constEnd())
       
   293         return result->second;
       
   294 
       
   295     return QVariant();
       
   296 }
       
   297 
       
   298 void QVariantAnimationPrivate::setValueAt(qreal step, const QVariant &value)
       
   299 {
       
   300     if (step < qreal(0.0) || step > qreal(1.0)) {
       
   301         qWarning("QVariantAnimation::setValueAt: invalid step = %f", step);
       
   302         return;
       
   303     }
       
   304 
       
   305     QVariantAnimation::KeyValue pair(step, value);
       
   306 
       
   307     QVariantAnimation::KeyValues::iterator result = qLowerBound(keyValues.begin(), keyValues.end(), pair, animationValueLessThan);
       
   308     if (result == keyValues.end() || result->first != step) {
       
   309         keyValues.insert(result, pair);
       
   310     } else {
       
   311         if (value.isValid())
       
   312             result->second = value; // replaces the previous value
       
   313         else
       
   314             keyValues.erase(result); // removes the previous value
       
   315     }
       
   316 
       
   317     recalculateCurrentInterval(/*force=*/true);
       
   318 }
       
   319 
       
   320 void QVariantAnimationPrivate::setDefaultStartEndValue(const QVariant &value)
       
   321 {
       
   322     defaultStartEndValue = value;
       
   323     recalculateCurrentInterval(/*force=*/true);
       
   324 }
       
   325 
       
   326 /*!
       
   327     Construct a QVariantAnimation object. \a parent is passed to QAbstractAnimation's
       
   328     constructor.
       
   329 */
       
   330 QVariantAnimation::QVariantAnimation(QObject *parent) : QAbstractAnimation(*new QVariantAnimationPrivate, parent)
       
   331 {
       
   332 }
       
   333 
       
   334 /*!
       
   335     \internal
       
   336 */
       
   337 QVariantAnimation::QVariantAnimation(QVariantAnimationPrivate &dd, QObject *parent) : QAbstractAnimation(dd, parent)
       
   338 {
       
   339 }
       
   340 
       
   341 /*!
       
   342     Destroys the animation.
       
   343 */
       
   344 QVariantAnimation::~QVariantAnimation()
       
   345 {
       
   346 }
       
   347 
       
   348 /*!
       
   349     \property QVariantAnimation::easingCurve
       
   350     \brief the easing curve of the animation
       
   351 
       
   352     This property defines the easing curve of the animation. By
       
   353     default, a linear easing curve is used, resulting in linear
       
   354     interpolation. Other curves are provided, for instance,
       
   355     QEasingCurve::InCirc, which provides a circular entry curve.
       
   356     Another example is QEasingCurve::InOutElastic, which provides an
       
   357     elastic effect on the values of the interpolated variant.
       
   358 
       
   359     The easing curve is used with the interpolator, the interpolated()
       
   360     virtual function, the animation's duration, and iterationCount, to
       
   361     control how the current value changes as the animation progresses.
       
   362 */
       
   363 QEasingCurve QVariantAnimation::easingCurve() const
       
   364 {
       
   365     Q_D(const QVariantAnimation);
       
   366     return d->easing;
       
   367 }
       
   368 
       
   369 void QVariantAnimation::setEasingCurve(const QEasingCurve &easing)
       
   370 {
       
   371     Q_D(QVariantAnimation);
       
   372     d->easing = easing;
       
   373     d->recalculateCurrentInterval();
       
   374 }
       
   375 
       
   376 typedef QVector<QVariantAnimation::Interpolator> QInterpolatorVector;
       
   377 Q_GLOBAL_STATIC(QInterpolatorVector, registeredInterpolators)
       
   378 
       
   379 /*!
       
   380     \fn void qRegisterAnimationInterpolator(QVariant (*func)(const T &from, const T &to, qreal progress))
       
   381     \relates QVariantAnimation
       
   382     \threadsafe
       
   383 
       
   384     Registers a custom interpolator \a func for the template type \c{T}.
       
   385     The interpolator has to be registered before the animation is constructed.
       
   386     To unregister (and use the default interpolator) set \a func to 0.
       
   387  */
       
   388 
       
   389 /*!
       
   390     \internal
       
   391     \typedef QVariantAnimation::Interpolator
       
   392 
       
   393     This is a typedef for a pointer to a function with the following
       
   394     signature:
       
   395     \code
       
   396     QVariant myInterpolator(const QVariant &from, const QVariant &to, qreal progress);
       
   397     \endcode
       
   398 
       
   399 */
       
   400 
       
   401 /*! \internal
       
   402  * Registers a custom interpolator \a func for the specific \a interpolationType.
       
   403  * The interpolator has to be registered before the animation is constructed.
       
   404  * To unregister (and use the default interpolator) set \a func to 0.
       
   405  */
       
   406 void QVariantAnimation::registerInterpolator(QVariantAnimation::Interpolator func, int interpolationType)
       
   407 {
       
   408     // will override any existing interpolators
       
   409     QInterpolatorVector *interpolators = registeredInterpolators();
       
   410     QMutexLocker locker(QMutexPool::globalInstanceGet(interpolators));
       
   411     if (int(interpolationType) >= interpolators->count())
       
   412         interpolators->resize(int(interpolationType) + 1);
       
   413     interpolators->replace(interpolationType, func);
       
   414 }
       
   415 
       
   416 
       
   417 template<typename T> static inline QVariantAnimation::Interpolator castToInterpolator(QVariant (*func)(const T &from, const T &to, qreal progress))
       
   418 {
       
   419      return reinterpret_cast<QVariantAnimation::Interpolator>(func);
       
   420 }
       
   421 
       
   422 QVariantAnimation::Interpolator QVariantAnimationPrivate::getInterpolator(int interpolationType)
       
   423 {
       
   424     QInterpolatorVector *interpolators = registeredInterpolators();
       
   425     QMutexLocker locker(QMutexPool::globalInstanceGet(interpolators));
       
   426     QVariantAnimation::Interpolator ret = 0;
       
   427     if (interpolationType < interpolators->count()) {
       
   428         ret = interpolators->at(interpolationType);
       
   429         if (ret) return ret;
       
   430     }
       
   431 
       
   432     switch(interpolationType)
       
   433     {
       
   434     case QMetaType::Int:
       
   435         return castToInterpolator(_q_interpolateVariant<int>);
       
   436     case QMetaType::Double:
       
   437         return castToInterpolator(_q_interpolateVariant<double>);
       
   438     case QMetaType::Float:
       
   439         return castToInterpolator(_q_interpolateVariant<float>);
       
   440     case QMetaType::QLine:
       
   441         return castToInterpolator(_q_interpolateVariant<QLine>);
       
   442     case QMetaType::QLineF:
       
   443         return castToInterpolator(_q_interpolateVariant<QLineF>);
       
   444     case QMetaType::QPoint:
       
   445         return castToInterpolator(_q_interpolateVariant<QPoint>);
       
   446     case QMetaType::QPointF:
       
   447         return castToInterpolator(_q_interpolateVariant<QPointF>);
       
   448     case QMetaType::QSize:
       
   449         return castToInterpolator(_q_interpolateVariant<QSize>);
       
   450     case QMetaType::QSizeF:
       
   451         return castToInterpolator(_q_interpolateVariant<QSizeF>);
       
   452     case QMetaType::QRect:
       
   453         return castToInterpolator(_q_interpolateVariant<QRect>);
       
   454     case QMetaType::QRectF:
       
   455         return castToInterpolator(_q_interpolateVariant<QRectF>);
       
   456     default:
       
   457         return 0; //this type is not handled
       
   458     }
       
   459 }
       
   460 
       
   461 /*!
       
   462     \property QVariantAnimation::duration
       
   463     \brief the duration of the animation
       
   464 
       
   465     This property describes the duration in milliseconds of the
       
   466     animation. The default duration is 250 milliseconds.
       
   467 
       
   468     \sa QAbstractAnimation::duration()
       
   469  */
       
   470 int QVariantAnimation::duration() const
       
   471 {
       
   472     Q_D(const QVariantAnimation);
       
   473     return d->duration;
       
   474 }
       
   475 
       
   476 void QVariantAnimation::setDuration(int msecs)
       
   477 {
       
   478     Q_D(QVariantAnimation);
       
   479     if (msecs < 0) {
       
   480         qWarning("QVariantAnimation::setDuration: cannot set a negative duration");
       
   481         return;
       
   482     }
       
   483     if (d->duration == msecs)
       
   484         return;
       
   485     d->duration = msecs;
       
   486     d->recalculateCurrentInterval();
       
   487 }
       
   488 
       
   489 /*!
       
   490     \property QVariantAnimation::startValue
       
   491     \brief the optional start value of the animation
       
   492 
       
   493     This property describes the optional start value of the animation. If
       
   494     omitted, or if a null QVariant is assigned as the start value, the
       
   495     animation will use the current position of the end when the animation
       
   496     is started.
       
   497 
       
   498     \sa endValue
       
   499 */
       
   500 QVariant QVariantAnimation::startValue() const
       
   501 {
       
   502     return keyValueAt(0);
       
   503 }
       
   504 
       
   505 void QVariantAnimation::setStartValue(const QVariant &value)
       
   506 {
       
   507     setKeyValueAt(0, value);
       
   508 }
       
   509 
       
   510 /*!
       
   511     \property QVariantAnimation::endValue
       
   512     \brief the end value of the animation
       
   513 
       
   514     This property describes the end value of the animation.
       
   515 
       
   516     \sa startValue
       
   517  */
       
   518 QVariant QVariantAnimation::endValue() const
       
   519 {
       
   520     return keyValueAt(1);
       
   521 }
       
   522 
       
   523 void QVariantAnimation::setEndValue(const QVariant &value)
       
   524 {
       
   525     setKeyValueAt(1, value);
       
   526 }
       
   527 
       
   528 
       
   529 /*!
       
   530     Returns the key frame value for the given \a step. The given \a step
       
   531     must be in the range 0 to 1. If there is no KeyValue for \a step,
       
   532     it returns an invalid QVariant.
       
   533 
       
   534     \sa keyValues(), setKeyValueAt()
       
   535 */
       
   536 QVariant QVariantAnimation::keyValueAt(qreal step) const
       
   537 {
       
   538     return d_func()->valueAt(step);
       
   539 }
       
   540 
       
   541 /*!
       
   542     \typedef QVariantAnimation::KeyValue
       
   543 
       
   544     This is a typedef for QPair<qreal, QVariant>.
       
   545 */
       
   546 /*!
       
   547     \typedef QVariantAnimation::KeyValues
       
   548 
       
   549     This is a typedef for QVector<KeyValue>
       
   550 */
       
   551 
       
   552 /*!
       
   553     Creates a key frame at the given \a step with the given \a value.
       
   554     The given \a step must be in the range 0 to 1.
       
   555 
       
   556     \sa setKeyValues(), keyValueAt()
       
   557 */
       
   558 void QVariantAnimation::setKeyValueAt(qreal step, const QVariant &value)
       
   559 {
       
   560     d_func()->setValueAt(step, value);
       
   561 }
       
   562 
       
   563 /*!
       
   564     Returns the key frames of this animation.
       
   565 
       
   566     \sa keyValueAt(), setKeyValues()
       
   567 */
       
   568 QVariantAnimation::KeyValues QVariantAnimation::keyValues() const
       
   569 {
       
   570     return d_func()->keyValues;
       
   571 }
       
   572 
       
   573 /*!
       
   574     Replaces the current set of key frames with the given \a keyValues.
       
   575     the step of the key frames must be in the range 0 to 1.
       
   576 
       
   577     \sa keyValues(), keyValueAt()
       
   578 */
       
   579 void QVariantAnimation::setKeyValues(const KeyValues &keyValues)
       
   580 {
       
   581     Q_D(QVariantAnimation);
       
   582     d->keyValues = keyValues;
       
   583     qSort(d->keyValues.begin(), d->keyValues.end(), animationValueLessThan);
       
   584     d->recalculateCurrentInterval(/*force=*/true);
       
   585 }
       
   586 
       
   587 /*!
       
   588     \property QVariantAnimation::currentValue
       
   589     \brief the current value of the animation.
       
   590 
       
   591     This property describes the current value; an interpolated value
       
   592     between the \l{startValue}{start value} and the \l{endValue}{end
       
   593     value}, using the current time for progress. The value itself is
       
   594     obtained from interpolated(), which is called repeatedly as the
       
   595     animation is running.
       
   596 
       
   597     QVariantAnimation calls the virtual updateCurrentValue() function
       
   598     when the current value changes. This is particularly useful for
       
   599     subclasses that need to track updates. For example,
       
   600     QPropertyAnimation uses this function to animate Qt \l{Qt's
       
   601     Property System}{properties}.
       
   602 
       
   603     \sa startValue, endValue
       
   604 */
       
   605 QVariant QVariantAnimation::currentValue() const
       
   606 {
       
   607     Q_D(const QVariantAnimation);
       
   608     if (!d->currentValue.isValid())
       
   609         const_cast<QVariantAnimationPrivate*>(d)->recalculateCurrentInterval();
       
   610     return d->currentValue;
       
   611 }
       
   612 
       
   613 /*!
       
   614     \reimp
       
   615  */
       
   616 bool QVariantAnimation::event(QEvent *event)
       
   617 {
       
   618     return QAbstractAnimation::event(event);
       
   619 }
       
   620 
       
   621 /*!
       
   622     \reimp
       
   623 */
       
   624 void QVariantAnimation::updateState(QAbstractAnimation::State oldState,
       
   625                                     QAbstractAnimation::State newState)
       
   626 {
       
   627     Q_UNUSED(oldState);
       
   628     Q_UNUSED(newState);
       
   629 }
       
   630 
       
   631 /*!
       
   632 
       
   633     This virtual function returns the linear interpolation between
       
   634     variants \a from and \a to, at \a progress, usually a value
       
   635     between 0 and 1. You can reimplement this function in a subclass
       
   636     of QVariantAnimation to provide your own interpolation algorithm.
       
   637 
       
   638     Note that in order for the interpolation to work with a
       
   639     QEasingCurve that return a value smaller than 0 or larger than 1
       
   640     (such as QEasingCurve::InBack) you should make sure that it can
       
   641     extrapolate. If the semantic of the datatype does not allow
       
   642     extrapolation this function should handle that gracefully.
       
   643 
       
   644     You should call the QVariantAnimation implementation of this
       
   645     function if you want your class to handle the types already
       
   646     supported by Qt (see class QVariantAnimation description for a
       
   647     list of supported types).
       
   648 
       
   649     \sa QEasingCurve
       
   650  */
       
   651 QVariant QVariantAnimation::interpolated(const QVariant &from, const QVariant &to, qreal progress) const
       
   652 {
       
   653     return d_func()->interpolator(from.constData(), to.constData(), progress);
       
   654 }
       
   655 
       
   656 /*!
       
   657     \reimp
       
   658  */
       
   659 void QVariantAnimation::updateCurrentTime(int)
       
   660 {
       
   661     d_func()->recalculateCurrentInterval();
       
   662 }
       
   663 
       
   664 QT_END_NAMESPACE
       
   665 
       
   666 #include "moc_qvariantanimation.cpp"
       
   667 
       
   668 #endif //QT_NO_ANIMATION