void QParallelAnimationGroupPrivate::disconnectUncontrolledAnimations()
{
    QHash<QAbstractAnimation *, int>::iterator it = uncontrolledFinishTime.begin();
    while (it != uncontrolledFinishTime.end()) {
        disconnectUncontrolledAnimation(it.key());
        ++it;
    }

    uncontrolledFinishTime.clear();
}
/*!
    \internal
    This method is called whenever an animation is removed from
    the group at index \a index. The animation is no more listed when this
    method is called.
*/
void QSequentialAnimationGroupPrivate::animationRemoved(int index, QAbstractAnimation *anim)
{
    Q_Q(QSequentialAnimationGroup);
    QAnimationGroupPrivate::animationRemoved(index, anim);

    Q_ASSERT(currentAnimation); // currentAnimation should always be set

    if (actualDuration.size() > index)
        actualDuration.removeAt(index);

    const int currentIndex = animations.indexOf(currentAnimation);
    if (currentIndex == -1) {
        //we're removing the current animation

        disconnectUncontrolledAnimation(currentAnimation);

        if (index < animations.count())
            setCurrentAnimation(index); //let's try to take the next one
        else if (index > 0)
            setCurrentAnimation(index - 1);
        else// case all animations were removed
            setCurrentAnimation(-1);
    } else if (currentAnimationIndex > index) {
        currentAnimationIndex--;
    }

    // duration of the previous animations up to the current animation
    currentTime = 0;
    for (int i = 0; i < currentAnimationIndex; ++i) {
        const int current = animationActualTotalDuration(i);
        currentTime += current;
    }

    if (currentIndex != -1) {
        //the current animation is not the one being removed
        //so we add its current time to the current time of this group
        currentTime += QAbstractAnimationPrivate::get(currentAnimation)->totalCurrentTime;
    }

    //let's also update the total current time
    totalCurrentTime = currentTime + loopCount * q->duration();
}
void QSequentialAnimationGroupPrivate::_q_uncontrolledAnimationFinished()
{
    Q_Q(QSequentialAnimationGroup);
    Q_ASSERT(qobject_cast<QAbstractAnimation *>(q->sender()) == currentAnimation);

    // we trust the duration returned by the animation
    while (actualDuration.size() < (currentAnimationIndex + 1))
        actualDuration.append(-1);
    actualDuration[currentAnimationIndex] = currentAnimation->currentTime();

    disconnectUncontrolledAnimation(currentAnimation);

    if ((direction == QAbstractAnimation::Forward && currentAnimation == animations.last())
        || (direction == QAbstractAnimation::Backward && currentAnimationIndex == 0)) {
        // we don't handle looping of a group with undefined duration
        q->stop();
    } else if (direction == QAbstractAnimation::Forward) {
        // set the current animation to be the next one
        setCurrentAnimation(currentAnimationIndex + 1);
    } else {
        // set the current animation to be the previous one
        setCurrentAnimation(currentAnimationIndex - 1);
    }
}
void QParallelAnimationGroupPrivate::animationRemoved(int index, QAbstractAnimation *anim)
{
    QAnimationGroupPrivate::animationRemoved(index, anim);
    disconnectUncontrolledAnimation(anim);
    uncontrolledFinishTime.remove(anim);
}