1// Copyright (C) 2016 Ford Motor Company
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "statemachine_p.h"
5
6#include <QAbstractTransition>
7#include <QQmlContext>
8#include <QQmlEngine>
9#include <QQmlInfo>
10
11StateMachine::StateMachine(QObject *parent)
12 : QStateMachine(parent), m_completed(false), m_running(false)
13{
14 connect(asender: this, SIGNAL(runningChanged(bool)), SIGNAL(qmlRunningChanged()));
15 connect(asender: this, SIGNAL(childModeChanged()), SLOT(checkChildMode()));
16}
17
18QQmlListProperty<QObject> StateMachine::childrenActualCalculation() const
19{
20 // Mutating accesses to m_children only happen in the QML thread,
21 // so there are no thread-safety issues.
22 // The engine only creates non-const instances of the class anyway
23 return QQmlListProperty<QObject>(const_cast<StateMachine*>(this), &m_children,
24 m_children.append, m_children.count, m_children.at,
25 m_children.clear, m_children.replace, m_children.removeLast);
26}
27
28bool StateMachine::isRunning() const
29{
30 return QStateMachine::isRunning();
31}
32
33void StateMachine::setRunning(bool running)
34{
35 if (m_completed)
36 QStateMachine::setRunning(running);
37 else
38 m_running = running;
39}
40
41void StateMachine::checkChildMode()
42{
43 if (childMode() != QState::ExclusiveStates) {
44 qmlWarning(me: this) << "Setting the childMode of a StateMachine to anything else than\n"
45 "QState.ExclusiveStates will result in an invalid state machine,\n"
46 "and can lead to incorrect behavior!";
47 }
48}
49
50void StateMachine::componentComplete()
51{
52 if (QStateMachine::initialState() == nullptr && childMode() == QState::ExclusiveStates)
53 qmlWarning(me: this) << "No initial state set for StateMachine";
54
55 // Everything is proper setup, now start the state-machine if we got
56 // asked to do so.
57 m_completed = true;
58 if (m_running)
59 setRunning(true);
60}
61
62QQmlListProperty<QObject> StateMachine::children()
63{
64 return m_childrenComputedProperty;
65}
66
67void StateMachine::childrenContentChanged()
68{
69 m_childrenComputedProperty.notify();
70 emit childrenChanged();
71}
72
73QBindable<QQmlListProperty<QObject>> StateMachine::bindableChildren() const
74{
75 return &m_childrenComputedProperty;
76}
77
78/*!
79 \qmltype StateMachine
80 \inqmlmodule QtQml.StateMachine
81 \inherits State
82 \ingroup statemachine-qmltypes
83 \since 5.4
84
85 \brief Provides a hierarchical finite state machine.
86
87 StateMachine is based on the concepts and notation of
88 \l{http://www.wisdom.weizmann.ac.il/~dharel/SCANNED.PAPERS/Statecharts.pdf}{Statecharts}.
89 StateMachine is part of \l{Qt State Machine QML Guide}{Qt State Machine QML API}
90
91 A state machine manages a set of states and transitions between those
92 states; these states and transitions define a state graph. Once a state
93 graph has been built, the state machine can execute it. StateMachine's
94 execution algorithm is based on the \l{http://www.w3.org/TR/scxml/}{State Chart XML (SCXML)}
95 algorithm. The framework's \l{Qt State Machine QML Guide}{overview}
96 gives several state graphs and the code to build them.
97
98 Before the machine can be started, the \l{State::initialState}{initialState}
99 must be set. The initial state is the state that the
100 machine enters when started. You can then set running property to true
101 or start() the state machine. The started signal is emitted when the
102 initial state is entered.
103
104 The state machine processes events and takes transitions until a
105 top-level final state is entered; the state machine then emits the
106 finished() signal. You can also stop() the state machine
107 explicitly (you can also set running property to false).
108 The stopped signal is emitted in this case.
109
110 \section1 Example Usage
111 The following snippet shows a state machine that will finish when a button
112 is clicked:
113
114 \snippet qml/statemachine/simplestatemachine.qml document
115
116 If an error is encountered, the machine will look for an
117 \l{State::errorState}{errorState}, and if one is available, it will
118 enter this state. After the error state is entered, the type of the error
119 can be retrieved with error(). The execution of the state graph will not
120 stop when the error state is entered. If no error state applies to the
121 erroneous state, the machine will stop executing and an error message will
122 be printed to the console.
123
124 \warning Setting the childMode of a StateMachine to anything else than QState::ExclusiveStates
125 will result in an invalid state machine, and can lead to incorrect behavior.
126
127 \clearfloat
128
129 \sa QAbstractState, State, SignalTransition, TimeoutTransition, HistoryState {Qt State Machine QML Guide}
130*/
131
132/*!
133 \qmlproperty enumeration StateMachine::globalRestorePolicy
134
135 \brief The restore policy for states of this state machine.
136
137 The default value of this property is QState.DontRestoreProperties.
138
139 This enum specifies the restore policy type. The restore policy
140 takes effect when the machine enters a state which sets one or more
141 properties. If the restore policy is set to QState.RestoreProperties,
142 the state machine will save the original value of the property before the
143 new value is set.
144
145 Later, when the machine either enters a state which does not set a
146 value for the given property, the property will automatically be restored
147 to its initial value.
148
149 Only one initial value will be saved for any given property. If a value
150 for a property has already been saved by the state machine, it will not be
151 overwritten until the property has been successfully restored.
152
153 \list
154 \li QState.DontRestoreProperties The state machine should not save the initial values of properties and restore them later.
155 \li QState.RestoreProperties The state machine should save the initial values of properties and restore them later.
156 \endlist
157*/
158
159/*!
160 \qmlproperty bool StateMachine::running
161
162 \brief The running state of this state machine.
163 \sa start(), stop()
164*/
165
166/*!
167 \qmlproperty string StateMachine::errorString
168 \readonly errorString
169
170 \brief The error string of this state machine.
171*/
172
173
174/*!
175 \qmlmethod StateMachine::start()
176
177 Starts this state machine. The machine will reset its configuration and
178 transition to the initial state. When a final top-level state (FinalState)
179 is entered, the machine will emit the finished() signal.
180
181 \note A state machine will not run without a running event loop, such as
182 the main application event loop started with QCoreApplication::exec() or
183 QApplication::exec().
184
185 \sa started, State::finished, stop(), State::initialState, running
186*/
187
188/*!
189 \qmlsignal StateMachine::started()
190
191 This signal is emitted when the state machine has entered its initial state
192 (State::initialState).
193
194 \sa running, start(), State::finished
195*/
196
197/*!
198 \qmlmethod StateMachine::stop()
199
200 Stops this state machine. The state machine will stop processing events
201 and then emit the stopped signal.
202
203 \sa stopped, start(), running
204*/
205
206/*!
207 \qmlsignal StateMachine::stopped()
208
209 This signal is emitted when the state machine has stopped.
210
211 \sa running, stop(), State::finished
212*/
213
214#include "moc_statemachine_p.cpp"
215

source code of qtscxml/src/statemachineqml/statemachine.cpp