First step to improve new animations memory model.

Now the QAbstractAnimations will be cached when running an animation
(instead of creating and destroying them everytime the animation runs).

The next step is to cache *also* the configuration parameters (as aseigo suggested,
by having an event filter to detect changes in the animated widgets and reseting
the animation parameters as needed).


svn path=/trunk/KDE/kdelibs/; revision=1039531
This commit is contained in:
Adenilson Cavalcanti Da Silva 2009-10-23 18:39:57 +00:00
parent 042ed56b39
commit 1049afdab6
11 changed files with 153 additions and 69 deletions

View File

@ -48,6 +48,10 @@ AbstractAnimation::~AbstractAnimation()
void AbstractAnimation::setWidgetToAnimate(QGraphicsWidget* receiver)
{
d->animObject = receiver;
/* Changed the object, delete the animation */
delete d->animation.data();
d->animation.clear();
}
QGraphicsWidget* AbstractAnimation::widgetToAnimate()
@ -105,13 +109,23 @@ bool AbstractAnimation::isVisible() const
return d->animVisible;
}
QAbstractAnimation* AbstractAnimation::animation()
{
return d->animation.data();
}
void AbstractAnimation::setAnimation(QAbstractAnimation *obj)
{
d->animation = obj;
}
void AbstractAnimation::start()
{
QAbstractAnimation* anim = toQAbstractAnimation(parent());
if (anim) {
anim->setDirection(d->forwards ? QAbstractAnimation::Forward :
QAbstractAnimation::Backward);
anim->start(QAbstractAnimation::DeleteWhenStopped);
anim->start();
}
}

View File

