summaryrefslogtreecommitdiffstats
path: root/doc/scxml.qdoc
blob: d0211baeae29232e6f83d22a21b6a04a46dfd45e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
/*!
  \page scxml.html
  \title Using SCXML files in Qt
  \ingroup sctools
  \brief An overview of the sctools module, which allows loading scripted state charts with SCXML

  \tableofcontents

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

  The files that the tool can load conform to the \l{State Chart XML: State Machine Notation for Control Abstraction}{State Chart XML (SCXML)} standard.
  
  \section1 Getting Started with Qt & SCXML
  \list 
  \i First of all, make yourself familiar with the \l{State Chart XML: State Machine Notation for Control Abstraction}{SCXML specification}.
  \i Read this document to understand how to enable SCXML files in your project, and how to load SCXML files in runtime/build-time.
  \i Go over the blackjack, calc and mediaplayer examples for usage demonstration.
  \endlist

  \section1 Enabling the QtScriptedStateMachine class

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

  \section1 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:
    \section2 Working with the script engine

    The main feature of \l QtScriptedStateMachine is that it includes a single \a 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 \l QtScriptedStateMachine::registerObject(), which allows you to add an object
    (and optionally all its descendants) to the scripting context.
     \l QtScriptedStateMachine::scriptEngine() allows you to manipulate the scripting context directly.
     Use the mediaplayer example as a reference for using the registerObject function.


    \section2 Connecting the state-machine to signals/slots

    A simpler way to interact with the state machine is through signals and slots.
    The slot \l QtScriptedStateMachine::postNamedEvent() and the signal \l 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 \l QtScriptedStateMachine::postNamedEvent().

    \section2 Extending the state-machine with custom invokers

    A custom invoker allows you to write your own \l{http://www.w3.org/TR/scxml/#Invoke}{invoke} tags, and implement specific invoke types,
    as described in the SCXML standard.

    To create a custom invoker, you must subclass from \l QtSsmInvoker, and implement at least:
    \list
        \i A constructor with \l QtScriptedEvent and \l QtStateMachine arguments
        \i The \l QtSsmInvoker::activate() function
        \i A static bool isTypeSupportedString(QString) function, conforms to the \l {http://www.w3.org/TR/scxml/#Invoke}{invoke} element's type attribute
        \i A static void initInvokerFactory(QtScriptedStateMachine*) function, allows some initialization (like adding properties to the script engine)
    \endlist


    When these terms are met, you can create an invoke-factory, and register it to the state machine.
    Example:
    \code
        #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);

    \endcode

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





  \section1 Loading SCXML files at runtime

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

\code
    #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 ();
\endcode


  \section1 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.

    \section2 Fully supported elements
     The tags \l {http://www.w3.org/TR/scxml/#state}{state}, \l {http://www.w3.org/TR/scxml/#parallel}{parallel}, \l {http://www.w3.org/TR/scxml/#final}{final}, \l {http://www.w3.org/TR/scxml/#onentry}{onentry}, \l {http://www.w3.org/TR/scxml/#onexit}{onexit}, \l {http://www.w3.org/TR/scxml/#raise}{raise}, \l {http://www.w3.org/TR/scxml/#if}{if}, \l {http://www.w3.org/TR/scxml/#elseif}{elseif}, \l {http://www.w3.org/TR/scxml/#else}{else}, \l {http://www.w3.org/TR/scxml/#log}{log}, \l {http://www.w3.org/TR/scxml/#cancel}{cancel}, \l {http://www.w3.org/TR/scxml/#datamodel}{datamodel},\l {http://www.w3.org/TR/scxml/#data}{data}, \l {http://www.w3.org/TR/scxml/#assign}{assign}, \l {http://www.w3.org/TR/scxml/#param}{param}, ands \l {http://www.w3.org/TR/scxml/#anchor}{anchor} are fully supported according to the scxml spec.

    \section2 Partially supported elements
     \list
        \i \l {http://www.w3.org/TR/scxml/#scxml}{scxml}: The attributes version, profile and exmode are ignored.
        \i \l {http://www.w3.org/TR/scxml/#initial}{initial}: Treated as a regular state that's marked as initial for the parent state.
        \i \l {http://www.w3.org/TR/scxml/#history}{history}: Actions in the history's default transition are ignored.
        \i \l {http://www.w3.org/TR/scxml/#content}{content}: Supports only JSON data, not XML.
        \i \l {http://www.w3.org/TR/scxml/#send}{send}: only the scxml target type is supported. The id attribute is ignored.
        \i \l {http://www.w3.org/TR/scxml/#invoke}{invoke}: the autoforward and id tags are ignored.
     \endlist

    \section2 Unsupported elements
     The elements \l {http://www.w3.org/TR/scxml/#Donedata}{donedata}, \l {http://www.w3.org/TR/scxml/#Finalize}{finalize} and \l {http://www.w3.org/TR/scxml/#Validate}{validate} are not supported.
     Also, the local/global script scoping functionality is not implemented.

    \section2 Extras
      \section3 Signal transitions
       To declare a signal transition, use a transition tag with a q-signal uri scheme.
       Example:
       \code
        <transition target="someState" event="q-signal:someObject.someSignal()" />
       \endcode

      \section3 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:

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

        \section3 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.

        \section3 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:
        \code
            <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>
        \endcode

        See the blackjack example for reference.





  */