From 381e67f03155167cd9c1c0c3c4c3905196f287df Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 21 Apr 2009 14:53:34 +0200 Subject: compile. --- tests/auto/qstate/tst_qstate.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/auto/qstate/tst_qstate.cpp b/tests/auto/qstate/tst_qstate.cpp index f28c3fa..f79fcd4 100644 --- a/tests/auto/qstate/tst_qstate.cpp +++ b/tests/auto/qstate/tst_qstate.cpp @@ -9,7 +9,7 @@ #include "qstate.h" #include "qstatemachine.h" -#include "qtransition.h" +#include "qactiontransition.h" #include "qsignaltransition.h" #include "qstateaction.h" @@ -265,11 +265,11 @@ void tst_QState::assignPropertyTwice() QCOMPARE(object->property("fooBar").toInt(), 30); } -class EventTestTransition: public QTransition +class EventTestTransition: public QActionTransition { public: EventTestTransition(QEvent::Type type, QState *targetState) - : QTransition(QList() << targetState), m_type(type) + : QActionTransition(QList() << targetState), m_type(type) { } -- cgit v0.12 From ae6ab698ea739ac82cc6245742b58c7265ee82f8 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 21 Apr 2009 15:55:35 +0200 Subject: Have QState::addTransition(QAbstractTransition*) return the transition object when it is added. Reduces the number of temporary variables you have to declare in your code since you can do things like: state->addTransition(new Transition())->addAnimation(new Animation()); Could also be used for error checking. --- src/corelib/statemachine/qstate.cpp | 9 +++++---- src/corelib/statemachine/qstate.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp index e3da1c5..abd7379 100644 --- a/src/corelib/statemachine/qstate.cpp +++ b/src/corelib/statemachine/qstate.cpp @@ -247,28 +247,29 @@ void QState::setErrorState(QAbstractState *state) Adds the given \a transition. The transition has this state as the source. This state takes ownership of the transition. */ -void QState::addTransition(QAbstractTransition *transition) +QAbstractTransition *QState::addTransition(QAbstractTransition *transition) { Q_D(QState); if (!transition) { qWarning("QState::addTransition: cannot add null transition"); - return; + return 0; } const QList &targets = QAbstractTransitionPrivate::get(transition)->targetStates; for (int i = 0; i < targets.size(); ++i) { QAbstractState *t = targets.at(i); if (!t) { qWarning("QState::addTransition: cannot add transition to null state"); - return; + return 0; } if ((QAbstractStatePrivate::get(t)->machine() != d->machine()) && QAbstractStatePrivate::get(t)->machine() && d->machine()) { qWarning("QState::addTransition: cannot add transition " "to a state in a different state machine"); - return; + return 0; } } transition->setParent(this); + return transition; } /*! diff --git a/src/corelib/statemachine/qstate.h b/src/corelib/statemachine/qstate.h index 4c86e02..1ec0896 100644 --- a/src/corelib/statemachine/qstate.h +++ b/src/corelib/statemachine/qstate.h @@ -81,7 +81,7 @@ public: QAbstractState *errorState() const; void setErrorState(QAbstractState *state); - void addTransition(QAbstractTransition *transition); + QAbstractTransition *addTransition(QAbstractTransition *transition); QSignalTransition *addTransition(QObject *sender, const char *signal, QAbstractState *target); QAbstractTransition *addTransition(QAbstractState *target); QStateFinishedTransition *addFinishedTransition(QAbstractState *target); -- cgit v0.12 From 750cea0a42bc969913547a7266e8ae16936a7a8c Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 21 Apr 2009 15:59:21 +0200 Subject: doc: Document return value of QState::addTransition(QAbstractTransition*) --- src/corelib/statemachine/qstate.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp index abd7379..28c84d5 100644 --- a/src/corelib/statemachine/qstate.cpp +++ b/src/corelib/statemachine/qstate.cpp @@ -245,7 +245,8 @@ void QState::setErrorState(QAbstractState *state) /*! Adds the given \a transition. The transition has this state as the source. - This state takes ownership of the transition. + This state takes ownership of the transition. If the transition is successfully + added, the function will return the \a transition pointer. Otherwise it will return null. */ QAbstractTransition *QState::addTransition(QAbstractTransition *transition) { -- cgit v0.12 From c912281e63b2883e481050f1e246d36e6026100e Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 21 Apr 2009 17:09:58 +0200 Subject: QAnimationState is no more, so we remove the test for it. The relevant tests have been ported to the new API and added to the QStateMachine autotest instead. --- tests/auto/qanimationstate/qanimationstate.pro | 5 - tests/auto/qanimationstate/tst_qanimationstate.cpp | 625 --------------------- tests/auto/qstatemachine/tst_qstatemachine.cpp | 327 +++++++++++ 3 files changed, 327 insertions(+), 630 deletions(-) delete mode 100644 tests/auto/qanimationstate/qanimationstate.pro delete mode 100644 tests/auto/qanimationstate/tst_qanimationstate.cpp diff --git a/tests/auto/qanimationstate/qanimationstate.pro b/tests/auto/qanimationstate/qanimationstate.pro deleted file mode 100644 index 8862c27..0000000 --- a/tests/auto/qanimationstate/qanimationstate.pro +++ /dev/null @@ -1,5 +0,0 @@ -load(qttest_p4) -QT = core -SOURCES += tst_qanimationstate.cpp - - diff --git a/tests/auto/qanimationstate/tst_qanimationstate.cpp b/tests/auto/qanimationstate/tst_qanimationstate.cpp deleted file mode 100644 index 085db24..0000000 --- a/tests/auto/qanimationstate/tst_qanimationstate.cpp +++ /dev/null @@ -1,625 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -****************************************************************************/ - -#include -#include -#include -#include - -//TESTED_CLASS=QAnimationState -//TESTED_FILES= - -#define QTRY_COMPARE(__expr, __expected) \ - do { \ - const int __step = 50; \ - const int __timeout = 5000; \ - if ((__expr) != (__expected)) { \ - QTest::qWait(0); \ - } \ - for (int __i = 0; __i < __timeout && ((__expr) != (__expected)); __i+=__step) { \ - QTest::qWait(__step); \ - } \ - QCOMPARE(__expr, __expected); \ - } while(0) - - -class tst_QAnimationState : public QObject -{ - Q_OBJECT -public: - tst_QAnimationState(); - virtual ~tst_QAnimationState(); - -private slots: - void init(); - void cleanup(); - void construction(); - void noAnimation(); - void simpleAnimation(); - void twoAnimations(); - void reuseAnimation(); - void nestedTargetState(); - void parallelTargetState(); - void playTwice(); - void twoAnimatedTransitions(); - void globalRestoreProperty(); - void specificRestoreProperty(); - void someAnimationsNotSpecified(); - void someActionsNotAnimated(); - void specificTargetValueOfAnimation(); - void persistentTargetValueOfAnimation(); -}; - -tst_QAnimationState::tst_QAnimationState() -{ -} - -tst_QAnimationState::~tst_QAnimationState() -{ -} - -void tst_QAnimationState::init() -{ -} - -void tst_QAnimationState::cleanup() -{ -} - -void tst_QAnimationState::construction() -{ - QAnimationState as; -} - -class EventTransition : public QTransition -{ -public: - EventTransition(QEvent::Type type, QAbstractState *target) - : QTransition(), m_type(type) { - setTargetState(target); - } -protected: - virtual bool eventTest(QEvent *e) const { - return (e->type() == m_type); - } -private: - QEvent::Type m_type; -}; - -void tst_QAnimationState::noAnimation() -{ - QStateMachine machine; - - QState *s1 = new QState(machine.rootState()); - QState *s2 = new QState(machine.rootState()); - s2->setProperty("entered", false); - s2->setPropertyOnEntry(s2, "entered", true); - - s1->addAnimatedTransition(new EventTransition(QEvent::User, s2)); - s2->addTransition(new EventTransition(QEvent::User, s1)); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - QVERIFY(machine.configuration().contains(s1)); - - machine.postEvent(new QEvent(QEvent::User)); - - QTRY_COMPARE(s2->property("entered").toBool(), true); - QVERIFY(machine.configuration().contains(s2)); - - machine.postEvent(new QEvent(QEvent::User)); - QCoreApplication::processEvents(); - - QVERIFY(machine.configuration().contains(s1)); - - s2->setProperty("entered", false); - machine.postEvent(new QEvent(QEvent::User)); - - QTRY_COMPARE(s2->property("entered").toBool(), true); - QVERIFY(machine.configuration().contains(s2)); -} - -class ValueCheckerState: public QState -{ -public: - ValueCheckerState(QState *parent) - : QState(parent) - { - } - - void addPropertyToCheck(const QObject *object, const char *propertyName) - { - m_objects.append(object); - m_propertyNames.append(propertyName); - valueOnEntry.append(QVariant()); - } - - QVariantList valueOnEntry; - -protected: - virtual void onEntry() - { - for (int i=0; iproperty(m_propertyNames.at(i)); - - QState::onEntry(); - } - - QList m_objects; - QList m_propertyNames; - -}; - -void tst_QAnimationState::simpleAnimation() -{ - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("fooBar", 1.0); - - QState *s1 = new QState(machine.rootState()); - ValueCheckerState *s2 = new ValueCheckerState(machine.rootState()); - s2->addPropertyToCheck(object, "fooBar"); - s2->setPropertyOnEntry(object, "fooBar", 2.0); - - QPropertyAnimation *animation = new QPropertyAnimation(object, "fooBar", s2); - s1->addAnimatedTransition(new EventTransition(QEvent::User, s2), animation); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - - QCOMPARE(s2->valueOnEntry.at(0).toDouble(), 2.0); -} - -void tst_QAnimationState::twoAnimations() -{ - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("foo", 1.0); - object->setProperty("bar", 3.0); - - QState *s1 = new QState(machine.rootState()); - ValueCheckerState *s2 = new ValueCheckerState(machine.rootState()); - s2->addPropertyToCheck(object, "foo"); - s2->addPropertyToCheck(object, "bar"); - s2->setPropertyOnEntry(object, "foo", 2.0); - s2->setPropertyOnEntry(object, "bar", 10.0); - - QPropertyAnimation *animationFoo = new QPropertyAnimation(object, "foo", s2); - QPropertyAnimation *animationBar = new QPropertyAnimation(object, "bar", s2); - animationBar->setDuration(900); - QAnimationState *as = s1->addAnimatedTransition(new EventTransition(QEvent::User, s2)); - as->addAnimation(animationFoo); - as->addAnimation(animationBar); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - - QCOMPARE(s2->valueOnEntry.at(0).toDouble(), 2.0); - QCOMPARE(s2->valueOnEntry.at(1).toDouble(), 10.0); -} - -void tst_QAnimationState::parallelTargetState() -{ - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("foo", 1.0); - object->setProperty("bar", 3.0); - - QState *s1 = new QState(machine.rootState()); - QState *s2 = new QState(QState::ParallelGroup, machine.rootState()); - - ValueCheckerState *c1 = new ValueCheckerState(s2); - c1->setPropertyOnEntry(object, "foo", 2.0); - c1->addPropertyToCheck(object, "foo"); - c1->addPropertyToCheck(object, "bar"); - - QState *c2 = new QState(s2); - c2->setPropertyOnEntry(object, "bar", 10.0); - - QAnimationState *as = s1->addAnimatedTransition(new EventTransition(QEvent::User, s2)); - as->addAnimation(new QPropertyAnimation(object, "foo", as)); - as->addAnimation(new QPropertyAnimation(object, "bar", as)); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - - QTRY_COMPARE(c1->valueOnEntry.at(0).isValid(), true); - QCOMPARE(c1->valueOnEntry.at(0).toDouble(), 2.0); - QCOMPARE(c1->valueOnEntry.at(1).toDouble(), 10.0); -} - - -void tst_QAnimationState::twoAnimatedTransitions() -{ - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("foo", 1.0); - - QState *s1 = new QState(machine.rootState()); - ValueCheckerState *s2 = new ValueCheckerState(machine.rootState()); - s2->addPropertyToCheck(object, "foo"); - s2->setPropertyOnEntry(object, "foo", 5.0); - ValueCheckerState *s3 = new ValueCheckerState(machine.rootState()); - s3->setPropertyOnEntry(object, "foo", 2.0); - s3->addPropertyToCheck(object, "foo"); - - s1->addAnimatedTransition(new EventTransition(QEvent::User, s2), - new QPropertyAnimation(object, "foo", s2)); - s2->addAnimatedTransition(new EventTransition(QEvent::User, s3), - new QPropertyAnimation(object, "foo", s2)); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s2->valueOnEntry.at(0).toDouble(), 5.0); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s3->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s3->valueOnEntry.at(0).toDouble(), 2.0); -} - -void tst_QAnimationState::playTwice() -{ - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("foo", 1.0); - - QState *s1 = new QState(machine.rootState()); - ValueCheckerState *s2 = new ValueCheckerState(machine.rootState()); - s2->addPropertyToCheck(object, "foo"); - s2->setPropertyOnEntry(object, "foo", 5.0); - QState *s3 = new QState(machine.rootState()); - s3->setPropertyOnEntry(object, "foo", 2.0); - - s1->addAnimatedTransition(new EventTransition(QEvent::User, s2), - new QPropertyAnimation(object, "foo", s2)); - s2->addTransition(new EventTransition(QEvent::User, s3)); - s3->addTransition(s1); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s2->valueOnEntry.at(0).toDouble(), 5.0); - - machine.postEvent(new QEvent(QEvent::User)); - QCoreApplication::processEvents(); - QVERIFY(machine.configuration().contains(s1)); - QCOMPARE(object->property("foo").toDouble(), 2.0); - - s2->valueOnEntry[0] = QVariant(); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - QCOMPARE(object->property("foo").toDouble(), 5.0); -} - -void tst_QAnimationState::nestedTargetState() -{ - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("foo", 1.0); - object->setProperty("bar", 3.0); - - QState *s1 = new QState(machine.rootState()); - ValueCheckerState *s2 = new ValueCheckerState(machine.rootState()); - s2->addPropertyToCheck(object, "foo"); - s2->addPropertyToCheck(object, "bar"); - s2->setPropertyOnEntry(object, "foo", 2.0); - - QState *s2Child = new QState(s2); - s2Child->setPropertyOnEntry(object, "bar", 10.0); - s2->setInitialState(s2Child); - - QState *s2Child2 = new QState(s2); - s2Child2->setPropertyOnEntry(object, "bar", 11.0); - s2Child->addTransition(s2Child2); // should *not* be considered by QAnimationState as part of target - - QAnimationState *as = s1->addAnimatedTransition(new EventTransition(QEvent::User, s2)); - as->addAnimation(new QPropertyAnimation(object, "foo", as)); - as->addAnimation(new QPropertyAnimation(object, "bar", as)); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - - QCOMPARE(s2->valueOnEntry.at(0).toDouble(), 2.0); - QCOMPARE(s2->valueOnEntry.at(1).toDouble(), 10.0); - QCOMPARE(object->property("bar").toDouble(), 11.0); -} - -void tst_QAnimationState::reuseAnimation() -{ - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("foo", 1.0); - - QState *s1 = new QState(machine.rootState()); - ValueCheckerState *s2 = new ValueCheckerState(machine.rootState()); - s2->addPropertyToCheck(object, "foo"); - s2->setPropertyOnEntry(object, "foo", 5.0); - ValueCheckerState *s3 = new ValueCheckerState(machine.rootState()); - s3->setPropertyOnEntry(object, "foo", 2.0); - s3->addPropertyToCheck(object, "foo"); - - QPropertyAnimation *anim = new QPropertyAnimation(object, "foo", s2); - s1->addAnimatedTransition(new EventTransition(QEvent::User, s2), anim); - s2->addAnimatedTransition(new EventTransition(QEvent::User, s3), anim); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s2->valueOnEntry.at(0).toDouble(), 5.0); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s3->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s3->valueOnEntry.at(0).toDouble(), 2.0); -} - -void tst_QAnimationState::globalRestoreProperty() -{ - QStateMachine machine; - machine.setGlobalRestorePolicy(QState::RestoreProperties); - - QObject *object = new QObject(); - object->setProperty("foo", 1.0); - object->setProperty("bar", 3.0); - - QState *s1 = new QState(machine.rootState()); - - ValueCheckerState *s2 = new ValueCheckerState(machine.rootState()); - s2->addPropertyToCheck(object, "foo"); - s2->addPropertyToCheck(object, "bar"); - s2->setPropertyOnEntry(object, "foo", 2.0); - - ValueCheckerState *s3 = new ValueCheckerState(machine.rootState()); - s3->addPropertyToCheck(object, "foo"); - s3->addPropertyToCheck(object, "bar"); - s3->setPropertyOnEntry(object, "bar", 5.0); - - ValueCheckerState *s4 = new ValueCheckerState(machine.rootState()); - s4->addPropertyToCheck(object, "foo"); - s4->addPropertyToCheck(object, "bar"); - - QAnimationState *as = s1->addAnimatedTransition(new EventTransition(QEvent::User, s2)); - as->addAnimation(new QPropertyAnimation(object, "foo", as)); - as->addAnimation(new QPropertyAnimation(object, "bar", as)); - - as = s2->addAnimatedTransition(new EventTransition(QEvent::User, s3)); - as->addAnimation(new QPropertyAnimation(object, "foo", as)); - as->addAnimation(new QPropertyAnimation(object, "bar", as)); - - as = s3->addAnimatedTransition(new EventTransition(QEvent::User, s4)); - as->addAnimation(new QPropertyAnimation(object, "foo", as)); - as->addAnimation(new QPropertyAnimation(object, "bar", as)); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s2->valueOnEntry.at(0).toDouble(), 2.0); - QCOMPARE(s2->valueOnEntry.at(1).toDouble(), 3.0); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s3->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s3->valueOnEntry.at(0).toDouble(), 1.0); - QCOMPARE(s3->valueOnEntry.at(1).toDouble(), 5.0); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s4->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s4->valueOnEntry.at(0).toDouble(), 1.0); - QCOMPARE(s4->valueOnEntry.at(1).toDouble(), 3.0); - -} - -void tst_QAnimationState::specificRestoreProperty() -{ - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("foo", 1.0); - object->setProperty("bar", 3.0); - - QState *s1 = new QState(machine.rootState()); - - ValueCheckerState *s2 = new ValueCheckerState(machine.rootState()); - s2->setRestorePolicy(QState::RestoreProperties); - s2->addPropertyToCheck(object, "foo"); - s2->addPropertyToCheck(object, "bar"); - s2->setPropertyOnEntry(object, "foo", 2.0); - - ValueCheckerState *s3 = new ValueCheckerState(machine.rootState()); - s3->setRestorePolicy(QState::RestoreProperties); - s3->addPropertyToCheck(object, "foo"); - s3->addPropertyToCheck(object, "bar"); - s3->setPropertyOnEntry(object, "bar", 5.0); - - ValueCheckerState *s4 = new ValueCheckerState(machine.rootState()); - s4->setRestorePolicy(QState::RestoreProperties); - s4->addPropertyToCheck(object, "foo"); - s4->addPropertyToCheck(object, "bar"); - - QAnimationState *as = s1->addAnimatedTransition(new EventTransition(QEvent::User, s2)); - as->addAnimation(new QPropertyAnimation(object, "foo", as)); - - as = s2->addAnimatedTransition(new EventTransition(QEvent::User, s3)); - as->addAnimation(new QPropertyAnimation(object, "bar", as)); - - as = s3->addAnimatedTransition(new EventTransition(QEvent::User, s4)); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s2->valueOnEntry.at(0).toDouble(), 2.0); - QCOMPARE(s2->valueOnEntry.at(1).toDouble(), 3.0); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s3->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s3->valueOnEntry.at(0).toDouble(), 1.0); - QCOMPARE(s3->valueOnEntry.at(1).toDouble(), 5.0); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s4->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s4->valueOnEntry.at(0).toDouble(), 1.0); - QCOMPARE(s4->valueOnEntry.at(1).toDouble(), 3.0); -} - -void tst_QAnimationState::someAnimationsNotSpecified() -{ - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("foo", 1.0); - object->setProperty("bar", 3.0); - - QState *s1 = new QState(machine.rootState()); - - ValueCheckerState *s2 = new ValueCheckerState(machine.rootState()); - s2->addPropertyToCheck(object, "foo"); - s2->addPropertyToCheck(object, "bar"); - s2->setPropertyOnEntry(object, "foo", 2.0); - - QAnimationState *as = s1->addAnimatedTransition(new EventTransition(QEvent::User, s2)); - as->addAnimation(new QPropertyAnimation(object, "foo", as)); - as->addAnimation(new QPropertyAnimation(object, "bar", as)); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s2->valueOnEntry.at(0).toDouble(), 2.0); - QCOMPARE(s2->valueOnEntry.at(1).toDouble(), 3.0); -} - -void tst_QAnimationState::someActionsNotAnimated() -{ - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("foo", 1.0); - object->setProperty("bar", 3.0); - - QState *s1 = new QState(machine.rootState()); - - ValueCheckerState *s2 = new ValueCheckerState(machine.rootState()); - s2->addPropertyToCheck(object, "foo"); - s2->addPropertyToCheck(object, "bar"); - s2->setPropertyOnEntry(object, "foo", 2.0); - s2->setPropertyOnEntry(object, "bar", 5.0); - - s1->addAnimatedTransition(new EventTransition(QEvent::User, s2), - new QPropertyAnimation(object, "foo", s1)); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s2->valueOnEntry.at(0).toDouble(), 2.0); - QCOMPARE(s2->valueOnEntry.at(1).toDouble(), 3.0); - QCOMPARE(object->property("foo").toDouble(), 2.0); - QCOMPARE(object->property("bar").toDouble(), 5.0); -} - -void tst_QAnimationState::specificTargetValueOfAnimation() -{ - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("foo", 1.0); - - QState *s1 = new QState(machine.rootState()); - - ValueCheckerState *s2 = new ValueCheckerState(machine.rootState()); - s2->addPropertyToCheck(object, "foo"); - s2->setPropertyOnEntry(object, "foo", 2.0); - - QPropertyAnimation *anim = new QPropertyAnimation(object, "foo"); - anim->setEndValue(10.0); - s1->addAnimatedTransition(new EventTransition(QEvent::User, s2), anim); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s2->valueOnEntry.at(0).toDouble(), 10.0); - QCOMPARE(object->property("foo").toDouble(), 2.0); -} - -void tst_QAnimationState::persistentTargetValueOfAnimation() -{ - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("foo", 1.0); - - QState *s1 = new QState(machine.rootState()); - - ValueCheckerState *s2 = new ValueCheckerState(machine.rootState()); - s2->addPropertyToCheck(object, "foo"); - s2->setPropertyOnEntry(object, "foo", 2.0); - - QPropertyAnimation *anim = new QPropertyAnimation(object, "foo"); - s1->addAnimatedTransition(new EventTransition(QEvent::User, s2), anim); - - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - QTRY_COMPARE(s2->valueOnEntry.at(0).isValid(), true); - QCOMPARE(s2->valueOnEntry.at(0).toDouble(), 2.0); - QCOMPARE(anim->endValue().isValid(), false); -} - - -QTEST_MAIN(tst_QAnimationState) -#include "tst_qanimationstate.moc" diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 085d16b..be80bed 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -70,6 +70,17 @@ static int globalTick; +// Run exec for a maximum of TIMEOUT msecs +#define QCOREAPPLICATION_EXEC(TIMEOUT) \ +{ \ + QTimer timer; \ + timer.setSingleShot(true); \ + timer.setInterval(TIMEOUT); \ + timer.start(); \ + connect(&timer, SIGNAL(timeout()), QCoreApplication::instance(), SLOT(quit())); \ + QCoreApplication::exec(); \ +} + class tst_QStateMachine : public QObject { Q_OBJECT @@ -122,6 +133,14 @@ private slots: void setGlobalRestorePolicyToGlobalRestore(); void restorePolicyOnChildState(); void transitionWithParent(); + + void simpleAnimation(); + void twoAnimations(); + void twoAnimatedTransitions(); + void playAnimationTwice(); + void nestedTargetStateForAnimation(); + void animatedGlobalRestoreProperty(); + void specificTargetValueOfAnimation(); }; tst_QStateMachine::tst_QStateMachine() @@ -2111,5 +2130,313 @@ void tst_QStateMachine::transitionWithParent() QCOMPARE(trans->targetStates().at(0), (QAbstractState*)s2); } +void tst_QStateMachine::simpleAnimation() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("fooBar", 1.0); + + QState *s1 = new QState(machine.rootState()); + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "fooBar", 2.0); + + EventTransition *et = new EventTransition(QEvent::User, s2); + QPropertyAnimation *animation = new QPropertyAnimation(object, "fooBar", s2); + et->addAnimation(animation); + s1->addTransition(et); + + QState *s3 = new QState(machine.rootState()); + s2->addTransition(animation, SIGNAL(finished()), s3); + s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + + machine.setInitialState(s1); + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(object->property("fooBar").toDouble(), 2.0); +} + +class SlotCalledCounter: public QObject +{ + Q_OBJECT +public: + SlotCalledCounter() : counter(0) {} + + int counter; + +public slots: + void slot() { counter++; } +}; + +void tst_QStateMachine::twoAnimations() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + object->setProperty("bar", 3.0); + + QState *s1 = new QState(machine.rootState()); + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "foo", 2.0); + s2->assignProperty(object, "bar", 10.0); + + QPropertyAnimation *animationFoo = new QPropertyAnimation(object, "foo", s2); + QPropertyAnimation *animationBar = new QPropertyAnimation(object, "bar", s2); + animationBar->setDuration(900); + + SlotCalledCounter counter; + connect(animationFoo, SIGNAL(finished()), &counter, SLOT(slot())); + connect(animationBar, SIGNAL(finished()), &counter, SLOT(slot())); + + EventTransition *et = new EventTransition(QEvent::User, s2); + et->addAnimation(animationFoo); + et->addAnimation(animationBar); + s1->addTransition(et); + + QState *s3 = new QState(machine.rootState()); + s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + s2->addTransition(&machine, SIGNAL(animationsFinished()), 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); + QCOMPARE(object->property("bar").toDouble(), 10.0); + + QCOMPARE(counter.counter, 2); +} + +void tst_QStateMachine::twoAnimatedTransitions() +{ + 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", 5.0); + QPropertyAnimation *fooAnimation = new QPropertyAnimation(object, "foo", s2); + s1->addTransition(new EventTransition(QEvent::User, s2))->addAnimation(fooAnimation); + + QState *s3 = new QState(machine.rootState()); + s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + s2->addTransition(fooAnimation, SIGNAL(finished()), s3); + + QState *s4 = new QState(machine.rootState()); + s4->assignProperty(object, "foo", 2.0); + QPropertyAnimation *fooAnimation2 = new QPropertyAnimation(object, "foo", s4); + s3->addTransition(new EventTransition(QEvent::User, s4))->addAnimation(fooAnimation2); + + QState *s5 = new QState(machine.rootState()); + s5->invokeMethodOnEntry(QApplication::instance(), "quit"); + s4->addTransition(fooAnimation2, SIGNAL(finished()), s5); + + 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(), 5.0); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s5)); + QCOMPARE(object->property("foo").toDouble(), 2.0); +} + +void tst_QStateMachine::playAnimationTwice() +{ + 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", 5.0); + QPropertyAnimation *fooAnimation = new QPropertyAnimation(object, "foo", s2); + s1->addTransition(new EventTransition(QEvent::User, s2))->addAnimation(fooAnimation); + + QState *s3 = new QState(machine.rootState()); + s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + s2->addTransition(fooAnimation, SIGNAL(finished()), s3); + + QState *s4 = new QState(machine.rootState()); + s4->assignProperty(object, "foo", 2.0); + s3->addTransition(new EventTransition(QEvent::User, s4))->addAnimation(fooAnimation); + + QState *s5 = new QState(machine.rootState()); + s5->invokeMethodOnEntry(QApplication::instance(), "quit"); + s4->addTransition(fooAnimation, SIGNAL(finished()), s5); + + 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(), 5.0); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s5)); + QCOMPARE(object->property("foo").toDouble(), 2.0); +} + +void tst_QStateMachine::nestedTargetStateForAnimation() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + object->setProperty("bar", 3.0); + + SlotCalledCounter counter; + + QState *s1 = new QState(machine.rootState()); + QState *s2 = new QState(machine.rootState()); + + s2->assignProperty(object, "foo", 2.0); + + QState *s2Child = new QState(s2); + s2Child->assignProperty(object, "bar", 10.0); + s2->setInitialState(s2Child); + + QState *s2Child2 = new QState(s2); + s2Child2->assignProperty(object, "bar", 11.0); + QAbstractTransition *at = s2Child->addTransition(new EventTransition(QEvent::User, s2Child2)); + + QPropertyAnimation *animation = new QPropertyAnimation(object, "bar", s2); + connect(animation, SIGNAL(finished()), &counter, SLOT(slot())); + at->addAnimation(animation); + + at = s1->addTransition(new EventTransition(QEvent::User, s2)); + + animation = new QPropertyAnimation(object, "foo", s2); + connect(animation, SIGNAL(finished()), &counter, SLOT(slot())); + at->addAnimation(animation); + + animation = new QPropertyAnimation(object, "bar", s2); + connect(animation, SIGNAL(finished()), &counter, SLOT(slot())); + at->addAnimation(animation); + + QState *s3 = new QState(machine.rootState()); + s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + s2->addTransition(&machine, SIGNAL(animationsFinished()), 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); + QCOMPARE(object->property("bar").toDouble(), 10.0); + QCOMPARE(counter.counter, 2); +} + +void tst_QStateMachine::animatedGlobalRestoreProperty() +{ + QStateMachine machine; + machine.setGlobalRestorePolicy(QState::RestoreProperties); + + QObject *object = new QObject(); + object->setProperty("foo", 1.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()); + + QState *s4 = new QState(machine.rootState()); + s4->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + + QAbstractTransition *at = s1->addTransition(new EventTransition(QEvent::User, s2)); + QPropertyAnimation *pa = new QPropertyAnimation(object, "foo", s2); + connect(pa, SIGNAL(finished()), &counter, SLOT(slot())); + at->addAnimation(pa); + + at = s2->addTransition(pa, SIGNAL(finished()), s3); + pa = new QPropertyAnimation(object, "foo", s3); + connect(pa, SIGNAL(finished()), &counter, SLOT(slot())); + at->addAnimation(pa); + + at = s3->addTransition(pa, SIGNAL(finished()), s4); + pa = new QPropertyAnimation(object, "foo", s4); + connect(pa, SIGNAL(finished()), &counter, SLOT(slot())); + at->addAnimation(pa); + + machine.setInitialState(s1); + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s4)); + QCOMPARE(object->property("foo").toDouble(), 1.0); + QCOMPARE(counter.counter, 2); +} + +void tst_QStateMachine::specificTargetValueOfAnimation() +{ + 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); + + QPropertyAnimation *anim = new QPropertyAnimation(object, "foo"); + anim->setEndValue(10.0); + s1->addTransition(new EventTransition(QEvent::User, s2))->addAnimation(anim); + + QState *s3 = new QState(machine.rootState()); + s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + s2->addTransition(anim, 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); + QCOMPARE(anim->endValue().toDouble(), 10.0); +} + + QTEST_MAIN(tst_QStateMachine) #include "tst_qstatemachine.moc" -- cgit v0.12 From e339b7568774e0b26d3f57a7f4b791d39b44b450 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 21 Apr 2009 17:26:36 +0200 Subject: Add API for adding default animations to the state machine. This is especially useful when using the RestoreProperties policy, because this is intended to allow you to build a state machine without having each state consider all the possible properties that may be set by some state at some point. Default animations provide the same convenience for animated properties. --- src/corelib/statemachine/qstatemachine.cpp | 111 +++++++++++++++++++- src/corelib/statemachine/qstatemachine.h | 16 +++ src/corelib/statemachine/qstatemachine_p.h | 9 +- 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 &tr // Find the animations to use for the state change. QList 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 targetStates = transition->targetStates(); + for (int j=0; jdefaultAnimations.append(animation); +} + +/*! + Returns the list of default animations that will be considered for any transition. +*/ +QList 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 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 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 defaultAnimations() const; + void removeDefaultAnimation(QAbstractAnimation *animation); + + void addDefaultAnimationForSourceState(QAbstractState *sourceState, QAbstractAnimation *animation); + QList defaultAnimationsForSourceState(QAbstractState *sourceState) const; + void removeDefaultAnimationForSourceState(QAbstractState *sourceState, QAbstractAnimation *animation); + + void addDefaultAnimationForTargetState(QAbstractState *targetState, QAbstractAnimation *animation); + QList 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 configuration; QList internalEventQueue; QList externalEventQueue; - + QStateMachine::Error error; QActionState::RestorePolicy globalRestorePolicy; @@ -186,7 +186,12 @@ public: QList > propertiesForAnimations; QList playingAnimations; QList resetEndValues; -#endif + + QList defaultAnimations; + QMultiHash defaultAnimationsForSource; + QMultiHash 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" -- cgit v0.12 From a81e1a625d25db862fe02bfa484a6216ff06bcf8 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 22 Apr 2009 11:17:14 +0200 Subject: Add tests for the removeDefaultAnimation* API --- tests/auto/qstatemachine/tst_qstatemachine.cpp | 127 +++++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 5796161..33239b8 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -145,6 +145,9 @@ private slots: void addDefaultAnimationWithUnusedAnimation(); void addDefaultAnimationForSource(); void addDefaultAnimationForTarget(); + void removeDefaultAnimation(); + void removeDefaultAnimationForSource(); + void removeDefaultAnimationForTarget(); }; tst_QStateMachine::tst_QStateMachine() @@ -2578,5 +2581,129 @@ void tst_QStateMachine::addDefaultAnimationForTarget() QCOMPARE(object->property("foo").toDouble(), 2.0); } +void tst_QStateMachine::removeDefaultAnimation() +{ + QStateMachine machine; + + QCOMPARE(machine.defaultAnimations().size(), 0); + + QPropertyAnimation *anim = new QPropertyAnimation(this, "foo"); + + machine.addDefaultAnimation(anim); + + QCOMPARE(machine.defaultAnimations().size(), 1); + QVERIFY(machine.defaultAnimations().contains(anim)); + + machine.removeDefaultAnimation(anim); + + QCOMPARE(machine.defaultAnimations().size(), 0); + + machine.addDefaultAnimation(anim); + + QPropertyAnimation *anim2 = new QPropertyAnimation(this, "foo"); + machine.addDefaultAnimation(anim2); + + QCOMPARE(machine.defaultAnimations().size(), 2); + QVERIFY(machine.defaultAnimations().contains(anim)); + QVERIFY(machine.defaultAnimations().contains(anim2)); + + machine.removeDefaultAnimation(anim); + + QCOMPARE(machine.defaultAnimations().size(), 1); + QVERIFY(machine.defaultAnimations().contains(anim2)); + + machine.removeDefaultAnimation(anim2); + QCOMPARE(machine.defaultAnimations().size(), 0); +} + +void tst_QStateMachine::removeDefaultAnimationForSource() +{ + QStateMachine machine; + + QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 0); + + QPropertyAnimation *anim = new QPropertyAnimation(this, "foo"); + + machine.addDefaultAnimationForSourceState(machine.rootState(), anim); + + QCOMPARE(machine.defaultAnimations().size(), 0); + QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 0); + QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 1); + QVERIFY(machine.defaultAnimationsForSourceState(machine.rootState()).contains(anim)); + + machine.removeDefaultAnimationForTargetState(machine.rootState(), anim); + + QCOMPARE(machine.defaultAnimations().size(), 0); + QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 0); + QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 1); + QVERIFY(machine.defaultAnimationsForSourceState(machine.rootState()).contains(anim)); + + machine.removeDefaultAnimationForSourceState(machine.rootState(), anim); + + QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 0); + + machine.addDefaultAnimationForSourceState(machine.rootState(), anim); + + QPropertyAnimation *anim2 = new QPropertyAnimation(this, "foo"); + machine.addDefaultAnimationForSourceState(machine.rootState(), anim2); + + QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 2); + QVERIFY(machine.defaultAnimationsForSourceState(machine.rootState()).contains(anim)); + QVERIFY(machine.defaultAnimationsForSourceState(machine.rootState()).contains(anim2)); + + machine.removeDefaultAnimationForSourceState(machine.rootState(), anim); + + QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 1); + QVERIFY(machine.defaultAnimationsForSourceState(machine.rootState()).contains(anim2)); + + machine.removeDefaultAnimationForSourceState(machine.rootState(), anim2); + QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 0); +} + +void tst_QStateMachine::removeDefaultAnimationForTarget() +{ + QStateMachine machine; + + QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 0); + + QPropertyAnimation *anim = new QPropertyAnimation(this, "foo"); + + machine.addDefaultAnimationForTargetState(machine.rootState(), anim); + + QCOMPARE(machine.defaultAnimations().size(), 0); + QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 0); + QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 1); + QVERIFY(machine.defaultAnimationsForTargetState(machine.rootState()).contains(anim)); + + machine.removeDefaultAnimationForSourceState(machine.rootState(), anim); + + QCOMPARE(machine.defaultAnimations().size(), 0); + QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 0); + QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 1); + QVERIFY(machine.defaultAnimationsForTargetState(machine.rootState()).contains(anim)); + + machine.removeDefaultAnimationForTargetState(machine.rootState(), anim); + + QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 0); + + machine.addDefaultAnimationForTargetState(machine.rootState(), anim); + + QPropertyAnimation *anim2 = new QPropertyAnimation(this, "foo"); + machine.addDefaultAnimationForTargetState(machine.rootState(), anim2); + + QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 2); + QVERIFY(machine.defaultAnimationsForTargetState(machine.rootState()).contains(anim)); + QVERIFY(machine.defaultAnimationsForTargetState(machine.rootState()).contains(anim2)); + + machine.removeDefaultAnimationForTargetState(machine.rootState(), anim); + + QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 1); + QVERIFY(machine.defaultAnimationsForTargetState(machine.rootState()).contains(anim2)); + + machine.removeDefaultAnimationForTargetState(machine.rootState(), anim2); + QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 0); +} + + QTEST_MAIN(tst_QStateMachine) #include "tst_qstatemachine.moc" -- cgit v0.12 From 31f5348ea1691a7664b6abc04cf425dd02637b33 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 22 Apr 2009 13:28:21 +0200 Subject: Test for overriding default animations. This test defines the order of precedence: 1. Specific animation for transition 2. Default animation for source state 3. Default animation for target state 4. Default animation --- tests/auto/qstatemachine/tst_qstatemachine.cpp | 247 +++++++++++++++++++++++++ 1 file changed, 247 insertions(+) diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 33239b8..b82055b 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -148,6 +148,12 @@ private slots: void removeDefaultAnimation(); void removeDefaultAnimationForSource(); void removeDefaultAnimationForTarget(); + void overrideDefaultAnimationWithSource(); + void overrideDefaultAnimationWithTarget(); + void overrideDefaultAnimationWithSpecific(); + void overrideDefaultSourceAnimationWithSpecific(); + void overrideDefaultTargetAnimationWithSpecific(); + void overrideDefaultTargetAnimationWithSource(); }; tst_QStateMachine::tst_QStateMachine() @@ -2704,6 +2710,247 @@ void tst_QStateMachine::removeDefaultAnimationForTarget() QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 0); } +void tst_QStateMachine::overrideDefaultAnimationWithSource() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + + SlotCalledCounter counter; + + QState *s1 = new QState(machine.rootState()); + machine.setInitialState(s1); + + 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 *defaultAnimation = new QPropertyAnimation(object, "foo"); + connect(defaultAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); + + QPropertyAnimation *moreSpecificAnimation = new QPropertyAnimation(object, "foo"); + s2->addTransition(moreSpecificAnimation, SIGNAL(finished()), s3); + connect(moreSpecificAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); + + machine.addDefaultAnimation(defaultAnimation); + machine.addDefaultAnimationForSourceState(s1, moreSpecificAnimation); + + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(counter.counter, 2); // specific animation started and stopped +} + +void tst_QStateMachine::overrideDefaultAnimationWithTarget() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + + SlotCalledCounter counter; + + QState *s1 = new QState(machine.rootState()); + machine.setInitialState(s1); + + 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 *defaultAnimation = new QPropertyAnimation(object, "foo"); + connect(defaultAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); + + QPropertyAnimation *moreSpecificAnimation = new QPropertyAnimation(object, "foo"); + s2->addTransition(moreSpecificAnimation, SIGNAL(finished()), s3); + connect(moreSpecificAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); + + machine.addDefaultAnimation(defaultAnimation); + machine.addDefaultAnimationForTargetState(s2, moreSpecificAnimation); + + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(counter.counter, 2); // specific animation started and stopped + +} + +void tst_QStateMachine::overrideDefaultAnimationWithSpecific() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + + SlotCalledCounter counter; + + QState *s1 = new QState(machine.rootState()); + machine.setInitialState(s1); + + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "foo", 2.0); + + QState *s3 = new QState(machine.rootState()); + s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + + QAbstractTransition *at = s1->addTransition(new EventTransition(QEvent::User, s2)); + + QPropertyAnimation *defaultAnimation = new QPropertyAnimation(object, "foo"); + connect(defaultAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); + + QPropertyAnimation *moreSpecificAnimation = new QPropertyAnimation(object, "foo"); + s2->addTransition(moreSpecificAnimation, SIGNAL(finished()), s3); + connect(moreSpecificAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); + + machine.addDefaultAnimation(defaultAnimation); + at->addAnimation(moreSpecificAnimation); + + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(counter.counter, 2); // specific animation started and stopped +} + +void tst_QStateMachine::overrideDefaultSourceAnimationWithSpecific() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + + SlotCalledCounter counter; + + QState *s1 = new QState(machine.rootState()); + machine.setInitialState(s1); + + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "foo", 2.0); + + QState *s3 = new QState(machine.rootState()); + s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + + QAbstractTransition *at = s1->addTransition(new EventTransition(QEvent::User, s2)); + + QPropertyAnimation *defaultAnimation = new QPropertyAnimation(object, "foo"); + connect(defaultAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); + + QPropertyAnimation *moreSpecificAnimation = new QPropertyAnimation(object, "foo"); + s2->addTransition(moreSpecificAnimation, SIGNAL(finished()), s3); + connect(moreSpecificAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); + + machine.addDefaultAnimationForSourceState(s1, defaultAnimation); + at->addAnimation(moreSpecificAnimation); + + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(counter.counter, 2); // specific animation started and stopped +} + +void tst_QStateMachine::overrideDefaultTargetAnimationWithSpecific() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + + SlotCalledCounter counter; + + QState *s1 = new QState(machine.rootState()); + machine.setInitialState(s1); + + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "foo", 2.0); + + QState *s3 = new QState(machine.rootState()); + s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + + QAbstractTransition *at = s1->addTransition(new EventTransition(QEvent::User, s2)); + + QPropertyAnimation *defaultAnimation = new QPropertyAnimation(object, "foo"); + connect(defaultAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); + + QPropertyAnimation *moreSpecificAnimation = new QPropertyAnimation(object, "foo"); + s2->addTransition(moreSpecificAnimation, SIGNAL(finished()), s3); + connect(moreSpecificAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); + + machine.addDefaultAnimationForTargetState(s2, defaultAnimation); + at->addAnimation(moreSpecificAnimation); + + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(counter.counter, 2); // specific animation started and stopped +} + +void tst_QStateMachine::overrideDefaultTargetAnimationWithSource() +{ + QStateMachine machine; + + QObject *object = new QObject(); + object->setProperty("foo", 1.0); + + SlotCalledCounter counter; + + QState *s1 = new QState(machine.rootState()); + machine.setInitialState(s1); + + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "foo", 2.0); + + QState *s3 = new QState(machine.rootState()); + s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + + QAbstractTransition *at = s1->addTransition(new EventTransition(QEvent::User, s2)); + + QPropertyAnimation *defaultAnimation = new QPropertyAnimation(object, "foo"); + connect(defaultAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); + + QPropertyAnimation *moreSpecificAnimation = new QPropertyAnimation(object, "foo"); + s2->addTransition(moreSpecificAnimation, SIGNAL(finished()), s3); + connect(moreSpecificAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); + + machine.addDefaultAnimationForTargetState(s2, defaultAnimation); + machine.addDefaultAnimationForSourceState(s1, moreSpecificAnimation); + + machine.start(); + QCoreApplication::processEvents(); + + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); + + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(counter.counter, 2); // specific animation started and stopped +} + QTEST_MAIN(tst_QStateMachine) #include "tst_qstatemachine.moc" -- cgit v0.12 From f87641584424deed25e2abdadea08c3be94b9ce1 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 22 Apr 2009 17:20:19 +0200 Subject: kill the stateactions api It just didn't give us that much. Typically you just reimplement onEntry/onExit/onTransition when you want to do something. We go back to the signals-and-slots approach: states have entered() and exited() signals that you can connect to. It's still possible to have an action-based API, but then you build it on top of the core API, which is OK. Replacing 4 public classes (and one layer in the hierarchy) with 2 signals feels good. --- doc/src/statemachine.qdoc | 7 +- examples/animation/example/mainwindow.cpp | 6 +- examples/animation/moveblocks/main.cpp | 2 +- examples/animation/stickman/lifecycle.cpp | 4 +- examples/statemachine/composition/main.cpp | 4 +- examples/statemachine/trafficlight/main.cpp | 6 +- src/corelib/statemachine/qabstractstate.cpp | 29 ++ src/corelib/statemachine/qabstractstate.h | 4 + src/corelib/statemachine/qabstractstate_p.h | 3 + src/corelib/statemachine/qactionstate.cpp | 293 ----------------- src/corelib/statemachine/qactionstate.h | 102 ------ src/corelib/statemachine/qactionstate_p.h | 83 ----- src/corelib/statemachine/qactiontransition.cpp | 230 ------------- src/corelib/statemachine/qactiontransition.h | 96 ------ src/corelib/statemachine/qactiontransition_p.h | 80 ----- src/corelib/statemachine/qeventtransition.cpp | 21 +- src/corelib/statemachine/qeventtransition.h | 7 +- src/corelib/statemachine/qeventtransition_p.h | 4 +- src/corelib/statemachine/qfinalstate.cpp | 10 +- src/corelib/statemachine/qfinalstate.h | 6 +- src/corelib/statemachine/qsignaltransition.cpp | 15 +- src/corelib/statemachine/qsignaltransition.h | 7 +- src/corelib/statemachine/qsignaltransition_p.h | 4 +- src/corelib/statemachine/qstate.cpp | 10 +- src/corelib/statemachine/qstate.h | 6 +- src/corelib/statemachine/qstate_p.h | 4 +- src/corelib/statemachine/qstateaction.cpp | 356 --------------------- src/corelib/statemachine/qstateaction.h | 119 ------- src/corelib/statemachine/qstateaction_p.h | 107 ------- .../statemachine/qstatefinishedtransition.cpp | 17 +- .../statemachine/qstatefinishedtransition.h | 7 +- src/corelib/statemachine/qstatemachine.cpp | 10 +- src/corelib/statemachine/qstatemachine.h | 4 +- src/corelib/statemachine/qstatemachine_p.h | 2 +- src/corelib/statemachine/statemachine.pri | 9 - tests/auto/qstatemachine/tst_qstatemachine.cpp | 194 ++--------- 36 files changed, 148 insertions(+), 1720 deletions(-) delete mode 100644 src/corelib/statemachine/qactionstate.cpp delete mode 100644 src/corelib/statemachine/qactionstate.h delete mode 100644 src/corelib/statemachine/qactionstate_p.h delete mode 100644 src/corelib/statemachine/qactiontransition.cpp delete mode 100644 src/corelib/statemachine/qactiontransition.h delete mode 100644 src/corelib/statemachine/qactiontransition_p.h delete mode 100644 src/corelib/statemachine/qstateaction.cpp delete mode 100644 src/corelib/statemachine/qstateaction.h delete mode 100644 src/corelib/statemachine/qstateaction_p.h diff --git a/doc/src/statemachine.qdoc b/doc/src/statemachine.qdoc index 3051d19..97c09b9 100644 --- a/doc/src/statemachine.qdoc +++ b/doc/src/statemachine.qdoc @@ -91,13 +91,12 @@ When any of the states is entered, the label's text will be changed accordingly. - The QActionState::invokeMethodOnEntry() function can be used to have a state - invoke a method (a slot) of a QObject when the state is entered. In the + The QActionState::entered() signal is emitted when the state is entered. In the following snippet, the button's showMaximized() slot will be called when state \c s3 is entered: \code - s2->invokeMethodOnEntry(button, "showMaximized"); + QObject::connect(s3, SIGNAL(entered()), button, SLOT(showMaximized())); \endcode \section1 Sharing Transitions By Grouping States @@ -209,7 +208,7 @@ mbox.addButton(QMessageBox::Ok); mbox.setText("Interrupted!"); mbox.setIcon(QMessageBox::Information); - s3->invokeMethodOnEntry(&mbox, "exec"); + QObject::connect(s3, SIGNAL(entered()), &mbox, SLOT(exec())); s3->addTransition(s1h); machine.addState(s3); diff --git a/examples/animation/example/mainwindow.cpp b/examples/animation/example/mainwindow.cpp index 2b0e035..bec755c 100644 --- a/examples/animation/example/mainwindow.cpp +++ b/examples/animation/example/mainwindow.cpp @@ -173,9 +173,9 @@ MainWindow::MainWindow() : QMainWindow(0) setCentralWidget(view); - state3->invokeMethodOnEntry(this, "onEnterState3"); - state2->invokeMethodOnEntry(this, "onEnterState2"); - state1->invokeMethodOnEntry(this, "onEnterState1"); + QObject::connect(state3, SIGNAL(entered()), this, SLOT(onEnterState3())); + QObject::connect(state2, SIGNAL(entered()), this, SLOT(onEnterState2())); + QObject::connect(state1, SIGNAL(entered()), this, SLOT(onEnterState1())); connect(listWidget, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(onItemClicked(QListWidgetItem*))); connect(button3, SIGNAL(clicked()), this, SLOT(onRemoveClicked())); diff --git a/examples/animation/moveblocks/main.cpp b/examples/animation/moveblocks/main.cpp index 1f253f3..639fff3 100644 --- a/examples/animation/moveblocks/main.cpp +++ b/examples/animation/moveblocks/main.cpp @@ -172,7 +172,7 @@ int main(int argc, char **argv) QTimer timer; timer.setInterval(1250); timer.setSingleShot(true); - group->invokeMethodOnEntry(&timer, "start"); + QObject::connect(group, SIGNAL(entered()), &timer, SLOT(start())); QState *state1; QState *state2; diff --git a/examples/animation/stickman/lifecycle.cpp b/examples/animation/stickman/lifecycle.cpp index 9233760..e67b32d 100644 --- a/examples/animation/stickman/lifecycle.cpp +++ b/examples/animation/stickman/lifecycle.cpp @@ -86,8 +86,8 @@ LifeCycle::LifeCycle(StickMan *stickMan, GraphicsView *keyReceiver) QTimer *timer = new QTimer(lightningBlink); timer->setSingleShot(true); timer->setInterval(100); - lightningBlink->invokeMethodOnEntry(timer, "start"); - lightningBlink->invokeMethodOnExit(timer, "stop"); + QObject::connect(lightningBlink, SIGNAL(entered()), timer, SLOT(start())); + QObject::connect(lightningBlink, SIGNAL(exited()), timer, SLOT(stop())); m_dead = new QState(m_machine->rootState()); m_dead->setRestorePolicy(QState::DoNotRestoreProperties); diff --git a/examples/statemachine/composition/main.cpp b/examples/statemachine/composition/main.cpp index 24b823c..927fc62 100644 --- a/examples/statemachine/composition/main.cpp +++ b/examples/statemachine/composition/main.cpp @@ -63,7 +63,7 @@ int main(int argc, char **argv) s1_timer->setObjectName("s1_timer"); QTimer t1; t1.setInterval(2000); - s1_timer->invokeMethodOnEntry(&t1, "start"); + QObject::connect(s1_timer, SIGNAL(entered()), &t1, SLOT(start())); QFinalState *s1_done = new QFinalState(s1); s1_done->setObjectName("s1_done"); s1_timer->addTransition(&t1, SIGNAL(timeout()), s1_done); @@ -80,7 +80,7 @@ int main(int argc, char **argv) s2_timer->setObjectName("s2_timer"); QTimer t2; t2.setInterval(2000); - s2_timer->invokeMethodOnEntry(&t2, "start"); + QObject::connect(s2_timer, SIGNAL(entered()), &t2, SLOT(start())); QFinalState *s2_done = new QFinalState(s2); s2_done->setObjectName("s2_done"); s2_timer->addTransition(&t2, SIGNAL(timeout()), s2_done); diff --git a/examples/statemachine/trafficlight/main.cpp b/examples/statemachine/trafficlight/main.cpp index 528ed00..115ecad 100644 --- a/examples/statemachine/trafficlight/main.cpp +++ b/examples/statemachine/trafficlight/main.cpp @@ -97,9 +97,9 @@ public: timer->setInterval(duration); timer->setSingleShot(true); QState *timing = new QState(this); - timing->invokeMethodOnEntry(light, "turnOn"); - timing->invokeMethodOnEntry(timer, "start"); - timing->invokeMethodOnExit(light, "turnOff"); + QObject::connect(timing, SIGNAL(entered()), light, SLOT(turnOn())); + QObject::connect(timing, SIGNAL(entered()), timer, SLOT(start())); + QObject::connect(timing, SIGNAL(exited()), light, SLOT(turnOff())); QFinalState *done = new QFinalState(this); timing->addTransition(timer, SIGNAL(timeout()), done); setInitialState(timing); diff --git a/src/corelib/statemachine/qabstractstate.cpp b/src/corelib/statemachine/qabstractstate.cpp index 89dcff9..030c63c 100644 --- a/src/corelib/statemachine/qabstractstate.cpp +++ b/src/corelib/statemachine/qabstractstate.cpp @@ -62,6 +62,9 @@ QT_BEGIN_NAMESPACE The assignProperty() function is used for defining property assignments that should be performed when a state is entered. + The entered() signal is emitted when the state has been entered. The + exited() signal is emitted when the state has been exited. + The parentState() function returns the state's parent state. \section1 Subclassing @@ -149,6 +152,18 @@ void QAbstractStatePrivate::callOnExit() q->onExit(); } +void QAbstractStatePrivate::emitEntered() +{ + Q_Q(QAbstractState); + emit q->entered(); +} + +void QAbstractStatePrivate::emitExited() +{ + Q_Q(QAbstractState); + emit q->exited(); +} + /*! Constructs a new state with the given \a parent state. */ @@ -256,6 +271,20 @@ QAbstractState::RestorePolicy QAbstractState::restorePolicy() const */ /*! + \fn QAbstractState::entered() + + This signal is emitted when the state has been entered (after onEntry() has + been called). +*/ + +/*! + \fn QAbstractState::exited() + + This signal is emitted when the state has been exited (after onExit() has + been called). +*/ + +/*! \reimp */ bool QAbstractState::event(QEvent *e) diff --git a/src/corelib/statemachine/qabstractstate.h b/src/corelib/statemachine/qabstractstate.h index b788a88..55e9a62 100644 --- a/src/corelib/statemachine/qabstractstate.h +++ b/src/corelib/statemachine/qabstractstate.h @@ -75,6 +75,10 @@ public: void setRestorePolicy(RestorePolicy restorePolicy); RestorePolicy restorePolicy() const; +Q_SIGNALS: + void entered(); + void exited(); + protected: QAbstractState(QState *parent = 0); diff --git a/src/corelib/statemachine/qabstractstate_p.h b/src/corelib/statemachine/qabstractstate_p.h index 7c565f0..e47fbd2 100644 --- a/src/corelib/statemachine/qabstractstate_p.h +++ b/src/corelib/statemachine/qabstractstate_p.h @@ -98,6 +98,9 @@ public: void callOnEntry(); void callOnExit(); + void emitEntered(); + void emitExited(); + QAbstractState::RestorePolicy restorePolicy; QList propertyAssignments; diff --git a/src/corelib/statemachine/qactionstate.cpp b/src/corelib/statemachine/qactionstate.cpp deleted file mode 100644 index 1da0350..0000000 --- a/src/corelib/statemachine/qactionstate.cpp +++ /dev/null @@ -1,293 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qactionstate.h" -#include "qactionstate_p.h" -#include "qstateaction.h" -#include "qstateaction_p.h" - -QT_BEGIN_NAMESPACE - -/*! - \class QActionState - - \brief The QActionState class provides an action-based state. - - \since 4.6 - \ingroup statemachine - - QActionState executes \l{QStateAction}{state actions} when the state is - entered and exited. QActionState is part of \l{The State Machine Framework}. - - You can add actions to a state with the addEntryAction() and addExitAction() - functions. The state executes the actions when the state is entered and - exited, respectively. - - The invokeMethodOnEntry() and invokeMethodOnExit() functions are used for - defining method invocations that should be performed when a state is entered - and exited, respectively. - - \code - QState *s2 = new QState(); - s2->invokeMethodOnEntry(&label, "showMaximized"); - machine.addState(s2); - \endcode - - \sa QStateAction -*/ - -QActionStatePrivate::QActionStatePrivate() -{ -} - -QActionStatePrivate::~QActionStatePrivate() -{ -} - -QActionStatePrivate *QActionStatePrivate::get(QActionState *q) -{ - return q->d_func(); -} - -const QActionStatePrivate *QActionStatePrivate::get(const QActionState *q) -{ - return q->d_func(); -} - -QList QActionStatePrivate::entryActions() const -{ - QList result; - QList::const_iterator it; -#ifdef QT_STATEMACHINE_SOLUTION - const QObjectList &children = q_func()->children(); -#endif - for (it = children.constBegin(); it != children.constEnd(); ++it) { - QStateAction *act = qobject_cast(*it); - if (act && (QStateActionPrivate::get(act)->when == QStateActionPrivate::ExecuteOnEntry)) - result.append(act); - } - return result; -} - -QList QActionStatePrivate::exitActions() const -{ - QList result; - QList::const_iterator it; -#ifdef QT_STATEMACHINE_SOLUTION - const QObjectList &children = q_func()->children(); -#endif - for (it = children.constBegin(); it != children.constEnd(); ++it) { - QStateAction *act = qobject_cast(*it); - if (act && (QStateActionPrivate::get(act)->when == QStateActionPrivate::ExecuteOnExit)) - result.append(act); - } - return result; -} - -/*! - Constructs a new action state with the given \a parent state. -*/ -QActionState::QActionState(QState *parent) - : QAbstractState(*new QActionStatePrivate, parent) -{ -} - -/*! - \internal -*/ -QActionState::QActionState(QActionStatePrivate &dd, - QState *parent) - : QAbstractState(dd, parent) -{ -} - -/*! - Destroys this action state. -*/ -QActionState::~QActionState() -{ -} - -/*! - Instructs this state to invoke the given \a method of the given \a object - with the given \a arguments when the state is entered. This function will - create a QStateInvokeMethodAction object and add it to the entry actions of - the state. - - \sa invokeMethodOnExit(), addEntryAction() -*/ -void QActionState::invokeMethodOnEntry(QObject *object, const char *method, - const QList &arguments) -{ - addEntryAction(new QStateInvokeMethodAction(object, method, arguments)); -} - -/*! - Instructs this state to invoke the given \a method of the given \a object - with the given \a arguments when the state is exited. This function will - create a QStateInvokeMethodAction object and add it to the exit actions of - the state. - - \sa invokeMethodOnEntry(), addExitAction() -*/ -void QActionState::invokeMethodOnExit(QObject *object, const char *method, - const QList &arguments) -{ - addExitAction(new QStateInvokeMethodAction(object, method, arguments)); -} - -/*! - Adds the given \a action to this state. The action will be executed when - this state is entered. The state takes ownership of the action. - - \sa addExitAction(), removeEntryAction() -*/ -void QActionState::addEntryAction(QStateAction *action) -{ - if (!action) { - qWarning("QActionState::addEntryAction: cannot add null action"); - return; - } - action->setParent(this); - QStateActionPrivate::get(action)->when = QStateActionPrivate::ExecuteOnEntry; -} - -/*! - Adds the given \a action to this state. The action will be executed when - this state is exited. The state takes ownership of the action. - - \sa addEntryAction(), removeExitAction() -*/ -void QActionState::addExitAction(QStateAction *action) -{ - if (!action) { - qWarning("QActionState::addExitAction: cannot add null action"); - return; - } - action->setParent(this); - QStateActionPrivate::get(action)->when = QStateActionPrivate::ExecuteOnExit; -} - -/*! - Removes the given entry \a action from this state. The state releases - ownership of the action. - - \sa addEntryAction() -*/ -void QActionState::removeEntryAction(QStateAction *action) -{ - if (!action) { - qWarning("QActionState::removeEntryAction: cannot remove null action"); - return; - } - if (action->parent() == this) - action->setParent(0); -} - -/*! - Removes the given exit \a action from this state. The state releases - ownership of the action. - - \sa addExitAction() -*/ -void QActionState::removeExitAction(QStateAction *action) -{ - if (!action) { - qWarning("QActionState::removeExitAction: cannot remove null action"); - return; - } - if (action->parent() == this) - action->setParent(0); -} - -/*! - Returns this state's entry actions. - - \sa addEntryAction(), exitActions() -*/ -QList QActionState::entryActions() const -{ - Q_D(const QActionState); - return d->entryActions(); -} - -/*! - Returns this state's exit actions. - - \sa addExitAction(), entryActions() -*/ -QList QActionState::exitActions() const -{ - Q_D(const QActionState); - return d->exitActions(); -} - -/*! - \reimp -*/ -void QActionState::onEntry() -{ - Q_D(QActionState); - QList actions = d->entryActions(); - for (int i = 0; i < actions.size(); ++i) - QStateActionPrivate::get(actions.at(i))->callExecute(); -} - -/*! - \reimp -*/ -void QActionState::onExit() -{ - Q_D(QActionState); - QList actions = d->exitActions(); - for (int i = 0; i < actions.size(); ++i) - QStateActionPrivate::get(actions.at(i))->callExecute(); -} - -/*! - \reimp -*/ -bool QActionState::event(QEvent *e) -{ - return QAbstractState::event(e); -} - -QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qactionstate.h b/src/corelib/statemachine/qactionstate.h deleted file mode 100644 index 517b4b2..0000000 --- a/src/corelib/statemachine/qactionstate.h +++ /dev/null @@ -1,102 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QACTIONSTATE_H -#define QACTIONSTATE_H - -#ifndef QT_STATEMACHINE_SOLUTION -#include -#else -#include "qabstractstate.h" -#endif - -#include -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Core) - -class QStateAction; - -class QActionStatePrivate; -class Q_CORE_EXPORT QActionState : public QAbstractState -{ - Q_OBJECT -public: - QActionState(QState *parent = 0); - ~QActionState(); - - void invokeMethodOnEntry(QObject *object, const char *method, - const QList &args = QList()); - void invokeMethodOnExit(QObject *object, const char *method, - const QList &args = QList()); - - void addEntryAction(QStateAction *action); - void addExitAction(QStateAction *action); - - void removeEntryAction(QStateAction *action); - void removeExitAction(QStateAction *action); - - QList entryActions() const; - QList exitActions() const; - -protected: - void onEntry(); - void onExit(); - - bool event(QEvent *e); - -protected: - QActionState(QActionStatePrivate &dd, QState *parent); - -private: - Q_DISABLE_COPY(QActionState) - Q_DECLARE_PRIVATE(QActionState) -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif diff --git a/src/corelib/statemachine/qactionstate_p.h b/src/corelib/statemachine/qactionstate_p.h deleted file mode 100644 index a06dde2..0000000 --- a/src/corelib/statemachine/qactionstate_p.h +++ /dev/null @@ -1,83 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QACTIONSTATE_P_H -#define QACTIONSTATE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qabstractstate_p.h" -#include "qactionstate.h" - -#include - -QT_BEGIN_NAMESPACE - -class QStateAction; - -class QActionState; -class Q_CORE_EXPORT QActionStatePrivate : public QAbstractStatePrivate -{ - Q_DECLARE_PUBLIC(QActionState) - -public: - QActionStatePrivate(); - ~QActionStatePrivate(); - - static QActionStatePrivate *get(QActionState *q); - static const QActionStatePrivate *get(const QActionState *q); - - QList entryActions() const; - QList exitActions() const; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/corelib/statemachine/qactiontransition.cpp b/src/corelib/statemachine/qactiontransition.cpp deleted file mode 100644 index 7c53e15..0000000 --- a/src/corelib/statemachine/qactiontransition.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qactiontransition.h" -#include "qactiontransition_p.h" -#include "qstateaction.h" -#include "qstateaction_p.h" - -QT_BEGIN_NAMESPACE - -/*! - \class QActionTransition - - \brief The QActionTransition class provides an action-based transition. - - \since 4.6 - \ingroup statemachine - - QActionTransition provides an action-based transition; you add actions with - the addAction() function. The transition executes the actions when the - transition is triggered. QActionTransition is part of \l{The State Machine - Framework}. - - The invokeMethodOnTransition() function is used for defining method - invocations that should be performed when a transition is taken. - - \code - QStateMachine machine; - QState *s1 = new QState(); - machine.addState(s1); - QActionTransition *t1 = new QActionTransition(); - QLabel label; - t1->invokeMethodOnTransition(&label, "clear"); - QState *s2 = new QState(); - machine.addState(s2); - t1->setTargetState(s2); - s1->addTransition(t1); - \endcode - - Actions are executed in the order in which they were added. - - \sa QState::addTransition(), QStateAction -*/ - -QActionTransitionPrivate::QActionTransitionPrivate() -{ -} - -QActionTransitionPrivate::~QActionTransitionPrivate() -{ -} - -QActionTransitionPrivate *QActionTransitionPrivate::get(QActionTransition *q) -{ - return q->d_func(); -} - -const QActionTransitionPrivate *QActionTransitionPrivate::get(const QActionTransition *q) -{ - return q->d_func(); -} - -QList QActionTransitionPrivate::actions() const -{ - QList result; - QList::const_iterator it; -#ifdef QT_STATEMACHINE_SOLUTION - const QObjectList &children = q_func()->children(); -#endif - for (it = children.constBegin(); it != children.constEnd(); ++it) { - QStateAction *s = qobject_cast(*it); - if (s) - result.append(s); - } - return result; -} - -/*! - Constructs a new QActionTransition object with the given \a sourceState. -*/ -QActionTransition::QActionTransition(QState *sourceState) - : QAbstractTransition(*new QActionTransitionPrivate, sourceState) -{ -} - -/*! - Constructs a new QActionTransition object with the given \a targets and \a - sourceState. -*/ -QActionTransition::QActionTransition(const QList &targets, QState *sourceState) - : QAbstractTransition(*new QActionTransitionPrivate, targets, sourceState) -{ -} - -/*! - \internal -*/ -QActionTransition::QActionTransition(QActionTransitionPrivate &dd, QState *parent) - : QAbstractTransition(dd, parent) -{ -} - -/*! - \internal -*/ -QActionTransition::QActionTransition(QActionTransitionPrivate &dd, const QList &targets, QState *parent) - : QAbstractTransition(dd, targets, parent) -{ -} - -/*! - Destroys this transition. -*/ -QActionTransition::~QActionTransition() -{ -} - -/*! - Instructs this QActionTransition to invoke the given \a method of the given \a - object with the given \a arguments when the transition is taken. This - function will create a QStateInvokeMethodAction object and add it to the - actions of the transition. -*/ -void QActionTransition::invokeMethodOnTransition(QObject *object, const char *method, - const QList &arguments) -{ - addAction(new QStateInvokeMethodAction(object, method, arguments)); -} - -/*! - Adds the given \a action to this transition. - The action will be executed when the transition is triggered. - The transition takes ownership of the action. - - \sa removeAction() -*/ -void QActionTransition::addAction(QStateAction *action) -{ - if (!action) { - qWarning("QActionTransition::addAction: cannot add null action"); - return; - } - action->setParent(this); -} - -/*! - Removes the given \a action from this transition. - The transition releases ownership of the action. - - \sa addAction() -*/ -void QActionTransition::removeAction(QStateAction *action) -{ - if (!action) { - qWarning("QActionTransition::removeAction: cannot remove null action"); - return; - } - action->setParent(0); -} - -/*! - Returns this transitions's actions, or an empty list if the transition has - no actions. - - \sa addAction() -*/ -QList QActionTransition::actions() const -{ - Q_D(const QActionTransition); - return d->actions(); -} - -/*! - \reimp -*/ -void QActionTransition::onTransition() -{ - Q_D(QActionTransition); - QList actions = d->actions(); - for (int i = 0; i < actions.size(); ++i) - QStateActionPrivate::get(actions.at(i))->callExecute(); -} - -/*! - \reimp -*/ -bool QActionTransition::event(QEvent *e) -{ - return QAbstractTransition::event(e); -} - -QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qactiontransition.h b/src/corelib/statemachine/qactiontransition.h deleted file mode 100644 index 1a779fa..0000000 --- a/src/corelib/statemachine/qactiontransition.h +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QACTIONTRANSITION_H -#define QACTIONTRANSITION_H - -#ifndef QT_STATEMACHINE_SOLUTION -#include -#else -#include "qabstracttransition.h" -#endif - -#include -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Core) - -class QStateAction; - -class QActionTransitionPrivate; -class Q_CORE_EXPORT QActionTransition : public QAbstractTransition -{ - Q_OBJECT -public: - QActionTransition(QState *sourceState = 0); - QActionTransition(const QList &targets, QState *sourceState = 0); - ~QActionTransition(); - - void invokeMethodOnTransition(QObject *object, const char *method, - const QList &args = QList()); - - void addAction(QStateAction *action); - void removeAction(QStateAction *action); - QList actions() const; - -protected: - virtual void onTransition(); - - bool event(QEvent *e); - -protected: - QActionTransition(QActionTransitionPrivate &dd, QState *parent); - QActionTransition(QActionTransitionPrivate &dd, const QList &targets, QState *parent); - -private: - Q_DISABLE_COPY(QActionTransition) - Q_DECLARE_PRIVATE(QActionTransition) -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif diff --git a/src/corelib/statemachine/qactiontransition_p.h b/src/corelib/statemachine/qactiontransition_p.h deleted file mode 100644 index 34f80d1..0000000 --- a/src/corelib/statemachine/qactiontransition_p.h +++ /dev/null @@ -1,80 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QACTIONTRANSITION_P_H -#define QACTIONTRANSITION_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qabstracttransition_p.h" - -#include - -QT_BEGIN_NAMESPACE - -class QStateAction; - -class QActionTransition; -class Q_CORE_EXPORT QActionTransitionPrivate : public QAbstractTransitionPrivate -{ - Q_DECLARE_PUBLIC(QActionTransition) -public: - QActionTransitionPrivate(); - ~QActionTransitionPrivate(); - - static QActionTransitionPrivate *get(QActionTransition *q); - static const QActionTransitionPrivate *get(const QActionTransition *q); - - QList actions() const; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/corelib/statemachine/qeventtransition.cpp b/src/corelib/statemachine/qeventtransition.cpp index 87ed77a..09b89f3 100644 --- a/src/corelib/statemachine/qeventtransition.cpp +++ b/src/corelib/statemachine/qeventtransition.cpp @@ -129,7 +129,7 @@ void QEventTransitionPrivate::invalidate() Constructs a new QEventTransition object with the given \a sourceState. */ QEventTransition::QEventTransition(QState *sourceState) - : QActionTransition(*new QEventTransitionPrivate, sourceState) + : QAbstractTransition(*new QEventTransitionPrivate, sourceState) { } @@ -139,7 +139,7 @@ QEventTransition::QEventTransition(QState *sourceState) */ QEventTransition::QEventTransition(QObject *object, QEvent::Type type, QState *sourceState) - : QActionTransition(*new QEventTransitionPrivate, sourceState) + : QAbstractTransition(*new QEventTransitionPrivate, sourceState) { Q_D(QEventTransition); d->registered = false; @@ -155,7 +155,7 @@ QEventTransition::QEventTransition(QObject *object, QEvent::Type type, QEventTransition::QEventTransition(QObject *object, QEvent::Type type, const QList &targets, QState *sourceState) - : QActionTransition(*new QEventTransitionPrivate, targets, sourceState) + : QAbstractTransition(*new QEventTransitionPrivate, targets, sourceState) { Q_D(QEventTransition); d->registered = false; @@ -167,7 +167,7 @@ QEventTransition::QEventTransition(QObject *object, QEvent::Type type, \internal */ QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QState *parent) - : QActionTransition(dd, parent) + : QAbstractTransition(dd, parent) { } @@ -176,7 +176,7 @@ QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QState *parent) */ QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QObject *object, QEvent::Type type, QState *parent) - : QActionTransition(dd, parent) + : QAbstractTransition(dd, parent) { Q_D(QEventTransition); d->registered = false; @@ -190,7 +190,7 @@ QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QObject *object, QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QObject *object, QEvent::Type type, const QList &targets, QState *parent) - : QActionTransition(dd, targets, parent) + : QAbstractTransition(dd, targets, parent) { Q_D(QEventTransition); d->registered = false; @@ -268,6 +268,13 @@ bool QEventTransition::eventTest(QEvent *event) const } /*! + \reimp +*/ +void QEventTransition::onTransition() +{ +} + +/*! Tests an instance of an event associated with this event transition and returns true if the transition should be taken, otherwise returns false. The type of the given \a event will be eventType(). @@ -286,7 +293,7 @@ bool QEventTransition::testEventCondition(QEvent *event) const */ bool QEventTransition::event(QEvent *e) { - return QActionTransition::event(e); + return QAbstractTransition::event(e); } QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qeventtransition.h b/src/corelib/statemachine/qeventtransition.h index 21a696c..e19b5af 100644 --- a/src/corelib/statemachine/qeventtransition.h +++ b/src/corelib/statemachine/qeventtransition.h @@ -43,9 +43,9 @@ #define QEVENTTRANSITION_H #ifndef QT_STATEMACHINE_SOLUTION -#include +#include #else -#include "qactiontransition.h" +#include "qabstracttransition.h" #endif #include @@ -56,7 +56,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Core) class QEventTransitionPrivate; -class Q_CORE_EXPORT QEventTransition : public QActionTransition +class Q_CORE_EXPORT QEventTransition : public QAbstractTransition { Q_OBJECT Q_PROPERTY(QObject* object READ eventSource WRITE setEventSource) @@ -80,6 +80,7 @@ protected: virtual bool testEventCondition(QEvent *event) const; // ### name bool eventTest(QEvent *event) const; + void onTransition(); bool event(QEvent *e); diff --git a/src/corelib/statemachine/qeventtransition_p.h b/src/corelib/statemachine/qeventtransition_p.h index 2bb5aaa..fca8c0d 100644 --- a/src/corelib/statemachine/qeventtransition_p.h +++ b/src/corelib/statemachine/qeventtransition_p.h @@ -53,12 +53,12 @@ // We mean it. // -#include "qactiontransition_p.h" +#include "qabstracttransition_p.h" QT_BEGIN_NAMESPACE class QEventTransition; -class Q_CORE_EXPORT QEventTransitionPrivate : public QActionTransitionPrivate +class Q_CORE_EXPORT QEventTransitionPrivate : public QAbstractTransitionPrivate { Q_DECLARE_PUBLIC(QEventTransition) public: diff --git a/src/corelib/statemachine/qfinalstate.cpp b/src/corelib/statemachine/qfinalstate.cpp index abf9d2e..16e080e 100644 --- a/src/corelib/statemachine/qfinalstate.cpp +++ b/src/corelib/statemachine/qfinalstate.cpp @@ -40,7 +40,7 @@ ****************************************************************************/ #include "qfinalstate.h" -#include "qactionstate_p.h" +#include "qabstractstate_p.h" QT_BEGIN_NAMESPACE @@ -80,7 +80,7 @@ QT_BEGIN_NAMESPACE \sa QStateFinishedTransition */ -class QFinalStatePrivate : public QActionStatePrivate +class QFinalStatePrivate : public QAbstractStatePrivate { Q_DECLARE_PUBLIC(QFinalState) @@ -96,7 +96,7 @@ QFinalStatePrivate::QFinalStatePrivate() Constructs a new QFinalState object with the given \a parent state. */ QFinalState::QFinalState(QState *parent) - : QActionState(*new QFinalStatePrivate, parent) + : QAbstractState(*new QFinalStatePrivate, parent) { } @@ -112,7 +112,6 @@ QFinalState::~QFinalState() */ void QFinalState::onEntry() { - QActionState::onEntry(); } /*! @@ -120,7 +119,6 @@ void QFinalState::onEntry() */ void QFinalState::onExit() { - QActionState::onExit(); } /*! @@ -128,7 +126,7 @@ void QFinalState::onExit() */ bool QFinalState::event(QEvent *e) { - return QActionState::event(e); + return QAbstractState::event(e); } QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qfinalstate.h b/src/corelib/statemachine/qfinalstate.h index 36813f5..726a399 100644 --- a/src/corelib/statemachine/qfinalstate.h +++ b/src/corelib/statemachine/qfinalstate.h @@ -43,9 +43,9 @@ #define QFINALSTATE_H #ifndef QT_STATEMACHINE_SOLUTION -#include +#include #else -#include "qactionstate.h" +#include "qabstractstate.h" #endif QT_BEGIN_HEADER @@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Core) class QFinalStatePrivate; -class Q_CORE_EXPORT QFinalState : public QActionState +class Q_CORE_EXPORT QFinalState : public QAbstractState { Q_OBJECT public: diff --git a/src/corelib/statemachine/qsignaltransition.cpp b/src/corelib/statemachine/qsignaltransition.cpp index 32f2d02..064ac6e 100644 --- a/src/corelib/statemachine/qsignaltransition.cpp +++ b/src/corelib/statemachine/qsignaltransition.cpp @@ -137,7 +137,7 @@ void QSignalTransitionPrivate::invalidate() Constructs a new signal transition with the given \a sourceState. */ QSignalTransition::QSignalTransition(QState *sourceState) - : QActionTransition(*new QSignalTransitionPrivate, sourceState) + : QAbstractTransition(*new QSignalTransitionPrivate, sourceState) { } @@ -147,7 +147,7 @@ QSignalTransition::QSignalTransition(QState *sourceState) */ QSignalTransition::QSignalTransition(QObject *sender, const char *signal, QState *sourceState) - : QActionTransition(*new QSignalTransitionPrivate, sourceState) + : QAbstractTransition(*new QSignalTransitionPrivate, sourceState) { Q_D(QSignalTransition); d->sender = sender; @@ -162,7 +162,7 @@ QSignalTransition::QSignalTransition(QObject *sender, const char *signal, QSignalTransition::QSignalTransition(QObject *sender, const char *signal, const QList &targets, QState *sourceState) - : QActionTransition(*new QSignalTransitionPrivate, targets, sourceState) + : QAbstractTransition(*new QSignalTransitionPrivate, targets, sourceState) { Q_D(QSignalTransition); d->sender = sender; @@ -245,9 +245,16 @@ bool QSignalTransition::eventTest(QEvent *event) const /*! \reimp */ +void QSignalTransition::onTransition() +{ +} + +/*! + \reimp +*/ bool QSignalTransition::event(QEvent *e) { - return QActionTransition::event(e); + return QAbstractTransition::event(e); } QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qsignaltransition.h b/src/corelib/statemachine/qsignaltransition.h index c1a41ae..4df97cf 100644 --- a/src/corelib/statemachine/qsignaltransition.h +++ b/src/corelib/statemachine/qsignaltransition.h @@ -43,9 +43,9 @@ #define QSIGNALTRANSITION_H #ifndef QT_STATEMACHINE_SOLUTION -#include +#include #else -#include "qactiontransition.h" +#include "qabstracttransition.h" #endif QT_BEGIN_HEADER @@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Core) class QSignalTransitionPrivate; -class Q_CORE_EXPORT QSignalTransition : public QActionTransition +class Q_CORE_EXPORT QSignalTransition : public QAbstractTransition { Q_OBJECT Q_PROPERTY(QObject* object READ senderObject WRITE setSenderObject) @@ -77,6 +77,7 @@ public: protected: bool eventTest(QEvent *event) const; + void onTransition(); bool event(QEvent *e); diff --git a/src/corelib/statemachine/qsignaltransition_p.h b/src/corelib/statemachine/qsignaltransition_p.h index bd815d9..a23e58c 100644 --- a/src/corelib/statemachine/qsignaltransition_p.h +++ b/src/corelib/statemachine/qsignaltransition_p.h @@ -53,12 +53,12 @@ // We mean it. // -#include "qactiontransition_p.h" +#include "qabstracttransition_p.h" QT_BEGIN_NAMESPACE class QSignalTransition; -class QSignalTransitionPrivate : public QActionTransitionPrivate +class QSignalTransitionPrivate : public QAbstractTransitionPrivate { Q_DECLARE_PUBLIC(QSignalTransition) public: diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp index 28c84d5..56a855e 100644 --- a/src/corelib/statemachine/qstate.cpp +++ b/src/corelib/statemachine/qstate.cpp @@ -138,7 +138,7 @@ const QStatePrivate *QStatePrivate::get(const QState *q) Constructs a new state with the given \a parent state. */ QState::QState(QState *parent) - : QActionState(*new QStatePrivate, parent) + : QAbstractState(*new QStatePrivate, parent) { } @@ -146,7 +146,7 @@ QState::QState(QState *parent) Constructs a new state of the given \a type with the given \a parent state. */ QState::QState(Type type, QState *parent) - : QActionState(*new QStatePrivate, parent) + : QAbstractState(*new QStatePrivate, parent) { Q_D(QState); d->isParallelGroup = (type == ParallelGroup); @@ -156,7 +156,7 @@ QState::QState(Type type, QState *parent) \internal */ QState::QState(QStatePrivate &dd, QState *parent) - : QActionState(dd, parent) + : QAbstractState(dd, parent) { } @@ -385,7 +385,6 @@ QHistoryState *QState::addHistoryState(HistoryType type) */ void QState::onEntry() { - QActionState::onEntry(); } /*! @@ -393,7 +392,6 @@ void QState::onEntry() */ void QState::onExit() { - QActionState::onExit(); } /*! @@ -430,7 +428,7 @@ void QState::setInitialState(QAbstractState *state) */ bool QState::event(QEvent *e) { - return QActionState::event(e); + return QAbstractState::event(e); } QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qstate.h b/src/corelib/statemachine/qstate.h index 1ec0896..7c64c80 100644 --- a/src/corelib/statemachine/qstate.h +++ b/src/corelib/statemachine/qstate.h @@ -43,9 +43,9 @@ #define QSTATE_H #ifndef QT_STATEMACHINE_SOLUTION -#include +#include #else -#include "qactionstate.h" +#include "qabstractstate.h" #endif QT_BEGIN_HEADER @@ -60,7 +60,7 @@ class QSignalTransition; class QStateFinishedTransition; class QStatePrivate; -class Q_CORE_EXPORT QState : public QActionState +class Q_CORE_EXPORT QState : public QAbstractState { Q_OBJECT public: diff --git a/src/corelib/statemachine/qstate_p.h b/src/corelib/statemachine/qstate_p.h index 17b312a..8d040d0 100644 --- a/src/corelib/statemachine/qstate_p.h +++ b/src/corelib/statemachine/qstate_p.h @@ -53,14 +53,14 @@ // We mean it. // -#include "qactionstate_p.h" +#include "qabstractstate_p.h" #include QT_BEGIN_NAMESPACE class QState; -class Q_CORE_EXPORT QStatePrivate : public QActionStatePrivate +class Q_CORE_EXPORT QStatePrivate : public QAbstractStatePrivate { Q_DECLARE_PUBLIC(QState) public: diff --git a/src/corelib/statemachine/qstateaction.cpp b/src/corelib/statemachine/qstateaction.cpp deleted file mode 100644 index 569d5d5..0000000 --- a/src/corelib/statemachine/qstateaction.cpp +++ /dev/null @@ -1,356 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qstateaction.h" -#include "qstateaction_p.h" -#include -#include - -QT_BEGIN_NAMESPACE - -QStateActionPrivate::QStateActionPrivate() -{ - when = ExecuteOnEntry; -} - -QStateActionPrivate::~QStateActionPrivate() -{ -} - -QStateActionPrivate *QStateActionPrivate::get(QStateAction *q) -{ - return q->d_func(); -} - -void QStateActionPrivate::callExecute() -{ - Q_Q(QStateAction); - q->execute(); -} - -/*! - \class QStateAction - - \brief The QStateAction class is the base class of QState actions. - - \since 4.6 - \ingroup statemachine - - A state action is added to a state by calling QActionState::addEntryAction() - or QActionState::addExitAction(). QStateAction is part of \l{The State - Machine Framework}. - - \section1 Subclassing - - Subclasses must implement the execute() function. -*/ - -/*! - Constructs a new QStateAction object with the given \a parent. -*/ -QStateAction::QStateAction(QObject *parent) - : QObject( -#ifndef QT_STATEMACHINE_SOLUTION - *new QStateActionPrivate, -#endif - parent) -#ifdef QT_STATEMACHINE_SOLUTION - , d_ptr(new QStateActionPrivate) -#endif -{ -#ifdef QT_STATEMACHINE_SOLUTION - d_ptr->q_ptr = this; -#endif -} - -/*! - \internal -*/ -QStateAction::QStateAction(QStateActionPrivate &dd, QObject *parent) - : QObject( -#ifndef QT_STATEMACHINE_SOLUTION - dd, -#endif - parent) -#ifdef QT_STATEMACHINE_SOLUTION - , d_ptr(&dd) -#endif -{ -#ifdef QT_STATEMACHINE_SOLUTION - d_ptr->q_ptr = this; -#endif -} - -/*! - Destroys this QStateAction object. -*/ -QStateAction::~QStateAction() -{ -#ifdef QT_STATEMACHINE_SOLUTION - delete d_ptr; -#endif -} - -/*! - \fn QStateAction::execute() - - Executes this action. -*/ - -/*! - \reimp -*/ -bool QStateAction::event(QEvent *e) -{ - return QObject::event(e); -} - -QStateInvokeMethodActionPrivate *QStateInvokeMethodActionPrivate::get(QStateInvokeMethodAction *q) -{ - return q->d_func(); -} - -/*! - \class QStateInvokeMethodAction - - \brief The QStateInvokeMethodAction class provides an invoke method action for QObjects. - - \since 4.6 - \ingroup statemachine - - The QStateInvokeMethodAction class provides an action that calls a method of - a QObject when a QState is entered or exited. QStateInvokeMethodAction is - part of \l{The State Machine Framework}. - - Typically you don't construct QStateInvokeMethodAction objects directly, but - rather call the QState::invokeMethodOnEntry() function or the - QState::invokeMethodOnExit() function. -*/ - -/*! - \property QStateInvokeMethodAction::arguments - - \brief the arguments to the method this action invokes -*/ - -/*! - \property QStateInvokeMethodAction::methodName - - \brief the name of the method this action invokes -*/ - -/*! - \property QStateInvokeMethodAction::target - - \brief the object on which this action invokes a method -*/ - -/*! - Constructs a new QStateInvokeMethodAction object for the method named \a - methodName of the given \a target object, with the given \a parent. -*/ -QStateInvokeMethodAction::QStateInvokeMethodAction( - QObject *target, const QByteArray &methodName, QObject *parent) - : QStateAction(*new QStateInvokeMethodActionPrivate, parent) -{ - Q_D(QStateInvokeMethodAction); - d->target = target; - d->methodName = methodName; - d->methodIndex = -1; -} - -/*! - Constructs a new QStateInvokeMethodAction object for the method named \a - methodName of the given \a target object, with the given arguments, \a args, - and with the given \a parent. -*/ -QStateInvokeMethodAction::QStateInvokeMethodAction( - QObject *target, const QByteArray &methodName, - const QList &args, QObject *parent) - : QStateAction(*new QStateInvokeMethodActionPrivate, parent) -{ - Q_D(QStateInvokeMethodAction); - d->target = target; - d->methodName = methodName; - d->methodIndex = -1; - d->args = args; -} - -/*! - Constructs a new QStateInvokeMethodAction object with the given \a parent. -*/ -QStateInvokeMethodAction::QStateInvokeMethodAction(QObject *parent) - : QStateAction(*new QStateInvokeMethodActionPrivate, parent) -{ - Q_D(QStateInvokeMethodAction); - d->target = 0; - d->methodIndex = -1; -} - -/*! - Destroys this QStateInvokeMethodAction object. -*/ -QStateInvokeMethodAction::~QStateInvokeMethodAction() -{ -} - -/*! - \reimp -*/ -void QStateInvokeMethodAction::execute() -{ - Q_D(QStateInvokeMethodAction); - if (!d->target) - return; - - if (d->methodIndex == -1) { - QVarLengthArray sig; - int len = d->methodName.length(); - if (len <= 0) - return; - sig.append(d->methodName, len); - sig.append('('); - - int paramCount; - for (paramCount = 0; paramCount < d->args.size() && paramCount < 10; ++paramCount) { - const char *tn = d->args.at(paramCount).typeName(); - len = qstrlen(tn); - if (len <= 0) - break; - sig.append(tn, len); - sig.append(','); - } - if (paramCount == 0) - sig.append(')'); // no parameters - else - sig[sig.size() - 1] = ')'; - sig.append('\0'); - - const QMetaObject *meta = d->target->metaObject(); - int idx = meta->indexOfMethod(sig.constData()); - if (idx < 0) { - QByteArray norm = QMetaObject::normalizedSignature(sig.constData()); - idx = meta->indexOfMethod(norm.constData()); - if ((idx < 0) || (idx >= meta->methodCount())) { - qWarning("InvokeMethodAction: unable to find method '%s' of %s(%p)", - sig.constData(), meta->className(), d->target); - return; - } - } - d->methodIndex = idx; - } - - void *param[11]; - param[0] = 0; // return value - for (int i = 0; i < 10; ++i) - param[i+1] = (i < d->args.size()) ? const_cast(d->args.at(i).constData()) : (void*)0; - (void)d->target->qt_metacall(QMetaObject::InvokeMetaMethod, d->methodIndex, param); -} - -/*! - Returns the object on which this action invokes a method. -*/ -QObject *QStateInvokeMethodAction::targetObject() const -{ - Q_D(const QStateInvokeMethodAction); - return d->target; -} - -/*! - Sets the object on which this action invokes a method. -*/ -void QStateInvokeMethodAction::setTargetObject(QObject *target) -{ - Q_D(QStateInvokeMethodAction); - d->target = target; -} - -/*! - Returns the name of the method this action will invoke. -*/ -QByteArray QStateInvokeMethodAction::methodName() const -{ - Q_D(const QStateInvokeMethodAction); - return d->methodName; -} - -/*! - Sets the name of the method this action will invoke. -*/ -void QStateInvokeMethodAction::setMethodName(const QByteArray &methodName) -{ - Q_D(QStateInvokeMethodAction); - if (methodName != d->methodName) { - d->methodName = methodName; - d->methodIndex = -1; - } -} - -/*! - Returns the arguments to the method this action will invoke. -*/ -QVariantList QStateInvokeMethodAction::arguments() const -{ - Q_D(const QStateInvokeMethodAction); - return d->args; -} - -/*! - Sets the arguments to the method this action will invoke. -*/ -void QStateInvokeMethodAction::setArguments(const QVariantList &arguments) -{ - Q_D(QStateInvokeMethodAction); - if (d->args != arguments) { - d->args = arguments; - d->methodIndex = -1; - } -} - -/*! - \reimp -*/ -bool QStateInvokeMethodAction::event(QEvent *e) -{ - return QStateAction::event(e); -} - -QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qstateaction.h b/src/corelib/statemachine/qstateaction.h deleted file mode 100644 index 6843080..0000000 --- a/src/corelib/statemachine/qstateaction.h +++ /dev/null @@ -1,119 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSTATEACTION_H -#define QSTATEACTION_H - -#include - -#include -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Core) - -class QStateActionPrivate; -class Q_CORE_EXPORT QStateAction : public QObject -{ - Q_OBJECT -public: - ~QStateAction(); - -protected: - QStateAction(QObject *parent = 0); - - virtual void execute() = 0; - - bool event(QEvent *e); - -protected: -#ifdef QT_STATEMACHINE_SOLUTION - QStateActionPrivate *d_ptr; -#endif - QStateAction(QStateActionPrivate &dd, QObject *parent); - -private: - Q_DISABLE_COPY(QStateAction) - Q_DECLARE_PRIVATE(QStateAction) -}; - -class QStateInvokeMethodActionPrivate; -class Q_CORE_EXPORT QStateInvokeMethodAction : public QStateAction -{ - Q_OBJECT - Q_PROPERTY(QObject* target READ targetObject WRITE setTargetObject) - Q_PROPERTY(QByteArray methodName READ methodName WRITE setMethodName) - Q_PROPERTY(QVariantList arguments READ arguments WRITE setArguments) -public: - QStateInvokeMethodAction(QObject *target, const QByteArray &methodName, - QObject *parent = 0); - QStateInvokeMethodAction(QObject *target, const QByteArray &methodName, - const QList &args, QObject *parent = 0); - QStateInvokeMethodAction(QObject *parent = 0); - ~QStateInvokeMethodAction(); - - QObject *targetObject() const; - void setTargetObject(QObject *target); - - QByteArray methodName() const; - void setMethodName(const QByteArray &methodName); - - QVariantList arguments() const; - void setArguments(const QVariantList &arguments); - -protected: - void execute(); - - bool event(QEvent *e); - -private: - Q_DISABLE_COPY(QStateInvokeMethodAction) - Q_DECLARE_PRIVATE(QStateInvokeMethodAction) -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif diff --git a/src/corelib/statemachine/qstateaction_p.h b/src/corelib/statemachine/qstateaction_p.h deleted file mode 100644 index 4016b74..0000000 --- a/src/corelib/statemachine/qstateaction_p.h +++ /dev/null @@ -1,107 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSTATEACTION_P_H -#define QSTATEACTION_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#ifndef QT_STATEMACHINE_SOLUTION -#include -#endif - -QT_BEGIN_NAMESPACE - -class QStateAction; -class QStateActionPrivate -#ifndef QT_STATEMACHINE_SOLUTION - : public QObjectPrivate -#endif -{ - Q_DECLARE_PUBLIC(QStateAction) -public: - QStateActionPrivate(); - ~QStateActionPrivate(); - - static QStateActionPrivate *get(QStateAction *q); - - void callExecute(); - - enum When { - ExecuteOnEntry, - ExecuteOnExit - }; - - When when; - -#ifdef QT_STATEMACHINE_SOLUTION - QStateAction *q_ptr; -#endif -}; - -class QStateInvokeMethodAction; -class QStateInvokeMethodActionPrivate : public QStateActionPrivate -{ - Q_DECLARE_PUBLIC(QStateInvokeMethodAction) -public: - QStateInvokeMethodActionPrivate() {} - ~QStateInvokeMethodActionPrivate() {} - - static QStateInvokeMethodActionPrivate *get(QStateInvokeMethodAction *q); - - QObject *target; - QByteArray methodName; - int methodIndex; - QList args; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/corelib/statemachine/qstatefinishedtransition.cpp b/src/corelib/statemachine/qstatefinishedtransition.cpp index 33c3d22..151a274 100644 --- a/src/corelib/statemachine/qstatefinishedtransition.cpp +++ b/src/corelib/statemachine/qstatefinishedtransition.cpp @@ -41,7 +41,7 @@ #include "qstatefinishedtransition.h" #include "qstatefinishedevent.h" -#include "qactiontransition_p.h" +#include "qabstracttransition_p.h" QT_BEGIN_NAMESPACE @@ -80,7 +80,7 @@ QT_BEGIN_NAMESPACE \brief the state whose QStateFinishedEvent this transition is associated with */ -class QStateFinishedTransitionPrivate : public QActionTransitionPrivate +class QStateFinishedTransitionPrivate : public QAbstractTransitionPrivate { Q_DECLARE_PUBLIC(QStateFinishedTransition) public: @@ -106,7 +106,7 @@ QStateFinishedTransitionPrivate *QStateFinishedTransitionPrivate::get(QStateFini sourceState. */ QStateFinishedTransition::QStateFinishedTransition(QState *sourceState) - : QActionTransition(*new QStateFinishedTransitionPrivate, sourceState) + : QAbstractTransition(*new QStateFinishedTransitionPrivate, sourceState) { } @@ -116,7 +116,7 @@ QStateFinishedTransition::QStateFinishedTransition(QState *sourceState) */ QStateFinishedTransition::QStateFinishedTransition( QState *state, const QList &targets, QState *sourceState) - : QActionTransition(*new QStateFinishedTransitionPrivate, targets, sourceState) + : QAbstractTransition(*new QStateFinishedTransitionPrivate, targets, sourceState) { Q_D(QStateFinishedTransition); d->state = state; @@ -167,9 +167,16 @@ bool QStateFinishedTransition::eventTest(QEvent *event) const /*! \reimp */ +void QStateFinishedTransition::onTransition() +{ +} + +/*! + \reimp +*/ bool QStateFinishedTransition::event(QEvent *e) { - return QActionTransition::event(e); + return QAbstractTransition::event(e); } QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qstatefinishedtransition.h b/src/corelib/statemachine/qstatefinishedtransition.h index f9320f5..ed86288 100644 --- a/src/corelib/statemachine/qstatefinishedtransition.h +++ b/src/corelib/statemachine/qstatefinishedtransition.h @@ -43,9 +43,9 @@ #define QSTATEFINISHEDTRANSITION_H #ifndef QT_STATEMACHINE_SOLUTION -#include +#include #else -#include "qactiontransition.h" +#include "qabstracttransition.h" #endif QT_BEGIN_HEADER @@ -57,7 +57,7 @@ QT_MODULE(Core) class QState; class QStateFinishedTransitionPrivate; -class Q_CORE_EXPORT QStateFinishedTransition : public QActionTransition +class Q_CORE_EXPORT QStateFinishedTransition : public QAbstractTransition { Q_OBJECT Q_PROPERTY(QState* state READ state WRITE setState) @@ -72,6 +72,7 @@ public: protected: bool eventTest(QEvent *event) const; + void onTransition(); bool event(QEvent *e); diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 1f8d8a8..b6ab205 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -49,8 +49,6 @@ #include "qsignaleventgenerator_p.h" #include "qabstractstate.h" #include "qabstractstate_p.h" -#include "qactionstate.h" -#include "qactionstate_p.h" #include "qfinalstate.h" #include "qhistorystate.h" #include "qhistorystate_p.h" @@ -58,8 +56,6 @@ #include "qstatefinishedtransition.h" #include "qstate.h" #include "qstate_p.h" -#include "qstateaction.h" -#include "qstateaction_p.h" #ifndef QT_STATEMACHINE_SOLUTION #include "private/qobject_p.h" #include "private/qthread_p.h" @@ -417,6 +413,7 @@ QList QStateMachinePrivate::exitStates(const QListcallOnExit(); configuration.remove(s); + QAbstractStatePrivate::get(s)->emitExited(); } return statesToExit_sorted; } @@ -504,6 +501,7 @@ QList QStateMachinePrivate::enterStates(const QListcallOnEntry(); + QAbstractStatePrivate::get(s)->emitEntered(); if (statesForDefaultEntry.contains(s)) { // ### executeContent(s.initial.transition.children()) } @@ -1490,9 +1488,9 @@ void QStateMachine::clearError() /*! Returns the global restore policy of the state machine. - \sa QActionState::restorePolicy() + \sa QAbstractState::restorePolicy() */ -QActionState::RestorePolicy QStateMachine::globalRestorePolicy() const +QAbstractState::RestorePolicy QStateMachine::globalRestorePolicy() const { Q_D(const QStateMachine); return d->globalRestorePolicy; diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h index f39efc7..901d160 100644 --- a/src/corelib/statemachine/qstatemachine.h +++ b/src/corelib/statemachine/qstatemachine.h @@ -43,9 +43,9 @@ #define QSTATEMACHINE_H #ifndef QT_STATEMACHINE_SOLUTION -# include +# include #else -# include "qactionstate.h" +# include "qabstractstate.h" #endif #include diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index a9fd2de..910b751 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -171,7 +171,7 @@ public: QList externalEventQueue; QStateMachine::Error error; - QActionState::RestorePolicy globalRestorePolicy; + QAbstractState::RestorePolicy globalRestorePolicy; QString errorString; QSet pendingErrorStates; diff --git a/src/corelib/statemachine/statemachine.pri b/src/corelib/statemachine/statemachine.pri index 4179e45..620c7a0 100644 --- a/src/corelib/statemachine/statemachine.pri +++ b/src/corelib/statemachine/statemachine.pri @@ -1,12 +1,8 @@ HEADERS += $$PWD/qstatemachine.h \ $$PWD/qstatemachine_p.h \ - $$PWD/qstateaction.h \ - $$PWD/qstateaction_p.h \ $$PWD/qsignaleventgenerator_p.h \ $$PWD/qabstractstate.h \ $$PWD/qabstractstate_p.h \ - $$PWD/qactionstate.h \ - $$PWD/qactionstate_p.h \ $$PWD/qstate.h \ $$PWD/qstate_p.h \ $$PWD/qfinalstate.h \ @@ -14,8 +10,6 @@ HEADERS += $$PWD/qstatemachine.h \ $$PWD/qhistorystate_p.h \ $$PWD/qabstracttransition.h \ $$PWD/qabstracttransition_p.h \ - $$PWD/qactiontransition.h \ - $$PWD/qactiontransition_p.h \ $$PWD/qstatefinishedevent.h \ $$PWD/qstatefinishedtransition.h \ $$PWD/qsignalevent.h \ @@ -23,14 +17,11 @@ HEADERS += $$PWD/qstatemachine.h \ $$PWD/qsignaltransition_p.h SOURCES += $$PWD/qstatemachine.cpp \ - $$PWD/qstateaction.cpp \ $$PWD/qabstractstate.cpp \ - $$PWD/qactionstate.cpp \ $$PWD/qstate.cpp \ $$PWD/qfinalstate.cpp \ $$PWD/qhistorystate.cpp \ $$PWD/qabstracttransition.cpp \ - $$PWD/qactiontransition.cpp \ $$PWD/qstatefinishedtransition.cpp \ $$PWD/qsignaltransition.cpp diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index b82055b..bf3ff71 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -45,7 +45,6 @@ #include "qstatemachine.h" #include "qstate.h" -#include "qactiontransition.h" #include "qhistorystate.h" #include "qkeyeventtransition.h" #include "qmouseeventtransition.h" @@ -102,8 +101,6 @@ private slots: void signalTransitions(); void eventTransitions(); void historyStates(); - void stateActions(); - void transitionActions(); void transitionToRootState(); void transitionEntersParent(); @@ -226,15 +223,16 @@ void tst_QStateMachine::cleanup() qInstallMsgHandler(s_oldHandler); } -class EventTransition : public QActionTransition +class EventTransition : public QAbstractTransition { public: EventTransition(QEvent::Type type, QAbstractState *target, QState *parent = 0) - : QActionTransition(QList() << target, parent), m_type(type) {} + : QAbstractTransition(QList() << target, parent), m_type(type) {} protected: virtual bool eventTest(QEvent *e) const { return (e->type() == m_type); } + virtual void onTransition() {} private: QEvent::Type m_type; }; @@ -1631,154 +1629,6 @@ void tst_QStateMachine::historyStates() QTRY_COMPARE(finishedSpy.count(), 1); } -class TestStateAction : public QStateAction -{ -public: - TestStateAction() : m_didExecute(false) - {} - bool didExecute() const { - return m_didExecute; - } -protected: - void execute() { - m_didExecute = true; - } -private: - bool m_didExecute; -}; - -void tst_QStateMachine::stateActions() -{ - QStateMachine machine; - QState *s1 = new QState(machine.rootState()); - - QVERIFY(s1->entryActions().isEmpty()); - QVERIFY(s1->exitActions().isEmpty()); - - QTest::ignoreMessage(QtWarningMsg, "QActionState::addEntryAction: cannot add null action"); - s1->addEntryAction(0); - QTest::ignoreMessage(QtWarningMsg, "QActionState::addExitAction: cannot add null action"); - s1->addExitAction(0); - QTest::ignoreMessage(QtWarningMsg, "QActionState::removeEntryAction: cannot remove null action"); - s1->removeEntryAction(0); - QTest::ignoreMessage(QtWarningMsg, "QActionState::removeExitAction: cannot remove null action"); - s1->removeExitAction(0); - - QFinalState *s2 = new QFinalState(machine.rootState()); - s1->addTransition(s2); - - machine.setInitialState(s1); - QSignalSpy finishedSpy(&machine, SIGNAL(finished())); - - QObject *obj = new QObject(); - QStateInvokeMethodAction *ima = new QStateInvokeMethodAction(obj, "deleteLater"); - QPointer ptr(obj); - QVERIFY(ptr != 0); - s1->addEntryAction(ima); - finishedSpy.clear(); - machine.start(); - QTRY_COMPARE(finishedSpy.count(), 1); - QCoreApplication::processEvents(); - QVERIFY(ptr == 0); - - s1->removeEntryAction(ima); - - s1->invokeMethodOnEntry(ima, "deleteLater"); - QCOMPARE(s1->entryActions().size(), 1); - - ptr = ima; - QVERIFY(ptr != 0); - finishedSpy.clear(); - machine.start(); - QTRY_COMPARE(finishedSpy.count(), 1); - QCoreApplication::processEvents(); - QVERIFY(ptr == 0); - - while (!s1->entryActions().isEmpty()) { - QStateAction *act = s1->entryActions().first(); - s1->removeEntryAction(act); - delete act; - } - - TestStateAction *act1 = new TestStateAction(); - s1->addEntryAction(act1); - TestStateAction *act2 = new TestStateAction(); - s1->addExitAction(act2); - QVERIFY(!act1->didExecute()); - QVERIFY(!act2->didExecute()); - - finishedSpy.clear(); - machine.start(); - QTRY_COMPARE(finishedSpy.count(), 1); - - QVERIFY(act1->didExecute()); - QVERIFY(act2->didExecute()); - - QCOMPARE(s1->entryActions().size(), 1); - QCOMPARE(s2->entryActions().size(), 0); - s2->addEntryAction(act1); // should remove it from s1 - QCOMPARE(s1->entryActions().size(), 0); - QCOMPARE(s2->entryActions().size(), 1); - QCOMPARE(act1->parent(), (QObject*)s2); - - QCOMPARE(s2->exitActions().size(), 0); - s2->addExitAction(act1); // should remove entry action - QCOMPARE(s2->exitActions().size(), 1); - QCOMPARE(s2->entryActions().size(), 0); - QCOMPARE(act1->parent(), (QObject*)s2); -} - -void tst_QStateMachine::transitionActions() -{ - QStateMachine machine; - QState *s1 = new QState(machine.rootState()); - - QFinalState *s2 = new QFinalState(machine.rootState()); - EventTransition *trans = new EventTransition(QEvent::User, s2); - s1->addTransition(trans); - QVERIFY(trans->actions().isEmpty()); - QTest::ignoreMessage(QtWarningMsg, "QActionTransition::addAction: cannot add null action"); - trans->addAction(0); - QVERIFY(trans->actions().isEmpty()); - - TestStateAction *act = new TestStateAction(); - trans->addAction(act); - QCOMPARE(trans->actions().size(), 1); - QCOMPARE(trans->actions().at(0), (QStateAction*)act); - QCOMPARE(act->parent(), (QObject*)trans); - QVERIFY(!act->didExecute()); - - trans->removeAction(act); - QVERIFY(trans->actions().isEmpty()); - QCOMPARE(act->parent(), (QObject*)0); - - trans->addAction(act); - - QSignalSpy finishedSpy(&machine, SIGNAL(finished())); - machine.setInitialState(s1); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - QCoreApplication::processEvents(); - QTRY_COMPARE(finishedSpy.count(), 1); - QVERIFY(act->didExecute()); - - trans->invokeMethodOnTransition(act, "deleteLater"); - - QPointer ptr(act); - QVERIFY(ptr != 0); - finishedSpy.clear(); - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - QCoreApplication::processEvents(); - QTRY_COMPARE(finishedSpy.count(), 1); - QCoreApplication::processEvents(); - QVERIFY(ptr == 0); -} - void tst_QStateMachine::defaultGlobalRestorePolicy() { QStateMachine machine; @@ -2161,7 +2011,7 @@ void tst_QStateMachine::simpleAnimation() QState *s3 = new QState(machine.rootState()); s2->addTransition(animation, SIGNAL(finished()), s3); - s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); machine.setInitialState(s1); machine.start(); @@ -2213,7 +2063,7 @@ void tst_QStateMachine::twoAnimations() s1->addTransition(et); QState *s3 = new QState(machine.rootState()); - s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); s2->addTransition(&machine, SIGNAL(animationsFinished()), s3); machine.setInitialState(s1); @@ -2245,7 +2095,7 @@ void tst_QStateMachine::twoAnimatedTransitions() s1->addTransition(new EventTransition(QEvent::User, s2))->addAnimation(fooAnimation); QState *s3 = new QState(machine.rootState()); - s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); s2->addTransition(fooAnimation, SIGNAL(finished()), s3); QState *s4 = new QState(machine.rootState()); @@ -2254,7 +2104,7 @@ void tst_QStateMachine::twoAnimatedTransitions() s3->addTransition(new EventTransition(QEvent::User, s4))->addAnimation(fooAnimation2); QState *s5 = new QState(machine.rootState()); - s5->invokeMethodOnEntry(QApplication::instance(), "quit"); + QObject::connect(s5, SIGNAL(entered()), QApplication::instance(), SLOT(quit())); s4->addTransition(fooAnimation2, SIGNAL(finished()), s5); machine.setInitialState(s1); @@ -2289,7 +2139,7 @@ void tst_QStateMachine::playAnimationTwice() s1->addTransition(new EventTransition(QEvent::User, s2))->addAnimation(fooAnimation); QState *s3 = new QState(machine.rootState()); - s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); s2->addTransition(fooAnimation, SIGNAL(finished()), s3); QState *s4 = new QState(machine.rootState()); @@ -2297,7 +2147,7 @@ void tst_QStateMachine::playAnimationTwice() s3->addTransition(new EventTransition(QEvent::User, s4))->addAnimation(fooAnimation); QState *s5 = new QState(machine.rootState()); - s5->invokeMethodOnEntry(QApplication::instance(), "quit"); + QObject::connect(s5, SIGNAL(entered()), QApplication::instance(), SLOT(quit())); s4->addTransition(fooAnimation, SIGNAL(finished()), s5); machine.setInitialState(s1); @@ -2355,7 +2205,7 @@ void tst_QStateMachine::nestedTargetStateForAnimation() at->addAnimation(animation); QState *s3 = new QState(machine.rootState()); - s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); s2->addTransition(&machine, SIGNAL(animationsFinished()), s3); machine.setInitialState(s1); @@ -2388,7 +2238,7 @@ void tst_QStateMachine::animatedGlobalRestoreProperty() QState *s3 = new QState(machine.rootState()); QState *s4 = new QState(machine.rootState()); - s4->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + QObject::connect(s4, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); QAbstractTransition *at = s1->addTransition(new EventTransition(QEvent::User, s2)); QPropertyAnimation *pa = new QPropertyAnimation(object, "foo", s2); @@ -2435,7 +2285,7 @@ void tst_QStateMachine::specificTargetValueOfAnimation() s1->addTransition(new EventTransition(QEvent::User, s2))->addAnimation(anim); QState *s3 = new QState(machine.rootState()); - s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); s2->addTransition(anim, SIGNAL(finished()), s3); machine.setInitialState(s1); @@ -2463,7 +2313,7 @@ void tst_QStateMachine::addDefaultAnimation() s2->assignProperty(object, "foo", 2.0); QState *s3 = new QState(machine.rootState()); - s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); s1->addTransition(new EventTransition(QEvent::User, s2)); @@ -2498,7 +2348,7 @@ void tst_QStateMachine::addDefaultAnimationWithUnusedAnimation() s2->assignProperty(object, "foo", 2.0); QState *s3 = new QState(machine.rootState()); - s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); s1->addTransition(new EventTransition(QEvent::User, s2)); @@ -2536,7 +2386,7 @@ void tst_QStateMachine::addDefaultAnimationForSource() s2->assignProperty(object, "foo", 2.0); QState *s3 = new QState(machine.rootState()); - s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); s1->addTransition(new EventTransition(QEvent::User, s2)); @@ -2568,7 +2418,7 @@ void tst_QStateMachine::addDefaultAnimationForTarget() s2->assignProperty(object, "foo", 2.0); QState *s3 = new QState(machine.rootState()); - s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); s1->addTransition(new EventTransition(QEvent::User, s2)); @@ -2726,7 +2576,7 @@ void tst_QStateMachine::overrideDefaultAnimationWithSource() s2->assignProperty(object, "foo", 2.0); QState *s3 = new QState(machine.rootState()); - s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); s1->addTransition(new EventTransition(QEvent::User, s2)); @@ -2766,7 +2616,7 @@ void tst_QStateMachine::overrideDefaultAnimationWithTarget() s2->assignProperty(object, "foo", 2.0); QState *s3 = new QState(machine.rootState()); - s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); s1->addTransition(new EventTransition(QEvent::User, s2)); @@ -2807,7 +2657,7 @@ void tst_QStateMachine::overrideDefaultAnimationWithSpecific() s2->assignProperty(object, "foo", 2.0); QState *s3 = new QState(machine.rootState()); - s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); QAbstractTransition *at = s1->addTransition(new EventTransition(QEvent::User, s2)); @@ -2847,7 +2697,7 @@ void tst_QStateMachine::overrideDefaultSourceAnimationWithSpecific() s2->assignProperty(object, "foo", 2.0); QState *s3 = new QState(machine.rootState()); - s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); QAbstractTransition *at = s1->addTransition(new EventTransition(QEvent::User, s2)); @@ -2887,7 +2737,7 @@ void tst_QStateMachine::overrideDefaultTargetAnimationWithSpecific() s2->assignProperty(object, "foo", 2.0); QState *s3 = new QState(machine.rootState()); - s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); QAbstractTransition *at = s1->addTransition(new EventTransition(QEvent::User, s2)); @@ -2927,7 +2777,7 @@ void tst_QStateMachine::overrideDefaultTargetAnimationWithSource() s2->assignProperty(object, "foo", 2.0); QState *s3 = new QState(machine.rootState()); - s3->invokeMethodOnEntry(QCoreApplication::instance(), "quit"); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); QAbstractTransition *at = s1->addTransition(new EventTransition(QEvent::User, s2)); -- cgit v0.12 From 44548c4e02061ec14ba126a857665593e1aca642 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 23 Apr 2009 09:33:52 +0200 Subject: Remove specific RestorePolicy per state from example. The semantics for this have changed to something which is more intuitive, so it is no longer useful for this case. --- examples/animation/stickman/lifecycle.cpp | 12 ------------ examples/animation/stickman/lifecycle.h | 1 - examples/animation/stickman/main.cpp | 2 -- 3 files changed, 15 deletions(-) diff --git a/examples/animation/stickman/lifecycle.cpp b/examples/animation/stickman/lifecycle.cpp index e67b32d..67dd209 100644 --- a/examples/animation/stickman/lifecycle.cpp +++ b/examples/animation/stickman/lifecycle.cpp @@ -70,14 +70,12 @@ LifeCycle::LifeCycle(StickMan *stickMan, GraphicsView *keyReceiver) // Set up intial state graph m_machine = new QStateMachine(); - m_machine->setGlobalRestorePolicy(QState::RestoreProperties); m_alive = new QState(m_machine->rootState()); m_alive->setObjectName("alive"); // Make it blink when lightning strikes before entering dead animation QState *lightningBlink = new QState(m_machine->rootState()); - lightningBlink->setRestorePolicy(QState::DoNotRestoreProperties); lightningBlink->assignProperty(m_stickMan->scene(), "backgroundBrush", Qt::white); lightningBlink->assignProperty(m_stickMan, "penColor", Qt::black); lightningBlink->assignProperty(m_stickMan, "fillColor", Qt::white); @@ -90,7 +88,6 @@ LifeCycle::LifeCycle(StickMan *stickMan, GraphicsView *keyReceiver) QObject::connect(lightningBlink, SIGNAL(exited()), timer, SLOT(stop())); m_dead = new QState(m_machine->rootState()); - m_dead->setRestorePolicy(QState::DoNotRestoreProperties); m_dead->assignProperty(m_stickMan->scene(), "backgroundBrush", Qt::black); m_dead->assignProperty(m_stickMan, "penColor", Qt::white); m_dead->assignProperty(m_stickMan, "fillColor", Qt::black); @@ -110,15 +107,6 @@ LifeCycle::LifeCycle(StickMan *stickMan, GraphicsView *keyReceiver) m_machine->setInitialState(m_alive); } -void LifeCycle::setResetKey(Qt::Key resetKey) -{ - // When resetKey is pressed, enter the idle state and do a restoration animation - // (requires no animation pointer, since no property is being set in the idle state) - KeyPressTransition *trans = new KeyPressTransition(m_keyReceiver, resetKey, m_idle); - trans->addAnimation(m_animationGroup); - m_alive->addTransition(trans); -} - void LifeCycle::setDeathAnimation(const QString &fileName) { QState *deathAnimation = makeState(m_dead, fileName); diff --git a/examples/animation/stickman/lifecycle.h b/examples/animation/stickman/lifecycle.h index 437e935..58372f4 100644 --- a/examples/animation/stickman/lifecycle.h +++ b/examples/animation/stickman/lifecycle.h @@ -17,7 +17,6 @@ public: ~LifeCycle(); void setDeathAnimation(const QString &fileName); - void setResetKey(Qt::Key key); void addActivity(const QString &fileName, Qt::Key key); void start(); diff --git a/examples/animation/stickman/main.cpp b/examples/animation/stickman/main.cpp index 62860ec..8fc0077 100644 --- a/examples/animation/stickman/main.cpp +++ b/examples/animation/stickman/main.cpp @@ -23,7 +23,6 @@ int main(int argc, char **argv) "
  • Press J to make the stickman jump.
  • " "
  • Press D to make the stickman dance.
  • " "
  • Press C to make him chill out.
  • " - "
  • Press Return to make him return to his original position.
  • " "
  • When you are done, press Escape.
  • " "

    " "

    If he is unlucky, the stickman will get struck by lightning, and never jump, dance or chill out again." @@ -46,7 +45,6 @@ int main(int argc, char **argv) view->setSceneRect(scene->sceneRect()); LifeCycle *cycle = new LifeCycle(stickMan, view); - cycle->setResetKey(Qt::Key_Return); cycle->setDeathAnimation("animations/dead"); cycle->addActivity("animations/jumping", Qt::Key_J); -- cgit v0.12 From 404db2ceac0ad4770c77f42e8f8a9cd003b151a1 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 23 Apr 2009 11:22:07 +0200 Subject: Compile. --- examples/animation/piemenu/qgraphicspiemenu_p.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/animation/piemenu/qgraphicspiemenu_p.h b/examples/animation/piemenu/qgraphicspiemenu_p.h index 87a749c..93b0079 100644 --- a/examples/animation/piemenu/qgraphicspiemenu_p.h +++ b/examples/animation/piemenu/qgraphicspiemenu_p.h @@ -17,7 +17,6 @@ #include #include -#include #include class QAction; @@ -34,7 +33,6 @@ public: QString title; QStateMachine *machine; QState *popupState; - //QTransition *transition; QList sections; QEventLoop *eventLoop; -- cgit v0.12 From ad1441fcb1c66ddafd890c1aa22a631d12c4ee0d Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 23 Apr 2009 11:46:02 +0200 Subject: Remove API for setting specific restore policies on states. We have no clear use case for this, so it has been removed. If the requirement arises we can add it back in later. Since it no longer makes sense to have it in QAbstractState, the RestorePolicy enum has been moved to QStateMachine. --- examples/animation/appchooser/main.cpp | 2 +- src/corelib/statemachine/qabstractstate.cpp | 60 +------------------------- src/corelib/statemachine/qabstractstate.h | 11 ----- src/corelib/statemachine/qabstractstate_p.h | 1 - src/corelib/statemachine/qstatemachine.cpp | 54 ++++++++++++++--------- src/corelib/statemachine/qstatemachine.h | 10 ++++- src/corelib/statemachine/qstatemachine_p.h | 2 +- tests/auto/qstate/tst_qstate.cpp | 25 ++--------- tests/auto/qstatemachine/tst_qstatemachine.cpp | 41 ++++++++++-------- 9 files changed, 73 insertions(+), 133 deletions(-) diff --git a/examples/animation/appchooser/main.cpp b/examples/animation/appchooser/main.cpp index 1a43ed7..6735012 100644 --- a/examples/animation/appchooser/main.cpp +++ b/examples/animation/appchooser/main.cpp @@ -104,7 +104,7 @@ int main(int argc, char **argv) window.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); QStateMachine machine; - machine.setGlobalRestorePolicy(QState::RestoreProperties); + machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties); QState *group = new QState(machine.rootState()); group->setObjectName("group"); diff --git a/src/corelib/statemachine/qabstractstate.cpp b/src/corelib/statemachine/qabstractstate.cpp index 030c63c..396063a 100644 --- a/src/corelib/statemachine/qabstractstate.cpp +++ b/src/corelib/statemachine/qabstractstate.cpp @@ -76,45 +76,7 @@ QT_BEGIN_NAMESPACE function to perform custom processing when the state is exited. */ -/*! - \enum QAbstractState::RestorePolicy - - This enum specifies the restore policy type for a state. The restore policy - takes effect when the machine enters a state which sets one or more - properties. If the restore policy of the state is set to RestoreProperties, - the state machine will save the original value of the property before the - new value is set. - - Later, when the machine either enters a state which has its restore policy - set to DoNotRestoreProperties or when it enters a state which does not set - a value for the given property, the property will automatically be restored - to its initial value. - - Only one initial value will be saved for any given property. If a value for a property has - already been saved by the state machine, it will not be overwritten until the property has been - successfully restored. Once the property has been restored, the state machine will clear the - initial value until it enters a new state which sets the property and which has RestoreProperties - as its restore policy. - - \value GlobalRestorePolicy The restore policy for the state should be retrieved using - QStateMachine::globalRestorePolicy() - \value DoNotRestoreProperties The state machine should not save the initial values of properties - set in the state and restore them later. - \value RestoreProperties The state machine should save the initial values of properties - set in the state and restore them later. - - - \sa setRestorePolicy(), restorePolicy(), QAbstractState::assignProperty() -*/ - -/*! - \property QAbstractState::restorePolicy - - \brief the restore policy of this state -*/ - -QAbstractStatePrivate::QAbstractStatePrivate() - : restorePolicy(QAbstractState::GlobalRestorePolicy) +QAbstractStatePrivate::QAbstractStatePrivate() { } @@ -237,26 +199,6 @@ void QAbstractState::assignProperty(QObject *object, const char *name, } /*! - Sets the restore policy of this state to \a restorePolicy. - - The default restore policy is QAbstractState::GlobalRestorePolicy. -*/ -void QAbstractState::setRestorePolicy(RestorePolicy restorePolicy) -{ - Q_D(QAbstractState); - d->restorePolicy = restorePolicy; -} - -/*! - Returns the restore policy for this state. -*/ -QAbstractState::RestorePolicy QAbstractState::restorePolicy() const -{ - Q_D(const QAbstractState); - return d->restorePolicy; -} - -/*! \fn QAbstractState::onExit() This function is called when the state is exited. Reimplement this function diff --git a/src/corelib/statemachine/qabstractstate.h b/src/corelib/statemachine/qabstractstate.h index 55e9a62..69e6bf1 100644 --- a/src/corelib/statemachine/qabstractstate.h +++ b/src/corelib/statemachine/qabstractstate.h @@ -56,15 +56,7 @@ class QAbstractStatePrivate; class Q_CORE_EXPORT QAbstractState : public QObject { Q_OBJECT - Q_ENUMS(RestorePolicy) - Q_PROPERTY(RestorePolicy restorePolicy READ restorePolicy WRITE setRestorePolicy) public: - enum RestorePolicy { - GlobalRestorePolicy, - DoNotRestoreProperties, - RestoreProperties - }; - ~QAbstractState(); QState *parentState() const; @@ -72,9 +64,6 @@ public: void assignProperty(QObject *object, const char *name, const QVariant &value); - void setRestorePolicy(RestorePolicy restorePolicy); - RestorePolicy restorePolicy() const; - Q_SIGNALS: void entered(); void exited(); diff --git a/src/corelib/statemachine/qabstractstate_p.h b/src/corelib/statemachine/qabstractstate_p.h index e47fbd2..8c8f436 100644 --- a/src/corelib/statemachine/qabstractstate_p.h +++ b/src/corelib/statemachine/qabstractstate_p.h @@ -101,7 +101,6 @@ public: void emitEntered(); void emitExited(); - QAbstractState::RestorePolicy restorePolicy; QList propertyAssignments; #ifdef QT_STATEMACHINE_SOLUTION diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index b6ab205..2d3eea1 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -188,7 +188,7 @@ QStateMachinePrivate::QStateMachinePrivate() processingScheduled = false; stop = false; error = QStateMachine::NoError; - globalRestorePolicy = QAbstractState::DoNotRestoreProperties; + globalRestorePolicy = QStateMachine::DoNotRestoreProperties; rootState = 0; initialErrorStateForRoot = 0; #ifndef QT_STATEMACHINE_SOLUTION @@ -631,14 +631,10 @@ void QStateMachinePrivate::applyProperties(const QList &tr for (int i = 0; i < enteredStates.size(); ++i) { QAbstractState *s = enteredStates.at(i); - QAbstractState::RestorePolicy restorePolicy = s->restorePolicy(); - if (restorePolicy == QAbstractState::GlobalRestorePolicy) - restorePolicy = globalRestorePolicy; - QList assignments = QAbstractStatePrivate::get(s)->propertyAssignments; for (int j = 0; j < assignments.size(); ++j) { const QPropertyAssignment &assn = assignments.at(j); - if (restorePolicy == QAbstractState::RestoreProperties) { + if (globalRestorePolicy == QStateMachine::RestoreProperties) { registerRestorable(assn.object, assn.propertyName); } pendingRestorables.remove(RestorableId(assn.object, assn.propertyName)); @@ -1458,6 +1454,32 @@ void QStateMachine::setErrorState(QAbstractState *state) */ /*! + \enum QStateMachine::RestorePolicy + + This enum specifies the restore policy type. The restore policy + takes effect when the machine enters a state which sets one or more + properties. If the restore policy is set to RestoreProperties, + the state machine will save the original value of the property before the + new value is set. + + Later, when the machine either enters a state which does not set + a value for the given property, the property will automatically be restored + to its initial value. + + Only one initial value will be saved for any given property. If a value for a property has + already been saved by the state machine, it will not be overwritten until the property has been + successfully restored. + + \value DoNotRestoreProperties The state machine should not save the initial values of properties + and restore them later. + \value RestoreProperties The state machine should save the initial values of properties + and restore them later. + + \sa setRestorePolicy(), restorePolicy(), QAbstractState::assignProperty() +*/ + + +/*! Returns the error code of the last error that occurred in the state machine. */ QStateMachine::Error QStateMachine::error() const @@ -1486,33 +1508,25 @@ void QStateMachine::clearError() } /*! - Returns the global restore policy of the state machine. + Returns the restore policy of the state machine. - \sa QAbstractState::restorePolicy() + \sa setGlobalRestorePolicy() */ -QAbstractState::RestorePolicy QStateMachine::globalRestorePolicy() const +QStateMachine::RestorePolicy QStateMachine::globalRestorePolicy() const { Q_D(const QStateMachine); return d->globalRestorePolicy; } /*! - Sets the global restore policy of the state machine to \a restorePolicy. The default global + Sets the restore policy of the state machine to \a restorePolicy. The default restore policy is QAbstractState::DoNotRestoreProperties. - The global restore policy cannot be set to QAbstractState::GlobalRestorePolicy. - - \sa QAbstractState::setRestorePolicy() + \sa globalRestorePolicy() */ -void QStateMachine::setGlobalRestorePolicy(QAbstractState::RestorePolicy restorePolicy) +void QStateMachine::setGlobalRestorePolicy(QStateMachine::RestorePolicy restorePolicy) { Q_D(QStateMachine); - if (restorePolicy == QState::GlobalRestorePolicy) { - qWarning("QStateMachine::setGlobalRestorePolicy: Cannot set global restore policy to " - "GlobalRestorePolicy"); - return; - } - d->globalRestorePolicy = restorePolicy; } diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h index 901d160..9a7a6fc 100644 --- a/src/corelib/statemachine/qstatemachine.h +++ b/src/corelib/statemachine/qstatemachine.h @@ -72,7 +72,13 @@ class Q_CORE_EXPORT QStateMachine : public QObject Q_PROPERTY(QAbstractState* initialState READ initialState WRITE setInitialState) Q_PROPERTY(QAbstractState* errorState READ errorState WRITE setErrorState) Q_PROPERTY(QString errorString READ errorString) + Q_PROPERTY(RestorePolicy globalRestorePolicy READ globalRestorePolicy WRITE setGlobalRestorePolicy) + Q_ENUMS(RestorePolicy) public: + enum RestorePolicy { + DoNotRestoreProperties, + RestoreProperties + }; enum Error { NoError, @@ -112,8 +118,8 @@ public: void removeDefaultAnimationForTargetState(QAbstractState *targetState, QAbstractAnimation *animation); #endif // QT_NO_ANIMATION - QAbstractState::RestorePolicy globalRestorePolicy() const; - void setGlobalRestorePolicy(QAbstractState::RestorePolicy restorePolicy); + QStateMachine::RestorePolicy globalRestorePolicy() const; + void setGlobalRestorePolicy(QStateMachine::RestorePolicy restorePolicy); void postEvent(QEvent *event, int delay = 0); diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index 910b751..9f93217 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -171,7 +171,7 @@ public: QList externalEventQueue; QStateMachine::Error error; - QAbstractState::RestorePolicy globalRestorePolicy; + QStateMachine::RestorePolicy globalRestorePolicy; QString errorString; QSet pendingErrorStates; diff --git a/tests/auto/qstate/tst_qstate.cpp b/tests/auto/qstate/tst_qstate.cpp index f79fcd4..f082caf 100644 --- a/tests/auto/qstate/tst_qstate.cpp +++ b/tests/auto/qstate/tst_qstate.cpp @@ -9,9 +9,7 @@ #include "qstate.h" #include "qstatemachine.h" -#include "qactiontransition.h" #include "qsignaltransition.h" -#include "qstateaction.h" // Will try to wait for the condition while allowing event processing #define QTRY_COMPARE(__expr, __expected) \ @@ -45,7 +43,6 @@ private slots: void assignProperty(); void assignPropertyTwice(); void historyInitialState(); - void addEntryAction(); private: bool functionCalled; @@ -214,22 +211,6 @@ public slots: }; -void tst_QState::addEntryAction() -{ - QStateMachine sm; - - TestClass testObject; - - QState *s0 = new QState(sm.rootState()); - s0->addEntryAction(new QStateInvokeMethodAction(&testObject, "slot")); - sm.setInitialState(s0); - - sm.start(); - QCoreApplication::processEvents(); - - QCOMPARE(testObject.called, true); -} - void tst_QState::assignProperty() { QStateMachine machine; @@ -265,11 +246,11 @@ void tst_QState::assignPropertyTwice() QCOMPARE(object->property("fooBar").toInt(), 30); } -class EventTestTransition: public QActionTransition +class EventTestTransition: public QAbstractTransition { public: EventTestTransition(QEvent::Type type, QState *targetState) - : QActionTransition(QList() << targetState), m_type(type) + : QAbstractTransition(QList() << targetState), m_type(type) { } @@ -279,6 +260,8 @@ protected: return e->type() == m_type; } + void onTransition() {} + private: QEvent::Type m_type; diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index bf3ff71..2fa9b1a 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -121,14 +121,17 @@ private slots: void customErrorStateNotInGraph(); void transitionToStateNotInGraph(); void restoreProperties(); + void defaultGlobalRestorePolicy(); void globalRestorePolicySetToRestore(); void globalRestorePolicySetToDoNotRestore(); - void restorePolicyNotInherited(); - void mixedRestoreProperties(); - void setRestorePolicyToDoNotRestore(); - void setGlobalRestorePolicyToGlobalRestore(); - void restorePolicyOnChildState(); + + //void restorePolicyNotInherited(); + //void mixedRestoreProperties(); + //void setRestorePolicyToDoNotRestore(); + //void setGlobalRestorePolicyToGlobalRestore(); + //void restorePolicyOnChildState(); + void transitionWithParent(); void simpleAnimation(); @@ -923,22 +926,20 @@ void tst_QStateMachine::restoreProperties() object->setProperty("b", 2); QStateMachine machine; + machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties); QState *S1 = new QState(); S1->setObjectName("S1"); S1->assignProperty(object, "a", 3); - S1->setRestorePolicy(QState::RestoreProperties); machine.addState(S1); QState *S2 = new QState(); S2->setObjectName("S2"); S2->assignProperty(object, "b", 5); - S2->setRestorePolicy(QState::RestoreProperties); machine.addState(S2); QState *S3 = new QState(); S3->setObjectName("S3"); - S3->setRestorePolicy(QState::RestoreProperties); machine.addState(S3); QFinalState *S4 = new QFinalState(); @@ -1668,6 +1669,7 @@ void tst_QStateMachine::defaultGlobalRestorePolicy() QCOMPARE(propertyHolder->property("b").toInt(), 4); } +/* void tst_QStateMachine::restorePolicyNotInherited() { QStateMachine machine; @@ -1714,12 +1716,12 @@ void tst_QStateMachine::restorePolicyNotInherited() QCOMPARE(propertyHolder->property("a").toInt(), 3); QCOMPARE(propertyHolder->property("b").toInt(), 4); -} +}*/ void tst_QStateMachine::globalRestorePolicySetToDoNotRestore() { QStateMachine machine; - machine.setGlobalRestorePolicy(QState::DoNotRestoreProperties); + machine.setGlobalRestorePolicy(QStateMachine::DoNotRestoreProperties); QObject *propertyHolder = new QObject(); propertyHolder->setProperty("a", 1); @@ -1756,6 +1758,7 @@ void tst_QStateMachine::globalRestorePolicySetToDoNotRestore() QCOMPARE(propertyHolder->property("b").toInt(), 4); } +/* void tst_QStateMachine::setRestorePolicyToDoNotRestore() { QObject *object = new QObject(); @@ -1812,19 +1815,20 @@ void tst_QStateMachine::setGlobalRestorePolicyToGlobalRestore() { s_countWarnings = false; QStateMachine machine; - machine.setGlobalRestorePolicy(QState::GlobalRestorePolicy); + machine.setGlobalRestorePolicy(QStateMachine::GlobalRestorePolicy); - QCOMPARE(machine.globalRestorePolicy(), QState::DoNotRestoreProperties); + QCOMPARE(machine.globalRestorePolicy(), QStateMachine::DoNotRestoreProperties); QCOMPARE(s_msgType, QtWarningMsg); s_msgType = QtDebugMsg; - machine.setGlobalRestorePolicy(QState::RestoreProperties); - machine.setGlobalRestorePolicy(QState::GlobalRestorePolicy); + machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties); + machine.setGlobalRestorePolicy(QStateMachine::GlobalRestorePolicy); - QCOMPARE(machine.globalRestorePolicy(), QState::RestoreProperties); + QCOMPARE(machine.globalRestorePolicy(), QStateMachine::RestoreProperties); QCOMPARE(s_msgType, QtWarningMsg); } + void tst_QStateMachine::restorePolicyOnChildState() { QStateMachine machine; @@ -1873,11 +1877,12 @@ void tst_QStateMachine::restorePolicyOnChildState() QCOMPARE(propertyHolder->property("a").toInt(), 1); QCOMPARE(propertyHolder->property("b").toInt(), 2); } +*/ void tst_QStateMachine::globalRestorePolicySetToRestore() { QStateMachine machine; - machine.setGlobalRestorePolicy(QState::RestoreProperties); + machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties); QObject *propertyHolder = new QObject(); propertyHolder->setProperty("a", 1); @@ -1914,6 +1919,7 @@ void tst_QStateMachine::globalRestorePolicySetToRestore() QCOMPARE(propertyHolder->property("b").toInt(), 2); } +/* void tst_QStateMachine::mixedRestoreProperties() { QStateMachine machine; @@ -1980,6 +1986,7 @@ void tst_QStateMachine::mixedRestoreProperties() // Enter s3, restore QCOMPARE(propertyHolder->property("a").toInt(), 5); } +*/ void tst_QStateMachine::transitionWithParent() { @@ -2224,7 +2231,7 @@ void tst_QStateMachine::nestedTargetStateForAnimation() void tst_QStateMachine::animatedGlobalRestoreProperty() { QStateMachine machine; - machine.setGlobalRestorePolicy(QState::RestoreProperties); + machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties); QObject *object = new QObject(); object->setProperty("foo", 1.0); -- cgit v0.12 From a8cce89940e42fb05efef049122286652bae61e3 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Fri, 24 Apr 2009 17:04:19 +0200 Subject: Add an OSD to display game progress in the scene --- examples/animation/sub-attaq/boat.cpp | 79 ++++++++++++++++------- examples/animation/sub-attaq/boat.h | 6 ++ examples/animation/sub-attaq/boat_p.h | 6 +- examples/animation/sub-attaq/graphicsscene.cpp | 22 +++++-- examples/animation/sub-attaq/graphicsscene.h | 5 ++ examples/animation/sub-attaq/progressitem.cpp | 67 +++++++++++++++++++ examples/animation/sub-attaq/progressitem.h | 61 ++++++++++++++++++ examples/animation/sub-attaq/states.cpp | 89 +++++++++++++++++++------- examples/animation/sub-attaq/states.h | 31 ++++++++- examples/animation/sub-attaq/sub-attaq.pro | 11 ++-- examples/animation/sub-attaq/submarine.cpp | 8 +-- 11 files changed, 320 insertions(+), 65 deletions(-) create mode 100644 examples/animation/sub-attaq/progressitem.cpp create mode 100644 examples/animation/sub-attaq/progressitem.h diff --git a/examples/animation/sub-attaq/boat.cpp b/examples/animation/sub-attaq/boat.cpp index 5721485..5b270c0 100644 --- a/examples/animation/sub-attaq/boat.cpp +++ b/examples/animation/sub-attaq/boat.cpp @@ -99,10 +99,30 @@ static QAbstractAnimation *setupDestroyAnimation(Boat *boat) anim4->setMemberFunctions((QGraphicsItem*)step4, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity); anim4->setDuration(100); anim4->setEndValue(1); + CustomPropertyAnimation *anim5 = new CustomPropertyAnimation(boat); + anim5->setMemberFunctions((QGraphicsItem*)step1, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity); + anim5->setDuration(100); + anim5->setEndValue(0); + CustomPropertyAnimation *anim6 = new CustomPropertyAnimation(boat); + anim6->setMemberFunctions((QGraphicsItem*)step2, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity); + anim6->setDuration(100); + anim6->setEndValue(0); + CustomPropertyAnimation *anim7 = new CustomPropertyAnimation(boat); + anim7->setMemberFunctions((QGraphicsItem*)step3, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity); + anim7->setDuration(100); + anim7->setEndValue(0); + CustomPropertyAnimation *anim8 = new CustomPropertyAnimation(boat); + anim8->setMemberFunctions((QGraphicsItem*)step4, &QGraphicsItem::opacity, &QGraphicsItem::setOpacity); + anim8->setDuration(100); + anim8->setEndValue(0); group->addAnimation(anim1); group->addAnimation(anim2); group->addAnimation(anim3); group->addAnimation(anim4); + group->addAnimation(anim5); + group->addAnimation(anim6); + group->addAnimation(anim7); + group->addAnimation(anim8); #else // work around for a bug where we don't transition if the duration is zero. QtPauseAnimation *anim = new QtPauseAnimation(group); @@ -126,37 +146,39 @@ Boat::Boat(QGraphicsItem * parent, Qt::WindowFlags wFlags) //The movement animation used to animate the boat movementAnimation = new QPropertyAnimation(this, "pos"); - AnimationManager::self()->registerAnimation(movementAnimation); + + //The movement animation used to animate the boat + destroyAnimation = setupDestroyAnimation(this); //We setup the state machien of the boat - QStateMachine *machine = new QStateMachine(this); + machine = new QStateMachine(this); QState *moving = new QState(machine->rootState()); - StopState *stopState = new StopState(this,moving); + StopState *stopState = new StopState(this, moving); machine->setInitialState(moving); moving->setInitialState(stopState); - MoveStateRight *moveStateRight = new MoveStateRight(this,moving); - MoveStateLeft *moveStateLeft = new MoveStateLeft(this,moving); - LaunchStateRight *launchStateRight = new LaunchStateRight(this,machine->rootState()); - LaunchStateLeft *launchStateLeft = new LaunchStateLeft(this,machine->rootState()); + MoveStateRight *moveStateRight = new MoveStateRight(this, moving); + MoveStateLeft *moveStateLeft = new MoveStateLeft(this, moving); + LaunchStateRight *launchStateRight = new LaunchStateRight(this, machine->rootState()); + LaunchStateLeft *launchStateLeft = new LaunchStateLeft(this, machine->rootState()); //then setup the transitions for the rightMove state - KeyStopTransition *leftStopRight = new KeyStopTransition(this,QEvent::KeyPress,Qt::Key_Left); + KeyStopTransition *leftStopRight = new KeyStopTransition(this, QEvent::KeyPress, Qt::Key_Left); leftStopRight->setTargetState(stopState); - KeyMoveTransition *leftMoveRight = new KeyMoveTransition(this,QEvent::KeyPress,Qt::Key_Left); + KeyMoveTransition *leftMoveRight = new KeyMoveTransition(this, QEvent::KeyPress, Qt::Key_Left); leftMoveRight->setTargetState(moveStateRight); - KeyMoveTransition *rightMoveRight = new KeyMoveTransition(this,QEvent::KeyPress,Qt::Key_Right); + KeyMoveTransition *rightMoveRight = new KeyMoveTransition(this, QEvent::KeyPress, Qt::Key_Right); rightMoveRight->setTargetState(moveStateRight); - KeyMoveTransition *rightMoveStop = new KeyMoveTransition(this,QEvent::KeyPress,Qt::Key_Right); + KeyMoveTransition *rightMoveStop = new KeyMoveTransition(this, QEvent::KeyPress, Qt::Key_Right); rightMoveStop->setTargetState(moveStateRight); //then setup the transitions for the leftMove state - KeyStopTransition *rightStopLeft = new KeyStopTransition(this,QEvent::KeyPress,Qt::Key_Right); + KeyStopTransition *rightStopLeft = new KeyStopTransition(this, QEvent::KeyPress, Qt::Key_Right); rightStopLeft->setTargetState(stopState); - KeyMoveTransition *rightMoveLeft = new KeyMoveTransition(this,QEvent::KeyPress,Qt::Key_Right); + KeyMoveTransition *rightMoveLeft = new KeyMoveTransition(this, QEvent::KeyPress, Qt::Key_Right); rightMoveLeft->setTargetState(moveStateLeft); - KeyMoveTransition *leftMoveLeft = new KeyMoveTransition(this,QEvent::KeyPress,Qt::Key_Left); + KeyMoveTransition *leftMoveLeft = new KeyMoveTransition(this, QEvent::KeyPress,Qt::Key_Left); leftMoveLeft->setTargetState(moveStateLeft); - KeyMoveTransition *leftMoveStop = new KeyMoveTransition(this,QEvent::KeyPress,Qt::Key_Left); + KeyMoveTransition *leftMoveStop = new KeyMoveTransition(this, QEvent::KeyPress,Qt::Key_Left); leftMoveStop->setTargetState(moveStateLeft); //We set up the right move state @@ -176,17 +198,17 @@ Boat::Boat(QGraphicsItem * parent, Qt::WindowFlags wFlags) moveStateRight->addTransition(movementAnimation, SIGNAL(finished()), stopState); //We set up the keys for dropping bombs - KeyLaunchTransition *upFireLeft = new KeyLaunchTransition(this,QEvent::KeyPress,Qt::Key_Up); + KeyLaunchTransition *upFireLeft = new KeyLaunchTransition(this, QEvent::KeyPress, Qt::Key_Up); upFireLeft->setTargetState(launchStateRight); - KeyLaunchTransition *upFireRight = new KeyLaunchTransition(this,QEvent::KeyPress,Qt::Key_Up); + KeyLaunchTransition *upFireRight = new KeyLaunchTransition(this, QEvent::KeyPress, Qt::Key_Up); upFireRight->setTargetState(launchStateRight); - KeyLaunchTransition *upFireStop = new KeyLaunchTransition(this,QEvent::KeyPress,Qt::Key_Up); + KeyLaunchTransition *upFireStop = new KeyLaunchTransition(this, QEvent::KeyPress, Qt::Key_Up); upFireStop->setTargetState(launchStateRight); - KeyLaunchTransition *downFireLeft = new KeyLaunchTransition(this,QEvent::KeyPress,Qt::Key_Down); + KeyLaunchTransition *downFireLeft = new KeyLaunchTransition(this, QEvent::KeyPress, Qt::Key_Down); downFireLeft->setTargetState(launchStateLeft); - KeyLaunchTransition *downFireRight = new KeyLaunchTransition(this,QEvent::KeyPress,Qt::Key_Down); + KeyLaunchTransition *downFireRight = new KeyLaunchTransition(this, QEvent::KeyPress, Qt::Key_Down); downFireRight->setTargetState(launchStateLeft); - KeyLaunchTransition *downFireMove = new KeyLaunchTransition(this,QEvent::KeyPress,Qt::Key_Down); + KeyLaunchTransition *downFireMove = new KeyLaunchTransition(this, QEvent::KeyPress, Qt::Key_Down); downFireMove->setTargetState(launchStateLeft); //We set up transitions for fire up @@ -208,7 +230,7 @@ Boat::Boat(QGraphicsItem * parent, Qt::WindowFlags wFlags) //This state play the destroyed animation QAnimationState *destroyedState = new QAnimationState(machine->rootState()); - destroyedState->setAnimation(setupDestroyAnimation(this)); + destroyedState->setAnimation(destroyAnimation); //Play a nice animation when the boat is destroyed moving->addTransition(this, SIGNAL(boatDestroyed()),destroyedState); @@ -219,9 +241,22 @@ Boat::Boat(QGraphicsItem * parent, Qt::WindowFlags wFlags) //The machine has finished to be executed, then the boat is dead connect(machine,SIGNAL(finished()),this, SIGNAL(boatExecutionFinished())); +} + +void Boat::run() +{ + //We register animations + AnimationManager::self()->registerAnimation(movementAnimation); + AnimationManager::self()->registerAnimation(destroyAnimation); machine->start(); } +void Boat::stop() +{ + movementAnimation->stop(); + machine->stop(); +} + void Boat::updateBoatMovement() { if (speed == 0 || direction == Boat::None) { diff --git a/examples/animation/sub-attaq/boat.h b/examples/animation/sub-attaq/boat.h index b8d5772..44de367 100644 --- a/examples/animation/sub-attaq/boat.h +++ b/examples/animation/sub-attaq/boat.h @@ -57,6 +57,8 @@ class PixmapItem; class Bomb; class QVariantAnimation; +class QAbstractAnimation; +class QStateMachine; class Boat : public QGraphicsWidget { @@ -71,6 +73,8 @@ public: enum { Type = UserType + 2 }; Boat(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0); void destroy(); + void run(); + void stop(); int bombsLaunched() const; void setBombsLaunched(int number); @@ -94,6 +98,8 @@ private: int bombsAlreadyLaunched; Movement direction; QVariantAnimation *movementAnimation; + QAbstractAnimation *destroyAnimation; + QStateMachine *machine; PixmapItem *pixmapItem; }; diff --git a/examples/animation/sub-attaq/boat_p.h b/examples/animation/sub-attaq/boat_p.h index 8dacaba..3c466b3 100644 --- a/examples/animation/sub-attaq/boat_p.h +++ b/examples/animation/sub-attaq/boat_p.h @@ -61,7 +61,7 @@ class KeyStopTransition : public QKeyEventTransition { public: KeyStopTransition(Boat *boat, QEvent::Type type, int key) - : QKeyEventTransition(boat,type, key) + : QKeyEventTransition(boat, type, key) { this->boat = boat; this->key = key; @@ -90,7 +90,7 @@ private: { public: KeyMoveTransition(Boat *boat, QEvent::Type type, int key) - : QKeyEventTransition(boat,type, key) + : QKeyEventTransition(boat, type, key) { this->boat = boat; this->key = key; @@ -131,7 +131,7 @@ private: { public: KeyLaunchTransition(Boat *boat, QEvent::Type type, int key) - : QKeyEventTransition(boat,type, key) + : QKeyEventTransition(boat, type, key) { this->boat = boat; this->key = key; diff --git a/examples/animation/sub-attaq/graphicsscene.cpp b/examples/animation/sub-attaq/graphicsscene.cpp index 5dcc034..a66925c 100644 --- a/examples/animation/sub-attaq/graphicsscene.cpp +++ b/examples/animation/sub-attaq/graphicsscene.cpp @@ -50,6 +50,7 @@ #include "custompropertyanimation.h" #include "animationmanager.h" #include "qanimationstate.h" +#include "progressitem.h" //Qt #if defined(QT_EXPERIMENTAL_SOLUTION) @@ -117,6 +118,15 @@ GraphicsScene::GraphicsScene(int x, int y, int width, int height, Mode mode) surfaceItem->setPos(0,sealLevel() - surfaceItem->boundingRect().height()/2); addItem(surfaceItem); + //The item that display score and level + progressItem = new ProgressItem(backgroundItem); + + //We create the boat + boat = new Boat(); + addItem(boat); + boat->setPos(this->width()/2, sealLevel() - boat->size().height()); + boat->hide(); + //parse the xml that contain all data of the game QXmlStreamReader reader; QFile file(QDir::currentPath() + "/data.xml"); @@ -335,17 +345,17 @@ void GraphicsScene::clearScene() { foreach (SubMarine *sub,submarines) { sub->destroy(); - delete sub; + sub->deleteLater(); } foreach (Torpedo *torpedo,torpedos) { torpedo->destroy(); - delete torpedo; + torpedo->deleteLater(); } foreach (Bomb *bomb,bombs) { bomb->destroy(); - delete bomb; + bomb->deleteLater(); } submarines.clear(); @@ -354,10 +364,8 @@ void GraphicsScene::clearScene() AnimationManager::self()->unregisterAllAnimations(); - if (boat) { - delete boat; - boat = 0; - } + boat->stop(); + boat->hide(); } QGraphicsPixmapItem *GraphicsScene::addWelcomeItem(const QPixmap &pm) diff --git a/examples/animation/sub-attaq/graphicsscene.h b/examples/animation/sub-attaq/graphicsscene.h index 875f59f..bc9734c 100644 --- a/examples/animation/sub-attaq/graphicsscene.h +++ b/examples/animation/sub-attaq/graphicsscene.h @@ -58,6 +58,7 @@ class SubMarine; class Torpedo; class Bomb; class PixmapItem; +class ProgressItem; class QAction; class GraphicsScene : public QGraphicsScene @@ -109,6 +110,7 @@ private slots: private: Mode mode; PixmapItem *backgroundItem; + ProgressItem *progressItem; QAction * newAction; QAction * quitAction; Boat *boat; @@ -121,8 +123,11 @@ private: friend class PauseState; friend class PlayState; + friend class LevelState; friend class LostState; friend class WinState; + friend class WinTransition; + friend class UpdateScoreTransition; }; #endif //__GRAPHICSSCENE__H__ diff --git a/examples/animation/sub-attaq/progressitem.cpp b/examples/animation/sub-attaq/progressitem.cpp new file mode 100644 index 0000000..59ccb9a --- /dev/null +++ b/examples/animation/sub-attaq/progressitem.cpp @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "progressitem.h" +#include "pixmapitem.h" + +ProgressItem::ProgressItem (QGraphicsItem * parent) + : QGraphicsTextItem(parent), currentLevel(1), currentScore(0) +{ + setFont(QFont("Comic Sans MS")); + setPos(parentItem()->boundingRect().topRight() - QPointF(180, -5)); +} + +void ProgressItem::setLevel(int level) +{ + currentLevel = level; + updateProgress(); +} + +void ProgressItem::setScore(int score) +{ + currentScore = score; + updateProgress(); +} + +void ProgressItem::updateProgress() +{ + setHtml(QString("Level : %1 Score : %2").arg(currentLevel).arg(currentScore)); +} diff --git a/examples/animation/sub-attaq/progressitem.h b/examples/animation/sub-attaq/progressitem.h new file mode 100644 index 0000000..006cc6d --- /dev/null +++ b/examples/animation/sub-attaq/progressitem.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PROGRESSITEM_H +#define PROGRESSITEM_H + +//Qt +#include + +class ProgressItem : public QGraphicsTextItem +{ +public: + ProgressItem(QGraphicsItem * parent = 0); + void setLevel(int level); + void setScore(int score); + +private: + void updateProgress(); + int currentLevel; + int currentScore; +}; + +#endif // PROGRESSITEM_H diff --git a/examples/animation/sub-attaq/states.cpp b/examples/animation/sub-attaq/states.cpp index f476f55..5dce445 100644 --- a/examples/animation/sub-attaq/states.cpp +++ b/examples/animation/sub-attaq/states.cpp @@ -46,6 +46,7 @@ #include "submarine.h" #include "torpedo.h" #include "animationmanager.h" +#include "progressitem.h" //Qt #include @@ -81,27 +82,31 @@ void PlayState::onEntry() if (machine) { machine->stop(); scene->clearScene(); + currentLevel = 0; + score = 0; delete machine; } machine = new QStateMachine(this); //This state is when player is playing - QState *playState = new QState(machine->rootState()); + LevelState *levelState = new LevelState(scene, this, machine->rootState()); - initializeLevel(); + //This state is when the player is actually playing but the game is not paused + QState *playingState = new QState(levelState); + levelState->setInitialState(playingState); //This state is when the game is paused - PauseState *pauseState = new PauseState(scene, machine->rootState()); + PauseState *pauseState = new PauseState(scene, levelState); //We have one view, it receive the key press event QKeyEventTransition *pressPplay = new QKeyEventTransition(scene->views().at(0), QEvent::KeyPress, Qt::Key_P); pressPplay->setTargetState(pauseState); QKeyEventTransition *pressPpause = new QKeyEventTransition(scene->views().at(0), QEvent::KeyPress, Qt::Key_P); - pressPpause->setTargetState(playState); + pressPpause->setTargetState(playingState); //Pause "P" is triggered, the player pause the game - playState->addTransition(pressPplay); + playingState->addTransition(pressPplay); //To get back playing when the game has been paused pauseState->addTransition(pressPpause); @@ -113,34 +118,37 @@ void PlayState::onEntry() WinState *winState = new WinState(scene, this, machine->rootState()); //The boat has been destroyed then the game is finished - playState->addTransition(scene->boat, SIGNAL(boatExecutionFinished()),lostState); + levelState->addTransition(scene->boat, SIGNAL(boatExecutionFinished()),lostState); //This transition check if we won or not WinTransition *winTransition = new WinTransition(scene, this, winState); //The boat has been destroyed then the game is finished - playState->addTransition(winTransition); + levelState->addTransition(winTransition); //This state is an animation when the score changed - UpdateScoreState *scoreState = new UpdateScoreState(this, machine->rootState()); + UpdateScoreState *scoreState = new UpdateScoreState(this, levelState); //This transition update the score when a submarine die - UpdateScoreTransition *scoreTransition = new UpdateScoreTransition(scene, this, scoreState); + UpdateScoreTransition *scoreTransition = new UpdateScoreTransition(scene, this, levelState); + scoreTransition->setTargetState(scoreState); //The boat has been destroyed then the game is finished - playState->addTransition(scoreTransition); + playingState->addTransition(scoreTransition); //We go back to play state - scoreState->addTransition(playState); + scoreState->addTransition(playingState); //We start playing!!! - machine->setInitialState(playState); + machine->setInitialState(levelState); //Final state QFinalState *final = new QFinalState(machine->rootState()); - //We win we should reach the final state - winState->addFinishedTransition(final); + //This transition is triggered when the player press space after completing a level + CustomSpaceTransition *spaceTransition = new CustomSpaceTransition(scene->views().at(0), this, QEvent::KeyPress, Qt::Key_Space); + spaceTransition->setTargetState(levelState); + winState->addTransition(spaceTransition); //We lost we should reach the final state lostState->addFinishedTransition(final); @@ -148,14 +156,29 @@ void PlayState::onEntry() machine->start(); } -void PlayState::initializeLevel() +LevelState::LevelState(GraphicsScene *scene, PlayState *game, QState *parent) : QState(parent), scene(scene), game(game) { - scene->boat = new Boat(); - scene->addItem(scene->boat); - scene->setFocusItem(scene->boat,Qt::OtherFocusReason); +} +void LevelState::onEntry() +{ + initializeLevel(); +} + +void LevelState::initializeLevel() +{ + //we re-init the boat scene->boat->setPos(scene->width()/2, scene->sealLevel() - scene->boat->size().height()); + scene->boat->setCurrentSpeed(0); + scene->boat->setCurrentDirection(Boat::None); + scene->boat->setBombsLaunched(0); + scene->boat->show(); + scene->setFocusItem(scene->boat,Qt::OtherFocusReason); + scene->boat->run(); + + scene->progressItem->setScore(game->score); + scene->progressItem->setLevel(game->currentLevel + 1); - GraphicsScene::LevelDescription currentLevelDescription = scene->levelsData.value(currentLevel); + GraphicsScene::LevelDescription currentLevelDescription = scene->levelsData.value(game->currentLevel); for (int i = 0; i < currentLevelDescription.submarines.size(); ++i ) { @@ -226,7 +249,7 @@ void WinState::onEntry() QString message; if (scene->levelsData.size() - 1 != game->currentLevel) { - message = QString("You win the level %1. Your score is %2.").arg(game->currentLevel+1).arg(game->score); + message = QString("You win the level %1. Your score is %2.\nPress Space to continue after closing this dialog.").arg(game->currentLevel+1).arg(game->score); //We increment the level number game->currentLevel++; } else { @@ -248,14 +271,13 @@ UpdateScoreState::UpdateScoreState(PlayState *game, QState *parent) : QState(par } void UpdateScoreState::onEntry() { - //### Make a nice anim to update the score in the scene QState::onEntry(); } /** Win transition */ UpdateScoreTransition::UpdateScoreTransition(GraphicsScene *scene, PlayState *game, QAbstractState *target) : QSignalTransition(scene,SIGNAL(subMarineDestroyed(int)), QList() << target), - game(game) + game(game), scene(scene) { } @@ -266,6 +288,7 @@ bool UpdateScoreTransition::eventTest(QEvent *event) const else { QSignalEvent *se = static_cast(event); game->score += se->arguments().at(0).toInt(); + scene->progressItem->setScore(game->score); return true; } } @@ -273,7 +296,7 @@ bool UpdateScoreTransition::eventTest(QEvent *event) const /** Win transition */ WinTransition::WinTransition(GraphicsScene *scene, PlayState *game, QAbstractState *target) : QSignalTransition(scene,SIGNAL(allSubMarineDestroyed(int)), QList() << target), - game(game) + game(game), scene(scene) { } @@ -284,6 +307,26 @@ bool WinTransition::eventTest(QEvent *event) const else { QSignalEvent *se = static_cast(event); game->score += se->arguments().at(0).toInt(); + scene->progressItem->setScore(game->score); return true; } } + +/** Space transition */ +CustomSpaceTransition::CustomSpaceTransition(QWidget *widget, PlayState *game, QEvent::Type type, int key) + : QKeyEventTransition(widget, type, key), + game(game) +{ +} + +bool CustomSpaceTransition::eventTest(QEvent *event) const +{ + Q_UNUSED(event); + if (!QKeyEventTransition::eventTest(event)) + return false; + if (game->currentLevel != 0) + return true; + else + return false; + +} diff --git a/examples/animation/sub-attaq/states.h b/examples/animation/sub-attaq/states.h index 52d4ffa..8dbdf86 100644 --- a/examples/animation/sub-attaq/states.h +++ b/examples/animation/sub-attaq/states.h @@ -47,10 +47,12 @@ #include "qstate.h" #include "qsignaltransition.h" #include "qpropertyanimation.h" +#include "qkeyeventtransition.h" #else #include #include #include +# include #endif #include @@ -64,7 +66,6 @@ class PlayState : public QState public: PlayState(GraphicsScene *scene, QState *parent = 0); ~PlayState(); - void initializeLevel(); protected: void onEntry(); @@ -79,8 +80,22 @@ private : friend class UpdateScoreState; friend class UpdateScoreTransition; friend class WinTransition; + friend class CustomSpaceTransition; friend class WinState; friend class LostState; + friend class LevelState; +}; + +class LevelState : public QState +{ +public: + LevelState(GraphicsScene *scene, PlayState *game, QState *parent = 0); +protected: + void onEntry(); +private : + void initializeLevel(); + GraphicsScene *scene; + PlayState *game; }; class PauseState : public QState @@ -140,6 +155,7 @@ protected: virtual bool eventTest(QEvent *event) const; private: PlayState * game; + GraphicsScene *scene; }; //These transtion test if we have won the game @@ -151,6 +167,19 @@ protected: virtual bool eventTest(QEvent *event) const; private: PlayState * game; + GraphicsScene *scene; +}; + +//These transtion is true if one level has been completed and the player want to continue + class CustomSpaceTransition : public QKeyEventTransition +{ +public: + CustomSpaceTransition(QWidget *widget, PlayState *game, QEvent::Type type, int key); +protected: + virtual bool eventTest(QEvent *event) const; +private: + PlayState *game; + int key; }; #endif // STATES_H diff --git a/examples/animation/sub-attaq/sub-attaq.pro b/examples/animation/sub-attaq/sub-attaq.pro index 1456d0e..961a9b5 100644 --- a/examples/animation/sub-attaq/sub-attaq.pro +++ b/examples/animation/sub-attaq/sub-attaq.pro @@ -2,10 +2,10 @@ # Automatically generated by qmake (2.01a) Thu Oct 9 10:53:30 2008 # ##################################################################### TEMPLATE = app -TARGET = +TARGET = DEPENDPATH += . INCLUDEPATH += . -QT+= xml +QT += xml contains(QT_CONFIG, opengl):QT += opengl # Input @@ -21,7 +21,8 @@ HEADERS += boat.h \ boat_p.h \ submarine_p.h \ custompropertyanimation.h \ - qanimationstate.h + qanimationstate.h \ + progressitem.h SOURCES += boat.cpp \ bomb.cpp \ main.cpp \ @@ -33,6 +34,6 @@ SOURCES += boat.cpp \ animationmanager.cpp \ states.cpp \ custompropertyanimation.cpp \ - qanimationstate.cpp - + qanimationstate.cpp \ + progressitem.cpp RESOURCES += subattaq.qrc diff --git a/examples/animation/sub-attaq/submarine.cpp b/examples/animation/sub-attaq/submarine.cpp index 555617c..b8a476e 100644 --- a/examples/animation/sub-attaq/submarine.cpp +++ b/examples/animation/sub-attaq/submarine.cpp @@ -126,15 +126,15 @@ SubMarine::SubMarine(int type, const QString &name, int points, QGraphicsItem * QState *moving = new QState(machine->rootState()); //This state is when the boat is moving from left to right - MovementState *movement = new MovementState(this,moving); + MovementState *movement = new MovementState(this, moving); //This state is when the boat is moving from left to right - ReturnState *rotation = new ReturnState(this,moving); + ReturnState *rotation = new ReturnState(this, moving); //This is the initial state of the moving root state moving->setInitialState(movement); - movement->addTransition(this, SIGNAL(subMarineStateChanged()),moving); + movement->addTransition(this, SIGNAL(subMarineStateChanged()), moving); //This is the initial state of the machine machine->setInitialState(moving); @@ -153,7 +153,7 @@ SubMarine::SubMarine(int type, const QString &name, int points, QGraphicsItem * destroyedState->setAnimation(setupDestroyAnimation(this)); //Play a nice animation when the submarine is destroyed - moving->addTransition(this, SIGNAL(subMarineDestroyed()),destroyedState); + moving->addTransition(this, SIGNAL(subMarineDestroyed()), destroyedState); //Transition to final state when the destroyed animation is finished destroyedState->addTransition(destroyedState, SIGNAL(animationFinished()), final); -- cgit v0.12 From c3290381a1dba7971dd70b7220a71e6feceb3f4c Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 24 Apr 2009 17:35:35 +0200 Subject: Unfinished tank AI game. The idea is that you plug in AIs for the tanks, and one such plugin will have a run time error, so the game server needs to use errorState for handling errors. --- examples/statemachine/errorstate/errorstate.pro | 13 ++ examples/statemachine/errorstate/main.cpp | 12 ++ examples/statemachine/errorstate/mainwindow.cpp | 184 ++++++++++++++++ examples/statemachine/errorstate/mainwindow.h | 41 ++++ examples/statemachine/errorstate/plugin.h | 16 ++ examples/statemachine/errorstate/tank.h | 31 +++ examples/statemachine/errorstate/tankitem.cpp | 274 ++++++++++++++++++++++++ examples/statemachine/errorstate/tankitem.h | 48 +++++ 8 files changed, 619 insertions(+) create mode 100644 examples/statemachine/errorstate/errorstate.pro create mode 100644 examples/statemachine/errorstate/main.cpp create mode 100644 examples/statemachine/errorstate/mainwindow.cpp create mode 100644 examples/statemachine/errorstate/mainwindow.h create mode 100644 examples/statemachine/errorstate/plugin.h create mode 100644 examples/statemachine/errorstate/tank.h create mode 100644 examples/statemachine/errorstate/tankitem.cpp create mode 100644 examples/statemachine/errorstate/tankitem.h diff --git a/examples/statemachine/errorstate/errorstate.pro b/examples/statemachine/errorstate/errorstate.pro new file mode 100644 index 0000000..d937b02 --- /dev/null +++ b/examples/statemachine/errorstate/errorstate.pro @@ -0,0 +1,13 @@ +###################################################################### +# Automatically generated by qmake (2.01a) on 22. apr 14:11:33 2009 +###################################################################### + +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += C:/dev/kinetic/examples/statemachine/errorstate/. . + +# Input +HEADERS += mainwindow.h plugin.h tank.h tankitem.h +SOURCES += main.cpp mainwindow.cpp tankitem.cpp +CONFIG += console diff --git a/examples/statemachine/errorstate/main.cpp b/examples/statemachine/errorstate/main.cpp new file mode 100644 index 0000000..26fc1bb --- /dev/null +++ b/examples/statemachine/errorstate/main.cpp @@ -0,0 +1,12 @@ +#include +#include "mainwindow.h" + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + MainWindow mainWindow; + mainWindow.show(); + + return app.exec(); +} diff --git a/examples/statemachine/errorstate/mainwindow.cpp b/examples/statemachine/errorstate/mainwindow.cpp new file mode 100644 index 0000000..598756f --- /dev/null +++ b/examples/statemachine/errorstate/mainwindow.cpp @@ -0,0 +1,184 @@ +#include "mainwindow.h" +#include "tankitem.h" +#include "plugin.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) +{ + init(); +} + +MainWindow::~MainWindow() +{ +} + +void MainWindow::addWall(const QRectF &wall) +{ + QGraphicsRectItem *item = new QGraphicsRectItem; + item->setRect(wall); + item->setBrush(Qt::darkGreen); + item->setPen(QPen(Qt::black, 0)); + + m_scene->addItem(item); +} + +void MainWindow::init() +{ + setWindowTitle("Pluggable Tank Game"); + + QGraphicsView *view = new QGraphicsView(this); + setCentralWidget(view); + + m_scene = new QGraphicsScene(this); + view->setScene(m_scene); + + QRectF sceneRect = QRectF(-200.0, -200.0, 400.0, 400.0); + m_scene->setSceneRect(sceneRect); + + { + TankItem *item = new TankItem(this); + + item->setPos(m_scene->sceneRect().topLeft() + QPointF(15.0, 15.0)); + item->setDirection(45.0); + item->setColor(Qt::red); + + m_spawns.append(item); + } + + { + TankItem *item = new TankItem(this); + + item->setPos(m_scene->sceneRect().topRight() + QPointF(-15.0, 15.0)); + item->setDirection(135.0); + item->setColor(Qt::green); + + m_spawns.append(item); + } + + { + TankItem *item = new TankItem(this); + + item->setPos(m_scene->sceneRect().bottomRight() + QPointF(-15.0, -15.0)); + item->setDirection(225.0); + item->setColor(Qt::blue); + + m_spawns.append(item); + } + + { + TankItem *item = new TankItem(this); + + item->setPos(m_scene->sceneRect().bottomLeft() + QPointF(15.0, -15.0)); + item->setDirection(315.0); + item->setColor(Qt::yellow); + + m_spawns.append(item); + } + + QPointF centerOfMap = sceneRect.center(); + addWall(QRectF(centerOfMap + QPointF(-50.0, -60.0), centerOfMap + QPointF(50.0, -50.0))); + addWall(QRectF(centerOfMap - QPointF(-50.0, -60.0), centerOfMap - QPointF(50.0, -50.0))); + addWall(QRectF(centerOfMap + QPointF(-50.0, -50.0), centerOfMap + QPointF(-40.0, 50.0))); + addWall(QRectF(centerOfMap - QPointF(-50.0, -50.0), centerOfMap - QPointF(-40.0, 50.0))); + + addWall(QRectF(sceneRect.topLeft() + QPointF(sceneRect.width() / 2.0 - 5.0, 0.0), + sceneRect.topLeft() + QPointF(sceneRect.width() / 2.0 + 5.0, 100.0))); + addWall(QRectF(sceneRect.bottomLeft() + QPointF(sceneRect.width() / 2.0 - 5.0, 0.0), + sceneRect.bottomLeft() + QPointF(sceneRect.width() / 2.0 + 5.0, -100.0))); + addWall(QRectF(sceneRect.topLeft() + QPointF(0.0, sceneRect.height() / 2.0 - 5.0), + sceneRect.topLeft() + QPointF(100.0, sceneRect.height() / 2.0 + 5.0))); + addWall(QRectF(sceneRect.topRight() + QPointF(0.0, sceneRect.height() / 2.0 - 5.0), + sceneRect.topRight() + QPointF(-100.0, sceneRect.height() / 2.0 + 5.0))); + + + QAction *addTankAction = menuBar()->addAction("&Add tank"); + QAction *runGameAction = menuBar()->addAction("&Run game"); + QAction *stopGameAction = menuBar()->addAction("&Stop game"); + menuBar()->addSeparator(); + QAction *quitAction = menuBar()->addAction("&Quit"); + + connect(addTankAction, SIGNAL(triggered()), this, SLOT(addTank())); + connect(stopGameAction, SIGNAL(triggered()), this, SIGNAL(gameOver())); + connect(quitAction, SIGNAL(triggered()), this, SLOT(close())); + + m_machine = new QStateMachine(this); + m_machine->setGlobalRestorePolicy(QStateMachine::RestoreProperties); + + QState *stoppedState = new QState(m_machine->rootState()); + + stoppedState->assignProperty(runGameAction, "enabled", true); + stoppedState->assignProperty(stopGameAction, "enabled", false); + m_machine->setInitialState(stoppedState); + + QState *spawnsAvailable = new QState(stoppedState); + spawnsAvailable->assignProperty(addTankAction, "enabled", true); + + QState *noSpawnsAvailable = new QState(stoppedState); + noSpawnsAvailable->assignProperty(addTankAction, "enabled", false); + + spawnsAvailable->addTransition(this, SIGNAL(mapFull()), noSpawnsAvailable); + + QHistoryState *hs = stoppedState->addHistoryState(); + hs->setDefaultState(spawnsAvailable); + stoppedState->setInitialState(spawnsAvailable); + + m_runningState = new QState(QState::ParallelGroup, m_machine->rootState()); + m_runningState->assignProperty(addTankAction, "enabled", false); + m_runningState->assignProperty(runGameAction, "enabled", false); + m_runningState->assignProperty(stopGameAction, "enabled", true); + + stoppedState->addTransition(runGameAction, SIGNAL(triggered()), m_runningState); + m_runningState->addTransition(this, SIGNAL(gameOver()), stoppedState); + + m_machine->start(); + + QTimer *timer = new QTimer(this); + timer->setInterval(100); + connect(timer, SIGNAL(timeout()), this, SLOT(runStep())); + connect(m_runningState, SIGNAL(entered()), timer, SLOT(start())); + connect(m_runningState, SIGNAL(exited()), timer, SLOT(stop())); + + m_time.start(); +} + +void MainWindow::runStep() +{ + int elapsed = m_time.elapsed(); + if (elapsed > 0) { + m_time.restart(); + qreal elapsedSecs = elapsed / 1000.0; + QList tankItems = qFindChildren(this); + foreach (TankItem *tankItem, tankItems) + tankItem->idle(elapsedSecs); + } +} + +void MainWindow::addTank() +{ + Q_ASSERT(!m_spawns.isEmpty()); + + QString fileName = QFileDialog::getOpenFileName(this, "Select plugin file", + "plugins/", "*.dll"); + QPluginLoader loader(fileName); + + Plugin *plugin = qobject_cast(loader.instance()); + if (plugin != 0) { + TankItem *tankItem = m_spawns.takeLast(); + m_scene->addItem(tankItem); + if (m_spawns.isEmpty()) + emit mapFull(); + + plugin->create(m_runningState, tankItem); + } +} + diff --git a/examples/statemachine/errorstate/mainwindow.h b/examples/statemachine/errorstate/mainwindow.h new file mode 100644 index 0000000..2bd574d --- /dev/null +++ b/examples/statemachine/errorstate/mainwindow.h @@ -0,0 +1,41 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include + +class QGraphicsScene; +class QStateMachine; +class QState; +class TankItem; +class MainWindow: public QMainWindow +{ + Q_OBJECT +public: + MainWindow(QWidget *parent = 0); + ~MainWindow(); + +public slots: + void addTank(); + void runStep(); + +signals: + void gameOver(); + void mapFull(); + +private: + void init(); + void addWall(const QRectF &wall); + + QGraphicsScene *m_scene; + + QStateMachine *m_machine; + QState *m_runningState; + + QList m_spawns; + QTime m_time; + +}; + +#endif + diff --git a/examples/statemachine/errorstate/plugin.h b/examples/statemachine/errorstate/plugin.h new file mode 100644 index 0000000..1ac7e0f --- /dev/null +++ b/examples/statemachine/errorstate/plugin.h @@ -0,0 +1,16 @@ +#ifndef PLUGIN_H +#define PLUGIN_H + +class QState; +class Tank; +class Plugin +{ +public: + virtual ~Plugin() {} + + virtual QState *create(QState *parentState, Tank *tank) = 0; +}; + +Q_DECLARE_INTERFACE(Plugin, "TankPlugin") + +#endif diff --git a/examples/statemachine/errorstate/tank.h b/examples/statemachine/errorstate/tank.h new file mode 100644 index 0000000..9def6df --- /dev/null +++ b/examples/statemachine/errorstate/tank.h @@ -0,0 +1,31 @@ +#ifndef TANK_H +#define TANK_H + +#include +#include + +class Tank: public QObject +{ + Q_OBJECT + Q_PROPERTY(qreal direction READ direction) + Q_PROPERTY(qreal distanceToObstacle READ distanceToObstacle) +public: + Tank(QObject *parent = 0) : QObject(parent) {} + + virtual qreal direction() const = 0; + virtual qreal distanceToObstacle() const = 0; + +signals: + void collision(const QLineF &collidedLine) const; + void actionCompleted(); + void tankSpotted(qreal otherTankDirection, qreal distance); + +public slots: + virtual void moveForwards(qreal length) = 0; + virtual void moveBackwards(qreal length) = 0; + virtual void turn(qreal newDirection) = 0; + virtual void stop() = 0; + virtual void fireCannon(qreal distance) = 0; +}; + +#endif diff --git a/examples/statemachine/errorstate/tankitem.cpp b/examples/statemachine/errorstate/tankitem.cpp new file mode 100644 index 0000000..21d4a25 --- /dev/null +++ b/examples/statemachine/errorstate/tankitem.cpp @@ -0,0 +1,274 @@ +#include "tankitem.h" + +#include +#include + +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +class Action +{ +public: + Action(TankItem *item) : m_item(item) + { + } + + TankItem *item() const { return m_item; } + void setItem(TankItem *item) { m_item = item; } + + virtual bool apply(qreal timeDelta) = 0; + +private: + TankItem *m_item; +}; + +class MoveAction: public Action +{ +public: + MoveAction(TankItem *item, qreal distance) + : Action(item), m_distance(distance) + { + } + + bool apply(qreal timeDelta) + { + qreal dist = timeDelta * item()->speed(); + m_distance -= dist; + if (qFuzzyCompare(m_distance, 0.0)) + return false; + + qreal a = item()->direction() * M_PI / 180.0; + + qreal yd = dist * sin(a); + qreal xd = dist * sin(M_PI / 2.0 - a); + + item()->setPos(item()->pos() + QPointF(xd, yd)); + return true; + } + +private: + qreal m_distance; +}; + +class TurnAction: public Action +{ +public: + TurnAction(TankItem *item, qreal distance) + : Action(item), m_distance(distance) + { + } + + bool apply(qreal timeDelta) + { + qreal dist = timeDelta * item()->angularSpeed(); + m_distance -= dist; + if (qFuzzyCompare(m_distance, 0.0)) + return false; + + item()->setDirection(item()->direction() + dist); + return true; + } + +private: + qreal m_distance; +}; + +class FireCannonAction: public Action +{ +public: + FireCannonAction(TankItem *item, qreal distance) + : Action(item), m_distance(distance) + { + } + + bool apply(qreal ) + { + return false; + } + +private: + qreal m_distance; +}; + +TankItem::TankItem(QObject *parent) : Tank(parent), m_currentAction(0), m_currentDirection(0.0) +{ +} + +void TankItem::idle(qreal elapsed) +{ + if (m_currentAction != 0) { + if (!m_currentAction->apply(elapsed)) { + setAction(0); + emit actionCompleted(); + } + } +} + +void TankItem::setAction(Action *newAction) +{ + if (m_currentAction != 0) + delete m_currentAction; + + m_currentAction = newAction; +} + +void TankItem::moveForwards(qreal length) +{ + setAction(new MoveAction(this, length)); +} + +void TankItem::moveBackwards(qreal length) +{ + setAction(new MoveAction(this, -length)); +} + +void TankItem::turn(qreal newDirection) +{ + setAction(new TurnAction(this, m_currentDirection - newDirection)); +} + +void TankItem::stop() +{ + setAction(0); +} + +void TankItem::fireCannon(qreal distance) +{ + setAction(new FireCannonAction(this, distance)); +} + +QPointF TankItem::tryMove(const QPointF &requestedPosition) const +{ + QLineF movementPath(pos(), requestedPosition); + + qreal cannonLength = 0.0; + { + QPointF p1 = boundingRect().center(); + QPointF p2 = QPointF(boundingRect().right() + 10.0, p1.y()); + + cannonLength = QLineF(mapToScene(p1), mapToScene(p2)).length(); + } + + movementPath.setLength(movementPath.length() + cannonLength); + + QRectF boundingRectPath(QPointF(qMin(movementPath.x1(), movementPath.x2()), qMin(movementPath.y1(), movementPath.y2())), + QPointF(qMax(movementPath.x1(), movementPath.x2()), qMax(movementPath.y1(), movementPath.y2()))); + + m_brp = mapFromScene(boundingRectPath); + + QList itemsInRect = scene()->items(boundingRectPath, Qt::IntersectsItemBoundingRect); + + QPointF nextPoint = requestedPosition; + QRectF sceneRect = scene()->sceneRect(); + + QLineF collidedLine; + foreach (QGraphicsItem *item, itemsInRect) { + if (item == static_cast(this)) + continue; + + QPolygonF mappedBoundingRect = item->mapToScene(item->boundingRect()); + for (int i=0; i sceneRect.right()) + nextPoint.rx() = sceneRect.right(); + if (nextPoint.y() < sceneRect.top()) + nextPoint.ry() = sceneRect.top(); + if (nextPoint.y() > sceneRect.bottom()) + nextPoint.ry() = sceneRect.bottom(); + + if (nextPoint != requestedPosition) { + emit collision(collidedLine); + } + + return nextPoint; +} + +QVariant TankItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) +{ + if (change == ItemPositionChange && scene()) + return tryMove(value.toPointF()); + else + return QGraphicsItem::itemChange(change, value); +} + + +void TankItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + QRectF brect = boundingRect(); + + painter->setBrush(m_color); + painter->setPen(Qt::black); + + // body + painter->drawRect(brect.adjusted(0.0, 4.0, -2.0, -4.0)); + + // cannon + QRectF cannonBase = brect.adjusted(10.0, 6.0, -12.0, -6.0); + painter->drawEllipse(cannonBase); + + painter->drawRect(QRectF(QPointF(cannonBase.center().x(), cannonBase.center().y() - 2.0), + QPointF(brect.right(), cannonBase.center().y() + 2.0))); + + // left track + painter->setBrush(QBrush(Qt::black, Qt::VerPattern)); + QRectF leftTrackRect = QRectF(brect.topLeft(), QPointF(brect.right() - 2.0, brect.top() + 4.0)); + painter->fillRect(leftTrackRect, Qt::darkYellow); + painter->drawRect(leftTrackRect); + + // right track + QRectF rightTrackRect = QRectF(QPointF(brect.left(), brect.bottom() - 4.0), + QPointF(brect.right() - 2.0, brect.bottom())); + painter->fillRect(rightTrackRect, Qt::darkYellow); + painter->drawRect(rightTrackRect); + + painter->setBrush(QColor::fromRgb(255, 0, 0, 128)); + painter->drawPolygon(m_brp); + +} + +QRectF TankItem::boundingRect() const +{ + return QRectF(-20.0, -10.0, 40.0, 20.0); +} + +qreal TankItem::direction() const +{ + return m_currentDirection; +} + +void TankItem::setDirection(qreal newDirection) +{ + m_currentDirection = newDirection; + rotate(newDirection); +} + +qreal TankItem::distanceToObstacle() const +{ + // ### + + return 0.0; +} + + + diff --git a/examples/statemachine/errorstate/tankitem.h b/examples/statemachine/errorstate/tankitem.h new file mode 100644 index 0000000..df13689 --- /dev/null +++ b/examples/statemachine/errorstate/tankitem.h @@ -0,0 +1,48 @@ +#ifndef TANKITEM_H +#define TANKITEM_H + +#include "tank.h" + +#include +#include + +class Action; +class TankItem: public Tank, public QGraphicsItem +{ + Q_OBJECT +public: + TankItem(QObject *parent = 0); + + virtual void moveForwards(qreal length); + virtual void moveBackwards(qreal length); + virtual void turn(qreal newDirection); + virtual void stop(); + virtual void fireCannon(qreal distance); + virtual qreal direction() const; + virtual qreal distanceToObstacle() const; + + void setColor(const QColor &color) { m_color = color; } + QColor color() const { return m_color; } + + void idle(qreal elapsed); + void setDirection(qreal newDirection); + + qreal speed() const { return 20.0; } + qreal angularSpeed() const { return 1.0; } + +protected: + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + QRectF boundingRect() const; + QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value); + +private: + QPointF tryMove(const QPointF &requestedPosition) const; + void setAction(Action *newAction); + + Action *m_currentAction; + qreal m_currentDirection; + QColor m_color; + mutable QPolygonF m_brp; +}; + +#endif -- cgit v0.12 From af4f0170810efeb071e6e9dac0df6a84962e9806 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 24 Apr 2009 17:36:48 +0200 Subject: Really broken plugin for errorState. Don't try to use this yet, it doesn't work at all. --- .../errorstateplugins/random_ai/random_ai.pro | 13 +++++ .../random_ai/random_ai_plugin.cpp | 40 ++++++++++++++ .../errorstateplugins/random_ai/random_ai_plugin.h | 62 ++++++++++++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 examples/statemachine/errorstateplugins/random_ai/random_ai.pro create mode 100644 examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.cpp create mode 100644 examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.h diff --git a/examples/statemachine/errorstateplugins/random_ai/random_ai.pro b/examples/statemachine/errorstateplugins/random_ai/random_ai.pro new file mode 100644 index 0000000..f290250 --- /dev/null +++ b/examples/statemachine/errorstateplugins/random_ai/random_ai.pro @@ -0,0 +1,13 @@ +TEMPLATE = lib +CONFIG += plugin +INCLUDEPATH += ../.. +HEADERS = random_ai_plugin.h +SOURCES = random_ai_plugin.cpp +TARGET = $$qtLibraryTarget(random_ai) +DESTDIR = ../../errorstate/plugins + +#! [0] +# install +target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstate/plugins +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS random_ai.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstateplugins/random_ai \ No newline at end of file diff --git a/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.cpp b/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.cpp new file mode 100644 index 0000000..429e3ca --- /dev/null +++ b/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.cpp @@ -0,0 +1,40 @@ +#include "random_ai_plugin.h" + +#include + +#include +#include + +#include + +QState *RandomAiPlugin::create(QState *parentState, Tank *tank) +{ + qsrand(uint(time(NULL))); + + QState *topLevel = new QState(parentState); + + QState *selectNextActionState = new SelectActionState(topLevel); + topLevel->setInitialState(selectNextActionState); + + QState *fireState = new RandomDistanceState(topLevel); + connect(fireState, SIGNAL(distanceComputed(qreal)), tank, SLOT(fireCannon(qreal))); + selectNextActionState->addTransition(selectNextActionState, SIGNAL(fireSelected()), fireState); + + QState *moveForwardsState = new RandomDistanceState(topLevel); + connect(moveForwardsState, SIGNAL(distanceComputed(qreal)), tank, SLOT(moveForwards(qreal))); + selectNextActionState->addTransition(selectNextActionState, SIGNAL(moveForwardsSelected()), moveForwardsState); + + QState *moveBackwardsState = new RandomDistanceState(topLevel); + connect(moveBackwardsState, SIGNAL(distanceComputed(qreal)), tank, SLOT(moveBackwards(qreal))); + selectNextActionState->addTransition(selectNextActionState, SIGNAL(moveBackwardsSelected()), moveBackwardsState); + + QState *turnState = new RandomDistanceState(topLevel); + connect(turnState, SIGNAL(distanceComputed(qreal)), tank, SLOT(turn(qreal))); + selectNextActionState->addTransition(selectNextActionState, SIGNAL(turnSelected()), turnState); + + topLevel->addTransition(tank, SIGNAL(actionCompleted()), selectNextActionState); + + return topLevel; +} + +Q_EXPORT_PLUGIN2(random_ai, RandomAiPlugin) diff --git a/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.h b/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.h new file mode 100644 index 0000000..27c9b92 --- /dev/null +++ b/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.h @@ -0,0 +1,62 @@ +#ifndef RANDOM_AI_PLUGIN_H +#define RANDOM_AI_PLUGIN_H + +#include +#include + +#include + +class SelectActionState: public QState +{ + Q_OBJECT +public: + SelectActionState(QState *parent = 0) : QState(parent) + { + } + +signals: + void fireSelected(); + void moveForwardsSelected(); + void moveBackwardsSelected(); + void turnSelected(); + +protected: + void onEntry() + { + int rand = qrand() % 4; + switch (rand) { + case 0: emit fireSelected(); break; + case 1: emit moveForwardsSelected(); break; + case 2: emit moveBackwardsSelected(); break; + case 3: emit turnSelected(); break; + }; + } +}; + +class RandomDistanceState: public QState +{ + Q_OBJECT +public: + RandomDistanceState(QState *parent = 0) : QState(parent) + { + } + +signals: + void distanceComputed(qreal distance); + +protected: + void onEntry() + { + emit distanceComputed(qreal(qrand() % 10)); + } +}; + +class RandomAiPlugin: public QObject, public Plugin +{ + Q_OBJECT + Q_INTERFACES(Plugin) +public: + virtual QState *create(QState *parentState, Tank *tank); +}; + +#endif // RANDOM_AI_PLUGIN_H -- cgit v0.12 From 6f955aedcdb6c2b1de04d1cd7e959e284581b3b3 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Mon, 27 Apr 2009 16:41:25 +0200 Subject: Build fix for mingw --- examples/animation/sub-attaq/animationmanager.cpp | 2 +- examples/animation/sub-attaq/animationmanager.h | 2 +- examples/animation/sub-attaq/boat.cpp | 12 +++++------ examples/animation/sub-attaq/boat.h | 6 ++---- examples/animation/sub-attaq/graphicsscene.cpp | 26 +++++++++++------------ examples/animation/sub-attaq/graphicsscene.h | 6 +++--- examples/animation/sub-attaq/mainwindow.cpp | 2 +- examples/animation/sub-attaq/mainwindow.h | 2 +- examples/animation/sub-attaq/pixmapitem.cpp | 2 +- examples/animation/sub-attaq/pixmapitem.h | 2 +- examples/animation/sub-attaq/progressitem.h | 2 +- examples/animation/sub-attaq/states.cpp | 6 +++--- examples/animation/sub-attaq/states.h | 10 ++++----- examples/animation/sub-attaq/submarine.cpp | 8 +++---- examples/animation/sub-attaq/submarine.h | 4 ++-- examples/animation/sub-attaq/submarine_p.h | 4 ++-- examples/animation/sub-attaq/torpedo.cpp | 6 +++--- examples/animation/sub-attaq/torpedo.h | 4 ++-- 18 files changed, 52 insertions(+), 54 deletions(-) diff --git a/examples/animation/sub-attaq/animationmanager.cpp b/examples/animation/sub-attaq/animationmanager.cpp index 9f99426..5b9282a 100644 --- a/examples/animation/sub-attaq/animationmanager.cpp +++ b/examples/animation/sub-attaq/animationmanager.cpp @@ -48,7 +48,7 @@ #else # include #endif -#include +#include // the universe's only animation manager AnimationManager *AnimationManager::instance = 0; diff --git a/examples/animation/sub-attaq/animationmanager.h b/examples/animation/sub-attaq/animationmanager.h index fe92680..69ec3d7 100644 --- a/examples/animation/sub-attaq/animationmanager.h +++ b/examples/animation/sub-attaq/animationmanager.h @@ -42,7 +42,7 @@ #ifndef ANIMATIONMANAGER_H #define ANIMATIONMANAGER_H -#include +#include class QAbstractAnimation; diff --git a/examples/animation/sub-attaq/boat.cpp b/examples/animation/sub-attaq/boat.cpp index 5b270c0..b1995dd 100644 --- a/examples/animation/sub-attaq/boat.cpp +++ b/examples/animation/sub-attaq/boat.cpp @@ -59,12 +59,12 @@ # include "qpauseanimation.h" #include "qsequentialanimationgroup.h" #else -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #endif static QAbstractAnimation *setupDestroyAnimation(Boat *boat) diff --git a/examples/animation/sub-attaq/boat.h b/examples/animation/sub-attaq/boat.h index 44de367..b28cf20 100644 --- a/examples/animation/sub-attaq/boat.h +++ b/examples/animation/sub-attaq/boat.h @@ -43,10 +43,8 @@ #define __BOAT__H__ //Qt -#include -#include - -#include +#include +#include #if defined(QT_EXPERIMENTAL_SOLUTION) # include "qtgraphicswidget.h" diff --git a/examples/animation/sub-attaq/graphicsscene.cpp b/examples/animation/sub-attaq/graphicsscene.cpp index a66925c..2a6f83c 100644 --- a/examples/animation/sub-attaq/graphicsscene.cpp +++ b/examples/animation/sub-attaq/graphicsscene.cpp @@ -61,20 +61,20 @@ #include "qfinalstate.h" #include "qpauseanimation.h" #else -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #endif -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include //helper function that creates an animation for position and inserts it into group static CustomPropertyAnimation *addGraphicsItemPosAnimation(QSequentialAnimationGroup *group, diff --git a/examples/animation/sub-attaq/graphicsscene.h b/examples/animation/sub-attaq/graphicsscene.h index bc9734c..0840564 100644 --- a/examples/animation/sub-attaq/graphicsscene.h +++ b/examples/animation/sub-attaq/graphicsscene.h @@ -43,13 +43,13 @@ #define __GRAPHICSSCENE__H__ //Qt -#include -#include +#include +#include #if defined(QT_EXPERIMENTAL_SOLUTION) # include "qstate.h" #else -# include +# include #endif diff --git a/examples/animation/sub-attaq/mainwindow.cpp b/examples/animation/sub-attaq/mainwindow.cpp index c25b9ef..a166241 100644 --- a/examples/animation/sub-attaq/mainwindow.cpp +++ b/examples/animation/sub-attaq/mainwindow.cpp @@ -47,7 +47,7 @@ #include #endif //Qt -#include +#include MainWindow::MainWindow() : QMainWindow(0) { diff --git a/examples/animation/sub-attaq/mainwindow.h b/examples/animation/sub-attaq/mainwindow.h index 6289b3f..72d1324 100644 --- a/examples/animation/sub-attaq/mainwindow.h +++ b/examples/animation/sub-attaq/mainwindow.h @@ -43,7 +43,7 @@ #define __MAINWINDOW__H__ //Qt -#include +#include class GraphicsScene; class QGraphicsView; diff --git a/examples/animation/sub-attaq/pixmapitem.cpp b/examples/animation/sub-attaq/pixmapitem.cpp index aa8b552..22a363f 100644 --- a/examples/animation/sub-attaq/pixmapitem.cpp +++ b/examples/animation/sub-attaq/pixmapitem.cpp @@ -43,7 +43,7 @@ #include "pixmapitem.h" //Qt -#include +#include PixmapItem::PixmapItem(const QString &fileName,GraphicsScene::Mode mode, QGraphicsItem * parent) : QGraphicsPixmapItem(parent),name(fileName) { diff --git a/examples/animation/sub-attaq/pixmapitem.h b/examples/animation/sub-attaq/pixmapitem.h index f3c1a41..31022c1 100644 --- a/examples/animation/sub-attaq/pixmapitem.h +++ b/examples/animation/sub-attaq/pixmapitem.h @@ -46,7 +46,7 @@ #include "graphicsscene.h" //Qt -#include +#include class PixmapItem : public QGraphicsPixmapItem { diff --git a/examples/animation/sub-attaq/progressitem.h b/examples/animation/sub-attaq/progressitem.h index 006cc6d..7b8db4d 100644 --- a/examples/animation/sub-attaq/progressitem.h +++ b/examples/animation/sub-attaq/progressitem.h @@ -43,7 +43,7 @@ #define PROGRESSITEM_H //Qt -#include +#include class ProgressItem : public QGraphicsTextItem { diff --git a/examples/animation/sub-attaq/states.cpp b/examples/animation/sub-attaq/states.cpp index 5dce445..1036fdf 100644 --- a/examples/animation/sub-attaq/states.cpp +++ b/examples/animation/sub-attaq/states.cpp @@ -49,8 +49,8 @@ #include "progressitem.h" //Qt -#include -#include +#include +#include #if defined(QT_EXPERIMENTAL_SOLUTION) #include "qstatemachine.h" #include "qkeyeventtransition.h" @@ -60,7 +60,7 @@ #include #include #include -#include +#include #endif PlayState::PlayState(GraphicsScene *scene, QState *parent) diff --git a/examples/animation/sub-attaq/states.h b/examples/animation/sub-attaq/states.h index 8dbdf86..ec69ae7 100644 --- a/examples/animation/sub-attaq/states.h +++ b/examples/animation/sub-attaq/states.h @@ -49,12 +49,12 @@ #include "qpropertyanimation.h" #include "qkeyeventtransition.h" #else -#include -#include -#include -# include +#include +#include +#include +# include #endif -#include +#include class GraphicsScene; class Boat; diff --git a/examples/animation/sub-attaq/submarine.cpp b/examples/animation/sub-attaq/submarine.cpp index b8a476e..0f03efc 100644 --- a/examples/animation/sub-attaq/submarine.cpp +++ b/examples/animation/sub-attaq/submarine.cpp @@ -56,10 +56,10 @@ # include "qsequentialanimationgroup.h" # include "qpauseanimation.h" #else -#include -#include -#include -#include +#include +#include +#include +#include #endif static QAbstractAnimation *setupDestroyAnimation(SubMarine *sub) diff --git a/examples/animation/sub-attaq/submarine.h b/examples/animation/sub-attaq/submarine.h index 562b4cf..7ee587d 100644 --- a/examples/animation/sub-attaq/submarine.h +++ b/examples/animation/sub-attaq/submarine.h @@ -47,8 +47,8 @@ #include "qvariantanimation.h" #include "qgraphicswidget.h" #else -#include -#include +#include +#include #endif class PixmapItem; diff --git a/examples/animation/sub-attaq/submarine_p.h b/examples/animation/sub-attaq/submarine_p.h index 354a406..918e7f5 100644 --- a/examples/animation/sub-attaq/submarine_p.h +++ b/examples/animation/sub-attaq/submarine_p.h @@ -51,9 +51,9 @@ #if defined(QT_EXPERIMENTAL_SOLUTION) #include "qpropertyanimation.h" #else -#include +#include #endif -#include +#include //This state is describing when the boat is moving right class MovementState : public QAnimationState diff --git a/examples/animation/sub-attaq/torpedo.cpp b/examples/animation/sub-attaq/torpedo.cpp index b24948d..88f1112 100644 --- a/examples/animation/sub-attaq/torpedo.cpp +++ b/examples/animation/sub-attaq/torpedo.cpp @@ -52,9 +52,9 @@ #include "qstatemachine.h" #include "qfinalstate.h" #else -#include -#include -#include +#include +#include +#include #endif Torpedo::Torpedo(QGraphicsItem * parent, Qt::WindowFlags wFlags) diff --git a/examples/animation/sub-attaq/torpedo.h b/examples/animation/sub-attaq/torpedo.h index 33bbc04..2e44e41 100644 --- a/examples/animation/sub-attaq/torpedo.h +++ b/examples/animation/sub-attaq/torpedo.h @@ -43,13 +43,13 @@ #define __TORPEDO__H__ //Qt -#include +#include #if defined(QT_EXPERIMENTAL_SOLUTION) # include "qvariantanimation.h" # include "qgraphicswidget.h" #else -# include +# include # include #endif -- cgit v0.12 From 53e8c64d0ed050bc195bb4851da2f6d65b5c8ca5 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Mon, 27 Apr 2009 17:38:01 +0200 Subject: make the entry/exit order well-defined for all combinations of states Comparing pointers meant that the order could be different each run. Now the entry/exit order will be consistent, even for states that are in disjoint parts of the hierarchy. --- src/corelib/statemachine/qstatemachine.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 2d3eea1..8cee1fc 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -234,6 +234,18 @@ Q_CORE_EXPORT const QStateMachinePrivate::Handler *qcoreStateMachineHandler() return &qt_kernel_statemachine_handler; } +static int indexOfDescendant(QState *s, QAbstractState *desc) +{ + QList childStates = QStatePrivate::get(s)->childStates(); + for (int i = 0; i < childStates.size(); ++i) { + QAbstractState *c = childStates.at(i); + if ((c == desc) || QStateMachinePrivate::isDescendantOf(desc, c)) { + return i; + } + } + return -1; +} + bool QStateMachinePrivate::stateEntryLessThan(QAbstractState *s1, QAbstractState *s2) { if (s1->parent() == s2->parent()) { @@ -244,8 +256,9 @@ bool QStateMachinePrivate::stateEntryLessThan(QAbstractState *s1, QAbstractState } else if (isDescendantOf(s2, s1)) { return true; } else { - // ### fixme - return s1 < s2; + QState *lca = findLCA(QList() << s1 << s2); + Q_ASSERT(lca != 0); + return (indexOfDescendant(lca, s1) < indexOfDescendant(lca, s2)); } } @@ -259,8 +272,9 @@ bool QStateMachinePrivate::stateExitLessThan(QAbstractState *s1, QAbstractState } else if (isDescendantOf(s2, s1)) { return false; } else { - // ### fixme - return s2 < s1; + QState *lca = findLCA(QList() << s1 << s2); + Q_ASSERT(lca != 0); + return (indexOfDescendant(lca, s1) < indexOfDescendant(lca, s2)); } } -- cgit v0.12 From a460bee2b3051bf6a5176b5c620f81ff962a7f53 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Mon, 27 Apr 2009 18:07:03 +0200 Subject: replace QStateFinished{Event,Transition} by QState::finished() signal Not worth it having two public classes when the same can be achieved by having a signal. --- src/corelib/statemachine/qfinalstate.cpp | 2 - src/corelib/statemachine/qstate.cpp | 30 ++-- src/corelib/statemachine/qstate.h | 5 +- src/corelib/statemachine/qstate_p.h | 2 + src/corelib/statemachine/qstatefinishedevent.h | 70 -------- .../statemachine/qstatefinishedtransition.cpp | 182 --------------------- .../statemachine/qstatefinishedtransition.h | 88 ---------- src/corelib/statemachine/qstatemachine.cpp | 60 +------ src/corelib/statemachine/statemachine.pri | 3 - tests/auto/qstatemachine/tst_qstatemachine.cpp | 4 +- 10 files changed, 23 insertions(+), 423 deletions(-) delete mode 100644 src/corelib/statemachine/qstatefinishedevent.h delete mode 100644 src/corelib/statemachine/qstatefinishedtransition.cpp delete mode 100644 src/corelib/statemachine/qstatefinishedtransition.h diff --git a/src/corelib/statemachine/qfinalstate.cpp b/src/corelib/statemachine/qfinalstate.cpp index 16e080e..6a1b608 100644 --- a/src/corelib/statemachine/qfinalstate.cpp +++ b/src/corelib/statemachine/qfinalstate.cpp @@ -76,8 +76,6 @@ QT_BEGIN_NAMESPACE machine.setInitialState(s1); machine.start(); \endcode - - \sa QStateFinishedTransition */ class QFinalStatePrivate : public QAbstractStatePrivate diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp index 56a855e..9bda250 100644 --- a/src/corelib/statemachine/qstate.cpp +++ b/src/corelib/statemachine/qstate.cpp @@ -46,7 +46,6 @@ #include "qabstracttransition.h" #include "qabstracttransition_p.h" #include "qsignaltransition.h" -#include "qstatefinishedtransition.h" #include "qstatemachine.h" #include "qstatemachine_p.h" @@ -75,9 +74,6 @@ QT_BEGIN_NAMESPACE The addHistoryState() function adds a history state. - The addFinishedTransition() function creates and adds a transition that's - triggered when a final child state is entered. - The setErrorState() sets the state's error state. The error state is the state that the state machine will transition to if an error is detected when attempting to enter the state (e.g. because no initial state has been set). @@ -134,6 +130,12 @@ const QStatePrivate *QStatePrivate::get(const QState *q) return q->d_func(); } +void QStatePrivate::emitFinished() +{ + Q_Q(QState); + emit q->finished(); +} + /*! Constructs a new state with the given \a parent state. */ @@ -294,20 +296,6 @@ QSignalTransition *QState::addTransition(QObject *sender, const char *signal, return trans; } -/*! - Adds a transition that's triggered by the finished event of this state, and - returns the new QStateFinishedTransition object. The transition has the - given \a target state. - - \sa QStateFinishedEvent -*/ -QStateFinishedTransition *QState::addFinishedTransition(QAbstractState *target) -{ - QStateFinishedTransition *trans = new QStateFinishedTransition(this, QList() << target); - addTransition(trans); - return trans; -} - namespace { // ### Make public? @@ -431,4 +419,10 @@ bool QState::event(QEvent *e) return QAbstractState::event(e); } +/*! + \fn QState::finished() + + This signal is emitted when a final child state of this state is entered. +*/ + QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qstate.h b/src/corelib/statemachine/qstate.h index 7c64c80..70211c1 100644 --- a/src/corelib/statemachine/qstate.h +++ b/src/corelib/statemachine/qstate.h @@ -57,7 +57,6 @@ QT_MODULE(Core) class QAbstractTransition; class QHistoryState; class QSignalTransition; -class QStateFinishedTransition; class QStatePrivate; class Q_CORE_EXPORT QState : public QAbstractState @@ -84,7 +83,6 @@ public: QAbstractTransition *addTransition(QAbstractTransition *transition); QSignalTransition *addTransition(QObject *sender, const char *signal, QAbstractState *target); QAbstractTransition *addTransition(QAbstractState *target); - QStateFinishedTransition *addFinishedTransition(QAbstractState *target); void removeTransition(QAbstractTransition *transition); QList transitions() const; @@ -93,6 +91,9 @@ public: QAbstractState *initialState() const; void setInitialState(QAbstractState *state); +Q_SIGNALS: + void finished(); + protected: void onEntry(); void onExit(); diff --git a/src/corelib/statemachine/qstate_p.h b/src/corelib/statemachine/qstate_p.h index 8d040d0..2df6823 100644 --- a/src/corelib/statemachine/qstate_p.h +++ b/src/corelib/statemachine/qstate_p.h @@ -74,6 +74,8 @@ public: QList historyStates() const; QList transitions() const; + void emitFinished(); + QAbstractState *errorState; bool isParallelGroup; QAbstractState *initialState; diff --git a/src/corelib/statemachine/qstatefinishedevent.h b/src/corelib/statemachine/qstatefinishedevent.h deleted file mode 100644 index c2f81f7..0000000 --- a/src/corelib/statemachine/qstatefinishedevent.h +++ /dev/null @@ -1,70 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSTATEFINISHEDEVENT_H -#define QSTATEFINISHEDEVENT_H - -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Core) - -class QState; - -class Q_CORE_EXPORT QStateFinishedEvent : public QEvent -{ -public: - QStateFinishedEvent(QState *state); - ~QStateFinishedEvent(); - - QState *state() const; - -private: - QState *m_state; - void *d; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/corelib/statemachine/qstatefinishedtransition.cpp b/src/corelib/statemachine/qstatefinishedtransition.cpp deleted file mode 100644 index 151a274..0000000 --- a/src/corelib/statemachine/qstatefinishedtransition.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qstatefinishedtransition.h" -#include "qstatefinishedevent.h" -#include "qabstracttransition_p.h" - -QT_BEGIN_NAMESPACE - -/*! - \class QStateFinishedTransition - - \brief The QStateFinishedTransition class provides a transition that triggers when a state is finished. - - \ingroup statemachine - - A state is finished when one of its final child states (a QFinalState) is - entered; this will cause a QStateFinishedEvent to be generated. The - QStateFinishedTransition class provides a way of associating a transition - with such an event. QStateFinishedTransition is part of \l{The State Machine - Framework}. - - \code - QStateMachine machine; - QState *s1 = new QState(machine.rootState()); - QState *s11 = new QState(s1); - QFinalState *s12 = new QFinalState(s1); - s11->addTransition(s12); - - QState *s2 = new QState(machine.rootState()); - QStateFinishedTransition *finishedTransition = new QStateFinishedTransition(s1); - finishedTransition->setTargetState(s2); - s1->addTransition(finishedTransition); - \endcode - - \sa QState::addFinishedTransition(), QStateFinishedEvent -*/ - -/*! - \property QStateFinishedTransition::state - - \brief the state whose QStateFinishedEvent this transition is associated with -*/ - -class QStateFinishedTransitionPrivate : public QAbstractTransitionPrivate -{ - Q_DECLARE_PUBLIC(QStateFinishedTransition) -public: - QStateFinishedTransitionPrivate(); - - static QStateFinishedTransitionPrivate *get(QStateFinishedTransition *q); - - QState *state; -}; - -QStateFinishedTransitionPrivate::QStateFinishedTransitionPrivate() -{ - state = 0; -} - -QStateFinishedTransitionPrivate *QStateFinishedTransitionPrivate::get(QStateFinishedTransition *q) -{ - return q->d_func(); -} - -/*! - Constructs a new QStateFinishedTransition object that has the given \a - sourceState. -*/ -QStateFinishedTransition::QStateFinishedTransition(QState *sourceState) - : QAbstractTransition(*new QStateFinishedTransitionPrivate, sourceState) -{ -} - -/*! - Constructs a new QStateFinishedTransition object associated with the given - \a state, and that has the given \a targets and \a sourceState. -*/ -QStateFinishedTransition::QStateFinishedTransition( - QState *state, const QList &targets, QState *sourceState) - : QAbstractTransition(*new QStateFinishedTransitionPrivate, targets, sourceState) -{ - Q_D(QStateFinishedTransition); - d->state = state; -} - -/*! - Destroys this QStateFinishedTransition. -*/ -QStateFinishedTransition::~QStateFinishedTransition() -{ -} - -/*! - Returns the state associated with this QStateFinishedTransition. -*/ -QState *QStateFinishedTransition::state() const -{ - Q_D(const QStateFinishedTransition); - return d->state; -} - -/*! - Sets the \a state associated with this QStateFinishedTransition. -*/ -void QStateFinishedTransition::setState(QState *state) -{ - Q_D(QStateFinishedTransition); - d->state = state; -} - -/*! - \reimp -*/ -bool QStateFinishedTransition::eventTest(QEvent *event) const -{ - Q_D(const QStateFinishedTransition); -#ifndef QT_STATEMACHINE_SOLUTION - if (event->type() == QEvent::StateFinished) { -#else - if (event->type() == QEvent::Type(QEvent::User-2)) { -#endif - QStateFinishedEvent *sfe = static_cast(event); - return (sfe->state() == d->state); - } - return false; -} - -/*! - \reimp -*/ -void QStateFinishedTransition::onTransition() -{ -} - -/*! - \reimp -*/ -bool QStateFinishedTransition::event(QEvent *e) -{ - return QAbstractTransition::event(e); -} - -QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qstatefinishedtransition.h b/src/corelib/statemachine/qstatefinishedtransition.h deleted file mode 100644 index ed86288..0000000 --- a/src/corelib/statemachine/qstatefinishedtransition.h +++ /dev/null @@ -1,88 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSTATEFINISHEDTRANSITION_H -#define QSTATEFINISHEDTRANSITION_H - -#ifndef QT_STATEMACHINE_SOLUTION -#include -#else -#include "qabstracttransition.h" -#endif - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Core) - -class QState; - -class QStateFinishedTransitionPrivate; -class Q_CORE_EXPORT QStateFinishedTransition : public QAbstractTransition -{ - Q_OBJECT - Q_PROPERTY(QState* state READ state WRITE setState) -public: - QStateFinishedTransition(QState *sourceState = 0); - QStateFinishedTransition(QState *state, const QList &targets, - QState *sourceState = 0); - ~QStateFinishedTransition(); - - QState *state() const; // ### name - void setState(QState *state); - -protected: - bool eventTest(QEvent *event) const; - void onTransition(); - - bool event(QEvent *e); - -private: - Q_DISABLE_COPY(QStateFinishedTransition) - Q_DECLARE_PRIVATE(QStateFinishedTransition) -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 8cee1fc..632390f 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -52,8 +52,6 @@ #include "qfinalstate.h" #include "qhistorystate.h" #include "qhistorystate_p.h" -#include "qstatefinishedevent.h" -#include "qstatefinishedtransition.h" #include "qstate.h" #include "qstate_p.h" #ifndef QT_STATEMACHINE_SOLUTION @@ -524,9 +522,9 @@ QList QStateMachinePrivate::enterStates(const QListparentState(); #ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": posting finished event for" << parent; + qDebug() << q << ": emitting finished signal for" << parent; #endif - internalEventQueue.append(new QStateFinishedEvent(parent)); + QStatePrivate::get(parent)->emitFinished(); if (grandparent && isParallel(grandparent)) { bool allChildStatesFinal = true; QList childStates = QStatePrivate::get(grandparent)->childStates(); @@ -539,9 +537,9 @@ QList QStateMachinePrivate::enterStates(const QListemitFinished(); } } } @@ -2102,56 +2100,6 @@ QSignalEvent::~QSignalEvent() Returns the arguments of the signal. */ -/*! - \class QStateFinishedEvent - - \brief The QStateFinishedEvent class contains parameters that describe a state that has finished. - - \since 4.6 - \ingroup statemachine - - A state is finished when one of its final child states (a QFinalState) is - entered; this will cause a QStateFinishedEvent to be generated by the state - machine. QStateFinishedEvent is part of \l{The State Machine Framework}. - - Typically you do not create QStateFinishedEvent objects yourself, but rather - use QStateFinishedTransition to create a transition that's triggered by a - state's finished event. - - \sa QStateFinishedTransition -*/ - -/*! - \internal - - Constructs a new QStateFinishedEvent object associated with the given \a state. -*/ -QStateFinishedEvent::QStateFinishedEvent(QState *state) - : -#ifndef QT_STATEMACHINE_SOLUTION - QEvent(StateFinished) -#else - QEvent(QEvent::Type(QEvent::User-2)) -#endif - , m_state(state), d(0) -{ -} - -/*! - Destroys this QStateFinishedEvent. -*/ -QStateFinishedEvent::~QStateFinishedEvent() -{ -} - -/*! - Returns the state associated with this QStateFinishedEvent. -*/ -QState *QStateFinishedEvent::state() const -{ - return m_state; -} - QT_END_NAMESPACE #include "moc_qstatemachine.cpp" diff --git a/src/corelib/statemachine/statemachine.pri b/src/corelib/statemachine/statemachine.pri index 620c7a0..69f887c 100644 --- a/src/corelib/statemachine/statemachine.pri +++ b/src/corelib/statemachine/statemachine.pri @@ -10,8 +10,6 @@ HEADERS += $$PWD/qstatemachine.h \ $$PWD/qhistorystate_p.h \ $$PWD/qabstracttransition.h \ $$PWD/qabstracttransition_p.h \ - $$PWD/qstatefinishedevent.h \ - $$PWD/qstatefinishedtransition.h \ $$PWD/qsignalevent.h \ $$PWD/qsignaltransition.h \ $$PWD/qsignaltransition_p.h @@ -22,7 +20,6 @@ SOURCES += $$PWD/qstatemachine.cpp \ $$PWD/qfinalstate.cpp \ $$PWD/qhistorystate.cpp \ $$PWD/qabstracttransition.cpp \ - $$PWD/qstatefinishedtransition.cpp \ $$PWD/qsignaltransition.cpp !contains(DEFINES, QT_NO_STATEMACHINE_EVENTFILTER) { diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 2fa9b1a..54446a6 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -1231,7 +1231,7 @@ void tst_QStateMachine::stateFinished() s1_1->addTransition(s1_2); s1->setInitialState(s1_1); QFinalState *s2 = new QFinalState(machine.rootState()); - s1->addTransition(new QStateFinishedTransition(s1, QList() << s2)); + s1->addTransition(s1, SIGNAL(finished()), s2); machine.setInitialState(s1); QSignalSpy finishedSpy(&machine, SIGNAL(finished())); machine.start(); @@ -1260,7 +1260,7 @@ void tst_QStateMachine::parallelStates() QFinalState *s2 = new QFinalState(); machine.addState(s2); - s1->addFinishedTransition(s2); + s1->addTransition(s1, SIGNAL(finished()), s2); machine.setInitialState(s1); QSignalSpy finishedSpy(&machine, SIGNAL(finished())); -- cgit v0.12 From 77abdfda731e010f8f93eb083478d10c7fd860fb Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Tue, 28 Apr 2009 13:10:35 +0200 Subject: compile after api changes --- examples/animation/sub-attaq/states.cpp | 4 ++-- examples/statemachine/composition/main.cpp | 4 ++-- examples/statemachine/trafficlight/main.cpp | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/animation/sub-attaq/states.cpp b/examples/animation/sub-attaq/states.cpp index f476f55..b381db7 100644 --- a/examples/animation/sub-attaq/states.cpp +++ b/examples/animation/sub-attaq/states.cpp @@ -140,10 +140,10 @@ void PlayState::onEntry() QFinalState *final = new QFinalState(machine->rootState()); //We win we should reach the final state - winState->addFinishedTransition(final); + winState->addTransition(winState, SIGNAL(finished()), final); //We lost we should reach the final state - lostState->addFinishedTransition(final); + lostState->addTransition(lostState, SIGNAL(finished()), final); machine->start(); } diff --git a/examples/statemachine/composition/main.cpp b/examples/statemachine/composition/main.cpp index 927fc62..0afff66 100644 --- a/examples/statemachine/composition/main.cpp +++ b/examples/statemachine/composition/main.cpp @@ -86,11 +86,11 @@ int main(int argc, char **argv) s2_timer->addTransition(&t2, SIGNAL(timeout()), s2_done); s2->setInitialState(s2_timer); - s1->addFinishedTransition(s2); + s1->addTransition(s1, SIGNAL(finished()), s2); QFinalState *s3 = new QFinalState(); s3->setObjectName("s3"); - s2->addFinishedTransition(s3); + s2->addTransition(s2, SIGNAL(finished()), s3); machine.addState(s1); machine.addState(s2); diff --git a/examples/statemachine/trafficlight/main.cpp b/examples/statemachine/trafficlight/main.cpp index 115ecad..ed0eeea 100644 --- a/examples/statemachine/trafficlight/main.cpp +++ b/examples/statemachine/trafficlight/main.cpp @@ -157,14 +157,14 @@ public: redGoingYellow->setObjectName("redGoingYellow"); LightState *yellowGoingGreen = new LightState(widget->yellowLight(), 1000); yellowGoingGreen->setObjectName("yellowGoingGreen"); - redGoingYellow->addFinishedTransition(yellowGoingGreen); + redGoingYellow->addTransition(redGoingYellow, SIGNAL(finished()), yellowGoingGreen); LightState *greenGoingYellow = new LightState(widget->greenLight(), 3000); greenGoingYellow->setObjectName("greenGoingYellow"); - yellowGoingGreen->addFinishedTransition(greenGoingYellow); + yellowGoingGreen->addTransition(yellowGoingGreen, SIGNAL(finished()), greenGoingYellow); LightState *yellowGoingRed = new LightState(widget->yellowLight(), 1000); yellowGoingRed->setObjectName("yellowGoingRed"); - greenGoingYellow->addFinishedTransition(yellowGoingRed); - yellowGoingRed->addFinishedTransition(redGoingYellow); + greenGoingYellow->addTransition(greenGoingYellow, SIGNAL(finished()), yellowGoingRed); + yellowGoingRed->addTransition(yellowGoingRed, SIGNAL(finished()), redGoingYellow); machine->addState(redGoingYellow); machine->addState(yellowGoingGreen); -- cgit v0.12 From 77ed0fdc4a74113982dbcd70b689b2addf30516c Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Tue, 28 Apr 2009 13:13:56 +0200 Subject: kill StateFinished event type since it doesn't exist anymore --- src/corelib/kernel/qcoreevent.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h index 5e76976..674b5b0 100644 --- a/src/corelib/kernel/qcoreevent.h +++ b/src/corelib/kernel/qcoreevent.h @@ -269,8 +269,7 @@ public: CocoaRequestModal = 190, // Internal for requesting an application modal Cocoa Window MacGLClearDrawable = 191, // Internal Cocoa, the window has changed, so we must clear - Signal = 191, - StateFinished = 192, + Signal = 192, Bound = 193, // 512 reserved for Qt Jambi's MetaCall event -- cgit v0.12 From a3e862a07bd724c02d1860eb106dfb245659775b Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 27 Apr 2009 15:24:41 +0200 Subject: Some updates to the errorstate example. Added cannon firing. There are some problems left: For some reason the parallel state group does not work properly, so only one tank moves even if you add more. There also seems to be something wrong with historyState->setDefaultState(). --- examples/statemachine/errorstate/errorstate.pro | 4 +- examples/statemachine/errorstate/gameitem.cpp | 67 ++++++++++ examples/statemachine/errorstate/gameitem.h | 22 ++++ examples/statemachine/errorstate/mainwindow.cpp | 42 +++++-- examples/statemachine/errorstate/mainwindow.h | 8 +- examples/statemachine/errorstate/rocketitem.cpp | 60 +++++++++ examples/statemachine/errorstate/rocketitem.h | 28 +++++ examples/statemachine/errorstate/tank.h | 4 +- examples/statemachine/errorstate/tankitem.cpp | 136 ++++++--------------- examples/statemachine/errorstate/tankitem.h | 21 ++-- .../random_ai/random_ai_plugin.cpp | 2 +- .../errorstateplugins/random_ai/random_ai_plugin.h | 2 +- 12 files changed, 270 insertions(+), 126 deletions(-) create mode 100644 examples/statemachine/errorstate/gameitem.cpp create mode 100644 examples/statemachine/errorstate/gameitem.h create mode 100644 examples/statemachine/errorstate/rocketitem.cpp create mode 100644 examples/statemachine/errorstate/rocketitem.h diff --git a/examples/statemachine/errorstate/errorstate.pro b/examples/statemachine/errorstate/errorstate.pro index d937b02..c159f94 100644 --- a/examples/statemachine/errorstate/errorstate.pro +++ b/examples/statemachine/errorstate/errorstate.pro @@ -8,6 +8,6 @@ DEPENDPATH += . INCLUDEPATH += C:/dev/kinetic/examples/statemachine/errorstate/. . # Input -HEADERS += mainwindow.h plugin.h tank.h tankitem.h -SOURCES += main.cpp mainwindow.cpp tankitem.cpp +HEADERS += mainwindow.h plugin.h tank.h tankitem.h rocketitem.h gameitem.h +SOURCES += main.cpp mainwindow.cpp tankitem.cpp rocketitem.cpp gameitem.cpp CONFIG += console diff --git a/examples/statemachine/errorstate/gameitem.cpp b/examples/statemachine/errorstate/gameitem.cpp new file mode 100644 index 0000000..786cf51 --- /dev/null +++ b/examples/statemachine/errorstate/gameitem.cpp @@ -0,0 +1,67 @@ +#include "gameitem.h" + +#include + +QPointF GameItem::tryMove(const QPointF &requestedPosition, QLineF *collidedLine, + QGraphicsItem **collidedItem) const +{ + QLineF movementPath(pos(), requestedPosition); + + qreal cannonLength = 0.0; + { + QPointF p1 = boundingRect().center(); + QPointF p2 = QPointF(boundingRect().right() + 10.0, p1.y()); + + cannonLength = QLineF(mapToScene(p1), mapToScene(p2)).length(); + } + + movementPath.setLength(movementPath.length() + cannonLength); + + QRectF boundingRectPath(QPointF(qMin(movementPath.x1(), movementPath.x2()), qMin(movementPath.y1(), movementPath.y2())), + QPointF(qMax(movementPath.x1(), movementPath.x2()), qMax(movementPath.y1(), movementPath.y2()))); + + QList itemsInRect = scene()->items(boundingRectPath, Qt::IntersectsItemBoundingRect); + + QPointF nextPoint = requestedPosition; + QRectF sceneRect = scene()->sceneRect(); + + foreach (QGraphicsItem *item, itemsInRect) { + if (item == static_cast(this)) + continue; + + QPolygonF mappedBoundingRect = item->mapToScene(item->boundingRect()); + for (int i=0; i sceneRect.right()) + nextPoint.rx() = sceneRect.right(); + if (nextPoint.y() < sceneRect.top()) + nextPoint.ry() = sceneRect.top(); + if (nextPoint.y() > sceneRect.bottom()) + nextPoint.ry() = sceneRect.bottom(); + + return nextPoint; +} + diff --git a/examples/statemachine/errorstate/gameitem.h b/examples/statemachine/errorstate/gameitem.h new file mode 100644 index 0000000..6ca32b7 --- /dev/null +++ b/examples/statemachine/errorstate/gameitem.h @@ -0,0 +1,22 @@ +#ifndef GAMEITEM_H +#define GAMEITEM_H + +#include + +class QLineF; +class GameItem: public QGraphicsItem +{ +public: + enum { Type = UserType + 1 }; + + int type() const { return Type; } + virtual void idle(qreal elapsed) = 0; + + virtual void hitByRocket() = 0; + +protected: + QPointF tryMove(const QPointF &requestedPosition, QLineF *collidedLine = 0, + QGraphicsItem **collidedItem = 0) const; +}; + +#endif diff --git a/examples/statemachine/errorstate/mainwindow.cpp b/examples/statemachine/errorstate/mainwindow.cpp index 598756f..c0af62d 100644 --- a/examples/statemachine/errorstate/mainwindow.cpp +++ b/examples/statemachine/errorstate/mainwindow.cpp @@ -1,5 +1,6 @@ #include "mainwindow.h" #include "tankitem.h" +#include "rocketitem.h" #include "plugin.h" #include @@ -13,7 +14,7 @@ #include MainWindow::MainWindow(QWidget *parent) - : QMainWindow(parent) + : QMainWindow(parent), m_scene(0), m_machine(0), m_runningState(0), m_started(false) { init(); } @@ -37,6 +38,7 @@ void MainWindow::init() setWindowTitle("Pluggable Tank Game"); QGraphicsView *view = new QGraphicsView(this); + view->setRenderHints(QPainter::Antialiasing); setCentralWidget(view); m_scene = new QGraphicsScene(this); @@ -118,6 +120,7 @@ void MainWindow::init() stoppedState->assignProperty(runGameAction, "enabled", true); stoppedState->assignProperty(stopGameAction, "enabled", false); + stoppedState->assignProperty(this, "started", false); m_machine->setInitialState(stoppedState); QState *spawnsAvailable = new QState(stoppedState); @@ -146,20 +149,42 @@ void MainWindow::init() timer->setInterval(100); connect(timer, SIGNAL(timeout()), this, SLOT(runStep())); connect(m_runningState, SIGNAL(entered()), timer, SLOT(start())); - connect(m_runningState, SIGNAL(exited()), timer, SLOT(stop())); + connect(m_runningState, SIGNAL(exited()), timer, SLOT(stop())); m_time.start(); } void MainWindow::runStep() { - int elapsed = m_time.elapsed(); - if (elapsed > 0) { + if (!m_started) { m_time.restart(); - qreal elapsedSecs = elapsed / 1000.0; - QList tankItems = qFindChildren(this); - foreach (TankItem *tankItem, tankItems) - tankItem->idle(elapsedSecs); + m_started = true; + } else { + int elapsed = m_time.elapsed(); + if (elapsed > 0) { + m_time.restart(); + qreal elapsedSecs = elapsed / 1000.0; + QList items = m_scene->items(); + foreach (QGraphicsItem *item, items) { + GameItem *gameItem = qgraphicsitem_cast(item); + if (gameItem != 0) + gameItem->idle(elapsedSecs); + } + } + } +} + +void MainWindow::addRocket() +{ + TankItem *tankItem = qobject_cast(sender()); + if (tankItem != 0) { + RocketItem *rocketItem = new RocketItem; + + QPointF s = tankItem->mapToScene(QPointF(tankItem->boundingRect().right() + 10.0, + tankItem->boundingRect().center().y())); + rocketItem->setPos(s); + rocketItem->setDirection(tankItem->direction()); + m_scene->addItem(rocketItem); } } @@ -175,6 +200,7 @@ void MainWindow::addTank() if (plugin != 0) { TankItem *tankItem = m_spawns.takeLast(); m_scene->addItem(tankItem); + connect(tankItem, SIGNAL(fireCannon()), this, SLOT(addRocket())); if (m_spawns.isEmpty()) emit mapFull(); diff --git a/examples/statemachine/errorstate/mainwindow.h b/examples/statemachine/errorstate/mainwindow.h index 2bd574d..33122eb 100644 --- a/examples/statemachine/errorstate/mainwindow.h +++ b/examples/statemachine/errorstate/mainwindow.h @@ -11,12 +11,17 @@ class TankItem; class MainWindow: public QMainWindow { Q_OBJECT + Q_PROPERTY(bool started READ started WRITE setStarted) public: MainWindow(QWidget *parent = 0); ~MainWindow(); + void setStarted(bool b) { m_started = b; } + bool started() const { return m_started; } + public slots: void addTank(); + void addRocket(); void runStep(); signals: @@ -34,7 +39,8 @@ private: QList m_spawns; QTime m_time; - + + bool m_started : 1; }; #endif diff --git a/examples/statemachine/errorstate/rocketitem.cpp b/examples/statemachine/errorstate/rocketitem.cpp new file mode 100644 index 0000000..de9eef7 --- /dev/null +++ b/examples/statemachine/errorstate/rocketitem.cpp @@ -0,0 +1,60 @@ +#include "rocketitem.h" + +#include +#include + +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +RocketItem::RocketItem() + : m_direction(0.0), m_distance(300.0) +{ +} + +QRectF RocketItem::boundingRect() const +{ + return QRectF(-1.0, -1.0, 2.0, 2.0); +} + +void RocketItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + painter->setBrush(Qt::black); + painter->drawEllipse(boundingRect()); +} + +void RocketItem::hitByRocket() +{ +} + +void RocketItem::idle(qreal elapsed) +{ + qreal dist = elapsed * speed(); + + m_distance -= dist; + if (m_distance < 0.0) { + scene()->removeItem(this); + delete this; + return; + } + + qreal a = m_direction * M_PI / 180.0; + + qreal yd = dist * sin(a); + qreal xd = dist * sin(M_PI / 2.0 - a); + + QPointF requestedPosition = pos() + QPointF(xd, yd); + QGraphicsItem *collidedItem = 0; + QPointF nextPosition = tryMove(requestedPosition, 0, &collidedItem); + if (requestedPosition == nextPosition) { + setPos(nextPosition); + } else { + if (GameItem *gameItem = qgraphicsitem_cast(collidedItem)) + gameItem->hitByRocket(); + + scene()->removeItem(this); + delete this; + } +} diff --git a/examples/statemachine/errorstate/rocketitem.h b/examples/statemachine/errorstate/rocketitem.h new file mode 100644 index 0000000..9805a8a --- /dev/null +++ b/examples/statemachine/errorstate/rocketitem.h @@ -0,0 +1,28 @@ +#ifndef ROCKETITEM_H +#define ROCKETITEM_H + +#include "gameitem.h" + +class RocketItem: public GameItem +{ +public: + RocketItem(); + + virtual void idle(qreal elapsed); + qreal speed() const { return 100.0; } + void setDirection(qreal direction) { m_direction = direction; } + + void hitByRocket(); + +protected: + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + QRectF boundingRect() const; + + +private: + qreal m_direction; + qreal m_distance; +}; + + +#endif diff --git a/examples/statemachine/errorstate/tank.h b/examples/statemachine/errorstate/tank.h index 9def6df..49c5daf 100644 --- a/examples/statemachine/errorstate/tank.h +++ b/examples/statemachine/errorstate/tank.h @@ -23,9 +23,9 @@ signals: public slots: virtual void moveForwards(qreal length) = 0; virtual void moveBackwards(qreal length) = 0; - virtual void turn(qreal newDirection) = 0; + virtual void turn(qreal degrees) = 0; virtual void stop() = 0; - virtual void fireCannon(qreal distance) = 0; + virtual void fireCannon() = 0; }; #endif diff --git a/examples/statemachine/errorstate/tankitem.cpp b/examples/statemachine/errorstate/tankitem.cpp index 21d4a25..814de2b 100644 --- a/examples/statemachine/errorstate/tankitem.cpp +++ b/examples/statemachine/errorstate/tankitem.cpp @@ -31,14 +31,18 @@ public: MoveAction(TankItem *item, qreal distance) : Action(item), m_distance(distance) { + m_reverse = m_distance < 0.0; } bool apply(qreal timeDelta) { - qreal dist = timeDelta * item()->speed(); + qreal dist = timeDelta * item()->speed() * (m_reverse ? -1.0 : 1.0); + m_distance -= dist; - if (qFuzzyCompare(m_distance, 0.0)) - return false; + if (m_reverse && m_distance > 0.0) + return false; + else if (m_distance < 0.0) + return false; qreal a = item()->direction() * M_PI / 180.0; @@ -51,6 +55,7 @@ public: private: qreal m_distance; + bool m_reverse; }; class TurnAction: public Action @@ -59,14 +64,17 @@ public: TurnAction(TankItem *item, qreal distance) : Action(item), m_distance(distance) { + m_reverse = m_distance < 0.0; } bool apply(qreal timeDelta) { - qreal dist = timeDelta * item()->angularSpeed(); + qreal dist = timeDelta * item()->angularSpeed() * (m_reverse ? -1.0 : 1.0); m_distance -= dist; - if (qFuzzyCompare(m_distance, 0.0)) - return false; + if (m_reverse && m_distance > 0.0) + return false; + else if (m_distance < 0.0) + return false; item()->setDirection(item()->direction() + dist); return true; @@ -74,27 +82,12 @@ public: private: qreal m_distance; -}; - -class FireCannonAction: public Action -{ -public: - FireCannonAction(TankItem *item, qreal distance) - : Action(item), m_distance(distance) - { - } - - bool apply(qreal ) - { - return false; - } - -private: - qreal m_distance; + bool m_reverse; }; TankItem::TankItem(QObject *parent) : Tank(parent), m_currentAction(0), m_currentDirection(0.0) { + connect(this, SIGNAL(fireCannon()), this, SIGNAL(actionCompleted())); } void TankItem::idle(qreal elapsed) @@ -107,6 +100,11 @@ void TankItem::idle(qreal elapsed) } } +void TankItem::hitByRocket() +{ + deleteLater(); +} + void TankItem::setAction(Action *newAction) { if (m_currentAction != 0) @@ -125,9 +123,9 @@ void TankItem::moveBackwards(qreal length) setAction(new MoveAction(this, -length)); } -void TankItem::turn(qreal newDirection) +void TankItem::turn(qreal degrees) { - setAction(new TurnAction(this, m_currentDirection - newDirection)); + setAction(new TurnAction(this, degrees)); } void TankItem::stop() @@ -135,81 +133,18 @@ void TankItem::stop() setAction(0); } -void TankItem::fireCannon(qreal distance) -{ - setAction(new FireCannonAction(this, distance)); -} - -QPointF TankItem::tryMove(const QPointF &requestedPosition) const -{ - QLineF movementPath(pos(), requestedPosition); - - qreal cannonLength = 0.0; - { - QPointF p1 = boundingRect().center(); - QPointF p2 = QPointF(boundingRect().right() + 10.0, p1.y()); - - cannonLength = QLineF(mapToScene(p1), mapToScene(p2)).length(); - } - - movementPath.setLength(movementPath.length() + cannonLength); - - QRectF boundingRectPath(QPointF(qMin(movementPath.x1(), movementPath.x2()), qMin(movementPath.y1(), movementPath.y2())), - QPointF(qMax(movementPath.x1(), movementPath.x2()), qMax(movementPath.y1(), movementPath.y2()))); - - m_brp = mapFromScene(boundingRectPath); - - QList itemsInRect = scene()->items(boundingRectPath, Qt::IntersectsItemBoundingRect); - - QPointF nextPoint = requestedPosition; - QRectF sceneRect = scene()->sceneRect(); - - QLineF collidedLine; - foreach (QGraphicsItem *item, itemsInRect) { - if (item == static_cast(this)) - continue; - - QPolygonF mappedBoundingRect = item->mapToScene(item->boundingRect()); - for (int i=0; i sceneRect.right()) - nextPoint.rx() = sceneRect.right(); - if (nextPoint.y() < sceneRect.top()) - nextPoint.ry() = sceneRect.top(); - if (nextPoint.y() > sceneRect.bottom()) - nextPoint.ry() = sceneRect.bottom(); - - if (nextPoint != requestedPosition) { - emit collision(collidedLine); - } - - return nextPoint; -} - QVariant TankItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) { - if (change == ItemPositionChange && scene()) - return tryMove(value.toPointF()); - else + if (change == ItemPositionChange && scene()) { + QPointF requestedPosition = value.toPointF(); + QLineF collidedLine; + QPointF nextPoint = tryMove(requestedPosition, &collidedLine); + if (nextPoint != requestedPosition) + emit collision(collidedLine); + return nextPoint; + } else { return QGraphicsItem::itemChange(change, value); + } } @@ -241,10 +176,6 @@ void TankItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidge QPointF(brect.right() - 2.0, brect.bottom())); painter->fillRect(rightTrackRect, Qt::darkYellow); painter->drawRect(rightTrackRect); - - painter->setBrush(QColor::fromRgb(255, 0, 0, 128)); - painter->drawPolygon(m_brp); - } QRectF TankItem::boundingRect() const @@ -259,8 +190,9 @@ qreal TankItem::direction() const void TankItem::setDirection(qreal newDirection) { + qreal diff = newDirection - m_currentDirection; m_currentDirection = newDirection; - rotate(newDirection); + rotate(diff); } qreal TankItem::distanceToObstacle() const diff --git a/examples/statemachine/errorstate/tankitem.h b/examples/statemachine/errorstate/tankitem.h index df13689..c9e0d22 100644 --- a/examples/statemachine/errorstate/tankitem.h +++ b/examples/statemachine/errorstate/tankitem.h @@ -2,12 +2,12 @@ #define TANKITEM_H #include "tank.h" +#include "gameitem.h" -#include #include class Action; -class TankItem: public Tank, public QGraphicsItem +class TankItem: public Tank, public GameItem { Q_OBJECT public: @@ -17,7 +17,6 @@ public: virtual void moveBackwards(qreal length); virtual void turn(qreal newDirection); virtual void stop(); - virtual void fireCannon(qreal distance); virtual qreal direction() const; virtual qreal distanceToObstacle() const; @@ -27,22 +26,26 @@ public: void idle(qreal elapsed); void setDirection(qreal newDirection); - qreal speed() const { return 20.0; } - qreal angularSpeed() const { return 1.0; } + qreal speed() const { return 90.0; } + qreal angularSpeed() const { return 90.0; } -protected: - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); QRectF boundingRect() const; + + void hitByRocket(); + +signals: + virtual void fireCannon(); + +protected: + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value); private: - QPointF tryMove(const QPointF &requestedPosition) const; void setAction(Action *newAction); Action *m_currentAction; qreal m_currentDirection; QColor m_color; - mutable QPolygonF m_brp; }; #endif diff --git a/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.cpp b/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.cpp index 429e3ca..135c7b6 100644 --- a/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.cpp +++ b/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.cpp @@ -17,7 +17,7 @@ QState *RandomAiPlugin::create(QState *parentState, Tank *tank) topLevel->setInitialState(selectNextActionState); QState *fireState = new RandomDistanceState(topLevel); - connect(fireState, SIGNAL(distanceComputed(qreal)), tank, SLOT(fireCannon(qreal))); + connect(fireState, SIGNAL(distanceComputed(qreal)), tank, SLOT(fireCannon())); selectNextActionState->addTransition(selectNextActionState, SIGNAL(fireSelected()), fireState); QState *moveForwardsState = new RandomDistanceState(topLevel); diff --git a/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.h b/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.h index 27c9b92..758b3e8 100644 --- a/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.h +++ b/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.h @@ -47,7 +47,7 @@ signals: protected: void onEntry() { - emit distanceComputed(qreal(qrand() % 10)); + emit distanceComputed(qreal(qrand() % 180)); } }; -- cgit v0.12 From 772cb8c46b96e850b391f157e4870895e53748d4 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 28 Apr 2009 13:47:00 +0200 Subject: Add a test for the semantics of transitions from a region in parallel states. This test checks for the behavior I expected, but that's apparently not how it's defined in the SCXML algorithm. Currently it XFAILs, and we'll either have to fix the algorithm or the test when we get word back on what the correct semantics are. --- tests/auto/qstatemachine/tst_qstatemachine.cpp | 47 ++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 54446a6..db25ad5 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -133,6 +133,7 @@ private slots: //void restorePolicyOnChildState(); void transitionWithParent(); + void parallelStateTransition(); void simpleAnimation(); void twoAnimations(); @@ -2808,6 +2809,52 @@ void tst_QStateMachine::overrideDefaultTargetAnimationWithSource() QCOMPARE(counter.counter, 2); // specific animation started and stopped } +void tst_QStateMachine::parallelStateTransition() +{ + QStateMachine machine; + + QState *parallelState = new QState(QState::ParallelGroup, machine.rootState()); + machine.setInitialState(parallelState); + + QState *s1 = new QState(parallelState); + QState *s2 = new QState(parallelState); + + QState *s1InitialChild = new QState(s1); + s1->setInitialState(s1InitialChild); + + QState *s2InitialChild = new QState(s2); + s2->setInitialState(s2InitialChild); + + QState *s1OtherChild = new QState(s1); + QState *s2OtherChild = new QState(s2); + + s1->addTransition(new EventTransition(QEvent::User, s1OtherChild)); + + machine.start(); + QCoreApplication::processEvents(); + + QVERIFY(machine.configuration().contains(parallelState)); + QVERIFY(machine.configuration().contains(s1)); + QVERIFY(machine.configuration().contains(s2)); + QVERIFY(machine.configuration().contains(s1InitialChild)); + QVERIFY(machine.configuration().contains(s2InitialChild)); + QCOMPARE(machine.configuration().size(), 5); + + machine.postEvent(new QEvent(QEvent::User)); + QCoreApplication::processEvents(); + + QVERIFY(machine.configuration().contains(parallelState)); + + QVERIFY(machine.configuration().contains(s1)); + + QEXPECT_FAIL("", "This failure is defined in the algorithm. We need to find out what behavior is correct.", Abort); + QVERIFY(machine.configuration().contains(s2)); + QVERIFY(machine.configuration().contains(s1OtherChild)); + QVERIFY(machine.configuration().contains(s2InitialChild)); + QCOMPARE(machine.configuration().size(), 5); + +} + QTEST_MAIN(tst_QStateMachine) #include "tst_qstatemachine.moc" -- cgit v0.12 From 6cb8adb930926511777f8e97bc45683ecbbf5b36 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 28 Apr 2009 15:47:02 +0200 Subject: Work around an oddity in parallel states that causes all regions to exit if there is a transition from one of them (even if the target state of the transition is inside the region.) --- examples/statemachine/errorstate/mainwindow.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/statemachine/errorstate/mainwindow.cpp b/examples/statemachine/errorstate/mainwindow.cpp index c0af62d..9281298 100644 --- a/examples/statemachine/errorstate/mainwindow.cpp +++ b/examples/statemachine/errorstate/mainwindow.cpp @@ -192,8 +192,7 @@ void MainWindow::addTank() { Q_ASSERT(!m_spawns.isEmpty()); - QString fileName = QFileDialog::getOpenFileName(this, "Select plugin file", - "plugins/", "*.dll"); + QString fileName = QFileDialog::getOpenFileName(this, "Select plugin file", "plugins/", "*.dll"); QPluginLoader loader(fileName); Plugin *plugin = qobject_cast(loader.instance()); @@ -203,8 +202,9 @@ void MainWindow::addTank() connect(tankItem, SIGNAL(fireCannon()), this, SLOT(addRocket())); if (m_spawns.isEmpty()) emit mapFull(); - - plugin->create(m_runningState, tankItem); + + QState *region = new QState(m_runningState); + region->setInitialState(plugin->create(region, tankItem)); } } -- cgit v0.12 From 9c28c75052a38eb3b317c2ac7ad2a26c73deeb2d Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Tue, 28 Apr 2009 13:26:09 +0200 Subject: kill StateFinished from docs --- src/corelib/kernel/qcoreevent.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp index fc1cefb..f98ef8b 100644 --- a/src/corelib/kernel/qcoreevent.cpp +++ b/src/corelib/kernel/qcoreevent.cpp @@ -265,7 +265,6 @@ QT_BEGIN_NAMESPACE \omitvalue CocoaRequestModal \omitvalue Bound \omitvalue Signal - \omitvalue StateFinished */ /*! -- cgit v0.12 From 4f6b9b1779fe33f876f96c196c3feef7e72992a0 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Tue, 28 Apr 2009 13:29:37 +0200 Subject: move assignProperty() to QState Doesn't belong in the abstract base class. --- doc/src/statemachine.qdoc | 9 ++++----- src/corelib/statemachine/qabstractstate.cpp | 24 ++---------------------- src/corelib/statemachine/qabstractstate.h | 3 --- src/corelib/statemachine/qabstractstate_p.h | 20 -------------------- src/corelib/statemachine/qstate.cpp | 21 +++++++++++++++++++++ src/corelib/statemachine/qstate.h | 4 ++++ src/corelib/statemachine/qstate_p.h | 19 +++++++++++++++++++ src/corelib/statemachine/qstatemachine.cpp | 12 +++++++----- src/corelib/statemachine/qstatemachine_p.h | 2 +- 9 files changed, 58 insertions(+), 56 deletions(-) diff --git a/doc/src/statemachine.qdoc b/doc/src/statemachine.qdoc index 97c09b9..1462ec1 100644 --- a/doc/src/statemachine.qdoc +++ b/doc/src/statemachine.qdoc @@ -76,11 +76,10 @@ becomes part of your application's event loop. The above state machine is perfectly fine, but it doesn't \e do anything; it - merely transitions from one state to another. The - QAbstractState::assignProperty() function can be used to have a state set a - property of a QObject when the state is entered. In the following snippet, - the value that should be assigned to a QLabel's text property is specified - for each state: + merely transitions from one state to another. The QState::assignProperty() + function can be used to have a state set a property of a QObject when the + state is entered. In the following snippet, the value that should be + assigned to a QLabel's text property is specified for each state: \code s1->assignProperty(label, "text", "In state s1"); diff --git a/src/corelib/statemachine/qabstractstate.cpp b/src/corelib/statemachine/qabstractstate.cpp index 396063a..12f14d7 100644 --- a/src/corelib/statemachine/qabstractstate.cpp +++ b/src/corelib/statemachine/qabstractstate.cpp @@ -41,9 +41,10 @@ #include "qabstractstate.h" #include "qabstractstate_p.h" +#include "qstate.h" +#include "qstate_p.h" #include "qstatemachine.h" #include "qstatemachine_p.h" -#include "qstate.h" QT_BEGIN_NAMESPACE @@ -59,9 +60,6 @@ QT_BEGIN_NAMESPACE of a QStateMachine. It defines the interface that all state objects have in common. QAbstractState is part of \l{The State Machine Framework}. - The assignProperty() function is used for defining property assignments that - should be performed when a state is entered. - The entered() signal is emitted when the state has been entered. The exited() signal is emitted when the state has been exited. @@ -181,24 +179,6 @@ QState *QAbstractState::parentState() const } /*! - Instructs this state to set the property with the given \a name of the given - \a object to the given \a value when the state is entered. -*/ -void QAbstractState::assignProperty(QObject *object, const char *name, - const QVariant &value) -{ - Q_D(QAbstractState); - for (int i = 0; i < d->propertyAssignments.size(); ++i) { - QPropertyAssignment &assn = d->propertyAssignments[i]; - if ((assn.object == object) && (assn.propertyName == name)) { - assn.value = value; - return; - } - } - d->propertyAssignments.append(QPropertyAssignment(object, name, value)); -} - -/*! \fn QAbstractState::onExit() This function is called when the state is exited. Reimplement this function diff --git a/src/corelib/statemachine/qabstractstate.h b/src/corelib/statemachine/qabstractstate.h index 69e6bf1..a5f1440 100644 --- a/src/corelib/statemachine/qabstractstate.h +++ b/src/corelib/statemachine/qabstractstate.h @@ -61,9 +61,6 @@ public: QState *parentState() const; - void assignProperty(QObject *object, const char *name, - const QVariant &value); - Q_SIGNALS: void entered(); void exited(); diff --git a/src/corelib/statemachine/qabstractstate_p.h b/src/corelib/statemachine/qabstractstate_p.h index 8c8f436..bbe12d6 100644 --- a/src/corelib/statemachine/qabstractstate_p.h +++ b/src/corelib/statemachine/qabstractstate_p.h @@ -57,28 +57,10 @@ #include #endif -#include -#include -#include - QT_BEGIN_NAMESPACE -class QAbstractTransition; -class QHistoryState; class QStateMachine; -struct QPropertyAssignment -{ - QPropertyAssignment(QObject *o, const QByteArray &n, - const QVariant &v, bool es = true) - : object(o), propertyName(n), value(v), explicitlySet(es) - {} - QObject *object; - QByteArray propertyName; - QVariant value; - bool explicitlySet; -}; - class QAbstractState; class Q_CORE_EXPORT QAbstractStatePrivate #ifndef QT_STATEMACHINE_SOLUTION @@ -101,8 +83,6 @@ public: void emitEntered(); void emitExited(); - QList propertyAssignments; - #ifdef QT_STATEMACHINE_SOLUTION QAbstractState *q_ptr; #endif diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp index 9bda250..5c3418b 100644 --- a/src/corelib/statemachine/qstate.cpp +++ b/src/corelib/statemachine/qstate.cpp @@ -65,6 +65,9 @@ QT_BEGIN_NAMESPACE The addTransition() function adds a transition. The removeTransition() function removes a transition. + The assignProperty() function is used for defining property assignments that + should be performed when a state is entered. + \section1 States with Child States For non-parallel state groups, the setInitialState() function must be called @@ -216,6 +219,24 @@ QList QStatePrivate::transitions() const } /*! + Instructs this state to set the property with the given \a name of the given + \a object to the given \a value when the state is entered. +*/ +void QState::assignProperty(QObject *object, const char *name, + const QVariant &value) +{ + Q_D(QState); + for (int i = 0; i < d->propertyAssignments.size(); ++i) { + QPropertyAssignment &assn = d->propertyAssignments[i]; + if ((assn.object == object) && (assn.propertyName == name)) { + assn.value = value; + return; + } + } + d->propertyAssignments.append(QPropertyAssignment(object, name, value)); +} + +/*! Returns this state group's error state. \sa QStateMachine::errorState(), QStateMachine::setErrorState() diff --git a/src/corelib/statemachine/qstate.h b/src/corelib/statemachine/qstate.h index 70211c1..0dd99dc 100644 --- a/src/corelib/statemachine/qstate.h +++ b/src/corelib/statemachine/qstate.h @@ -91,8 +91,12 @@ public: QAbstractState *initialState() const; void setInitialState(QAbstractState *state); + void assignProperty(QObject *object, const char *name, + const QVariant &value); + Q_SIGNALS: void finished(); + void polished(); protected: void onEntry(); diff --git a/src/corelib/statemachine/qstate_p.h b/src/corelib/statemachine/qstate_p.h index 2df6823..603bc18 100644 --- a/src/corelib/statemachine/qstate_p.h +++ b/src/corelib/statemachine/qstate_p.h @@ -56,9 +56,26 @@ #include "qabstractstate_p.h" #include +#include +#include QT_BEGIN_NAMESPACE +struct QPropertyAssignment +{ + QPropertyAssignment(QObject *o, const QByteArray &n, + const QVariant &v, bool es = true) + : object(o), propertyName(n), value(v), explicitlySet(es) + {} + QObject *object; + QByteArray propertyName; + QVariant value; + bool explicitlySet; +}; + +class QAbstractTransition; +class QHistoryState; + class QState; class Q_CORE_EXPORT QStatePrivate : public QAbstractStatePrivate { @@ -79,6 +96,8 @@ public: QAbstractState *errorState; bool isParallelGroup; QAbstractState *initialState; + + QList propertyAssignments; }; QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 632390f..1434bc0 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -40,6 +40,8 @@ ****************************************************************************/ #include "qstatemachine.h" +#include "qstate.h" +#include "qstate_p.h" #include "qstatemachine_p.h" #include "qabstracttransition.h" #include "qabstracttransition_p.h" @@ -52,8 +54,6 @@ #include "qfinalstate.h" #include "qhistorystate.h" #include "qhistorystate_p.h" -#include "qstate.h" -#include "qstate_p.h" #ifndef QT_STATEMACHINE_SOLUTION #include "private/qobject_p.h" #include "private/qthread_p.h" @@ -641,9 +641,11 @@ void QStateMachinePrivate::applyProperties(const QList &tr QList propertyAssignments; QHash pendingRestorables = registeredRestorables; for (int i = 0; i < enteredStates.size(); ++i) { - QAbstractState *s = enteredStates.at(i); + QState *s = qobject_cast(enteredStates.at(i)); + if (!s) + continue; - QList assignments = QAbstractStatePrivate::get(s)->propertyAssignments; + QList assignments = QStatePrivate::get(s)->propertyAssignments; for (int j = 0; j < assignments.size(); ++j) { const QPropertyAssignment &assn = assignments.at(j); if (globalRestorePolicy == QStateMachine::RestoreProperties) { @@ -1487,7 +1489,7 @@ void QStateMachine::setErrorState(QAbstractState *state) \value RestoreProperties The state machine should save the initial values of properties and restore them later. - \sa setRestorePolicy(), restorePolicy(), QAbstractState::assignProperty() + \sa setRestorePolicy(), restorePolicy(), QState::assignProperty() */ diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index 9f93217..323473d 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -62,7 +62,7 @@ #include #include -#include "qabstractstate_p.h" +#include "qstate_p.h" QT_BEGIN_NAMESPACE -- cgit v0.12 From 6293521a6e5ee0ce010180a40e6fda3ef3a8b245 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Tue, 28 Apr 2009 13:45:23 +0200 Subject: add animationsEnabled property --- src/corelib/statemachine/qstatemachine.cpp | 47 +++++++++++++++++++++++++----- src/corelib/statemachine/qstatemachine.h | 6 ++++ src/corelib/statemachine/qstatemachine_p.h | 2 ++ 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 1434bc0..8d5317a 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -177,6 +177,14 @@ QT_BEGIN_NAMESPACE \brief the error string of this state machine */ +#ifndef QT_NO_ANIMATION +/*! + \property QStateMachine::animationsEnabled + + \brief whether animations are enabled +*/ +#endif + // #define QSTATEMACHINE_DEBUG QStateMachinePrivate::QStateMachinePrivate() @@ -192,6 +200,9 @@ QStateMachinePrivate::QStateMachinePrivate() #ifndef QT_STATEMACHINE_SOLUTION signalEventGenerator = 0; #endif +#ifndef QT_NO_ANIMATION + animationsEnabled = true; +#endif } QStateMachinePrivate::~QStateMachinePrivate() @@ -622,17 +633,19 @@ void QStateMachinePrivate::applyProperties(const QList &tr // Find the animations to use for the state change. QList selectedAnimations; - for (int i = 0; i < transitionList.size(); ++i) { - QAbstractTransition *transition = transitionList.at(i); + if (animationsEnabled) { + for (int i = 0; i < transitionList.size(); ++i) { + QAbstractTransition *transition = transitionList.at(i); - selectedAnimations << transition->animations(); - selectedAnimations << defaultAnimationsForSource.values(transition->sourceState()); + selectedAnimations << transition->animations(); + selectedAnimations << defaultAnimationsForSource.values(transition->sourceState()); - QList targetStates = transition->targetStates(); - for (int j=0; j targetStates = transition->targetStates(); + for (int j=0; janimationsEnabled; +} + +/*! + Sets whether animations are \a enabled for this state machine. +*/ +void QStateMachine::setAnimationsEnabled(bool enabled) +{ + Q_D(QStateMachine); + d->animationsEnabled = enabled; +} + +/*! Adds a default \a animation to be considered for any transition. */ void QStateMachine::addDefaultAnimation(QAbstractAnimation *animation) diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h index 9a7a6fc..3ad215b 100644 --- a/src/corelib/statemachine/qstatemachine.h +++ b/src/corelib/statemachine/qstatemachine.h @@ -74,6 +74,9 @@ class Q_CORE_EXPORT QStateMachine : public QObject Q_PROPERTY(QString errorString READ errorString) Q_PROPERTY(RestorePolicy globalRestorePolicy READ globalRestorePolicy WRITE setGlobalRestorePolicy) Q_ENUMS(RestorePolicy) +#ifndef QT_NO_ANIMATION + Q_PROPERTY(bool animationsEnabled READ animationsEnabled WRITE setAnimationsEnabled) +#endif public: enum RestorePolicy { DoNotRestoreProperties, @@ -105,6 +108,9 @@ public: void clearError(); #ifndef QT_NO_ANIMATION + bool animationsEnabled() const; + void setAnimationsEnabled(bool enabled); + void addDefaultAnimation(QAbstractAnimation *animation); QList defaultAnimations() const; void removeDefaultAnimation(QAbstractAnimation *animation); diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index 323473d..bb58edc 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -179,6 +179,8 @@ public: QAbstractState *initialErrorStateForRoot; #ifndef QT_NO_ANIMATION + bool animationsEnabled; + QPair, QList > initializeAnimation(QAbstractAnimation *abstractAnimation, const QPropertyAssignment &prop); -- cgit v0.12 From 2c22f8748f62db3cd4c2782abcd19c273f4a4426 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Tue, 28 Apr 2009 14:05:15 +0200 Subject: say hello (again) to QAbstract{State,Transition}::machine() It's useful and it's simple for us to expose, so let's. --- examples/statemachine/clockticking/main.cpp | 24 ++++++------------ examples/statemachine/pingpong/main.cpp | 31 ++++++++---------------- src/corelib/statemachine/qabstractstate.cpp | 13 +++++++++- src/corelib/statemachine/qabstractstate.h | 2 ++ src/corelib/statemachine/qabstracttransition.cpp | 13 +++++++++- src/corelib/statemachine/qabstracttransition.h | 3 +++ 6 files changed, 47 insertions(+), 39 deletions(-) diff --git a/examples/statemachine/clockticking/main.cpp b/examples/statemachine/clockticking/main.cpp index 5501e2c..301060b 100644 --- a/examples/statemachine/clockticking/main.cpp +++ b/examples/statemachine/clockticking/main.cpp @@ -57,25 +57,21 @@ public: class ClockState : public QState { public: - ClockState(QStateMachine *machine, QState *parent) - : QState(parent), m_machine(machine) {} + ClockState(QState *parent) + : QState(parent) {} protected: virtual void onEntry() { fprintf(stdout, "ClockState entered; posting the initial tick\n"); - m_machine->postEvent(new ClockEvent()); + machine()->postEvent(new ClockEvent()); } - -private: - QStateMachine *m_machine; }; class ClockTransition : public QAbstractTransition { public: - ClockTransition(QStateMachine *machine) - : QAbstractTransition(), m_machine(machine) { } + ClockTransition() {} protected: virtual bool eventTest(QEvent *e) const { @@ -84,18 +80,14 @@ protected: virtual void onTransition() { fprintf(stdout, "ClockTransition triggered; posting another tick with a delay of 1 second\n"); - m_machine->postEvent(new ClockEvent(), 1000); + machine()->postEvent(new ClockEvent(), 1000); } - -private: - QStateMachine *m_machine; }; class ClockListener : public QAbstractTransition { public: - ClockListener() - : QAbstractTransition() {} + ClockListener() {} protected: virtual bool eventTest(QEvent *e) const { @@ -115,9 +107,9 @@ int main(int argc, char **argv) QState *group = new QState(QState::ParallelGroup); group->setObjectName("group"); - ClockState *clock = new ClockState(&machine, group); + ClockState *clock = new ClockState(group); clock->setObjectName("clock"); - clock->addTransition(new ClockTransition(&machine)); + clock->addTransition(new ClockTransition()); QState *listener = new QState(group); listener->setObjectName("listener"); diff --git a/examples/statemachine/pingpong/main.cpp b/examples/statemachine/pingpong/main.cpp index 00ff643..ec1ebf2 100644 --- a/examples/statemachine/pingpong/main.cpp +++ b/examples/statemachine/pingpong/main.cpp @@ -64,25 +64,21 @@ public: class Pinger : public QState { public: - Pinger(QStateMachine *machine, QState *parent) - : QState(parent), m_machine(machine) {} + Pinger(QState *parent) + : QState(parent) {} protected: virtual void onEntry() { - m_machine->postEvent(new PingEvent()); + machine()->postEvent(new PingEvent()); fprintf(stdout, "ping?\n"); } - -private: - QStateMachine *m_machine; }; class PongTransition : public QAbstractTransition { public: - PongTransition(QStateMachine *machine) - : QAbstractTransition(), m_machine(machine) {} + PongTransition() {} protected: virtual bool eventTest(QEvent *e) const { @@ -90,19 +86,15 @@ protected: } virtual void onTransition() { - m_machine->postEvent(new PingEvent(), 500); + machine()->postEvent(new PingEvent(), 500); fprintf(stdout, "ping?\n"); } - -private: - QStateMachine *m_machine; }; class PingTransition : public QAbstractTransition { public: - PingTransition(QStateMachine *machine) - : QAbstractTransition(), m_machine(machine) {} + PingTransition() {} protected: virtual bool eventTest(QEvent *e) const { @@ -110,12 +102,9 @@ protected: } virtual void onTransition() { - m_machine->postEvent(new PongEvent(), 500); + machine()->postEvent(new PongEvent(), 500); fprintf(stdout, "pong!\n"); } - -private: - QStateMachine *m_machine; }; int main(int argc, char **argv) @@ -126,13 +115,13 @@ int main(int argc, char **argv) QState *group = new QState(QState::ParallelGroup); group->setObjectName("group"); - Pinger *pinger = new Pinger(&machine, group); + Pinger *pinger = new Pinger(group); pinger->setObjectName("pinger"); - pinger->addTransition(new PongTransition(&machine)); + pinger->addTransition(new PongTransition()); QState *ponger = new QState(group); ponger->setObjectName("ponger"); - ponger->addTransition(new PingTransition(&machine)); + ponger->addTransition(new PingTransition()); machine.addState(group); machine.setInitialState(group); diff --git a/src/corelib/statemachine/qabstractstate.cpp b/src/corelib/statemachine/qabstractstate.cpp index 12f14d7..cc6f0f9 100644 --- a/src/corelib/statemachine/qabstractstate.cpp +++ b/src/corelib/statemachine/qabstractstate.cpp @@ -63,7 +63,8 @@ QT_BEGIN_NAMESPACE The entered() signal is emitted when the state has been entered. The exited() signal is emitted when the state has been exited. - The parentState() function returns the state's parent state. + The parentState() function returns the state's parent state. The machine() + function returns the state machine that the state is part of. \section1 Subclassing @@ -179,6 +180,16 @@ QState *QAbstractState::parentState() const } /*! + Returns the state machine that this state is part of, or 0 if the state is + not part of a state machine. +*/ +QStateMachine *QAbstractState::machine() const +{ + Q_D(const QAbstractState); + return d->machine(); +} + +/*! \fn QAbstractState::onExit() This function is called when the state is exited. Reimplement this function diff --git a/src/corelib/statemachine/qabstractstate.h b/src/corelib/statemachine/qabstractstate.h index a5f1440..30a68ff 100644 --- a/src/corelib/statemachine/qabstractstate.h +++ b/src/corelib/statemachine/qabstractstate.h @@ -51,6 +51,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Core) class QState; +class QStateMachine; class QAbstractStatePrivate; class Q_CORE_EXPORT QAbstractState : public QObject @@ -60,6 +61,7 @@ public: ~QAbstractState(); QState *parentState() const; + QStateMachine *machine() const; Q_SIGNALS: void entered(); diff --git a/src/corelib/statemachine/qabstracttransition.cpp b/src/corelib/statemachine/qabstracttransition.cpp index dfce310..731871c 100644 --- a/src/corelib/statemachine/qabstracttransition.cpp +++ b/src/corelib/statemachine/qabstracttransition.cpp @@ -61,7 +61,8 @@ QT_BEGIN_NAMESPACE Framework}. The sourceState() function returns the source of the transition. The - targetStates() function returns the targets of the transition. + targetStates() function returns the targets of the transition. The machine() + function returns the state machine that the transition is part of. Transitions can cause animations to be played. Use the addAnimation() function to add an animation to the transition. @@ -286,6 +287,16 @@ void QAbstractTransition::setTargetStates(const QList &targets) d->targetStates = targets; } +/*! + Returns the state machine that this transition is part of, or 0 if the + transition is not part of a state machine. +*/ +QStateMachine *QAbstractTransition::machine() const +{ + Q_D(const QAbstractTransition); + return d->machine(); +} + #ifndef QT_NO_ANIMATION /*! diff --git a/src/corelib/statemachine/qabstracttransition.h b/src/corelib/statemachine/qabstracttransition.h index c49731f..37365c5 100644 --- a/src/corelib/statemachine/qabstracttransition.h +++ b/src/corelib/statemachine/qabstracttransition.h @@ -55,6 +55,7 @@ QT_MODULE(Core) class QEvent; class QAbstractState; class QState; +class QStateMachine; #ifndef QT_NO_ANIMATION class QAbstractAnimation; @@ -78,6 +79,8 @@ public: QList targetStates() const; void setTargetStates(const QList &targets); + QStateMachine *machine() const; + #ifndef QT_NO_ANIMATION void addAnimation(QAbstractAnimation *animation); void removeAnimation(QAbstractAnimation *animation); -- cgit v0.12 From f810a0210c0cdd1ba070f16ebebdec1da7c72b50 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 29 Apr 2009 08:25:03 +0200 Subject: make history state constructible Decided in API review. The intention of QHistoryState not being constructible was so that people wouldn't subclass it and reimplement onEntry()/onExit(), thinking that those functions would actually get called (which they won't). However, we recently added the entered() signal to QAbstractState, so people are going to connect to it and ask why they never get the signal for a QHistoryState. We might as well make QHistoryState constructible and just document that it doesn't make sense to subclass it. --- examples/animation/sub-attaq/boat.cpp | 2 +- examples/statemachine/pauseandresume/main.cpp | 2 +- src/corelib/statemachine/qhistorystate.cpp | 64 ++++++++++++++++++++++---- src/corelib/statemachine/qhistorystate.h | 21 ++++++--- src/corelib/statemachine/qhistorystate_p.h | 5 +- src/corelib/statemachine/qstate.cpp | 26 ----------- src/corelib/statemachine/qstate.h | 7 --- src/corelib/statemachine/qstatemachine.cpp | 6 +-- tests/auto/qstatemachine/tst_qstatemachine.cpp | 4 +- 9 files changed, 78 insertions(+), 59 deletions(-) diff --git a/examples/animation/sub-attaq/boat.cpp b/examples/animation/sub-attaq/boat.cpp index 5721485..f01f1bb 100644 --- a/examples/animation/sub-attaq/boat.cpp +++ b/examples/animation/sub-attaq/boat.cpp @@ -200,7 +200,7 @@ Boat::Boat(QGraphicsItem * parent, Qt::WindowFlags wFlags) stopState->addTransition(downFireMove); //Finally the launch state should come back to its original state - QHistoryState *historyState = moving->addHistoryState(); + QHistoryState *historyState = new QHistoryState(moving); launchStateLeft->addTransition(historyState); launchStateRight->addTransition(historyState); diff --git a/examples/statemachine/pauseandresume/main.cpp b/examples/statemachine/pauseandresume/main.cpp index e0ebbff..5bacb41 100644 --- a/examples/statemachine/pauseandresume/main.cpp +++ b/examples/statemachine/pauseandresume/main.cpp @@ -73,7 +73,7 @@ public: s1->addTransition(pb, SIGNAL(clicked()), s2); s2->addTransition(pb, SIGNAL(clicked()), s1); - QHistoryState *h = process->addHistoryState(); + QHistoryState *h = new QHistoryState(process); h->setDefaultState(s1); QState *interrupted = new QState(machine->rootState()); diff --git a/src/corelib/statemachine/qhistorystate.cpp b/src/corelib/statemachine/qhistorystate.cpp index 8143d41..4e3db08 100644 --- a/src/corelib/statemachine/qhistorystate.cpp +++ b/src/corelib/statemachine/qhistorystate.cpp @@ -85,17 +85,38 @@ QT_BEGIN_NAMESPACE \endcode */ +/*! + \property QHistoryState::defaultState + + \brief the default state of this history state +*/ + +/*! + \property QHistoryState::historyType + + \brief the type of history that this history state records +*/ + +/*! + \enum QHistoryState::HistoryType + + This enum specifies the type of history that a QHistoryState records. + + \value ShallowHistory Only the immediate child states of the parent state + are recorded. In this case a transition with the history state as its + target will end up in the immediate child state that the parent was in the + last time it was exited. This is the default. + + \value DeepHistory Nested states are recorded. In this case a transition + with the history state as its target will end up in the most deeply nested + descendant state the parent was in the last time it was exited. +*/ + QHistoryStatePrivate::QHistoryStatePrivate() : defaultState(0) { } -QHistoryState *QHistoryStatePrivate::create(QState::HistoryType type, - QState *parent) -{ - return new QHistoryState(type, parent); -} - QHistoryStatePrivate *QHistoryStatePrivate::get(QHistoryState *q) { return q->d_func(); @@ -107,12 +128,19 @@ const QHistoryStatePrivate *QHistoryStatePrivate::get(const QHistoryState *q) } /*! - \internal - + Constructs a new shallow history state with the given \a parent state. +*/ +QHistoryState::QHistoryState(QState *parent) + : QAbstractState(*new QHistoryStatePrivate, parent) +{ + Q_D(QHistoryState); + d->historyType = ShallowHistory; +} +/*! Constructs a new history state of the given \a type, with the given \a parent state. */ -QHistoryState::QHistoryState(QState::HistoryType type, QState *parent) +QHistoryState::QHistoryState(HistoryType type, QState *parent) : QAbstractState(*new QHistoryStatePrivate, parent) { Q_D(QHistoryState); @@ -152,6 +180,24 @@ void QHistoryState::setDefaultState(QAbstractState *state) } /*! + Returns the type of history that this history state records. +*/ +QHistoryState::HistoryType QHistoryState::historyType() const +{ + Q_D(const QHistoryState); + return d->historyType; +} + +/*! + Sets the \a type of history that this history state records. +*/ +void QHistoryState::setHistoryType(HistoryType type) +{ + Q_D(QHistoryState); + d->historyType = type; +} + +/*! \reimp */ void QHistoryState::onEntry() diff --git a/src/corelib/statemachine/qhistorystate.h b/src/corelib/statemachine/qhistorystate.h index 9cd7f0b..c7648bc 100644 --- a/src/corelib/statemachine/qhistorystate.h +++ b/src/corelib/statemachine/qhistorystate.h @@ -43,9 +43,9 @@ #define QHISTORYSTATE_H #ifndef QT_STATEMACHINE_SOLUTION -#include +#include #else -#include "qstate.h" +#include "qabstractstate.h" #endif QT_BEGIN_HEADER @@ -58,12 +58,25 @@ class QHistoryStatePrivate; class Q_CORE_EXPORT QHistoryState : public QAbstractState { Q_OBJECT + Q_PROPERTY(QAbstractState* defaultState READ defaultState WRITE setDefaultState) + Q_PROPERTY(HistoryType historyType READ historyType WRITE setHistoryType) + Q_ENUMS(HistoryType) public: + enum HistoryType { + ShallowHistory, + DeepHistory + }; + + QHistoryState(QState *parent = 0); + QHistoryState(HistoryType type, QState *parent = 0); ~QHistoryState(); QAbstractState *defaultState() const; void setDefaultState(QAbstractState *state); + HistoryType historyType() const; + void setHistoryType(HistoryType type); + protected: void onEntry(); void onExit(); @@ -71,10 +84,6 @@ protected: bool event(QEvent *e); private: - QHistoryState(QState::HistoryType type, - QState *parent = 0); - -private: Q_DISABLE_COPY(QHistoryState) Q_DECLARE_PRIVATE(QHistoryState) }; diff --git a/src/corelib/statemachine/qhistorystate_p.h b/src/corelib/statemachine/qhistorystate_p.h index 84648b5..2f17496 100644 --- a/src/corelib/statemachine/qhistorystate_p.h +++ b/src/corelib/statemachine/qhistorystate_p.h @@ -67,14 +67,11 @@ class QHistoryStatePrivate : public QAbstractStatePrivate public: QHistoryStatePrivate(); - static QHistoryState *create(QState::HistoryType type, - QState *parent); - static QHistoryStatePrivate *get(QHistoryState *q); static const QHistoryStatePrivate *get(const QHistoryState *q); QAbstractState *defaultState; - QState::HistoryType historyType; + QHistoryState::HistoryType historyType; QList configuration; }; diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp index 5c3418b..dd3af51 100644 --- a/src/corelib/statemachine/qstate.cpp +++ b/src/corelib/statemachine/qstate.cpp @@ -75,8 +75,6 @@ QT_BEGIN_NAMESPACE and the state machine needs to know which child state to enter when the parent state is the target of a transition. - The addHistoryState() function adds a history state. - The setErrorState() sets the state's error state. The error state is the state that the state machine will transition to if an error is detected when attempting to enter the state (e.g. because no initial state has been set). @@ -95,21 +93,6 @@ QT_BEGIN_NAMESPACE group state is entered, all its child states are entered in parallel. */ -/*! - \enum QState::HistoryType - - This enum specifies the type of history that a QHistoryState records. - - \value ShallowHistory Only the immediate child states of the parent state - are recorded. In this case a transition with the history state as its - target will end up in the immediate child state that the parent was in the - last time it was exited. This is the default. - - \value DeepHistory Nested states are recorded. In this case a transition - with the history state as its target will end up in the most deeply nested - descendant state the parent was in the last time it was exited. -*/ - QStatePrivate::QStatePrivate() : errorState(0), isParallelGroup(false), initialState(0) { @@ -381,15 +364,6 @@ QList QState::transitions() const } /*! - Creates a history state of the given \a type for this state and returns the - new state. The history state becomes a child of this state. -*/ -QHistoryState *QState::addHistoryState(HistoryType type) -{ - return QHistoryStatePrivate::create(type, this); -} - -/*! \reimp */ void QState::onEntry() diff --git a/src/corelib/statemachine/qstate.h b/src/corelib/statemachine/qstate.h index 0dd99dc..33f0709 100644 --- a/src/corelib/statemachine/qstate.h +++ b/src/corelib/statemachine/qstate.h @@ -68,11 +68,6 @@ public: ParallelGroup }; - enum HistoryType { - ShallowHistory, - DeepHistory - }; - QState(QState *parent = 0); QState(Type type, QState *parent = 0); ~QState(); @@ -86,8 +81,6 @@ public: void removeTransition(QAbstractTransition *transition); QList transitions() const; - QHistoryState *addHistoryState(HistoryType type = ShallowHistory); - QAbstractState *initialState() const; void setInitialState(QAbstractState *state); diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 8d5317a..1ee526a 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -415,7 +415,7 @@ QList QStateMachinePrivate::exitStates(const QList::const_iterator it; for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) { QAbstractState *s0 = *it; - if (QHistoryStatePrivate::get(h)->historyType == QState::DeepHistory) { + if (QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) { if (isAtomic(s0) && isDescendantOf(s0, s)) QHistoryStatePrivate::get(h)->configuration.append(s0); } else if (s0->parentState() == s) { @@ -423,7 +423,7 @@ QList QStateMachinePrivate::exitStates(const QListhistoryType == QState::DeepHistory) ? "deep" : "shallow") + qDebug() << q_func() << ": recorded" << ((QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) ? "deep" : "shallow") << "history for" << s << "in" << h << ":" << QHistoryStatePrivate::get(h)->configuration; #endif } @@ -479,7 +479,7 @@ QList QStateMachinePrivate::enterStates(const QListhistoryType == QState::DeepHistory) ? "deep" : "shallow") + << ((QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) ? "deep" : "shallow") << "history from" << s << ":" << hconf; #endif } else { diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index db25ad5..1c5f52b 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -823,7 +823,7 @@ void tst_QStateMachine::historyStateHasNowhereToGo() brokenState->setObjectName("brokenState"); brokenState->setInitialState(new QState(brokenState)); - QHistoryState *historyState = brokenState->addHistoryState(); + QHistoryState *historyState = new QHistoryState(brokenState); historyState->setObjectName("historyState"); initialState->addTransition(new EventTransition(QEvent::User, historyState)); @@ -1587,7 +1587,7 @@ void tst_QStateMachine::historyStates() QState *s0 = new QState(root); QState *s00 = new QState(s0); QState *s01 = new QState(s0); - QHistoryState *s0h = s0->addHistoryState(); + QHistoryState *s0h = new QHistoryState(s0); QState *s1 = new QState(root); QFinalState *s2 = new QFinalState(root); -- cgit v0.12 From 419bdc6bdcd80d7a7858e93d2e4b6dc3ac5fc47a Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 29 Apr 2009 10:27:12 +0200 Subject: kill unnecessary qmake variable mods --- src/gui/statemachine/statemachine.pri | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/gui/statemachine/statemachine.pri b/src/gui/statemachine/statemachine.pri index 24de458..2eb1e05 100644 --- a/src/gui/statemachine/statemachine.pri +++ b/src/gui/statemachine/statemachine.pri @@ -1,6 +1,3 @@ -INCLUDEPATH += $$PWD -DEPENDPATH += $$PWD - SOURCES += $$PWD/qguistatemachine.cpp !contains(DEFINES, QT_NO_STATEMACHINE_EVENTFILTER) { HEADERS += \ -- cgit v0.12 From f39a905bc75e7ce95294f3584ea8a400ab383861 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 29 Apr 2009 10:29:57 +0200 Subject: compile --- src/corelib/statemachine/qstatemachine_p.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index bb58edc..139fee8 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -62,6 +62,7 @@ #include #include +#include "qstate.h" #include "qstate_p.h" QT_BEGIN_NAMESPACE -- cgit v0.12 From 58b74319a639cb471cdec92c0e8a054fc6d4d5f5 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 29 Apr 2009 10:54:10 +0200 Subject: modifiers --> modifiersMask Result of API review. A == comparison of the modifiers is not useful. The common case is you want to test if one or more modifiers are set, i.e. a mask check. --- examples/animation/sub-attaq/boat_p.h | 9 ------ src/gui/statemachine/qbasickeyeventtransition.cpp | 27 ++++++++++-------- src/gui/statemachine/qbasickeyeventtransition_p.h | 7 +++-- .../statemachine/qbasicmouseeventtransition.cpp | 22 +++++++++++++++ .../statemachine/qbasicmouseeventtransition_p.h | 3 ++ src/gui/statemachine/qkeyeventtransition.cpp | 21 +++++++++----- src/gui/statemachine/qkeyeventtransition.h | 5 ++-- src/gui/statemachine/qmouseeventtransition.cpp | 32 ++++++++++++++++++++++ src/gui/statemachine/qmouseeventtransition.h | 5 ++++ 9 files changed, 98 insertions(+), 33 deletions(-) diff --git a/examples/animation/sub-attaq/boat_p.h b/examples/animation/sub-attaq/boat_p.h index 8dacaba..ff69335 100644 --- a/examples/animation/sub-attaq/boat_p.h +++ b/examples/animation/sub-attaq/boat_p.h @@ -65,9 +65,6 @@ public: { this->boat = boat; this->key = key; -#if defined(Q_OS_MAC) - setModifiers(Qt::KeypadModifier); -#endif } protected: virtual bool eventTest(QEvent *event) const @@ -94,9 +91,6 @@ public: { this->boat = boat; this->key = key; -#if defined(Q_OS_MAC) - setModifiers(Qt::KeypadModifier); -#endif } protected: virtual bool eventTest(QEvent *event) const @@ -135,9 +129,6 @@ public: { this->boat = boat; this->key = key; -#if defined(Q_OS_MAC) - setModifiers(Qt::KeypadModifier); -#endif } protected: virtual bool eventTest(QEvent *event) const diff --git a/src/gui/statemachine/qbasickeyeventtransition.cpp b/src/gui/statemachine/qbasickeyeventtransition.cpp index 2ce428c..4e3fa11 100644 --- a/src/gui/statemachine/qbasickeyeventtransition.cpp +++ b/src/gui/statemachine/qbasickeyeventtransition.cpp @@ -39,14 +39,14 @@ public: QEvent::Type eventType; int key; - Qt::KeyboardModifiers modifiers; + Qt::KeyboardModifiers modifiersMask; }; QBasicKeyEventTransitionPrivate::QBasicKeyEventTransitionPrivate() { eventType = QEvent::None; key = 0; - modifiers = Qt::NoModifier; + modifiersMask = Qt::NoModifier; } QBasicKeyEventTransitionPrivate *QBasicKeyEventTransitionPrivate::get(QBasicKeyEventTransition *q) @@ -77,17 +77,17 @@ QBasicKeyEventTransition::QBasicKeyEventTransition(QEvent::Type type, int key, /*! Constructs a new event transition for events of the given \a type for the - given \a key, with the given \a modifiers and \a sourceState. + given \a key, with the given \a modifiersMask and \a sourceState. */ QBasicKeyEventTransition::QBasicKeyEventTransition(QEvent::Type type, int key, - Qt::KeyboardModifiers modifiers, + Qt::KeyboardModifiers modifiersMask, QState *sourceState) : QAbstractTransition(*new QBasicKeyEventTransitionPrivate, sourceState) { Q_D(QBasicKeyEventTransition); d->eventType = type; d->key = key; - d->modifiers = modifiers; + d->modifiersMask = modifiersMask; } /*! @@ -134,21 +134,23 @@ void QBasicKeyEventTransition::setKey(int key) } /*! - Returns the keyboard modifiers that this key event transition checks for. + Returns the keyboard modifiers mask that this key event transition checks + for. */ -Qt::KeyboardModifiers QBasicKeyEventTransition::modifiers() const +Qt::KeyboardModifiers QBasicKeyEventTransition::modifiersMask() const { Q_D(const QBasicKeyEventTransition); - return d->modifiers; + return d->modifiersMask; } /*! - Sets the keyboard modifiers that this key event transition will check for. + Sets the keyboard modifiers mask that this key event transition will check + for. */ -void QBasicKeyEventTransition::setModifiers(Qt::KeyboardModifiers modifiers) +void QBasicKeyEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask) { Q_D(QBasicKeyEventTransition); - d->modifiers = modifiers; + d->modifiersMask = modifiersMask; } /*! @@ -159,7 +161,8 @@ bool QBasicKeyEventTransition::eventTest(QEvent *event) const Q_D(const QBasicKeyEventTransition); if (event->type() == d->eventType) { QKeyEvent *ke = static_cast(event); - return (ke->key() == d->key) && (ke->modifiers() == d->modifiers); + return (ke->key() == d->key) + && ((ke->modifiers() & d->modifiersMask) == d->modifiersMask); } return false; } diff --git a/src/gui/statemachine/qbasickeyeventtransition_p.h b/src/gui/statemachine/qbasickeyeventtransition_p.h index ff52f4d..de49eac 100644 --- a/src/gui/statemachine/qbasickeyeventtransition_p.h +++ b/src/gui/statemachine/qbasickeyeventtransition_p.h @@ -41,7 +41,8 @@ public: QBasicKeyEventTransition(QState *sourceState = 0); QBasicKeyEventTransition(QEvent::Type type, int key, QState *sourceState = 0); QBasicKeyEventTransition(QEvent::Type type, int key, - Qt::KeyboardModifiers modifiers, QState *sourceState = 0); + Qt::KeyboardModifiers modifiersMask, + QState *sourceState = 0); ~QBasicKeyEventTransition(); QEvent::Type eventType() const; @@ -50,8 +51,8 @@ public: int key() const; void setKey(int key); - Qt::KeyboardModifiers modifiers() const; - void setModifiers(Qt::KeyboardModifiers modifiers); + Qt::KeyboardModifiers modifiersMask() const; + void setModifiersMask(Qt::KeyboardModifiers modifiers); protected: bool eventTest(QEvent *event) const; diff --git a/src/gui/statemachine/qbasicmouseeventtransition.cpp b/src/gui/statemachine/qbasicmouseeventtransition.cpp index b7583f8..83254dc 100644 --- a/src/gui/statemachine/qbasicmouseeventtransition.cpp +++ b/src/gui/statemachine/qbasicmouseeventtransition.cpp @@ -39,6 +39,7 @@ public: QEvent::Type eventType; Qt::MouseButton button; + Qt::KeyboardModifiers modifiersMask; QPainterPath path; }; @@ -118,6 +119,26 @@ void QBasicMouseEventTransition::setButton(Qt::MouseButton button) } /*! + Returns the keyboard modifiers mask that this mouse event transition checks + for. +*/ +Qt::KeyboardModifiers QBasicMouseEventTransition::modifiersMask() const +{ + Q_D(const QBasicMouseEventTransition); + return d->modifiersMask; +} + +/*! + Sets the keyboard modifiers mask that this mouse event transition will check + for. +*/ +void QBasicMouseEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask) +{ + Q_D(QBasicMouseEventTransition); + d->modifiersMask = modifiersMask; +} + +/*! Returns the path for this mouse event transition. */ QPainterPath QBasicMouseEventTransition::path() const @@ -144,6 +165,7 @@ bool QBasicMouseEventTransition::eventTest(QEvent *event) const if (event->type() == d->eventType) { QMouseEvent *me = static_cast(event); return (me->button() == d->button) + && ((me->modifiers() & d->modifiersMask) == d->modifiersMask) && (d->path.isEmpty() || d->path.contains(me->pos())); } return false; diff --git a/src/gui/statemachine/qbasicmouseeventtransition_p.h b/src/gui/statemachine/qbasicmouseeventtransition_p.h index ee04fc7..77fbd58 100644 --- a/src/gui/statemachine/qbasicmouseeventtransition_p.h +++ b/src/gui/statemachine/qbasicmouseeventtransition_p.h @@ -51,6 +51,9 @@ public: Qt::MouseButton button() const; void setButton(Qt::MouseButton button); + Qt::KeyboardModifiers modifiersMask() const; + void setModifiersMask(Qt::KeyboardModifiers modifiers); + QPainterPath path() const; void setPath(const QPainterPath &path); diff --git a/src/gui/statemachine/qkeyeventtransition.cpp b/src/gui/statemachine/qkeyeventtransition.cpp index 88e4add..7c1ae8a 100644 --- a/src/gui/statemachine/qkeyeventtransition.cpp +++ b/src/gui/statemachine/qkeyeventtransition.cpp @@ -39,6 +39,12 @@ QT_BEGIN_NAMESPACE \brief the key that this key event transition is associated with */ +/*! + \property QKeyEventTransition::modifiersMask + + \brief the keyboard modifiers mask that this key event transition checks for +*/ + class QKeyEventTransitionPrivate : public QEventTransitionPrivate { Q_DECLARE_PUBLIC(QKeyEventTransition) @@ -111,22 +117,23 @@ void QKeyEventTransition::setKey(int key) } /*! - Returns the keyboard modifiers that this key event transition checks for. + Returns the keyboard modifiers mask that this key event transition checks + for. */ -Qt::KeyboardModifiers QKeyEventTransition::modifiers() const +Qt::KeyboardModifiers QKeyEventTransition::modifiersMask() const { Q_D(const QKeyEventTransition); - return d->transition->modifiers(); + return d->transition->modifiersMask(); } /*! - Sets the keyboard \a modifiers that this key event transition will check - for. + Sets the keyboard \a modifiers mask that this key event transition will + check for. */ -void QKeyEventTransition::setModifiers(Qt::KeyboardModifiers modifiers) +void QKeyEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask) { Q_D(QKeyEventTransition); - d->transition->setModifiers(modifiers); + d->transition->setModifiersMask(modifiersMask); } /*! diff --git a/src/gui/statemachine/qkeyeventtransition.h b/src/gui/statemachine/qkeyeventtransition.h index 5bae8d7..ef814db 100644 --- a/src/gui/statemachine/qkeyeventtransition.h +++ b/src/gui/statemachine/qkeyeventtransition.h @@ -28,6 +28,7 @@ class Q_GUI_EXPORT QKeyEventTransition : public QEventTransition { Q_OBJECT Q_PROPERTY(int key READ key WRITE setKey) + Q_PROPERTY(Qt::KeyboardModifiers modifiersMask READ modifiersMask WRITE setModifiersMask) public: QKeyEventTransition(QState *sourceState = 0); QKeyEventTransition(QObject *object, QEvent::Type type, int key, @@ -40,8 +41,8 @@ public: int key() const; void setKey(int key); - Qt::KeyboardModifiers modifiers() const; - void setModifiers(Qt::KeyboardModifiers modifiers); + Qt::KeyboardModifiers modifiersMask() const; + void setModifiersMask(Qt::KeyboardModifiers modifiers); protected: void onTransition(); diff --git a/src/gui/statemachine/qmouseeventtransition.cpp b/src/gui/statemachine/qmouseeventtransition.cpp index f5df904..d6d9b62 100644 --- a/src/gui/statemachine/qmouseeventtransition.cpp +++ b/src/gui/statemachine/qmouseeventtransition.cpp @@ -34,6 +34,18 @@ QT_BEGIN_NAMESPACE \sa QState::addTransition() */ +/*! + \property QMouseEventTransition::button + + \brief the button that this mouse event transition is associated with +*/ + +/*! + \property QMouseEventTransition::modifiersMask + + \brief the keyboard modifiers mask that this mouse event transition checks for +*/ + class QMouseEventTransitionPrivate : public QEventTransitionPrivate { Q_DECLARE_PUBLIC(QMouseEventTransition) @@ -113,6 +125,26 @@ void QMouseEventTransition::setButton(Qt::MouseButton button) } /*! + Returns the keyboard modifiers mask that this mouse event transition checks + for. +*/ +Qt::KeyboardModifiers QMouseEventTransition::modifiersMask() const +{ + Q_D(const QMouseEventTransition); + return d->transition->modifiersMask(); +} + +/*! + Sets the keyboard \a modifiers mask that this mouse event transition will + check for. +*/ +void QMouseEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask) +{ + Q_D(QMouseEventTransition); + d->transition->setModifiersMask(modifiersMask); +} + +/*! Returns the path for this mouse event transition. */ QPainterPath QMouseEventTransition::path() const diff --git a/src/gui/statemachine/qmouseeventtransition.h b/src/gui/statemachine/qmouseeventtransition.h index 162b1b5..dbd615f 100644 --- a/src/gui/statemachine/qmouseeventtransition.h +++ b/src/gui/statemachine/qmouseeventtransition.h @@ -29,6 +29,8 @@ class QPainterPath; class Q_GUI_EXPORT QMouseEventTransition : public QEventTransition { Q_OBJECT + Q_PROPERTY(Qt::MouseButton button READ button WRITE setButton) + Q_PROPERTY(Qt::KeyboardModifiers modifiersMask READ modifiersMask WRITE setModifiersMask) public: QMouseEventTransition(QState *sourceState = 0); QMouseEventTransition(QObject *object, QEvent::Type type, @@ -42,6 +44,9 @@ public: Qt::MouseButton button() const; void setButton(Qt::MouseButton button); + Qt::KeyboardModifiers modifiersMask() const; + void setModifiersMask(Qt::KeyboardModifiers modifiers); + QPainterPath path() const; void setPath(const QPainterPath &path); -- cgit v0.12 From a7c2eff47c5ad3e98ca5505b64cdbba716cbedbd Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 29 Apr 2009 11:05:03 +0200 Subject: rename a few properties and methods Result of API review. --- src/corelib/statemachine/qabstracttransition.cpp | 6 +++--- src/corelib/statemachine/qabstracttransition.h | 6 +++--- src/corelib/statemachine/qeventtransition.cpp | 6 +++--- src/corelib/statemachine/qeventtransition.h | 6 +++--- src/corelib/statemachine/qsignaltransition.cpp | 2 +- src/corelib/statemachine/qsignaltransition.h | 2 +- tests/auto/qstatemachine/tst_qstatemachine.cpp | 14 +++++++------- 7 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/corelib/statemachine/qabstracttransition.cpp b/src/corelib/statemachine/qabstracttransition.cpp index 731871c..5fa1742 100644 --- a/src/corelib/statemachine/qabstracttransition.cpp +++ b/src/corelib/statemachine/qabstracttransition.cpp @@ -79,19 +79,19 @@ QT_BEGIN_NAMESPACE */ /*! - \property QAbstractTransition::source + \property QAbstractTransition::sourceState \brief the source state (parent) of this transition */ /*! - \property QAbstractTransition::target + \property QAbstractTransition::targetState \brief the target state of this transition */ /*! - \property QAbstractTransition::targets + \property QAbstractTransition::targetStates \brief the target states of this transition diff --git a/src/corelib/statemachine/qabstracttransition.h b/src/corelib/statemachine/qabstracttransition.h index 37365c5..79ab808 100644 --- a/src/corelib/statemachine/qabstracttransition.h +++ b/src/corelib/statemachine/qabstracttransition.h @@ -65,9 +65,9 @@ class QAbstractTransitionPrivate; class Q_CORE_EXPORT QAbstractTransition : public QObject { Q_OBJECT - Q_PROPERTY(QState* source READ sourceState) - Q_PROPERTY(QAbstractState* target READ targetState WRITE setTargetState) - Q_PROPERTY(QList targets READ targetStates WRITE setTargetStates) + Q_PROPERTY(QState* sourceState READ sourceState) + Q_PROPERTY(QAbstractState* targetState READ targetState WRITE setTargetState) + Q_PROPERTY(QList targetStates READ targetStates WRITE setTargetStates) public: QAbstractTransition(QState *sourceState = 0); QAbstractTransition(const QList &targets, QState *sourceState = 0); diff --git a/src/corelib/statemachine/qeventtransition.cpp b/src/corelib/statemachine/qeventtransition.cpp index 09b89f3..2126373 100644 --- a/src/corelib/statemachine/qeventtransition.cpp +++ b/src/corelib/statemachine/qeventtransition.cpp @@ -88,7 +88,7 @@ QT_BEGIN_NAMESPACE */ /*! - \property QEventTransition::object + \property QEventTransition::eventObject \brief the event source that this event transition is associated with */ @@ -229,7 +229,7 @@ void QEventTransition::setEventType(QEvent::Type type) /*! Returns the event source associated with this event transition. */ -QObject *QEventTransition::eventSource() const +QObject *QEventTransition::eventObject() const { Q_D(const QEventTransition); return d->object; @@ -239,7 +239,7 @@ QObject *QEventTransition::eventSource() const Sets the event source associated with this event transition to be the given \a object. */ -void QEventTransition::setEventSource(QObject *object) +void QEventTransition::setEventObject(QObject *object) { Q_D(QEventTransition); if (d->object == object) diff --git a/src/corelib/statemachine/qeventtransition.h b/src/corelib/statemachine/qeventtransition.h index e19b5af..82fcd36 100644 --- a/src/corelib/statemachine/qeventtransition.h +++ b/src/corelib/statemachine/qeventtransition.h @@ -59,7 +59,7 @@ class QEventTransitionPrivate; class Q_CORE_EXPORT QEventTransition : public QAbstractTransition { Q_OBJECT - Q_PROPERTY(QObject* object READ eventSource WRITE setEventSource) + Q_PROPERTY(QObject* eventObject READ eventObject WRITE setEventObject) #ifndef QT_STATEMACHINE_SOLUTION Q_PROPERTY(QEvent::Type eventType READ eventType WRITE setEventType) #endif @@ -70,8 +70,8 @@ public: const QList &targets, QState *sourceState = 0); ~QEventTransition(); - QObject *eventSource() const; - void setEventSource(QObject *object); + QObject *eventObject() const; + void setEventObject(QObject *object); QEvent::Type eventType() const; void setEventType(QEvent::Type type); diff --git a/src/corelib/statemachine/qsignaltransition.cpp b/src/corelib/statemachine/qsignaltransition.cpp index 064ac6e..e9e248f 100644 --- a/src/corelib/statemachine/qsignaltransition.cpp +++ b/src/corelib/statemachine/qsignaltransition.cpp @@ -96,7 +96,7 @@ QT_BEGIN_NAMESPACE */ /*! - \property QSignalTransition::object + \property QSignalTransition::senderObject \brief the sender object that this signal transition is associated with */ diff --git a/src/corelib/statemachine/qsignaltransition.h b/src/corelib/statemachine/qsignaltransition.h index 4df97cf..b8e8fc6 100644 --- a/src/corelib/statemachine/qsignaltransition.h +++ b/src/corelib/statemachine/qsignaltransition.h @@ -58,7 +58,7 @@ class QSignalTransitionPrivate; class Q_CORE_EXPORT QSignalTransition : public QAbstractTransition { Q_OBJECT - Q_PROPERTY(QObject* object READ senderObject WRITE setSenderObject) + Q_PROPERTY(QObject* senderObject READ senderObject WRITE setSenderObject) Q_PROPERTY(QByteArray signal READ signal WRITE setSignal) public: QSignalTransition(QState *sourceState = 0); diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 1c5f52b..89cb51a 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -1487,10 +1487,10 @@ void tst_QStateMachine::eventTransitions() QFinalState *s1 = new QFinalState(machine.rootState()); QEventTransition *trans = new QEventTransition(); - QCOMPARE(trans->eventSource(), (QObject*)0); + QCOMPARE(trans->eventObject(), (QObject*)0); QCOMPARE(trans->eventType(), QEvent::None); - trans->setEventSource(&button); - QCOMPARE(trans->eventSource(), (QObject*)&button); + trans->setEventObject(&button); + QCOMPARE(trans->eventObject(), (QObject*)&button); trans->setEventType(QEvent::MouseButtonPress); QCOMPARE(trans->eventType(), QEvent::MouseButtonPress); trans->setTargetState(s1); @@ -1512,10 +1512,10 @@ void tst_QStateMachine::eventTransitions() QFinalState *s1 = new QFinalState(machine.rootState()); QMouseEventTransition *trans = new QMouseEventTransition(); - QCOMPARE(trans->eventSource(), (QObject*)0); + QCOMPARE(trans->eventObject(), (QObject*)0); QCOMPARE(trans->eventType(), QEvent::None); QCOMPARE(trans->button(), Qt::NoButton); - trans->setEventSource(&button); + trans->setEventObject(&button); trans->setEventType(QEvent::MouseButtonPress); trans->setButton(Qt::LeftButton); trans->setTargetState(s1); @@ -1559,10 +1559,10 @@ void tst_QStateMachine::eventTransitions() QFinalState *s1 = new QFinalState(machine.rootState()); QKeyEventTransition *trans = new QKeyEventTransition(); - QCOMPARE(trans->eventSource(), (QObject*)0); + QCOMPARE(trans->eventObject(), (QObject*)0); QCOMPARE(trans->eventType(), QEvent::None); QCOMPARE(trans->key(), 0); - trans->setEventSource(&button); + trans->setEventObject(&button); trans->setEventType(QEvent::KeyPress); trans->setKey(Qt::Key_A); trans->setTargetState(s1); -- cgit v0.12 From e06c2e150f3607daf45b2ecd14bdcca9aba6208d Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 29 Apr 2009 10:56:47 +0200 Subject: Merge the two queries for entry states to support having history states as the initial state. Done by No'am, integrated by me. --- src/corelib/statemachine/qstatemachine.cpp | 149 +++++++++++++------------ tests/auto/qstatemachine/tst_qstatemachine.cpp | 35 ++++++ 2 files changed, 113 insertions(+), 71 deletions(-) diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 1ee526a..020700e 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -470,36 +470,13 @@ QList QStateMachinePrivate::enterStates(const QList(s)) { - QList hconf = QHistoryStatePrivate::get(h)->configuration; - if (!hconf.isEmpty()) { - for (int k = 0; k < hconf.size(); ++k) { - QAbstractState *s0 = hconf.at(k); - addStatesToEnter(s0, lca, statesToEnter, statesForDefaultEntry); - } -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": restoring" - << ((QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) ? "deep" : "shallow") - << "history from" << s << ":" << hconf; -#endif - } else { - QList hlst; - if (QHistoryStatePrivate::get(h)->defaultState) - hlst.append(QHistoryStatePrivate::get(h)->defaultState); - if (hlst.isEmpty()) { - setError(QStateMachine::NoDefaultStateInHistoryState, h); - } else { - for (int k = 0; k < hlst.size(); ++k) { - QAbstractState *s0 = hlst.at(k); - addStatesToEnter(s0, lca, statesToEnter, statesForDefaultEntry); - } -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": initial history targets for" << s << ":" << hlst; -#endif - } + addStatesToEnter(s, lca, statesToEnter, statesForDefaultEntry); + if (isParallel(lca)) { + QList lcac = QStatePrivate::get(lca)->childStates(); + foreach (QAbstractState* child,lcac) { + if (!statesToEnter.contains(child)) + addStatesToEnter(child,lca,statesToEnter,statesForDefaultEntry); } - } else { - addStatesToEnter(s, lca, statesToEnter, statesForDefaultEntry); } } } @@ -574,48 +551,78 @@ void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root, QSet &statesToEnter, QSet &statesForDefaultEntry) { - statesToEnter.insert(s); - if (isParallel(s)) { - QState *grp = qobject_cast(s); - QList lst = QStatePrivate::get(grp)->childStates(); - for (int i = 0; i < lst.size(); ++i) { - QAbstractState *child = lst.at(i); - addStatesToEnter(child, grp, statesToEnter, statesForDefaultEntry); - } - } else if (isCompound(s)) { - statesForDefaultEntry.insert(s); - QState *grp = qobject_cast(s); - QAbstractState *initial = grp->initialState(); - if (initial != 0) { - addStatesToEnter(initial, grp, statesToEnter, statesForDefaultEntry); - } else { - setError(QStateMachine::NoInitialStateError, grp); - return; - } - } - QList ancs = properAncestors(s, root); - for (int i = 0; i < ancs.size(); ++i) { - QState *anc = ancs.at(i); - if (!anc->parentState()) - continue; - statesToEnter.insert(anc); - if (isParallel(anc)) { - QList lst = QStatePrivate::get(anc)->childStates(); - for (int j = 0; j < lst.size(); ++j) { - QAbstractState *child = lst.at(j); - bool hasDescendantInList = false; - QSet::const_iterator it; - for (it = statesToEnter.constBegin(); it != statesToEnter.constEnd(); ++it) { - if (isDescendantOf(*it, child)) { - hasDescendantInList = true; - break; - } - } - if (!hasDescendantInList) - addStatesToEnter(child, anc, statesToEnter, statesForDefaultEntry); - } - } - } + if (QHistoryState *h = qobject_cast(s)) { + QList hconf = QHistoryStatePrivate::get(h)->configuration; + if (!hconf.isEmpty()) { + for (int k = 0; k < hconf.size(); ++k) { + QAbstractState *s0 = hconf.at(k); + addStatesToEnter(s0, root, statesToEnter, statesForDefaultEntry); + } + #ifdef QSTATEMACHINE_DEBUG + qDebug() <historyType == QHistoryState::DeepHistory) ? "deep" : "shallow") + << "history from" << s << ":" << hconf; + #endif + } else { + QList hlst; + if (QHistoryStatePrivate::get(h)->defaultState) + hlst.append(QHistoryStatePrivate::get(h)->defaultState); + if (hlst.isEmpty()) { + setError(QStateMachine::NoDefaultStateInHistoryState, h); + } else { + for (int k = 0; k < hlst.size(); ++k) { + QAbstractState *s0 = hlst.at(k); + addStatesToEnter(s0, root, statesToEnter, statesForDefaultEntry); + } + #ifdef QSTATEMACHINE_DEBUG + qDebug() << q_func() << ": initial history targets for" << s << ":" << hlst; + #endif + } + } + } else { + statesToEnter.insert(s); + if (isParallel(s)) { + QState *grp = qobject_cast(s); + QList lst = QStatePrivate::get(grp)->childStates(); + for (int i = 0; i < lst.size(); ++i) { + QAbstractState *child = lst.at(i); + addStatesToEnter(child, grp, statesToEnter, statesForDefaultEntry); + } + } else if (isCompound(s)) { + statesForDefaultEntry.insert(s); + QState *grp = qobject_cast(s); + QAbstractState *initial = grp->initialState(); + if (initial != 0) { + addStatesToEnter(initial, grp, statesToEnter, statesForDefaultEntry); + } else { + setError(QStateMachine::NoInitialStateError, grp); + return; + } + } + QList ancs = properAncestors(s, root); + for (int i = 0; i < ancs.size(); ++i) { + QState *anc = ancs.at(i); + if (!anc->parentState()) + continue; + statesToEnter.insert(anc); + if (isParallel(anc)) { + QList lst = QStatePrivate::get(anc)->childStates(); + for (int j = 0; j < lst.size(); ++j) { + QAbstractState *child = lst.at(j); + bool hasDescendantInList = false; + QSet::const_iterator it; + for (it = statesToEnter.constBegin(); it != statesToEnter.constEnd(); ++it) { + if (isDescendantOf(*it, child)) { + hasDescendantInList = true; + break; + } + } + if (!hasDescendantInList) + addStatesToEnter(child, anc, statesToEnter, statesForDefaultEntry); + } + } + } + } } void QStateMachinePrivate::applyProperties(const QList &transitionList, diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 89cb51a..e42adde 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -117,6 +117,7 @@ private slots: void customErrorStateIsNull(); void clearError(); void historyStateHasNowhereToGo(); + void historyStateAsInitialState(); void brokenStateIsNeverEntered(); void customErrorStateNotInGraph(); void transitionToStateNotInGraph(); @@ -811,6 +812,40 @@ void tst_QStateMachine::clearError() QVERIFY(machine.errorString().isEmpty()); } +void tst_QStateMachine::historyStateAsInitialState() +{ + QStateMachine machine; + + QHistoryState *hs = machine.rootState()->addHistoryState(); + machine.setInitialState(hs); + + QState *s1 = new QState(machine.rootState()); + hs->setDefaultState(s1); + + QState *s2 = new QState(machine.rootState()); + + QHistoryState *s2h = s2->addHistoryState(); + s2->setInitialState(s2h); + + QState *s21 = new QState(s2); + s2h->setDefaultState(s21); + + s1->addTransition(new EventTransition(QEvent::User, s2)); + + machine.start(); + QCoreApplication::processEvents(); + + QCOMPARE(machine.configuration().size(), 1); + QVERIFY(machine.configuration().contains(s1)); + + machine.postEvent(new QEvent(QEvent::User)); + QCoreApplication::processEvents(); + + QCOMPARE(machine.configuration().size(), 2); + QVERIFY(machine.configuration().contains(s2)); + QVERIFY(machine.configuration().contains(s21)); +} + void tst_QStateMachine::historyStateHasNowhereToGo() { QStateMachine machine; -- cgit v0.12 From c3f245e4dd5ca3422c6fdcb88c9ceea6b8a4c3ed Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 29 Apr 2009 11:09:56 +0200 Subject: Compile against new QHistoryState API. --- tests/auto/qstatemachine/tst_qstatemachine.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index e42adde..7e034ea 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -816,7 +816,7 @@ void tst_QStateMachine::historyStateAsInitialState() { QStateMachine machine; - QHistoryState *hs = machine.rootState()->addHistoryState(); + QHistoryState *hs = new QHistoryState(machine.rootState()); machine.setInitialState(hs); QState *s1 = new QState(machine.rootState()); @@ -824,7 +824,7 @@ void tst_QStateMachine::historyStateAsInitialState() QState *s2 = new QState(machine.rootState()); - QHistoryState *s2h = s2->addHistoryState(); + QHistoryState *s2h = new QHistoryState(s2); s2->setInitialState(s2h); QState *s21 = new QState(s2); -- cgit v0.12 From 6926197f1b817882fa074eecbe4f62f40e067642 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 29 Apr 2009 11:14:06 +0200 Subject: Remove QEXPECT_FAIL because e06c2e15 fixes this test as well. --- tests/auto/qstatemachine/tst_qstatemachine.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 7e034ea..3f44287 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -2882,7 +2882,6 @@ void tst_QStateMachine::parallelStateTransition() QVERIFY(machine.configuration().contains(s1)); - QEXPECT_FAIL("", "This failure is defined in the algorithm. We need to find out what behavior is correct.", Abort); QVERIFY(machine.configuration().contains(s2)); QVERIFY(machine.configuration().contains(s1OtherChild)); QVERIFY(machine.configuration().contains(s2InitialChild)); -- cgit v0.12 From cf9794278807c578bab2f3b015a99cc3adf20db5 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 29 Apr 2009 11:22:35 +0200 Subject: Adapt to recent API changes and bug fixes. --- examples/statemachine/errorstate/mainwindow.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/statemachine/errorstate/mainwindow.cpp b/examples/statemachine/errorstate/mainwindow.cpp index 9281298..f5edf60 100644 --- a/examples/statemachine/errorstate/mainwindow.cpp +++ b/examples/statemachine/errorstate/mainwindow.cpp @@ -117,6 +117,7 @@ void MainWindow::init() m_machine->setGlobalRestorePolicy(QStateMachine::RestoreProperties); QState *stoppedState = new QState(m_machine->rootState()); + stoppedState->setObjectName("stoppedState"); stoppedState->assignProperty(runGameAction, "enabled", true); stoppedState->assignProperty(stopGameAction, "enabled", false); @@ -125,15 +126,18 @@ void MainWindow::init() QState *spawnsAvailable = new QState(stoppedState); spawnsAvailable->assignProperty(addTankAction, "enabled", true); + spawnsAvailable->setObjectName("spawnsAvailable"); QState *noSpawnsAvailable = new QState(stoppedState); noSpawnsAvailable->assignProperty(addTankAction, "enabled", false); spawnsAvailable->addTransition(this, SIGNAL(mapFull()), noSpawnsAvailable); - QHistoryState *hs = stoppedState->addHistoryState(); + QHistoryState *hs = new QHistoryState(stoppedState); + hs->setObjectName("hs"); hs->setDefaultState(spawnsAvailable); - stoppedState->setInitialState(spawnsAvailable); + + stoppedState->setInitialState(hs); m_runningState = new QState(QState::ParallelGroup, m_machine->rootState()); m_runningState->assignProperty(addTankAction, "enabled", false); -- cgit v0.12 From c731d50a8ac908da982c911c73509cdd766c4c0f Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 29 Apr 2009 11:30:10 +0200 Subject: Add test that property assignments set on parallel states are actually applied after entering. --- tests/auto/qstatemachine/tst_qstatemachine.cpp | 43 ++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 3f44287..2733855 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -135,6 +135,7 @@ private slots: void transitionWithParent(); void parallelStateTransition(); + void parallelStateAssignmentsDone(); void simpleAnimation(); void twoAnimations(); @@ -2822,7 +2823,7 @@ void tst_QStateMachine::overrideDefaultTargetAnimationWithSource() QState *s3 = new QState(machine.rootState()); QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); - QAbstractTransition *at = s1->addTransition(new EventTransition(QEvent::User, s2)); + s1->addTransition(new EventTransition(QEvent::User, s2)); QPropertyAnimation *defaultAnimation = new QPropertyAnimation(object, "foo"); connect(defaultAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); @@ -2844,6 +2845,43 @@ void tst_QStateMachine::overrideDefaultTargetAnimationWithSource() QCOMPARE(counter.counter, 2); // specific animation started and stopped } +void tst_QStateMachine::parallelStateAssignmentsDone() +{ + QStateMachine machine; + + QObject *propertyHolder = new QObject(&machine); + propertyHolder->setProperty("foo", 123); + propertyHolder->setProperty("bar", 456); + propertyHolder->setProperty("zoot", 789); + + QState *s1 = new QState(machine.rootState()); + machine.setInitialState(s1); + + QState *parallelState = new QState(QState::ParallelGroup, machine.rootState()); + parallelState->assignProperty(propertyHolder, "foo", 321); + + QState *s2 = new QState(parallelState); + s2->assignProperty(propertyHolder, "bar", 654); + + QState *s3 = new QState(parallelState); + s3->assignProperty(propertyHolder, "zoot", 987); + + s1->addTransition(new EventTransition(QEvent::User, parallelState)); + machine.start(); + QCoreApplication::processEvents(); + + QCOMPARE(propertyHolder->property("foo").toInt(), 123); + QCOMPARE(propertyHolder->property("bar").toInt(), 456); + QCOMPARE(propertyHolder->property("zoot").toInt(), 789); + + machine.postEvent(new QEvent(QEvent::User)); + QCoreApplication::processEvents(); + + QCOMPARE(propertyHolder->property("foo").toInt(), 321); + QCOMPARE(propertyHolder->property("bar").toInt(), 654); + QCOMPARE(propertyHolder->property("zoot").toInt(), 987); +} + void tst_QStateMachine::parallelStateTransition() { QStateMachine machine; @@ -2860,8 +2898,7 @@ void tst_QStateMachine::parallelStateTransition() QState *s2InitialChild = new QState(s2); s2->setInitialState(s2InitialChild); - QState *s1OtherChild = new QState(s1); - QState *s2OtherChild = new QState(s2); + QState *s1OtherChild = new QState(s1); s1->addTransition(new EventTransition(QEvent::User, s1OtherChild)); -- cgit v0.12 From fa612960f423aa413d6d83813807a470aef27d7d Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 29 Apr 2009 11:40:38 +0200 Subject: replace QState::Type with QState::childMode property Result of API review. --- doc/src/statemachine.qdoc | 11 +++-- examples/statemachine/clockticking/main.cpp | 2 +- examples/statemachine/pingpong/main.cpp | 2 +- src/corelib/statemachine/qstate.cpp | 58 +++++++++++++++++++++----- src/corelib/statemachine/qstate.h | 16 ++++--- src/corelib/statemachine/qstate_p.h | 2 +- src/corelib/statemachine/qstatemachine.cpp | 4 +- tests/auto/qstatemachine/tst_qstatemachine.cpp | 4 +- 8 files changed, 70 insertions(+), 29 deletions(-) diff --git a/doc/src/statemachine.qdoc b/doc/src/statemachine.qdoc index 1462ec1..60ae815 100644 --- a/doc/src/statemachine.qdoc +++ b/doc/src/statemachine.qdoc @@ -241,11 +241,11 @@ \caption This is a caption \endomit - To create a parallel state group, pass QState::ParallelStateGroup to the - QState constructor. + To create a parallel state group, pass QState::ParallelStates to the QState + constructor. \code - QState *s1 = new QState(QState::ParallelStateGroup); + QState *s1 = new QState(QState::ParallelStates); // s11 and s12 will be entered in parallel QState *s11 = new QState(s1); QState *s12 = new QState(s1); @@ -253,9 +253,8 @@ \section1 Detecting that a Composite State has Finished - A child state can be final; when a final child state is entered, a - QStateFinishedEvent is generated for the parent state. You can use the - QStateFinishedTransition class to trigger a transition based on this event. + A child state can be final; when a final child state is entered, the parent + state emits the QState::finished() signal. \img statemachine-finished.png \omit diff --git a/examples/statemachine/clockticking/main.cpp b/examples/statemachine/clockticking/main.cpp index 301060b..9b54f29 100644 --- a/examples/statemachine/clockticking/main.cpp +++ b/examples/statemachine/clockticking/main.cpp @@ -104,7 +104,7 @@ int main(int argc, char **argv) QCoreApplication app(argc, argv); QStateMachine machine; - QState *group = new QState(QState::ParallelGroup); + QState *group = new QState(QState::ParallelStates); group->setObjectName("group"); ClockState *clock = new ClockState(group); diff --git a/examples/statemachine/pingpong/main.cpp b/examples/statemachine/pingpong/main.cpp index ec1ebf2..68f7115 100644 --- a/examples/statemachine/pingpong/main.cpp +++ b/examples/statemachine/pingpong/main.cpp @@ -112,7 +112,7 @@ int main(int argc, char **argv) QCoreApplication app(argc, argv); QStateMachine machine; - QState *group = new QState(QState::ParallelGroup); + QState *group = new QState(QState::ParallelStates); group->setObjectName("group"); Pinger *pinger = new Pinger(group); diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp index dd3af51..5b49f1f 100644 --- a/src/corelib/statemachine/qstate.cpp +++ b/src/corelib/statemachine/qstate.cpp @@ -81,20 +81,37 @@ QT_BEGIN_NAMESPACE */ /*! - \enum QState::Type + \property QState::initialState - This enum specifies the type of a state. + \brief the initial state of this state +*/ + +/*! + \property QState::errorState + + \brief the error state of this state +*/ + +/*! + \property QState::childMode + + \brief the child mode of this state +*/ + +/*! + \enum QState::ChildMode + + This enum specifies how a state's child states are treated. - \value Normal A normal state. If the state has no child states, it is an - atomic state; otherwise, the child states are mutually exclusive and an + \value ExclusiveStates The child states are mutually exclusive and an initial state must be set by calling QState::setInitialState(). - \value ParallelGroup The state is a parallel group state. When a parallel - group state is entered, all its child states are entered in parallel. + \value ParallelStates The child states are parallel. When the parent state + is entered, all its child states are entered in parallel. */ QStatePrivate::QStatePrivate() - : errorState(0), isParallelGroup(false), initialState(0) + : errorState(0), initialState(0), childMode(QState::ExclusiveStates) { } @@ -131,13 +148,14 @@ QState::QState(QState *parent) } /*! - Constructs a new state of the given \a type with the given \a parent state. + Constructs a new state with the given \a childMode and the given \a parent + state. */ -QState::QState(Type type, QState *parent) +QState::QState(ChildMode childMode, QState *parent) : QAbstractState(*new QStatePrivate, parent) { Q_D(QState); - d->isParallelGroup = (type == ParallelGroup); + d->childMode = childMode; } /*! @@ -393,7 +411,7 @@ QAbstractState *QState::initialState() const void QState::setInitialState(QAbstractState *state) { Q_D(QState); - if (d->isParallelGroup) { + if (d->childMode == QState::ParallelStates) { qWarning("QState::setInitialState: ignoring attempt to set initial state " "of parallel state group %p", this); return; @@ -407,6 +425,24 @@ void QState::setInitialState(QAbstractState *state) } /*! + Returns the child mode of this state. +*/ +QState::ChildMode QState::childMode() const +{ + Q_D(const QState); + return d->childMode; +} + +/*! + Sets the child \a mode of this state. +*/ +void QState::setChildMode(ChildMode mode) +{ + Q_D(QState); + d->childMode = mode; +} + +/*! \reimp */ bool QState::event(QEvent *e) diff --git a/src/corelib/statemachine/qstate.h b/src/corelib/statemachine/qstate.h index 33f0709..926d41f 100644 --- a/src/corelib/statemachine/qstate.h +++ b/src/corelib/statemachine/qstate.h @@ -55,21 +55,24 @@ QT_BEGIN_NAMESPACE QT_MODULE(Core) class QAbstractTransition; -class QHistoryState; class QSignalTransition; class QStatePrivate; class Q_CORE_EXPORT QState : public QAbstractState { Q_OBJECT + Q_PROPERTY(QAbstractState* initialState READ initialState WRITE setInitialState) + Q_PROPERTY(QAbstractState* errorState READ errorState WRITE setErrorState) + Q_PROPERTY(ChildMode childMode READ childMode WRITE setChildMode) + Q_ENUMS(ChildMode) public: - enum Type { - Normal, - ParallelGroup + enum ChildMode { + ExclusiveStates, + ParallelStates }; QState(QState *parent = 0); - QState(Type type, QState *parent = 0); + QState(ChildMode childMode, QState *parent = 0); ~QState(); QAbstractState *errorState() const; @@ -84,6 +87,9 @@ public: QAbstractState *initialState() const; void setInitialState(QAbstractState *state); + ChildMode childMode() const; + void setChildMode(ChildMode mode); + void assignProperty(QObject *object, const char *name, const QVariant &value); diff --git a/src/corelib/statemachine/qstate_p.h b/src/corelib/statemachine/qstate_p.h index 603bc18..0c8c858 100644 --- a/src/corelib/statemachine/qstate_p.h +++ b/src/corelib/statemachine/qstate_p.h @@ -94,8 +94,8 @@ public: void emitFinished(); QAbstractState *errorState; - bool isParallelGroup; QAbstractState *initialState; + QState::ChildMode childMode; QList propertyAssignments; }; diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 020700e..0ddeac9 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -751,7 +751,7 @@ bool QStateMachinePrivate::isFinal(const QAbstractState *s) bool QStateMachinePrivate::isParallel(const QAbstractState *s) { const QState *ss = qobject_cast(s); - return ss && QStatePrivate::get(ss)->isParallelGroup; + return ss && (QStatePrivate::get(ss)->childMode == QState::ParallelStates); } bool QStateMachinePrivate::isCompound(const QAbstractState *s) @@ -766,7 +766,7 @@ bool QStateMachinePrivate::isCompound(const QAbstractState *s) bool QStateMachinePrivate::isAtomic(const QAbstractState *s) { const QState *ss = qobject_cast(s); - return (ss && !QStatePrivate::get(ss)->isParallelGroup + return (ss && (QStatePrivate::get(ss)->childMode != QState::ParallelStates) && QStatePrivate::get(ss)->childStates().isEmpty()) || isFinal(s); } diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 2733855..7187b14 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -1281,7 +1281,7 @@ void tst_QStateMachine::parallelStates() { QStateMachine machine; - QState *s1 = new QState(QState::ParallelGroup); + QState *s1 = new QState(QState::ParallelStates); QState *s1_1 = new QState(s1); QState *s1_1_1 = new QState(s1_1); QFinalState *s1_1_f = new QFinalState(s1_1); @@ -2886,7 +2886,7 @@ void tst_QStateMachine::parallelStateTransition() { QStateMachine machine; - QState *parallelState = new QState(QState::ParallelGroup, machine.rootState()); + QState *parallelState = new QState(QState::ParallelStates, machine.rootState()); machine.setInitialState(parallelState); QState *s1 = new QState(parallelState); -- cgit v0.12 From 35f353f16f696a7362d3e899c9a7e2066dc09c65 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 29 Apr 2009 11:47:42 +0200 Subject: add missing QT_END_HEADER --- src/corelib/statemachine/qsignalevent.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/corelib/statemachine/qsignalevent.h b/src/corelib/statemachine/qsignalevent.h index 5dcabc4..8221f68 100644 --- a/src/corelib/statemachine/qsignalevent.h +++ b/src/corelib/statemachine/qsignalevent.h @@ -72,4 +72,6 @@ private: QT_END_NAMESPACE +QT_END_HEADER + #endif -- cgit v0.12 From 6ca9c87235b057bc635576b0c414ca789afaf592 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 29 Apr 2009 12:20:11 +0200 Subject: rename QBoundEvent to QWrappedEvent and make it public Result of API review. --- src/corelib/kernel/qcoreevent.h | 2 +- src/corelib/statemachine/qboundevent_p.h | 82 -------------------------- src/corelib/statemachine/qeventtransition.cpp | 34 ++++------- src/corelib/statemachine/qeventtransition.h | 2 - src/corelib/statemachine/qstatemachine.cpp | 58 +++++++++++++++++- src/corelib/statemachine/qwrappedevent.h | 76 ++++++++++++++++++++++++ src/corelib/statemachine/statemachine.pri | 2 +- src/gui/statemachine/qkeyeventtransition.cpp | 18 +++--- src/gui/statemachine/qkeyeventtransition.h | 1 - src/gui/statemachine/qmouseeventtransition.cpp | 18 +++--- tests/auto/qstatemachine/tst_qstatemachine.cpp | 2 +- 11 files changed, 159 insertions(+), 136 deletions(-) delete mode 100644 src/corelib/statemachine/qboundevent_p.h create mode 100644 src/corelib/statemachine/qwrappedevent.h diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h index 674b5b0..18188a8 100644 --- a/src/corelib/kernel/qcoreevent.h +++ b/src/corelib/kernel/qcoreevent.h @@ -270,7 +270,7 @@ public: MacGLClearDrawable = 191, // Internal Cocoa, the window has changed, so we must clear Signal = 192, - Bound = 193, + Wrapped = 193, // 512 reserved for Qt Jambi's MetaCall event // 513 reserved for Qt Jambi's DeleteOnMainThread event diff --git a/src/corelib/statemachine/qboundevent_p.h b/src/corelib/statemachine/qboundevent_p.h deleted file mode 100644 index b641ff3..0000000 --- a/src/corelib/statemachine/qboundevent_p.h +++ /dev/null @@ -1,82 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QBOUNDEVENT_P_H -#define QBOUNDEVENT_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -QT_BEGIN_NAMESPACE - -class QBoundEvent : public QEvent -{ -public: - QBoundEvent(QObject *object, QEvent *event) -#ifdef QT_STATEMACHINE_SOLUTION - : QEvent(QEvent::Type(QEvent::User-3)), -#else - : QEvent(QEvent::Bound), -#endif - m_object(object), m_event(event) {} - ~QBoundEvent() {} - - inline QObject *object() const { return m_object; } - inline QEvent *event() const { return m_event; } - -private: - QObject *m_object; - QEvent *m_event; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/corelib/statemachine/qeventtransition.cpp b/src/corelib/statemachine/qeventtransition.cpp index 2126373..cbd03bd 100644 --- a/src/corelib/statemachine/qeventtransition.cpp +++ b/src/corelib/statemachine/qeventtransition.cpp @@ -41,7 +41,7 @@ #include "qeventtransition.h" #include "qeventtransition_p.h" -#include "qboundevent_p.h" +#include "qwrappedevent.h" #include "qstate.h" #include "qstate_p.h" #include "qstatemachine.h" @@ -79,10 +79,11 @@ QT_BEGIN_NAMESPACE \section1 Subclassing - Many event classes have attributes in addition to the event type itself. - The testEventCondition() function can be reimplemented to check attributes - of an event instance in order to determine whether the transition should be - triggered or not. + When reimplementing the eventTest() function, you should first call the base + implementation to verify that the event is a QWrappedEvent for the proper + object and event type. You may then cast the event to a QWrappedEvent and + get the original event by calling QWrappedEvent::event(), and perform + additional checks on that object. \sa QState::addTransition() */ @@ -257,12 +258,11 @@ bool QEventTransition::eventTest(QEvent *event) const #ifdef QT_STATEMACHINE_SOLUTION if (event->type() == QEvent::Type(QEvent::User-3)) { #else - if (event->type() == QEvent::Bound) { + if (event->type() == QEvent::Wrapped) { #endif - QBoundEvent *oe = static_cast(event); - return (oe->object() == d->object) - && (oe->event()->type() == d->eventType) - && testEventCondition(oe->event()); + QWrappedEvent *we = static_cast(event); + return (we->object() == d->object) + && (we->event()->type() == d->eventType); } return false; } @@ -275,20 +275,6 @@ void QEventTransition::onTransition() } /*! - Tests an instance of an event associated with this event transition and - returns true if the transition should be taken, otherwise returns false. - The type of the given \a event will be eventType(). - - Reimplement this function if you have custom conditions associated with - the transition. The default implementation always returns true. -*/ -bool QEventTransition::testEventCondition(QEvent *event) const -{ - Q_UNUSED(event); - return true; -} - -/*! \reimp */ bool QEventTransition::event(QEvent *e) diff --git a/src/corelib/statemachine/qeventtransition.h b/src/corelib/statemachine/qeventtransition.h index 82fcd36..484602c 100644 --- a/src/corelib/statemachine/qeventtransition.h +++ b/src/corelib/statemachine/qeventtransition.h @@ -77,8 +77,6 @@ public: void setEventType(QEvent::Type type); protected: - virtual bool testEventCondition(QEvent *event) const; // ### name - bool eventTest(QEvent *event) const; void onTransition(); diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 0ddeac9..b0f6cd6 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -62,7 +62,7 @@ #ifndef QT_NO_STATEMACHINE_EVENTFILTER #include "qeventtransition.h" #include "qeventtransition_p.h" -#include "qboundevent_p.h" +#include "qwrappedevent.h" #endif #ifndef QT_NO_ANIMATION @@ -1827,7 +1827,7 @@ bool QStateMachine::eventFilter(QObject *watched, QEvent *event) Q_D(QStateMachine); Q_ASSERT(d->qobjectEvents.contains(watched)); if (d->qobjectEvents[watched].contains(event->type())) - postEvent(new QBoundEvent(watched, d->handler->cloneEvent(event))); + postEvent(new QWrappedEvent(watched, d->handler->cloneEvent(event))); return false; } #endif @@ -2140,6 +2140,60 @@ QSignalEvent::~QSignalEvent() Returns the arguments of the signal. */ + +/*! + \class QWrappedEvent + + \brief The QWrappedEvent class holds a clone of an event associated with a QObject. + + \since 4.6 + \ingroup statemachine + + A wrapped event is generated by a QStateMachine in response to a Qt + event. The QEventTransition class provides a transition associated with a + such an event. QWrappedEvent is part of \l{The State Machine Framework}. + + The object() function returns the object that generated the event. The + event() function returns a clone of the original event. + + \sa QEventTransition +*/ + +/*! + \internal + + Constructs a new QWrappedEvent object with the given \a object + and \a event. +*/ +QWrappedEvent::QWrappedEvent(QObject *object, QEvent *event) +#ifdef QT_STATEMACHINE_SOLUTION + : QEvent(QEvent::Type(QEvent::User-3)) +#else + : QEvent(QEvent::Wrapped) +#endif + , m_object(object), m_event(event) +{ +} + +/*! + Destroys this QWrappedEvent. +*/ +QWrappedEvent::~QWrappedEvent() +{ +} + +/*! + \fn QWrappedEvent::object() const + + Returns the object that the event is associated with. +*/ + +/*! + \fn QWrappedEvent::event() const + + Returns a clone of the original event. +*/ + QT_END_NAMESPACE #include "moc_qstatemachine.cpp" diff --git a/src/corelib/statemachine/qwrappedevent.h b/src/corelib/statemachine/qwrappedevent.h new file mode 100644 index 0000000..b01c608 --- /dev/null +++ b/src/corelib/statemachine/qwrappedevent.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWRAPPEDEVENT_H +#define QWRAPPEDEVENT_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +class QObject; + +class Q_CORE_EXPORT QWrappedEvent : public QEvent +{ +public: + QWrappedEvent(QObject *object, QEvent *event); + ~QWrappedEvent(); + + inline QObject *object() const { return m_object; } + inline QEvent *event() const { return m_event; } + +private: + QObject *m_object; + QEvent *m_event; + +private: + Q_DISABLE_COPY(QWrappedEvent) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/corelib/statemachine/statemachine.pri b/src/corelib/statemachine/statemachine.pri index 69f887c..5b19bc1 100644 --- a/src/corelib/statemachine/statemachine.pri +++ b/src/corelib/statemachine/statemachine.pri @@ -23,7 +23,7 @@ SOURCES += $$PWD/qstatemachine.cpp \ $$PWD/qsignaltransition.cpp !contains(DEFINES, QT_NO_STATEMACHINE_EVENTFILTER) { -HEADERS += $$PWD/qboundevent_p.h \ +HEADERS += $$PWD/qwrappedevent.h \ $$PWD/qeventtransition.h \ $$PWD/qeventtransition_p.h SOURCES += $$PWD/qeventtransition.cpp diff --git a/src/gui/statemachine/qkeyeventtransition.cpp b/src/gui/statemachine/qkeyeventtransition.cpp index 7c1ae8a..37f4dd9 100644 --- a/src/gui/statemachine/qkeyeventtransition.cpp +++ b/src/gui/statemachine/qkeyeventtransition.cpp @@ -11,6 +11,7 @@ #include "qkeyeventtransition.h" #include "qbasickeyeventtransition_p.h" +#include #if defined(QT_EXPERIMENTAL_SOLUTION) # include "qeventtransition_p.h" @@ -139,19 +140,14 @@ void QKeyEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask) /*! \reimp */ -bool QKeyEventTransition::testEventCondition(QEvent *event) const -{ - Q_D(const QKeyEventTransition); - d->transition->setEventType(event->type()); - return QAbstractTransitionPrivate::get(d->transition)->callEventTest(event); -} - -/*! - \reimp -*/ bool QKeyEventTransition::eventTest(QEvent *event) const { - return QEventTransition::eventTest(event); + Q_D(const QKeyEventTransition); + if (!QEventTransition::eventTest(event)) + return false; + QWrappedEvent *we = static_cast(event); + d->transition->setEventType(we->event()->type()); + return QAbstractTransitionPrivate::get(d->transition)->callEventTest(we->event()); } /*! diff --git a/src/gui/statemachine/qkeyeventtransition.h b/src/gui/statemachine/qkeyeventtransition.h index ef814db..fa95c1b 100644 --- a/src/gui/statemachine/qkeyeventtransition.h +++ b/src/gui/statemachine/qkeyeventtransition.h @@ -47,7 +47,6 @@ public: protected: void onTransition(); bool eventTest(QEvent *event) const; - bool testEventCondition(QEvent *event) const; private: Q_DISABLE_COPY(QKeyEventTransition) diff --git a/src/gui/statemachine/qmouseeventtransition.cpp b/src/gui/statemachine/qmouseeventtransition.cpp index d6d9b62..353b833 100644 --- a/src/gui/statemachine/qmouseeventtransition.cpp +++ b/src/gui/statemachine/qmouseeventtransition.cpp @@ -11,6 +11,7 @@ #include "qmouseeventtransition.h" #include "qbasicmouseeventtransition_p.h" +#include #include #if defined(QT_EXPERIMENTAL_SOLUTION) @@ -169,19 +170,14 @@ void QMouseEventTransition::setPath(const QPainterPath &path) /*! \reimp */ -bool QMouseEventTransition::testEventCondition(QEvent *event) const -{ - Q_D(const QMouseEventTransition); - d->transition->setEventType(event->type()); - return QAbstractTransitionPrivate::get(d->transition)->callEventTest(event); -} - -/*! - \reimp -*/ bool QMouseEventTransition::eventTest(QEvent *event) const { - return QEventTransition::eventTest(event); + Q_D(const QMouseEventTransition); + if (!QEventTransition::eventTest(event)) + return false; + QWrappedEvent *we = static_cast(event); + d->transition->setEventType(we->event()->type()); + return QAbstractTransitionPrivate::get(d->transition)->callEventTest(we->event()); } /*! diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 7187b14..b380f6d 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -2857,7 +2857,7 @@ void tst_QStateMachine::parallelStateAssignmentsDone() QState *s1 = new QState(machine.rootState()); machine.setInitialState(s1); - QState *parallelState = new QState(QState::ParallelGroup, machine.rootState()); + QState *parallelState = new QState(QState::ParallelStates, machine.rootState()); parallelState->assignProperty(propertyHolder, "foo", 321); QState *s2 = new QState(parallelState); -- cgit v0.12 From 36aa9e0468bfa874679dd94b2d50850a1dd7a1d1 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 29 Apr 2009 12:59:05 +0200 Subject: compile fix for the benchmark QItemAnimation has disappeared and it's now better to start the animation instead of pausing it --- tests/benchmarks/qanimation/main.cpp | 57 ++++++++------------------- tests/benchmarks/qanimation/rectanimation.cpp | 28 ++++++------- tests/benchmarks/qanimation/rectanimation.h | 10 ++--- 3 files changed, 36 insertions(+), 59 deletions(-) diff --git a/tests/benchmarks/qanimation/main.cpp b/tests/benchmarks/qanimation/main.cpp index 7bbcffb..7bb770f 100644 --- a/tests/benchmarks/qanimation/main.cpp +++ b/tests/benchmarks/qanimation/main.cpp @@ -11,8 +11,6 @@ class tst_qanimation : public QObject { Q_OBJECT private slots: - void itemAnimation(); - void itemAnimation_data() { data();} void itemPropertyAnimation(); void itemPropertyAnimation_data() { data();} void dummyAnimation(); @@ -32,35 +30,14 @@ private: void tst_qanimation::data() { - QTest::addColumn("paused"); + QTest::addColumn("started"); QTest::newRow("NotRunning") << false; - QTest::newRow("Paused") << true; -} - -void tst_qanimation::itemAnimation() -{ - QFETCH(bool, paused); - QGraphicsWidget item; - - //first the item animation - { - QItemAnimation anim(&item, QItemAnimation::Position); - anim.setDuration(ITERATION_COUNT); - anim.setStartValue(QPointF(0,0)); - anim.setEndValue(QPointF(ITERATION_COUNT,ITERATION_COUNT)); - if (paused) - anim.pause(); - QBENCHMARK { - for(int i = 0; i < anim.duration(); ++i) { - anim.setCurrentTime(i); - } - } - } + QTest::newRow("Running") << true; } void tst_qanimation::itemPropertyAnimation() { - QFETCH(bool, paused); + QFETCH(bool, started); QGraphicsWidget item; //then the property animation @@ -69,8 +46,8 @@ void tst_qanimation::itemPropertyAnimation() anim.setDuration(ITERATION_COUNT); anim.setStartValue(QPointF(0,0)); anim.setEndValue(QPointF(ITERATION_COUNT,ITERATION_COUNT)); - if (paused) - anim.pause(); + if (started) + anim.start(); QBENCHMARK { for(int i = 0; i < ITERATION_COUNT; ++i) { anim.setCurrentTime(i); @@ -82,7 +59,7 @@ void tst_qanimation::itemPropertyAnimation() void tst_qanimation::dummyAnimation() { - QFETCH(bool, paused); + QFETCH(bool, started); DummyObject dummy; //first the dummy animation @@ -91,8 +68,8 @@ void tst_qanimation::dummyAnimation() anim.setDuration(ITERATION_COUNT); anim.setStartValue(QRect(0, 0, 0, 0)); anim.setEndValue(QRect(0, 0, ITERATION_COUNT,ITERATION_COUNT)); - if (paused) - anim.pause(); + if (started) + anim.start(); QBENCHMARK { for(int i = 0; i < anim.duration(); ++i) { anim.setCurrentTime(i); @@ -103,7 +80,7 @@ void tst_qanimation::dummyAnimation() void tst_qanimation::dummyPropertyAnimation() { - QFETCH(bool, paused); + QFETCH(bool, started); DummyObject dummy; //then the property animation @@ -112,8 +89,8 @@ void tst_qanimation::dummyPropertyAnimation() anim.setDuration(ITERATION_COUNT); anim.setStartValue(QRect(0, 0, 0, 0)); anim.setEndValue(QRect(0, 0, ITERATION_COUNT,ITERATION_COUNT)); - if (paused) - anim.pause(); + if (started) + anim.start(); QBENCHMARK { for(int i = 0; i < ITERATION_COUNT; ++i) { anim.setCurrentTime(i); @@ -125,7 +102,7 @@ void tst_qanimation::dummyPropertyAnimation() void tst_qanimation::rectAnimation() { //this is the simplest animation you can do - QFETCH(bool, paused); + QFETCH(bool, started); DummyObject dummy; //then the property animation @@ -134,8 +111,8 @@ void tst_qanimation::rectAnimation() anim.setDuration(ITERATION_COUNT); anim.setStartValue(QRect(0, 0, 0, 0)); anim.setEndValue(QRect(0, 0, ITERATION_COUNT,ITERATION_COUNT)); - if (paused) - anim.pause(); + if (started) + anim.start(); QBENCHMARK { for(int i = 0; i < ITERATION_COUNT; ++i) { anim.setCurrentTime(i); @@ -147,7 +124,7 @@ void tst_qanimation::rectAnimation() void tst_qanimation::floatAnimation() { //this is the simplest animation you can do - QFETCH(bool, paused); + QFETCH(bool, started); DummyObject dummy; //then the property animation @@ -156,8 +133,8 @@ void tst_qanimation::floatAnimation() anim.setDuration(ITERATION_COUNT); anim.setStartValue(0.f); anim.setEndValue(1.f); - if (paused) - anim.pause(); + if (started) + anim.start(); QBENCHMARK { for(int i = 0; i < ITERATION_COUNT; ++i) { anim.setCurrentTime(i); diff --git a/tests/benchmarks/qanimation/rectanimation.cpp b/tests/benchmarks/qanimation/rectanimation.cpp index 66c7a33..d60a943 100644 --- a/tests/benchmarks/qanimation/rectanimation.cpp +++ b/tests/benchmarks/qanimation/rectanimation.cpp @@ -7,49 +7,49 @@ static inline int interpolateInteger(int from, int to, qreal progress) } -RectAnimation::RectAnimation(DummyObject *obj) : object(obj), dura(250) +RectAnimation::RectAnimation(DummyObject *obj) : m_object(obj), m_dura(250) { } void RectAnimation::setEndValue(const QRect &rect) { - end = rect; + m_end = rect; } void RectAnimation::setStartValue(const QRect &rect) { - start = rect; + m_start = rect; } void RectAnimation::setDuration(int d) { - dura = d; + m_dura = d; } int RectAnimation::duration() const { - return dura; + return m_dura; } void RectAnimation::updateCurrentTime(int msecs) { - qreal progress = easing.valueForProgress( qreal(msecs) / qreal(dura) ); + qreal progress = m_easing.valueForProgress( qreal(msecs) / qreal(m_dura) ); QRect now; - now.setCoords(interpolateInteger(start.left(), end.left(), progress), - interpolateInteger(start.top(), end.top(), progress), - interpolateInteger(start.right(), end.right(), progress), - interpolateInteger(start.bottom(), end.bottom(), progress)); + now.setCoords(interpolateInteger(m_start.left(), m_end.left(), progress), + interpolateInteger(m_start.top(), m_end.top(), progress), + interpolateInteger(m_start.right(), m_end.right(), progress), + interpolateInteger(m_start.bottom(), m_end.bottom(), progress)); - bool changed = (now != current); + bool changed = (now != m_current); if (changed) - current = now; + m_current = now; if (state() == Stopped) return; - if (object) - object->setRect(current); + if (m_object) + m_object->setRect(m_current); } void RectAnimation::updateState(QAbstractAnimation::State state) diff --git a/tests/benchmarks/qanimation/rectanimation.h b/tests/benchmarks/qanimation/rectanimation.h index c9770c4..99b82b4 100644 --- a/tests/benchmarks/qanimation/rectanimation.h +++ b/tests/benchmarks/qanimation/rectanimation.h @@ -21,10 +21,10 @@ public: virtual void updateState(QAbstractAnimation::State state); private: - DummyObject *object; - QEasingCurve easing; - QRect start, end, current; - int dura; + DummyObject *m_object; + QEasingCurve m_easing; + QRect m_start, m_end, m_current; + int m_dura; }; -#endif \ No newline at end of file +#endif -- cgit v0.12 From 4bb51ce9c9e34058a1f9cefae9bf1c82ff4d3c5b Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 29 Apr 2009 13:31:21 +0200 Subject: kill dead function declaration --- src/gui/statemachine/qmouseeventtransition.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gui/statemachine/qmouseeventtransition.h b/src/gui/statemachine/qmouseeventtransition.h index dbd615f..d5fb565 100644 --- a/src/gui/statemachine/qmouseeventtransition.h +++ b/src/gui/statemachine/qmouseeventtransition.h @@ -53,7 +53,6 @@ public: protected: void onTransition(); bool eventTest(QEvent *event) const; - bool testEventCondition(QEvent *event) const; private: Q_DISABLE_COPY(QMouseEventTransition) -- cgit v0.12 From f7d69d7538fc77f65fb2f0223a5c3def03d3f9c8 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 29 Apr 2009 14:00:31 +0200 Subject: kill source/target-specific animations Result of API review. We don't have use cases for them yet. We can add them back if valid use cases do turn up. --- src/corelib/statemachine/qstatemachine.cpp | 66 ---------- src/corelib/statemachine/qstatemachine.h | 8 -- tests/auto/qstatemachine/tst_qstatemachine.cpp | 165 +++++++++++++------------ 3 files changed, 85 insertions(+), 154 deletions(-) diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index b0f6cd6..8320b0d 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -1930,72 +1930,6 @@ void QStateMachine::removeDefaultAnimation(QAbstractAnimation *animation) 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 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 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 diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h index 3ad215b..bbe85e2 100644 --- a/src/corelib/statemachine/qstatemachine.h +++ b/src/corelib/statemachine/qstatemachine.h @@ -114,14 +114,6 @@ public: void addDefaultAnimation(QAbstractAnimation *animation); QList defaultAnimations() const; void removeDefaultAnimation(QAbstractAnimation *animation); - - void addDefaultAnimationForSourceState(QAbstractState *sourceState, QAbstractAnimation *animation); - QList defaultAnimationsForSourceState(QAbstractState *sourceState) const; - void removeDefaultAnimationForSourceState(QAbstractState *sourceState, QAbstractAnimation *animation); - - void addDefaultAnimationForTargetState(QAbstractState *targetState, QAbstractAnimation *animation); - QList defaultAnimationsForTargetState(QAbstractState *targetState) const; - void removeDefaultAnimationForTargetState(QAbstractState *targetState, QAbstractAnimation *animation); #endif // QT_NO_ANIMATION QStateMachine::RestorePolicy globalRestorePolicy() const; diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index b380f6d..abe0c2b 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -144,19 +144,21 @@ private slots: void nestedTargetStateForAnimation(); void animatedGlobalRestoreProperty(); void specificTargetValueOfAnimation(); + void addDefaultAnimation(); void addDefaultAnimationWithUnusedAnimation(); - void addDefaultAnimationForSource(); - void addDefaultAnimationForTarget(); void removeDefaultAnimation(); - void removeDefaultAnimationForSource(); - void removeDefaultAnimationForTarget(); - void overrideDefaultAnimationWithSource(); - void overrideDefaultAnimationWithTarget(); void overrideDefaultAnimationWithSpecific(); - void overrideDefaultSourceAnimationWithSpecific(); - void overrideDefaultTargetAnimationWithSpecific(); - void overrideDefaultTargetAnimationWithSource(); + +// void addDefaultAnimationForSource(); +// void addDefaultAnimationForTarget(); +// void removeDefaultAnimationForSource(); +// void removeDefaultAnimationForTarget(); +// void overrideDefaultAnimationWithSource(); +// void overrideDefaultAnimationWithTarget(); +// void overrideDefaultSourceAnimationWithSpecific(); +// void overrideDefaultTargetAnimationWithSpecific(); +// void overrideDefaultTargetAnimationWithSource(); }; tst_QStateMachine::tst_QStateMachine() @@ -2417,28 +2419,71 @@ void tst_QStateMachine::addDefaultAnimationWithUnusedAnimation() QCOMPARE(counter.counter, 1); } -void tst_QStateMachine::addDefaultAnimationForSource() +void tst_QStateMachine::removeDefaultAnimation() +{ + QStateMachine machine; + + QCOMPARE(machine.defaultAnimations().size(), 0); + + QPropertyAnimation *anim = new QPropertyAnimation(this, "foo"); + + machine.addDefaultAnimation(anim); + + QCOMPARE(machine.defaultAnimations().size(), 1); + QVERIFY(machine.defaultAnimations().contains(anim)); + + machine.removeDefaultAnimation(anim); + + QCOMPARE(machine.defaultAnimations().size(), 0); + + machine.addDefaultAnimation(anim); + + QPropertyAnimation *anim2 = new QPropertyAnimation(this, "foo"); + machine.addDefaultAnimation(anim2); + + QCOMPARE(machine.defaultAnimations().size(), 2); + QVERIFY(machine.defaultAnimations().contains(anim)); + QVERIFY(machine.defaultAnimations().contains(anim2)); + + machine.removeDefaultAnimation(anim); + + QCOMPARE(machine.defaultAnimations().size(), 1); + QVERIFY(machine.defaultAnimations().contains(anim2)); + + machine.removeDefaultAnimation(anim2); + QCOMPARE(machine.defaultAnimations().size(), 0); +} + +void tst_QStateMachine::overrideDefaultAnimationWithSpecific() { QStateMachine machine; QObject *object = new QObject(); object->setProperty("foo", 1.0); + SlotCalledCounter counter; + QState *s1 = new QState(machine.rootState()); + machine.setInitialState(s1); QState *s2 = new QState(machine.rootState()); s2->assignProperty(object, "foo", 2.0); QState *s3 = new QState(machine.rootState()); QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); + + QAbstractTransition *at = s1->addTransition(new EventTransition(QEvent::User, s2)); - s1->addTransition(new EventTransition(QEvent::User, s2)); + QPropertyAnimation *defaultAnimation = new QPropertyAnimation(object, "foo"); + connect(defaultAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); - QPropertyAnimation *pa = new QPropertyAnimation(object, "foo", &machine); - machine.addDefaultAnimationForSourceState(s1, pa); - s2->addTransition(pa, SIGNAL(finished()), s3); + QPropertyAnimation *moreSpecificAnimation = new QPropertyAnimation(object, "foo"); + s2->addTransition(moreSpecificAnimation, SIGNAL(finished()), s3); + connect(moreSpecificAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); + + machine.addDefaultAnimation(defaultAnimation); + at->addAnimation(moreSpecificAnimation); - machine.setInitialState(s1); machine.start(); QCoreApplication::processEvents(); @@ -2446,10 +2491,11 @@ void tst_QStateMachine::addDefaultAnimationForSource() QCOREAPPLICATION_EXEC(5000); QVERIFY(machine.configuration().contains(s3)); - QCOMPARE(object->property("foo").toDouble(), 2.0); + QCOMPARE(counter.counter, 2); // specific animation started and stopped } -void tst_QStateMachine::addDefaultAnimationForTarget() +/* +void tst_QStateMachine::addDefaultAnimationForSource() { QStateMachine machine; @@ -2467,7 +2513,7 @@ void tst_QStateMachine::addDefaultAnimationForTarget() s1->addTransition(new EventTransition(QEvent::User, s2)); QPropertyAnimation *pa = new QPropertyAnimation(object, "foo", &machine); - machine.addDefaultAnimationForTargetState(s2, pa); + machine.addDefaultAnimationForSourceState(s1, pa); s2->addTransition(pa, SIGNAL(finished()), s3); machine.setInitialState(s1); @@ -2481,39 +2527,36 @@ void tst_QStateMachine::addDefaultAnimationForTarget() QCOMPARE(object->property("foo").toDouble(), 2.0); } -void tst_QStateMachine::removeDefaultAnimation() +void tst_QStateMachine::addDefaultAnimationForTarget() { QStateMachine machine; - QCOMPARE(machine.defaultAnimations().size(), 0); - - QPropertyAnimation *anim = new QPropertyAnimation(this, "foo"); - - machine.addDefaultAnimation(anim); - - QCOMPARE(machine.defaultAnimations().size(), 1); - QVERIFY(machine.defaultAnimations().contains(anim)); + QObject *object = new QObject(); + object->setProperty("foo", 1.0); - machine.removeDefaultAnimation(anim); + QState *s1 = new QState(machine.rootState()); - QCOMPARE(machine.defaultAnimations().size(), 0); + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(object, "foo", 2.0); - machine.addDefaultAnimation(anim); + QState *s3 = new QState(machine.rootState()); + QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); - QPropertyAnimation *anim2 = new QPropertyAnimation(this, "foo"); - machine.addDefaultAnimation(anim2); + s1->addTransition(new EventTransition(QEvent::User, s2)); - QCOMPARE(machine.defaultAnimations().size(), 2); - QVERIFY(machine.defaultAnimations().contains(anim)); - QVERIFY(machine.defaultAnimations().contains(anim2)); + QPropertyAnimation *pa = new QPropertyAnimation(object, "foo", &machine); + machine.addDefaultAnimationForTargetState(s2, pa); + s2->addTransition(pa, SIGNAL(finished()), s3); - machine.removeDefaultAnimation(anim); + machine.setInitialState(s1); + machine.start(); + QCoreApplication::processEvents(); - QCOMPARE(machine.defaultAnimations().size(), 1); - QVERIFY(machine.defaultAnimations().contains(anim2)); + machine.postEvent(new QEvent(QEvent::User)); + QCOREAPPLICATION_EXEC(5000); - machine.removeDefaultAnimation(anim2); - QCOMPARE(machine.defaultAnimations().size(), 0); + QVERIFY(machine.configuration().contains(s3)); + QCOMPARE(object->property("foo").toDouble(), 2.0); } void tst_QStateMachine::removeDefaultAnimationForSource() @@ -2685,46 +2728,6 @@ void tst_QStateMachine::overrideDefaultAnimationWithTarget() } -void tst_QStateMachine::overrideDefaultAnimationWithSpecific() -{ - QStateMachine machine; - - QObject *object = new QObject(); - object->setProperty("foo", 1.0); - - SlotCalledCounter counter; - - QState *s1 = new QState(machine.rootState()); - machine.setInitialState(s1); - - QState *s2 = new QState(machine.rootState()); - s2->assignProperty(object, "foo", 2.0); - - QState *s3 = new QState(machine.rootState()); - QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); - - QAbstractTransition *at = s1->addTransition(new EventTransition(QEvent::User, s2)); - - QPropertyAnimation *defaultAnimation = new QPropertyAnimation(object, "foo"); - connect(defaultAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); - - QPropertyAnimation *moreSpecificAnimation = new QPropertyAnimation(object, "foo"); - s2->addTransition(moreSpecificAnimation, SIGNAL(finished()), s3); - connect(moreSpecificAnimation, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State)), &counter, SLOT(slot())); - - machine.addDefaultAnimation(defaultAnimation); - at->addAnimation(moreSpecificAnimation); - - machine.start(); - QCoreApplication::processEvents(); - - machine.postEvent(new QEvent(QEvent::User)); - QCOREAPPLICATION_EXEC(5000); - - QVERIFY(machine.configuration().contains(s3)); - QCOMPARE(counter.counter, 2); // specific animation started and stopped -} - void tst_QStateMachine::overrideDefaultSourceAnimationWithSpecific() { QStateMachine machine; @@ -2845,6 +2848,8 @@ void tst_QStateMachine::overrideDefaultTargetAnimationWithSource() QCOMPARE(counter.counter, 2); // specific animation started and stopped } +*/ + void tst_QStateMachine::parallelStateAssignmentsDone() { QStateMachine machine; -- cgit v0.12 From 6558134ec1dbf13ab56a40b0b269a50e92feb188 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 29 Apr 2009 14:10:45 +0200 Subject: doc --- src/corelib/statemachine/qstatemachine.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 8320b0d..b278bb5 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -177,6 +177,12 @@ QT_BEGIN_NAMESPACE \brief the error string of this state machine */ +/*! + \property QStateMachine::globalRestorePolicy + + \brief the restore policy for states of this state machine. +*/ + #ifndef QT_NO_ANIMATION /*! \property QStateMachine::animationsEnabled @@ -1509,7 +1515,7 @@ void QStateMachine::setErrorState(QAbstractState *state) \value RestoreProperties The state machine should save the initial values of properties and restore them later. - \sa setRestorePolicy(), restorePolicy(), QState::assignProperty() + \sa QStateMachine::globalRestorePolicy QState::assignProperty() */ -- cgit v0.12 From 90c9f525bffe2418bc4d246645adca8c731f7774 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 29 Apr 2009 14:16:51 +0200 Subject: kill QStateMachine::states() and QState::transitions() Result of API review. Don't need them (for now). --- src/corelib/statemachine/qstate.cpp | 12 ----------- src/corelib/statemachine/qstate.h | 1 - src/corelib/statemachine/qstatemachine.cpp | 9 -------- src/corelib/statemachine/qstatemachine.h | 1 - tests/auto/qstatemachine/tst_qstatemachine.cpp | 30 ++++++++++++++------------ 5 files changed, 16 insertions(+), 37 deletions(-) diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp index 5b49f1f..173cc8d 100644 --- a/src/corelib/statemachine/qstate.cpp +++ b/src/corelib/statemachine/qstate.cpp @@ -370,18 +370,6 @@ void QState::removeTransition(QAbstractTransition *transition) } /*! - Returns the list of transitions from this state, or an empty list if there - are no transitions from this state. - - \sa addTransition(), removeTransition() -*/ -QList QState::transitions() const -{ - Q_D(const QState); - return d->transitions(); -} - -/*! \reimp */ void QState::onEntry() diff --git a/src/corelib/statemachine/qstate.h b/src/corelib/statemachine/qstate.h index 926d41f..9faef26 100644 --- a/src/corelib/statemachine/qstate.h +++ b/src/corelib/statemachine/qstate.h @@ -82,7 +82,6 @@ public: QSignalTransition *addTransition(QObject *sender, const char *signal, QAbstractState *target); QAbstractTransition *addTransition(QAbstractState *target); void removeTransition(QAbstractTransition *transition); - QList transitions() const; QAbstractState *initialState() const; void setInitialState(QAbstractState *state); diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index b278bb5..8dfb229 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -1736,15 +1736,6 @@ void QStateMachine::postInternalEvent(QEvent *event) } /*! - Returns the list of this state machine's states, or an empty list if the - state machine has no states. -*/ -QList QStateMachine::states() const -{ - return QStatePrivate::get(rootState())->childStates(); -} - -/*! \internal Returns the maximal consistent set of states (including parallel and final diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h index bbe85e2..6e504d0 100644 --- a/src/corelib/statemachine/qstatemachine.h +++ b/src/corelib/statemachine/qstatemachine.h @@ -121,7 +121,6 @@ public: void postEvent(QEvent *event, int delay = 0); - QList states() const; QSet configuration() const; #ifndef QT_NO_STATEMACHINE_EVENTFILTER diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index abe0c2b..5ce0f35 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -48,6 +48,7 @@ #include "qhistorystate.h" #include "qkeyeventtransition.h" #include "qmouseeventtransition.h" +#include "private/qstate_p.h" #include "private/qstatemachine_p.h" // Will try to wait for the condition while allowing event processing @@ -1027,8 +1028,9 @@ void tst_QStateMachine::rootState() void tst_QStateMachine::addAndRemoveState() { QStateMachine machine; - QCOMPARE(machine.states().size(), 1); // the error state - QCOMPARE(machine.states().at(0), (QAbstractState*)machine.errorState()); + QStatePrivate *root_d = QStatePrivate::get(machine.rootState()); + QCOMPARE(root_d->childStates().size(), 1); // the error state + QCOMPARE(root_d->childStates().at(0), (QAbstractState*)machine.errorState()); QTest::ignoreMessage(QtWarningMsg, "QStateMachine::addState: cannot add null state"); machine.addState(0); @@ -1037,9 +1039,9 @@ void tst_QStateMachine::addAndRemoveState() QCOMPARE(s1->parentState(), (QState*)0); machine.addState(s1); QCOMPARE(s1->parentState(), machine.rootState()); - QCOMPARE(machine.states().size(), 2); - QCOMPARE(machine.states().at(0), (QAbstractState*)machine.errorState()); - QCOMPARE(machine.states().at(1), (QAbstractState*)s1); + QCOMPARE(root_d->childStates().size(), 2); + QCOMPARE(root_d->childStates().at(0), (QAbstractState*)machine.errorState()); + QCOMPARE(root_d->childStates().at(1), (QAbstractState*)s1); QTest::ignoreMessage(QtWarningMsg, "QStateMachine::addState: state has already been added to this machine"); machine.addState(s1); @@ -1048,24 +1050,24 @@ void tst_QStateMachine::addAndRemoveState() QCOMPARE(s2->parentState(), (QState*)0); machine.addState(s2); QCOMPARE(s2->parentState(), machine.rootState()); - QCOMPARE(machine.states().size(), 3); - QCOMPARE(machine.states().at(0), (QAbstractState*)machine.errorState()); - QCOMPARE(machine.states().at(1), (QAbstractState*)s1); - QCOMPARE(machine.states().at(2), (QAbstractState*)s2); + QCOMPARE(root_d->childStates().size(), 3); + QCOMPARE(root_d->childStates().at(0), (QAbstractState*)machine.errorState()); + QCOMPARE(root_d->childStates().at(1), (QAbstractState*)s1); + QCOMPARE(root_d->childStates().at(2), (QAbstractState*)s2); QTest::ignoreMessage(QtWarningMsg, "QStateMachine::addState: state has already been added to this machine"); machine.addState(s2); machine.removeState(s1); QCOMPARE(s1->parentState(), (QState*)0); - QCOMPARE(machine.states().size(), 2); - QCOMPARE(machine.states().at(0), (QAbstractState*)machine.errorState()); - QCOMPARE(machine.states().at(1), (QAbstractState*)s2); + QCOMPARE(root_d->childStates().size(), 2); + QCOMPARE(root_d->childStates().at(0), (QAbstractState*)machine.errorState()); + QCOMPARE(root_d->childStates().at(1), (QAbstractState*)s2); machine.removeState(s2); QCOMPARE(s2->parentState(), (QState*)0); - QCOMPARE(machine.states().size(), 1); - QCOMPARE(machine.states().at(0), (QAbstractState*)machine.errorState()); + QCOMPARE(root_d->childStates().size(), 1); + QCOMPARE(root_d->childStates().at(0), (QAbstractState*)machine.errorState()); QTest::ignoreMessage(QtWarningMsg, "QStateMachine::removeState: cannot remove null state"); machine.removeState(0); -- cgit v0.12 From 20702b4a5992a87e8edc40949ea80fa625a3fc8c Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 29 Apr 2009 14:18:55 +0200 Subject: update stale doc --- src/corelib/kernel/qcoreevent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp index f98ef8b..fa2e7b0 100644 --- a/src/corelib/kernel/qcoreevent.cpp +++ b/src/corelib/kernel/qcoreevent.cpp @@ -263,7 +263,7 @@ QT_BEGIN_NAMESPACE \omitvalue NetworkReplyUpdated \omitvalue FutureCallOut \omitvalue CocoaRequestModal - \omitvalue Bound + \omitvalue Wrapped \omitvalue Signal */ -- cgit v0.12 From 146a63c8025d4b5a20554e067d0246df9be3e68a Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 29 Apr 2009 16:00:35 +0200 Subject: SCXML defines an atomic state as a with no children or . However, in SCXML it makes no sense for a tag to be atomic, hence have no children, whereas in a dynamic state machine you might set an atomic state as parallel because this should govern the behavior if the state gets children later. We decided that the most intuitive definition is that a state is atomic if it has no children, regardless of whether it has the parallel child mode. With the old definition, transitions from empty parallel states will never be taken, as illustrated by the test. --- src/corelib/statemachine/qstatemachine.cpp | 5 ++--- tests/auto/qstatemachine/tst_qstatemachine.cpp | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 8dfb229..2f8a19e 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -772,9 +772,8 @@ bool QStateMachinePrivate::isCompound(const QAbstractState *s) bool QStateMachinePrivate::isAtomic(const QAbstractState *s) { const QState *ss = qobject_cast(s); - return (ss && (QStatePrivate::get(ss)->childMode != QState::ParallelStates) - && QStatePrivate::get(ss)->childStates().isEmpty()) - || isFinal(s); + return (ss && QStatePrivate::get(ss)->childStates().isEmpty()) + || isFinal(s); } diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 5ce0f35..3acde49 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -135,6 +135,7 @@ private slots: //void restorePolicyOnChildState(); void transitionWithParent(); + void transitionsFromParallelStateWithNoChildren(); void parallelStateTransition(); void parallelStateAssignmentsDone(); @@ -2889,6 +2890,30 @@ void tst_QStateMachine::parallelStateAssignmentsDone() QCOMPARE(propertyHolder->property("zoot").toInt(), 987); } +void tst_QStateMachine::transitionsFromParallelStateWithNoChildren() +{ + QStateMachine machine; + + QState *parallelState = new QState(QState::ParallelGroup, machine.rootState()); + machine.setInitialState(parallelState); + + QState *s1 = new QState(machine.rootState()); + parallelState->addTransition(new EventTransition(QEvent::User, s1)); + + machine.start(); + QCoreApplication::processEvents(); + + QCOMPARE(1, machine.configuration().size()); + QVERIFY(machine.configuration().contains(parallelState)); + + machine.postEvent(new QEvent(QEvent::User)); + + QCoreApplication::processEvents(); + + QCOMPARE(1, machine.configuration().size()); + QVERIFY(machine.configuration().contains(s1)); +} + void tst_QStateMachine::parallelStateTransition() { QStateMachine machine; -- cgit v0.12 From 085c0bcc85cea0d44a2a63fd7f8ebf6c4bfcaf4c Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 29 Apr 2009 16:36:19 +0200 Subject: Kill gameOver signal as it was only used when you clicked the stop action --- examples/statemachine/errorstate/mainwindow.cpp | 14 ++++++-------- examples/statemachine/errorstate/mainwindow.h | 1 - 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/examples/statemachine/errorstate/mainwindow.cpp b/examples/statemachine/errorstate/mainwindow.cpp index f5edf60..8a15e8b 100644 --- a/examples/statemachine/errorstate/mainwindow.cpp +++ b/examples/statemachine/errorstate/mainwindow.cpp @@ -110,44 +110,41 @@ void MainWindow::init() QAction *quitAction = menuBar()->addAction("&Quit"); connect(addTankAction, SIGNAL(triggered()), this, SLOT(addTank())); - connect(stopGameAction, SIGNAL(triggered()), this, SIGNAL(gameOver())); connect(quitAction, SIGNAL(triggered()), this, SLOT(close())); m_machine = new QStateMachine(this); m_machine->setGlobalRestorePolicy(QStateMachine::RestoreProperties); - QState *stoppedState = new QState(m_machine->rootState()); + QState *stoppedState = new QState(m_machine->rootState()); stoppedState->setObjectName("stoppedState"); - stoppedState->assignProperty(runGameAction, "enabled", true); stoppedState->assignProperty(stopGameAction, "enabled", false); stoppedState->assignProperty(this, "started", false); m_machine->setInitialState(stoppedState); QState *spawnsAvailable = new QState(stoppedState); - spawnsAvailable->assignProperty(addTankAction, "enabled", true); spawnsAvailable->setObjectName("spawnsAvailable"); + spawnsAvailable->assignProperty(addTankAction, "enabled", true); QState *noSpawnsAvailable = new QState(stoppedState); + noSpawnsAvailable->setObjectName("noSpawnsAvailable"); noSpawnsAvailable->assignProperty(addTankAction, "enabled", false); spawnsAvailable->addTransition(this, SIGNAL(mapFull()), noSpawnsAvailable); QHistoryState *hs = new QHistoryState(stoppedState); - hs->setObjectName("hs"); hs->setDefaultState(spawnsAvailable); stoppedState->setInitialState(hs); m_runningState = new QState(QState::ParallelGroup, m_machine->rootState()); + m_runningState->setObjectName("runningState"); m_runningState->assignProperty(addTankAction, "enabled", false); m_runningState->assignProperty(runGameAction, "enabled", false); m_runningState->assignProperty(stopGameAction, "enabled", true); stoppedState->addTransition(runGameAction, SIGNAL(triggered()), m_runningState); - m_runningState->addTransition(this, SIGNAL(gameOver()), stoppedState); - - m_machine->start(); + m_runningState->addTransition(stopGameAction, SIGNAL(triggered()), stoppedState); QTimer *timer = new QTimer(this); timer->setInterval(100); @@ -155,6 +152,7 @@ void MainWindow::init() connect(m_runningState, SIGNAL(entered()), timer, SLOT(start())); connect(m_runningState, SIGNAL(exited()), timer, SLOT(stop())); + m_machine->start(); m_time.start(); } diff --git a/examples/statemachine/errorstate/mainwindow.h b/examples/statemachine/errorstate/mainwindow.h index 33122eb..622dabe 100644 --- a/examples/statemachine/errorstate/mainwindow.h +++ b/examples/statemachine/errorstate/mainwindow.h @@ -25,7 +25,6 @@ public slots: void runStep(); signals: - void gameOver(); void mapFull(); private: -- cgit v0.12 From 9371a8069c4c0e0a00172980004c967d5dd296fd Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 29 Apr 2009 16:40:31 +0200 Subject: Compile against new QState::ChildMode API. --- examples/statemachine/errorstate/mainwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/statemachine/errorstate/mainwindow.cpp b/examples/statemachine/errorstate/mainwindow.cpp index 8a15e8b..e04ca94 100644 --- a/examples/statemachine/errorstate/mainwindow.cpp +++ b/examples/statemachine/errorstate/mainwindow.cpp @@ -137,7 +137,7 @@ void MainWindow::init() stoppedState->setInitialState(hs); - m_runningState = new QState(QState::ParallelGroup, m_machine->rootState()); + m_runningState = new QState(QState::ParallelStates, m_machine->rootState()); m_runningState->setObjectName("runningState"); m_runningState->assignProperty(addTankAction, "enabled", false); m_runningState->assignProperty(runGameAction, "enabled", false); -- cgit v0.12 From c11686d88a4329c4c86d1b7090fbe5c004c42f64 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 29 Apr 2009 16:41:12 +0200 Subject: remove multiplication by 1 in easing curves --- src/3rdparty/easing/easing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/3rdparty/easing/easing.cpp b/src/3rdparty/easing/easing.cpp index 9177c26..5bd3997 100644 --- a/src/3rdparty/easing/easing.cpp +++ b/src/3rdparty/easing/easing.cpp @@ -321,7 +321,7 @@ static qreal easeInOutExpo(qreal t) if (t==0.0) return qreal(0.0); if (t==1.0) return qreal(1.0); t*=2.0; - if (t < 1) return 0.5 * ::qPow(qreal(2.0), 10 * (t - 1)) - 1.0 * 0.0005; + if (t < 1) return 0.5 * ::qPow(qreal(2.0), 10 * (t - 1)) - 0.0005; return 0.5 * 1.0005 * (-::qPow(qreal(2.0), -10 * (t - 1)) + 2); } @@ -471,8 +471,8 @@ static qreal easeInOutElastic(qreal t, qreal a, qreal p) s = p / (2 * M_PI) * ::asin(1.0 / a); } - if (t < 1) return -.5*(a*::qPow(2.0f,10*(t-1)) * ::sin( ((t-1)*1.0-s)*(2*M_PI)/p )); - return a*::qPow(2.0f,-10*(t-1)) * ::sin( ((t-1)*1.0-s)*(2*M_PI)/p )*.5 + 1.0; + if (t < 1) return -.5*(a*::qPow(2.0f,10*(t-1)) * ::sin( (t-1-s)*(2*M_PI)/p )); + return a*::qPow(2.0f,-10*(t-1)) * ::sin( (t-1-s)*(2*M_PI)/p )*.5 + 1.0; } /** -- cgit v0.12 From b599036b8cf4eda2a12a0127a484dff659e594b8 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 29 Apr 2009 17:03:27 +0200 Subject: kill QStateMachine::animationsFinished(), introduce QState::polished() --- examples/animation/stickman/lifecycle.cpp | 4 +- src/corelib/statemachine/qstate.cpp | 16 ++ src/corelib/statemachine/qstate_p.h | 3 + src/corelib/statemachine/qstatemachine.cpp | 242 ++++++++++++++----------- src/corelib/statemachine/qstatemachine.h | 4 - src/corelib/statemachine/qstatemachine_p.h | 8 +- tests/auto/qstatemachine/tst_qstatemachine.cpp | 155 +++++++++++++++- 7 files changed, 317 insertions(+), 115 deletions(-) diff --git a/examples/animation/stickman/lifecycle.cpp b/examples/animation/stickman/lifecycle.cpp index df69d47..b22af55 100644 --- a/examples/animation/stickman/lifecycle.cpp +++ b/examples/animation/stickman/lifecycle.cpp @@ -203,14 +203,14 @@ QState *LifeCycle::makeState(QState *parentState, const QString &animationFileNa topLevel->setInitialState(frameState); } else { connectByAnimation(previousState, frameState, - new QSignalTransition(m_machine, SIGNAL(animationsFinished()))); + new QSignalTransition(previousState, SIGNAL(polished()))); } previousState = frameState; } // Loop connectByAnimation(previousState, topLevel->initialState(), - new QSignalTransition(m_machine, SIGNAL(animationsFinished()))); + new QSignalTransition(previousState, SIGNAL(polished()))); return topLevel; diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp index 173cc8d..2d59ab8 100644 --- a/src/corelib/statemachine/qstate.cpp +++ b/src/corelib/statemachine/qstate.cpp @@ -139,6 +139,12 @@ void QStatePrivate::emitFinished() emit q->finished(); } +void QStatePrivate::emitPolished() +{ + Q_Q(QState); + emit q->polished(); +} + /*! Constructs a new state with the given \a parent state. */ @@ -222,6 +228,8 @@ QList QStatePrivate::transitions() const /*! Instructs this state to set the property with the given \a name of the given \a object to the given \a value when the state is entered. + + \sa polished() */ void QState::assignProperty(QObject *object, const char *name, const QVariant &value) @@ -444,4 +452,12 @@ bool QState::event(QEvent *e) This signal is emitted when a final child state of this state is entered. */ +/*! + \fn QState::polished() + + This signal is emitted when all properties have been assigned their final value. + + \sa QState::assignProperty(), QAbstractTransition::addAnimation() +*/ + QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qstate_p.h b/src/corelib/statemachine/qstate_p.h index 0c8c858..1f913b4 100644 --- a/src/corelib/statemachine/qstate_p.h +++ b/src/corelib/statemachine/qstate_p.h @@ -63,6 +63,8 @@ QT_BEGIN_NAMESPACE struct QPropertyAssignment { + QPropertyAssignment() + : object(0) {} QPropertyAssignment(QObject *o, const QByteArray &n, const QVariant &v, bool es = true) : object(o), propertyName(n), value(v), explicitlySet(es) @@ -92,6 +94,7 @@ public: QList transitions() const; void emitFinished(); + void emitPolished(); QAbstractState *errorState; QAbstractState *initialState; diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 2f8a19e..9060f0e 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -375,13 +375,13 @@ void QStateMachinePrivate::microstep(const QList &enabledT qDebug() << q_func() << ": begin microstep( enabledTransitions:" << enabledTransitions << ")"; qDebug() << q_func() << ": configuration before exiting states:" << configuration; #endif - exitStates(enabledTransitions); + QList exitedStates = exitStates(enabledTransitions); #ifdef QSTATEMACHINE_DEBUG qDebug() << q_func() << ": configuration after exiting states:" << configuration; #endif executeTransitionContent(enabledTransitions); QList enteredStates = enterStates(enabledTransitions); - applyProperties(enabledTransitions, enteredStates); + applyProperties(enabledTransitions, exitedStates, enteredStates); #ifdef QSTATEMACHINE_DEBUG qDebug() << q_func() << ": configuration after entering states:" << configuration; qDebug() << q_func() << ": end microstep"; @@ -632,39 +632,15 @@ void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root, } void QStateMachinePrivate::applyProperties(const QList &transitionList, + const QList &exitedStates, const QList &enteredStates) { -#ifndef QT_NO_ANIMATION Q_Q(QStateMachine); - // Gracefully terminate playing animations. - for (int i = 0; i < playingAnimations.size(); ++i) - playingAnimations.at(i)->stop(); - playingAnimations.clear(); - for (int i = 0; i < resetEndValues.size(); ++i) - qobject_cast(resetEndValues.at(i))->setEndValue(QVariant()); // ### generalize - resetEndValues.clear(); - - // Find the animations to use for the state change. - QList selectedAnimations; - if (animationsEnabled) { - for (int i = 0; i < transitionList.size(); ++i) { - QAbstractTransition *transition = transitionList.at(i); - - selectedAnimations << transition->animations(); - selectedAnimations << defaultAnimationsForSource.values(transition->sourceState()); - - QList targetStates = transition->targetStates(); - for (int j=0; j propertyAssignments; + // Process the property assignments of the entered states. + QHash > propertyAssignmentsForState; QHash pendingRestorables = registeredRestorables; for (int i = 0; i < enteredStates.size(); ++i) { QState *s = qobject_cast(enteredStates.at(i)); @@ -678,53 +654,114 @@ void QStateMachinePrivate::applyProperties(const QList &tr registerRestorable(assn.object, assn.propertyName); } pendingRestorables.remove(RestorableId(assn.object, assn.propertyName)); - propertyAssignments.append(assn); + propertyAssignmentsForState[s].append(assn); } } - propertyAssignments << restorablesToPropertyList(pendingRestorables); + if (!pendingRestorables.isEmpty()) { + QAbstractState *s; + if (!enteredStates.isEmpty()) + s = enteredStates.last(); // ### handle if parallel + else + s = 0; + propertyAssignmentsForState[s] << restorablesToPropertyList(pendingRestorables); + } #ifndef QT_NO_ANIMATION - // Set the animated properties that did not finish animating and that are not - // set in the new state. - for (int i = 0; i < propertiesForAnimations.size(); ++i) { - QPropertyAssignment assn = propertiesForAnimations.at(i).second; - bool found = false; - for (int j = 0; j < propertyAssignments.size(); ++j) { - if ((propertyAssignments.at(j).object == assn.object) - && (propertyAssignments.at(j).propertyName == assn.propertyName)) { - found = true; - break; + // Gracefully terminate playing animations for states that are exited. + for (int i = 0; i < exitedStates.size(); ++i) { + QAbstractState *s = exitedStates.at(i); + QList animations = animationsForState.take(s); + for (int j = 0; j < animations.size(); ++j) { + QAbstractAnimation *anim = animations.at(j); + QObject::disconnect(anim, SIGNAL(finished()), q, SLOT(_q_animationFinished())); + stateForAnimation.remove(anim); + if (resetAnimationEndValues.contains(anim)) { + qobject_cast(anim)->setEndValue(QVariant()); // ### generalize + resetAnimationEndValues.remove(anim); + } + QPropertyAssignment assn = propertyForAnimation.take(anim); + Q_ASSERT(assn.object != 0); + // If there is no property assignment that sets this property, + // set the property to its target value. + bool found = false; + QHash >::const_iterator it; + for (it = propertyAssignmentsForState.constBegin(); it != propertyAssignmentsForState.constEnd(); ++it) { + const QList &assignments = it.value(); + for (int k = 0; k < assignments.size(); ++k) { + if ((assignments.at(k).object == assn.object) + && (assignments.at(k).propertyName == assn.propertyName)) { + found = true; + break; + } + } + } + if (!found) { + assn.object->setProperty(assn.propertyName, assn.value); } + // Stop the (top-level) animation. + // ### Stopping nested animation has weird behavior. + while (QAnimationGroup *group = anim->group()) + anim = group; + anim->stop(); } - if (!found) { - assn.object->setProperty(assn.propertyName, assn.value); + } + + // Find the animations to use for the state change. + QList selectedAnimations; + if (animationsEnabled) { + for (int i = 0; i < transitionList.size(); ++i) { + QAbstractTransition *transition = transitionList.at(i); + + selectedAnimations << transition->animations(); + selectedAnimations << defaultAnimationsForSource.values(transition->sourceState()); + + QList targetStates = transition->targetStates(); + for (int j=0; j::iterator it; - for (it = propertyAssignments.begin(); it != propertyAssignments.end(); ) { - QPair, QList > ret; - ret = initializeAnimation(anim, *it); - QList handlers = ret.first; - if (!handlers.isEmpty()) { - for (int j = 0; j < handlers.size(); ++j) - propertiesForAnimations.append(qMakePair(handlers.at(j), *it)); - it = propertyAssignments.erase(it); - } else { - ++it; + QHash >::iterator it; + for (it = propertyAssignmentsForState.begin(); it != propertyAssignmentsForState.end(); ) { + QList::iterator it2; + QAbstractState *s = it.key(); + QList &assignments = it.value(); + for (it2 = assignments.begin(); it2 != assignments.end(); ) { + QPair, QList > ret; + ret = initializeAnimation(anim, *it2); + QList handlers = ret.first; + if (!handlers.isEmpty()) { + for (int j = 0; j < handlers.size(); ++j) { + QAbstractAnimation *a = handlers.at(j); + propertyForAnimation.insert(a, *it2); + stateForAnimation.insert(a, s); + animationsForState[s].append(a); + // ### connect to just the top-level animation? + QObject::disconnect(a, SIGNAL(finished()), q, SLOT(_q_animationFinished())); + QObject::connect(a, SIGNAL(finished()), q, SLOT(_q_animationFinished())); + } + it2 = assignments.erase(it2); + } else { + ++it2; + } + for (int j = 0; j < ret.second.size(); ++j) + resetAnimationEndValues.insert(ret.second.at(j)); } - resetEndValues << ret.second; + if (assignments.isEmpty()) + it = propertyAssignmentsForState.erase(it); + else + ++it; } - // We require that at least one animation is valid. // ### generalize QList variantAnims = qFindChildren(anim); if (QVariantAnimation *va = qobject_cast(anim)) variantAnims.append(va); + bool hasValidEndValue = false; for (int j = 0; j < variantAnims.size(); ++j) { if (variantAnims.at(j)->endValue().isValid()) { @@ -734,18 +771,28 @@ void QStateMachinePrivate::applyProperties(const QList &tr } if (hasValidEndValue) { - QObject::disconnect(anim, SIGNAL(finished()), q, SLOT(_q_animationFinished())); - QObject::connect(anim, SIGNAL(finished()), q, SLOT(_q_animationFinished())); anim->start(); - playingAnimations.append(anim); } } #endif // !QT_NO_ANIMATION // Immediately set the properties that are not animated. - for (int i = 0; i < propertyAssignments.size(); ++i) { - const QPropertyAssignment &assn = propertyAssignments.at(i); - assn.object->setProperty(assn.propertyName, assn.value); + { + QHash >::const_iterator it; + for (it = propertyAssignmentsForState.constBegin(); it != propertyAssignmentsForState.constEnd(); ++it) { + const QList &assignments = it.value(); + for (int i = 0; i < assignments.size(); ++i) { + const QPropertyAssignment &assn = assignments.at(i); + assn.object->setProperty(assn.propertyName, assn.value); + } + } + } + + // Emit polished signal for entered states that have no animated properties. + for (int i = 0; i < enteredStates.size(); ++i) { + QState *s = qobject_cast(enteredStates.at(i)); + if (s && !animationsForState.contains(s)) + QStatePrivate::get(s)->emitPolished(); } } @@ -965,37 +1012,35 @@ QStateMachinePrivate::initializeAnimation(QAbstractAnimation *abstractAnimation, return qMakePair(handledAnimations, localResetEndValues); } -static bool isAncestorOf(QObject *anc, QObject *o) -{ - for (o = o->parent() ; o != 0; o = o->parent()) { - if (o == anc) - return true; - } - return false; -} - void QStateMachinePrivate::_q_animationFinished() { Q_Q(QStateMachine); - QAbstractAnimation *animation = qobject_cast(q->sender()); - Q_ASSERT(animation != 0); - QList >::iterator it; - for (it = propertiesForAnimations.begin(); it != propertiesForAnimations.end(); ) { - QAbstractAnimation *a = (*it).first; - if (a == animation || isAncestorOf(animation, a)) { - QPropertyAssignment assn = (*it).second; - assn.object->setProperty(assn.propertyName, assn.value); - if (!assn.explicitlySet) - unregisterRestorable(assn.object, assn.propertyName); - it = propertiesForAnimations.erase(it); - } else { - ++it; - } + QAbstractAnimation *anim = qobject_cast(q->sender()); + Q_ASSERT(anim != 0); + QObject::disconnect(anim, SIGNAL(finished()), q, SLOT(_q_animationFinished())); + if (resetAnimationEndValues.contains(anim)) { + qobject_cast(anim)->setEndValue(QVariant()); // ### generalize + resetAnimationEndValues.remove(anim); } - playingAnimations.removeOne(animation); - if (playingAnimations.isEmpty()) - emit q->animationsFinished(); + // Set the final property value. + QPropertyAssignment assn = propertyForAnimation.take(anim); + Q_ASSERT(assn.object != 0); + assn.object->setProperty(assn.propertyName, assn.value); + if (!assn.explicitlySet) + unregisterRestorable(assn.object, assn.propertyName); + + QAbstractState *state = stateForAnimation.take(anim); + Q_ASSERT(state != 0); + QHash >::iterator it; + it = animationsForState.find(state); + Q_ASSERT(it != animationsForState.end()); + QList &animations = it.value(); + animations.removeOne(anim); + if (animations.isEmpty()) { + animationsForState.erase(it); + QStatePrivate::get(qobject_cast(state))->emitPolished(); + } } #endif // !QT_NO_ANIMATION @@ -1056,7 +1101,8 @@ void QStateMachinePrivate::_q_start() transitions.append(initialTransition); executeTransitionContent(transitions); enterStates(transitions); - applyProperties(transitions, QList() << initial); + applyProperties(transitions, QList() << start, + QList() << initial); delete start; #ifdef QSTATEMACHINE_DEBUG @@ -1774,18 +1820,6 @@ QSet QStateMachine::configuration() const \sa QStateMachine::stop() */ -#ifndef QT_NO_ANIMATION - -/*! - \fn QStateMachine::animationsFinished() - - This signal is emitted when the state machine has finished playing all - animations associated with the latest transition (i.e., all properties have - reached their target values). -*/ - -#endif - /*! \reimp */ diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h index 6e504d0..10bd443 100644 --- a/src/corelib/statemachine/qstatemachine.h +++ b/src/corelib/statemachine/qstatemachine.h @@ -136,10 +136,6 @@ Q_SIGNALS: void stopped(); void finished(); -#ifndef QT_NO_ANIMATION - void animationsFinished(); -#endif - protected: void postInternalEvent(QEvent *event); diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index 139fee8..b3707ea 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -131,6 +131,7 @@ public: QSet &statesForDefaultEntry); void applyProperties(const QList &transitionList, + const QList &exitedStates, const QList &enteredStates); bool isInFinalState(QAbstractState *s) const; @@ -186,9 +187,10 @@ public: initializeAnimation(QAbstractAnimation *abstractAnimation, const QPropertyAssignment &prop); - QList > propertiesForAnimations; - QList playingAnimations; - QList resetEndValues; + QHash > animationsForState; + QHash propertyForAnimation; + QHash stateForAnimation; + QSet resetAnimationEndValues; QList defaultAnimations; QMultiHash defaultAnimationsForSource; diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 3acde49..7f0d39b 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -95,6 +95,8 @@ private slots: void rootState(); void addAndRemoveState(); void stateEntryAndExit(); + void assignProperty(); + void assignPropertyWithAnimation(); void postEvent(); void stateFinished(); void parallelStates(); @@ -1186,6 +1188,155 @@ void tst_QStateMachine::stateEntryAndExit() } } +void tst_QStateMachine::assignProperty() +{ + QStateMachine machine; + QState *s1 = new QState(machine.rootState()); + s1->assignProperty(s1, "objectName", "s1"); + QFinalState *s2 = new QFinalState(machine.rootState()); + s1->addTransition(s2); + machine.setInitialState(s1); + machine.start(); + QCoreApplication::processEvents(); + QCOMPARE(s1->objectName(), QString::fromLatin1("s1")); + + s1->assignProperty(s1, "objectName", "foo"); + machine.start(); + QCoreApplication::processEvents(); + QCOMPARE(s1->objectName(), QString::fromLatin1("foo")); + + s1->assignProperty(s1, "noSuchProperty", 123); + machine.start(); + QCoreApplication::processEvents(); + QCOMPARE(s1->objectName(), QString::fromLatin1("foo")); + QCOMPARE(s1->dynamicPropertyNames().size(), 1); + QCOMPARE(s1->dynamicPropertyNames().at(0), QByteArray("noSuchProperty")); + + QSignalSpy polishedSpy(s1, SIGNAL(polished())); + machine.start(); + QCoreApplication::processEvents(); + QCOMPARE(polishedSpy.count(), 1); +} + +void tst_QStateMachine::assignPropertyWithAnimation() +{ + // Single animation + { + QStateMachine machine; + QObject obj; + QState *s1 = new QState(machine.rootState()); + s1->assignProperty(&obj, "foo", 123); + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(&obj, "foo", 456); + s2->assignProperty(&obj, "bar", 789); + QAbstractTransition *trans = s1->addTransition(s2); + QPropertyAnimation anim(&obj, "foo"); + anim.setDuration(250); + trans->addAnimation(&anim); + QFinalState *s3 = new QFinalState(machine.rootState()); + s2->addTransition(s2, SIGNAL(polished()), s3); + + machine.setInitialState(s1); + QSignalSpy finishedSpy(&machine, SIGNAL(finished())); + machine.start(); + QTRY_COMPARE(finishedSpy.count(), 1); + QCOMPARE(obj.property("foo").toInt(), 456); + QCOMPARE(obj.property("bar").toInt(), 789); + } + // Two animations + { + QStateMachine machine; + QObject obj; + QState *s1 = new QState(machine.rootState()); + s1->assignProperty(&obj, "foo", 123); + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(&obj, "foo", 456); + s2->assignProperty(&obj, "bar", 789); + QAbstractTransition *trans = s1->addTransition(s2); + QPropertyAnimation anim(&obj, "foo"); + anim.setDuration(150); + trans->addAnimation(&anim); + QPropertyAnimation anim2(&obj, "bar"); + anim2.setDuration(150); + trans->addAnimation(&anim2); + QFinalState *s3 = new QFinalState(machine.rootState()); + s2->addTransition(s2, SIGNAL(polished()), s3); + + machine.setInitialState(s1); + QSignalSpy finishedSpy(&machine, SIGNAL(finished())); + machine.start(); + QTRY_COMPARE(finishedSpy.count(), 1); + QCOMPARE(obj.property("foo").toInt(), 456); + QCOMPARE(obj.property("bar").toInt(), 789); + } + // Animation group + { + QStateMachine machine; + QObject obj; + QState *s1 = new QState(machine.rootState()); + s1->assignProperty(&obj, "foo", 123); + s1->assignProperty(&obj, "bar", 321); + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(&obj, "foo", 456); + s2->assignProperty(&obj, "bar", 654); + s2->assignProperty(&obj, "baz", 789); + QAbstractTransition *trans = s1->addTransition(s2); + QSequentialAnimationGroup group; + group.addAnimation(new QPropertyAnimation(&obj, "foo")); + group.addAnimation(new QPropertyAnimation(&obj, "bar")); + trans->addAnimation(&group); + QFinalState *s3 = new QFinalState(machine.rootState()); + s2->addTransition(s2, SIGNAL(polished()), s3); + + machine.setInitialState(s1); + QSignalSpy finishedSpy(&machine, SIGNAL(finished())); + machine.start(); + QTRY_COMPARE(finishedSpy.count(), 1); + QCOMPARE(obj.property("foo").toInt(), 456); + QCOMPARE(obj.property("bar").toInt(), 654); + QCOMPARE(obj.property("baz").toInt(), 789); + } + // Nested states + { + QStateMachine machine; + QObject obj; + QState *s1 = new QState(machine.rootState()); + s1->setObjectName("s1"); + s1->assignProperty(&obj, "foo", 123); + s1->assignProperty(&obj, "bar", 456); + QState *s2 = new QState(machine.rootState()); + s2->setObjectName("s2"); + s2->assignProperty(&obj, "foo", 321); + QState *s21 = new QState(s2); + s21->setObjectName("s21"); + s21->assignProperty(&obj, "bar", 654); + QState *s22 = new QState(s2); + s22->setObjectName("s22"); + s22->assignProperty(&obj, "bar", 789); + s2->setInitialState(s21); + + QAbstractTransition *trans = s1->addTransition(s2); + QPropertyAnimation anim(&obj, "foo"); + anim.setDuration(500); + trans->addAnimation(&anim); + QPropertyAnimation anim2(&obj, "bar"); + anim2.setDuration(250); + trans->addAnimation(&anim2); + + s21->addTransition(s21, SIGNAL(polished()), s22); + + QFinalState *s3 = new QFinalState(machine.rootState()); + s22->addTransition(s2, SIGNAL(polished()), s3); + + machine.setInitialState(s1); + QSignalSpy finishedSpy(&machine, SIGNAL(finished())); + machine.start(); + QTRY_COMPARE(finishedSpy.count(), 1); + QCOMPARE(obj.property("foo").toInt(), 321); + QCOMPARE(obj.property("bar").toInt(), 789); + } +} + struct StringEvent : public QEvent { public: @@ -2113,7 +2264,7 @@ void tst_QStateMachine::twoAnimations() QState *s3 = new QState(machine.rootState()); QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); - s2->addTransition(&machine, SIGNAL(animationsFinished()), s3); + s2->addTransition(s2, SIGNAL(polished()), s3); machine.setInitialState(s1); machine.start(); @@ -2255,7 +2406,7 @@ void tst_QStateMachine::nestedTargetStateForAnimation() QState *s3 = new QState(machine.rootState()); QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); - s2->addTransition(&machine, SIGNAL(animationsFinished()), s3); + s2->addTransition(s2, SIGNAL(polished()), s3); machine.setInitialState(s1); machine.start(); -- cgit v0.12 From bfc92cacbeeb2d1a5ca39e31ccdb94f9674bd547 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 29 Apr 2009 18:47:46 +0200 Subject: Small refactor of QVariantAnimation::updateCurrentValue we only test the inequality of the new value compared to the previous one in case we have something conected to currentValueChanged signal. The comparison is quite heavy in QVariant. So avoiding it a good thing. --- src/corelib/animation/qvariantanimation.cpp | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp index 9f8cbf0..bb6cf1c 100644 --- a/src/corelib/animation/qvariantanimation.cpp +++ b/src/corelib/animation/qvariantanimation.cpp @@ -175,26 +175,16 @@ void QVariantAnimationPrivate::updateCurrentValue() endProgress = currentInterval.end.first; const qreal localProgress = (progress - startProgress) / (endProgress - startProgress); - bool changed = false; - { - //we do that here in a limited scope so that ret is dereferenced and frees memory - //and the call to updateCurrentValue can recreate QVariant of the same type (for ex. in - //QGraphicsItem::setPos - QVariant ret = q->interpolated(currentInterval.start.second, - currentInterval.end.second, - localProgress); - if (currentValue != ret) { - changed = true; - qSwap(currentValue, ret); - } - } - - if (changed) { - //the value has changed - q->updateCurrentValue(currentValue); + QVariant ret = q->interpolated(currentInterval.start.second, + currentInterval.end.second, + localProgress); + qSwap(currentValue, ret); + q->updateCurrentValue(currentValue); #ifndef QT_EXPERIMENTAL_SOLUTION if (connectedSignals & changedSignalMask) #endif + if (currentValue != ret) { + //the value has changed emit q->valueChanged(currentValue); } } -- cgit v0.12 From 0f8de3b0b4ccccbeba97999635eb5716f561fb30 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 30 Apr 2009 09:13:44 +0200 Subject: Add two AIs: They are both designed to do the same. Spin until they see a tank and then fire. One of them has an error, which causes it to enter its error state. The errorstate example has been changed to handle this by disabling the tank. The rest of the tanks will keep working. --- examples/statemachine/errorstate/gameitem.h | 5 -- examples/statemachine/errorstate/mainwindow.cpp | 19 ++++++-- examples/statemachine/errorstate/plugin.h | 2 + examples/statemachine/errorstate/rocketitem.cpp | 9 ++-- examples/statemachine/errorstate/rocketitem.h | 5 +- examples/statemachine/errorstate/tankitem.cpp | 56 ++++++++++++++++++---- examples/statemachine/errorstate/tankitem.h | 10 ++++ .../errorstateplugins/errorstateplugins.pro | 10 ++++ .../errorstateplugins/spin_ai/spin_ai.cpp | 29 +++++++++++ .../errorstateplugins/spin_ai/spin_ai.h | 44 +++++++++++++++++ .../errorstateplugins/spin_ai/spin_ai.pro | 13 +++++ .../spin_ai_with_error/spin_ai_with_error.cpp | 29 +++++++++++ .../spin_ai_with_error/spin_ai_with_error.h | 44 +++++++++++++++++ .../spin_ai_with_error/spin_ai_with_error.pro | 13 +++++ 14 files changed, 262 insertions(+), 26 deletions(-) create mode 100644 examples/statemachine/errorstateplugins/errorstateplugins.pro create mode 100644 examples/statemachine/errorstateplugins/spin_ai/spin_ai.cpp create mode 100644 examples/statemachine/errorstateplugins/spin_ai/spin_ai.h create mode 100644 examples/statemachine/errorstateplugins/spin_ai/spin_ai.pro create mode 100644 examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.cpp create mode 100644 examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.h create mode 100644 examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.pro diff --git a/examples/statemachine/errorstate/gameitem.h b/examples/statemachine/errorstate/gameitem.h index 6ca32b7..9808706 100644 --- a/examples/statemachine/errorstate/gameitem.h +++ b/examples/statemachine/errorstate/gameitem.h @@ -7,13 +7,8 @@ class QLineF; class GameItem: public QGraphicsItem { public: - enum { Type = UserType + 1 }; - - int type() const { return Type; } virtual void idle(qreal elapsed) = 0; - virtual void hitByRocket() = 0; - protected: QPointF tryMove(const QPointF &requestedPosition, QLineF *collidedLine = 0, QGraphicsItem **collidedItem = 0) const; diff --git a/examples/statemachine/errorstate/mainwindow.cpp b/examples/statemachine/errorstate/mainwindow.cpp index e04ca94..daf7be0 100644 --- a/examples/statemachine/errorstate/mainwindow.cpp +++ b/examples/statemachine/errorstate/mainwindow.cpp @@ -105,6 +105,7 @@ void MainWindow::init() QAction *addTankAction = menuBar()->addAction("&Add tank"); QAction *runGameAction = menuBar()->addAction("&Run game"); + runGameAction->setObjectName("runGameAction"); QAction *stopGameAction = menuBar()->addAction("&Stop game"); menuBar()->addSeparator(); QAction *quitAction = menuBar()->addAction("&Quit"); @@ -112,9 +113,7 @@ void MainWindow::init() connect(addTankAction, SIGNAL(triggered()), this, SLOT(addTank())); connect(quitAction, SIGNAL(triggered()), this, SLOT(close())); - m_machine = new QStateMachine(this); - m_machine->setGlobalRestorePolicy(QStateMachine::RestoreProperties); - + m_machine = new QStateMachine(this); QState *stoppedState = new QState(m_machine->rootState()); stoppedState->setObjectName("stoppedState"); stoppedState->assignProperty(runGameAction, "enabled", true); @@ -168,7 +167,11 @@ void MainWindow::runStep() qreal elapsedSecs = elapsed / 1000.0; QList items = m_scene->items(); foreach (QGraphicsItem *item, items) { - GameItem *gameItem = qgraphicsitem_cast(item); + // ### + GameItem *gameItem = qgraphicsitem_cast(item); + if (gameItem == 0) + gameItem = qgraphicsitem_cast(item); + if (gameItem != 0) gameItem->idle(elapsedSecs); } @@ -206,7 +209,13 @@ void MainWindow::addTank() emit mapFull(); QState *region = new QState(m_runningState); - region->setInitialState(plugin->create(region, tankItem)); + QState *pluginState = plugin->create(region, tankItem); + region->setInitialState(pluginState); + + // If the plugin has an error it is disabled + QState *errorState = new QState(region); + errorState->assignProperty(tankItem, "enabled", false); + pluginState->setErrorState(errorState); } } diff --git a/examples/statemachine/errorstate/plugin.h b/examples/statemachine/errorstate/plugin.h index 1ac7e0f..69b9574 100644 --- a/examples/statemachine/errorstate/plugin.h +++ b/examples/statemachine/errorstate/plugin.h @@ -1,6 +1,8 @@ #ifndef PLUGIN_H #define PLUGIN_H +#include + class QState; class Tank; class Plugin diff --git a/examples/statemachine/errorstate/rocketitem.cpp b/examples/statemachine/errorstate/rocketitem.cpp index de9eef7..85d436b 100644 --- a/examples/statemachine/errorstate/rocketitem.cpp +++ b/examples/statemachine/errorstate/rocketitem.cpp @@ -1,4 +1,5 @@ #include "rocketitem.h" +#include "tankitem.h" #include #include @@ -25,10 +26,6 @@ void RocketItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWid painter->drawEllipse(boundingRect()); } -void RocketItem::hitByRocket() -{ -} - void RocketItem::idle(qreal elapsed) { qreal dist = elapsed * speed(); @@ -51,8 +48,8 @@ void RocketItem::idle(qreal elapsed) if (requestedPosition == nextPosition) { setPos(nextPosition); } else { - if (GameItem *gameItem = qgraphicsitem_cast(collidedItem)) - gameItem->hitByRocket(); + if (TankItem *tankItem = qgraphicsitem_cast(collidedItem)) + tankItem->hitByRocket(); scene()->removeItem(this); delete this; diff --git a/examples/statemachine/errorstate/rocketitem.h b/examples/statemachine/errorstate/rocketitem.h index 9805a8a..b055b0a 100644 --- a/examples/statemachine/errorstate/rocketitem.h +++ b/examples/statemachine/errorstate/rocketitem.h @@ -6,13 +6,14 @@ class RocketItem: public GameItem { public: + enum { Type = UserType + 2 }; + RocketItem(); + int type() const { return Type; } virtual void idle(qreal elapsed); qreal speed() const { return 100.0; } void setDirection(qreal direction) { m_direction = direction; } - - void hitByRocket(); protected: virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); diff --git a/examples/statemachine/errorstate/tankitem.cpp b/examples/statemachine/errorstate/tankitem.cpp index 814de2b..705623c 100644 --- a/examples/statemachine/errorstate/tankitem.cpp +++ b/examples/statemachine/errorstate/tankitem.cpp @@ -85,17 +85,25 @@ private: bool m_reverse; }; -TankItem::TankItem(QObject *parent) : Tank(parent), m_currentAction(0), m_currentDirection(0.0) +TankItem::TankItem(QObject *parent) + : Tank(parent), m_currentAction(0), m_currentDirection(0.0), m_enabled(true) { connect(this, SIGNAL(fireCannon()), this, SIGNAL(actionCompleted())); } void TankItem::idle(qreal elapsed) { - if (m_currentAction != 0) { - if (!m_currentAction->apply(elapsed)) { - setAction(0); - emit actionCompleted(); + if (m_enabled) { + if (m_currentAction != 0) { + if (!m_currentAction->apply(elapsed)) { + setAction(0); + emit actionCompleted(); + } + + QGraphicsItem *item = 0; + qreal distance = distanceToObstacle(&item); + if (TankItem *tankItem = qgraphicsitem_cast(item)) + emit tankSpotted(tankItem->direction(), distance); } } } @@ -176,6 +184,17 @@ void TankItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidge QPointF(brect.right() - 2.0, brect.bottom())); painter->fillRect(rightTrackRect, Qt::darkYellow); painter->drawRect(rightTrackRect); + + if (!m_enabled) { + painter->setPen(QPen(Qt::red, 5)); + + painter->drawEllipse(brect); + + QPainterPath path; + path.addEllipse(brect); + painter->setClipPath(path); + painter->drawLine(brect.topRight(), brect.bottomLeft()); + } } QRectF TankItem::boundingRect() const @@ -195,11 +214,32 @@ void TankItem::setDirection(qreal newDirection) rotate(diff); } -qreal TankItem::distanceToObstacle() const +qreal TankItem::distanceToObstacle(QGraphicsItem **obstacle) const { - // ### + qreal dist = sqrt(pow(scene()->sceneRect().width(), 2) + pow(scene()->sceneRect().height(), 2)); + + qreal a = m_currentDirection * M_PI / 180.0; + + qreal yd = dist * sin(a); + qreal xd = dist * sin(M_PI / 2.0 - a); - return 0.0; + QPointF requestedPosition = pos() + QPointF(xd, yd); + QGraphicsItem *collidedItem = 0; + QPointF nextPosition = tryMove(requestedPosition, 0, &collidedItem); + if (collidedItem != 0) { + if (obstacle != 0) + *obstacle = collidedItem; + + QPointF d = nextPosition - pos(); + return sqrt(pow(d.x(), 2) + pow(d.y(), 2)); + } else { + return 0.0; + } +} + +qreal TankItem::distanceToObstacle() const +{ + return distanceToObstacle(0); } diff --git a/examples/statemachine/errorstate/tankitem.h b/examples/statemachine/errorstate/tankitem.h index c9e0d22..e598cfd 100644 --- a/examples/statemachine/errorstate/tankitem.h +++ b/examples/statemachine/errorstate/tankitem.h @@ -10,8 +10,13 @@ class Action; class TankItem: public Tank, public GameItem { Q_OBJECT + Q_PROPERTY(bool enabled READ enabled WRITE setEnabled) public: + enum { Type = UserType + 1 }; + TankItem(QObject *parent = 0); + + int type() const { return Type; } virtual void moveForwards(qreal length); virtual void moveBackwards(qreal length); @@ -19,6 +24,7 @@ public: virtual void stop(); virtual qreal direction() const; virtual qreal distanceToObstacle() const; + virtual qreal distanceToObstacle(QGraphicsItem **item) const; void setColor(const QColor &color) { m_color = color; } QColor color() const { return m_color; } @@ -33,6 +39,9 @@ public: void hitByRocket(); + void setEnabled(bool b) { m_enabled = b; } + bool enabled() const { return m_enabled; } + signals: virtual void fireCannon(); @@ -46,6 +55,7 @@ private: Action *m_currentAction; qreal m_currentDirection; QColor m_color; + bool m_enabled; }; #endif diff --git a/examples/statemachine/errorstateplugins/errorstateplugins.pro b/examples/statemachine/errorstateplugins/errorstateplugins.pro new file mode 100644 index 0000000..e7718a9 --- /dev/null +++ b/examples/statemachine/errorstateplugins/errorstateplugins.pro @@ -0,0 +1,10 @@ +TEMPLATE = subdirs +SUBDIRS = random_ai \ + spin_ai_with_error \ + spin_ai + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstateplugins +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS errorstateplugins.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstateplugins +INSTALLS += target sources diff --git a/examples/statemachine/errorstateplugins/spin_ai/spin_ai.cpp b/examples/statemachine/errorstateplugins/spin_ai/spin_ai.cpp new file mode 100644 index 0000000..8452523 --- /dev/null +++ b/examples/statemachine/errorstateplugins/spin_ai/spin_ai.cpp @@ -0,0 +1,29 @@ +#include "spin_ai.h" + +#include + +QState *SpinAi::create(QState *parentState, Tank *tank) +{ + QState *topLevel = new QState(parentState); + QState *spinState = new SpinState(tank, topLevel); + topLevel->setInitialState(spinState); + + // When tank is spotted, fire two times and go back to spin state + QState *fireState = new QState(topLevel); + + QState *fireOnce = new QState(fireState); + fireState->setInitialState(fireOnce); + connect(fireOnce, SIGNAL(entered()), tank, SLOT(fireCannon())); + + QState *fireTwice = new QState(fireState); + connect(fireTwice, SIGNAL(entered()), tank, SLOT(fireCannon())); + + fireOnce->addTransition(tank, SIGNAL(actionCompleted()), fireTwice); + fireTwice->addTransition(tank, SIGNAL(actionCompleted()), spinState); + + spinState->addTransition(tank, SIGNAL(tankSpotted(qreal,qreal)), fireState); + + return topLevel; +} + +Q_EXPORT_PLUGIN2(spin_ai, SpinAi) diff --git a/examples/statemachine/errorstateplugins/spin_ai/spin_ai.h b/examples/statemachine/errorstateplugins/spin_ai/spin_ai.h new file mode 100644 index 0000000..7336640 --- /dev/null +++ b/examples/statemachine/errorstateplugins/spin_ai/spin_ai.h @@ -0,0 +1,44 @@ +#ifndef SPIN_AI_H +#define SPIN_AI_H + +#include +#include + +#include +#include + +class SpinState: public QState +{ + Q_OBJECT +public: + SpinState(Tank *tank, QState *parent) : QState(parent), m_tank(tank) + { + } + +public slots: + void spin() + { + m_tank->turn(90.0); + } + +protected: + void onEntry() + { + connect(m_tank, SIGNAL(actionCompleted()), this, SLOT(spin())); + spin(); + } + +private: + Tank *m_tank; + +}; + +class SpinAi: public QObject, public Plugin +{ + Q_OBJECT + Q_INTERFACES(Plugin) +public: + virtual QState *create(QState *parentState, Tank *tank); +}; + +#endif diff --git a/examples/statemachine/errorstateplugins/spin_ai/spin_ai.pro b/examples/statemachine/errorstateplugins/spin_ai/spin_ai.pro new file mode 100644 index 0000000..c2fd937 --- /dev/null +++ b/examples/statemachine/errorstateplugins/spin_ai/spin_ai.pro @@ -0,0 +1,13 @@ +TEMPLATE = lib +CONFIG += plugin +INCLUDEPATH += ../.. +HEADERS = spin_ai.h +SOURCES = spin_ai.cpp +TARGET = $$qtLibraryTarget(spin_ai) +DESTDIR = ../../errorstate/plugins + +#! [0] +# install +target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstate/plugins +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS spin_ai.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstateplugins/spin_ai \ No newline at end of file diff --git a/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.cpp b/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.cpp new file mode 100644 index 0000000..dd73270 --- /dev/null +++ b/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.cpp @@ -0,0 +1,29 @@ +#include "spin_ai_with_error.h" + +#include + +QState *SpinAiWithError::create(QState *parentState, Tank *tank) +{ + QState *topLevel = new QState(parentState); + QState *spinState = new SpinState(tank, topLevel); + topLevel->setInitialState(spinState); + + // When tank is spotted, fire two times and go back to spin state + // (no initial state set for fireState will lead to run-time error in machine) + QState *fireState = new QState(topLevel); + + QState *fireOnce = new QState(fireState); + connect(fireOnce, SIGNAL(entered()), tank, SLOT(fireCannon())); + + QState *fireTwice = new QState(fireState); + connect(fireTwice, SIGNAL(entered()), tank, SLOT(fireCannon())); + + fireOnce->addTransition(tank, SIGNAL(actionCompleted()), fireTwice); + fireTwice->addTransition(tank, SIGNAL(actionCompleted()), spinState); + + spinState->addTransition(tank, SIGNAL(tankSpotted(qreal,qreal)), fireState); + + return topLevel; +} + +Q_EXPORT_PLUGIN2(spin_ai_with_error, SpinAiWithError) diff --git a/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.h b/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.h new file mode 100644 index 0000000..26def66 --- /dev/null +++ b/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.h @@ -0,0 +1,44 @@ +#ifndef SPIN_AI_WITH_ERROR_H +#define SPIN_AI_WITH_ERROR_H + +#include +#include + +#include +#include + +class SpinState: public QState +{ + Q_OBJECT +public: + SpinState(Tank *tank, QState *parent) : QState(parent), m_tank(tank) + { + } + +public slots: + void spin() + { + m_tank->turn(90.0); + } + +protected: + void onEntry() + { + connect(m_tank, SIGNAL(actionCompleted()), this, SLOT(spin())); + spin(); + } + +private: + Tank *m_tank; + +}; + +class SpinAiWithError: public QObject, public Plugin +{ + Q_OBJECT + Q_INTERFACES(Plugin) +public: + virtual QState *create(QState *parentState, Tank *tank); +}; + +#endif diff --git a/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.pro b/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.pro new file mode 100644 index 0000000..31f4c7f --- /dev/null +++ b/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.pro @@ -0,0 +1,13 @@ +TEMPLATE = lib +CONFIG += plugin +INCLUDEPATH += ../.. +HEADERS = spin_ai_with_error.h +SOURCES = spin_ai_with_error.cpp +TARGET = $$qtLibraryTarget(spin_ai_with_error) +DESTDIR = ../../errorstate/plugins + +#! [0] +# install +target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstate/plugins +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS spin_ai_with_error.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstateplugins/spin_ai_with_error \ No newline at end of file -- cgit v0.12 From 0d33e6e464c324d1b43b08ce7ac0dcd4c216d17e Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 30 Apr 2009 09:43:13 +0200 Subject: Make design better. Remove the Tank interface. This is now an implicit interface based on the meta-object system. --- examples/statemachine/errorstate/errorstate.pro | 2 +- examples/statemachine/errorstate/gameitem.cpp | 4 +++ examples/statemachine/errorstate/gameitem.h | 8 ++++- examples/statemachine/errorstate/mainwindow.cpp | 9 ++---- examples/statemachine/errorstate/plugin.h | 3 +- examples/statemachine/errorstate/rocketitem.cpp | 11 ++++--- examples/statemachine/errorstate/rocketitem.h | 7 ++-- examples/statemachine/errorstate/tank.h | 31 ------------------ examples/statemachine/errorstate/tankitem.cpp | 9 ++++-- examples/statemachine/errorstate/tankitem.h | 37 ++++++++++++---------- .../random_ai/random_ai_plugin.cpp | 4 +-- .../errorstateplugins/random_ai/random_ai_plugin.h | 2 +- .../errorstateplugins/spin_ai/spin_ai.cpp | 2 +- .../errorstateplugins/spin_ai/spin_ai.h | 10 +++--- .../spin_ai_with_error/spin_ai_with_error.cpp | 2 +- .../spin_ai_with_error/spin_ai_with_error.h | 10 +++--- 16 files changed, 65 insertions(+), 86 deletions(-) delete mode 100644 examples/statemachine/errorstate/tank.h diff --git a/examples/statemachine/errorstate/errorstate.pro b/examples/statemachine/errorstate/errorstate.pro index c159f94..b93a691 100644 --- a/examples/statemachine/errorstate/errorstate.pro +++ b/examples/statemachine/errorstate/errorstate.pro @@ -8,6 +8,6 @@ DEPENDPATH += . INCLUDEPATH += C:/dev/kinetic/examples/statemachine/errorstate/. . # Input -HEADERS += mainwindow.h plugin.h tank.h tankitem.h rocketitem.h gameitem.h +HEADERS += mainwindow.h plugin.h tankitem.h rocketitem.h gameitem.h SOURCES += main.cpp mainwindow.cpp tankitem.cpp rocketitem.cpp gameitem.cpp CONFIG += console diff --git a/examples/statemachine/errorstate/gameitem.cpp b/examples/statemachine/errorstate/gameitem.cpp index 786cf51..d286df4 100644 --- a/examples/statemachine/errorstate/gameitem.cpp +++ b/examples/statemachine/errorstate/gameitem.cpp @@ -2,6 +2,10 @@ #include +GameItem::GameItem(QObject *parent) : QObject(parent) +{ +} + QPointF GameItem::tryMove(const QPointF &requestedPosition, QLineF *collidedLine, QGraphicsItem **collidedItem) const { diff --git a/examples/statemachine/errorstate/gameitem.h b/examples/statemachine/errorstate/gameitem.h index 9808706..43b8785 100644 --- a/examples/statemachine/errorstate/gameitem.h +++ b/examples/statemachine/errorstate/gameitem.h @@ -4,9 +4,15 @@ #include class QLineF; -class GameItem: public QGraphicsItem +class GameItem: public QObject, public QGraphicsItem { + Q_OBJECT public: + enum { Type = UserType + 1 }; + int type() const { return Type; } + + GameItem(QObject *parent = 0); + virtual void idle(qreal elapsed) = 0; protected: diff --git a/examples/statemachine/errorstate/mainwindow.cpp b/examples/statemachine/errorstate/mainwindow.cpp index daf7be0..4d9b88e 100644 --- a/examples/statemachine/errorstate/mainwindow.cpp +++ b/examples/statemachine/errorstate/mainwindow.cpp @@ -167,12 +167,7 @@ void MainWindow::runStep() qreal elapsedSecs = elapsed / 1000.0; QList items = m_scene->items(); foreach (QGraphicsItem *item, items) { - // ### - GameItem *gameItem = qgraphicsitem_cast(item); - if (gameItem == 0) - gameItem = qgraphicsitem_cast(item); - - if (gameItem != 0) + if (GameItem *gameItem = qgraphicsitem_cast(item)) gameItem->idle(elapsedSecs); } } @@ -204,7 +199,7 @@ void MainWindow::addTank() if (plugin != 0) { TankItem *tankItem = m_spawns.takeLast(); m_scene->addItem(tankItem); - connect(tankItem, SIGNAL(fireCannon()), this, SLOT(addRocket())); + connect(tankItem, SIGNAL(cannonFired()), this, SLOT(addRocket())); if (m_spawns.isEmpty()) emit mapFull(); diff --git a/examples/statemachine/errorstate/plugin.h b/examples/statemachine/errorstate/plugin.h index 69b9574..2b48d43 100644 --- a/examples/statemachine/errorstate/plugin.h +++ b/examples/statemachine/errorstate/plugin.h @@ -4,13 +4,12 @@ #include class QState; -class Tank; class Plugin { public: virtual ~Plugin() {} - virtual QState *create(QState *parentState, Tank *tank) = 0; + virtual QState *create(QState *parentState, QObject *tank) = 0; }; Q_DECLARE_INTERFACE(Plugin, "TankPlugin") diff --git a/examples/statemachine/errorstate/rocketitem.cpp b/examples/statemachine/errorstate/rocketitem.cpp index 85d436b..c324980 100644 --- a/examples/statemachine/errorstate/rocketitem.cpp +++ b/examples/statemachine/errorstate/rocketitem.cpp @@ -10,8 +10,8 @@ #define M_PI 3.14159265358979323846 #endif -RocketItem::RocketItem() - : m_direction(0.0), m_distance(300.0) +RocketItem::RocketItem(QObject *parent) + : GameItem(parent), m_direction(0.0), m_distance(300.0) { } @@ -48,8 +48,11 @@ void RocketItem::idle(qreal elapsed) if (requestedPosition == nextPosition) { setPos(nextPosition); } else { - if (TankItem *tankItem = qgraphicsitem_cast(collidedItem)) - tankItem->hitByRocket(); + if (GameItem *gameItem = qgraphicsitem_cast(collidedItem)) { + TankItem *tankItem = qobject_cast(gameItem); + if (tankItem != 0) + tankItem->hitByRocket(); + } scene()->removeItem(this); delete this; diff --git a/examples/statemachine/errorstate/rocketitem.h b/examples/statemachine/errorstate/rocketitem.h index b055b0a..189a1dd 100644 --- a/examples/statemachine/errorstate/rocketitem.h +++ b/examples/statemachine/errorstate/rocketitem.h @@ -5,12 +5,10 @@ class RocketItem: public GameItem { + Q_OBJECT public: - enum { Type = UserType + 2 }; + RocketItem(QObject *parent = 0); - RocketItem(); - - int type() const { return Type; } virtual void idle(qreal elapsed); qreal speed() const { return 100.0; } void setDirection(qreal direction) { m_direction = direction; } @@ -19,7 +17,6 @@ protected: virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); QRectF boundingRect() const; - private: qreal m_direction; qreal m_distance; diff --git a/examples/statemachine/errorstate/tank.h b/examples/statemachine/errorstate/tank.h deleted file mode 100644 index 49c5daf..0000000 --- a/examples/statemachine/errorstate/tank.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef TANK_H -#define TANK_H - -#include -#include - -class Tank: public QObject -{ - Q_OBJECT - Q_PROPERTY(qreal direction READ direction) - Q_PROPERTY(qreal distanceToObstacle READ distanceToObstacle) -public: - Tank(QObject *parent = 0) : QObject(parent) {} - - virtual qreal direction() const = 0; - virtual qreal distanceToObstacle() const = 0; - -signals: - void collision(const QLineF &collidedLine) const; - void actionCompleted(); - void tankSpotted(qreal otherTankDirection, qreal distance); - -public slots: - virtual void moveForwards(qreal length) = 0; - virtual void moveBackwards(qreal length) = 0; - virtual void turn(qreal degrees) = 0; - virtual void stop() = 0; - virtual void fireCannon() = 0; -}; - -#endif diff --git a/examples/statemachine/errorstate/tankitem.cpp b/examples/statemachine/errorstate/tankitem.cpp index 705623c..ae338fe 100644 --- a/examples/statemachine/errorstate/tankitem.cpp +++ b/examples/statemachine/errorstate/tankitem.cpp @@ -86,9 +86,9 @@ private: }; TankItem::TankItem(QObject *parent) - : Tank(parent), m_currentAction(0), m_currentDirection(0.0), m_enabled(true) + : GameItem(parent), m_currentAction(0), m_currentDirection(0.0), m_enabled(true) { - connect(this, SIGNAL(fireCannon()), this, SIGNAL(actionCompleted())); + connect(this, SIGNAL(cannonFired()), this, SIGNAL(actionCompleted())); } void TankItem::idle(qreal elapsed) @@ -121,6 +121,11 @@ void TankItem::setAction(Action *newAction) m_currentAction = newAction; } +void TankItem::fireCannon() +{ + emit cannonFired(); +} + void TankItem::moveForwards(qreal length) { setAction(new MoveAction(this, length)); diff --git a/examples/statemachine/errorstate/tankitem.h b/examples/statemachine/errorstate/tankitem.h index e598cfd..45016ec 100644 --- a/examples/statemachine/errorstate/tankitem.h +++ b/examples/statemachine/errorstate/tankitem.h @@ -1,31 +1,20 @@ #ifndef TANKITEM_H #define TANKITEM_H -#include "tank.h" #include "gameitem.h" #include class Action; -class TankItem: public Tank, public GameItem +class TankItem: public GameItem { Q_OBJECT Q_PROPERTY(bool enabled READ enabled WRITE setEnabled) -public: - enum { Type = UserType + 1 }; - + Q_PROPERTY(qreal direction READ direction WRITE turn) + Q_PROPERTY(qreal distanceToObstacle READ distanceToObstacle) +public: TankItem(QObject *parent = 0); - - int type() const { return Type; } - - virtual void moveForwards(qreal length); - virtual void moveBackwards(qreal length); - virtual void turn(qreal newDirection); - virtual void stop(); - virtual qreal direction() const; - virtual qreal distanceToObstacle() const; - virtual qreal distanceToObstacle(QGraphicsItem **item) const; - + void setColor(const QColor &color) { m_color = color; } QColor color() const { return m_color; } @@ -42,8 +31,22 @@ public: void setEnabled(bool b) { m_enabled = b; } bool enabled() const { return m_enabled; } + qreal direction() const; + qreal distanceToObstacle() const; + qreal distanceToObstacle(QGraphicsItem **item) const; + signals: - virtual void fireCannon(); + void tankSpotted(qreal direction, qreal distance); + void collision(const QLineF &collidedLine); + void actionCompleted(); + void cannonFired(); + +public slots: + void moveForwards(qreal length); + void moveBackwards(qreal length); + void turn(qreal newDirection); + void stop(); + void fireCannon(); protected: virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); diff --git a/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.cpp b/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.cpp index 135c7b6..c196247 100644 --- a/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.cpp +++ b/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.cpp @@ -1,13 +1,11 @@ #include "random_ai_plugin.h" -#include - #include #include #include -QState *RandomAiPlugin::create(QState *parentState, Tank *tank) +QState *RandomAiPlugin::create(QState *parentState, QObject *tank) { qsrand(uint(time(NULL))); diff --git a/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.h b/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.h index 758b3e8..d3670bd 100644 --- a/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.h +++ b/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.h @@ -56,7 +56,7 @@ class RandomAiPlugin: public QObject, public Plugin Q_OBJECT Q_INTERFACES(Plugin) public: - virtual QState *create(QState *parentState, Tank *tank); + virtual QState *create(QState *parentState, QObject *tank); }; #endif // RANDOM_AI_PLUGIN_H diff --git a/examples/statemachine/errorstateplugins/spin_ai/spin_ai.cpp b/examples/statemachine/errorstateplugins/spin_ai/spin_ai.cpp index 8452523..de95f41 100644 --- a/examples/statemachine/errorstateplugins/spin_ai/spin_ai.cpp +++ b/examples/statemachine/errorstateplugins/spin_ai/spin_ai.cpp @@ -2,7 +2,7 @@ #include -QState *SpinAi::create(QState *parentState, Tank *tank) +QState *SpinAi::create(QState *parentState, QObject *tank) { QState *topLevel = new QState(parentState); QState *spinState = new SpinState(tank, topLevel); diff --git a/examples/statemachine/errorstateplugins/spin_ai/spin_ai.h b/examples/statemachine/errorstateplugins/spin_ai/spin_ai.h index 7336640..309ba14 100644 --- a/examples/statemachine/errorstateplugins/spin_ai/spin_ai.h +++ b/examples/statemachine/errorstateplugins/spin_ai/spin_ai.h @@ -2,23 +2,23 @@ #define SPIN_AI_H #include -#include #include #include +#include class SpinState: public QState { Q_OBJECT public: - SpinState(Tank *tank, QState *parent) : QState(parent), m_tank(tank) + SpinState(QObject *tank, QState *parent) : QState(parent), m_tank(tank) { } public slots: void spin() { - m_tank->turn(90.0); + m_tank->setProperty("direction", 90.0); } protected: @@ -29,7 +29,7 @@ protected: } private: - Tank *m_tank; + QObject *m_tank; }; @@ -38,7 +38,7 @@ class SpinAi: public QObject, public Plugin Q_OBJECT Q_INTERFACES(Plugin) public: - virtual QState *create(QState *parentState, Tank *tank); + virtual QState *create(QState *parentState, QObject *tank); }; #endif diff --git a/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.cpp b/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.cpp index dd73270..5499ba3 100644 --- a/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.cpp +++ b/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.cpp @@ -2,7 +2,7 @@ #include -QState *SpinAiWithError::create(QState *parentState, Tank *tank) +QState *SpinAiWithError::create(QState *parentState, QObject *tank) { QState *topLevel = new QState(parentState); QState *spinState = new SpinState(tank, topLevel); diff --git a/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.h b/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.h index 26def66..fa06d10 100644 --- a/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.h +++ b/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.h @@ -2,23 +2,23 @@ #define SPIN_AI_WITH_ERROR_H #include -#include #include #include +#include class SpinState: public QState { Q_OBJECT public: - SpinState(Tank *tank, QState *parent) : QState(parent), m_tank(tank) + SpinState(QObject *tank, QState *parent) : QState(parent), m_tank(tank) { } public slots: void spin() { - m_tank->turn(90.0); + m_tank->setProperty("direction", 90.0); } protected: @@ -29,7 +29,7 @@ protected: } private: - Tank *m_tank; + QObject *m_tank; }; @@ -38,7 +38,7 @@ class SpinAiWithError: public QObject, public Plugin Q_OBJECT Q_INTERFACES(Plugin) public: - virtual QState *create(QState *parentState, Tank *tank); + virtual QState *create(QState *parentState, QObject *tank); }; #endif -- cgit v0.12 From 9e6311a7fd23a9fb7bb3a8a8edc78cddddc3f807 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 30 Apr 2009 09:49:09 +0200 Subject: The intuitive interpretation of RestoreProperties is that a value is potentially restored once the state that set it is exited. So if you have a parent state P which sets 'foo' and then several child states of P, the property should not be restored as long as P is active, regardless of which transitions are taken inside P and what properties are being assigned there. Before, we would restore the property when we entered a state that did not assign it, ignoring what properties where being assigned in the parent. --- src/corelib/statemachine/qstatemachine.cpp | 11 +++++ tests/auto/qstatemachine/tst_qstatemachine.cpp | 56 +++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 9060f0e..81d65d5 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -656,6 +656,17 @@ void QStateMachinePrivate::applyProperties(const QList &tr pendingRestorables.remove(RestorableId(assn.object, assn.propertyName)); propertyAssignmentsForState[s].append(assn); } + + // Remove pending restorables for all parent states to avoid restoring properties + // before the state that assigned them is exited. + QState *parentState = s; + while (parentState = parentState->parentState()) { + assignments = QStatePrivate::get(parentState)->propertyAssignments; + for (int j=0; jsetProperty("foo", 1); + propertyHolder->setProperty("bar", 2); + + QState *s1 = new QState(machine.rootState()); + machine.setInitialState(s1); + + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(propertyHolder, "foo", 3); + + QState *s21 = new QState(s2); + s21->assignProperty(propertyHolder, "bar", 4); + s2->setInitialState(s21); + + QState *s22 = new QState(s2); + s22->assignProperty(propertyHolder, "bar", 5); + + s1->addTransition(new EventTransition(QEvent::User, s2)); + s21->addTransition(new EventTransition(QEvent::User, s22)); + + machine.start(); + QCoreApplication::processEvents(); + + QCOMPARE(machine.configuration().size(), 1); + QVERIFY(machine.configuration().contains(s1)); + QCOMPARE(propertyHolder->property("foo").toInt(), 1); + QCOMPARE(propertyHolder->property("bar").toInt(), 2); + + machine.postEvent(new QEvent(QEvent::User)); + QCoreApplication::processEvents(); + + QCOMPARE(machine.configuration().size(), 2); + QVERIFY(machine.configuration().contains(s2)); + QVERIFY(machine.configuration().contains(s21)); + QCOMPARE(propertyHolder->property("foo").toInt(), 3); + QCOMPARE(propertyHolder->property("bar").toInt(), 4); + + machine.postEvent(new QEvent(QEvent::User)); + QCoreApplication::processEvents(); + + QCOMPARE(machine.configuration().size(), 2); + QVERIFY(machine.configuration().contains(s2)); + QVERIFY(machine.configuration().contains(s22)); + QCOMPARE(propertyHolder->property("foo").toInt(), 3); + QCOMPARE(propertyHolder->property("bar").toInt(), 5); +} + + QTEST_MAIN(tst_QStateMachine) #include "tst_qstatemachine.moc" -- cgit v0.12 From 18e848faad9289f6052249ef4fe6a20f0654b786 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 30 Apr 2009 10:09:09 +0200 Subject: When restoring properties in descendants of a state which assigns it a value, the property should be restored to the value assigned by the ancestor state. When restoreProperties is on, assigning a value in a state means it will have that value as long as the state is active, unless an active state deeper in the hierarchy assigns it a different value. This is basically a stack of "initial" values, but implemented using the parent hierarchy of the state instead. --- src/corelib/statemachine/qstatemachine.cpp | 7 ++- tests/auto/qstatemachine/tst_qstatemachine.cpp | 64 ++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 81d65d5..0ebc993 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -658,13 +658,16 @@ void QStateMachinePrivate::applyProperties(const QList &tr } // Remove pending restorables for all parent states to avoid restoring properties - // before the state that assigned them is exited. + // before the state that assigned them is exited. If state does not explicitly + // assign a property which is assigned by the parent, it inherits the parent's assignment. QState *parentState = s; while (parentState = parentState->parentState()) { assignments = QStatePrivate::get(parentState)->propertyAssignments; for (int j=0; j 0) + propertyAssignmentsForState[s].append(assn); } } } diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index fa4c233..80bf674 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -141,6 +141,7 @@ private slots: void parallelStateTransition(); void parallelStateAssignmentsDone(); void nestedRestoreProperties(); + void nestedRestoreProperties2(); void simpleAnimation(); void twoAnimations(); @@ -3162,6 +3163,69 @@ void tst_QStateMachine::nestedRestoreProperties() QCOMPARE(propertyHolder->property("bar").toInt(), 5); } +void tst_QStateMachine::nestedRestoreProperties2() +{ + QStateMachine machine; + machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties); + + QObject *propertyHolder = new QObject(&machine); + propertyHolder->setProperty("foo", 1); + propertyHolder->setProperty("bar", 2); + + QState *s1 = new QState(machine.rootState()); + machine.setInitialState(s1); + + QState *s2 = new QState(machine.rootState()); + s2->assignProperty(propertyHolder, "foo", 3); + + QState *s21 = new QState(s2); + s21->assignProperty(propertyHolder, "bar", 4); + s2->setInitialState(s21); + + QState *s22 = new QState(s2); + s22->assignProperty(propertyHolder, "foo", 6); + s22->assignProperty(propertyHolder, "bar", 5); + + s1->addTransition(new EventTransition(QEvent::User, s2)); + s21->addTransition(new EventTransition(QEvent::User, s22)); + s22->addTransition(new EventTransition(QEvent::User, s21)); + + machine.start(); + QCoreApplication::processEvents(); + + QCOMPARE(machine.configuration().size(), 1); + QVERIFY(machine.configuration().contains(s1)); + QCOMPARE(propertyHolder->property("foo").toInt(), 1); + QCOMPARE(propertyHolder->property("bar").toInt(), 2); + + machine.postEvent(new QEvent(QEvent::User)); + QCoreApplication::processEvents(); + + QCOMPARE(machine.configuration().size(), 2); + QVERIFY(machine.configuration().contains(s2)); + QVERIFY(machine.configuration().contains(s21)); + QCOMPARE(propertyHolder->property("foo").toInt(), 3); + QCOMPARE(propertyHolder->property("bar").toInt(), 4); + + machine.postEvent(new QEvent(QEvent::User)); + QCoreApplication::processEvents(); + + QCOMPARE(machine.configuration().size(), 2); + QVERIFY(machine.configuration().contains(s2)); + QVERIFY(machine.configuration().contains(s22)); + QCOMPARE(propertyHolder->property("foo").toInt(), 6); + QCOMPARE(propertyHolder->property("bar").toInt(), 5); + + machine.postEvent(new QEvent(QEvent::User)); + QCoreApplication::processEvents(); + + QCOMPARE(machine.configuration().size(), 2); + QVERIFY(machine.configuration().contains(s2)); + QVERIFY(machine.configuration().contains(s21)); + QCOMPARE(propertyHolder->property("foo").toInt(), 3); + QCOMPARE(propertyHolder->property("bar").toInt(), 4); + +} QTEST_MAIN(tst_QStateMachine) -- cgit v0.12 From 1e4e05144dd8a0c642b6a7f77aa53fa6975d89d9 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 30 Apr 2009 12:49:14 +0200 Subject: Add unfinished "more advanced" AI for errorstate. --- examples/statemachine/errorstate/tankitem.cpp | 5 + examples/statemachine/errorstate/tankitem.h | 9 +- .../errorstateplugins/errorstateplugins.pro | 3 +- .../errorstateplugins/seek_ai/seek_ai.cpp | 42 ++++++++ .../errorstateplugins/seek_ai/seek_ai.h | 117 +++++++++++++++++++++ .../errorstateplugins/seek_ai/seek_ai.pro | 13 +++ 6 files changed, 184 insertions(+), 5 deletions(-) create mode 100644 examples/statemachine/errorstateplugins/seek_ai/seek_ai.cpp create mode 100644 examples/statemachine/errorstateplugins/seek_ai/seek_ai.h create mode 100644 examples/statemachine/errorstateplugins/seek_ai/seek_ai.pro diff --git a/examples/statemachine/errorstate/tankitem.cpp b/examples/statemachine/errorstate/tankitem.cpp index ae338fe..1e02171 100644 --- a/examples/statemachine/errorstate/tankitem.cpp +++ b/examples/statemachine/errorstate/tankitem.cpp @@ -141,6 +141,11 @@ void TankItem::turn(qreal degrees) setAction(new TurnAction(this, degrees)); } +void TankItem::turnTo(qreal degrees) +{ + setAction(new TurnAction(this, degrees - direction())); +} + void TankItem::stop() { setAction(0); diff --git a/examples/statemachine/errorstate/tankitem.h b/examples/statemachine/errorstate/tankitem.h index 45016ec..cefed69 100644 --- a/examples/statemachine/errorstate/tankitem.h +++ b/examples/statemachine/errorstate/tankitem.h @@ -10,7 +10,7 @@ class TankItem: public GameItem { Q_OBJECT Q_PROPERTY(bool enabled READ enabled WRITE setEnabled) - Q_PROPERTY(qreal direction READ direction WRITE turn) + Q_PROPERTY(qreal direction READ direction WRITE turnTo) Q_PROPERTY(qreal distanceToObstacle READ distanceToObstacle) public: TankItem(QObject *parent = 0); @@ -42,9 +42,10 @@ signals: void cannonFired(); public slots: - void moveForwards(qreal length); - void moveBackwards(qreal length); - void turn(qreal newDirection); + void moveForwards(qreal length = 10.0); + void moveBackwards(qreal length = 10.0); + void turn(qreal degrees = 30.0); + void turnTo(qreal degrees = 0.0); void stop(); void fireCannon(); diff --git a/examples/statemachine/errorstateplugins/errorstateplugins.pro b/examples/statemachine/errorstateplugins/errorstateplugins.pro index e7718a9..5b6b758 100644 --- a/examples/statemachine/errorstateplugins/errorstateplugins.pro +++ b/examples/statemachine/errorstateplugins/errorstateplugins.pro @@ -1,7 +1,8 @@ TEMPLATE = subdirs SUBDIRS = random_ai \ spin_ai_with_error \ - spin_ai + spin_ai \ + seek_ai # install target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstateplugins diff --git a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.cpp b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.cpp new file mode 100644 index 0000000..229f83a --- /dev/null +++ b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.cpp @@ -0,0 +1,42 @@ +#include "seek_ai.h" + +QState *SeekAi::create(QState *parentState, QObject *tank) +{ + QState *topLevel = new QState(parentState); + topLevel->setObjectName("topLevel"); + + QState *seek = new QState(topLevel); + seek->setObjectName("seek"); + topLevel->setInitialState(seek); + + QState *lookForNearestWall = new SearchState(tank, seek); + lookForNearestWall->setObjectName("lookForNearestWall"); + seek->setInitialState(lookForNearestWall); + + QState *driveToFirstObstacle = new QState(seek); + driveToFirstObstacle->setObjectName("driveToFirstObstacle"); + lookForNearestWall->addTransition(lookForNearestWall, SIGNAL(nearestObstacleStraightAhead()), + driveToFirstObstacle); + + QState *drive = new QState(driveToFirstObstacle); + drive->setObjectName("drive"); + driveToFirstObstacle->setInitialState(drive); + connect(drive, SIGNAL(entered()), tank, SLOT(moveForwards())); + connect(drive, SIGNAL(exited()), tank, SLOT(stop())); + + // Go in loop + QState *finishedDriving = new QState(driveToFirstObstacle); + finishedDriving->setObjectName("finishedDriving"); + drive->addTransition(tank, SIGNAL(actionCompleted()), finishedDriving); + finishedDriving->addTransition(drive); + + QState *turnTo = new QState(seek); + turnTo->setObjectName("turnTo"); + driveToFirstObstacle->addTransition(new CollisionTransition(tank, turnTo)); + + turnTo->addTransition(tank, SIGNAL(actionCompleted()), driveToFirstObstacle); + + return topLevel; +} + +Q_EXPORT_PLUGIN2(seek_ai, SeekAi) diff --git a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h new file mode 100644 index 0000000..f96a68f --- /dev/null +++ b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h @@ -0,0 +1,117 @@ +#ifndef SEEK_AI_H +#define SEEK_AI_H + +#include + +#include +#include +#include +#include +#include + +class SearchState: public QState +{ + Q_OBJECT +public: + SearchState(QObject *tank, QState *parentState = 0) + : QState(parentState), + m_tank(tank), + m_distanceToTurn(360.0), + m_nearestDistance(-1.0), + m_directionOfNearestObstacle(0.0) + { + } + +public slots: + void turnAlittle() + { + qreal dist = m_tank->property("distanceToObstacle").toDouble(); + + if (m_nearestDistance < 0.0 || dist < m_nearestDistance) { + m_nearestDistance = dist; + m_directionOfNearestObstacle = m_tank->property("direction").toDouble(); + } + + m_distanceToTurn -= 10.0; + if (m_distanceToTurn < 0.0) { + disconnect(m_tank, SIGNAL(actionCompleted()), this, SLOT(turnAlittle())); + connect(m_tank, SIGNAL(actionCompleted()), this, SIGNAL(nearestObstacleStraightAhead())); + m_tank->setProperty("direction", m_directionOfNearestObstacle); + } + + qreal currentDirection = m_tank->property("direction").toDouble(); + m_tank->setProperty("direction", currentDirection + 10.0); + } + +signals: + void nearestObstacleStraightAhead(); + +protected: + void onEntry() + { + connect(m_tank, SIGNAL(actionCompleted()), this, SLOT(turnAlittle())); + turnAlittle(); + } + + void onExit() + { + disconnect(m_tank, SIGNAL(actionCompleted()), this, SLOT(turnAlittle())); + disconnect(m_tank, SIGNAL(actionCompleted()), this, SLOT(nearestObstacleStraightAhead())); + } + +private: + QObject *m_tank; + + qreal m_distanceToTurn; + qreal m_nearestDistance; + qreal m_directionOfNearestObstacle; +}; + +class CollisionTransition: public QSignalTransition +{ +public: + CollisionTransition(QObject *tank, QState *turnTo) + : QSignalTransition(tank, SIGNAL(collision(QLineF)), turnTo), + m_tank(tank), + m_turnTo(turnTo) + { + } + +protected: + bool eventTest(QEvent *event) + { + QSignalEvent *se = static_cast(event); + m_lastLine = se->arguments().at(0).toLineF(); + + return QSignalTransition::eventTest(event); + } + + void onTransition() + { + qreal currentDirection = m_tank->property("direction").toDouble(); + qreal angleOfWall = m_lastLine.angle(); + + qreal newDirection; + if (qAbs(currentDirection - angleOfWall) < qAbs(angleOfWall - currentDirection)) + newDirection = angleOfWall; + else + newDirection = -angleOfWall; + + m_turnTo->assignProperty(m_tank, "direction", newDirection); + } + +private: + QLineF m_lastLine; + QObject *m_tank; + QState *m_turnTo; +}; + +class SeekAi: public QObject, public Plugin +{ + Q_OBJECT + Q_INTERFACES(Plugin) +public: + virtual QState *create(QState *parentState, QObject *tank); +}; + +#endif diff --git a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.pro b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.pro new file mode 100644 index 0000000..11bd242 --- /dev/null +++ b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.pro @@ -0,0 +1,13 @@ +TEMPLATE = lib +CONFIG += plugin +INCLUDEPATH += ../.. +HEADERS = seek_ai.h +SOURCES = seek_ai.cpp +TARGET = $$qtLibraryTarget(seek_ai) +DESTDIR = ../../errorstate/plugins + +#! [0] +# install +target.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstate/plugins +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS seek_ai.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/statemachine/errorstateplugins/seek_ai \ No newline at end of file -- cgit v0.12 From e2cb1fe3f71a0fd74c49af2fc451a1e05ed2742b Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Mon, 4 May 2009 15:44:39 +0200 Subject: ignore QState::assignProperty() calls where the target object is 0 --- src/corelib/statemachine/qstate.cpp | 4 ++++ tests/auto/qstatemachine/tst_qstatemachine.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp index 2d59ab8..a431888 100644 --- a/src/corelib/statemachine/qstate.cpp +++ b/src/corelib/statemachine/qstate.cpp @@ -235,6 +235,10 @@ void QState::assignProperty(QObject *object, const char *name, const QVariant &value) { Q_D(QState); + if (!object) { + qWarning("QState::assignProperty: cannot assign property '%s' of null object", name); + return; + } for (int i = 0; i < d->propertyAssignments.size(); ++i) { QPropertyAssignment &assn = d->propertyAssignments[i]; if ((assn.object == object) && (assn.propertyName == name)) { diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 80bf674..5dfc758 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -1194,6 +1194,10 @@ void tst_QStateMachine::assignProperty() { QStateMachine machine; QState *s1 = new QState(machine.rootState()); + + QTest::ignoreMessage(QtWarningMsg, "QState::assignProperty: cannot assign property 'foo' of null object"); + s1->assignProperty(0, "foo", QVariant()); + s1->assignProperty(s1, "objectName", "s1"); QFinalState *s2 = new QFinalState(machine.rootState()); s1->addTransition(s2); -- cgit v0.12 From 30cce6b9d75e25e2f4d06fb8e2571a135ec62e35 Mon Sep 17 00:00:00 2001 From: Geir Vattekar Date: Tue, 5 May 2009 12:08:05 +0200 Subject: Doc: Updated QVariantAnimation class description --- src/corelib/animation/qabstractanimation.cpp | 18 ++-- src/corelib/animation/qvariantanimation.cpp | 143 +++++++++++++++++++-------- 2 files changed, 114 insertions(+), 47 deletions(-) diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index 71ef45c..40fa8fa 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -46,14 +46,13 @@ \since 4.5 \preliminary - This class is part of \l{The Animation Framework}. It serves as a base class - for standard animations and groups, with functions for shared - functionality, and it also makes it easy for you to define custom - animations that plug into the rest of the animation framework. - - If you want to create an animation, you should look at the two subclasses, - QVariantAnimation and QAnimationGroup, instead. + The class defines the functions for the functionality shared + between all animations. By inheriting this class, you can create + custom animations that plug into the rest of the animation + framework. + + QAbstractAnimation provides an interface for the current time and duration, the loop count, and the state of an animation. These properties define the base functionality common to all animations in Qt. The virtual @@ -86,6 +85,11 @@ changes, which is particularily useful for animations that are not driven by time. + \omit + If you want to create an animation, you should look at the two subclasses, + QVariantAnimation and QAnimationGroup, instead. + \endomit + \sa QVariantAnimation, QAnimationGroup, {The Animation Framework} */ diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp index bb6cf1c..dd32424 100644 --- a/src/corelib/animation/qvariantanimation.cpp +++ b/src/corelib/animation/qvariantanimation.cpp @@ -59,26 +59,68 @@ QT_BEGIN_NAMESPACE \since 4.5 \preliminary - This class is part of {The Animation Framework}. It serves as a base class - for property and item animations, with functions for shared functionality. - - If you want to create an animation, you should look at QPropertyAnimation instead. - + This class is part of \l{The Animation Framework}. It serves as a + base class for property and item animations, with functions for + shared functionality. + + QVariantAnimation cannot be used directly as it is an abstract + class; it does not implement + \l{QAbstractAnimation::}{updateCurrentValue()} from + QAbstractAnimation. The class performs interpolation over + \l{QVariant}s, but leaves using the interpolated values to its + subclasses. Currently, Qt provides QPropertyAnimation, which + animates Qt \l{Qt's Property System}{properties}. See the + QPropertyAnimation class description if you wish to animate such + properties. + You can then set start and end values for the property by calling setStartValue() and setEndValue(), and finally call start() to - start the animation. When control goes back to the event loop, QVariantAnimation - will interpolate the property of the target object and emit the valueChanged - signal. To react to a change in the current value you have to reimplement the - updateCurrentValue virtual method. - - There are two ways to affect how QVariantAnimation interpolates the values. - You can set an easing curve by calling setEasingCurve(), and configure the - duration by calling setDuration(). You can change how the QVariants are - interpolated by creating a subclass of QVariantAnimation, and reimplementing the - virtual interpolated() function. - - - \sa QPropertyAnimation, {The Animation Framework} + start the animation. QVariantAnimation will interpolate the + property of the target object and emit valueChanged(). To react to + a change in the current value you have to reimplement the + updateCurrentValue() virtual function. + + It is also possible to set values at specified steps situated + between the start and end value. The interpolation will then + touch these points at the specified steps. Note that the start and + end values are defined as the key values at 0.0 and 1.0. + + There are two ways to affect how QVariantAnimation interpolates + the values. You can set an easing curve by calling + setEasingCurve(), and configure the duration by calling + setDuration(). You can change how the QVariants are interpolated + by creating a subclass of QVariantAnimation, and reimplementing + the virtual interpolated() function. + + Subclassing QVariantAnimation can be an alternative if you have + \l{QVariant}s that you do not wish to declare as Qt properties. + Note, however, that you in most cases will be better off declaring + your QVariant as a property. + + Not all QVariant types are supported. Below is a list of currently + supported QVariant types: + + \list + \o \l{QMetaType::}{Int} + \o \l{QMetaType::}{Double} + \o \l{QMetaType::}{Float} + \o \l{QMetaType::}{QLine} + \o \l{QMetaType::}{QLineF} + \o \l{QMetaType::}{QPoint} + \o \l{QMetaType::}{QSize} + \o \l{QMetaType::}{QSizeF} + \o \l{QMetaType::}{QRect} + \o \l{QMetaType::}{QRectF} + \endlist + + If you need to interpolate other variant types, including custom + types, you have to implement interpolation for these yourself. + You do this by reimplementing interpolated(), which returns + interpolation values for the value being interpolated. + + \omit We need some snippets around here. \endomit + + \sa QPropertyAnimation, QAbstractAnimation, {The Animation Framework} */ /*! @@ -261,16 +303,23 @@ QVariantAnimation::~QVariantAnimation() \property QVariantAnimation::easingCurve \brief the easing curve of the animation - This property defines the easing curve of the animation. By default, a - linear easing curve is used, resulting in linear interpolation of the - end property. For many animations, it's useful to try different easing - curves, including QEasingCurve::InCirc, which provides a circular entry curve, - and QEasingCurve::InOutElastic, which provides an elastic effect on the values - of the interpolated property. + This property defines the easing curve of the animation. By + default, a linear easing curve is used, resulting in linear + interpolation. Other curves are provided, for instance, + QEasingCurve::InCirc, which provides a circular entry curve. + Another example is QEasingCurve::InOutElastic, which provides an + elastic effect on the values of the interpolated variant. + The easing curve is used with the interpolator, the interpolated() + virtual function, the animation's duration, and iterationCount, to + control how the current value changes as the animation progresses. + +<<<<<<< Updated upstream:src/corelib/animation/qvariantanimation.cpp The easing curve is used with the interpolator, the interpolated() virtual function, the animation's duration, and loopCount, to control how the current value changes as the animation progresses. +======= +>>>>>>> Stashed changes:src/corelib/animation/qvariantanimation.cpp */ QEasingCurve QVariantAnimation::easingCurve() const { @@ -372,8 +421,8 @@ QVariantAnimation::Interpolator QVariantAnimationPrivate::getInterpolator(int in \property QVariantAnimation::duration \brief the duration of the animation - This property describes the duration of the animation. The default - duration is 250 milliseconds. + This property describes the duration in milliseconds of the + animation. The default duration is 250 milliseconds. \sa QAbstractAnimation::duration() */ @@ -509,17 +558,22 @@ void QVariantAnimation::setKeyValues(const KeyValues &keyValues) /*! \property QVariantAnimation::currentValue - \brief the current value of the animation + \brief the current value of the animation. - This property describes the current value; an interpolation between the - start value and the end value, using the current time for progress. + This property describes the current value; an interpolated value + between the \l{startValue}{start value} and the \l{endValue}{end + value}, using the current time for progress. The value itself is + obtained from interpolated(), which is called repeatedly as the + animation is running. - QVariantAnimation calls the virtual updateCurrentValue() function when the - current value changes. This is particularily useful for subclasses that - need to track updates. + QVariantAnimation calls the virtual updateCurrentValue() function + when the current value changes. This is particularly useful for + subclasses that need to track updates. For example, + QPropertyAnimation uses this function to animate Qt \l{Qt's + Property System}{properties}. \sa startValue, endValue - */ +*/ QVariant QVariantAnimation::currentValue() const { Q_D(const QVariantAnimation); @@ -549,13 +603,22 @@ void QVariantAnimation::updateState(QAbstractAnimation::State oldState, } /*! - This virtual function returns the linear interpolation between variants \a - from and \a to, at \a progress, usually a value between 0 and 1. You can reimplement - this function in a subclass of QVariantAnimation to provide your own interpolation - algorithm. Note that in order for the interpolation to work with a QEasingCurve - that return a value smaller than 0 or larger than 1 (such as QEasingCurve::InBack) - you should make sure that it can extrapolate. If the semantic of the datatype - does not allow extrapolation this function should handle that gracefully. + + This virtual function returns the linear interpolation between + variants \a from and \a to, at \a progress, usually a value + between 0 and 1. You can reimplement this function in a subclass + of QVariantAnimation to provide your own interpolation algorithm. + + Note that in order for the interpolation to work with a + QEasingCurve that return a value smaller than 0 or larger than 1 + (such as QEasingCurve::InBack) you should make sure that it can + extrapolate. If the semantic of the datatype does not allow + extrapolation this function should handle that gracefully. + + You should call the QVariantAnimation implementation of this + function if you want your class to handle the types already + supported by Qt (see class QVariantAnimation description for a + list of supported types). \sa QEasingCurve */ -- cgit v0.12 From 81a6aebbdf9319a731ee1ee368f2f05bf4bfd83c Mon Sep 17 00:00:00 2001 From: Geir Vattekar Date: Tue, 5 May 2009 12:15:08 +0200 Subject: Doc: Git merge conflict in QVariantAnimation --- src/corelib/animation/qvariantanimation.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp index dd32424..73ed0df 100644 --- a/src/corelib/animation/qvariantanimation.cpp +++ b/src/corelib/animation/qvariantanimation.cpp @@ -313,13 +313,6 @@ QVariantAnimation::~QVariantAnimation() The easing curve is used with the interpolator, the interpolated() virtual function, the animation's duration, and iterationCount, to control how the current value changes as the animation progresses. - -<<<<<<< Updated upstream:src/corelib/animation/qvariantanimation.cpp - The easing curve is used with the interpolator, the interpolated() virtual - function, the animation's duration, and loopCount, to control how the - current value changes as the animation progresses. -======= ->>>>>>> Stashed changes:src/corelib/animation/qvariantanimation.cpp */ QEasingCurve QVariantAnimation::easingCurve() const { -- cgit v0.12 From d388730da773c46f228894186c29d330a774b72b Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 5 May 2009 13:48:24 +0200 Subject: Fix support reverse actions. Logic was broken and would always return false immediately for reverse actions, thus immediately stopping them. --- examples/statemachine/errorstate/tankitem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/statemachine/errorstate/tankitem.cpp b/examples/statemachine/errorstate/tankitem.cpp index 1e02171..fc71ef9 100644 --- a/examples/statemachine/errorstate/tankitem.cpp +++ b/examples/statemachine/errorstate/tankitem.cpp @@ -41,7 +41,7 @@ public: m_distance -= dist; if (m_reverse && m_distance > 0.0) return false; - else if (m_distance < 0.0) + else if (!m_reverse && m_distance < 0.0) return false; qreal a = item()->direction() * M_PI / 180.0; @@ -73,7 +73,7 @@ public: m_distance -= dist; if (m_reverse && m_distance > 0.0) return false; - else if (m_distance < 0.0) + else if (!m_reverse && m_distance < 0.0) return false; item()->setDirection(item()->direction() + dist); -- cgit v0.12 From 8b4daee4bd6c6dd3da7b7e71b6c468059cf53ea0 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 5 May 2009 14:18:55 +0200 Subject: Make sure the correct position/direction is actually set at the end of a loop. Also make sure we set the direction to an angle within 360 degrees. --- examples/statemachine/errorstate/tankitem.cpp | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/examples/statemachine/errorstate/tankitem.cpp b/examples/statemachine/errorstate/tankitem.cpp index fc71ef9..5506a7e 100644 --- a/examples/statemachine/errorstate/tankitem.cpp +++ b/examples/statemachine/errorstate/tankitem.cpp @@ -2,6 +2,7 @@ #include #include +#include #include @@ -38,11 +39,12 @@ public: { qreal dist = timeDelta * item()->speed() * (m_reverse ? -1.0 : 1.0); + bool done = false; + if (qAbs(m_distance) < qAbs(dist)) { + done = true; + dist = m_distance; + } m_distance -= dist; - if (m_reverse && m_distance > 0.0) - return false; - else if (!m_reverse && m_distance < 0.0) - return false; qreal a = item()->direction() * M_PI / 180.0; @@ -50,7 +52,7 @@ public: qreal xd = dist * sin(M_PI / 2.0 - a); item()->setPos(item()->pos() + QPointF(xd, yd)); - return true; + return !done; } private: @@ -70,14 +72,15 @@ public: bool apply(qreal timeDelta) { qreal dist = timeDelta * item()->angularSpeed() * (m_reverse ? -1.0 : 1.0); + bool done = false; + if (qAbs(m_distance) < qAbs(dist)) { + done = true; + dist = m_distance; + } m_distance -= dist; - if (m_reverse && m_distance > 0.0) - return false; - else if (!m_reverse && m_distance < 0.0) - return false; item()->setDirection(item()->direction() + dist); - return true; + return !done; } private: @@ -219,6 +222,9 @@ qreal TankItem::direction() const void TankItem::setDirection(qreal newDirection) { + int fullRotations = int(newDirection) / 360; + newDirection -= fullRotations * 360.0; + qreal diff = newDirection - m_currentDirection; m_currentDirection = newDirection; rotate(diff); -- cgit v0.12 From 6de0b13042f39b7570588eb5615cc1e16a71eced Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 5 May 2009 14:50:56 +0200 Subject: Set collidedLine for the implicit walls around the scene to allow for collision response. --- examples/statemachine/errorstate/gameitem.cpp | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/examples/statemachine/errorstate/gameitem.cpp b/examples/statemachine/errorstate/gameitem.cpp index d286df4..1a2af71 100644 --- a/examples/statemachine/errorstate/gameitem.cpp +++ b/examples/statemachine/errorstate/gameitem.cpp @@ -1,6 +1,7 @@ #include "gameitem.h" #include +#include GameItem::GameItem(QObject *parent) : QObject(parent) { @@ -56,15 +57,31 @@ QPointF GameItem::tryMove(const QPointF &requestedPosition, QLineF *collidedLine } } + // Don't go outside of map - if (nextPoint.x() < sceneRect.left()) + if (nextPoint.x() < sceneRect.left()) { nextPoint.rx() = sceneRect.left(); - if (nextPoint.x() > sceneRect.right()) + if (collidedLine != 0) + *collidedLine = QLineF(scene()->sceneRect().topLeft(), scene()->sceneRect().bottomLeft()); + } + + if (nextPoint.x() > sceneRect.right()) { nextPoint.rx() = sceneRect.right(); - if (nextPoint.y() < sceneRect.top()) + if (collidedLine != 0) + *collidedLine = QLineF(scene()->sceneRect().topRight(), scene()->sceneRect().bottomRight()); + } + + if (nextPoint.y() < sceneRect.top()) { nextPoint.ry() = sceneRect.top(); - if (nextPoint.y() > sceneRect.bottom()) + if (collidedLine != 0) + *collidedLine = QLineF(scene()->sceneRect().topLeft(), scene()->sceneRect().topRight()); + } + + if (nextPoint.y() > sceneRect.bottom()) { nextPoint.ry() = sceneRect.bottom(); + if (collidedLine != 0) + *collidedLine = QLineF(scene()->sceneRect().bottomLeft(), scene()->sceneRect().bottomRight()); + } return nextPoint; } -- cgit v0.12 From ef2c9e7e6ea543a7ca1ee23b5bbaa9dee5f77b8a Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 5 May 2009 14:54:04 +0200 Subject: Make sure target state is set correctly. Also make sure eventTest() actually overrides the virtual function. --- examples/statemachine/errorstateplugins/seek_ai/seek_ai.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h index f96a68f..7f108a1 100644 --- a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h +++ b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h @@ -8,6 +8,7 @@ #include #include #include +#include class SearchState: public QState { @@ -75,14 +76,16 @@ public: m_tank(tank), m_turnTo(turnTo) { + setTargetState(turnTo); } protected: - bool eventTest(QEvent *event) + bool eventTest(QEvent *event) const { - QSignalEvent *se = static_cast(event); - m_lastLine = se->arguments().at(0).toLineF(); - + if (event->type() == QEvent::Signal) { + QSignalEvent *se = static_cast(event); + m_lastLine = se->arguments().at(0).toLineF(); + } return QSignalTransition::eventTest(event); } @@ -101,7 +104,7 @@ protected: } private: - QLineF m_lastLine; + mutable QLineF m_lastLine; QObject *m_tank; QState *m_turnTo; }; -- cgit v0.12 From 6eae8aedd14acbc4ea73f336124b0243e9ebb9c0 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 5 May 2009 15:24:03 +0200 Subject: Add randomness. --- examples/statemachine/errorstateplugins/seek_ai/seek_ai.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h index 7f108a1..83f50a7 100644 --- a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h +++ b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h @@ -95,10 +95,10 @@ protected: qreal angleOfWall = m_lastLine.angle(); qreal newDirection; - if (qAbs(currentDirection - angleOfWall) < qAbs(angleOfWall - currentDirection)) + if (qrand() % 2 == 0) newDirection = angleOfWall; else - newDirection = -angleOfWall; + newDirection = angleOfWall - 180.0; m_turnTo->assignProperty(m_tank, "direction", newDirection); } -- cgit v0.12 From 0a5b73b777536556bbc8f9178f2d7e78eeb79d74 Mon Sep 17 00:00:00 2001 From: Geir Vattekar Date: Tue, 5 May 2009 17:57:49 +0200 Subject: Doc: Work on QAbstractAnimation class description --- src/corelib/animation/qabstractanimation.cpp | 95 ++++++++++++++-------------- 1 file changed, 49 insertions(+), 46 deletions(-) diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index 40fa8fa..440a37d 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -42,55 +42,58 @@ /*! \class QAbstractAnimation \ingroup animation - \brief The QAbstractAnimation class provides an abstract base class for animations. + \brief The QAbstractAnimation class is the base of all animations. \since 4.5 \preliminary - The class defines the functions for the functionality shared - between all animations. By inheriting this class, you can create - custom animations that plug into the rest of the animation - framework. - - - - QAbstractAnimation provides an interface for the current time and - duration, the loop count, and the state of an animation. These properties - define the base functionality common to all animations in Qt. The virtual - duration() function returns the local duration of the animation; i.e., for - how long the animation should update the current time before - looping. Subclasses can implement this function differently; for example, - QVariantAnimation returns the duration of a simple animated property, whereas - QAnimationGroup returns the duration of a set or sequence of - animations. You can also set a loop count by calling setLoopCount(); a - loop count of 2 will let the animation run twice (the default value is - 1). - - Like QTimeLine, QAbstractAnimation also provides an interface for starting - and stopping an animation, and for tracking its progress. You can call the - start() slot to start the animation. When the animation starts, the - stateChanged() signal is emitted, and state() returns Running. If you call the - stop() slot, the stateChanged() signal is emitted, and state() returns - Stopped. If you call the pause() slot, the stateChanged() signal is emitted - and state() returns Paused. If the animation reaches the end, the finished() - signal is emitted. You can check the current state by calling state(). - - QAbstractAnimation provides two functions that are pure virtual, and must - be reimplemented in a subclass: duration(), and updateCurrentTime(). The - duration() function lets you report a duration for the animation (a return - value of -1 signals that the animation runs forever until explicitly - stopped). The current time is delivered by the framework through calls to - updateCurrentTime(). By reimplementing this function, you can track the - animation progress and update your target objects accordingly. By - reimplementing updateState(), you can track the animation's state - changes, which is particularily useful for animations that are not driven - by time. - - \omit - If you want to create an animation, you should look at the two subclasses, - QVariantAnimation and QAnimationGroup, instead. - \endomit - - \sa QVariantAnimation, QAnimationGroup, {The Animation Framework} + The class defines the functions for the functionality shared by + all animations. By inheriting this class, you can create custom + animations that plug into the rest of the animation framework. + + The progress of an animation is given by its current time + (currentTime()), which is measured in milliseconds from the start + of the animation (0) to its end (duration()). The value is updated + automatically while the animation is running. It can also be set + directly with setCurrentTime(). + + At any point an animation is in one of three states: + \l{QAbstractAnimation::}{Running}, + \l{QAbstractAnimation::}{Stopped}, or + \l{QAbstractAnimation::}{Paused}--as defined by the + \l{QAbstractAnimation::}{State} enum. The current state can be + changed by calling start(), stop(), pause(), or resume(). An + animation will always reset its \l{currentTime()}{current time} + when it is started. If paused, it will continue with the same + current time when resumed. When an animation is stopped, it cannot + be resumed, but will keep its current time (until started again). + QAbstractAnimation will emit stateChanged() whenever its state + changes. + + An animation can loop any number of times by setting the loopCount + property. When an animation's current time reaches its duration(), + it will reset the current time and keep running. A loop count of 1 + (the default value) means that the animation will run one time. + Note that a duration of -1 means that the animation will run until + stopped; the current time will increase indefinitely. When the + current time equals duration() and the animation is in its + final loop, the \l{QAbstractAnimation::}{Stopped} state is + entered, and the finished() signal is emitted. + + QAbstractAnimation provides pure virtual functions used by + subclasses to track the progress of the animation: duration() and + updateCurrentTime(). The duration() function lets you report a + duration for the animation (as discussed above). The current time + is delivered by the animation framework through calls to + updateCurrentTime(). By reimplementing this function, you can + track the animation progress. Note that neither the interval + between calls nor the number of calls to this function are + defined; though, it will normally be 60 updates per second. + + By reimplementing updateState(), you can track the animation's + state changes, which is particularly useful for animations that + are not driven by time. + + \sa QVariantAnimation, QPropertyAnimation, QAnimationGroup, {The Animation Framework} */ /*! -- cgit v0.12 From 2e0430832d3656753f73b09765769d10aa51add3 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Tue, 5 May 2009 18:17:43 +0200 Subject: add event as argument to onEntry(), onExit() and onTransition() Accessing the event can be useful. E.g., onEntry() can do some common event processing regardless of which transition caused the state to be entered; onTransition() can be used in combination with eventTest(), where eventTest() would first check that the input matches some criteria, and then the actual processing of that input would be done in onTransition. --- examples/animation/moveblocks/main.cpp | 6 ++-- examples/animation/sub-attaq/boat_p.h | 12 +++---- examples/animation/sub-attaq/qanimationstate.cpp | 4 +-- examples/animation/sub-attaq/qanimationstate.h | 4 +-- examples/animation/sub-attaq/states.cpp | 16 ++++----- examples/animation/sub-attaq/states.h | 14 ++++---- examples/animation/sub-attaq/submarine_p.h | 12 +++---- examples/statemachine/clockticking/main.cpp | 6 ++-- .../errorstateplugins/random_ai/random_ai_plugin.h | 4 +-- .../errorstateplugins/seek_ai/seek_ai.h | 6 ++-- .../errorstateplugins/spin_ai/spin_ai.h | 2 +- .../spin_ai_with_error/spin_ai_with_error.h | 2 +- examples/statemachine/factorial/main.cpp | 4 +-- examples/statemachine/helloworld/main.cpp | 2 +- examples/statemachine/pingpong/main.cpp | 6 ++-- src/corelib/statemachine/qabstractstate.cpp | 22 ++++++------ src/corelib/statemachine/qabstractstate.h | 4 +-- src/corelib/statemachine/qabstractstate_p.h | 4 +-- src/corelib/statemachine/qabstracttransition.cpp | 11 +++--- src/corelib/statemachine/qabstracttransition.h | 2 +- src/corelib/statemachine/qabstracttransition_p.h | 2 +- src/corelib/statemachine/qeventtransition.cpp | 3 +- src/corelib/statemachine/qeventtransition.h | 2 +- src/corelib/statemachine/qfinalstate.cpp | 6 ++-- src/corelib/statemachine/qfinalstate.h | 4 +-- src/corelib/statemachine/qhistorystate.cpp | 4 +-- src/corelib/statemachine/qhistorystate.h | 4 +-- src/corelib/statemachine/qsignaltransition.cpp | 3 +- src/corelib/statemachine/qsignaltransition.h | 2 +- src/corelib/statemachine/qstate.cpp | 8 +++-- src/corelib/statemachine/qstate.h | 4 +-- src/corelib/statemachine/qstatemachine.cpp | 41 +++++++++++----------- src/corelib/statemachine/qstatemachine_p.h | 8 ++--- src/gui/statemachine/qbasickeyeventtransition.cpp | 2 +- src/gui/statemachine/qbasickeyeventtransition_p.h | 2 +- .../statemachine/qbasicmouseeventtransition.cpp | 2 +- .../statemachine/qbasicmouseeventtransition_p.h | 2 +- src/gui/statemachine/qkeyeventtransition.cpp | 4 +-- src/gui/statemachine/qkeyeventtransition.h | 2 +- src/gui/statemachine/qmouseeventtransition.cpp | 4 +-- src/gui/statemachine/qmouseeventtransition.h | 2 +- tests/auto/qstatemachine/tst_qstatemachine.cpp | 16 ++++----- 42 files changed, 140 insertions(+), 130 deletions(-) diff --git a/examples/animation/moveblocks/main.cpp b/examples/animation/moveblocks/main.cpp index eb23bd5..06ed3dd 100644 --- a/examples/animation/moveblocks/main.cpp +++ b/examples/animation/moveblocks/main.cpp @@ -101,7 +101,7 @@ protected: && (static_cast(event)->rand() == m_rand); } - virtual void onTransition() {} + virtual void onTransition(QEvent *) {} private: int m_rand; @@ -116,7 +116,7 @@ public: m_stateCount(0), m_lastIndex(0) { } - virtual void onEntry() + virtual void onEntry(QEvent *) { int n; while ((n = (qrand() % m_stateCount + 1)) == m_lastIndex) @@ -124,7 +124,7 @@ public: m_lastIndex = n; m_machine->postEvent(new StateSwitchEvent(n)); } - virtual void onExit() {} + virtual void onExit(QEvent *) {} void addState(QState *state, QAbstractAnimation *animation) { StateSwitchTransition *trans = new StateSwitchTransition(++m_stateCount); diff --git a/examples/animation/sub-attaq/boat_p.h b/examples/animation/sub-attaq/boat_p.h index 855b10f..17fbe5c 100644 --- a/examples/animation/sub-attaq/boat_p.h +++ b/examples/animation/sub-attaq/boat_p.h @@ -104,7 +104,7 @@ protected: return false; } - void onTransition() + void onTransition(QEvent *) { //We decrease the speed if needed if (key == Qt::Key_Left && boat->currentDirection() == Boat::Right) @@ -156,7 +156,7 @@ public: this->boat = boat; } protected: - void onEntry() + void onEntry(QEvent *) { boat->setCurrentDirection(Boat::Right); boat->updateBoatMovement(); @@ -174,7 +174,7 @@ public: this->boat = boat; } protected: - void onEntry() + void onEntry(QEvent *) { boat->setCurrentDirection(Boat::Left); boat->updateBoatMovement(); @@ -192,7 +192,7 @@ public: this->boat = boat; } protected: - void onEntry() + void onEntry(QEvent *) { boat->setCurrentSpeed(0); boat->setCurrentDirection(Boat::None); @@ -211,7 +211,7 @@ public: this->boat = boat; } protected: - void onEntry() + void onEntry(QEvent *) { Bomb *b = new Bomb(); b->setPos(boat->x()+boat->size().width(),boat->y()); @@ -233,7 +233,7 @@ public: this->boat = boat; } protected: - void onEntry() + void onEntry(QEvent *) { Bomb *b = new Bomb(); b->setPos(boat->x() - b->size().width(), boat->y()); diff --git a/examples/animation/sub-attaq/qanimationstate.cpp b/examples/animation/sub-attaq/qanimationstate.cpp index 3659657..0f30ac2 100644 --- a/examples/animation/sub-attaq/qanimationstate.cpp +++ b/examples/animation/sub-attaq/qanimationstate.cpp @@ -146,7 +146,7 @@ QAbstractAnimation* QAnimationState::animation() const /*! \reimp */ -void QAnimationState::onEntry() +void QAnimationState::onEntry(QEvent *) { Q_D(QAnimationState); if (d->animation) @@ -156,7 +156,7 @@ void QAnimationState::onEntry() /*! \reimp */ -void QAnimationState::onExit() +void QAnimationState::onExit(QEvent *) { Q_D(QAnimationState); if (d->animation) diff --git a/examples/animation/sub-attaq/qanimationstate.h b/examples/animation/sub-attaq/qanimationstate.h index ddf5681..88c0a6d 100644 --- a/examples/animation/sub-attaq/qanimationstate.h +++ b/examples/animation/sub-attaq/qanimationstate.h @@ -74,8 +74,8 @@ Q_SIGNALS: void animationFinished(); protected: - void onEntry(); - void onExit(); + void onEntry(QEvent *); + void onExit(QEvent *); bool event(QEvent *e); private: diff --git a/examples/animation/sub-attaq/states.cpp b/examples/animation/sub-attaq/states.cpp index 0b98016..c6af924 100644 --- a/examples/animation/sub-attaq/states.cpp +++ b/examples/animation/sub-attaq/states.cpp @@ -76,7 +76,7 @@ PlayState::~PlayState() { } -void PlayState::onEntry() +void PlayState::onEntry(QEvent *) { //We are now playing? if (machine) { @@ -159,7 +159,7 @@ void PlayState::onEntry() LevelState::LevelState(GraphicsScene *scene, PlayState *game, QState *parent) : QState(parent), scene(scene), game(game) { } -void LevelState::onEntry() +void LevelState::onEntry(QEvent *) { initializeLevel(); } @@ -202,12 +202,12 @@ void LevelState::initializeLevel() PauseState::PauseState(GraphicsScene *scene, QState *parent) : QState(parent),scene(scene) { } -void PauseState::onEntry() +void PauseState::onEntry(QEvent *) { AnimationManager::self()->pauseAll(); scene->boat->setEnabled(false); } -void PauseState::onExit() +void PauseState::onExit(QEvent *) { AnimationManager::self()->resumeAll(); scene->boat->setEnabled(true); @@ -219,7 +219,7 @@ LostState::LostState(GraphicsScene *scene, PlayState *game, QState *parent) : QS { } -void LostState::onEntry() +void LostState::onEntry(QEvent *) { //The message to display QString message = QString("You lose on level %1. Your score is %2.").arg(game->currentLevel+1).arg(game->score); @@ -242,7 +242,7 @@ WinState::WinState(GraphicsScene *scene, PlayState *game, QState *parent) : QSta { } -void WinState::onEntry() +void WinState::onEntry(QEvent *) { //We clear the scene scene->clearScene(); @@ -269,9 +269,9 @@ UpdateScoreState::UpdateScoreState(PlayState *game, QState *parent) : QState(par { this->game = game; } -void UpdateScoreState::onEntry() +void UpdateScoreState::onEntry(QEvent *e) { - QState::onEntry(); + QState::onEntry(e); } /** Win transition */ diff --git a/examples/animation/sub-attaq/states.h b/examples/animation/sub-attaq/states.h index ec69ae7..27beb71 100644 --- a/examples/animation/sub-attaq/states.h +++ b/examples/animation/sub-attaq/states.h @@ -68,7 +68,7 @@ public: ~PlayState(); protected: - void onEntry(); + void onEntry(QEvent *); private : GraphicsScene *scene; @@ -91,7 +91,7 @@ class LevelState : public QState public: LevelState(GraphicsScene *scene, PlayState *game, QState *parent = 0); protected: - void onEntry(); + void onEntry(QEvent *); private : void initializeLevel(); GraphicsScene *scene; @@ -104,8 +104,8 @@ public: PauseState(GraphicsScene *scene, QState *parent = 0); protected: - void onEntry(); - void onExit(); + void onEntry(QEvent *); + void onExit(QEvent *); private : GraphicsScene *scene; Boat *boat; @@ -117,7 +117,7 @@ public: LostState(GraphicsScene *scene, PlayState *game, QState *parent = 0); protected: - void onEntry(); + void onEntry(QEvent *); private : GraphicsScene *scene; PlayState *game; @@ -129,7 +129,7 @@ public: WinState(GraphicsScene *scene, PlayState *game, QState *parent = 0); protected: - void onEntry(); + void onEntry(QEvent *); private : GraphicsScene *scene; PlayState *game; @@ -140,7 +140,7 @@ class UpdateScoreState : public QState public: UpdateScoreState(PlayState *game, QState *parent); protected: - void onEntry(); + void onEntry(QEvent *); private: QPropertyAnimation *scoreAnimation; PlayState *game; diff --git a/examples/animation/sub-attaq/submarine_p.h b/examples/animation/sub-attaq/submarine_p.h index 918e7f5..c76d991 100644 --- a/examples/animation/sub-attaq/submarine_p.h +++ b/examples/animation/sub-attaq/submarine_p.h @@ -77,7 +77,7 @@ protected slots: } protected: - void onEntry() + void onEntry(QEvent *e) { if (submarine->currentDirection() == SubMarine::Left) { movementAnimation->setEndValue(QPointF(0,submarine->y())); @@ -88,7 +88,7 @@ protected: movementAnimation->setDuration((submarine->scene()->width()-submarine->size().width()-submarine->x())/submarine->currentSpeed()*12); } movementAnimation->setStartValue(submarine->pos()); - QAnimationState::onEntry(); + QAnimationState::onEntry(e); } private: @@ -109,19 +109,19 @@ public: } protected: - void onEntry() + void onEntry(QEvent *e) { returnAnimation->stop(); returnAnimation->setStartValue(submarine->yRotation()); returnAnimation->setEndValue(submarine->currentDirection() == SubMarine::Right ? 360. : 180.); returnAnimation->setDuration(500); - QAnimationState::onEntry(); + QAnimationState::onEntry(e); } - void onExit() + void onExit(QEvent *e) { submarine->currentDirection() == SubMarine::Right ? submarine->setCurrentDirection(SubMarine::Left) : submarine->setCurrentDirection(SubMarine::Right); - QAnimationState::onExit(); + QAnimationState::onExit(e); } private: diff --git a/examples/statemachine/clockticking/main.cpp b/examples/statemachine/clockticking/main.cpp index 9b54f29..ea8e692 100644 --- a/examples/statemachine/clockticking/main.cpp +++ b/examples/statemachine/clockticking/main.cpp @@ -61,7 +61,7 @@ public: : QState(parent) {} protected: - virtual void onEntry() + virtual void onEntry(QEvent *) { fprintf(stdout, "ClockState entered; posting the initial tick\n"); machine()->postEvent(new ClockEvent()); @@ -77,7 +77,7 @@ protected: virtual bool eventTest(QEvent *e) const { return (e->type() == QEvent::User+2); } - virtual void onTransition() + virtual void onTransition(QEvent *) { fprintf(stdout, "ClockTransition triggered; posting another tick with a delay of 1 second\n"); machine()->postEvent(new ClockEvent(), 1000); @@ -93,7 +93,7 @@ protected: virtual bool eventTest(QEvent *e) const { return (e->type() == QEvent::User+2); } - virtual void onTransition() + virtual void onTransition(QEvent *) { fprintf(stdout, "ClockListener heard a tick!\n"); } diff --git a/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.h b/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.h index d3670bd..3db464b 100644 --- a/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.h +++ b/examples/statemachine/errorstateplugins/random_ai/random_ai_plugin.h @@ -21,7 +21,7 @@ signals: void turnSelected(); protected: - void onEntry() + void onEntry(QEvent *) { int rand = qrand() % 4; switch (rand) { @@ -45,7 +45,7 @@ signals: void distanceComputed(qreal distance); protected: - void onEntry() + void onEntry(QEvent *) { emit distanceComputed(qreal(qrand() % 180)); } diff --git a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h index 83f50a7..7d8aa68 100644 --- a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h +++ b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h @@ -48,13 +48,13 @@ signals: void nearestObstacleStraightAhead(); protected: - void onEntry() + void onEntry(QEvent *) { connect(m_tank, SIGNAL(actionCompleted()), this, SLOT(turnAlittle())); turnAlittle(); } - void onExit() + void onExit(QEvent *) { disconnect(m_tank, SIGNAL(actionCompleted()), this, SLOT(turnAlittle())); disconnect(m_tank, SIGNAL(actionCompleted()), this, SLOT(nearestObstacleStraightAhead())); @@ -89,7 +89,7 @@ protected: return QSignalTransition::eventTest(event); } - void onTransition() + void onTransition(QEvent *) { qreal currentDirection = m_tank->property("direction").toDouble(); qreal angleOfWall = m_lastLine.angle(); diff --git a/examples/statemachine/errorstateplugins/spin_ai/spin_ai.h b/examples/statemachine/errorstateplugins/spin_ai/spin_ai.h index 309ba14..4b4629c 100644 --- a/examples/statemachine/errorstateplugins/spin_ai/spin_ai.h +++ b/examples/statemachine/errorstateplugins/spin_ai/spin_ai.h @@ -22,7 +22,7 @@ public slots: } protected: - void onEntry() + void onEntry(QEvent *) { connect(m_tank, SIGNAL(actionCompleted()), this, SLOT(spin())); spin(); diff --git a/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.h b/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.h index fa06d10..9a96a8b 100644 --- a/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.h +++ b/examples/statemachine/errorstateplugins/spin_ai_with_error/spin_ai_with_error.h @@ -22,7 +22,7 @@ public slots: } protected: - void onEntry() + void onEntry(QEvent *) { connect(m_tank, SIGNAL(actionCompleted()), this, SLOT(spin())); spin(); diff --git a/examples/statemachine/factorial/main.cpp b/examples/statemachine/factorial/main.cpp index 9e39ced..2b63690 100644 --- a/examples/statemachine/factorial/main.cpp +++ b/examples/statemachine/factorial/main.cpp @@ -104,7 +104,7 @@ public: return m_fact->property("x").toInt() > 1; } - virtual void onTransition() + virtual void onTransition(QEvent *) { int x = m_fact->property("x").toInt(); int fac = m_fact->property("fac").toInt(); @@ -128,7 +128,7 @@ public: return m_fact->property("x").toInt() <= 1; } - virtual void onTransition() + virtual void onTransition(QEvent *) { fprintf(stdout, "%d\n", m_fact->property("fac").toInt()); } diff --git a/examples/statemachine/helloworld/main.cpp b/examples/statemachine/helloworld/main.cpp index 13486d4..fbe34b5 100644 --- a/examples/statemachine/helloworld/main.cpp +++ b/examples/statemachine/helloworld/main.cpp @@ -52,7 +52,7 @@ public: S0(QState *parent = 0) : QState(parent) {} - virtual void onEntry() + virtual void onEntry(QEvent *) { fprintf(stdout, "Hello world!\n"); } diff --git a/examples/statemachine/pingpong/main.cpp b/examples/statemachine/pingpong/main.cpp index 68f7115..eb8fd5d 100644 --- a/examples/statemachine/pingpong/main.cpp +++ b/examples/statemachine/pingpong/main.cpp @@ -68,7 +68,7 @@ public: : QState(parent) {} protected: - virtual void onEntry() + virtual void onEntry(QEvent *) { machine()->postEvent(new PingEvent()); fprintf(stdout, "ping?\n"); @@ -84,7 +84,7 @@ protected: virtual bool eventTest(QEvent *e) const { return (e->type() == QEvent::User+3); } - virtual void onTransition() + virtual void onTransition(QEvent *) { machine()->postEvent(new PingEvent(), 500); fprintf(stdout, "ping?\n"); @@ -100,7 +100,7 @@ protected: virtual bool eventTest(QEvent *e) const { return (e->type() == QEvent::User+2); } - virtual void onTransition() + virtual void onTransition(QEvent *) { machine()->postEvent(new PongEvent(), 500); fprintf(stdout, "pong!\n"); diff --git a/src/corelib/statemachine/qabstractstate.cpp b/src/corelib/statemachine/qabstractstate.cpp index cc6f0f9..3f84314 100644 --- a/src/corelib/statemachine/qabstractstate.cpp +++ b/src/corelib/statemachine/qabstractstate.cpp @@ -101,16 +101,16 @@ QStateMachine *QAbstractStatePrivate::machine() const return 0; } -void QAbstractStatePrivate::callOnEntry() +void QAbstractStatePrivate::callOnEntry(QEvent *e) { Q_Q(QAbstractState); - q->onEntry(); + q->onEntry(e); } -void QAbstractStatePrivate::callOnExit() +void QAbstractStatePrivate::callOnExit(QEvent *e) { Q_Q(QAbstractState); - q->onExit(); + q->onExit(e); } void QAbstractStatePrivate::emitEntered() @@ -190,17 +190,19 @@ QStateMachine *QAbstractState::machine() const } /*! - \fn QAbstractState::onExit() + \fn QAbstractState::onExit(QEvent *event) - This function is called when the state is exited. Reimplement this function - to perform custom processing when the state is exited. + This function is called when the state is exited. The given \a event is what + caused the state to be exited. Reimplement this function to perform custom + processing when the state is exited. */ /*! - \fn QAbstractState::onEntry() + \fn QAbstractState::onEntry(QEvent *event) - This function is called when the state is entered. Reimplement this function - to perform custom processing when the state is entered. + This function is called when the state is entered. The given \a event is + what caused the state to be entered. Reimplement this function to perform + custom processing when the state is entered. */ /*! diff --git a/src/corelib/statemachine/qabstractstate.h b/src/corelib/statemachine/qabstractstate.h index 30a68ff..f6b4b21 100644 --- a/src/corelib/statemachine/qabstractstate.h +++ b/src/corelib/statemachine/qabstractstate.h @@ -70,8 +70,8 @@ Q_SIGNALS: protected: QAbstractState(QState *parent = 0); - virtual void onEntry() = 0; - virtual void onExit() = 0; + virtual void onEntry(QEvent *event) = 0; + virtual void onExit(QEvent *event) = 0; bool event(QEvent *e); diff --git a/src/corelib/statemachine/qabstractstate_p.h b/src/corelib/statemachine/qabstractstate_p.h index bbe12d6..6c09696 100644 --- a/src/corelib/statemachine/qabstractstate_p.h +++ b/src/corelib/statemachine/qabstractstate_p.h @@ -77,8 +77,8 @@ public: QStateMachine *machine() const; - void callOnEntry(); - void callOnExit(); + void callOnEntry(QEvent *e); + void callOnExit(QEvent *e); void emitEntered(); void emitExited(); diff --git a/src/corelib/statemachine/qabstracttransition.cpp b/src/corelib/statemachine/qabstracttransition.cpp index 5fa1742..1897aa6 100644 --- a/src/corelib/statemachine/qabstracttransition.cpp +++ b/src/corelib/statemachine/qabstracttransition.cpp @@ -131,10 +131,10 @@ bool QAbstractTransitionPrivate::callEventTest(QEvent *e) const return q->eventTest(e); } -void QAbstractTransitionPrivate::callOnTransition() +void QAbstractTransitionPrivate::callOnTransition(QEvent *e) { Q_Q(QAbstractTransition); - q->onTransition(); + q->onTransition(e); } QState *QAbstractTransitionPrivate::sourceState() const @@ -353,10 +353,11 @@ QList QAbstractTransition::animations() const */ /*! - \fn QAbstractTransition::onTransition() + \fn QAbstractTransition::onTransition(QEvent *event) - This function is called when the transition is triggered. Reimplement this - function to perform custom processing when the transition is triggered. + This function is called when the transition is triggered. The given \a event + is what caused the transition to trigger. Reimplement this function to + perform custom processing when the transition is triggered. */ /*! diff --git a/src/corelib/statemachine/qabstracttransition.h b/src/corelib/statemachine/qabstracttransition.h index 79ab808..e207944 100644 --- a/src/corelib/statemachine/qabstracttransition.h +++ b/src/corelib/statemachine/qabstracttransition.h @@ -90,7 +90,7 @@ public: protected: virtual bool eventTest(QEvent *event) const = 0; - virtual void onTransition() = 0; + virtual void onTransition(QEvent *event) = 0; bool event(QEvent *e); diff --git a/src/corelib/statemachine/qabstracttransition_p.h b/src/corelib/statemachine/qabstracttransition_p.h index a48a09c..b4e1c88 100644 --- a/src/corelib/statemachine/qabstracttransition_p.h +++ b/src/corelib/statemachine/qabstracttransition_p.h @@ -79,7 +79,7 @@ public: static const QAbstractTransitionPrivate *get(const QAbstractTransition *q); bool callEventTest(QEvent *e) const; - void callOnTransition(); + void callOnTransition(QEvent *e); QState *sourceState() const; QStateMachine *machine() const; diff --git a/src/corelib/statemachine/qeventtransition.cpp b/src/corelib/statemachine/qeventtransition.cpp index cbd03bd..86259e4 100644 --- a/src/corelib/statemachine/qeventtransition.cpp +++ b/src/corelib/statemachine/qeventtransition.cpp @@ -270,8 +270,9 @@ bool QEventTransition::eventTest(QEvent *event) const /*! \reimp */ -void QEventTransition::onTransition() +void QEventTransition::onTransition(QEvent *event) { + Q_UNUSED(event); } /*! diff --git a/src/corelib/statemachine/qeventtransition.h b/src/corelib/statemachine/qeventtransition.h index 484602c..a128cee 100644 --- a/src/corelib/statemachine/qeventtransition.h +++ b/src/corelib/statemachine/qeventtransition.h @@ -78,7 +78,7 @@ public: protected: bool eventTest(QEvent *event) const; - void onTransition(); + void onTransition(QEvent *event); bool event(QEvent *e); diff --git a/src/corelib/statemachine/qfinalstate.cpp b/src/corelib/statemachine/qfinalstate.cpp index 6a1b608..772ec87 100644 --- a/src/corelib/statemachine/qfinalstate.cpp +++ b/src/corelib/statemachine/qfinalstate.cpp @@ -108,15 +108,17 @@ QFinalState::~QFinalState() /*! \reimp */ -void QFinalState::onEntry() +void QFinalState::onEntry(QEvent *event) { + Q_UNUSED(event); } /*! \reimp */ -void QFinalState::onExit() +void QFinalState::onExit(QEvent *event) { + Q_UNUSED(event); } /*! diff --git a/src/corelib/statemachine/qfinalstate.h b/src/corelib/statemachine/qfinalstate.h index 726a399..eb8aa0f 100644 --- a/src/corelib/statemachine/qfinalstate.h +++ b/src/corelib/statemachine/qfinalstate.h @@ -63,8 +63,8 @@ public: ~QFinalState(); protected: - void onEntry(); - void onExit(); + void onEntry(QEvent *event); + void onExit(QEvent *event); bool event(QEvent *e); diff --git a/src/corelib/statemachine/qhistorystate.cpp b/src/corelib/statemachine/qhistorystate.cpp index 4e3db08..fd6f53d 100644 --- a/src/corelib/statemachine/qhistorystate.cpp +++ b/src/corelib/statemachine/qhistorystate.cpp @@ -200,14 +200,14 @@ void QHistoryState::setHistoryType(HistoryType type) /*! \reimp */ -void QHistoryState::onEntry() +void QHistoryState::onEntry(QEvent *event) { } /*! \reimp */ -void QHistoryState::onExit() +void QHistoryState::onExit(QEvent *event) { } diff --git a/src/corelib/statemachine/qhistorystate.h b/src/corelib/statemachine/qhistorystate.h index c7648bc..d0f75de 100644 --- a/src/corelib/statemachine/qhistorystate.h +++ b/src/corelib/statemachine/qhistorystate.h @@ -78,8 +78,8 @@ public: void setHistoryType(HistoryType type); protected: - void onEntry(); - void onExit(); + void onEntry(QEvent *event); + void onExit(QEvent *event); bool event(QEvent *e); diff --git a/src/corelib/statemachine/qsignaltransition.cpp b/src/corelib/statemachine/qsignaltransition.cpp index e9e248f..d5833bd 100644 --- a/src/corelib/statemachine/qsignaltransition.cpp +++ b/src/corelib/statemachine/qsignaltransition.cpp @@ -245,8 +245,9 @@ bool QSignalTransition::eventTest(QEvent *event) const /*! \reimp */ -void QSignalTransition::onTransition() +void QSignalTransition::onTransition(QEvent *event) { + Q_UNUSED(event); } /*! diff --git a/src/corelib/statemachine/qsignaltransition.h b/src/corelib/statemachine/qsignaltransition.h index b8e8fc6..98a9ae7 100644 --- a/src/corelib/statemachine/qsignaltransition.h +++ b/src/corelib/statemachine/qsignaltransition.h @@ -77,7 +77,7 @@ public: protected: bool eventTest(QEvent *event) const; - void onTransition(); + void onTransition(QEvent *event); bool event(QEvent *e); diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp index a431888..3220619 100644 --- a/src/corelib/statemachine/qstate.cpp +++ b/src/corelib/statemachine/qstate.cpp @@ -339,7 +339,7 @@ public: UnconditionalTransition(QAbstractState *target) : QAbstractTransition(QList() << target) {} protected: - void onTransition() {} + void onTransition(QEvent *) {} bool eventTest(QEvent *) const { return true; } }; @@ -384,15 +384,17 @@ void QState::removeTransition(QAbstractTransition *transition) /*! \reimp */ -void QState::onEntry() +void QState::onEntry(QEvent *event) { + Q_UNUSED(event); } /*! \reimp */ -void QState::onExit() +void QState::onExit(QEvent *event) { + Q_UNUSED(event); } /*! diff --git a/src/corelib/statemachine/qstate.h b/src/corelib/statemachine/qstate.h index 9faef26..73955d7 100644 --- a/src/corelib/statemachine/qstate.h +++ b/src/corelib/statemachine/qstate.h @@ -97,8 +97,8 @@ Q_SIGNALS: void polished(); protected: - void onEntry(); - void onExit(); + void onEntry(QEvent *event); + void onExit(QEvent *event); bool event(QEvent *e); diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 0ebc993..8b0b4f3 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -369,18 +369,18 @@ QSet QStateMachinePrivate::selectTransitions(QEvent *event return enabledTransitions; } -void QStateMachinePrivate::microstep(const QList &enabledTransitions) +void QStateMachinePrivate::microstep(QEvent *event, const QList &enabledTransitions) { #ifdef QSTATEMACHINE_DEBUG qDebug() << q_func() << ": begin microstep( enabledTransitions:" << enabledTransitions << ")"; qDebug() << q_func() << ": configuration before exiting states:" << configuration; #endif - QList exitedStates = exitStates(enabledTransitions); + QList exitedStates = exitStates(event, enabledTransitions); #ifdef QSTATEMACHINE_DEBUG qDebug() << q_func() << ": configuration after exiting states:" << configuration; #endif - executeTransitionContent(enabledTransitions); - QList enteredStates = enterStates(enabledTransitions); + executeTransitionContent(event, enabledTransitions); + QList enteredStates = enterStates(event, enabledTransitions); applyProperties(enabledTransitions, exitedStates, enteredStates); #ifdef QSTATEMACHINE_DEBUG qDebug() << q_func() << ": configuration after entering states:" << configuration; @@ -388,7 +388,7 @@ void QStateMachinePrivate::microstep(const QList &enabledT #endif } -QList QStateMachinePrivate::exitStates(const QList &enabledTransitions) +QList QStateMachinePrivate::exitStates(QEvent *event, const QList &enabledTransitions) { // qDebug() << "exitStates(" << enabledTransitions << ")"; QSet statesToExit; @@ -440,25 +440,25 @@ QList QStateMachinePrivate::exitStates(const QListcallOnExit(); + QAbstractStatePrivate::get(s)->callOnExit(event); configuration.remove(s); QAbstractStatePrivate::get(s)->emitExited(); } return statesToExit_sorted; } -void QStateMachinePrivate::executeTransitionContent(const QList &enabledTransitions) +void QStateMachinePrivate::executeTransitionContent(QEvent *event, const QList &enabledTransitions) { for (int i = 0; i < enabledTransitions.size(); ++i) { QAbstractTransition *t = enabledTransitions.at(i); #ifdef QSTATEMACHINE_DEBUG qDebug() << q_func() << ": triggering" << t; #endif - QAbstractTransitionPrivate::get(t)->callOnTransition(); + QAbstractTransitionPrivate::get(t)->callOnTransition(event); } } -QList QStateMachinePrivate::enterStates(const QList &enabledTransitions) +QList QStateMachinePrivate::enterStates(QEvent *event, const QList &enabledTransitions) { #ifdef QSTATEMACHINE_DEBUG Q_Q(QStateMachine); @@ -506,7 +506,7 @@ QList QStateMachinePrivate::enterStates(const QListcallOnEntry(); + QAbstractStatePrivate::get(s)->callOnEntry(event); QAbstractStatePrivate::get(s)->emitEntered(); if (statesForDefaultEntry.contains(s)) { // ### executeContent(s.initial.transition.children()) @@ -1067,8 +1067,8 @@ public: StartState(QState *parent) : QState(parent) {} protected: - void onEntry() {} - void onExit() {} + void onEntry(QEvent *) {} + void onExit(QEvent *) {} }; class InitialTransition : public QAbstractTransition @@ -1078,7 +1078,7 @@ public: : QAbstractTransition(QList() << target) {} protected: virtual bool eventTest(QEvent *) const { return true; } - virtual void onTransition() {} + virtual void onTransition(QEvent *) {} }; } // namespace @@ -1113,8 +1113,9 @@ void QStateMachinePrivate::_q_start() start->addTransition(initialTransition); QList transitions; transitions.append(initialTransition); - executeTransitionContent(transitions); - enterStates(transitions); + QEvent nullEvent(QEvent::None); + executeTransitionContent(&nullEvent, transitions); + enterStates(&nullEvent, transitions); applyProperties(transitions, QList() << start, QList() << initial); delete start; @@ -1180,7 +1181,7 @@ void QStateMachinePrivate::_q_process() } if (!enabledTransitions.isEmpty()) { q->beginMicrostep(e); - microstep(enabledTransitions.toList()); + microstep(e, enabledTransitions.toList()); q->endMicrostep(e); } #ifdef QSTATEMACHINE_DEBUG @@ -1455,7 +1456,7 @@ public: setObjectName(QString::fromLatin1("DefaultErrorState")); } - void onEntry() + void onEntry(QEvent *) { QAbstractStatePrivate *d = QAbstractStatePrivate::get(this); QStateMachine *machine = d->machine(); @@ -1464,7 +1465,7 @@ public: qPrintable(machine->errorString())); } - void onExit() {} + void onExit(QEvent *) {} }; class RootState : public QState @@ -1475,8 +1476,8 @@ public: { } - void onEntry() {} - void onExit() {} + void onEntry(QEvent *) {} + void onExit(QEvent *) {} }; } // namespace diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index b3707ea..bb4a78c 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -120,12 +120,12 @@ public: void _q_animationFinished(); #endif - void microstep(const QList &transitionList); + void microstep(QEvent *event, const QList &transitionList); bool isPreempted(const QAbstractState *s, const QSet &transitions) const; QSet selectTransitions(QEvent *event) const; - QList exitStates(const QList &transitionList); - void executeTransitionContent(const QList &transitionList); - QList enterStates(const QList &enabledTransitions); + QList exitStates(QEvent *event, const QList &transitionList); + void executeTransitionContent(QEvent *event, const QList &transitionList); + QList enterStates(QEvent *event, const QList &enabledTransitions); void addStatesToEnter(QAbstractState *s, QState *root, QSet &statesToEnter, QSet &statesForDefaultEntry); diff --git a/src/gui/statemachine/qbasickeyeventtransition.cpp b/src/gui/statemachine/qbasickeyeventtransition.cpp index 4e3fa11..7821feb 100644 --- a/src/gui/statemachine/qbasickeyeventtransition.cpp +++ b/src/gui/statemachine/qbasickeyeventtransition.cpp @@ -170,7 +170,7 @@ bool QBasicKeyEventTransition::eventTest(QEvent *event) const /*! \reimp */ -void QBasicKeyEventTransition::onTransition() +void QBasicKeyEventTransition::onTransition(QEvent *) { } diff --git a/src/gui/statemachine/qbasickeyeventtransition_p.h b/src/gui/statemachine/qbasickeyeventtransition_p.h index de49eac..0d08da0 100644 --- a/src/gui/statemachine/qbasickeyeventtransition_p.h +++ b/src/gui/statemachine/qbasickeyeventtransition_p.h @@ -56,7 +56,7 @@ public: protected: bool eventTest(QEvent *event) const; - void onTransition(); + void onTransition(QEvent *); private: Q_DISABLE_COPY(QBasicKeyEventTransition) diff --git a/src/gui/statemachine/qbasicmouseeventtransition.cpp b/src/gui/statemachine/qbasicmouseeventtransition.cpp index 83254dc..0cb727e 100644 --- a/src/gui/statemachine/qbasicmouseeventtransition.cpp +++ b/src/gui/statemachine/qbasicmouseeventtransition.cpp @@ -174,7 +174,7 @@ bool QBasicMouseEventTransition::eventTest(QEvent *event) const /*! \reimp */ -void QBasicMouseEventTransition::onTransition() +void QBasicMouseEventTransition::onTransition(QEvent *) { } diff --git a/src/gui/statemachine/qbasicmouseeventtransition_p.h b/src/gui/statemachine/qbasicmouseeventtransition_p.h index 77fbd58..20c7f8f 100644 --- a/src/gui/statemachine/qbasicmouseeventtransition_p.h +++ b/src/gui/statemachine/qbasicmouseeventtransition_p.h @@ -59,7 +59,7 @@ public: protected: bool eventTest(QEvent *event) const; - void onTransition(); + void onTransition(QEvent *); private: Q_DISABLE_COPY(QBasicMouseEventTransition) diff --git a/src/gui/statemachine/qkeyeventtransition.cpp b/src/gui/statemachine/qkeyeventtransition.cpp index 37f4dd9..e6ab11b 100644 --- a/src/gui/statemachine/qkeyeventtransition.cpp +++ b/src/gui/statemachine/qkeyeventtransition.cpp @@ -153,9 +153,9 @@ bool QKeyEventTransition::eventTest(QEvent *event) const /*! \reimp */ -void QKeyEventTransition::onTransition() +void QKeyEventTransition::onTransition(QEvent *event) { - QEventTransition::onTransition(); + QEventTransition::onTransition(event); } QT_END_NAMESPACE diff --git a/src/gui/statemachine/qkeyeventtransition.h b/src/gui/statemachine/qkeyeventtransition.h index fa95c1b..3f797f1 100644 --- a/src/gui/statemachine/qkeyeventtransition.h +++ b/src/gui/statemachine/qkeyeventtransition.h @@ -45,7 +45,7 @@ public: void setModifiersMask(Qt::KeyboardModifiers modifiers); protected: - void onTransition(); + void onTransition(QEvent *event); bool eventTest(QEvent *event) const; private: diff --git a/src/gui/statemachine/qmouseeventtransition.cpp b/src/gui/statemachine/qmouseeventtransition.cpp index 353b833..3191a2f 100644 --- a/src/gui/statemachine/qmouseeventtransition.cpp +++ b/src/gui/statemachine/qmouseeventtransition.cpp @@ -183,9 +183,9 @@ bool QMouseEventTransition::eventTest(QEvent *event) const /*! \reimp */ -void QMouseEventTransition::onTransition() +void QMouseEventTransition::onTransition(QEvent *event) { - QEventTransition::onTransition(); + QEventTransition::onTransition(event); } QT_END_NAMESPACE diff --git a/src/gui/statemachine/qmouseeventtransition.h b/src/gui/statemachine/qmouseeventtransition.h index d5fb565..eee971e 100644 --- a/src/gui/statemachine/qmouseeventtransition.h +++ b/src/gui/statemachine/qmouseeventtransition.h @@ -51,7 +51,7 @@ public: void setPath(const QPainterPath &path); protected: - void onTransition(); + void onTransition(QEvent *event); bool eventTest(QEvent *event) const; private: diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 5dfc758..94afe51 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -186,10 +186,10 @@ public: : QState(parent) {} QList > events; protected: - virtual void onEntry() { + virtual void onEntry(QEvent *) { events.append(qMakePair(globalTick++, Entry)); } - virtual void onExit() { + virtual void onExit(QEvent *) { events.append(qMakePair(globalTick++, Exit)); } }; @@ -204,7 +204,7 @@ protected: virtual bool eventTest(QEvent *) const { return true; } - virtual void onTransition() { + virtual void onTransition(QEvent *) { triggers.append(globalTick++); } }; @@ -246,7 +246,7 @@ protected: virtual bool eventTest(QEvent *e) const { return (e->type() == m_type); } - virtual void onTransition() {} + virtual void onTransition(QEvent *) {} private: QEvent::Type m_type; }; @@ -380,7 +380,7 @@ public: { } - void onEntry() + void onEntry(QEvent *) { error = m_machine->error(); errorString = m_machine->errorString(); @@ -1367,7 +1367,7 @@ protected: StringEvent *se = static_cast(e); return (m_value == se->value) && (!m_cond.isValid() || (m_cond.indexIn(m_value) != -1)); } - virtual void onTransition() {} + virtual void onTransition(QEvent *) {} private: QString m_value; @@ -1384,11 +1384,11 @@ public: { m_value = value; } protected: - virtual void onEntry() + virtual void onEntry(QEvent *) { m_machine->postEvent(new StringEvent(m_value)); } - virtual void onExit() {} + virtual void onExit(QEvent *) {} private: QStateMachine *m_machine; -- cgit v0.12 From b8a4216f2fb5bc6e5fd5b54c661344e60fc9093c Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Tue, 5 May 2009 18:30:47 +0200 Subject: get rid of warnings --- src/corelib/statemachine/qhistorystate.cpp | 2 ++ src/corelib/statemachine/qstatemachine.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/corelib/statemachine/qhistorystate.cpp b/src/corelib/statemachine/qhistorystate.cpp index fd6f53d..b6ec471 100644 --- a/src/corelib/statemachine/qhistorystate.cpp +++ b/src/corelib/statemachine/qhistorystate.cpp @@ -202,6 +202,7 @@ void QHistoryState::setHistoryType(HistoryType type) */ void QHistoryState::onEntry(QEvent *event) { + Q_UNUSED(event); } /*! @@ -209,6 +210,7 @@ void QHistoryState::onEntry(QEvent *event) */ void QHistoryState::onExit(QEvent *event) { + Q_UNUSED(event); } /*! diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 8b0b4f3..232d801 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -661,7 +661,7 @@ void QStateMachinePrivate::applyProperties(const QList &tr // before the state that assigned them is exited. If state does not explicitly // assign a property which is assigned by the parent, it inherits the parent's assignment. QState *parentState = s; - while (parentState = parentState->parentState()) { + while ((parentState = parentState->parentState()) != 0) { assignments = QStatePrivate::get(parentState)->propertyAssignments; for (int j=0; j Date: Tue, 5 May 2009 19:45:06 +0200 Subject: doc improvements --- src/corelib/statemachine/qfinalstate.cpp | 8 +++++--- src/corelib/statemachine/qhistorystate.cpp | 12 +++++++---- src/corelib/statemachine/qstate.cpp | 22 +++++++++++++++----- src/corelib/statemachine/qstatemachine.cpp | 32 ++++++++++++++++++++---------- 4 files changed, 51 insertions(+), 23 deletions(-) diff --git a/src/corelib/statemachine/qfinalstate.cpp b/src/corelib/statemachine/qfinalstate.cpp index 772ec87..0980336 100644 --- a/src/corelib/statemachine/qfinalstate.cpp +++ b/src/corelib/statemachine/qfinalstate.cpp @@ -55,9 +55,9 @@ QT_BEGIN_NAMESPACE A final state is used to communicate that (part of) a QStateMachine has finished its work. When a final top-level state is entered, the state machine's \l{QStateMachine::finished()}{finished}() signal is emitted. In - general, when a final substate (a child of a QState) is entered, a - QStateFinishedEvent is generated for the final state's parent - state. QFinalState is part of \l{The State Machine Framework}. + general, when a final substate (a child of a QState) is entered, the parent + state's \l{QState::finished()}{finished}() signal is emitted. QFinalState + is part of \l{The State Machine Framework}. To use a final state, you create a QFinalState object and add a transition to it from another state. Example: @@ -76,6 +76,8 @@ QT_BEGIN_NAMESPACE machine.setInitialState(s1); machine.start(); \endcode + + \sa QStateMachine::finished(), QState::finished() */ class QFinalStatePrivate : public QAbstractStatePrivate diff --git a/src/corelib/statemachine/qhistorystate.cpp b/src/corelib/statemachine/qhistorystate.cpp index b6ec471..d1b2391 100644 --- a/src/corelib/statemachine/qhistorystate.cpp +++ b/src/corelib/statemachine/qhistorystate.cpp @@ -58,9 +58,8 @@ QT_BEGIN_NAMESPACE other child states of the parent state. QHistoryState is part of \l{The State Machine Framework}. - Use QState::addHistoryState() to construct a history state. Use the - setDefaultState() function to set the state that should be entered if the - parent state has never been entered. Example: + Use the setDefaultState() function to set the state that should be entered + if the parent state has never been entered. Example: \code QStateMachine machine; @@ -69,7 +68,7 @@ QT_BEGIN_NAMESPACE QState *s11 = new QState(s1); QState *s12 = new QState(s1); - QState *s1h = s1->addHistoryState(); + QHistoryState *s1h = new QHistoryState(s1); s1h->setDefaultState(s11); machine.addState(s1); @@ -83,6 +82,9 @@ QT_BEGIN_NAMESPACE // state if s1 has never been entered. s1->addTransition(button, SIGNAL(clicked()), s1h); \endcode + + By default a history state is shallow, meaning that it won't remember nested + states. This can be configured through the historyType property. */ /*! @@ -95,6 +97,8 @@ QT_BEGIN_NAMESPACE \property QHistoryState::historyType \brief the type of history that this history state records + + The default value of this property is QHistoryState::ShallowHistory. */ /*! diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp index 3220619..4c9e033 100644 --- a/src/corelib/statemachine/qstate.cpp +++ b/src/corelib/statemachine/qstate.cpp @@ -68,22 +68,30 @@ QT_BEGIN_NAMESPACE The assignProperty() function is used for defining property assignments that should be performed when a state is entered. + Top-level states must be passed QStateMachine::rootState() as their parent + state, or added to a state machine using QStateMachine::addState(). + \section1 States with Child States - For non-parallel state groups, the setInitialState() function must be called - to set the initial state. The child states are mutually exclusive states, - and the state machine needs to know which child state to enter when the - parent state is the target of a transition. + The childMode property determines how child states are treated. For + non-parallel state groups, the setInitialState() function must be called to + set the initial state. The child states are mutually exclusive states, and + the state machine needs to know which child state to enter when the parent + state is the target of a transition. + + The state emits the QState::finished() signal when a final child state + (QFinalState) is entered. The setErrorState() sets the state's error state. The error state is the state that the state machine will transition to if an error is detected when attempting to enter the state (e.g. because no initial state has been set). + */ /*! \property QState::initialState - \brief the initial state of this state + \brief the initial state of this state (one of its child states) */ /*! @@ -96,6 +104,8 @@ QT_BEGIN_NAMESPACE \property QState::childMode \brief the child mode of this state + + The default value of this property is QState::ExclusiveStates. */ /*! @@ -456,6 +466,8 @@ bool QState::event(QEvent *e) \fn QState::finished() This signal is emitted when a final child state of this state is entered. + + \sa QFinalState */ /*! diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 232d801..6f626f5 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -163,6 +163,8 @@ QT_BEGIN_NAMESPACE \property QStateMachine::initialState \brief the initial state of this state machine + + The initial state must be one of the rootState()'s child states. */ /*! @@ -181,6 +183,9 @@ QT_BEGIN_NAMESPACE \property QStateMachine::globalRestorePolicy \brief the restore policy for states of this state machine. + + The default value of this property is + QStateMachine::DoNotRestoreProperties. */ #ifndef QT_NO_ANIMATION @@ -188,6 +193,10 @@ QT_BEGIN_NAMESPACE \property QStateMachine::animationsEnabled \brief whether animations are enabled + + The default value of this property is true. + + \sa QAbstractTransition::addAnimation() */ #endif @@ -1663,7 +1672,7 @@ void QStateMachine::setInitialState(QAbstractState *state) If the state is already in a different machine, it will first be removed from its old machine, and then added to this machine. - \sa removeState(), rootState() + \sa removeState(), rootState(), setInitialState() */ void QStateMachine::addState(QAbstractState *state) { @@ -1700,10 +1709,9 @@ void QStateMachine::removeState(QAbstractState *state) } /*! - Starts this state machine. - The machine will reset its configuration and transition to the initial - state. When a final top-level state is entered, the machine will emit the - finished() signal. + Starts this state machine. The machine will reset its configuration and + transition to the initial state. When a final top-level state (QFinalState) + is entered, the machine will emit the finished() signal. \sa started(), finished(), stop(), initialState() */ @@ -1730,9 +1738,10 @@ void QStateMachine::start() } /*! - Stops this state machine. + Stops this state machine. The state machine will stop processing events and + then emit the stopped() signal. - \sa stopped() + \sa stopped(), start() */ void QStateMachine::stop() { @@ -1813,7 +1822,8 @@ QSet QStateMachine::configuration() const /*! \fn QStateMachine::started() - This signal is emitted when the state machine has entered its initial state. + This signal is emitted when the state machine has entered its initial state + (QStateMachine::initialState). \sa QStateMachine::finished(), QStateMachine::start() */ @@ -1822,7 +1832,7 @@ QSet QStateMachine::configuration() const \fn QStateMachine::finished() This signal is emitted when the state machine has reached a top-level final - state. + state (QFinalState). \sa QStateMachine::started() */ @@ -1832,7 +1842,7 @@ QSet QStateMachine::configuration() const This signal is emitted when the state machine has stopped. - \sa QStateMachine::stop() + \sa QStateMachine::stop(), QStateMachine::finished() */ /*! @@ -2110,7 +2120,7 @@ QSignalEvent::~QSignalEvent() Returns the index of the signal. - \sa QMetaObject::indexOfSignal() + \sa QMetaObject::indexOfSignal(), QMetaObject::method() */ /*! -- cgit v0.12 From ce44510d932c0fc77c368f45848a0fc751f5a18b Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Tue, 5 May 2009 20:08:47 +0200 Subject: get rid of margin --- examples/statemachine/trafficlight/main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/statemachine/trafficlight/main.cpp b/examples/statemachine/trafficlight/main.cpp index ed0eeea..3c47a51 100644 --- a/examples/statemachine/trafficlight/main.cpp +++ b/examples/statemachine/trafficlight/main.cpp @@ -151,6 +151,7 @@ public: QVBoxLayout *vbox = new QVBoxLayout(this); TrafficLightWidget *widget = new TrafficLightWidget(); vbox->addWidget(widget); + vbox->setMargin(0); QStateMachine *machine = new QStateMachine(this); LightState *redGoingYellow = new LightState(widget->redLight(), 3000); @@ -182,7 +183,7 @@ int main(int argc, char **argv) QApplication app(argc, argv); TrafficLight widget; - widget.resize(120, 300); + widget.resize(110, 300); widget.show(); return app.exec(); -- cgit v0.12 From 7f3b4bdc97e155f84d5294fa822481b8e16e4fc1 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 5 May 2009 15:33:28 +0200 Subject: Avoid passage where the walls meet the edge of the scene rect. --- examples/statemachine/errorstate/mainwindow.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/examples/statemachine/errorstate/mainwindow.cpp b/examples/statemachine/errorstate/mainwindow.cpp index 4d9b88e..39b8663 100644 --- a/examples/statemachine/errorstate/mainwindow.cpp +++ b/examples/statemachine/errorstate/mainwindow.cpp @@ -88,18 +88,19 @@ void MainWindow::init() } QPointF centerOfMap = sceneRect.center(); + addWall(QRectF(centerOfMap + QPointF(-50.0, -60.0), centerOfMap + QPointF(50.0, -50.0))); addWall(QRectF(centerOfMap - QPointF(-50.0, -60.0), centerOfMap - QPointF(50.0, -50.0))); addWall(QRectF(centerOfMap + QPointF(-50.0, -50.0), centerOfMap + QPointF(-40.0, 50.0))); addWall(QRectF(centerOfMap - QPointF(-50.0, -50.0), centerOfMap - QPointF(-40.0, 50.0))); - - addWall(QRectF(sceneRect.topLeft() + QPointF(sceneRect.width() / 2.0 - 5.0, 0.0), + + addWall(QRectF(sceneRect.topLeft() + QPointF(sceneRect.width() / 2.0 - 5.0, -10.0), sceneRect.topLeft() + QPointF(sceneRect.width() / 2.0 + 5.0, 100.0))); - addWall(QRectF(sceneRect.bottomLeft() + QPointF(sceneRect.width() / 2.0 - 5.0, 0.0), + addWall(QRectF(sceneRect.bottomLeft() + QPointF(sceneRect.width() / 2.0 - 5.0, 10.0), sceneRect.bottomLeft() + QPointF(sceneRect.width() / 2.0 + 5.0, -100.0))); - addWall(QRectF(sceneRect.topLeft() + QPointF(0.0, sceneRect.height() / 2.0 - 5.0), + addWall(QRectF(sceneRect.topLeft() + QPointF(-10.0, sceneRect.height() / 2.0 - 5.0), sceneRect.topLeft() + QPointF(100.0, sceneRect.height() / 2.0 + 5.0))); - addWall(QRectF(sceneRect.topRight() + QPointF(0.0, sceneRect.height() / 2.0 - 5.0), + addWall(QRectF(sceneRect.topRight() + QPointF(10.0, sceneRect.height() / 2.0 - 5.0), sceneRect.topRight() + QPointF(-100.0, sceneRect.height() / 2.0 + 5.0))); -- cgit v0.12 From a9fd7d6881107b7e06362076c587530124fb1484 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 5 May 2009 16:38:53 +0200 Subject: Add chase state and ability to detect and fire at other tanks. This reveals an assert in the state machine which needs to be debugged. --- .../errorstateplugins/seek_ai/seek_ai.cpp | 6 ++ .../errorstateplugins/seek_ai/seek_ai.h | 90 +++++++++++++++++++++- 2 files changed, 92 insertions(+), 4 deletions(-) diff --git a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.cpp b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.cpp index 229f83a..2fb05d4 100644 --- a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.cpp +++ b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.cpp @@ -36,6 +36,12 @@ QState *SeekAi::create(QState *parentState, QObject *tank) turnTo->addTransition(tank, SIGNAL(actionCompleted()), driveToFirstObstacle); + ChaseState *chase = new ChaseState(tank, topLevel); + chase->setObjectName("chase"); + seek->addTransition(new TankSpottedTransition(tank, chase)); + chase->addTransition(chase, SIGNAL(finished()), driveToFirstObstacle); + chase->addTransition(new TankSpottedTransition(tank, chase)); + return topLevel; } diff --git a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h index 7d8aa68..34d203e 100644 --- a/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h +++ b/examples/statemachine/errorstateplugins/seek_ai/seek_ai.h @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -72,7 +73,7 @@ class CollisionTransition: public QSignalTransition { public: CollisionTransition(QObject *tank, QState *turnTo) - : QSignalTransition(tank, SIGNAL(collision(QLineF)), turnTo), + : QSignalTransition(tank, SIGNAL(collision(QLineF))), m_tank(tank), m_turnTo(turnTo) { @@ -82,16 +83,16 @@ public: protected: bool eventTest(QEvent *event) const { - if (event->type() == QEvent::Signal) { + bool b = QSignalTransition::eventTest(event); + if (b) { QSignalEvent *se = static_cast(event); m_lastLine = se->arguments().at(0).toLineF(); } - return QSignalTransition::eventTest(event); + return b; } void onTransition(QEvent *) { - qreal currentDirection = m_tank->property("direction").toDouble(); qreal angleOfWall = m_lastLine.angle(); qreal newDirection; @@ -109,6 +110,87 @@ private: QState *m_turnTo; }; +class ChaseState: public QState +{ + class GoToLocationState: public QState + { + public: + GoToLocationState(QObject *tank, QState *parentState = 0) + : QState(parentState), m_tank(tank), m_distance(0.0) + { + } + + void setDistance(qreal distance) { m_distance = distance; } + + protected: + void onEntry() + { + QMetaObject::invokeMethod(m_tank, "moveForwards", Q_ARG(qreal, m_distance)); + } + + private: + QObject *m_tank; + qreal m_distance; + }; + +public: + ChaseState(QObject *tank, QState *parentState = 0) : QState(parentState), m_tank(tank) + { + QState *fireCannon = new QState(this); + connect(fireCannon, SIGNAL(entered()), tank, SLOT(fireCannon())); + setInitialState(fireCannon); + + m_goToLocation = new GoToLocationState(this); + fireCannon->addTransition(tank, SIGNAL(actionCompleted()), m_goToLocation); + + m_turnToDirection = new QState(this); + m_goToLocation->addTransition(tank, SIGNAL(actionCompleted()), m_turnToDirection); + + QFinalState *finalState = new QFinalState(this); + m_turnToDirection->addTransition(tank, SIGNAL(actionCompleted()), finalState); + } + + void setDirection(qreal direction) + { + m_turnToDirection->assignProperty(m_tank, "direction", direction); + } + + void setDistance(qreal distance) + { + m_goToLocation->setDistance(distance); + } + +private: + QObject *m_tank; + GoToLocationState *m_goToLocation; + QState *m_turnToDirection; + +}; + +class TankSpottedTransition: public QSignalTransition +{ +public: + TankSpottedTransition(QObject *tank, ChaseState *target) : QSignalTransition(tank, SIGNAL(tankSpotted(qreal,qreal))), m_chase(target) + { + setTargetState(target); + } + +protected: + bool eventTest(QEvent *event) const + { + bool b = QSignalTransition::eventTest(event); + if (b) { + QSignalEvent *se = static_cast(event); + m_chase->setDirection(se->arguments().at(0).toDouble()); + m_chase->setDistance(se->arguments().at(1).toDouble()); + } + return b; + } + +private: + ChaseState *m_chase; +}; + class SeekAi: public QObject, public Plugin { Q_OBJECT -- cgit v0.12 From 48ca4182e518a6439264f87b54e691deecc59e20 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 6 May 2009 10:25:41 +0200 Subject: Instead of adding animations for all properties to all transitions, we use the default animation concept, since this is its intended use. --- examples/animation/appchooser/main.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/examples/animation/appchooser/main.cpp b/examples/animation/appchooser/main.cpp index 02302d9..1c63aba 100644 --- a/examples/animation/appchooser/main.cpp +++ b/examples/animation/appchooser/main.cpp @@ -90,15 +90,16 @@ void createStates(const QObjectList &objects, for (int i = 0; i < objects.size(); ++i) { QState *state = new QState(parent); state->assignProperty(objects.at(i), "geometry", selectedRect); - QAbstractTransition *trans = parent->addTransition(objects.at(i), SIGNAL(clicked()), state); - for (int j = 0; j < objects.size(); ++j) { - QPropertyAnimation *animation = new QPropertyAnimation(objects.at(j), "geometry"); - animation->setDuration(2000); - trans->addAnimation(animation); - } + parent->addTransition(objects.at(i), SIGNAL(clicked()), state); } } +void createAnimations(const QObjectList &objects, QStateMachine *machine) +{ + for (int i=0; iaddDefaultAnimation(new QPropertyAnimation(objects.at(i), "geometry")); +} + int main(int argc, char **argv) { Q_INIT_RESOURCE(appchooser); @@ -143,7 +144,10 @@ int main(int argc, char **argv) QState *idleState = new QState(group); group->setInitialState(idleState); - createStates(QObjectList() << p1 << p2 << p3 << p4, selectedRect, group); + QObjectList objects; + objects << p1 << p2 << p3 << p4; + createStates(objects, selectedRect, group); + createAnimations(objects, &machine); machine.setInitialState(group); machine.start(); -- cgit v0.12 From d2c34394b7105e26612c1fe2b2bb22be4bd8e097 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 6 May 2009 10:29:20 +0200 Subject: Fix bogus default start value when interrupting an animation that has an implicit end value. We need to stop the animation prior to setting the end value to an invalid variant, otherwise the current value of the property will be updated based on the new end value and randomness will occur. --- src/corelib/statemachine/qstatemachine.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 6f626f5..98aa9f2 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -698,6 +698,13 @@ void QStateMachinePrivate::applyProperties(const QList &tr QAbstractAnimation *anim = animations.at(j); QObject::disconnect(anim, SIGNAL(finished()), q, SLOT(_q_animationFinished())); stateForAnimation.remove(anim); + + // Stop the (top-level) animation. + // ### Stopping nested animation has weird behavior. + while (QAnimationGroup *group = anim->group()) + anim = group; + anim->stop(); + if (resetAnimationEndValues.contains(anim)) { qobject_cast(anim)->setEndValue(QVariant()); // ### generalize resetAnimationEndValues.remove(anim); @@ -721,11 +728,6 @@ void QStateMachinePrivate::applyProperties(const QList &tr if (!found) { assn.object->setProperty(assn.propertyName, assn.value); } - // Stop the (top-level) animation. - // ### Stopping nested animation has weird behavior. - while (QAnimationGroup *group = anim->group()) - anim = group; - anim->stop(); } } -- cgit v0.12 From 612e0d23938b37907f3f4fdf9733732e4b7b8a7e Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 6 May 2009 10:33:46 +0200 Subject: Remove superfluous code We have gone back to the old definition of implicit start values where the a new default start value is sniffed every time the animation is restarted, so we do not need to emulate this behavior ourselves anymore. Behavior should be identical. --- src/corelib/statemachine/qstatemachine.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 98aa9f2..7d6616a 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -1019,13 +1019,6 @@ QStateMachinePrivate::initializeAnimation(QAbstractAnimation *abstractAnimation, && prop.object == animation->targetObject() && prop.propertyName == animation->propertyName()) { - if (!animation->startValue().isValid()) { - QByteArray propertyName = animation->propertyName(); - QVariant currentValue = animation->targetObject()->property(propertyName); - - QVariantAnimationPrivate::get(animation)->setDefaultStartValue(currentValue); - } - // Only change end value if it is undefined if (!animation->endValue().isValid()) { animation->setEndValue(prop.value); -- cgit v0.12 From ed900ca77ad3c3e337054346213dc38a58137818 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 7 May 2009 10:05:05 +0200 Subject: Compile with new API addHistoryState() is gone and onTransition() now takes an argument. --- tests/auto/qstate/tst_qstate.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/qstate/tst_qstate.cpp b/tests/auto/qstate/tst_qstate.cpp index f082caf..bb7de20 100644 --- a/tests/auto/qstate/tst_qstate.cpp +++ b/tests/auto/qstate/tst_qstate.cpp @@ -260,7 +260,7 @@ protected: return e->type() == m_type; } - void onTransition() {} + void onTransition(QEvent *) {} private: QEvent::Type m_type; @@ -274,7 +274,7 @@ void tst_QState::historyInitialState() QState *s1 = new QState(machine.rootState()); QState *s2 = new QState(machine.rootState()); - QHistoryState *h1 = s2->addHistoryState(); + QHistoryState *h1 = new QHistoryState(s2); s2->setInitialState(h1); -- cgit v0.12 From 7bfe66e825e98b049dfdb0b6008e3f334909eec7 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 7 May 2009 10:20:25 +0200 Subject: Make sure machine enters error state if history state has no default state Keep searching the parent hierarchy for error states even if a state in the hierarchy cannot be cast to QState. Also make currentErrorState==0 an assert, since there should always be an error state (we default to the special initialErrorState if we are unable to find anything else), otherwise the machine might get into an undefined state (e.g. configuration is empty) --- src/corelib/statemachine/qstatemachine.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 7d6616a..41d4c6c 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -582,6 +582,7 @@ void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root, QList hlst; if (QHistoryStatePrivate::get(h)->defaultState) hlst.append(QHistoryStatePrivate::get(h)->defaultState); + if (hlst.isEmpty()) { setError(QStateMachine::NoDefaultStateInHistoryState, h); } else { @@ -946,15 +947,15 @@ QAbstractState *QStateMachinePrivate::findErrorState(QAbstractState *context) // Find error state recursively in parent hierarchy if not set explicitly for context state QAbstractState *errorState = 0; + QState *s = qobject_cast(context); - if (s) { + if (s) errorState = s->errorState(); - if (!errorState) - errorState = findErrorState(s->parentState()); - return errorState; - } - return errorState; + if (!errorState) + errorState = findErrorState(context->parentState()); + + return errorState; } void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractState *currentContext) @@ -990,10 +991,9 @@ void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractSta currentErrorState = initialErrorStateForRoot; } - if (currentErrorState) { - QState *lca = findLCA(QList() << currentErrorState << currentContext); - addStatesToEnter(currentErrorState, lca, pendingErrorStates, pendingErrorStatesForDefaultEntry); - } + Q_ASSERT(currentErrorState != 0); + QState *lca = findLCA(QList() << currentErrorState << currentContext); + addStatesToEnter(currentErrorState, lca, pendingErrorStates, pendingErrorStatesForDefaultEntry); } #ifndef QT_NO_ANIMATION -- cgit v0.12 From 74cdd7c31e91e15d5941ece11a6bdf1c4e1b2309 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 7 May 2009 10:24:00 +0200 Subject: Fix tests for history state and entering root state Change expectation for entering the root state. We should never have the root state in the configuration. Also fix the expected error message in historyStateHasNowhereToGo since this has changed along with the API. --- tests/auto/qstatemachine/tst_qstatemachine.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 94afe51..8026d6e 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -264,16 +264,14 @@ void tst_QStateMachine::transitionToRootState() machine.start(); QCoreApplication::processEvents(); - QCOMPARE(machine.configuration().count(), 2); + QCOMPARE(machine.configuration().count(), 1); QVERIFY(machine.configuration().contains(initialState)); - QVERIFY(machine.configuration().contains(machine.rootState())); machine.postEvent(new QEvent(QEvent::User)); QCoreApplication::processEvents(); - QCOMPARE(machine.configuration().count(), 2); + QCOMPARE(machine.configuration().count(), 1); QVERIFY(machine.configuration().contains(initialState)); - QVERIFY(machine.configuration().contains(machine.rootState())); } void tst_QStateMachine::transitionEntersParent() @@ -880,7 +878,7 @@ void tst_QStateMachine::historyStateHasNowhereToGo() QCOMPARE(machine.configuration().count(), 1); QVERIFY(machine.configuration().contains(machine.errorState())); QCOMPARE(machine.error(), QStateMachine::NoDefaultStateInHistoryState); - QCOMPARE(machine.errorString(), QString::fromLatin1("Missing transition from history state 'historyState'")); + QCOMPARE(machine.errorString(), QString::fromLatin1("Missing default state in history state 'historyState'")); } void tst_QStateMachine::brokenStateIsNeverEntered() -- cgit v0.12 From 0db46b7a592017a4ec541ce703b787458eeb8287 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Thu, 7 May 2009 11:25:35 +0200 Subject: Provide a way in private API to have a consistent timer for animations. This allows for better testing because from now on we can rely on the results to be always the same and not rely on timer accuracy any more. Task-number: 251764 Reviewed-by: leo --- src/corelib/animation/qabstractanimation.cpp | 16 +++++++++++++--- src/corelib/animation/qabstractanimation_p.h | 3 +++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index 440a37d..93ecc73 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -162,7 +162,7 @@ QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC(QThreadStorage, unifiedTimer); -QUnifiedTimer::QUnifiedTimer() : QObject(), lastTick(0) +QUnifiedTimer::QUnifiedTimer() : QObject(), lastTick(0), consistentTimingInterval(0) { } @@ -189,12 +189,22 @@ void QUnifiedTimer::updateRecentlyStartedAnimations() animationsToStart.clear(); } +/* + this allows to haeve a consistent timer interval at each tick from the timer + not taking the real time that passed into account. + Just set this to 0 if you want to get back to a time-driven behaviour. + */ +void QUnifiedTimer::setConsitentTiming(int interval) +{ + consistentTimingInterval = interval; +} + void QUnifiedTimer::timerEvent(QTimerEvent *event) { //this is simply the time we last received a tick - int oldLastTick = lastTick; + const int oldLastTick = lastTick; if (time.isValid()) - lastTick = time.elapsed(); + lastTick = consistentTimingInterval > 0 ? oldLastTick + consistentTimingInterval : time.elapsed(); //we transfer the waiting animations into the "really running" state updateRecentlyStartedAnimations(); diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h index 666e6a7..0e10b9a 100644 --- a/src/corelib/animation/qabstractanimation_p.h +++ b/src/corelib/animation/qabstractanimation_p.h @@ -123,6 +123,8 @@ public: void registerAnimation(QAbstractAnimation *animation); void unregisterAnimation(QAbstractAnimation *animation); + void setConsitentTiming(int interval); + private: void updateRecentlyStartedAnimations(); @@ -130,6 +132,7 @@ private: QBasicTimer animationTimer, startStopAnimationTimer; QTime time; int lastTick; + int consistentTimingInterval; QList animations, animationsToStart; }; -- cgit v0.12 From 576dca0086b1566eafe9a24cf5946f46f4e857bf Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 7 May 2009 11:40:40 +0200 Subject: Fix infinite loop when source and target of transition are in different trees The SCXML algorithm depends on the guarantee that there is always an LCA regardless of the state list. The case where the targets are in a different tree than the source (e.g. if you have not given the target state a parent) is a bug. The fix is to set an error when this happens in exitStates() and exit states as if the pending error states were the target states. In enterStates we will detect the error and skip the step of selecting states to enter, and instead just enter the pending error states. This breaks transitions to and from the root state, which is not supported by the SCXML algorithm. --- src/corelib/statemachine/qstatemachine.cpp | 48 ++++++++++++++++++-------- src/corelib/statemachine/qstatemachine.h | 1 + tests/auto/qstatemachine/tst_qstatemachine.cpp | 5 ++- 3 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 41d4c6c..efcf707 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -409,6 +409,15 @@ QList QStateMachinePrivate::exitStates(QEvent *event, const QLi continue; lst.prepend(t->sourceState()); QAbstractState *lca = findLCA(lst); + if (lca == 0) { + setError(QStateMachine::NoCommonAncestorForTransitionError, t->sourceState()); + lst = pendingErrorStates.toList(); + lst.prepend(t->sourceState()); + + lca = findLCA(lst); + Q_ASSERT(lca != 0); + } + { QSet::const_iterator it; for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) { @@ -476,21 +485,23 @@ QList QStateMachinePrivate::enterStates(QEvent *event, const QL QSet statesToEnter; QSet statesForDefaultEntry; - for (int i = 0; i < enabledTransitions.size(); ++i) { - QAbstractTransition *t = enabledTransitions.at(i); - QList lst = t->targetStates(); - if (lst.isEmpty()) - continue; - lst.prepend(t->sourceState()); - QState *lca = findLCA(lst); - for (int j = 1; j < lst.size(); ++j) { - QAbstractState *s = lst.at(j); - addStatesToEnter(s, lca, statesToEnter, statesForDefaultEntry); - if (isParallel(lca)) { - QList lcac = QStatePrivate::get(lca)->childStates(); - foreach (QAbstractState* child,lcac) { - if (!statesToEnter.contains(child)) - addStatesToEnter(child,lca,statesToEnter,statesForDefaultEntry); + if (pendingErrorStates.isEmpty()) { + for (int i = 0; i < enabledTransitions.size(); ++i) { + QAbstractTransition *t = enabledTransitions.at(i); + QList lst = t->targetStates(); + if (lst.isEmpty()) + continue; + lst.prepend(t->sourceState()); + QState *lca = findLCA(lst); + for (int j = 1; j < lst.size(); ++j) { + QAbstractState *s = lst.at(j); + addStatesToEnter(s, lca, statesToEnter, statesForDefaultEntry); + if (isParallel(lca)) { + QList lcac = QStatePrivate::get(lca)->childStates(); + foreach (QAbstractState* child,lcac) { + if (!statesToEnter.contains(child)) + addStatesToEnter(child,lca,statesToEnter,statesForDefaultEntry); + } } } } @@ -976,6 +987,13 @@ void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractSta errorString = QStateMachine::tr("Missing default state in history state '%1'") .arg(currentContext->objectName()); break; + + case QStateMachine::NoCommonAncestorForTransitionError: + Q_ASSERT(currentContext != 0); + + errorString = QStateMachine::tr("No common ancestor for targets and source of transition from state '%1'") + .arg(currentContext->objectName()); + break; default: errorString = QStateMachine::tr("Unknown error"); }; diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h index 10bd443..d0927a3 100644 --- a/src/corelib/statemachine/qstatemachine.h +++ b/src/corelib/statemachine/qstatemachine.h @@ -87,6 +87,7 @@ public: NoError, NoInitialStateError, NoDefaultStateInHistoryState, + NoCommonAncestorForTransitionError }; QStateMachine(QObject *parent = 0); diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 8026d6e..e7ea403 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -919,8 +919,6 @@ void tst_QStateMachine::brokenStateIsNeverEntered() void tst_QStateMachine::transitionToStateNotInGraph() { - QSKIP("Hangs", SkipAll); - s_countWarnings = false; QStateMachine machine; @@ -930,13 +928,14 @@ void tst_QStateMachine::transitionToStateNotInGraph() machine.setInitialState(initialState); QState *independentState = new QState(); + independentState->setObjectName("independentState"); initialState->addTransition(independentState); machine.start(); QCoreApplication::processEvents(); QCOMPARE(machine.configuration().count(), 1); - QVERIFY(machine.configuration().contains(initialState)); + QVERIFY(machine.configuration().contains(qobject_cast(machine.rootState())->errorState())); } void tst_QStateMachine::customErrorStateNotInGraph() -- cgit v0.12 From a99a849dffc51a76256e880a81e6829c76199559 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Thu, 7 May 2009 11:41:34 +0200 Subject: Addeed a warning if one is trying to animate a property that's not part of the object Task-number: 251763 --- src/corelib/animation/qpropertyanimation.cpp | 2 ++ tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/corelib/animation/qpropertyanimation.cpp b/src/corelib/animation/qpropertyanimation.cpp index 9a0c5bc..65e2f57 100644 --- a/src/corelib/animation/qpropertyanimation.cpp +++ b/src/corelib/animation/qpropertyanimation.cpp @@ -97,6 +97,8 @@ void QPropertyAnimationPrivate::updateMetaProperty() property = mo->property(propertyIndex); propertyType = property.userType(); } else { + if (!target->dynamicPropertyNames().contains(propertyName)) + qWarning("QPropertyAnimation: you're trying to animate a non-existing property %s of your QObject", propertyName.constData()); hasMetaProperty = 2; } } diff --git a/tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp b/tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp index f0deab5..2e5fd00 100644 --- a/tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp +++ b/tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp @@ -624,6 +624,7 @@ QVariant xaxisQPointInterpolator(const QPointF &f, const QPointF &t, qreal progr void tst_QPropertyAnimation::interpolated() { QObject o; + o.setProperty("point", QPointF()); //this will avoid warnings o.setProperty("number", qVariantFromValue(Number(42))); QCOMPARE(qVariantValue(o.property("number")), Number(42)); { @@ -649,9 +650,9 @@ void tst_QPropertyAnimation::interpolated() anim.start(); anim.pause(); anim.setCurrentTime(100); - QCOMPARE(o.property("point").toPointF(), QPointF(10, 0)); + QCOMPARE(o.property("point"), QVariant(QPointF(10, 0))); anim.setCurrentTime(500); - QCOMPARE(o.property("point").toPointF(), QPointF(50, 0)); + QCOMPARE(o.property("point"), QVariant(QPointF(50, 0))); } { // unregister it and see if we get back the default behaviour -- cgit v0.12 From 56d27b54e2fe64782250e8e39012f345588cfad5 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 7 May 2009 11:45:19 +0200 Subject: Rename NoDefaultStateInHistoryState -> NoDefaultStateInHistoryStateError for consistency The other error values have Error in the name for namespacing purposes. --- src/corelib/statemachine/qstatemachine.cpp | 8 ++++---- src/corelib/statemachine/qstatemachine.h | 2 +- tests/auto/qstatemachine/tst_qstatemachine.cpp | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index efcf707..dcdf5ed 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -595,7 +595,7 @@ void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root, hlst.append(QHistoryStatePrivate::get(h)->defaultState); if (hlst.isEmpty()) { - setError(QStateMachine::NoDefaultStateInHistoryState, h); + setError(QStateMachine::NoDefaultStateInHistoryStateError, h); } else { for (int k = 0; k < hlst.size(); ++k) { QAbstractState *s0 = hlst.at(k); @@ -981,7 +981,7 @@ void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractSta .arg(currentContext->objectName()); break; - case QStateMachine::NoDefaultStateInHistoryState: + case QStateMachine::NoDefaultStateInHistoryStateError: Q_ASSERT(currentContext != 0); errorString = QStateMachine::tr("Missing default state in history state '%1'") @@ -1568,9 +1568,9 @@ void QStateMachine::setErrorState(QAbstractState *state) \value NoInitialStateError The machine has entered a QState with children which does not have an initial state set. The context of this error is the state which is missing an initial state. - \value NoDefaultStateInHistoryState The machine has entered a QHistoryState which does not have + \value NoDefaultStateInHistoryStateError The machine has entered a QHistoryState which does not have a default state set. The context of this error is the QHistoryState which is missing a - default state. + default state. \sa setErrorState() */ diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h index d0927a3..d73404a 100644 --- a/src/corelib/statemachine/qstatemachine.h +++ b/src/corelib/statemachine/qstatemachine.h @@ -86,7 +86,7 @@ public: enum Error { NoError, NoInitialStateError, - NoDefaultStateInHistoryState, + NoDefaultStateInHistoryStateError, NoCommonAncestorForTransitionError }; diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index e7ea403..3876a20 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -877,7 +877,7 @@ void tst_QStateMachine::historyStateHasNowhereToGo() QCOMPARE(machine.configuration().count(), 1); QVERIFY(machine.configuration().contains(machine.errorState())); - QCOMPARE(machine.error(), QStateMachine::NoDefaultStateInHistoryState); + QCOMPARE(machine.error(), QStateMachine::NoDefaultStateInHistoryStateError); QCOMPARE(machine.errorString(), QString::fromLatin1("Missing default state in history state 'historyState'")); } -- cgit v0.12 From 2edb7ce649bba7221f02aeae021645e219e25f70 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Thu, 7 May 2009 11:51:16 +0200 Subject: doc: Add documentation for NoCommonAncestorForTransitionError enum --- src/corelib/statemachine/qstatemachine.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index dcdf5ed..7f2132d 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -1571,6 +1571,11 @@ void QStateMachine::setErrorState(QAbstractState *state) \value NoDefaultStateInHistoryStateError The machine has entered a QHistoryState which does not have a default state set. The context of this error is the QHistoryState which is missing a default state. + \value NoCommonAncestorForTransitionError The machine has selected a transition whose source + and targets are not part of the same tree of states, and thus are not part of the same + state machine. Commonly, this could mean that one of the states has not been given + any parent or added to any machine. The context of this error is the source state of + the transition. \sa setErrorState() */ -- cgit v0.12 From 1e404bcb6df5127a1d0e24ed11cce1c0260a57e9 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Thu, 7 May 2009 09:17:37 +0200 Subject: store top-level animation in dedicated variable The animation itself is used by subsequent code, so we mustn't change it. --- src/corelib/statemachine/qstatemachine.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 7f2132d..4533115 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -713,9 +713,10 @@ void QStateMachinePrivate::applyProperties(const QList &tr // Stop the (top-level) animation. // ### Stopping nested animation has weird behavior. - while (QAnimationGroup *group = anim->group()) - anim = group; - anim->stop(); + QAbstractAnimation *topLevelAnim = anim; + while (QAnimationGroup *group = topLevelAnim->group()) + topLevelAnim = group; + topLevelAnim->stop(); if (resetAnimationEndValues.contains(anim)) { qobject_cast(anim)->setEndValue(QVariant()); // ### generalize -- cgit v0.12 From 81eebfbe01edb002d55c3504cc2558689cf0f936 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Thu, 7 May 2009 12:40:38 +0200 Subject: add QStateMachine::isRunning() --- src/corelib/statemachine/qstatemachine.cpp | 11 +++++++ src/corelib/statemachine/qstatemachine.h | 2 ++ tests/auto/qstatemachine/tst_qstatemachine.cpp | 42 ++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 4533115..21e564c 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -1728,6 +1728,17 @@ void QStateMachine::removeState(QAbstractState *state) } /*! + Returns whether this state machine is running. + + start(), stop() +*/ +bool QStateMachine::isRunning() const +{ + Q_D(const QStateMachine); + return (d->state == QStateMachinePrivate::Running); +} + +/*! Starts this state machine. The machine will reset its configuration and transition to the initial state. When a final top-level state (QFinalState) is entered, the machine will emit the finished() signal. diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h index d73404a..5dc6c0b 100644 --- a/src/corelib/statemachine/qstatemachine.h +++ b/src/corelib/statemachine/qstatemachine.h @@ -108,6 +108,8 @@ public: QString errorString() const; void clearError(); + bool isRunning() const; + #ifndef QT_NO_ANIMATION bool animationsEnabled() const; void setAnimationsEnabled(bool enabled); diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 3876a20..edd6459 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -104,6 +104,7 @@ private slots: void signalTransitions(); void eventTransitions(); void historyStates(); + void startAndStop(); void transitionToRootState(); void transitionEntersParent(); @@ -1094,14 +1095,17 @@ void tst_QStateMachine::stateEntryAndExit() s2->addTransition(s3); QSignalSpy startedSpy(&machine, SIGNAL(started())); + QSignalSpy stoppedSpy(&machine, SIGNAL(stopped())); QSignalSpy finishedSpy(&machine, SIGNAL(finished())); machine.setInitialState(s1); QVERIFY(machine.configuration().isEmpty()); globalTick = 0; + QVERIFY(!machine.isRunning()); machine.start(); QTRY_COMPARE(startedSpy.count(), 1); QTRY_COMPARE(finishedSpy.count(), 1); + QTRY_COMPARE(stoppedSpy.count(), 0); QCOMPARE(machine.configuration().count(), 1); QVERIFY(machine.configuration().contains(s3)); @@ -1826,6 +1830,44 @@ void tst_QStateMachine::historyStates() QTRY_COMPARE(finishedSpy.count(), 1); } +void tst_QStateMachine::startAndStop() +{ + QStateMachine machine; + QSignalSpy startedSpy(&machine, SIGNAL(started())); + QSignalSpy stoppedSpy(&machine, SIGNAL(stopped())); + QSignalSpy finishedSpy(&machine, SIGNAL(finished())); + QVERIFY(!machine.isRunning()); + QTest::ignoreMessage(QtWarningMsg, "QStateMachine::start: No initial state set for machine. Refusing to start."); + machine.start(); + QCOMPARE(startedSpy.count(), 0); + QCOMPARE(stoppedSpy.count(), 0); + QCOMPARE(finishedSpy.count(), 0); + QVERIFY(!machine.isRunning()); + machine.stop(); + QCOMPARE(startedSpy.count(), 0); + QCOMPARE(stoppedSpy.count(), 0); + QCOMPARE(finishedSpy.count(), 0); + + QState *s1 = new QState(machine.rootState()); + machine.setInitialState(s1); + machine.start(); + QTRY_COMPARE(machine.isRunning(), true); + QTRY_COMPARE(startedSpy.count(), 1); + QCOMPARE(stoppedSpy.count(), 0); + QCOMPARE(finishedSpy.count(), 0); + QCOMPARE(machine.configuration().count(), 1); + QVERIFY(machine.configuration().contains(s1)); + + machine.stop(); + QTRY_COMPARE(machine.isRunning(), false); + QTRY_COMPARE(stoppedSpy.count(), 1); + QCOMPARE(startedSpy.count(), 1); + QCOMPARE(finishedSpy.count(), 0); + + QCOMPARE(machine.configuration().count(), 1); + QVERIFY(machine.configuration().contains(s1)); +} + void tst_QStateMachine::defaultGlobalRestorePolicy() { QStateMachine machine; -- cgit v0.12 From 8b57ae82ef507db1912a35fbe5d60f2cc3668cdb Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Thu, 7 May 2009 14:44:22 +0200 Subject: change the API of private class for QAbstractAnimation to allow setting the timer interval. We also export the private clas so it can be used by other modules --- src/corelib/animation/qabstractanimation.cpp | 34 ++++++++++++++++++++-------- src/corelib/animation/qabstractanimation_p.h | 15 ++++++++---- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index 93ecc73..6a824b6 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -156,13 +156,13 @@ #include #include -#define TIMER_INTERVAL 16 +#define DEFAULT_TIMER_INTERVAL 16 QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC(QThreadStorage, unifiedTimer); -QUnifiedTimer::QUnifiedTimer() : QObject(), lastTick(0), consistentTimingInterval(0) +QUnifiedTimer::QUnifiedTimer() : QObject(), lastTick(0), timingInterval(DEFAULT_TIMER_INTERVAL), consistentTiming(false) { } @@ -190,13 +190,29 @@ void QUnifiedTimer::updateRecentlyStartedAnimations() } /* - this allows to haeve a consistent timer interval at each tick from the timer + defines the timing interval. Default is DEFAULT_TIMER_INTERVAL +*/ +void QUnifiedTimer::setTimingInterval(int interval) +{ + timingInterval = interval; + if (animationTimer.isActive()) { + //we changed the timing interval + animationTimer.start(timingInterval, this); + } +} + +/* + this allows to have a consistent timer interval at each tick from the timer not taking the real time that passed into account. - Just set this to 0 if you want to get back to a time-driven behaviour. - */ -void QUnifiedTimer::setConsitentTiming(int interval) +*/ +void QUnifiedTimer::setConsitentTiming(bool b) +{ + consistentTiming = b; +} + +int QUnifiedTimer::elapsedTime() const { - consistentTimingInterval = interval; + return lastTick; } void QUnifiedTimer::timerEvent(QTimerEvent *event) @@ -204,7 +220,7 @@ void QUnifiedTimer::timerEvent(QTimerEvent *event) //this is simply the time we last received a tick const int oldLastTick = lastTick; if (time.isValid()) - lastTick = consistentTimingInterval > 0 ? oldLastTick + consistentTimingInterval : time.elapsed(); + lastTick = consistentTiming ? oldLastTick + timingInterval : time.elapsed(); //we transfer the waiting animations into the "really running" state updateRecentlyStartedAnimations(); @@ -215,7 +231,7 @@ void QUnifiedTimer::timerEvent(QTimerEvent *event) animationTimer.stop(); time = QTime(); } else { - animationTimer.start(TIMER_INTERVAL, this); + animationTimer.start(timingInterval, this); lastTick = 0; time.start(); } diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h index 0e10b9a..49c0195 100644 --- a/src/corelib/animation/qabstractanimation_p.h +++ b/src/corelib/animation/qabstractanimation_p.h @@ -110,7 +110,7 @@ private: }; -class QUnifiedTimer : public QObject +class Q_CORE_EXPORT QUnifiedTimer : public QObject { private: QUnifiedTimer(); @@ -118,13 +118,17 @@ private: public: static QUnifiedTimer *instance(); - void timerEvent(QTimerEvent *); - void updateTimer(); void registerAnimation(QAbstractAnimation *animation); void unregisterAnimation(QAbstractAnimation *animation); - void setConsitentTiming(int interval); + void setTimingInterval(int interval); + void setConsitentTiming(bool consistent); + + int elapsedTime() const; +protected: + void timerEvent(QTimerEvent *); + void updateTimer(); private: void updateRecentlyStartedAnimations(); @@ -132,7 +136,8 @@ private: QBasicTimer animationTimer, startStopAnimationTimer; QTime time; int lastTick; - int consistentTimingInterval; + int timingInterval; + bool consistentTiming; QList animations, animationsToStart; }; -- cgit v0.12 From 2a410483a29c0e821588fd94c3179f7ab775ebbf Mon Sep 17 00:00:00 2001 From: Geir Vattekar Date: Thu, 7 May 2009 15:56:12 +0200 Subject: Doc: Work on QPropertyAnimation class description --- src/corelib/animation/qpropertyanimation.cpp | 57 +++++++++++++++++++--------- 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/src/corelib/animation/qpropertyanimation.cpp b/src/corelib/animation/qpropertyanimation.cpp index 9a0c5bc..8abdacc 100644 --- a/src/corelib/animation/qpropertyanimation.cpp +++ b/src/corelib/animation/qpropertyanimation.cpp @@ -41,27 +41,48 @@ /*! \class QPropertyAnimation - \brief The QPropertyAnimation class animates properties for QObject(and QWidget) + \brief The QPropertyAnimation class animates Qt properties \ingroup animation \preliminary - This class is part of {The Animation Framework}. You can use QPropertyAnimation - by itself as a simple animation class, or as part of more complex - animations through QAnimationGroup. - - The most common way to use QPropertyAnimation is to construct an instance - of it by passing a pointer to a QObject or a QWidget, and the name of the - property you would like to animate to QPropertyAnimation's constructor. - - The start value of the animation is optional. If you do not set any start - value, the animation will operate on the target's current property value - at the point when the animation was started. You can call setStartValue() - to set the start value, and setEndValue() to set the target value for - the animated property. - - Animations can operate on QObjects and QWidgets. You can choose to assign a - target object by either calling setTargetObject() or by passing a QObject - pointer to QPropertyAnimation's constructor. + QPropertyAnimation interpolates over \l{Qt's Property System}{Qt + properties}. As property values are stored in \l{QVariant}s, the + class inherits QVariantAnimation, and supports animation of the + same \l{QVariant::Type}{variant types} as its super class. + + A class declaring properties must be a QObject. To make it + possible to animate a property, it must provide a setter (so that + QPropertyAnimation can set the property's value). Note that this + makes it possible to animate many of Qt's widgets. Let's look at + an example: + + \code + QPropertyAnimation animation(myWidget, "geometry"); + animation.setDuration(10000); + animation.setStartValue(QRect(0, 0, 100, 30)); + animation.setEndValue(QRect(250, 250, 100, 30)); + + animation.start(); + \endcode + + The property name and the QObject instance of which property + should be animated are passed to the constructor. You can then + specify the start and end value of the property. The procedure is + equal for properties in classes you have implemented + yourself--just check with QVariantAnimation that your QVariant + type is supported. + + The QVariantAnimation class description explains how to set up the + animation in detail. Note, however, that if a start value is not + set, the property will start at the value it had when the + QPropertyAnimation instance was created. + + QPropertyAnimation works like a charm on its own. For complex + animations that, for instance, contain several objects, + QAnimationGroup is provided. An animation group is an animation + that can contain other animations, and that can manage when its + animations are played. Look at QParallelAnimationGroup for an + example. \sa QVariantAnimation, QAnimationGroup, {The Animation Framework} */ -- cgit v0.12