@ -52,6 +52,7 @@ class PLASMA_EXPORT AbstractAnimation : public QObject
Q_PROPERTY(bool isVisible READ isVisible WRITE setVisible)
Q_PROPERTY(QGraphicsWidget *widgetToAnimate READ widgetToAnimate WRITE setWidgetToAnimate)
Q_PROPERTY(bool forwards READ forwards WRITE setForwards)
Q_PROPERTY(QAbstractAnimation* animation READ animation WRITE setAnimation)
public:
@ -139,6 +140,18 @@ public:
*/
bool isVisible() const;
/**
* Access the QAbstractAnimation of this plasma::Animation object.
*/
QAbstractAnimation *animation();
/**
* Access the QAbstractAnimation of this plasma::Animation object.
* @arg obj An animation pointer (it will be cleared by the object)
*/
void setAnimation(QAbstractAnimation *obj);
public slots:
/**

View File

@ -63,13 +63,15 @@ QAbstractAnimation* ExpandAnimation::render(QObject* parent)
break;
}
//create animation
QPropertyAnimation* anim = new QPropertyAnimation(m_object, "geometry", parent);
//Recreate only if needed
QPropertyAnimation *anim = dynamic_cast<QPropertyAnimation* >(animation());
if (!anim) {
anim = new QPropertyAnimation(m_object, "geometry", parent);
setAnimation(anim);
}
anim->setEndValue(geometry);
anim->setDuration(duration());
//QObject::connect(anim, SIGNAL(finished()), anim, SLOT(deleteLater()));
return anim;
}

View File

@ -76,7 +76,12 @@ void FadeAnimation::setWidgetToAnimate(QGraphicsWidget *widget)
QAbstractAnimation* FadeAnimation::render(QObject* parent)
{
//create animation
QPropertyAnimation* anim = new QPropertyAnimation(m_opacityEffect.data(), "opacity", parent);
QPropertyAnimation* anim = dynamic_cast<QPropertyAnimation* >(animation());
if (!anim) {
anim = new QPropertyAnimation(m_opacityEffect.data(), "opacity", parent);
setAnimation(anim);
}
anim->setStartValue(m_startOpacity);
anim->setEndValue(m_targetOpacity);
anim->setDuration(duration());

View File

@ -59,8 +59,13 @@ QAbstractAnimation* GrowAnimation::render(QObject* parent){
qreal newX = geometry.x() - w * locfactor;
qreal newY = geometry.y() - h * locfactor;
//create animation
QPropertyAnimation* anim = new QPropertyAnimation(m_object, "geometry", parent);
//Recreate only if needed
QPropertyAnimation *anim = dynamic_cast<QPropertyAnimation* >(animation());
if (!anim) {
anim = new QPropertyAnimation(m_object, "geometry", parent);
setAnimation(anim);
}
anim->setEndValue(QRectF(
newX, newY,
newWidth, newHeight));

View File

@ -31,8 +31,14 @@ PauseAnimation::PauseAnimation(QObject *parent)
QAbstractAnimation* PauseAnimation::render(QObject* parent)
{
//create animation
return new QPauseAnimation(duration(), parent);
//Recreate only if needed
QPauseAnimation *anim = dynamic_cast<QPauseAnimation* >(animation());
if (!anim) {
anim = new QPauseAnimation(duration(), parent);
setAnimation(anim);
}
return anim;
}
} //namespace Plasma

View File

@ -50,6 +50,7 @@ public :
QAbstractAnimation *animation;
QGraphicsWidget *under;
/* FIXME: clean up this guy */
QRectF *pulseGeometry;
qreal zvalue, mscale, mopacity;
QPropertyAnimation *opacityAnimation;
@ -88,25 +89,6 @@ void PulseAnimation::setCopy(QGraphicsWidget *copy)
d->mscale = d->under->scale();
}
void PulseAnimation::updateGeometry(QRectF updated, qreal zCoordinate, qreal scale)
{
d->zvalue = zCoordinate;
--d->zvalue;
d->under->setGeometry(updated);
d->under->setPos(0, 0);
d->under->setOpacity(0);
d->under->setZValue(d->zvalue);
/* TODO: move this to a function */
QRectF initial(d->under->geometry());
qreal W = initial.width() * scale * 0.33;
qreal H = initial.height() * scale * 0.33;
QRectF end(initial.x() - W, initial.y() - H, initial.width() * scale,
initial.height() * scale);
d->geometryAnimation->setEndValue(end);
}
void PulseAnimation::resetPulser()
{
d->under->setGeometry(*d->pulseGeometry);
@ -118,6 +100,7 @@ void PulseAnimation::resetPulser()
void PulseAnimation::createAnimation(qreal duration, qreal scale)
{
bool dirty = false;
QGraphicsWidget *target = widgetToAnimate();
/* Fallback to parent widget if we don't have one 'shadow' widget */
if (!d->under) {
@ -128,34 +111,53 @@ void PulseAnimation::createAnimation(qreal duration, qreal scale)
setCopy(d->under);
}
d->pulseGeometry = new QRectF(d->under->geometry());
QParallelAnimationGroup *group = new QParallelAnimationGroup(this);
d->opacityAnimation = new QPropertyAnimation(d->under, "opacity");
d->opacityAnimation->setDuration(duration);
d->opacityAnimation->setEndValue(0);
group->addAnimation(d->opacityAnimation);
/* TODO: move this to a function */
d->geometryAnimation = new QPropertyAnimation(d->under, "geometry");
d->geometryAnimation->setDuration(duration);
QRectF initial(d->under->geometry());
qreal W = initial.width() * scale * 0.33;
qreal H = initial.height() * scale * 0.33;
QRectF end(initial.x() - W, initial.y() - H, initial.width() * scale,
initial.height() * scale);
d->geometryAnimation->setEndValue(end);
group->addAnimation(d->geometryAnimation);
QParallelAnimationGroup *anim = dynamic_cast<QParallelAnimationGroup* >(animation());
if (!anim) {
d->pulseGeometry = new QRectF(d->under->geometry());
QParallelAnimationGroup *group = new QParallelAnimationGroup(this);
d->opacityAnimation = new QPropertyAnimation(d->under, "opacity");
d->opacityAnimation->setDuration(duration);
d->opacityAnimation->setEndValue(0);
group->addAnimation(d->opacityAnimation);
d->scaleAnimation = new QPropertyAnimation(d->under, "scale");
d->scaleAnimation->setDuration(duration);
d->scaleAnimation->setEndValue(scale);
group->addAnimation(d->scaleAnimation);
/* TODO: move this to a function */
d->geometryAnimation = new QPropertyAnimation(d->under, "geometry");
d->geometryAnimation->setDuration(duration);
QRectF initial(d->under->geometry());
qreal W = initial.width() * scale * 0.33;
qreal H = initial.height() * scale * 0.33;
QRectF end(initial.x() - W, initial.y() - H, initial.width() * scale,
initial.height() * scale);
d->geometryAnimation->setEndValue(end);
group->addAnimation(d->geometryAnimation);
d->animation = group;
d->scaleAnimation = new QPropertyAnimation(d->under, "scale");
d->scaleAnimation->setDuration(duration);
d->scaleAnimation->setEndValue(scale);
/* The group takes ownership of all animations */
group->addAnimation(d->scaleAnimation);
d->animation = group;
setAnimation(d->animation);
dirty = true;
//This makes sure that if there is *not* a shadow widget, the
//parent widget will still remain visible
connect(d->animation, SIGNAL(finished()), this, SLOT(resetPulser()));
} else {
*(d->pulseGeometry) = d->under->geometry();
d->opacityAnimation->setEndValue(0);
QRectF initial(d->under->geometry());
qreal W = initial.width() * scale * 0.33;
qreal H = initial.height() * scale * 0.33;
QRectF end(initial.x() - W, initial.y() - H, initial.width() * scale,
initial.height() * scale);
d->geometryAnimation->setEndValue(end);
}
if (dirty) {
//This makes sure that if there is *not* a shadow widget, the
//parent widget will still remain visible
connect(d->animation, SIGNAL(finished()), this, SLOT(resetPulser()));
}
}
QAbstractAnimation* PulseAnimation::render(QObject* parent)

View File

@ -143,7 +143,12 @@ QPropertyAnimation *RotationAnimation::render(QObject *parent)
transformation.append(d->rotation);
m_object->setTransformations(transformation);
QPropertyAnimation *rotationAnimation= new QPropertyAnimation(d->rotation, "angle", m_object);
QPropertyAnimation *rotationAnimation = dynamic_cast<QPropertyAnimation* >(animation());
if (!rotationAnimation) {
rotationAnimation = new QPropertyAnimation(d->rotation, "angle", m_object);
setAnimation(rotationAnimation);
}
rotationAnimation->setStartValue(0);
rotationAnimation->setEndValue(angle());
rotationAnimation->setDuration(duration());

View File

@ -24,6 +24,7 @@
#include <QGraphicsRotation>
#include <QSequentialAnimationGroup>
#include <kdebug.h>
namespace Plasma
{
@ -51,6 +52,9 @@ RotationStackedAnimation::RotationStackedAnimation(QObject *parent)
RotationStackedAnimation::~RotationStackedAnimation()
{
/* XXX: do we need to delete the layout if the 'parent' layout is
* deleted too ?
*/
delete d->sLayout;
delete d;
}
@ -88,13 +92,26 @@ QGraphicsLayoutItem *RotationStackedAnimation::layout()
QAbstractAnimation *RotationStackedAnimation::render(QObject *parent)
{
Q_UNUSED(parent);
bool dirty = false;
QPair<QGraphicsWidget *,QGraphicsWidget *> widgets = qMakePair(widgetToAnimate(), d->backWidget);
QPropertyAnimation *frontAnim, *backAnim;
QSequentialAnimationGroup *groupAnim = dynamic_cast<QSequentialAnimationGroup* >(animation());
if (!groupAnim) {
QSequentialAnimationGroup *groupAnim = new QSequentialAnimationGroup(parent);
QPropertyAnimation *frontAnim = new QPropertyAnimation(d->frontRotation, "angle", groupAnim);
QPropertyAnimation *backAnim = new QPropertyAnimation(d->backRotation, "angle", groupAnim);
groupAnim = new QSequentialAnimationGroup(parent);
frontAnim = new QPropertyAnimation(d->frontRotation, "angle", groupAnim);
backAnim = new QPropertyAnimation(d->backRotation, "angle", groupAnim);
setAnimation(groupAnim);
dirty = true;
} else {
if (groupAnim->animationCount() == 2) {
frontAnim = dynamic_cast<QPropertyAnimation* >(groupAnim->animationAt(0));
backAnim = dynamic_cast<QPropertyAnimation* >(groupAnim->animationAt(1));
} else {
kDebug() << "_ Where are my little animations? Duh!";
return groupAnim;
}
}
const qreal widgetFrontWidth = widgets.first->size().width();
const qreal widgetFrontHeight = widgets.first->size().height();
@ -137,10 +154,11 @@ QAbstractAnimation *RotationStackedAnimation::render(QObject *parent)
frontAnim->setDuration(duration()/2);
backAnim->setDuration(duration()/2);
connect(frontAnim, SIGNAL(finished()), this, SLOT(rotateBackWidget()));
groupAnim->addAnimation(frontAnim);
groupAnim->addAnimation(backAnim);
if (dirty) {
connect(frontAnim, SIGNAL(finished()), this, SLOT(rotateBackWidget()));
groupAnim->addAnimation(frontAnim);
groupAnim->addAnimation(backAnim);
}
return groupAnim;
}

View File

@ -34,6 +34,7 @@ SlideAnimation::SlideAnimation(AnimationDirection direction, qreal distance)
QAbstractAnimation* SlideAnimation::render(QObject* parent)
{
bool dirty = false;
QGraphicsWidget *m_object = widgetToAnimate();
qreal x = m_object->x();
qreal y = m_object->y();
@ -67,18 +68,25 @@ QAbstractAnimation* SlideAnimation::render(QObject* parent)
break;
}
QPropertyAnimation* anim = new QPropertyAnimation(m_object, "pos", parent);
//Recreate only if needed
QPropertyAnimation* anim = dynamic_cast<QPropertyAnimation* >(animation());
if (!anim) {
anim = new QPropertyAnimation(m_object, "pos", parent);
setAnimation(anim);
dirty = true;
}
anim->setEndValue(QPointF(newX, newY));
anim->setDuration(duration());
//QObject::connect(anim, SIGNAL(finished()), anim, SLOT(deleteLater()));
if (isVisible()) {
QObject::connect(anim, SIGNAL(finished()), m_object, SLOT(show()));
} else {
QObject::connect(anim, SIGNAL(finished()), m_object, SLOT(hide()));
if (dirty) {
if (isVisible()) {
QObject::connect(anim, SIGNAL(finished()), m_object, SLOT(show()));
} else {
QObject::connect(anim, SIGNAL(finished()), m_object, SLOT(hide()));
}
}
return anim;
}

View File

@ -23,6 +23,7 @@
#include <QEasingCurve>
#include <QWeakPointer>
class QAbstractAnimation;
namespace Plasma
{
@ -37,6 +38,11 @@ public:
*/
QWeakPointer<QGraphicsWidget> animObject;
/**
* All animations will have *at least* one animation property
*/
QWeakPointer<QAbstractAnimation> animation;
/**
* Animation direction: where the animation will move.
*/