summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/scxml/mediaplayer-widgets-static/doc/src/mediaplayer-widgets-static.qdoc2
-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
-rw-r--r--tests/auto/statemachine/tst_statemachine.cpp1
7 files changed, 73 insertions, 15 deletions
diff --git a/examples/scxml/mediaplayer-widgets-static/doc/src/mediaplayer-widgets-static.qdoc b/examples/scxml/mediaplayer-widgets-static/doc/src/mediaplayer-widgets-static.qdoc
index 562a7af..9d1ae39 100644
--- a/examples/scxml/mediaplayer-widgets-static/doc/src/mediaplayer-widgets-static.qdoc
+++ b/examples/scxml/mediaplayer-widgets-static/doc/src/mediaplayer-widgets-static.qdoc
@@ -53,7 +53,7 @@
\quotefromfile mediaplayer-widgets-static/mediaplayer-widgets-static.cpp
\skipto mediaplayer.h
- \printuntil machine.init
+ \printuntil MainWindow mainWindow
To be notified when a state machine sends out an event, we connect to the
corresponding signals. The media player state machine will send out events
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;
diff --git a/tests/auto/statemachine/tst_statemachine.cpp b/tests/auto/statemachine/tst_statemachine.cpp
index 913ec86..7a269b2 100644
--- a/tests/auto/statemachine/tst_statemachine.cpp
+++ b/tests/auto/statemachine/tst_statemachine.cpp
@@ -112,7 +112,6 @@ void tst_StateMachine::activeStateNames()
QSignalSpy stableStateSpy(stateMachine.data(), SIGNAL(reachedStableState()));
- stateMachine->init();
stateMachine->start();
stableStateSpy.wait(5000);