diff options
-rw-r--r-- | src/corelib/statemachine/qstatemachine.cpp | 57 | ||||
-rw-r--r-- | src/corelib/statemachine/qstatemachine_p.h | 3 | ||||
-rw-r--r-- | tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp | 39 |
3 files changed, 76 insertions, 23 deletions
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index ccc40ac9b4..5adb6c3fb1 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -518,6 +518,10 @@ QList<QAbstractState*> QStateMachinePrivate::computeStatesToEnter(const QList<QA QAbstractState *s = lst.at(j); addStatesToEnter(s, lca, statesToEnter, statesForDefaultEntry); } + for (int j = src ? 1 : 0; j < lst.size(); ++j) { + QAbstractState *s = lst.at(j); + addAncestorStatesToEnter(s, lca, statesToEnter, statesForDefaultEntry); + } if (isParallel(lca)) { QList<QAbstractState*> lcac = QStatePrivate::get(lca)->childStates(); foreach (QAbstractState* child,lcac) { @@ -715,32 +719,38 @@ void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root, return; } } - QList<QState*> 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<QAbstractState*> lst = QStatePrivate::get(anc)->childStates(); - for (int j = 0; j < lst.size(); ++j) { - QAbstractState *child = lst.at(j); - bool hasDescendantInList = false; - QSet<QAbstractState*>::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::addAncestorStatesToEnter(QAbstractState *s, QState *root, + QSet<QAbstractState*> &statesToEnter, + QSet<QAbstractState*> &statesForDefaultEntry) +{ + QList<QState*> 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<QAbstractState*> lst = QStatePrivate::get(anc)->childStates(); + for (int j = 0; j < lst.size(); ++j) { + QAbstractState *child = lst.at(j); + bool hasDescendantInList = false; + QSet<QAbstractState*>::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); + } + } + } +} + bool QStateMachinePrivate::isFinal(const QAbstractState *s) { return s && (QAbstractStatePrivate::get(s)->stateType == QAbstractStatePrivate::FinalState); @@ -1077,6 +1087,7 @@ void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractSta if (currentErrorState != 0) { QState *lca = findLCA(QList<QAbstractState*>() << currentErrorState << currentContext); addStatesToEnter(currentErrorState, lca, pendingErrorStates, pendingErrorStatesForDefaultEntry); + addAncestorStatesToEnter(currentErrorState, lca, pendingErrorStates, pendingErrorStatesForDefaultEntry); } else { qWarning("Unrecoverable error detected in running state machine: %s", qPrintable(errorString)); diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index 423c077a83..113f17f973 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -150,6 +150,9 @@ public: void addStatesToEnter(QAbstractState *s, QState *root, QSet<QAbstractState*> &statesToEnter, QSet<QAbstractState*> &statesForDefaultEntry); + void addAncestorStatesToEnter(QAbstractState *s, QState *root, + QSet<QAbstractState*> &statesToEnter, + QSet<QAbstractState*> &statesForDefaultEntry); static QState *toStandardState(QAbstractState *state); static const QState *toStandardState(const QAbstractState *state); diff --git a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp index 436b386a28..06d169c0e7 100644 --- a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp @@ -203,6 +203,8 @@ private slots: void changeStateWhileAnimatingProperty(); void propertiesAreAssignedBeforeEntryCallbacks_data(); void propertiesAreAssignedBeforeEntryCallbacks(); + + void multiTargetTransitionInsideParallelStateGroup(); }; class TestState : public QState @@ -246,6 +248,9 @@ public: EventTransition(QEvent::Type type, QAbstractState *target, QState *parent = 0) : QAbstractTransition(parent), m_type(type) { setTargetState(target); } + EventTransition(QEvent::Type type, const QList<QAbstractState *> &targets, QState *parent = 0) + : QAbstractTransition(parent), m_type(type) + { setTargetStates(targets); } protected: virtual bool eventTest(QEvent *e) { return (e->type() == m_type); @@ -4647,5 +4652,39 @@ void tst_QStateMachine::propertiesAreAssignedBeforeEntryCallbacks() QVERIFY(s2->enteredPassed); } +// QTBUG-25958 +void tst_QStateMachine::multiTargetTransitionInsideParallelStateGroup() +{ + QStateMachine machine; + QState *s1 = new QState(&machine); + machine.setInitialState(s1); + + QState *s2 = new QState(QState::ParallelStates, &machine); + + QState *s21 = new QState(s2); + QState *s211 = new QState(s21); + QState *s212 = new QState(s21); + s21->setInitialState(s212); + + QState *s22 = new QState(s2); + QState *s221 = new QState(s22); + QState *s222 = new QState(s22); + s22->setInitialState(s222); + + QAbstractTransition *t1 = new EventTransition(QEvent::User, QList<QAbstractState *>() << s211 << s221); + s1->addTransition(t1); + + machine.start(); + QTRY_VERIFY(machine.configuration().contains(s1)); + + machine.postEvent(new QEvent(QEvent::User)); + QTRY_VERIFY(machine.configuration().contains(s2)); + QCOMPARE(machine.configuration().size(), 5); + QVERIFY(machine.configuration().contains(s21)); + QVERIFY(machine.configuration().contains(s211)); + QVERIFY(machine.configuration().contains(s22)); + QVERIFY(machine.configuration().contains(s221)); +} + QTEST_MAIN(tst_QStateMachine) #include "tst_qstatemachine.moc" |