PDA

View Full Version : qstatemachine how to do conditional transitions based on concurrent state



daviddrell
7th October 2010, 14:54
in D. Harel's 1987 paper, in figures 19 & 20, he describes a notational method for making state transitions in AND-parallel states where the transition (fig-19: beta(G)) is conditioned on the state of the adjacent sub-state-machine. Is there a best practices recommendation for implementing this same functionality with qstatemachine? There does not seem to be a direct method for this.

thanks

wysota
7th October 2010, 16:45
When referring to an article it would be polite to at least give the title of the article and any means of finding it.

daviddrell
7th October 2010, 19:14
My Apologies. it was bad of me to assume that only those already familiar with the paper ( i.e the authors of QStateMachines) would be responding.

its an old paper so only available in scanned-pdf:

The Qt statemachine (http://doc.qt.nokia.com/4.6/statemachine-api.html) frame work page contains a link to the paper:

http://www.wisdom.weizmann.ac.il/~harel/papers/Statecharts.pdf

Statecharts: A Visual Formalism for Comlex Systems, by David Harel. Science
of computer programming 8, 1987, pp231-274

wysota
7th October 2010, 19:35
it was bad of me to assume that only those already familiar with the paper ( i.e the authors of QStateMachines) would be responding.
If that was the case you would probably be waiting forever :)


he describes a notational method for making state transitions in AND-parallel states where the transition (fig-19: beta(G)) is conditioned on the state of the adjacent sub-state-machine
The problem with Qt's state machines is that it is not possible to directly ask the machine about what state it is in so to obtain information whether the sub-machine is in state "G" you need to cheat a bit by asking the machine to toggle an external flag that states whether it is in G state or not. Use a boolean property of some object and make the G state set this property to true and all other states to set it to false. Alternatively use QState::onExit() and QState::onEntry() of the G state to manipulate some external variable in a similar manner. Then you will be able to make some other transition active based on the value of this variable - either by reimplementing QAbstractTransition::eventTest() for the transition to check the variable or by using some higher-level transition class.

To generalise -- you can use QAbstractTransition::eventTest() to implement any transition condition you want. The only problem is to provide an infrastructure for it. In your case you can do something like this:


class InStateTransition : public QSignalTransition {
Q_OBJECT
Q_PROPERTY(bool canTrigger READ canTrigger WRITE setCanTrigger)
public:
InStateTransition(QState * sourceState = 0) : QSignalTransition(sourceState) {
m_canTrigger = false;
}
void setCanTrigger(bool v) { m_canTrigger = v; }
bool canTrigger() const { return m_canTrigger; }
protected:
bool eventTest(QEvent *e) {
if(!QSignalTransition::eventTest(e))
return false;
return canTrigger();
}
private:
bool m_canTrigger;
};

Then you can use i.e.:

stateG->assignProperty(someInStateTransition, "canTrigger", true);
stateOtherThanG->assignProperty(someInStateTransition, "canTrigger", false);

And the transition will only fire when stateG is active.

daviddrell
7th October 2010, 20:10
thank you for the excellent and complete response. I was afraid that would be the answer. But you built it for me so its not so bad.

wysota
7th October 2010, 20:47
I didn't test it, it might not even compile :) But it's something to get you started.