don't delete states when we're running animations: we call into other objects which may decide to stop or start other animations, which would cause double deletes. this one's bugged me (and our users; it's bee reported at least 18 times!) for a good long while, and finally tonight i figured it out :)
BUG:192066 svn path=/trunk/KDE/kdelibs/; revision=979139
This commit is contained in:
parent
8a4dc5460d
commit
74a6212595
133
animator.cpp
133
animator.cpp
@ -106,6 +106,7 @@ class AnimatorPrivate
|
||||
|
||||
~AnimatorPrivate()
|
||||
{
|
||||
cleanupStates();
|
||||
qDeleteAll(animatedItems);
|
||||
qDeleteAll(animatedElements);
|
||||
qDeleteAll(movingItems);
|
||||
@ -168,7 +169,9 @@ class AnimatorPrivate
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void init(Animator *q);
|
||||
void cleanupStates();
|
||||
void animatedItemDestroyed(QObject*);
|
||||
void movingItemDestroyed(QObject*);
|
||||
void animatedElementDestroyed(QObject*);
|
||||
@ -180,13 +183,17 @@ class AnimatorPrivate
|
||||
QTime time;
|
||||
QTimeLine timeline;
|
||||
|
||||
//TODO: eventually perhaps we should allow multiple animations simulataneously
|
||||
// which would imply changing this to a QMap<QGraphicsItem*, QList<QTimeLine*> >
|
||||
// and really making the code fun ;)
|
||||
QMap<QGraphicsItem*, AnimationState*> animatedItems;
|
||||
QMap<QGraphicsItem*, MovementState*> movingItems;
|
||||
QMap<int, ElementAnimationState*> animatedElements;
|
||||
QMap<int, CustomAnimationState*> customAnims;
|
||||
// active items
|
||||
QMap<QGraphicsItem *, AnimationState *> animatedItems;
|
||||
QMap<QGraphicsItem *, MovementState *> movingItems;
|
||||
QMap<int, ElementAnimationState *> animatedElements;
|
||||
QMap<int, CustomAnimationState *> customAnims;
|
||||
|
||||
// items to cull
|
||||
QList<AnimationState *> animatedItemsToDelete;
|
||||
QList<MovementState *> movingItemsToDelete;
|
||||
QList<ElementAnimationState *> animatedElementsToDelete;
|
||||
QList<CustomAnimationState *> customAnimsToDelete;
|
||||
};
|
||||
|
||||
class AnimatorSingleton
|
||||
@ -223,7 +230,12 @@ void AnimatorPrivate::animatedItemDestroyed(QObject *o)
|
||||
//kDebug() << "comparing against" << it.value()->qobj;
|
||||
if (it.value()->qobj == o) {
|
||||
kDebug() << "found deleted animated item";
|
||||
delete it.value();
|
||||
if (timerId) {
|
||||
animatedItemsToDelete.append(it.value());
|
||||
} else {
|
||||
delete it.value();
|
||||
}
|
||||
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
@ -235,7 +247,12 @@ void AnimatorPrivate::movingItemDestroyed(QObject *o)
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
if (it.value()->qobj == o) {
|
||||
delete it.value();
|
||||
if (timerId) {
|
||||
movingItemsToDelete.append(it.value());
|
||||
} else {
|
||||
delete it.value();
|
||||
}
|
||||
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
@ -247,7 +264,12 @@ void AnimatorPrivate::animatedElementDestroyed(QObject *o)
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
if (it.value()->qobj == o) {
|
||||
delete it.value();
|
||||
if (timerId) {
|
||||
animatedElementsToDelete.append(it.value());
|
||||
} else {
|
||||
delete it.value();
|
||||
}
|
||||
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
@ -258,8 +280,13 @@ void AnimatorPrivate::customAnimReceiverDestroyed(QObject *o)
|
||||
QMutableMapIterator<int, CustomAnimationState*> it(customAnims);
|
||||
while (it.hasNext()) {
|
||||
if (it.next().value()->receiver == o) {
|
||||
delete[] it.value()->slot;
|
||||
delete it.value();
|
||||
if (timerId) {
|
||||
customAnimsToDelete.append(it.value());
|
||||
} else {
|
||||
delete[] it.value()->slot;
|
||||
delete it.value();
|
||||
}
|
||||
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
@ -272,7 +299,12 @@ int Animator::animateItem(QGraphicsItem *item, Animation animation)
|
||||
//TODO: shoudl we allow multiple anims per item?
|
||||
QMap<QGraphicsItem*, AnimationState*>::iterator it = d->animatedItems.find(item);
|
||||
if (it != d->animatedItems.end()) {
|
||||
delete it.value();
|
||||
if (d->timerId) {
|
||||
d->animatedItemsToDelete.append(it.value());
|
||||
} else {
|
||||
delete it.value();
|
||||
}
|
||||
|
||||
d->animatedItems.erase(it);
|
||||
}
|
||||
|
||||
@ -322,8 +354,12 @@ int Animator::moveItem(QGraphicsItem *item, Movement movement, const QPoint &des
|
||||
//kDebug();
|
||||
QMap<QGraphicsItem*, MovementState*>::iterator it = d->movingItems.find(item);
|
||||
if (it != d->movingItems.end()) {
|
||||
delete it.value();
|
||||
d->movingItems.erase(it);
|
||||
if (d->timerId) {
|
||||
d->movingItemsToDelete.append(it.value());
|
||||
} else {
|
||||
delete it.value();
|
||||
d->movingItems.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
int frames = d->driver->movementAnimationFps(movement);
|
||||
@ -410,8 +446,13 @@ void Animator::stopCustomAnimation(int id)
|
||||
{
|
||||
QMap<int, CustomAnimationState*>::iterator it = d->customAnims.find(id);
|
||||
if (it != d->customAnims.end()) {
|
||||
delete [] it.value()->slot;
|
||||
delete it.value();
|
||||
if (d->timerId) {
|
||||
d->customAnimsToDelete.append(it.value());
|
||||
} else {
|
||||
delete [] it.value()->slot;
|
||||
delete it.value();
|
||||
}
|
||||
|
||||
d->customAnims.erase(it);
|
||||
}
|
||||
//kDebug() << "stopCustomAnimation(AnimId " << id << ") done";
|
||||
@ -423,8 +464,13 @@ void Animator::stopItemAnimation(int id)
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
if (it.value()->id == id) {
|
||||
delete it.value();
|
||||
it.remove();
|
||||
if (d->timerId) {
|
||||
d->animatedItemsToDelete.append(it.value());
|
||||
} else {
|
||||
delete it.value();
|
||||
it.remove();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -436,8 +482,13 @@ void Animator::stopItemMovement(int id)
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
if (it.value()->id == id) {
|
||||
delete it.value();
|
||||
it.remove();
|
||||
if (d->timerId) {
|
||||
d->movingItemsToDelete.append(it.value());
|
||||
} else {
|
||||
delete it.value();
|
||||
it.remove();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -493,7 +544,12 @@ void Animator::stopElementAnimation(int id)
|
||||
{
|
||||
QMap<int, ElementAnimationState*>::iterator it = d->animatedElements.find(id);
|
||||
if (it != d->animatedElements.end()) {
|
||||
delete it.value();
|
||||
if (d->timerId) {
|
||||
d->animatedElementsToDelete.append(it.value());
|
||||
} else {
|
||||
delete it.value();
|
||||
}
|
||||
|
||||
d->animatedElements.erase(it);
|
||||
}
|
||||
//kDebug() << "stopElementAnimation(AnimId " << id << ") done";
|
||||
@ -582,7 +638,7 @@ void Animator::timerEvent(QTimerEvent *event)
|
||||
d->performAnimation(1, state);
|
||||
d->animatedItems.erase(d->animatedItems.find(state->item));
|
||||
emit animationFinished(state->item, state->animation);
|
||||
delete state;
|
||||
d->animatedItemsToDelete.append(state);
|
||||
}
|
||||
} else {
|
||||
state->currentInterval -= elapsed;
|
||||
@ -609,7 +665,7 @@ void Animator::timerEvent(QTimerEvent *event)
|
||||
d->performMovement(1, state);
|
||||
d->movingItems.erase(d->movingItems.find(state->item));
|
||||
emit movementFinished(state->item);
|
||||
delete state;
|
||||
d->movingItemsToDelete.append(state);
|
||||
}
|
||||
} else {
|
||||
state->currentInterval -= elapsed;
|
||||
@ -645,7 +701,7 @@ void Animator::timerEvent(QTimerEvent *event)
|
||||
} else {
|
||||
d->animatedElements.remove(state->id);
|
||||
emit elementAnimationFinished(state->id);
|
||||
delete state;
|
||||
d->animatedElementsToDelete.append(state);
|
||||
}
|
||||
} else {
|
||||
state->currentInterval -= elapsed;
|
||||
@ -685,8 +741,7 @@ void Animator::timerEvent(QTimerEvent *event)
|
||||
}
|
||||
d->customAnims.erase(d->customAnims.find(state->id));
|
||||
emit customAnimationFinished(state->id);
|
||||
delete [] state->slot;
|
||||
delete state;
|
||||
d->customAnimsToDelete.append(state);
|
||||
}
|
||||
} else {
|
||||
state->currentInterval -= elapsed;
|
||||
@ -698,6 +753,8 @@ void Animator::timerEvent(QTimerEvent *event)
|
||||
killTimer(d->timerId);
|
||||
d->timerId = 0;
|
||||
}
|
||||
|
||||
d->cleanupStates();
|
||||
}
|
||||
|
||||
void AnimatorPrivate::init(Animator *q)
|
||||
@ -732,6 +789,28 @@ void AnimatorPrivate::init(Animator *q)
|
||||
}
|
||||
}
|
||||
|
||||
void AnimatorPrivate::cleanupStates()
|
||||
{
|
||||
/*
|
||||
kDebug() << animatedItemsToDelete.count() << animatedElementsToDelete.count()
|
||||
<< movingItemsToDelete.count() << customAnimsToDelete.count();
|
||||
*/
|
||||
qDeleteAll(animatedItemsToDelete);
|
||||
animatedItemsToDelete.clear();
|
||||
qDeleteAll(animatedElementsToDelete);
|
||||
animatedElementsToDelete.clear();
|
||||
qDeleteAll(movingItemsToDelete);
|
||||
movingItemsToDelete.clear();
|
||||
|
||||
QListIterator<CustomAnimationState*> it(customAnimsToDelete);
|
||||
while (it.hasNext()) {
|
||||
CustomAnimationState *state = it.next();
|
||||
delete[] state->slot;
|
||||
delete state;
|
||||
}
|
||||
customAnimsToDelete.clear();
|
||||
}
|
||||
|
||||
} // namespace Plasma
|
||||
|
||||
#include <animator.moc>
|
||||
|
Loading…
Reference in New Issue
Block a user