summaryrefslogtreecommitdiffstats
path: root/src/corelib/animation/qpropertyanimation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/animation/qpropertyanimation.cpp')
-rw-r--r--src/corelib/animation/qpropertyanimation.cpp99
1 files changed, 64 insertions, 35 deletions
diff --git a/src/corelib/animation/qpropertyanimation.cpp b/src/corelib/animation/qpropertyanimation.cpp
index ed20e667..65f1361 100644
--- a/src/corelib/animation/qpropertyanimation.cpp
+++ b/src/corelib/animation/qpropertyanimation.cpp
@@ -42,20 +42,20 @@
/*!
\class QPropertyAnimation
\brief The QPropertyAnimation class animates Qt properties
- \ingroup group_animation
- \preliminary
+ \since 4.6
+ \ingroup animation
QPropertyAnimation interpolates over \l{Qt's Property System}{Qt
properties}. As property values are stored in \l{QVariant}s, the
class inherits QVariantAnimation, and supports animation of the
- same \l{QVariant::Type}{variant types} as its super class.
+ same \l{QVariant::Type}{variant types} as its super class.
A class declaring properties must be a QObject. To make it
possible to animate a property, it must provide a setter (so that
QPropertyAnimation can set the property's value). Note that this
makes it possible to animate many of Qt's widgets. Let's look at
an example:
-
+
\code
QPropertyAnimation animation(myWidget, "geometry");
animation.setDuration(10000);
@@ -87,40 +87,37 @@
\sa QVariantAnimation, QAnimationGroup, {The Animation Framework}
*/
-#ifndef QT_NO_ANIMATION
-
#include "qpropertyanimation.h"
#include "qanimationgroup.h"
-#include <QtCore/qdebug.h>
-
#include "qpropertyanimation_p.h"
#include <QtCore/qmath.h>
#include <QtCore/qmutex.h>
+#include <private/qmutexpool_p.h>
+
+#ifndef QT_NO_ANIMATION
QT_BEGIN_NAMESPACE
typedef QPair<QObject *, QByteArray> QPropertyAnimationPair;
typedef QHash<QPropertyAnimationPair, QPropertyAnimation*> QPropertyAnimationHash;
-Q_GLOBAL_STATIC(QPropertyAnimationHash, _q_runningAnimations);
-Q_GLOBAL_STATIC_WITH_ARGS(QMutex, guardHashLock, (QMutex::Recursive) )
+Q_GLOBAL_STATIC(QPropertyAnimationHash, _q_runningAnimations)
void QPropertyAnimationPrivate::updateMetaProperty()
{
if (!target || propertyName.isEmpty())
return;
- if (hasMetaProperty == 0 && !property.isValid()) {
+ if (!hasMetaProperty && !property.isValid()) {
const QMetaObject *mo = target->metaObject();
propertyIndex = mo->indexOfProperty(propertyName);
if (propertyIndex != -1) {
- hasMetaProperty = 1;
+ hasMetaProperty = true;
property = mo->property(propertyIndex);
propertyType = property.userType();
} else {
if (!target->dynamicPropertyNames().contains(propertyName))
qWarning("QPropertyAnimation: you're trying to animate a non-existing property %s of your QObject", propertyName.constData());
- hasMetaProperty = 2;
}
}
@@ -133,7 +130,7 @@ void QPropertyAnimationPrivate::updateProperty(const QVariant &newValue)
if (!target || state == QAbstractAnimation::Stopped)
return;
- if (hasMetaProperty == 1) {
+ if (hasMetaProperty) {
if (newValue.userType() == propertyType) {
//no conversion is needed, we directly call the QObject::qt_metacall
void *data = const_cast<void*>(newValue.constData());
@@ -146,6 +143,14 @@ void QPropertyAnimationPrivate::updateProperty(const QVariant &newValue)
}
}
+void QPropertyAnimationPrivate::_q_targetDestroyed()
+{
+ Q_Q(QPropertyAnimation);
+ //we stop here so that this animation is removed from the global hash
+ q->stop();
+ target = 0;
+}
+
/*!
Construct a QPropertyAnimation object. \a parent is passed to QObject's
constructor.
@@ -188,14 +193,27 @@ QObject *QPropertyAnimation::targetObject() const
Q_D(const QPropertyAnimation);
return d->target;
}
+
void QPropertyAnimation::setTargetObject(QObject *target)
{
Q_D(QPropertyAnimation);
if (d->target == target)
return;
+ if (d->state != QAbstractAnimation::Stopped) {
+ qWarning("QPropertyAnimation::setTargetObject: you can't change the target of a running animation");
+ return;
+ }
+
+ //we need to get notified when the target is destroyed
+ if (d->target)
+ disconnect(d->target, SIGNAL(destroyed()), this, SLOT(_q_targetDestroyed()));
+
+ if (target)
+ connect(target, SIGNAL(destroyed()), SLOT(_q_targetDestroyed()));
+
d->target = target;
- d->hasMetaProperty = 0;
+ d->hasMetaProperty = false;
d->updateMetaProperty();
}
@@ -211,11 +229,17 @@ QByteArray QPropertyAnimation::propertyName() const
Q_D(const QPropertyAnimation);
return d->propertyName;
}
+
void QPropertyAnimation::setPropertyName(const QByteArray &propertyName)
{
Q_D(QPropertyAnimation);
+ if (d->state != QAbstractAnimation::Stopped) {
+ qWarning("QPropertyAnimation::setPropertyName: you can't change the property name of a running animation");
+ return;
+ }
+
d->propertyName = propertyName;
- d->hasMetaProperty = 0;
+ d->hasMetaProperty = false;
d->updateMetaProperty();
}
@@ -258,27 +282,32 @@ void QPropertyAnimation::updateState(QAbstractAnimation::State oldState,
}
QVariantAnimation::updateState(oldState, newState);
- QMutexLocker locker(guardHashLock());
- QPropertyAnimationHash * hash = _q_runningAnimations();
- QPropertyAnimationPair key(d->target, d->propertyName);
- if (newState == Running) {
- d->updateMetaProperty();
- QPropertyAnimation *oldAnim = hash->value(key, 0);
- if (oldAnim) {
- // try to stop the top level group
- QAbstractAnimation *current = oldAnim;
- while (current->group() && current->state() != Stopped)
- current = current->group();
- current->stop();
- }
- hash->insert(key, this);
- // update the default start value
- if (oldState == Stopped) {
- d->setDefaultStartValue(d->target->property(d->propertyName.constData()));
+ QPropertyAnimation *animToStop = 0;
+ {
+ QPropertyAnimationHash * hash = _q_runningAnimations();
+ QMutexLocker locker(QMutexPool::globalInstanceGet(hash));
+ QPropertyAnimationPair key(d->target, d->propertyName);
+ if (newState == Running) {
+ d->updateMetaProperty();
+ animToStop = hash->value(key, 0);
+ hash->insert(key, this);
+ // update the default start value
+ if (oldState == Stopped) {
+ d->setDefaultStartValue(d->target->property(d->propertyName.constData()));
+ }
+ } else if (hash->value(key) == this) {
+ hash->remove(key);
}
- } else if (hash->value(key) == this) {
- hash->remove(key);
+ }
+
+ //we need to do that after the mutex was unlocked
+ if (animToStop) {
+ // try to stop the top level group
+ QAbstractAnimation *current = animToStop;
+ while (current->group() && current->state() != Stopped)
+ current = current->group();
+ current->stop();
}
}