summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/statemachine/qabstracttransition.cpp46
-rw-r--r--src/corelib/statemachine/qabstracttransition.h10
-rw-r--r--src/corelib/statemachine/qabstracttransition_p.h1
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp25
-rw-r--r--tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp44
5 files changed, 113 insertions, 13 deletions
diff --git a/src/corelib/statemachine/qabstracttransition.cpp b/src/corelib/statemachine/qabstracttransition.cpp
index f128acd54e..81b38ea4c4 100644
--- a/src/corelib/statemachine/qabstracttransition.cpp
+++ b/src/corelib/statemachine/qabstracttransition.cpp
@@ -101,7 +101,35 @@ QT_BEGIN_NAMESPACE
parallel group state.
*/
+/*!
+ \property QAbstractTransition::transitionType
+
+ \brief indicates whether this transition is an internal transition, or an external transition.
+
+ Internal and external transitions behave the same, except for the case of a transition whose
+ source state is a compound state and whose target(s) is a descendant of the source. In such a
+ case, an internal transition will not exit and re-enter its source state, while an external one
+ will.
+
+ By default, the type is an external transition.
+*/
+
+/*!
+ \enum QAbstractTransition::TransitionType
+
+ This enum specifies the kind of transition. By default, the type is an external transition.
+
+ \value ExternalTransition Any state that is the source state of a transition (which is not a
+ target-less transition) is left, and re-entered when necessary.
+ \value InternalTransition If the target state of a transition is a sub-state of a compound state,
+ and that compound state is the source state, an internal transition will
+ not leave the source state.
+
+ \sa QAbstractTransition::transitionType
+*/
+
QAbstractTransitionPrivate::QAbstractTransitionPrivate()
+ : transitionType(QAbstractTransition::ExternalTransition)
{
}
@@ -249,6 +277,24 @@ void QAbstractTransition::setTargetStates(const QList<QAbstractState*> &targets)
}
/*!
+ Returns the type of the transition.
+*/
+QAbstractTransition::TransitionType QAbstractTransition::transitionType() const
+{
+ Q_D(const QAbstractTransition);
+ return d->transitionType;
+}
+
+/*!
+ Sets the type of the transition to \a type.
+*/
+void QAbstractTransition::setTransitionType(TransitionType type)
+{
+ Q_D(QAbstractTransition);
+ d->transitionType = type;
+}
+
+/*!
Returns the state machine that this transition is part of, or 0 if the
transition is not part of a state machine.
*/
diff --git a/src/corelib/statemachine/qabstracttransition.h b/src/corelib/statemachine/qabstracttransition.h
index 768a364a4b..bf32b3e825 100644
--- a/src/corelib/statemachine/qabstracttransition.h
+++ b/src/corelib/statemachine/qabstracttransition.h
@@ -59,7 +59,14 @@ class Q_CORE_EXPORT QAbstractTransition : public QObject
Q_PROPERTY(QState* sourceState READ sourceState)
Q_PROPERTY(QAbstractState* targetState READ targetState WRITE setTargetState NOTIFY targetStateChanged)
Q_PROPERTY(QList<QAbstractState*> targetStates READ targetStates WRITE setTargetStates NOTIFY targetStatesChanged)
+ Q_PROPERTY(TransitionType transitionType READ transitionType WRITE setTransitionType)
public:
+ enum TransitionType {
+ ExternalTransition,
+ InternalTransition
+ };
+ Q_ENUM(TransitionType)
+
QAbstractTransition(QState *sourceState = 0);
virtual ~QAbstractTransition();
@@ -69,6 +76,9 @@ public:
QList<QAbstractState*> targetStates() const;
void setTargetStates(const QList<QAbstractState*> &targets);
+ TransitionType transitionType() const;
+ void setTransitionType(TransitionType type);
+
QStateMachine *machine() const;
#ifndef QT_NO_ANIMATION
diff --git a/src/corelib/statemachine/qabstracttransition_p.h b/src/corelib/statemachine/qabstracttransition_p.h
index d89d057497..4b0644acd9 100644
--- a/src/corelib/statemachine/qabstracttransition_p.h
+++ b/src/corelib/statemachine/qabstracttransition_p.h
@@ -73,6 +73,7 @@ public:
void emitTriggered();
QList<QPointer<QAbstractState> > targetStates;
+ QAbstractTransition::TransitionType transitionType;
#ifndef QT_NO_ANIMATION
QList<QAbstractAnimation*> animations;
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
index d91b4ba14a..6e36f93c40 100644
--- a/src/corelib/statemachine/qstatemachine.cpp
+++ b/src/corelib/statemachine/qstatemachine.cpp
@@ -889,23 +889,22 @@ QAbstractState *QStateMachinePrivate::getTransitionDomain(QAbstractTransition *t
if (cache->transitionDomain(t, &domain))
return domain;
-#if 0
- // Qt only has external transitions, so skip the special case for the internal transitions
- if (QState *tSource = t->sourceState()) {
- if (isCompound(tSource)) {
- bool allDescendants = true;
- foreach (QAbstractState *s, effectiveTargetStates) {
- if (!isDescendant(s, tSource)) {
- allDescendants = false;
- break;
+ if (t->transitionType() == QAbstractTransition::InternalTransition) {
+ if (QState *tSource = t->sourceState()) {
+ if (isCompound(tSource)) {
+ bool allDescendants = true;
+ foreach (QAbstractState *s, effectiveTargetStates) {
+ if (!isDescendant(s, tSource)) {
+ allDescendants = false;
+ break;
+ }
}
- }
- if (allDescendants)
- return tSource;
+ if (allDescendants)
+ return tSource;
+ }
}
}
-#endif
QList<QAbstractState *> states(effectiveTargetStates);
if (QAbstractState *src = t->sourceState())
diff --git a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
index 9fb2e40cb8..6ddfb828e8 100644
--- a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
+++ b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
@@ -247,6 +247,7 @@ private slots:
void qtbug_44963();
void qtbug_44783();
+ void internalTransition();
};
class TestState : public QState
@@ -6338,5 +6339,48 @@ void tst_QStateMachine::qtbug_44783()
QVERIFY(machine.isRunning());
}
+void tst_QStateMachine::internalTransition()
+{
+ SignalEmitter emitter;
+
+ QStateMachine machine;
+ QState *s = new QState(&machine);
+ QState *s1 = new QState(s);
+ QState *s11 = new QState(s1);
+
+ DEFINE_ACTIVE_SPY(s);
+ DEFINE_ACTIVE_SPY(s1);
+ DEFINE_ACTIVE_SPY(s11);
+
+ machine.setInitialState(s);
+ s->setInitialState(s1);
+ s1->setInitialState(s11);
+ QSignalTransition *t = s1->addTransition(&emitter, SIGNAL(signalWithNoArg()), s11);
+ t->setObjectName("s1->s11");
+ t->setTransitionType(QAbstractTransition::InternalTransition);
+
+ s->setObjectName("s");
+ s1->setObjectName("s1");
+ s11->setObjectName("s11");
+
+ machine.start();
+
+ QTRY_COMPARE(machine.configuration().contains(s), true);
+ QTRY_COMPARE(machine.configuration().contains(s1), true);
+ QTRY_COMPARE(machine.configuration().contains(s11), true);
+ TEST_ACTIVE_CHANGED(s, 1);
+ TEST_ACTIVE_CHANGED(s1, 1);
+ TEST_ACTIVE_CHANGED(s11, 1);
+
+ emitter.emitSignalWithNoArg();
+
+ QTRY_COMPARE(machine.configuration().contains(s), true);
+ QTRY_COMPARE(machine.configuration().contains(s1), true);
+ QTRY_COMPARE(machine.configuration().contains(s11), true);
+ TEST_ACTIVE_CHANGED(s11, 3);
+ TEST_ACTIVE_CHANGED(s1, 1); // external transitions will return 3, internal transitions should return 1.
+ TEST_ACTIVE_CHANGED(s, 1);
+}
+
QTEST_MAIN(tst_QStateMachine)
#include "tst_qstatemachine.moc"