|
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 |