diff options
author | Ulf Hermann <ulf.hermann@theqtcompany.com> | 2016-03-10 11:21:38 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@theqtcompany.com> | 2016-03-30 11:56:37 +0000 |
commit | 703c6a6bee98c5d316de408867982b1684ad550b (patch) | |
tree | 8e0b8c5fa5fb452462fb3dae7cf2639e8682bcf3 /src | |
parent | 2f2e803aa720e8a60b18eab7e4c41e67cd449457 (diff) |
Automatically initialize state machines when starting
This removes the need to call init() before start(), making the API
much more intuitive. We also expose the initial values as a Q_PROPERTY
so that they can be set in a declarative way from QML.
Change-Id: If3c995c956764018bcab7b6caa8485e32bba6f1a
Reviewed-by: Erik Verbruggen <erik.verbruggen@theqtcompany.com>
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@theqtcompany.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/imports/scxmlstatemachine/statemachineloader.cpp | 1 | ||||
-rw-r--r-- | src/scxml/qscxmlinvokableservice.cpp | 3 | ||||
-rw-r--r-- | src/scxml/qscxmlstatemachine.cpp | 68 | ||||
-rw-r--r-- | src/scxml/qscxmlstatemachine.h | 11 | ||||
-rw-r--r-- | src/scxml/qscxmlstatemachine_p.h | 2 |
5 files changed, 72 insertions, 13 deletions
diff --git a/src/imports/scxmlstatemachine/statemachineloader.cpp b/src/imports/scxmlstatemachine/statemachineloader.cpp index ffdfca9..2062ab6 100644 --- a/src/imports/scxmlstatemachine/statemachineloader.cpp +++ b/src/imports/scxmlstatemachine/statemachineloader.cpp @@ -135,7 +135,6 @@ bool QScxmlStateMachineLoader::parse(const QUrl &filename) m_stateMachine = QScxmlStateMachine::fromData(&buf, filename.toString()); m_stateMachine->setParent(this); - m_stateMachine->init(); if (m_stateMachine->parseErrors().isEmpty()) { emit stateMachineChanged(); diff --git a/src/scxml/qscxmlinvokableservice.cpp b/src/scxml/qscxmlinvokableservice.cpp index f9f2c67..ca64cdb 100644 --- a/src/scxml/qscxmlinvokableservice.cpp +++ b/src/scxml/qscxmlinvokableservice.cpp @@ -245,7 +245,8 @@ bool QScxmlInvokableScxml::start() return false; m_stateMachine->setSessionId(id); - if (m_stateMachine->init(data)) { + m_stateMachine->setInitialValues(data); + if (m_stateMachine->init()) { qCDebug(qscxmlLog) << parentStateMachine() << "starting" << m_stateMachine; m_stateMachine->start(); return true; diff --git a/src/scxml/qscxmlstatemachine.cpp b/src/scxml/qscxmlstatemachine.cpp index eeca441..2522ade 100644 --- a/src/scxml/qscxmlstatemachine.cpp +++ b/src/scxml/qscxmlstatemachine.cpp @@ -223,6 +223,7 @@ QScxmlStateMachinePrivate::QScxmlStateMachinePrivate() : QObjectPrivate() , m_sessionId(QScxmlStateMachine::generateSessionId(QStringLiteral("session-"))) , m_isInvoked(false) + , m_isInitialized(false) , m_dataModel(Q_NULLPTR) , m_dataBinding(QScxmlStateMachine::EarlyBinding) , m_executionEngine(Q_NULLPTR) @@ -464,14 +465,32 @@ QScxmlStateMachine::QScxmlStateMachine(QScxmlStateMachinePrivate &dd, QObject *p \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. + Changing the data model when the state machine has been \c initialized is + not specified in the SCXML standard and leads to undefined behavior. \sa QScxmlDataModel, QScxmlNullDataModel, QScxmlEcmaScriptDataModel, QScxmlCppDataModel */ /*! + \property QScxmlStateMachine::initialized + + \brief Whether the state machine has been initialized. + + It is \c true if the state machine has been initialized, \c false otherwise. + + \sa QScxmlStateMachine::init(), QScxmlDataModel +*/ + +/*! + \property QScxmlStateMachine::initialValues + + \brief The initial values to be used for setting up the data model. + + \sa QScxmlStateMachine::init(), QScxmlDataModel +*/ + +/*! \enum QScxmlStateMachine::BindingMethod This enum specifies the binding method. The binding method controls the point in time @@ -535,6 +554,12 @@ bool QScxmlStateMachine::isInvoked() const return d->m_isInvoked; } +bool QScxmlStateMachine::isInitialized() const +{ + Q_D(const QScxmlStateMachine); + return d->m_isInitialized; +} + /*! * 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 @@ -990,25 +1015,31 @@ void QScxmlStateMachine::setScxmlEventFilter(QScxmlEventFilter *newFilter) * Initializes the state machine. * * State machine initialization consists of calling QScxmlDataModel::setup(), setting the initial - * values for \c <data> elements, and executing any \c <script> tags of the \c <scxml> tag. - * - * \a initialDataValues contains initial values for data elements from the \c <invoke> tag. - * These values will be used instead of the initial values from the \c <data> elements. + * values for \c <data> elements, and executing any \c <script> tags of the \c <scxml> tag. The + * initial data values are taken from the \c initialValues property. * * Returns \c false if parse errors occur or if any of the initialization steps fail. * Returns \c true otherwise. */ -bool QScxmlStateMachine::init(const QVariantMap &initialDataValues) +bool QScxmlStateMachine::init() { Q_D(QScxmlStateMachine); + if (d->m_isInitialized) + return false; + if (!parseErrors().isEmpty()) return false; - if (!dataModel() || !dataModel()->setup(initialDataValues)) + if (!dataModel() || !dataModel()->setup(d->m_initialValues)) + return false; + + if (!d->executeInitialSetup()) return false; - return d->executeInitialSetup(); + d->m_isInitialized = true; + emit initializedChanged(true); + return true; } /*! @@ -1036,6 +1067,21 @@ void QScxmlStateMachine::setRunning(bool running) stop(); } +QVariantMap QScxmlStateMachine::initialValues() +{ + Q_D(const QScxmlStateMachine); + return d->m_initialValues; +} + +void QScxmlStateMachine::setInitialValues(const QVariantMap &initialValues) +{ + Q_D(QScxmlStateMachine); + if (initialValues != d->m_initialValues) { + d->m_initialValues = initialValues; + emit initialValuesChanged(initialValues); + } +} + /*! * Returns the name of the state machine as set by the \e name attribute of the \c <scxml> tag. */ @@ -1237,6 +1283,10 @@ void QScxmlStateMachine::start() if (!parseErrors().isEmpty()) return; + // Failure to initialize doesn't prevent start(). See w3c-ecma/test487 in the scion test suite. + if (!isInitialized() && !init()) + qCDebug(qscxmlLog) << this << "cannot be initialized on start(). Starting anyway ..."; + d->m_qStateMachine->start(); } diff --git a/src/scxml/qscxmlstatemachine.h b/src/scxml/qscxmlstatemachine.h index f1e7f82..0037fef 100644 --- a/src/scxml/qscxmlstatemachine.h +++ b/src/scxml/qscxmlstatemachine.h @@ -75,7 +75,9 @@ class Q_SCXML_EXPORT QScxmlStateMachine: public QObject Q_OBJECT Q_ENUMS(BindingMethod) Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged) + Q_PROPERTY(bool initialized READ isInitialized NOTIFY initializedChanged) Q_PROPERTY(QScxmlDataModel *dataModel READ dataModel WRITE setDataModel NOTIFY dataModelChanged) + Q_PROPERTY(QVariantMap initialValues READ initialValues WRITE setInitialValues NOTIFY initialValuesChanged) protected: #ifndef Q_QDOC @@ -98,17 +100,19 @@ public: static QString generateSessionId(const QString &prefix); bool isInvoked() const; + bool isInitialized() const; void setDataModel(QScxmlDataModel *model); QScxmlDataModel *dataModel() const; BindingMethod dataBinding() const; - bool init(const QVariantMap &initialDataValues = QVariantMap()); - bool isRunning() const; void setRunning(bool running); + QVariantMap initialValues(); + void setInitialValues(const QVariantMap &initialValues); + QString name() const; QStringList stateNames(bool compress = true) const; QStringList activeStateNames(bool compress = true) const; @@ -135,10 +139,13 @@ Q_SIGNALS: void finished(); void eventOccurred(const QScxmlEvent &event); void dataModelChanged(QScxmlDataModel *model); + void initialValuesChanged(const QVariantMap &initialValues); + void initializedChanged(bool initialized); public Q_SLOTS: void start(); void stop(); + bool init(); protected: // methods for friends: friend QScxmlDataModel; diff --git a/src/scxml/qscxmlstatemachine_p.h b/src/scxml/qscxmlstatemachine_p.h index 5f2fff1..99334cf 100644 --- a/src/scxml/qscxmlstatemachine_p.h +++ b/src/scxml/qscxmlstatemachine_p.h @@ -139,6 +139,8 @@ public: public: // types & data fields: QString m_sessionId; bool m_isInvoked; + bool m_isInitialized; + QVariantMap m_initialValues; QScxmlDataModel *m_dataModel; QScxmlStateMachine::BindingMethod m_dataBinding; QScxmlExecutableContent::QScxmlExecutionEngine *m_executionEngine; |