summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp57
-rw-r--r--src/corelib/statemachine/qstatemachine_p.h3
-rw-r--r--tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp39
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"