[Qt-interest] QT SM framework: Ignoring inherited transition w/o causing state transition

Sean Harmer sean.harmer at maps-technology.com
Fri Mar 26 14:45:08 CET 2010


Hi Mandeep,

On Friday 26 March 2010 13:18:29 Mandeep Sandhu wrote:
> Hi all,
> 
> I was going through the Qt docs on how to make a child state ignore an
> event which is valid for its parent state
> (http://doc.qt.nokia.com/4.6/statemachine-api.html#sharing-transitions-by-g
> rouping-states).
> 
> The way it's shown is that the child state which wants to ignore the
> event, catches it and simply transitions to itself. This works fine,
> but with a side-effect. It causes the SM to leave the state and enter
> back in. Since I'm using custom states, I do some processing in the
> onEntry/onExit callbacks, they get called even though logically, no
> transition based processing should happen.
> 
> Is there a way to "stay" in the same state and not move out and come
> back in? Since I really want to remain in the same state.

Yes, I thought we went through this the other day? Simply make the transition 
on the grouping state a guarded transition that checks whether the SM is in 
the state from which you wish to ignore the transition.

Using the example from the docs we could do this as follows:

class MyTransition : public QSignalTransition
{
Q_OBJECT
public:
    MyTransition( const QList<QAbstractState*> blackList, 
                  QAbstractState* sourceState )
    : QSignalTransition( sourceState ), m_blackList( blackList ) {}

    bool eventTest( QEvent* e )
    {
        if ( !QSignalTransition::eventTest( e ) )
            return false;

        QSet<QAbstractState*> configuration = machine()->configuration();
        foreach ( QAbstractState* state, m_blackList )
        {
            if ( configuration.contains( state ) )
                return false;
        }
        return true;
    }

private:
	QList<QAbstractState*> m_blackList;
};

Then in the main function instead of calling:

s1->addTransition(quitButton, SIGNAL(clicked()), s2);


we instead use an instance of the above custom transition:

MyTransition* trans 
    = new MyTransition( ( QList<QAbstractState*>() << s12 ), s1 );
trans->setSenderObject( quitButton );
trans->setSignal( SIGNAL( clicked() ) );
s1->addTransition( trans );

So now, when the quitButton emits the clicked() signal we use the event test 
function of our custom transition which simply iterates through its list of 
blacklisted states from which we should not transition ans returns true/false 
as appropriate.

In this case we return false if the SM is in state s12. And since no 
transition happens your processing code in onEntry()/onExit() will not be 
called as per your requirements.

NB Note that you can provide a black list of any states. They do not 
necessarily have to be children of s1.

Cheers,

Sean



More information about the Qt-interest-old mailing list