diff options
-rw-r--r-- | examples/scxml/mediaplayer-qml-cppdatamodel/mediaplayer-qml-cppdatamodel.cpp | 3 | ||||
-rw-r--r-- | examples/scxml/mediaplayer-qml-cppdatamodel/thedatamodel.cpp | 5 | ||||
-rw-r--r-- | examples/scxml/mediaplayer-qml-cppdatamodel/thedatamodel.h | 3 | ||||
-rw-r--r-- | src/scxml/qscxmlcppdatamodel.cpp | 6 | ||||
-rw-r--r-- | src/scxml/qscxmlcppdatamodel.h | 2 | ||||
-rw-r--r-- | src/scxml/qscxmlcppdatamodel_p.h | 2 | ||||
-rw-r--r-- | src/scxml/qscxmldatamodel.cpp | 57 | ||||
-rw-r--r-- | src/scxml/qscxmldatamodel.h | 9 | ||||
-rw-r--r-- | src/scxml/qscxmldatamodel_p.h | 11 | ||||
-rw-r--r-- | src/scxml/qscxmlecmascriptdatamodel.cpp | 11 | ||||
-rw-r--r-- | src/scxml/qscxmlecmascriptdatamodel.h | 2 | ||||
-rw-r--r-- | src/scxml/qscxmlnulldatamodel.cpp | 10 | ||||
-rw-r--r-- | src/scxml/qscxmlnulldatamodel.h | 2 | ||||
-rw-r--r-- | src/scxml/qscxmlparser.cpp | 9 | ||||
-rw-r--r-- | src/scxml/qscxmlstatemachine.cpp | 34 | ||||
-rw-r--r-- | src/scxml/qscxmlstatemachine.h | 3 | ||||
-rw-r--r-- | tools/qscxmlc/scxmlcppdumper.cpp | 4 |
17 files changed, 108 insertions, 65 deletions
diff --git a/examples/scxml/mediaplayer-qml-cppdatamodel/mediaplayer-qml-cppdatamodel.cpp b/examples/scxml/mediaplayer-qml-cppdatamodel/mediaplayer-qml-cppdatamodel.cpp index cc087f2..461e84f 100644 --- a/examples/scxml/mediaplayer-qml-cppdatamodel/mediaplayer-qml-cppdatamodel.cpp +++ b/examples/scxml/mediaplayer-qml-cppdatamodel/mediaplayer-qml-cppdatamodel.cpp @@ -60,7 +60,8 @@ int main(int argc, char *argv[]) QGuiApplication app(argc, argv); MediaPlayerStateMachine stateMachine; - TheDataModel dataModel(&stateMachine); + TheDataModel dataModel; + stateMachine.setDataModel(&dataModel); stateMachine.init(); stateMachine.start(); diff --git a/examples/scxml/mediaplayer-qml-cppdatamodel/thedatamodel.cpp b/examples/scxml/mediaplayer-qml-cppdatamodel/thedatamodel.cpp index b4409ef..0a3e200 100644 --- a/examples/scxml/mediaplayer-qml-cppdatamodel/thedatamodel.cpp +++ b/examples/scxml/mediaplayer-qml-cppdatamodel/thedatamodel.cpp @@ -52,11 +52,6 @@ #include <QScxmlEvent> -TheDataModel::TheDataModel(QScxmlStateMachine *stateMachine) - : QScxmlCppDataModel(stateMachine) -{ -} - bool TheDataModel::isValidMedia() const { QString eventMedia = eventData().value(QStringLiteral("media")).toString(); diff --git a/examples/scxml/mediaplayer-qml-cppdatamodel/thedatamodel.h b/examples/scxml/mediaplayer-qml-cppdatamodel/thedatamodel.h index e0f5bdf..e7a0e79 100644 --- a/examples/scxml/mediaplayer-qml-cppdatamodel/thedatamodel.h +++ b/examples/scxml/mediaplayer-qml-cppdatamodel/thedatamodel.h @@ -58,9 +58,6 @@ class TheDataModel: public QScxmlCppDataModel Q_OBJECT Q_SCXML_DATAMODEL -public: - TheDataModel(QScxmlStateMachine *stateMachine); - private: bool isValidMedia() const; QVariantMap eventData() const; diff --git a/src/scxml/qscxmlcppdatamodel.cpp b/src/scxml/qscxmlcppdatamodel.cpp index be2fce8..9f00b75 100644 --- a/src/scxml/qscxmlcppdatamodel.cpp +++ b/src/scxml/qscxmlcppdatamodel.cpp @@ -128,10 +128,10 @@ void TheDataModel::evaluateToVoid(QScxmlExecutableContent::EvaluatorId id, bool */ /*! - * Creates a new C++ data model with the state machine \a stateMachine. + * Creates a new C++ data model with the parent object \a parent. */ -QScxmlCppDataModel::QScxmlCppDataModel(QScxmlStateMachine *stateMachine) - : QScxmlDataModel(*(new QScxmlCppDataModelPrivate(stateMachine))) +QScxmlCppDataModel::QScxmlCppDataModel(QObject *parent) + : QScxmlDataModel(*(new QScxmlCppDataModelPrivate), parent) {} /*! diff --git a/src/scxml/qscxmlcppdatamodel.h b/src/scxml/qscxmlcppdatamodel.h index c6366e3..f6e344d 100644 --- a/src/scxml/qscxmlcppdatamodel.h +++ b/src/scxml/qscxmlcppdatamodel.h @@ -58,7 +58,7 @@ class Q_SCXML_EXPORT QScxmlCppDataModel: public QScxmlDataModel Q_OBJECT Q_DECLARE_PRIVATE(QScxmlCppDataModel) public: - QScxmlCppDataModel(QScxmlStateMachine *stateMachine); + QScxmlCppDataModel(QObject *parent = 0); bool setup(const QVariantMap &initialDataValues) Q_DECL_OVERRIDE; diff --git a/src/scxml/qscxmlcppdatamodel_p.h b/src/scxml/qscxmlcppdatamodel_p.h index 5a779e2..1712a73 100644 --- a/src/scxml/qscxmlcppdatamodel_p.h +++ b/src/scxml/qscxmlcppdatamodel_p.h @@ -60,8 +60,6 @@ QT_BEGIN_NAMESPACE class Q_SCXML_EXPORT QScxmlCppDataModelPrivate : public QScxmlDataModelPrivate { public: - QScxmlCppDataModelPrivate(QScxmlStateMachine *stateMachine) : - QScxmlDataModelPrivate(stateMachine) {} QScxmlEvent event; }; diff --git a/src/scxml/qscxmldatamodel.cpp b/src/scxml/qscxmldatamodel.cpp index fd1ce9b..6e6d62b 100644 --- a/src/scxml/qscxmldatamodel.cpp +++ b/src/scxml/qscxmldatamodel.cpp @@ -69,21 +69,49 @@ QScxmlDataModel::ForeachLoopBody::~ForeachLoopBody() */ /*! - * Creates a new data model for the state machine \a stateMachine. + \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(QScxmlStateMachine *stateMachine) - : QObject(*(new QScxmlDataModelPrivate(stateMachine))) +QScxmlDataModel::QScxmlDataModel(QObject *parent) + : QObject(*(new QScxmlDataModelPrivate), parent) { - QScxmlStateMachinePrivate::get(stateMachine)->m_dataModel = this; } /*! * \internal */ -QScxmlDataModel::QScxmlDataModel(QScxmlDataModelPrivate &dd) : - QObject(dd) +QScxmlDataModel::QScxmlDataModel(QScxmlDataModelPrivate &dd, QObject *parent) : + QObject(dd, parent) { - QScxmlStateMachinePrivate::get(dd.m_stateMachine)->m_dataModel = this; +} + +/*! + * 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 == Q_NULLPTR && stateMachine != Q_NULLPTR) { + d->m_stateMachine = stateMachine; + if (stateMachine) + stateMachine->setDataModel(this); + emit stateMachineChanged(stateMachine); + } } /*! @@ -100,34 +128,25 @@ QScxmlTableData *QScxmlDataModel::tableData() const return stateMachine()->tableData(); } -QScxmlDataModel *QScxmlDataModelPrivate::instantiateDataModel( - DocumentModel::Scxml::DataModelType type, QScxmlStateMachine *stateMachine) +QScxmlDataModel *QScxmlDataModelPrivate::instantiateDataModel(DocumentModel::Scxml::DataModelType type) { - Q_ASSERT(stateMachine); - QScxmlDataModel *dataModel = Q_NULLPTR; switch (type) { case DocumentModel::Scxml::NullDataModel: - dataModel = new QScxmlNullDataModel(stateMachine); + dataModel = new QScxmlNullDataModel; break; case DocumentModel::Scxml::JSDataModel: - dataModel = new QScxmlEcmaScriptDataModel(stateMachine); + dataModel = new QScxmlEcmaScriptDataModel; break; case DocumentModel::Scxml::CppDataModel: break; default: Q_UNREACHABLE(); } - QScxmlStateMachinePrivate::get(stateMachine)->parserData()->m_ownedDataModel.reset(dataModel); return dataModel; } -void QScxmlDataModelPrivate::setStateMachine(QScxmlStateMachine *stateMachine) -{ - m_stateMachine = stateMachine; -} - /*! * \fn QScxmlDataModel::setup(const QVariantMap &initialDataValues) * diff --git a/src/scxml/qscxmldatamodel.h b/src/scxml/qscxmldatamodel.h index 79ae7c1..75c55e6 100644 --- a/src/scxml/qscxmldatamodel.h +++ b/src/scxml/qscxmldatamodel.h @@ -57,6 +57,7 @@ class Q_SCXML_EXPORT QScxmlDataModel : public QObject { Q_OBJECT Q_DECLARE_PRIVATE(QScxmlDataModel) + Q_PROPERTY(QScxmlStateMachine *stateMachine READ stateMachine WRITE setStateMachine NOTIFY stateMachineChanged) public: class ForeachLoopBody @@ -67,8 +68,9 @@ public: }; public: - QScxmlDataModel(QScxmlStateMachine *stateMachine); + QScxmlDataModel(QObject *parent = 0); + void setStateMachine(QScxmlStateMachine *stateMachine); QScxmlStateMachine *stateMachine() const; virtual bool setup(const QVariantMap &initialDataValues) = 0; @@ -89,8 +91,11 @@ public: virtual bool hasScxmlProperty(const QString &name) const = 0; virtual bool setScxmlProperty(const QString &name, const QVariant &value, const QString &context) = 0; +Q_SIGNALS: + void stateMachineChanged(QScxmlStateMachine *stateMachine); + protected: - QScxmlDataModel(QScxmlDataModelPrivate &dd); + QScxmlDataModel(QScxmlDataModelPrivate &dd, QObject *parent = 0); #ifndef Q_QDOC QScxmlTableData *tableData() const; #endif // Q_QDOC diff --git a/src/scxml/qscxmldatamodel_p.h b/src/scxml/qscxmldatamodel_p.h index ee9e405..1fdcfbb 100644 --- a/src/scxml/qscxmldatamodel_p.h +++ b/src/scxml/qscxmldatamodel_p.h @@ -60,16 +60,9 @@ QT_BEGIN_NAMESPACE class QScxmlDataModelPrivate : public QObjectPrivate { public: - QScxmlDataModelPrivate(QScxmlStateMachine *stateMachine) - : m_stateMachine(stateMachine) - { - Q_ASSERT(stateMachine != Q_NULLPTR); - } + QScxmlDataModelPrivate() : m_stateMachine(Q_NULLPTR) {} - static QScxmlDataModel *instantiateDataModel(DocumentModel::Scxml::DataModelType type, - QScxmlStateMachine *stateMachine); - - void setStateMachine(QScxmlStateMachine *stateMachine); + static QScxmlDataModel *instantiateDataModel(DocumentModel::Scxml::DataModelType type); public: QScxmlStateMachine *m_stateMachine; diff --git a/src/scxml/qscxmlecmascriptdatamodel.cpp b/src/scxml/qscxmlecmascriptdatamodel.cpp index 91de2aa..54c2dfb 100644 --- a/src/scxml/qscxmlecmascriptdatamodel.cpp +++ b/src/scxml/qscxmlecmascriptdatamodel.cpp @@ -65,9 +65,8 @@ class QScxmlEcmaScriptDataModelPrivate : public QScxmlDataModelPrivate { Q_DECLARE_PUBLIC(QScxmlEcmaScriptDataModel) public: - QScxmlEcmaScriptDataModelPrivate(QScxmlStateMachine *stateMachine) - : QScxmlDataModelPrivate(stateMachine) - , jsEngine(Q_NULLPTR) + QScxmlEcmaScriptDataModelPrivate() + : jsEngine(Q_NULLPTR) {} QString evalStr(const QString &expr, const QString &context, bool *ok) @@ -356,10 +355,10 @@ private: */ /*! - * Creates a new ECMAScript data model for the state machine \a stateMachine. + * Creates a new ECMAScript data model, with the parent object \a parent. */ -QScxmlEcmaScriptDataModel::QScxmlEcmaScriptDataModel(QScxmlStateMachine *stateMachine) - : QScxmlDataModel(*(new QScxmlEcmaScriptDataModelPrivate(stateMachine))) +QScxmlEcmaScriptDataModel::QScxmlEcmaScriptDataModel(QObject *parent) + : QScxmlDataModel(*(new QScxmlEcmaScriptDataModelPrivate), parent) {} /*! diff --git a/src/scxml/qscxmlecmascriptdatamodel.h b/src/scxml/qscxmlecmascriptdatamodel.h index 37d62c8..0b0708c 100644 --- a/src/scxml/qscxmlecmascriptdatamodel.h +++ b/src/scxml/qscxmlecmascriptdatamodel.h @@ -51,7 +51,7 @@ class Q_SCXML_EXPORT QScxmlEcmaScriptDataModel: public QScxmlDataModel Q_OBJECT Q_DECLARE_PRIVATE(QScxmlEcmaScriptDataModel) public: - QScxmlEcmaScriptDataModel(QScxmlStateMachine *stateMachine); + QScxmlEcmaScriptDataModel(QObject *parent = 0); bool setup(const QVariantMap &initialDataValues) Q_DECL_OVERRIDE; diff --git a/src/scxml/qscxmlnulldatamodel.cpp b/src/scxml/qscxmlnulldatamodel.cpp index 754bc1a..c24a729 100644 --- a/src/scxml/qscxmlnulldatamodel.cpp +++ b/src/scxml/qscxmlnulldatamodel.cpp @@ -59,10 +59,6 @@ class QScxmlNullDataModelPrivate : public QScxmlDataModelPrivate }; public: - QScxmlNullDataModelPrivate(QScxmlStateMachine *stateMachine) - : QScxmlDataModelPrivate(stateMachine) - {} - bool evalBool(QScxmlExecutableContent::EvaluatorId id, bool *ok) { Q_Q(QScxmlNullDataModel); @@ -132,10 +128,10 @@ private: */ /*! - * Creates a new Qt SCXML data model for the state machine \a stateMachine. + * Creates a new Qt SCXML data model, with the parent object \a parent. */ -QScxmlNullDataModel::QScxmlNullDataModel(QScxmlStateMachine *stateMachine) - : QScxmlDataModel(*(new QScxmlNullDataModelPrivate(stateMachine))) +QScxmlNullDataModel::QScxmlNullDataModel(QObject *parent) + : QScxmlDataModel(*(new QScxmlNullDataModelPrivate), parent) {} /*! diff --git a/src/scxml/qscxmlnulldatamodel.h b/src/scxml/qscxmlnulldatamodel.h index 9f75db7..5fb28d9 100644 --- a/src/scxml/qscxmlnulldatamodel.h +++ b/src/scxml/qscxmlnulldatamodel.h @@ -50,7 +50,7 @@ class Q_SCXML_EXPORT QScxmlNullDataModel: public QScxmlDataModel Q_OBJECT Q_DECLARE_PRIVATE(QScxmlNullDataModel) public: - QScxmlNullDataModel(QScxmlStateMachine *stateMachine); + QScxmlNullDataModel(QObject *parent = 0); bool setup(const QVariantMap &initialDataValues) Q_DECL_OVERRIDE; diff --git a/src/scxml/qscxmlparser.cpp b/src/scxml/qscxmlparser.cpp index 6a91142..162b6a2 100644 --- a/src/scxml/qscxmlparser.cpp +++ b/src/scxml/qscxmlparser.cpp @@ -1007,7 +1007,9 @@ inline QScxmlInvokableService *InvokeDynamicScxmlFactory::invoke(QScxmlStateMach { auto child = QStateMachineBuilder().build(m_content.data()); - QScxmlDataModelPrivate::instantiateDataModel(m_content->root->dataModel, child); + auto dm = QScxmlDataModelPrivate::instantiateDataModel(m_content->root->dataModel); + dm->setParent(child); + child->setDataModel(dm); return finishInvoke(child, parent); } @@ -1148,8 +1150,9 @@ void QScxmlParser::instantiateDataModel(QScxmlStateMachine *stateMachine) const if (root == Q_NULLPTR) { qWarning() << "SCXML document has no root element"; } else { - QScxmlDataModel *dm = QScxmlDataModelPrivate::instantiateDataModel(root->dataModel, - stateMachine); + QScxmlDataModel *dm = QScxmlDataModelPrivate::instantiateDataModel(root->dataModel); + QScxmlStateMachinePrivate::get(stateMachine)->parserData()->m_ownedDataModel.reset(dm); + stateMachine->setDataModel(dm); if (dm == Q_NULLPTR) qWarning() << "No data-model instantiated"; } diff --git a/src/scxml/qscxmlstatemachine.cpp b/src/scxml/qscxmlstatemachine.cpp index 1939fcc..eeca441 100644 --- a/src/scxml/qscxmlstatemachine.cpp +++ b/src/scxml/qscxmlstatemachine.cpp @@ -456,6 +456,22 @@ QScxmlStateMachine::QScxmlStateMachine(QScxmlStateMachinePrivate &dd, QObject *p */ /*! + \property QScxmlStateMachine::dataModel + + \brief The data model to be used for this state machine. + + 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}. + + Changing the data model while the state machine is \c running is not + specified in the SCXML standard and leads to undefined behavior. + + \sa QScxmlDataModel, QScxmlNullDataModel, QScxmlEcmaScriptDataModel, + QScxmlCppDataModel +*/ + +/*! \enum QScxmlStateMachine::BindingMethod This enum specifies the binding method. The binding method controls the point in time @@ -520,6 +536,24 @@ bool QScxmlStateMachine::isInvoked() const } /*! + * Sets the data model for this state machine to \a model. There is a 1:1 + * relation between state machines and models. After setting the model once you + * cannot change it anymore. Any further attempts to set the model using this + * method will be ignored. + */ +void QScxmlStateMachine::setDataModel(QScxmlDataModel *model) +{ + Q_D(QScxmlStateMachine); + + if (d->m_dataModel == Q_NULLPTR && model != Q_NULLPTR) { + d->m_dataModel = model; + if (model) + model->setStateMachine(this); + emit dataModelChanged(model); + } +} + +/*! * Returns the data model used by the state machine. */ QScxmlDataModel *QScxmlStateMachine::dataModel() const diff --git a/src/scxml/qscxmlstatemachine.h b/src/scxml/qscxmlstatemachine.h index 0f7aeed..f1e7f82 100644 --- a/src/scxml/qscxmlstatemachine.h +++ b/src/scxml/qscxmlstatemachine.h @@ -75,6 +75,7 @@ class Q_SCXML_EXPORT QScxmlStateMachine: public QObject Q_OBJECT Q_ENUMS(BindingMethod) Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged) + Q_PROPERTY(QScxmlDataModel *dataModel READ dataModel WRITE setDataModel NOTIFY dataModelChanged) protected: #ifndef Q_QDOC @@ -98,6 +99,7 @@ public: bool isInvoked() const; + void setDataModel(QScxmlDataModel *model); QScxmlDataModel *dataModel() const; BindingMethod dataBinding() const; @@ -132,6 +134,7 @@ Q_SIGNALS: void reachedStableState(); void finished(); void eventOccurred(const QScxmlEvent &event); + void dataModelChanged(QScxmlDataModel *model); public Q_SLOTS: void start(); diff --git a/tools/qscxmlc/scxmlcppdumper.cpp b/tools/qscxmlc/scxmlcppdumper.cpp index b6d3ec9..be123b1 100644 --- a/tools/qscxmlc/scxmlcppdumper.cpp +++ b/tools/qscxmlc/scxmlcppdumper.cpp @@ -320,12 +320,12 @@ protected: case Scxml::NullDataModel: clazz.classFields << QStringLiteral("QScxmlNullDataModel dataModel;"); clazz.implIncludes << QStringLiteral("QScxmlNullDataModel"); - clazz.constructor.initializer << QStringLiteral("dataModel(&stateMachine)"); + clazz.init.impl << QStringLiteral("stateMachine.setDataModel(&dataModel);"); break; case Scxml::JSDataModel: clazz.classFields << QStringLiteral("QScxmlEcmaScriptDataModel dataModel;"); clazz.implIncludes << QStringLiteral("QScxmlEcmaScriptDataModel"); - clazz.constructor.initializer << QStringLiteral("dataModel(&stateMachine)"); + clazz.init.impl << QStringLiteral("stateMachine.setDataModel(&dataModel);"); break; case Scxml::CppDataModel: clazz.dataModelClassName = node->cppDataModelClassName; |