statemachine: Support parallel root state
QStateMachine inherits from QState, so it should be possible to set its childMode to ParallelStates, and it should behave as expected (the machine should emit the finished() signal when all its child states are in final states). Task-number: QTBUG-22931 Change-Id: Ic436351be0be69e3b01ae9984561132cd9839fa7 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
This commit is contained in:
parent
28e9a602cb
commit
d281aa6936
@ -639,10 +639,17 @@ void QStateMachinePrivate::enterStates(QEvent *event, const QList<QAbstractState
|
|||||||
{
|
{
|
||||||
QSet<QAbstractState*>::const_iterator it;
|
QSet<QAbstractState*>::const_iterator it;
|
||||||
for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
|
for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
|
||||||
if (isFinal(*it) && (*it)->parentState() == rootState()) {
|
if (isFinal(*it)) {
|
||||||
processing = false;
|
QState *parent = (*it)->parentState();
|
||||||
stopProcessingReason = Finished;
|
if (((parent == rootState())
|
||||||
break;
|
&& (rootState()->childMode() == QState::ExclusiveStates))
|
||||||
|
|| ((parent->parentState() == rootState())
|
||||||
|
&& (rootState()->childMode() == QState::ParallelStates)
|
||||||
|
&& isInFinalState(rootState()))) {
|
||||||
|
processing = false;
|
||||||
|
stopProcessingReason = Finished;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -754,8 +761,7 @@ bool QStateMachinePrivate::isCompound(const QAbstractState *s) const
|
|||||||
// Don't treat the machine as compound if it's a sub-state of this machine
|
// Don't treat the machine as compound if it's a sub-state of this machine
|
||||||
if (isMachine && (group != rootState()))
|
if (isMachine && (group != rootState()))
|
||||||
return false;
|
return false;
|
||||||
return (!isParallel(group) && !QStatePrivate::get(group)->childStates().isEmpty())
|
return (!isParallel(group) && !QStatePrivate::get(group)->childStates().isEmpty());
|
||||||
|| isMachine;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QStateMachinePrivate::isAtomic(const QAbstractState *s) const
|
bool QStateMachinePrivate::isAtomic(const QAbstractState *s) const
|
||||||
@ -1286,16 +1292,26 @@ QAbstractTransition *QStateMachinePrivate::createInitialTransition() const
|
|||||||
class InitialTransition : public QAbstractTransition
|
class InitialTransition : public QAbstractTransition
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
InitialTransition(QAbstractState *target)
|
InitialTransition(const QList<QAbstractState *> &targets)
|
||||||
: QAbstractTransition()
|
: QAbstractTransition()
|
||||||
{ setTargetState(target); }
|
{ setTargetStates(targets); }
|
||||||
protected:
|
protected:
|
||||||
virtual bool eventTest(QEvent *) { return true; }
|
virtual bool eventTest(QEvent *) { return true; }
|
||||||
virtual void onTransition(QEvent *) {}
|
virtual void onTransition(QEvent *) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_ASSERT(rootState() != 0);
|
QState *root = rootState();
|
||||||
return new InitialTransition(rootState()->initialState());
|
Q_ASSERT(root != 0);
|
||||||
|
QList<QAbstractState *> targets;
|
||||||
|
switch (root->childMode()) {
|
||||||
|
case QState::ExclusiveStates:
|
||||||
|
targets.append(root->initialState());
|
||||||
|
break;
|
||||||
|
case QState::ParallelStates:
|
||||||
|
targets = QStatePrivate::get(root)->childStates();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return new InitialTransition(targets);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QStateMachinePrivate::clearHistory()
|
void QStateMachinePrivate::clearHistory()
|
||||||
@ -2039,7 +2055,7 @@ void QStateMachine::start()
|
|||||||
{
|
{
|
||||||
Q_D(QStateMachine);
|
Q_D(QStateMachine);
|
||||||
|
|
||||||
if (initialState() == 0) {
|
if ((childMode() == QState::ExclusiveStates) && (initialState() == 0)) {
|
||||||
qWarning("QStateMachine::start: No initial state set for machine. Refusing to start.");
|
qWarning("QStateMachine::start: No initial state set for machine. Refusing to start.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1912,11 +1912,16 @@ void tst_QStateMachine::parallelRootState()
|
|||||||
|
|
||||||
QSignalSpy startedSpy(&machine, SIGNAL(started()));
|
QSignalSpy startedSpy(&machine, SIGNAL(started()));
|
||||||
QVERIFY(startedSpy.isValid());
|
QVERIFY(startedSpy.isValid());
|
||||||
QTest::ignoreMessage(QtWarningMsg, "QStateMachine::start: No initial state set for machine. Refusing to start.");
|
QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
|
||||||
|
QVERIFY(finishedSpy.isValid());
|
||||||
machine.start();
|
machine.start();
|
||||||
QCoreApplication::processEvents();
|
QTRY_COMPARE(startedSpy.count(), 1);
|
||||||
QEXPECT_FAIL("", "parallel root state is not supported (QTBUG-22931)", Continue);
|
QCOMPARE(machine.configuration().size(), 4);
|
||||||
QCOMPARE(startedSpy.count(), 1);
|
QVERIFY(machine.configuration().contains(s1));
|
||||||
|
QVERIFY(machine.configuration().contains(s1_f));
|
||||||
|
QVERIFY(machine.configuration().contains(s2));
|
||||||
|
QVERIFY(machine.configuration().contains(s2_f));
|
||||||
|
QTRY_COMPARE(finishedSpy.count(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QStateMachine::allSourceToTargetConfigurations()
|
void tst_QStateMachine::allSourceToTargetConfigurations()
|
||||||
|
Loading…
Reference in New Issue
Block a user