summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@theqtcompany.com>2016-03-10 11:21:38 +0100
committerUlf Hermann <ulf.hermann@theqtcompany.com>2016-03-30 11:56:37 +0000
commit703c6a6bee98c5d316de408867982b1684ad550b (patch)
tree8e0b8c5fa5fb452462fb3dae7cf2639e8682bcf3 /src
parent2f2e803aa720e8a60b18eab7e4c41e67cd449457 (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.cpp1
-rw-r--r--src/scxml/qscxmlinvokableservice.cpp3
-rw-r--r--src/scxml/qscxmlstatemachine.cpp68
-rw-r--r--src/scxml/qscxmlstatemachine.h11
-rw-r--r--src/scxml/qscxmlstatemachine_p.h2
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;