diff options
-rw-r--r-- | src/corelib/statemachine/qstatemachine.cpp | 111 | ||||
-rw-r--r-- | src/corelib/statemachine/qstatemachine.h | 16 | ||||
-rw-r--r-- | src/corelib/statemachine/qstatemachine_p.h | 9 | ||||
-rw-r--r-- | tests/auto/qstatemachine/tst_qstatemachine.cpp | 140 |
4 files changed, 272 insertions, 4 deletions
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 0a1d248..1f8d8a8 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -612,8 +612,17 @@ void QStateMachinePrivate::applyProperties(const QList<QAbstractTransition*> &tr // Find the animations to use for the state change. QList<QAbstractAnimation*> selectedAnimations; - for (int i = 0; i < transitionList.size(); ++i) - selectedAnimations << transitionList.at(i)->animations(); + for (int i = 0; i < transitionList.size(); ++i) { + QAbstractTransition *transition = transitionList.at(i); + + selectedAnimations << transition->animations(); + selectedAnimations << defaultAnimationsForSource.values(transition->sourceState()); + + QList<QAbstractState *> targetStates = transition->targetStates(); + for (int j=0; j<targetStates.size(); ++j) + selectedAnimations << defaultAnimationsForTarget.values(targetStates.at(j)); + } + selectedAnimations << defaultAnimations; #else Q_UNUSED(transitionList); #endif @@ -1828,6 +1837,104 @@ void QStateMachine::endMicrostep(QEvent *event) Q_UNUSED(event); } +#ifndef QT_NO_ANIMATION + +/*! + Adds a default \a animation to be considered for any transition. +*/ +void QStateMachine::addDefaultAnimation(QAbstractAnimation *animation) +{ + Q_D(QStateMachine); + d->defaultAnimations.append(animation); +} + +/*! + Returns the list of default animations that will be considered for any transition. +*/ +QList<QAbstractAnimation*> QStateMachine::defaultAnimations() const +{ + Q_D(const QStateMachine); + return d->defaultAnimations; +} + +/*! + Removes \a animation from the list of default animations. +*/ +void QStateMachine::removeDefaultAnimation(QAbstractAnimation *animation) +{ + Q_D(QStateMachine); + d->defaultAnimations.removeAll(animation); +} + + +/*! + Adds a default \a animation to be considered for any transition with the source state + \a sourceState. +*/ +void QStateMachine::addDefaultAnimationForSourceState(QAbstractState *sourceState, + QAbstractAnimation *animation) +{ + Q_D(QStateMachine); + d->defaultAnimationsForSource.insert(sourceState, animation); +} + + +/*! + Returns the list of default animations that will be considered for any transition with + the source state \a sourceState. +*/ +QList<QAbstractAnimation*> QStateMachine::defaultAnimationsForSourceState(QAbstractState *sourceState) const +{ + Q_D(const QStateMachine); + return d->defaultAnimationsForSource.values(sourceState); +} + +/*! + Removes \a animation from the list of default animations for the source state + \a sourceState. +*/ +void QStateMachine::removeDefaultAnimationForSourceState(QAbstractState *sourceState, + QAbstractAnimation *animation) +{ + Q_D(QStateMachine); + d->defaultAnimationsForSource.remove(sourceState, animation); +} + +/*! + Adds a default \a animation to be considered for any transition with the target state + \a targetState. +*/ +void QStateMachine::addDefaultAnimationForTargetState(QAbstractState *targetState, + QAbstractAnimation *animation) +{ + Q_D(QStateMachine); + d->defaultAnimationsForTarget.insert(targetState, animation); +} + +/*! + Returns the list of default animations that will be considered for any transition with + the target state \a targetState. +*/ +QList<QAbstractAnimation *> QStateMachine::defaultAnimationsForTargetState(QAbstractState *targetState) const +{ + Q_D(const QStateMachine); + return d->defaultAnimationsForTarget.values(targetState); +} + +/*! + Removes \a animation from the list of default animations for the target state + \a targetState. +*/ +void QStateMachine::removeDefaultAnimationForTargetState(QAbstractState *targetState, + QAbstractAnimation *animation) +{ + Q_D(QStateMachine); + d->defaultAnimationsForTarget.remove(targetState, animation); +} + +#endif // QT_NO_ANIMATION + + static const uint qt_meta_data_QSignalEventGenerator[] = { // content: diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h index c7de171..f39efc7 100644 --- a/src/corelib/statemachine/qstatemachine.h +++ b/src/corelib/statemachine/qstatemachine.h @@ -63,6 +63,8 @@ class QAbstractState; class QState; class QStateMachinePrivate; +class QAbstractAnimation; +class QAbstractState; class Q_CORE_EXPORT QStateMachine : public QObject { Q_OBJECT @@ -96,6 +98,20 @@ public: QString errorString() const; void clearError(); +#ifndef QT_NO_ANIMATION + void addDefaultAnimation(QAbstractAnimation *animation); + QList<QAbstractAnimation *> defaultAnimations() const; + void removeDefaultAnimation(QAbstractAnimation *animation); + + void addDefaultAnimationForSourceState(QAbstractState *sourceState, QAbstractAnimation *animation); + QList<QAbstractAnimation *> defaultAnimationsForSourceState(QAbstractState *sourceState) const; + void removeDefaultAnimationForSourceState(QAbstractState *sourceState, QAbstractAnimation *animation); + + void addDefaultAnimationForTargetState(QAbstractState *targetState, QAbstractAnimation *animation); + QList<QAbstractAnimation *> defaultAnimationsForTargetState(QAbstractState *targetState) const; + void removeDefaultAnimationForTargetState(QAbstractState *targetState, QAbstractAnimation *animation); +#endif // QT_NO_ANIMATION + QAbstractState::RestorePolicy globalRestorePolicy() const; void setGlobalRestorePolicy(QAbstractState::RestorePolicy restorePolicy); diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index 04dc71e..a9fd2de 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -169,7 +169,7 @@ public: QSet<QAbstractState*> configuration; QList<QEvent*> internalEventQueue; QList<QEvent*> externalEventQueue; - + QStateMachine::Error error; QActionState::RestorePolicy globalRestorePolicy; @@ -186,7 +186,12 @@ public: QList<QPair<QAbstractAnimation*, QPropertyAssignment> > propertiesForAnimations; QList<QAbstractAnimation*> playingAnimations; QList<QAbstractAnimation*> resetEndValues; -#endif + + QList<QAbstractAnimation *> defaultAnimations; + QMultiHash<QAbstractState *, QAbstractAnimation *> defaultAnimationsForSource; + QMultiHash<QAbstractState *, QAbstractAnimation *> defaultAnimationsForTarget; + +#endif // QT_NO_ANIMATION #ifndef QT_STATEMACHINE_SOLUTION QSignalEventGenerator *signalEventGenerator; diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index be80bed..5796161 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -141,6 +141,10 @@ private slots: void nestedTargetStateForAnimation(); void animatedGlobalRestoreProperty(); void specificTargetValueOfAnimation(); + void addDefaultAnimation(); + void addDefaultAnimationWithUnusedAnimation(); + void addDefaultAnimationForSource(); + void addDefaultAnimationForTarget(); }; tst_QStateMachine::tst_QStateMachine() @@ -2437,6 +2441,142 @@ void tst_QStateMachine::specificTargetValueOfAnimation() QCOMPARE(anim->endValue().toDouble(), 10.0); } +void tst_QStateMachine::addDefaultAnimation() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + + QState *s1 = new QState(machine.rootState()); + + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "foo", 2.0); + + QState *s3 = new QState(machine.rootState()); + s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + + s1->addTransition(new EventTransition(QEvent::User, s2)); + + QPropertyAnimation *pa = new QPropertyAnimation(object, "foo", &machine); + machine.addDefaultAnimation(pa); + s2->addTransition(pa, SIGNAL(finished()), s3); + + machine.setInitialState(s1); + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(object->property("foo").toDouble(), 2.0); +} + +void tst_QStateMachine::addDefaultAnimationWithUnusedAnimation() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + object->setProperty("bar", 2.0); + + SlotCalledCounter counter; + + QState *s1 = new QState(machine.rootState()); + + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "foo", 2.0); + + QState *s3 = new QState(machine.rootState()); + s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + + s1->addTransition(new EventTransition(QEvent::User, s2)); + + QPropertyAnimation *pa = new QPropertyAnimation(object, "foo", &machine); + connect(pa, SIGNAL(finished()), &counter, SLOT(slot())); + machine.addDefaultAnimation(pa); + s2->addTransition(pa, SIGNAL(finished()), s3); + + pa = new QPropertyAnimation(object, "bar", &machine); + connect(pa, SIGNAL(finished()), &counter, SLOT(slot())); + machine.addDefaultAnimation(pa); + + machine.setInitialState(s1); + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(object->property("foo").toDouble(), 2.0); + QCOMPARE(counter.counter, 1); +} + +void tst_QStateMachine::addDefaultAnimationForSource() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + + QState *s1 = new QState(machine.rootState()); + + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "foo", 2.0); + + QState *s3 = new QState(machine.rootState()); + s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + + s1->addTransition(new EventTransition(QEvent::User, s2)); + + QPropertyAnimation *pa = new QPropertyAnimation(object, "foo", &machine); + machine.addDefaultAnimationForSourceState(s1, pa); + s2->addTransition(pa, SIGNAL(finished()), s3); + + machine.setInitialState(s1); + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(object->property("foo").toDouble(), 2.0); +} + +void tst_QStateMachine::addDefaultAnimationForTarget() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + + QState *s1 = new QState(machine.rootState()); + + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "foo", 2.0); + + QState *s3 = new QState(machine.rootState()); + s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + + s1->addTransition(new EventTransition(QEvent::User, s2)); + + QPropertyAnimation *pa = new QPropertyAnimation(object, "foo", &machine); + machine.addDefaultAnimationForTargetState(s2, pa); + s2->addTransition(pa, SIGNAL(finished()), s3); + + machine.setInitialState(s1); + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(object->property("foo").toDouble(), 2.0); +} QTEST_MAIN(tst_QStateMachine) #include "tst_qstatemachine.moc" |