Revision control
++ // Copyright (C) 2016 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
++ // Qt-Security score:critical reason:execute-external-code
++
++ #include "qscxmldatamodel_p.h"
++ #include "qscxmlnulldatamodel.h"
++ #include "qscxmlstatemachine_p.h"
++
++ #include <QtCore/private/qfactoryloader_p.h>
++ #include "qscxmldatamodelplugin_p.h"
++
++ QT_BEGIN_NAMESPACE
++
++ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
++ ("org.qt-project.qt.scxml.datamodel.plugin",
++ QStringLiteral("/scxmldatamodel")))
++
++ /*!
++ \class QScxmlDataModel::ForeachLoopBody
++ \brief The ForeachLoopBody class represents a function to be executed on
++ each iteration of an SCXML foreach loop.
++ \since 5.8
++ \inmodule QtScxml
++ */
++
++ /*!
++ Creates a new foreach loop body.
++ */
++ QScxmlDataModel::ForeachLoopBody::ForeachLoopBody()
++ {}
++ /*!
++ Destroys a foreach loop body.
++ */
++ QScxmlDataModel::ForeachLoopBody::~ForeachLoopBody()
++ {}
++
++ /*!
++ \fn QScxmlDataModel::ForeachLoopBody::run(bool *ok)
++
++ This function is executed on each iteration. If the execution fails, \a ok is
++ set to \c false, otherwise it is set to \c true.
++ */
++
++ /*!
++ * \class QScxmlDataModel
++ * \brief The QScxmlDataModel class is the data model base class for a Qt SCXML
++ * state machine.
++ * \since 5.7
++ * \inmodule QtScxml
++ *
++ * SCXML data models are described in
++ * \l {SCXML Specification - 5 Data Model and Data Manipulation}. For more
++ * information about supported data models, see \l {SCXML Compliance}.
++ *
++ * One data model can only belong to one state machine.
++ *
++ * \sa QScxmlStateMachine QScxmlCppDataModel QScxmlNullDataModel
++ */
++
++ /*!
++ \property QScxmlDataModel::stateMachine
++
++ \brief The state machine this data model belongs to.
++
++ A data model can only belong to a single state machine and a state machine
++ can only have one data model. This relation needs to be set up before the
++ state machine is started. Setting this property on a data model will
++ automatically set the corresponding \c dataModel property on the
++ \a stateMachine.
++ */
++
++ /*!
++ * Creates a new data model, with the parent object \a parent.
++ */
++ QScxmlDataModel::QScxmlDataModel(QObject *parent)
++ : QObject(*(new QScxmlDataModelPrivate), parent)
++ {
++ }
++
++ /*!
++ Creates a new data model from the private object \a dd, with the parent
++ object \a parent.
++ */
++ QScxmlDataModel::QScxmlDataModel(QScxmlDataModelPrivate &dd, QObject *parent) :
++ QObject(dd, parent)
++ {
++ }
++
++ /*!
++ * Sets the state machine this model belongs to to \a stateMachine. There is a
++ * 1:1 relation between state machines and models. After setting the state
++ * machine once you cannot change it anymore. Any further attempts to set the
++ * state machine using this method will be ignored.
++ */
++ void QScxmlDataModel::setStateMachine(QScxmlStateMachine *stateMachine)
++ {
++ Q_D(QScxmlDataModel);
++
++ if (d->m_stateMachine.valueBypassingBindings() == nullptr && stateMachine != nullptr) {
++ // the binding is removed only on the first valid set
++ // as the later attempts are ignored
++ d->m_stateMachine.removeBindingUnlessInWrapper();
++ d->m_stateMachine.setValueBypassingBindings(stateMachine);
++ stateMachine->setDataModel(this);
++ d->m_stateMachine.notify();
++ }
++ }
++
++ /*!
++ * Returns the state machine associated with the data model.
++ */
++ QScxmlStateMachine *QScxmlDataModel::stateMachine() const
++ {
++ Q_D(const QScxmlDataModel);
++ return d->m_stateMachine;
++ }
++
++ QBindable<QScxmlStateMachine*> QScxmlDataModel::bindableStateMachine()
++ {
++ Q_D(QScxmlDataModel);
++ return &d->m_stateMachine;
++ }
++
++ /*!
++ * Creates a data model from a plugin specified by a \a pluginKey.
++ */
++ QScxmlDataModel *QScxmlDataModel::createScxmlDataModel(const QString& pluginKey)
++ {
++ QScxmlDataModel *model = nullptr;
++
++ int pluginIndex = loader()->indexOf(pluginKey);
++
++ if (QObject *object = loader()->instance(pluginIndex)) {
++ if (auto *plugin = qobject_cast<QScxmlDataModelPlugin *>(object)) {
++ model = plugin->createScxmlDataModel();
++ if (!model)
++ qWarning() << pluginKey << " data model was not instantiated, createScxmlDataModel() returned null.";
++
++ } else {
++ qWarning() << "plugin object for" << pluginKey << "is not a QScxmlDatModelPlugin.";
++ }
++ delete object;
++ } else {
++ qWarning() << pluginKey << " plugin not found." ;
++ }
++ return model;
++ }
++
++ QScxmlDataModel *QScxmlDataModelPrivate::instantiateDataModel(DocumentModel::Scxml::DataModelType type)
++ {
++ QScxmlDataModel *dataModel = nullptr;
++ switch (type) {
++ case DocumentModel::Scxml::NullDataModel:
++ dataModel = new QScxmlNullDataModel;
++ break;
++ case DocumentModel::Scxml::JSDataModel:
++ dataModel = QScxmlDataModel::createScxmlDataModel(QStringLiteral("ecmascriptdatamodel"));
++ break;
++ case DocumentModel::Scxml::CppDataModel:
++ break;
++ default:
++ Q_UNREACHABLE();
++ }
++ return dataModel;
++ }
++
++ /*!
++ * \fn QScxmlDataModel::setup(const QVariantMap &initialDataValues)
++ *
++ * Initializes the data model with the initial values specified by
++ * \a initialDataValues.
++ *
++ * Returns \c false if parse errors occur or if any of the initialization steps
++ * fail. Returns \c true otherwise.
++ */
++
++ /*!
++ * \fn QScxmlDataModel::setScxmlEvent(const QScxmlEvent &event)
++ *
++ * Sets the \a event to use in the subsequent executable content execution.
++ */
++
++ /*!
++ * \fn QScxmlDataModel::scxmlProperty(const QString &name) const
++ *
++ * Returns the value of the property \a name.
++ */
++
++ /*!
++ * \fn QScxmlDataModel::hasScxmlProperty(const QString &name) const
++ *
++ * Returns \c true if a property with the given \a name exists, \c false
++ * otherwise.
++ */
++
++ /*!
++ * \fn QScxmlDataModel::setScxmlProperty(const QString &name,
++ * const QVariant &value,
++ * const QString &context)
++ *
++ * Sets a the value \a value for the property \a name.
++ *
++ * The \a context is a string that is used in error messages to indicate the
++ * location in the SCXML file where the error occurred.
++ *
++ * Returns \c true if successful or \c false if an error occurred.
++ */
++
++ /*!
++ * \fn QScxmlDataModel::evaluateToString(
++ * QScxmlExecutableContent::EvaluatorId id, bool *ok)
++ * Evaluates the executable content pointed to by \a id and sets \a ok to
++ * \c false if there was an error or to \c true if there was not.
++ * Returns the result of the evaluation as a QString.
++ */
++
++ /*!
++ * \fn QScxmlDataModel::evaluateToBool(QScxmlExecutableContent::EvaluatorId id,
++ * bool *ok)
++ * Evaluates the executable content pointed to by \a id and sets \a ok to
++ * \c false if there was an error or to \c true if there was not.
++ * Returns the result of the evaluation as a boolean value.
++ */
++
++ /*!
++ * \fn QScxmlDataModel::evaluateToVariant(
++ * QScxmlExecutableContent::EvaluatorId id, bool *ok)
++ * Evaluates the executable content pointed to by \a id and sets \a ok to
++ * \c false if there was an error or to \c true if there was not.
++ * Returns the result of the evaluation as a QVariant.
++ */
++
++ /*!
++ * \fn QScxmlDataModel::evaluateToVoid(QScxmlExecutableContent::EvaluatorId id,
++ * bool *ok)
++ * Evaluates the executable content pointed to by \a id and sets \a ok to
++ * \c false if there was an error or to \c true if there was not.
++ * The execution is expected to return no result.
++ */
++
++ /*!
++ * \fn QScxmlDataModel::evaluateAssignment(
++ * QScxmlExecutableContent::EvaluatorId id, bool *ok)
++ * Evaluates the assignment pointed to by \a id and sets \a ok to
++ * \c false if there was an error or to \c true if there was not.
++ */
++
++ /*!
++ * \fn QScxmlDataModel::evaluateInitialization(
++ * QScxmlExecutableContent::EvaluatorId id, bool *ok)
++ * Evaluates the initialization pointed to by \a id and sets \a ok to
++ * \c false if there was an error or to \c true if there was not.
++ */
++
++ /*!
++ * \fn QScxmlDataModel::evaluateForeach(
++ * QScxmlExecutableContent::EvaluatorId id, bool *ok,
++ * ForeachLoopBody *body)
++ * Evaluates the foreach loop pointed to by \a id and sets \a ok to
++ * \c false if there was an error or to \c true if there was not. The
++ * \a body is executed on each iteration.
++ */
++
++ QT_END_NAMESPACE