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