Commit 3a5f473a16b3bc64e6793a9a5002d961a2a0762a

  • avatar
  • thierry
  • Wed Mar 17 11:30:59 CET 2010
Fix a crash in animation groups when deleting uncontrolled animations

The problem was that we were not removing their references from the
private object hash and at some point we could access it.

Task-number: QTBUG-8910
Reviewed-by: gabi
  
244244 // in ChildRemoved event
245245 d->animations.removeAt(index);
246246 animation->setParent(0);
247 d->animationRemovedAt(index);
247 d->animationRemoved(index, animation);
248248 return animation;
249249}
250250
285285}
286286
287287
288void QAnimationGroupPrivate::animationRemovedAt(int index)
288void QAnimationGroupPrivate::animationRemoved(int index, QAbstractAnimation *)
289289{
290290 Q_Q(QAnimationGroup);
291291 Q_UNUSED(index);
  
7272 isGroup = true;
7373 }
7474
75 virtual void animationInsertedAt(int index) { Q_UNUSED(index) };
76 virtual void animationRemovedAt(int index);
75 virtual void animationInsertedAt(int) { }
76 virtual void animationRemoved(int, QAbstractAnimation *);
77
78 void disconnectUncontrolledAnimation(QAbstractAnimation *anim)
79 {
80 //0 for the signal here because we might be called from the animation destructor
81 QObject::disconnect(anim, 0, q_func(), SLOT(_q_uncontrolledAnimationFinished()));
82 }
83
84 void connectUncontrolledAnimation(QAbstractAnimation *anim)
85 {
86 QObject::connect(anim, SIGNAL(finished()), q_func(), SLOT(_q_uncontrolledAnimationFinished()));
87 }
7788
7889 QList<QAbstractAnimation *> animations;
7990};
  
246246
247247void QParallelAnimationGroupPrivate::disconnectUncontrolledAnimations()
248248{
249 Q_Q(QParallelAnimationGroup);
250
251249 QHash<QAbstractAnimation *, int>::iterator it = uncontrolledFinishTime.begin();
252250 while (it != uncontrolledFinishTime.end()) {
253 QObject::disconnect(it.key(), SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished()));
251 disconnectUncontrolledAnimation(it.key());
254252 ++it;
255253 }
256254
257257
258258void QParallelAnimationGroupPrivate::connectUncontrolledAnimations()
259259{
260 Q_Q(QParallelAnimationGroup);
261
262260 for (int i = 0; i < animations.size(); ++i) {
263261 QAbstractAnimation *animation = animations.at(i);
264262 if (animation->duration() == -1 || animation->loopCount() < 0) {
265263 uncontrolledFinishTime[animation] = -1;
266 QObject::connect(animation, SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished()));
264 connectUncontrolledAnimation(animation);
267265 }
268266 }
269267}
299299bool QParallelAnimationGroupPrivate::isUncontrolledAnimationFinished(QAbstractAnimation *anim) const
300300{
301301 return uncontrolledFinishTime.value(anim, -1) >= 0;
302}
303
304void QParallelAnimationGroupPrivate::animationRemoved(int index, QAbstractAnimation *anim)
305{
306 QAnimationGroupPrivate::animationRemoved(index, anim);
307 disconnectUncontrolledAnimation(anim);
308 uncontrolledFinishTime.remove(anim);
302309}
303310
304311/*!
  
8080 void connectUncontrolledAnimations();
8181 void disconnectUncontrolledAnimations();
8282
83 void animationRemoved(int index, QAbstractAnimation *);
84
8385 // private slot
8486 void _q_uncontrolledAnimationFinished();
8587};
  
479479
480480 // connects to the finish signal of uncontrolled animations
481481 if (currentAnimation->totalDuration() == -1)
482 QObject::connect(currentAnimation, SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished()));
482 connectUncontrolledAnimation(currentAnimation);
483483
484484 currentAnimation->start();
485485 if (!intermediate && state == QSequentialAnimationGroup::Paused)
496496 actualDuration.append(-1);
497497 actualDuration[currentAnimationIndex] = currentAnimation->currentTime();
498498
499 QObject::disconnect(currentAnimation, SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished()));
499 disconnectUncontrolledAnimation(currentAnimation);
500500
501501 if ((direction == QAbstractAnimation::Forward && currentAnimation == animations.last())
502502 || (direction == QAbstractAnimation::Backward && currentAnimationIndex == 0)) {
543543 the group at index \a index. The animation is no more listed when this
544544 method is called.
545545*/
546void QSequentialAnimationGroupPrivate::animationRemovedAt(int index)
546void QSequentialAnimationGroupPrivate::animationRemoved(int index, QAbstractAnimation *anim)
547547{
548548 Q_Q(QSequentialAnimationGroup);
549 QAnimationGroupPrivate::animationRemovedAt(index);
549 QAnimationGroupPrivate::animationRemoved(index, anim);
550550
551551 Q_ASSERT(currentAnimation); // currentAnimation should always be set
552552
555555
556556 const int currentIndex = animations.indexOf(currentAnimation);
557557 if (currentIndex == -1) {
558 //we're removing the current animation, let's update it to another one
558 //we're removing the current animation
559
560 disconnectUncontrolledAnimation(currentAnimation);
561
559562 if (index < animations.count())
560563 setCurrentAnimation(index); //let's try to take the next one
561564 else if (index > 0)
  
8585 void activateCurrentAnimation(bool intermediate = false);
8686
8787 void animationInsertedAt(int index);
88 void animationRemovedAt(int index);
88 void animationRemoved(int index, QAbstractAnimation *anim);
8989
9090 bool atEnd() const;
9191
  
7575 void loopCount();
7676 void autoAdd();
7777 void pauseResume();
78
79 void QTBUG8910_crashWhenRemovingUncontrolledAnimation();
7880};
7981
8082tst_QParallelAnimationGroup::tst_QParallelAnimationGroup()
10011001 QCOMPARE(spy.count(), 2); //this shouldn't have changed
10021002 group.resume();
10031003 QCOMPARE(spy.count(), 2); //this shouldn't have changed
1004}
10041005
10051006
1006
1007void tst_QParallelAnimationGroup::QTBUG8910_crashWhenRemovingUncontrolledAnimation()
1008{
1009 QParallelAnimationGroup group;
1010 TestAnimation *anim = new TestAnimation;
1011 anim->setLoopCount(-1);
1012 TestAnimation *anim2 = new TestAnimation;
1013 anim2->setLoopCount(-1);
1014 group.addAnimation(anim);
1015 group.addAnimation(anim2);
1016 group.start();
1017 delete anim;
1018 // it would crash here because the internals of the group would still have a reference to anim
1019 delete anim2;
10071020}
10081021
10091022