1// Copyright (C) 2016 The Qt Company Ltd.
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 "qscxmldatamodel_p.h"
5#include "qscxmlnulldatamodel.h"
6#include "qscxmlstatemachine_p.h"
7
8#include <QtCore/private/qfactoryloader_p.h>
9#include "qscxmldatamodelplugin_p.h"
10
11QT_BEGIN_NAMESPACE
12
13Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
14 ("org.qt-project.qt.scxml.datamodel.plugin",
15 QStringLiteral("/scxmldatamodel")))
16
17/*!
18 \class QScxmlDataModel::ForeachLoopBody
19 \brief The ForeachLoopBody class represents a function to be executed on
20 each iteration of an SCXML foreach loop.
21 \since 5.8
22 \inmodule QtScxml
23 */
24
25/*!
26 Creates a new foreach loop body.
27 */
28QScxmlDataModel::ForeachLoopBody::ForeachLoopBody()
29{}
30/*!
31 Destroys a foreach loop body.
32 */
33QScxmlDataModel::ForeachLoopBody::~ForeachLoopBody()
34{}
35
36/*!
37 \fn QScxmlDataModel::ForeachLoopBody::run(bool *ok)
38
39 This function is executed on each iteration. If the execution fails, \a ok is
40 set to \c false, otherwise it is set to \c true.
41 */
42
43/*!
44 * \class QScxmlDataModel
45 * \brief The QScxmlDataModel class is the data model base class for a Qt SCXML
46 * state machine.
47 * \since 5.7
48 * \inmodule QtScxml
49 *
50 * SCXML data models are described in
51 * \l {SCXML Specification - 5 Data Model and Data Manipulation}. For more
52 * information about supported data models, see \l {SCXML Compliance}.
53 *
54 * One data model can only belong to one state machine.
55 *
56 * \sa QScxmlStateMachine QScxmlCppDataModel QScxmlNullDataModel
57 */
58
59/*!
60 \property QScxmlDataModel::stateMachine
61
62 \brief The state machine this data model belongs to.
63
64 A data model can only belong to a single state machine and a state machine
65 can only have one data model. This relation needs to be set up before the
66 state machine is started. Setting this property on a data model will
67 automatically set the corresponding \c dataModel property on the
68 \a stateMachine.
69*/
70
71/*!
72 * Creates a new data model, with the parent object \a parent.
73 */
74QScxmlDataModel::QScxmlDataModel(QObject *parent)
75 : QObject(*(new QScxmlDataModelPrivate), parent)
76{
77}
78
79/*!
80 Creates a new data model from the private object \a dd, with the parent
81 object \a parent.
82 */
83QScxmlDataModel::QScxmlDataModel(QScxmlDataModelPrivate &dd, QObject *parent) :
84 QObject(dd, parent)
85{
86}
87
88/*!
89 * Sets the state machine this model belongs to to \a stateMachine. There is a
90 * 1:1 relation between state machines and models. After setting the state
91 * machine once you cannot change it anymore. Any further attempts to set the
92 * state machine using this method will be ignored.
93 */
94void QScxmlDataModel::setStateMachine(QScxmlStateMachine *stateMachine)
95{
96 Q_D(QScxmlDataModel);
97
98 if (d->m_stateMachine.valueBypassingBindings() == nullptr && stateMachine != nullptr) {
99 // the binding is removed only on the first valid set
100 // as the later attempts are ignored
101 d->m_stateMachine.removeBindingUnlessInWrapper();
102 d->m_stateMachine.setValueBypassingBindings(stateMachine);
103 stateMachine->setDataModel(this);
104 d->m_stateMachine.notify();
105 }
106}
107
108/*!
109 * Returns the state machine associated with the data model.
110 */
111QScxmlStateMachine *QScxmlDataModel::stateMachine() const
112{
113 Q_D(const QScxmlDataModel);
114 return d->m_stateMachine;
115}
116
117QBindable<QScxmlStateMachine*> QScxmlDataModel::bindableStateMachine()
118{
119 Q_D(QScxmlDataModel);
120 return &d->m_stateMachine;
121}
122
123/*!
124 * Creates a data model from a plugin specified by a \a pluginKey.
125 */
126QScxmlDataModel *QScxmlDataModel::createScxmlDataModel(const QString& pluginKey)
127{
128 QScxmlDataModel *model = nullptr;
129
130 int pluginIndex = loader()->indexOf(needle: pluginKey);
131
132 if (QObject *object = loader()->instance(index: pluginIndex)) {
133 if (auto *plugin = qobject_cast<QScxmlDataModelPlugin *>(object)) {
134 model = plugin->createScxmlDataModel();
135 if (!model)
136 qWarning() << pluginKey << " data model was not instantiated, createScxmlDataModel() returned null.";
137
138 } else {
139 qWarning() << "plugin object for" << pluginKey << "is not a QScxmlDatModelPlugin.";
140 }
141 delete object;
142 } else {
143 qWarning() << pluginKey << " plugin not found." ;
144 }
145 return model;
146}
147
148QScxmlDataModel *QScxmlDataModelPrivate::instantiateDataModel(DocumentModel::Scxml::DataModelType type)
149{
150 QScxmlDataModel *dataModel = nullptr;
151 switch (type) {
152 case DocumentModel::Scxml::NullDataModel:
153 dataModel = new QScxmlNullDataModel;
154 break;
155 case DocumentModel::Scxml::JSDataModel:
156 dataModel = QScxmlDataModel::createScxmlDataModel(QStringLiteral("ecmascriptdatamodel"));
157 break;
158 case DocumentModel::Scxml::CppDataModel:
159 break;
160 default:
161 Q_UNREACHABLE();
162 }
163 return dataModel;
164}
165
166/*!
167 * \fn QScxmlDataModel::setup(const QVariantMap &initialDataValues)
168 *
169 * Initializes the data model with the initial values specified by
170 * \a initialDataValues.
171 *
172 * Returns \c false if parse errors occur or if any of the initialization steps
173 * fail. Returns \c true otherwise.
174 */
175
176/*!
177 * \fn QScxmlDataModel::setScxmlEvent(const QScxmlEvent &event)
178 *
179 * Sets the \a event to use in the subsequent executable content execution.
180 */
181
182/*!
183 * \fn QScxmlDataModel::scxmlProperty(const QString &name) const
184 *
185 * Returns the value of the property \a name.
186 */
187
188/*!
189 * \fn QScxmlDataModel::hasScxmlProperty(const QString &name) const
190 *
191 * Returns \c true if a property with the given \a name exists, \c false
192 * otherwise.
193 */
194
195/*!
196 * \fn QScxmlDataModel::setScxmlProperty(const QString &name,
197 * const QVariant &value,
198 * const QString &context)
199 *
200 * Sets a the value \a value for the property \a name.
201 *
202 * The \a context is a string that is used in error messages to indicate the
203 * location in the SCXML file where the error occurred.
204 *
205 * Returns \c true if successful or \c false if an error occurred.
206 */
207
208/*!
209 * \fn QScxmlDataModel::evaluateToString(
210 * QScxmlExecutableContent::EvaluatorId id, bool *ok)
211 * Evaluates the executable content pointed to by \a id and sets \a ok to
212 * \c false if there was an error or to \c true if there was not.
213 * Returns the result of the evaluation as a QString.
214 */
215
216/*!
217 * \fn QScxmlDataModel::evaluateToBool(QScxmlExecutableContent::EvaluatorId id,
218 * bool *ok)
219 * Evaluates the executable content pointed to by \a id and sets \a ok to
220 * \c false if there was an error or to \c true if there was not.
221 * Returns the result of the evaluation as a boolean value.
222 */
223
224/*!
225 * \fn QScxmlDataModel::evaluateToVariant(
226 * QScxmlExecutableContent::EvaluatorId id, bool *ok)
227 * Evaluates the executable content pointed to by \a id and sets \a ok to
228 * \c false if there was an error or to \c true if there was not.
229 * Returns the result of the evaluation as a QVariant.
230 */
231
232/*!
233 * \fn QScxmlDataModel::evaluateToVoid(QScxmlExecutableContent::EvaluatorId id,
234 * bool *ok)
235 * Evaluates the executable content pointed to by \a id and sets \a ok to
236 * \c false if there was an error or to \c true if there was not.
237 * The execution is expected to return no result.
238 */
239
240/*!
241 * \fn QScxmlDataModel::evaluateAssignment(
242 * QScxmlExecutableContent::EvaluatorId id, bool *ok)
243 * Evaluates the assignment pointed to by \a id and sets \a ok to
244 * \c false if there was an error or to \c true if there was not.
245 */
246
247/*!
248 * \fn QScxmlDataModel::evaluateInitialization(
249 * QScxmlExecutableContent::EvaluatorId id, bool *ok)
250 * Evaluates the initialization pointed to by \a id and sets \a ok to
251 * \c false if there was an error or to \c true if there was not.
252 */
253
254/*!
255 * \fn QScxmlDataModel::evaluateForeach(
256 * QScxmlExecutableContent::EvaluatorId id, bool *ok,
257 * ForeachLoopBody *body)
258 * Evaluates the foreach loop pointed to by \a id and sets \a ok to
259 * \c false if there was an error or to \c true if there was not. The
260 * \a body is executed on each iteration.
261 */
262
263QT_END_NAMESPACE
264

source code of qtscxml/src/scxml/qscxmldatamodel.cpp