Qt 4.8
qvariantanimation.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
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 
53 
168 {
169  return p1.first < p2.first;
170 }
171 
172 static QVariant defaultInterpolator(const void *, const void *, qreal)
173 {
174  return QVariant();
175 }
176 
177 template<> Q_INLINE_TEMPLATE QRect _q_interpolate(const QRect &f, const QRect &t, qreal progress)
178 {
179  QRect ret;
180  ret.setCoords(_q_interpolate(f.left(), t.left(), progress),
181  _q_interpolate(f.top(), t.top(), progress),
182  _q_interpolate(f.right(), t.right(), progress),
183  _q_interpolate(f.bottom(), t.bottom(), progress));
184  return ret;
185 }
186 
187 template<> Q_INLINE_TEMPLATE QRectF _q_interpolate(const QRectF &f, const QRectF &t, qreal progress)
188 {
189  qreal x1, y1, w1, h1;
190  f.getRect(&x1, &y1, &w1, &h1);
191  qreal x2, y2, w2, h2;
192  t.getRect(&x2, &y2, &w2, &h2);
193  return QRectF(_q_interpolate(x1, x2, progress), _q_interpolate(y1, y2, progress),
194  _q_interpolate(w1, w2, progress), _q_interpolate(h1, h2, progress));
195 }
196 
197 template<> Q_INLINE_TEMPLATE QLine _q_interpolate(const QLine &f, const QLine &t, qreal progress)
198 {
199  return QLine( _q_interpolate(f.p1(), t.p1(), progress), _q_interpolate(f.p2(), t.p2(), progress));
200 }
201 
202 template<> Q_INLINE_TEMPLATE QLineF _q_interpolate(const QLineF &f, const QLineF &t, qreal progress)
203 {
204  return QLineF( _q_interpolate(f.p1(), t.p1(), progress), _q_interpolate(f.p2(), t.p2(), progress));
205 }
206 
208 { }
209 
211 {
212  //this ensures that all the keyValues are of type t
213  for (int i = 0; i < keyValues.count(); ++i) {
215  pair.second.convert(static_cast<QVariant::Type>(t));
216  }
217  //we also need update to the current interval if needed
218  currentInterval.start.second.convert(static_cast<QVariant::Type>(t));
219  currentInterval.end.second.convert(static_cast<QVariant::Type>(t));
220 
221  //... and the interpolator
223 }
224 
226 {
227  int type = currentInterval.start.second.userType();
228  if (type == currentInterval.end.second.userType())
230  else
231  interpolator = 0;
232 
233  //we make sure that the interpolator is always set to something
234  if (!interpolator)
236 }
237 
248 {
249  // can't interpolate if we don't have at least 2 values
250  if ((keyValues.count() + (defaultStartEndValue.isValid() ? 1 : 0)) < 2)
251  return;
252 
253  const qreal endProgress = (direction == QAbstractAnimation::Forward) ? qreal(1) : qreal(0);
254  const qreal progress = easing.valueForProgress(((duration == 0) ? endProgress : qreal(currentTime) / qreal(duration)));
255 
256  //0 and 1 are still the boundaries
257  if (force || (currentInterval.start.first > 0 && progress < currentInterval.start.first)
258  || (currentInterval.end.first < 1 && progress > currentInterval.end.first)) {
259  //let's update currentInterval
262  qMakePair(progress, QVariant()),
264  if (it == keyValues.constBegin()) {
265  //the item pointed to by it is the start element in the range
266  if (it->first == 0 && keyValues.count() > 1) {
267  currentInterval.start = *it;
268  currentInterval.end = *(it+1);
269  } else {
271  currentInterval.end = *it;
272  }
273  } else if (it == keyValues.constEnd()) {
274  --it; //position the iterator on the last item
275  if (it->first == 1 && keyValues.count() > 1) {
276  //we have an end value (item with progress = 1)
277  currentInterval.start = *(it-1);
278  currentInterval.end = *it;
279  } else {
280  //we use the default end value here
281  currentInterval.start = *it;
283  }
284  } else {
285  currentInterval.start = *(it-1);
286  currentInterval.end = *it;
287  }
288 
289  // update all the values of the currentInterval
291  }
292  setCurrentValueForProgress(progress);
293 }
294 
296 {
298 
299  const qreal startProgress = currentInterval.start.first;
300  const qreal endProgress = currentInterval.end.first;
301  const qreal localProgress = (progress - startProgress) / (endProgress - startProgress);
302 
303  QVariant ret = q->interpolated(currentInterval.start.second,
304  currentInterval.end.second,
305  localProgress);
306  qSwap(currentValue, ret);
307  q->updateCurrentValue(currentValue);
308  static QBasicAtomicInt changedSignalIndex = Q_BASIC_ATOMIC_INITIALIZER(0);
309  if (!changedSignalIndex) {
310  //we keep the mask so that we emit valueChanged only when needed (for performance reasons)
311  changedSignalIndex.testAndSetRelaxed(0, signalIndex("valueChanged(QVariant)"));
312  }
313  if (isSignalConnected(changedSignalIndex) && currentValue != ret) {
314  //the value has changed
315  emit q->valueChanged(currentValue);
316  }
317 }
318 
320 {
323  if (result != keyValues.constEnd())
324  return result->second;
325 
326  return QVariant();
327 }
328 
330 {
331  if (step < qreal(0.0) || step > qreal(1.0)) {
332  qWarning("QVariantAnimation::setValueAt: invalid step = %f", step);
333  return;
334  }
335 
336  QVariantAnimation::KeyValue pair(step, value);
337 
339  if (result == keyValues.end() || result->first != step) {
340  keyValues.insert(result, pair);
341  } else {
342  if (value.isValid())
343  result->second = value; // replaces the previous value
344  else
345  keyValues.erase(result); // removes the previous value
346  }
347 
348  recalculateCurrentInterval(/*force=*/true);
349 }
350 
352 {
353  defaultStartEndValue = value;
354  recalculateCurrentInterval(/*force=*/true);
355 }
356 
362 {
363 }
364 
369 {
370 }
371 
376 {
377 }
378 
405 {
406  Q_D(const QVariantAnimation);
407  return d->easing;
408 }
409 
411 {
413  d->easing = easing;
414  d->recalculateCurrentInterval();
415 }
416 
418 Q_GLOBAL_STATIC(QInterpolatorVector, registeredInterpolators)
419 
420 
448 {
449  // will override any existing interpolators
450  QInterpolatorVector *interpolators = registeredInterpolators();
451  // When built on solaris with GCC, the destructors can be called
452  // in such an order that we get here with interpolators == NULL,
453  // to continue causes the app to crash on exit with a SEGV
454  if (interpolators) {
455 #ifndef QT_NO_THREAD
456  QMutexLocker locker(QMutexPool::globalInstanceGet(interpolators));
457 #endif
458  if (int(interpolationType) >= interpolators->count())
459  interpolators->resize(int(interpolationType) + 1);
460  interpolators->replace(interpolationType, func);
461  }
462 }
463 
464 
465 template<typename T> static inline QVariantAnimation::Interpolator castToInterpolator(QVariant (*func)(const T &from, const T &to, qreal progress))
466 {
467  return reinterpret_cast<QVariantAnimation::Interpolator>(func);
468 }
469 
471 {
472  QInterpolatorVector *interpolators = registeredInterpolators();
473 #ifndef QT_NO_THREAD
474  QMutexLocker locker(QMutexPool::globalInstanceGet(interpolators));
475 #endif
477  if (interpolationType < interpolators->count()) {
478  ret = interpolators->at(interpolationType);
479  if (ret) return ret;
480  }
481 
482  switch(interpolationType)
483  {
484  case QMetaType::Int:
485  return castToInterpolator(_q_interpolateVariant<int>);
486  case QMetaType::UInt:
487  return castToInterpolator(_q_interpolateVariant<uint>);
488  case QMetaType::Double:
489  return castToInterpolator(_q_interpolateVariant<double>);
490  case QMetaType::Float:
491  return castToInterpolator(_q_interpolateVariant<float>);
492  case QMetaType::QLine:
493  return castToInterpolator(_q_interpolateVariant<QLine>);
494  case QMetaType::QLineF:
495  return castToInterpolator(_q_interpolateVariant<QLineF>);
496  case QMetaType::QPoint:
497  return castToInterpolator(_q_interpolateVariant<QPoint>);
498  case QMetaType::QPointF:
499  return castToInterpolator(_q_interpolateVariant<QPointF>);
500  case QMetaType::QSize:
501  return castToInterpolator(_q_interpolateVariant<QSize>);
502  case QMetaType::QSizeF:
503  return castToInterpolator(_q_interpolateVariant<QSizeF>);
504  case QMetaType::QRect:
505  return castToInterpolator(_q_interpolateVariant<QRect>);
506  case QMetaType::QRectF:
507  return castToInterpolator(_q_interpolateVariant<QRectF>);
508  default:
509  return 0; //this type is not handled
510  }
511 }
512 
525 int QVariantAnimation::duration() const
526 {
527  Q_D(const QVariantAnimation);
528  return d->duration;
529 }
530 
532 {
534  if (msecs < 0) {
535  qWarning("QVariantAnimation::setDuration: cannot set a negative duration");
536  return;
537  }
538  if (d->duration == msecs)
539  return;
540  d->duration = msecs;
541  d->recalculateCurrentInterval();
542 }
543 
559 {
560  return keyValueAt(0);
561 }
562 
564 {
565  setKeyValueAt(0, value);
566 }
567 
580 {
581  return keyValueAt(1);
582 }
583 
585 {
586  setKeyValueAt(1, value);
587 }
588 
589 
598 {
599  return d_func()->valueAt(step);
600 }
601 
623 {
624  d_func()->setValueAt(step, value);
625 }
626 
633 {
634  return d_func()->keyValues;
635 }
636 
644 {
646  d->keyValues = keyValues;
647  qSort(d->keyValues.begin(), d->keyValues.end(), animationValueLessThan);
648  d->recalculateCurrentInterval(/*force=*/true);
649 }
650 
672 {
673  Q_D(const QVariantAnimation);
674  if (!d->currentValue.isValid())
675  const_cast<QVariantAnimationPrivate*>(d)->recalculateCurrentInterval();
676  return d->currentValue;
677 }
678 
683 {
684  return QAbstractAnimation::event(event);
685 }
686 
691  QAbstractAnimation::State oldState)
692 {
693  Q_UNUSED(oldState);
694  Q_UNUSED(newState);
695 }
696 
717 QVariant QVariantAnimation::interpolated(const QVariant &from, const QVariant &to, qreal progress) const
718 {
719  return d_func()->interpolator(from.constData(), to.constData(), progress);
720 }
721 
726 {
727  d_func()->recalculateCurrentInterval();
728 }
729 
731 
732 #include "moc_qvariantanimation.cpp"
733 
734 #endif //QT_NO_ANIMATION
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
double d
Definition: qnumeric_p.h:62
void getRect(qreal *x, qreal *y, qreal *w, qreal *h) const
Extracts the position of the rectangle&#39;s top-left corner to *x and y, and its dimensions to *width an...
Definition: qrect.h:746
void setKeyValueAt(qreal step, const QVariant &value)
Creates a key frame at the given step with the given value.
KeyValues keyValues() const
Returns the key frames of this animation.
int type
Definition: qmetatype.cpp:239
qreal valueForProgress(qreal progress) const
Return the effective progress for the easing curve at progress.
double qreal
Definition: qglobal.h:1193
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
State
This enum describes the state of the animation.
The QEasingCurve class provides easing curves for controlling animation.
Definition: qeasingcurve.h:55
void replace(int i, const T &t)
Replaces the item at index position i with value.
Definition: qvector.h:382
The QLine class provides a two-dimensional vector using integer precision.
Definition: qline.h:57
void setValueAt(qreal, const QVariant &)
#define it(className, varName)
int count(const T &t) const
Returns the number of occurrences of value in the vector.
Definition: qvector.h:742
QPoint p1() const
Returns the line&#39;s start point.
Definition: qline.h:132
QPointF p1() const
Returns the line&#39;s start point.
Definition: qline.h:314
QPoint p2() const
Returns the line&#39;s end point.
Definition: qline.h:137
T1 first
Definition: qpair.h:65
const_iterator constEnd() const
Returns a const STL-style iterator pointing to the imaginary item after the last item in the vector...
Definition: qvector.h:252
QVariant valueAt(qreal step) const
T2 second
Definition: qpair.h:66
int left() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:240
QVariant endValue() const
void setEasingCurve(const QEasingCurve &easing)
Q_OUTOFLINE_TEMPLATE RandomAccessIterator qBinaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
Definition: qalgorithms.h:295
void setKeyValues(const KeyValues &values)
Replaces the current set of key frames with the given keyValues.
virtual QVariant interpolated(const QVariant &from, const QVariant &to, qreal progress) const
This virtual function returns the linear interpolation between variants from and to, at progress, usually a value between 0 and 1.
static Q_CORE_EXPORT QVariantAnimation::Interpolator getInterpolator(int interpolationType)
int bottom() const
Returns the y-coordinate of the rectangle&#39;s bottom edge.
Definition: qrect.h:249
void setEndValue(const QVariant &value)
The QVector class is a template class that provides a dynamic array.
Definition: qdatastream.h:64
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
#define Q_BASIC_ATOMIC_INITIALIZER(a)
Definition: qbasicatomic.h:218
QVariant keyValueAt(qreal step) const
Returns the key frame value for the given step.
#define Q_D(Class)
Definition: qglobal.h:2482
QAbstractAnimation::Direction direction
QVariant(* Interpolator)(const void *from, const void *to, qreal progress)
void setStartValue(const QVariant &value)
QVariant currentValue() const
void resize(int size)
Sets the size of the vector to size.
Definition: qvector.h:342
iterator end()
Returns an STL-style iterator pointing to the imaginary item after the last item in the vector...
Definition: qvector.h:250
#define Q_Q(Class)
Definition: qglobal.h:2483
The QLineF class provides a two-dimensional vector using floating point precision.
Definition: qline.h:212
void setDuration(int msecs)
static bool animationValueLessThan(const QVariantAnimation::KeyValue &p1, const QVariantAnimation::KeyValue &p2)
QEasingCurve easingCurve() const
const_iterator constBegin() const
Returns a const STL-style iterator pointing to the first item in the vector.
Definition: qvector.h:249
bool testAndSetRelaxed(int expectedValue, int newValue)
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
The QRectF class defines a rectangle in the plane using floating point precision. ...
Definition: qrect.h:511
The QVariantAnimation class provides an abstract base class for animations.
#define Q_GLOBAL_STATIC(TYPE, NAME)
Declares a global static variable with the given type and name.
Definition: qglobal.h:1968
#define emit
Definition: qobjectdefs.h:76
void setDefaultStartEndValue(const QVariant &value)
Q_CORE_EXPORT void qWarning(const char *,...)
#define Q_INLINE_TEMPLATE
Definition: qglobal.h:1713
void setCoords(int x1, int y1, int x2, int y2)
Sets the coordinates of the rectangle&#39;s top-left corner to (x1, y1), and the coordinates of its botto...
Definition: qrect.h:416
The QAbstractAnimation class is the base of all animations.
QVariantAnimation::KeyValues keyValues
void qSort(RandomAccessIterator start, RandomAccessIterator end)
Definition: qalgorithms.h:177
void qSwap(T &value1, T &value2)
Definition: qglobal.h:2181
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
bool convert(Type t)
Casts the variant to the requested type, t.
Definition: qvariant.cpp:2959
KeyValue * iterator
The QVector::iterator typedef provides an STL-style non-const iterator for QVector and QStack...
Definition: qvector.h:244
static QVariantAnimation::Interpolator castToInterpolator(QVariant(*func)(const T &from, const T &to, qreal progress))
QVariant startValue() const
void insert(int i, const T &t)
Inserts value at index position i in the vector.
Definition: qvector.h:362
Q_OUTOFLINE_TEMPLATE RandomAccessIterator qLowerBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value)
Definition: qalgorithms.h:227
int top() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:243
bool isSignalConnected(uint signalIdx) const
Returns true if the signal with index signal_index from object sender is connected.
Definition: qobject_p.h:237
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes...
Definition: qmutex.h:101
int right() const
Returns the x-coordinate of the rectangle&#39;s right edge.
Definition: qrect.h:246
QVariantAnimation::Interpolator interpolator
iterator begin()
Returns an STL-style iterator pointing to the first item in the vector.
Definition: qvector.h:247
void updateCurrentTime(int)
Reimplemented Function
QObject * parent() const
Returns a pointer to the parent object.
Definition: qobject.h:273
QVector< QVariantAnimation::Interpolator > QInterpolatorVector
iterator erase(iterator begin, iterator end)
Removes all the items from begin up to (but not including) end.
Definition: qvector.h:627
Q_OUTOFLINE_TEMPLATE QPair< T1, T2 > qMakePair(const T1 &x, const T2 &y)
Definition: qpair.h:102
void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
Reimplemented Function
const void * constData() const
Definition: qvariant.cpp:3065
void setCurrentValueForProgress(const qreal progress)
QPointF p2() const
Returns the line&#39;s end point.
Definition: qline.h:319
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
void recalculateCurrentInterval(bool force=false)
The goal of this function is to update the currentInterval member.
bool event(QEvent *event)
Reimplemented Function
QObject * parent
Definition: qobject.h:92
~QVariantAnimation()
Destroys the animation.
const KeyValue * const_iterator
The QVector::const_iterator typedef provides an STL-style const iterator for QVector and QStack...
Definition: qvector.h:245
int duration() const
static QVariant defaultInterpolator(const void *, const void *, qreal)
bool isValid() const
Returns true if the storage type of this variant is not QVariant::Invalid; otherwise returns false...
Definition: qvariant.h:485
Q_INLINE_TEMPLATE QRect _q_interpolate(const QRect &f, const QRect &t, qreal progress)
The QEvent class is the base class of all event classes.
Definition: qcoreevent.h:56
bool event(QEvent *event)
Reimplemented Function
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
static QMutex * globalInstanceGet(const void *address)
Returns a QMutex from the global mutex pool.
Definition: qmutexpool.cpp:150
struct QVariantAnimationPrivate::@1 currentInterval
QVariantAnimation(QObject *parent=0)
Construct a QVariantAnimation object.
int signalIndex(const char *signalName) const
Returns the signal index used in the internal connectionLists vector.
Definition: qobject.cpp:3719
static void registerInterpolator(Interpolator func, int interpolationType)