Home

Using SCXML files in Qt

The sctools module allows loading SCXML files into a QtScriptedStateMachine object.

The files that the tool can load conform to the State Chart XML (SCXML) standard.

Getting Started with Qt & SCXML

Enabling the QtScriptedStateMachine class

The QtScriptedStateMachine class is enabled automatically when the script module is enabled.

Using the QtScriptedStateMachine class

QtScriptedStateMachine is a subclass of QtStateMachine. QtStateMachine actually includes most of the "interesting" API, while QtScriptedStateMachine adds the missing parts to support SCXML.

Most of the interaction with QtScriptedStateMachine occurs after the state-machine is loaded, and before it's started. The interesting functionalities of QtScriptedStateMachine are:

Working with the script engine

The main feature of QtScriptedStateMachine is that it includes a single QScriptEngine object that's shared between all state actions and transitions. That's what allows the states to rely on a single data context for evaluating conditions and executing the entry/exit/transition actions.

A very useful function is QtScriptedStateMachine::registerObject(), which allows you to add an object (and optionally all its descendants) to the scripting context. QtScriptedStateMachine::scriptEngine() allows you to manipulate the scripting context directly. Use the mediaplayer example as a reference for using the registerObject function.

Connecting the state-machine to signals/slots

A simpler way to interact with the state machine is through signals and slots. The slot QtScriptedStateMachine::postNamedEvent() and the signal QtScriptedStateMachine::eventTriggered() allow for a simple interaction with the state machine, as you can connect signals to postNamedEvent and eventTriggered to and signal/slot.

There are no entered/exited signals from states, as that would make the state-machines less deterministic and would create results that are difficult to manage and predict (does the signal get emitted before, after or during the normal execution list?)

The calc example shows the usage of QtScriptedStateMachine::postNamedEvent().

Extending the state-machine with custom invokers

A custom invoker allows you to write your own invoke tags, and implement specific invoke types, as described in the SCXML standard.

To create a custom invoker, you must subclass from QtSsmInvoker, and implement at least:

When these terms are met, you can create an invoke-factory, and register it to the state machine. Example:

     #include <QtScriptedStateMachine>

     class MyInvoker : public QtSsmInvoker
     {
         Q_OBJECT
         public:
             MyInvoker(QtScriptedEvent* ievent, QtScriptedStateMachine* p) : QtSsmInvoker(ievent,p),menu(0)
             {
             }
             static void initInvokerFactory(QtScriptedStateMachine* machine)
             {
                 machine->scriptEngine()->globalObject().setProperty("some-name",someValue);
             }
             static bool isTypeSupported (const QString & s) { return s== "my-type"; }
         public Q_SLOTS:
             void activate ()
             {
                 doSomeStuff ();
             }
     };
 ...
     static QSsmAutoInvokerFactory<MyInvoker> _s_factory;
     myScriptedStateMachine->registerInvoker(&_s_factory);

The initEvent protected member can be used to access the parameters given to the invoker by the calling state machine. QtSsmInvoker::postParentEvent() allows sending events back to the calling state machine.

Loading SCXML files at runtime

To load SCXML files in runtime, the static function QtScriptedStateMachine::load() must be used. Note that this function requires the xmlpatterns and xml modules to be enabled. QtScriptedStateMachine::load() it creates a new QtScriptedStateMachine object. An example code would be:

 #include "qscriptedstatemachine.h"

 // some code
 QtScriptedStateMachine* stateMachine = QtScriptedStateMachine::load ("path-to-some-file.scxml");
 // ... register some objects, handle some stuff in the script engine...
 stateMachine->start ();

Supported SCXML tags and features

Though most of the SCXML features are supported in this implementation, the support is incomplete, partially because the spec itself is still evolving. This documentation tries to capture most of the gaps and differences.

Fully supported elements

The tags state, parallel, final, onentry, onexit, raise, if, elseif, else, log, cancel, datamodel,data, assign, param, ands anchor are fully supported according to the scxml spec.

Partially supported elements

Unsupported elements

The elements donedata, finalize and validate are not supported. Also, the local/global script scoping functionality is not implemented.

Extras

Signal transitions

To declare a signal transition, use a transition tag with a q-signal uri scheme. Example:

     <transition target="someState" event="q-signal:someObject.someSignal()" />
Property binding

The q-binding invoker can be used to setup properties on entry, that are restored on exit. Note that if the properties are changed externally while the state is active, the properties would still be restored.

The binding invoke element accepts a content tag with a JSON array, of which each element is a 3-item array: [object, property-name, property-value].

Example:

      <invoke type="q-bindings"><content>
                     [[myObject,"someProperty",someValue1 + someValue2],
                     [myObject,"text","hello"]]
      </content></invoke>
Menus

A custom invoker added to the solution is the "q-menu" invoker. This invoker allows you to display a QMenu and listen to its events. The q-menu invoker should a content tag, which includes an expression evaluating to an ecmascript object defining the menu. Note that support for menus is currently experimental, and the mediaplayer example demonstrates its use.

Message Boxes

Similar to q-menus, the "q-messagebox" invoker lets you show a QMessageBox and react to the user interactions with it.

The q-messagebox invoker accepts an ecmascript object that contains name/value pairs for the QMessageBox properties.

Example:

         <invoke type="q-messagebox">
             <content>
                 {
                   "parent" : myParentWidget,
                   "icon" : QMessageBox.Question,
                   "windowTitle" : "Would you like to exit?",
                   "text" : "Are you sure?",
                   "standardButtons" : QMessageBox.Yes|QMessageBox.No
                 }
             </content>
         </invoke>

See the blackjack example for reference.


Copyright © 2009 Nokia Trademarks
Qt Solutions