1
/*!
2
  \page scxml.html
3
  \title Using SCXML files in Qt
4
  \ingroup sctools
5
  \brief An overview of the sctools module, which allows loading scripted state charts with SCXML
6
7
  \tableofcontents
8
9
  The sctools module allows loading SCXML files into a QtScriptedStateMachine object.
10
11
  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.
12
  
13
  \section1 Getting Started with Qt & SCXML
14
  \list 
15
  \i First of all, make yourself familiar with the \l{State Chart XML: State Machine Notation for Control Abstraction}{SCXML specification}.
16
  \i Read this document to understand how to enable SCXML files in your project, and how to load SCXML files in runtime/build-time.
17
  \i Go over the blackjack, calc and mediaplayer examples for usage demonstration.
18
  \endlist
19
20
  \section1 Enabling the QtScriptedStateMachine class
21
22
    The \l QtScriptedStateMachine class is enabled automatically when the script module is enabled.
23
24
  \section1 Using the QtScriptedStateMachine class
25
26
    QtScriptedStateMachine is a subclass of QtStateMachine. QtStateMachine actually includes most of the
27
    "interesting" API, while QtScriptedStateMachine adds the missing parts to support SCXML.
28
29
     Most of the interaction with QtScriptedStateMachine occurs after the state-machine is loaded,
30
     and before it's started.
31
    The interesting functionalities of QtScriptedStateMachine are:
32
    \section2 Working with the script engine
33
34
    The main feature of \l QtScriptedStateMachine is that it includes a single \a QScriptEngine object that's
35
    shared between all state actions and transitions. That's what allows the states to rely on a single
36
    data context for evaluating conditions and executing the entry/exit/transition actions.
37
38
    A very useful function is \l QtScriptedStateMachine::registerObject(), which allows you to add an object
39
    (and optionally all its descendants) to the scripting context.
40
     \l QtScriptedStateMachine::scriptEngine() allows you to manipulate the scripting context directly.
41
     Use the mediaplayer example as a reference for using the registerObject function.
42
43
44
    \section2 Connecting the state-machine to signals/slots
45
46
    A simpler way to interact with the state machine is through signals and slots.
47
    The slot \l QtScriptedStateMachine::postNamedEvent() and the signal \l QtScriptedStateMachine::eventTriggered()
48
    allow for a simple interaction with the state machine, as you can connect signals to postNamedEvent
49
    and eventTriggered to and signal/slot.
50
51
    There are no entered/exited signals from states, as that would make the state-machines less deterministic
52
    and would create results that are difficult to manage and predict (does the signal get emitted before,
53
    after or during the normal execution list?)
54
55
    The calc example shows the usage of \l QtScriptedStateMachine::postNamedEvent().
56
57
    \section2 Extending the state-machine with custom invokers
58
59
    A custom invoker allows you to write your own \l{http://www.w3.org/TR/scxml/#Invoke}{invoke} tags, and implement specific invoke types,
60
    as described in the SCXML standard.
61
62
    To create a custom invoker, you must subclass from \l QtSsmInvoker, and implement at least:
63
    \list
64
        \i A constructor with \l QtScriptedEvent and \l QtStateMachine arguments
65
        \i The \l QtSsmInvoker::activate() function
66
        \i A static bool isTypeSupportedString(QString) function, conforms to the \l {http://www.w3.org/TR/scxml/#Invoke}{invoke} element's type attribute
67
        \i A static void initInvokerFactory(QtScriptedStateMachine*) function, allows some initialization (like adding properties to the script engine)
68
    \endlist
69
70
71
    When these terms are met, you can create an invoke-factory, and register it to the state machine.
72
    Example:
73
    \code
74
        #include <QtScriptedStateMachine>
75
76
        class MyInvoker : public QtSsmInvoker
77
        {
78
            Q_OBJECT
79
            public:
80
                MyInvoker(QtScriptedEvent* ievent, QtScriptedStateMachine* p) : QtSsmInvoker(ievent,p),menu(0)
81
                {
82
                }
83
                static void initInvokerFactory(QtScriptedStateMachine* machine)
84
                {
85
                    machine->scriptEngine()->globalObject().setProperty("some-name",someValue);
86
                }
87
                static bool isTypeSupported (const QString & s) { return s== "my-type"; }
88
            public Q_SLOTS:
89
                void activate ()
90
                {
91
                    doSomeStuff ();
92
                }
93
        };
94
    ...
95
        static QSsmAutoInvokerFactory<MyInvoker> _s_factory;
96
        myScriptedStateMachine->registerInvoker(&_s_factory);
97
98
    \endcode
99
100
    The initEvent protected member can be used to access the parameters
101
    given to the invoker by the calling state machine. \l QtSsmInvoker::postParentEvent()
102
    allows sending events back to the calling state machine.
103
104
105
106
107
108
  \section1 Loading SCXML files at runtime
109
110
  To load SCXML files in runtime, the static function \l QtScriptedStateMachine::load() must be used.
111
  Note that this function requires the xmlpatterns and xml modules to be enabled.
112
  \l QtScriptedStateMachine::load() it creates a new \l QtScriptedStateMachine object.
113
  An example code would be:
114
115
\code
116
    #include "qscriptedstatemachine.h"
117
118
    // some code
119
    QtScriptedStateMachine* stateMachine = QtScriptedStateMachine::load ("path-to-some-file.scxml");
120
    // ... register some objects, handle some stuff in the script engine...
121
    stateMachine->start ();
122
\endcode
123
124
125
  \section1 Supported SCXML tags and features
126
127
Though most of the SCXML features are supported in this implementation, the support is incomplete,
128
partially because the spec itself is still evolving. This documentation tries to capture most of the
129
gaps and differences.
130
131
    \section2 Fully supported elements
132
     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.
133
134
    \section2 Partially supported elements
135
     \list
136
        \i \l {http://www.w3.org/TR/scxml/#scxml}{scxml}: The attributes version, profile and exmode are ignored.
137
        \i \l {http://www.w3.org/TR/scxml/#initial}{initial}: Treated as a regular state that's marked as initial for the parent state.
138
        \i \l {http://www.w3.org/TR/scxml/#history}{history}: Actions in the history's default transition are ignored.
139
        \i \l {http://www.w3.org/TR/scxml/#content}{content}: Supports only JSON data, not XML.
140
        \i \l {http://www.w3.org/TR/scxml/#send}{send}: only the scxml target type is supported. The id attribute is ignored.
141
        \i \l {http://www.w3.org/TR/scxml/#invoke}{invoke}: the autoforward and id tags are ignored.
142
     \endlist
143
144
    \section2 Unsupported elements
145
     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.
146
     Also, the local/global script scoping functionality is not implemented.
147
148
    \section2 Extras
149
      \section3 Signal transitions
150
       To declare a signal transition, use a transition tag with a q-signal uri scheme.
151
       Example:
152
       \code
153
        <transition target="someState" event="q-signal:someObject.someSignal()" />
154
       \endcode
155
156
      \section3 Property binding
157
       The q-binding invoker can be used to setup properties on entry, that are restored on exit.
158
       Note that if the properties are changed externally while the state is active, the properties
159
       would still be restored.
160
161
        The binding invoke element accepts a content tag with a JSON array, of which each element is a 3-item 
162
		array: [object, property-name, property-value]. 
163
164
        Example:
165
166
        \code
167
         <invoke type="q-bindings"><content>
168
			[[myObject,"someProperty",someValue1 + someValue2],
169
			[myObject,"text","hello"]]
170
         </content></invoke>
171
         \endcode
172
173
        \section3 Menus
174
         A custom invoker added to the solution is the "q-menu" invoker. This invoker allows you to display a
175
         QMenu and listen to its events.
176
         The q-menu invoker should a content tag, which includes an expression evaluating to an ecmascript
177
         object defining the menu.
178
         Note that support for menus is currently experimental, and the mediaplayer example demonstrates its use.
179
180
        \section3 Message Boxes
181
         Similar to q-menus, the "q-messagebox" invoker lets you show a QMessageBox and react to
182
         the user interactions with it.
183
184
         The q-messagebox invoker accepts an ecmascript object that contains name/value pairs for the QMessageBox
185
         properties.
186
187
        Example:
188
        \code
189
            <invoke type="q-messagebox">
190
                <content>
191
                    {
192
                      "parent" : myParentWidget,
193
                      "icon" : QMessageBox.Question,
194
                      "windowTitle" : "Would you like to exit?",
195
                      "text" : "Are you sure?",
196
                      "standardButtons" : QMessageBox.Yes|QMessageBox.No
197
                    }
198
                </content>
199
            </invoke>
200
        \endcode
201
202
        See the blackjack example for reference.
203
204
205
206
207
208
  */