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