Home |
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.
The QtScriptedStateMachine class is enabled automatically when the script module is enabled.
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:
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.
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().
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.
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 ();
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.
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.
The elements donedata, finalize and validate are not supported. Also, the local/global script scoping functionality is not implemented.
To declare a signal transition, use a transition tag with a q-signal uri scheme. Example:
<transition target="someState" event="q-signal:someObject.someSignal()" />
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>
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.
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 |