summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2017-04-21 11:09:50 +0200
committerLiang Qi <liang.qi@qt.io>2017-04-21 11:09:50 +0200
commitb490e1b782ac28a82d7902f926f6e041ede179ca (patch)
treeb1d8866ef27e5b2dbcdc71c6d3fbc9678a37b639
parent45e2a4826705c7489b77d28ae706474b94022624 (diff)
parent384cb7975d9caa4e508454d811d2e391763e5981 (diff)
Merge remote-tracking branch 'origin/5.9' into dev
-rw-r--r--examples/scxml/ftpclient/main.cpp3
-rw-r--r--examples/scxml/ftpclient/simpleftp.scxml2
-rw-r--r--src/imports/scxmlstatemachine/eventconnection.cpp39
-rw-r--r--src/imports/scxmlstatemachine/invokedservices.cpp33
-rw-r--r--src/imports/scxmlstatemachine/plugin.cpp4
-rw-r--r--src/imports/scxmlstatemachine/statemachineloader.cpp29
-rw-r--r--src/imports/scxmlstatemachine/statemachineloader_p.h2
-rw-r--r--src/scxml/doc/qtscxml-instantiating-state-machines.qdoc4
-rw-r--r--src/scxml/qscxmlcompiler.cpp20
-rw-r--r--src/scxml/qscxmlcompiler_p.h14
-rw-r--r--src/scxml/qscxmldatamodel.h4
-rw-r--r--src/scxml/qscxmlecmascriptdatamodel.cpp4
-rw-r--r--src/scxml/qscxmlecmascriptplatformproperties.cpp2
-rw-r--r--src/scxml/qscxmlecmascriptplatformproperties_p.h4
-rw-r--r--src/scxml/qscxmlerror.h2
-rw-r--r--src/scxml/qscxmlevent.cpp6
-rw-r--r--src/scxml/qscxmlevent.h4
-rw-r--r--src/scxml/qscxmlevent_p.h2
-rw-r--r--src/scxml/qscxmlexecutablecontent_p.h2
-rw-r--r--src/scxml/qscxmlglobals_p.h2
-rw-r--r--src/scxml/qscxmlinvokableservice.cpp29
-rw-r--r--src/scxml/qscxmlinvokableservice_p.h5
-rw-r--r--src/scxml/qscxmlstatemachine.cpp259
-rw-r--r--src/scxml/qscxmlstatemachine.h10
-rw-r--r--src/scxml/qscxmlstatemachineinfo_p.h2
-rw-r--r--src/scxml/qscxmltabledata.h2
-rw-r--r--tests/3rdparty/scion-tests/scxml-test-framework/test/content-expr-in-send/test0.txml.json7
-rw-r--r--tests/3rdparty/scion-tests/scxml-test-framework/test/content-expr-in-send/test0.txml.scxml16
-rw-r--r--tests/auto/scion/tst_scion.cpp103
-rw-r--r--tests/auto/statemachine/invoke.scxml73
-rw-r--r--tests/auto/statemachine/tst_statemachine.cpp22
-rw-r--r--tests/auto/statemachine/tst_statemachine.qrc1
-rw-r--r--tools/tools.pro2
33 files changed, 612 insertions, 101 deletions
diff --git a/examples/scxml/ftpclient/main.cpp b/examples/scxml/ftpclient/main.cpp
index 25102d2..8dd0c16 100644
--- a/examples/scxml/ftpclient/main.cpp
+++ b/examples/scxml/ftpclient/main.cpp
@@ -89,7 +89,8 @@ int main(int argc, char *argv[])
// Translate commands from the state machine into FTP control messages.
ftpClient.connectToEvent("submit.cmd", &controlChannel,
[&controlChannel](const QScxmlEvent &event) {
- controlChannel.command(event.name().mid(11).toUtf8(), event.data().toByteArray());
+ controlChannel.command(event.name().mid(11).toUtf8(),
+ event.data().toMap()["params"].toByteArray());
});
// Commands to be sent
diff --git a/examples/scxml/ftpclient/simpleftp.scxml b/examples/scxml/ftpclient/simpleftp.scxml
index 79eb7b9..7d57040 100644
--- a/examples/scxml/ftpclient/simpleftp.scxml
+++ b/examples/scxml/ftpclient/simpleftp.scxml
@@ -75,7 +75,7 @@
<state id="W">
<onentry>
<send eventexpr="&quot;submit.&quot; + _event.name">
- <content expr="_event.data"/>
+ <param name="params" expr="_event.data"/>
</send>
</onentry>
diff --git a/src/imports/scxmlstatemachine/eventconnection.cpp b/src/imports/scxmlstatemachine/eventconnection.cpp
index 9803a9a..2a073bd 100644
--- a/src/imports/scxmlstatemachine/eventconnection.cpp
+++ b/src/imports/scxmlstatemachine/eventconnection.cpp
@@ -41,6 +41,45 @@
QT_BEGIN_NAMESPACE
+/*!
+ \qmltype EventConnection
+ \instantiates QScxmlEventConnection
+ \inqmlmodule QtScxml
+ \since QtScxml 5.8
+
+ \brief Connects to events sent out by state machines.
+
+ To receive a notification when a state machine sends out an event, a
+ connection can be created to the corresponding signal.
+*/
+
+/*!
+ \qmlproperty stringlist EventConnection::events
+
+ The list of SCXML event specifiers that describe the events to listen for.
+
+ Even though spaces are allowed in event specifications in SCXML documents,
+ they are not allowed in this list. However, the list can contain multiple
+ specifiers, to the same effect.
+*/
+
+/*!
+ \qmlproperty ScxmlStateMachine EventConnection::stateMachine
+
+ The state machine that sends out the event.
+*/
+
+/*!
+ \qmlsignal EventConnection::occurred(event)
+
+ This signal is emitted when the event \a event occurrs.
+
+ The corresponding signal handler is \c onOccurred.
+
+ \sa QScxmlEvent
+*/
+
+
QScxmlEventConnection::QScxmlEventConnection(QObject *parent) :
QObject(parent), m_stateMachine(nullptr)
{
diff --git a/src/imports/scxmlstatemachine/invokedservices.cpp b/src/imports/scxmlstatemachine/invokedservices.cpp
index 93c97d6..6011557 100644
--- a/src/imports/scxmlstatemachine/invokedservices.cpp
+++ b/src/imports/scxmlstatemachine/invokedservices.cpp
@@ -42,10 +42,31 @@
QT_BEGIN_NAMESPACE
+/*!
+ \qmltype InvokedServices
+ \instantiates QScxmlInvokedServices
+ \inqmlmodule QtScxml
+ \since QtScxml 5.8
+
+ \brief Provices access to the services invoked by state machines.
+
+ Makes the invoked services easily accessible by their names, without
+ constantly iterating through QScxmlStateMachine::invokedServices.
+
+ The services are called from state machines via the mechanism described in
+ \l{SCXML Specification - 6.4 <invoke>}.
+*/
+
QScxmlInvokedServices::QScxmlInvokedServices(QObject *parent) : QObject(parent)
{
}
+/*!
+ \qmlproperty var InvokedServices::children
+
+ The services invoked by the state machine.
+*/
+
QVariantMap QScxmlInvokedServices::children()
{
QVariantMap ret;
@@ -61,6 +82,12 @@ void QScxmlInvokedServices::classBegin()
{
}
+/*!
+ \qmlproperty ScxmlStateMachine InvokedServices::stateMachine
+
+ The state machine that invoked the services.
+*/
+
QScxmlStateMachine *QScxmlInvokedServices::stateMachine() const
{
return m_stateMachine;
@@ -81,6 +108,12 @@ void QScxmlInvokedServices::setStateMachine(QScxmlStateMachine *stateMachine)
}
}
+/*!
+ \qmlproperty list<QtObject> InvokedServices::qmlChildren
+
+ A list of additional QtObject types nested in this type.
+*/
+
QQmlListProperty<QObject> QScxmlInvokedServices::qmlChildren()
{
return QQmlListProperty<QObject>(this, m_qmlChildren);
diff --git a/src/imports/scxmlstatemachine/plugin.cpp b/src/imports/scxmlstatemachine/plugin.cpp
index 6842846..b662491 100644
--- a/src/imports/scxmlstatemachine/plugin.cpp
+++ b/src/imports/scxmlstatemachine/plugin.cpp
@@ -43,7 +43,7 @@
#include "statemachineextended_p.h"
#include "invokedservices_p.h"
-#include <QQmlExtensionPlugin>
+#include <qqmlextensionplugin.h>
#include <qqml.h>
QT_BEGIN_NAMESPACE
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
class QScxmlStateMachinePlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Scxml/1.0")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
void registerTypes(const char *uri)
diff --git a/src/imports/scxmlstatemachine/statemachineloader.cpp b/src/imports/scxmlstatemachine/statemachineloader.cpp
index 42048bf..946988f 100644
--- a/src/imports/scxmlstatemachine/statemachineloader.cpp
+++ b/src/imports/scxmlstatemachine/statemachineloader.cpp
@@ -40,11 +40,11 @@
#include "statemachineloader_p.h"
#include <QtScxml/qscxmlstatemachine.h>
-#include <QQmlContext>
-#include <QQmlEngine>
-#include <QQmlInfo>
-#include <QQmlFile>
-#include <QBuffer>
+#include <qqmlcontext.h>
+#include <qqmlengine.h>
+#include <qqmlinfo.h>
+#include <qqmlfile.h>
+#include <qbuffer.h>
/*!
\qmltype StateMachineLoader
@@ -56,18 +56,6 @@
\since QtScxml 5.7
*/
-/*!
- \qmlsignal StateMachineLoader::sourceChanged()
- This signal is emitted when the user changes the source URL for the SCXML document.
-*/
-
-/*!
- \qmlsignal StateMachineLoader::stateMachineChanged()
-
- This signal is emitted when the stateMachine property changes. That is, when
- a new state machine is loaded or when the old one becomes invalid.
-*/
-
QScxmlStateMachineLoader::QScxmlStateMachineLoader(QObject *parent)
: QObject(parent)
, m_dataModel(Q_NULLPTR)
@@ -77,7 +65,7 @@ QScxmlStateMachineLoader::QScxmlStateMachineLoader(QObject *parent)
}
/*!
- \qmlproperty QObject StateMachineLoader::stateMachine
+ \qmlproperty ScxmlStateMachine StateMachineLoader::stateMachine
The state machine instance.
*/
@@ -87,9 +75,10 @@ QT_PREPEND_NAMESPACE(QScxmlStateMachine) *QScxmlStateMachineLoader::stateMachine
}
/*!
- \qmlproperty string StateMachineLoader::source
+ \qmlproperty url StateMachineLoader::source
- The url of the SCXML document to load. Only synchronously accessible URLs are supported.
+ The URL of the SCXML document to load. Only synchronously accessible URLs
+ are supported.
*/
QUrl QScxmlStateMachineLoader::source()
{
diff --git a/src/imports/scxmlstatemachine/statemachineloader_p.h b/src/imports/scxmlstatemachine/statemachineloader_p.h
index 6eaf6f4..a4ee3f1 100644
--- a/src/imports/scxmlstatemachine/statemachineloader_p.h
+++ b/src/imports/scxmlstatemachine/statemachineloader_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <QUrl>
+#include <QtCore/qurl.h>
#include <QtScxml/qscxmlstatemachine.h>
#include <private/qqmlengine_p.h>
diff --git a/src/scxml/doc/qtscxml-instantiating-state-machines.qdoc b/src/scxml/doc/qtscxml-instantiating-state-machines.qdoc
index c431653..0737dff 100644
--- a/src/scxml/doc/qtscxml-instantiating-state-machines.qdoc
+++ b/src/scxml/doc/qtscxml-instantiating-state-machines.qdoc
@@ -46,11 +46,11 @@
import QtScxml 5.8
Item {
- property QtObject stateMachine: scxmlLoader.stateMachine
+ property StateMachine stateMachine: scxmlLoader.stateMachine
StateMachineLoader {
id: scxmlLoader
- filename: "statemachine.scxml"
+ source: "statemachine.scxml"
}
}
\endqml
diff --git a/src/scxml/qscxmlcompiler.cpp b/src/scxml/qscxmlcompiler.cpp
index b8434c6..626015b 100644
--- a/src/scxml/qscxmlcompiler.cpp
+++ b/src/scxml/qscxmlcompiler.cpp
@@ -40,13 +40,13 @@
#include "qscxmlcompiler_p.h"
#include "qscxmlexecutablecontent_p.h"
-#include <QXmlStreamReader>
-#include <QLoggingCategory>
-#include <QJsonDocument>
-#include <QJsonObject>
-#include <QFile>
-#include <QVector>
-#include <QString>
+#include <qxmlstream.h>
+#include <qloggingcategory.h>
+#include <qjsondocument.h>
+#include <qjsonobject.h>
+#include <qfile.h>
+#include <qvector.h>
+#include <qstring.h>
#ifndef BUILD_QSCXMLC
#include "qscxmlecmascriptdatamodel.h"
@@ -56,12 +56,6 @@
#include "qscxmlstatemachine.h"
#include "qscxmltabledata_p.h"
-#include <QState>
-#include <QHistoryState>
-#include <QEventTransition>
-#include <QSignalTransition>
-#include <QJSValue>
-#include <private/qabstracttransition_p.h>
#include <private/qmetaobjectbuilder_p.h>
#endif // BUILD_QSCXMLC
diff --git a/src/scxml/qscxmlcompiler_p.h b/src/scxml/qscxmlcompiler_p.h
index f74e282..d3e25df 100644
--- a/src/scxml/qscxmlcompiler_p.h
+++ b/src/scxml/qscxmlcompiler_p.h
@@ -53,13 +53,13 @@
#include "qscxmlcompiler.h"
-#include <QDir>
-#include <QFileInfo>
-#include <QSet>
-#include <QSharedPointer>
-#include <QStringList>
-#include <QString>
-#include <QXmlStreamAttributes>
+#include <QtCore/qdir.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qset.h>
+#include <QtCore/qsharedpointer.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qxmlstream.h>
QT_BEGIN_NAMESPACE
diff --git a/src/scxml/qscxmldatamodel.h b/src/scxml/qscxmldatamodel.h
index d34a84a..bb86c81 100644
--- a/src/scxml/qscxmldatamodel.h
+++ b/src/scxml/qscxmldatamodel.h
@@ -42,8 +42,8 @@
#include <QtScxml/qscxmlexecutablecontent.h>
-#include <QVariant>
-#include <QVector>
+#include <QtCore/qvariant.h>
+#include <QtCore/qvector.h>
QT_BEGIN_NAMESPACE
diff --git a/src/scxml/qscxmlecmascriptdatamodel.cpp b/src/scxml/qscxmlecmascriptdatamodel.cpp
index e517989..a12bb30 100644
--- a/src/scxml/qscxmlecmascriptdatamodel.cpp
+++ b/src/scxml/qscxmlecmascriptdatamodel.cpp
@@ -44,8 +44,8 @@
#include "qscxmlstatemachine_p.h"
#include "qscxmldatamodel_p.h"
-#include <QJSEngine>
-#include <QJsonDocument>
+#include <qjsengine.h>
+#include <qjsondocument.h>
#include <QtQml/private/qjsvalue_p.h>
#include <QtQml/private/qv4scopedvalue_p.h>
diff --git a/src/scxml/qscxmlecmascriptplatformproperties.cpp b/src/scxml/qscxmlecmascriptplatformproperties.cpp
index 41e27b5..c4bb195 100644
--- a/src/scxml/qscxmlecmascriptplatformproperties.cpp
+++ b/src/scxml/qscxmlecmascriptplatformproperties.cpp
@@ -40,7 +40,7 @@
#include "qscxmlecmascriptplatformproperties_p.h"
#include "qscxmlstatemachine.h"
-#include <QJSEngine>
+#include <qjsengine.h>
QT_BEGIN_NAMESPACE
class QScxmlPlatformProperties::Data
diff --git a/src/scxml/qscxmlecmascriptplatformproperties_p.h b/src/scxml/qscxmlecmascriptplatformproperties_p.h
index cf1c4a9..53babeb 100644
--- a/src/scxml/qscxmlecmascriptplatformproperties_p.h
+++ b/src/scxml/qscxmlecmascriptplatformproperties_p.h
@@ -53,8 +53,8 @@
#include "qscxmlglobals.h"
-#include <QJSValue>
-#include <QObject>
+#include <QtQml/qjsvalue.h>
+#include <QtCore/qobject.h>
QT_BEGIN_NAMESPACE
diff --git a/src/scxml/qscxmlerror.h b/src/scxml/qscxmlerror.h
index cae249e..cc8d53b 100644
--- a/src/scxml/qscxmlerror.h
+++ b/src/scxml/qscxmlerror.h
@@ -43,7 +43,7 @@
#include <QtScxml/qscxmlglobals.h>
#include <QtCore/qobjectdefs.h>
-#include <QString>
+#include <QtCore/qstring.h>
QT_BEGIN_NAMESPACE
diff --git a/src/scxml/qscxmlevent.cpp b/src/scxml/qscxmlevent.cpp
index 6da52d7..d8c7c1d 100644
--- a/src/scxml/qscxmlevent.cpp
+++ b/src/scxml/qscxmlevent.cpp
@@ -41,8 +41,8 @@
#include "qscxmlevent_p.h"
#include "qscxmlstatemachine_p.h"
-#include <QJsonDocument>
-#include <QJsonObject>
+#include <qjsondocument.h>
+#include <qjsonobject.h>
QT_BEGIN_NAMESPACE
@@ -67,7 +67,7 @@ QScxmlEvent *QScxmlEventBuilder::buildEvent()
if (contentExpr == NoEvaluator) {
data = contents;
} else {
- data = dataModel->evaluateToString(contentExpr, &ok);
+ data = dataModel->evaluateToVariant(contentExpr, &ok);
}
if (!ok) {
// expr evaluation failure results in the data property of the event being set to null. See e.g. test528.
diff --git a/src/scxml/qscxmlevent.h b/src/scxml/qscxmlevent.h
index 267f5ec..e07da7a 100644
--- a/src/scxml/qscxmlevent.h
+++ b/src/scxml/qscxmlevent.h
@@ -42,8 +42,8 @@
#include <QtScxml/qscxmlglobals.h>
-#include <QStringList>
-#include <QVariantList>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qvariant.h>
QT_BEGIN_NAMESPACE
diff --git a/src/scxml/qscxmlevent_p.h b/src/scxml/qscxmlevent_p.h
index 15bd6fa..f5f5164 100644
--- a/src/scxml/qscxmlevent_p.h
+++ b/src/scxml/qscxmlevent_p.h
@@ -58,7 +58,7 @@
#include <QtScxml/qscxmlstatemachine.h>
#endif
-#include <QAtomicInt>
+#include <QtCore/qatomic.h>
QT_BEGIN_NAMESPACE
diff --git a/src/scxml/qscxmlexecutablecontent_p.h b/src/scxml/qscxmlexecutablecontent_p.h
index cfaec55..707e8cd 100644
--- a/src/scxml/qscxmlexecutablecontent_p.h
+++ b/src/scxml/qscxmlexecutablecontent_p.h
@@ -54,7 +54,7 @@
#include <QtScxml/qscxmlexecutablecontent.h>
#include <QtScxml/private/qscxmltabledata_p.h>
#include <QtScxml/private/qscxmlcompiler_p.h>
-#include <QTextStream>
+#include <QtCore/qtextstream.h>
#ifndef BUILD_QSCXMLC
#include <QtScxml/qscxmldatamodel.h>
diff --git a/src/scxml/qscxmlglobals_p.h b/src/scxml/qscxmlglobals_p.h
index 559636b..fac74dc 100644
--- a/src/scxml/qscxmlglobals_p.h
+++ b/src/scxml/qscxmlglobals_p.h
@@ -53,7 +53,7 @@
#include "qscxmlglobals.h"
-#include <QLoggingCategory>
+#include <QtCore/qloggingcategory.h>
QT_BEGIN_NAMESPACE
diff --git a/src/scxml/qscxmlinvokableservice.cpp b/src/scxml/qscxmlinvokableservice.cpp
index a897eaa..4cf9bd9 100644
--- a/src/scxml/qscxmlinvokableservice.cpp
+++ b/src/scxml/qscxmlinvokableservice.cpp
@@ -319,7 +319,7 @@ QVariantMap QScxmlInvokableServicePrivate::calculateData(
QScxmlScxmlService::~QScxmlScxmlService()
{
- delete stateMachine;
+ delete m_stateMachine;
}
/*!
@@ -329,7 +329,7 @@ QScxmlScxmlService::~QScxmlScxmlService()
QScxmlScxmlService::QScxmlScxmlService(QScxmlStateMachine *stateMachine,
QScxmlStateMachine *parentStateMachine,
QScxmlInvokableServiceFactory *factory)
- : QScxmlInvokableService(parentStateMachine, factory), stateMachine(stateMachine)
+ : QScxmlInvokableService(parentStateMachine, factory), m_stateMachine(stateMachine)
{
QScxmlStateMachinePrivate::get(stateMachine)->m_parentStateMachine = parentStateMachine;
}
@@ -340,7 +340,7 @@ QScxmlScxmlService::QScxmlScxmlService(QScxmlStateMachine *stateMachine,
bool QScxmlScxmlService::start()
{
Q_D(QScxmlInvokableService);
- qCDebug(qscxmlLog) << parentStateMachine() << "preparing to start" << stateMachine;
+ qCDebug(qscxmlLog) << parentStateMachine() << "preparing to start" << m_stateMachine;
const QScxmlInvokableServiceFactory *factory
= qobject_cast<QScxmlInvokableServiceFactory *>(parent());
@@ -355,15 +355,15 @@ bool QScxmlScxmlService::start()
if (!ok)
return false;
- QScxmlStateMachinePrivate::get(stateMachine)->m_sessionId = id;
- stateMachine->setInitialValues(data);
- if (stateMachine->init()) {
- qCDebug(qscxmlLog) << parentStateMachine() << "starting" << stateMachine;
- stateMachine->start();
+ QScxmlStateMachinePrivate::get(m_stateMachine)->m_sessionId = id;
+ m_stateMachine->setInitialValues(data);
+ if (m_stateMachine->init()) {
+ qCDebug(qscxmlLog) << parentStateMachine() << "starting" << m_stateMachine;
+ m_stateMachine->start();
return true;
}
- qCDebug(qscxmlLog) << parentStateMachine() << "failed to start" << stateMachine;
+ qCDebug(qscxmlLog) << parentStateMachine() << "failed to start" << m_stateMachine;
return false;
}
@@ -372,7 +372,7 @@ bool QScxmlScxmlService::start()
*/
QString QScxmlScxmlService::id() const
{
- return stateMachine->sessionId();
+ return m_stateMachine->sessionId();
}
/*!
@@ -380,7 +380,7 @@ QString QScxmlScxmlService::id() const
*/
QString QScxmlScxmlService::name() const
{
- return stateMachine->name();
+ return m_stateMachine->name();
}
/*!
@@ -388,7 +388,12 @@ QString QScxmlScxmlService::name() const
*/
void QScxmlScxmlService::postEvent(QScxmlEvent *event)
{
- QScxmlStateMachinePrivate::get(stateMachine)->postEvent(event);
+ QScxmlStateMachinePrivate::get(m_stateMachine)->postEvent(event);
+}
+
+QScxmlStateMachine *QScxmlScxmlService::stateMachine() const
+{
+ return m_stateMachine;
}
/*!
diff --git a/src/scxml/qscxmlinvokableservice_p.h b/src/scxml/qscxmlinvokableservice_p.h
index e2a9e7b..37ca870 100644
--- a/src/scxml/qscxmlinvokableservice_p.h
+++ b/src/scxml/qscxmlinvokableservice_p.h
@@ -88,6 +88,7 @@ class Q_SCXML_EXPORT QScxmlScxmlService: public QScxmlInvokableService
{
Q_OBJECT
Q_DECLARE_PRIVATE(QScxmlInvokableService)
+ Q_PROPERTY(QScxmlStateMachine *stateMachine READ stateMachine CONSTANT)
public:
QScxmlScxmlService(QScxmlStateMachine *stateMachine,
QScxmlStateMachine *parentStateMachine,
@@ -98,8 +99,10 @@ public:
QString id() const Q_DECL_OVERRIDE;
QString name() const Q_DECL_OVERRIDE;
void postEvent(QScxmlEvent *event) Q_DECL_OVERRIDE;
+ QScxmlStateMachine *stateMachine() const;
- QScxmlStateMachine *stateMachine;
+private:
+ QScxmlStateMachine *m_stateMachine;
};
class QScxmlStaticScxmlServiceFactoryPrivate : public QScxmlInvokableServiceFactoryPrivate
diff --git a/src/scxml/qscxmlstatemachine.cpp b/src/scxml/qscxmlstatemachine.cpp
index 6bc7ab5..e57630f 100644
--- a/src/scxml/qscxmlstatemachine.cpp
+++ b/src/scxml/qscxmlstatemachine.cpp
@@ -43,15 +43,13 @@
#include "qscxmlinvokableservice.h"
#include "qscxmldatamodel_p.h"
-#include <QAbstractState>
-#include <QAbstractTransition>
-#include <QFile>
-#include <QHash>
-#include <QJSEngine>
-#include <QLoggingCategory>
-#include <QString>
-#include <QTimer>
-#include <QThread>
+#include <qfile.h>
+#include <qhash.h>
+#include <qjsengine.h>
+#include <qloggingcategory.h>
+#include <qstring.h>
+#include <qtimer.h>
+#include <qthread.h>
#include <functional>
@@ -81,6 +79,22 @@ Q_LOGGING_CATEGORY(scxmlLog, "scxml.statemachine")
*/
/*!
+ \qmltype ScxmlStateMachine
+ \instantiates QScxmlStateMachine
+ \inqmlmodule QtScxml
+ \since 5.7
+
+ \brief Provides an interface to the state machines created from SCXML files.
+
+ The ScxmlStateMachine type is an implementation of the
+ \l{SCXML Specification}{State Chart XML (SCXML)}.
+
+ All states that are defined in the SCXML file are accessible as properties
+ of this type. These properties are boolean values and indicate whether the
+ state is active or inactive.
+*/
+
+/*!
\fn QScxmlStateMachine::connectToEvent(const QString &scxmlEventSpec,
const QObject *receiver,
PointerToMemberFunction method,
@@ -307,6 +321,7 @@ void EventLoopHook::timerEvent(QTimerEvent *timerEvent)
QScxmlEvent *scxmlEvent = it->second;
smp->m_delayedEvents.erase(it);
smp->routeEvent(scxmlEvent);
+ killTimer(timerId);
return;
}
}
@@ -416,7 +431,10 @@ QScxmlStateMachinePrivate::QScxmlStateMachinePrivate(const QMetaObject *metaObje
, m_eventLoopHook(this)
, m_metaObject(metaObject)
, m_infoSignalProxy(nullptr)
-{}
+{
+ static int metaType = qRegisterMetaType<QScxmlStateMachine *>();
+ Q_UNUSED(metaType);
+}
QScxmlStateMachinePrivate::~QScxmlStateMachinePrivate()
{
@@ -1481,6 +1499,12 @@ QScxmlStateMachine::QScxmlStateMachine(QScxmlStateMachinePrivate &dd, QObject *p
*/
/*!
+ \qmlproperty bool ScxmlStateMachine::running
+
+ The running state of this state machine.
+*/
+
+/*!
\property QScxmlStateMachine::dataModel
\brief The data model to be used for this state machine.
@@ -1497,6 +1521,22 @@ QScxmlStateMachine::QScxmlStateMachine(QScxmlStateMachinePrivate &dd, QObject *p
*/
/*!
+ \qmlproperty ScxmlDataModel ScxmlStateMachine::dataModel
+
+ 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 when the state machine has been \l 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.
@@ -1507,6 +1547,13 @@ QScxmlStateMachine::QScxmlStateMachine(QScxmlStateMachinePrivate &dd, QObject *p
*/
/*!
+ \qmlproperty bool ScxmlStateMachine::initialized
+
+ This read-only property is set to \c true if the state machine has been
+ initialized, \c false otherwise.
+*/
+
+/*!
\property QScxmlStateMachine::initialValues
\brief The initial values to be used for setting up the data model.
@@ -1515,6 +1562,12 @@ QScxmlStateMachine::QScxmlStateMachine(QScxmlStateMachinePrivate &dd, QObject *p
*/
/*!
+ \qmlproperty var ScxmlStateMachine::initialValues
+
+ The initial values to be used for setting up the data model.
+*/
+
+/*!
\property QScxmlStateMachine::sessionId
\brief The session ID of the current state machine.
@@ -1529,12 +1582,32 @@ QScxmlStateMachine::QScxmlStateMachine(QScxmlStateMachinePrivate &dd, QObject *p
*/
/*!
+ \qmlproperty string ScxmlStateMachine::sessionId
+
+ The session ID of the current state machine.
+
+ The session ID is used for message routing between parent and child state
+ machines. If a state machine is started by an \c <invoke> element, any event
+ it sends will have the \c invokeid field set to the session ID. The state
+ machine will use the origin of an event (which is set by the \e target or
+ \e targetexpr attribute in a \c <send> element) to dispatch messages to the
+ correct child state machine.
+*/
+
+/*!
\property QScxmlStateMachine::name
\brief The name of the state machine as set by the \e name attribute of the \c <scxml> tag.
*/
/*!
+ \qmlproperty string ScxmlStateMachine::name
+
+ The name of the state machine as set by the \e name attribute of the
+ \c <scxml> tag.
+*/
+
+/*!
\property QScxmlStateMachine::invoked
\brief Whether the state machine was invoked from an outer state machine.
@@ -1544,18 +1617,41 @@ QScxmlStateMachine::QScxmlStateMachine(QScxmlStateMachinePrivate &dd, QObject *p
*/
/*!
+ \qmlproperty bool ScxmlStateMachine::invoked
+
+ Whether the state machine was invoked from an outer state machine.
+
+ This read-only property is set to \c true when the state machine was started
+ as a service with the \c <invoke> element, \c false otherwise.
+ */
+
+/*!
\property QScxmlStateMachine::parseErrors
\brief The list of parse errors that occurred while creating a state machine from an SCXML file.
*/
/*!
+ \qmlproperty var ScxmlStateMachine::parseErrors
+
+ The list of parse errors that occurred while creating a state machine from
+ an SCXML file.
+ */
+
+/*!
\property QScxmlStateMachine::loader
\brief The loader that is currently used to resolve and load URIs for the state machine.
*/
/*!
+ \qmlproperty Loader ScxmlStateMachine::loader
+
+ The loader that is currently used to resolve and load URIs for the state
+ machine.
+ */
+
+/*!
\property QScxmlStateMachine::tableData
\brief The table data that is used when generating C++ from an SCXML file.
@@ -1675,6 +1771,22 @@ void QScxmlStateMachine::setTableData(QScxmlTableData *tableData)
}
/*!
+ \qmlmethod ScxmlStateMachine::stateNames(bool compress)
+
+ Retrieves a list of state names of all states.
+
+ When \a compress is \c true (the default), the states that contain child
+ states is filtered out and only the \e {leaf states} is returned. When it
+ is \c false, the full list of all states is returned.
+
+ The returned list does not contain the states of possible nested state
+ machines.
+
+ \note The order of the state names in the list is the order in which the
+ states occurred in the SCXML document.
+*/
+
+/*!
* Retrieves a list of state names of all states.
*
* When \a compress is \c true (the default), the states that contain child states
@@ -1700,6 +1812,17 @@ QStringList QScxmlStateMachine::stateNames(bool compress) const
}
/*!
+ \qmlmethod ScxmlStateMachine::activeStateNames(bool compress)
+
+ Retrieves a list of state names of all active states.
+
+ When a state is active, all its parent states are active by definition. When
+ \a compress is \c true (the default), the parent states are filtered out and
+ only the \e {leaf states} are returned. When it is \c false, the full list
+ of active states is returned.
+*/
+
+/*!
* Retrieves a list of state names of all active states.
*
* When a state is active, all its parent states are active by definition. When \a compress
@@ -1720,6 +1843,13 @@ QStringList QScxmlStateMachine::activeStateNames(bool compress) const
}
/*!
+ \qmlmethod ScxmlStateMachine::isActive(string scxmlStateName)
+
+ Returns \c true if the state specified by \a scxmlStateName is active,
+ \c false otherwise.
+*/
+
+/*!
* Returns \c true if the state specified by \a scxmlStateName is active, \c false otherwise.
*/
bool QScxmlStateMachine::isActive(const QString &scxmlStateName) const
@@ -1811,6 +1941,17 @@ QMetaObject::Connection QScxmlStateMachine::connectToEventImpl(const QString &sc
}
/*!
+ \qmlmethod ScxmlStateMachine::init()
+
+ Initializes the state machine by setting the initial values for \c <data>
+ elements and executing any \c <script> tags of the \c <scxml> tag. The
+ initial data values are taken from the \l initialValues property.
+
+ Returns \c false if parse errors occur or if any of the initialization steps
+ fail. Returns \c true otherwise.
+*/
+
+/*!
* Initializes the state machine.
*
* State machine initialization consists of calling QScxmlDataModel::setup(), setting the initial
@@ -1887,10 +2028,24 @@ QString QScxmlStateMachine::name() const
}
/*!
+ \qmlmethod ScxmlStateMachine::submitEvent(event)
+
+ Submits the SCXML event \a event to the internal or external event queue
+ depending on the priority of the event.
+
+ When a delay is set, the event will be queued for delivery after the timeout
+ has passed. The state machine takes ownership of the event and deletes it
+ after processing.
+
+ \sa QScxmlEvent
+ */
+
+/*!
* Submits the SCXML event \a event to the internal or external event queue depending on the
* priority of the event.
*
* When a delay is set, the event will be queued for delivery after the timeout has passed.
+ * The state machine takes ownership of \a event and deletes it after processing.
*/
void QScxmlStateMachine::submitEvent(QScxmlEvent *event)
{
@@ -1925,6 +2080,12 @@ void QScxmlStateMachine::submitEvent(const QString &eventName)
e->setEventType(QScxmlEvent::ExternalEvent);
submitEvent(e);
}
+/*!
+ \qmlmethod ScxmlStateMachine::submitEvent(string eventName, var data)
+
+ A utility method to create and submit an external event with the specified
+ \a eventName as the name and \a data as the payload data (optional).
+*/
/*!
* A utility method to create and submit an external event with the specified
@@ -1944,6 +2105,12 @@ void QScxmlStateMachine::submitEvent(const QString &eventName, const QVariant &d
}
/*!
+ \qmlmethod ScxmlStateMachine::cancelDelayedEvent(string sendId)
+
+ Cancels a delayed event with the specified \a sendId.
+*/
+
+/*!
* Cancels a delayed event with the specified \a sendId.
*/
void QScxmlStateMachine::cancelDelayedEvent(const QString &sendId)
@@ -1964,6 +2131,24 @@ void QScxmlStateMachine::cancelDelayedEvent(const QString &sendId)
}
/*!
+ \qmlmethod ScxmlStateMachine::isDispatchableTarget(string target)
+
+ Returns \c true if a message to \a target can be dispatched by this state
+ machine.
+
+ Valid targets are:
+ \list
+ \li \c #_parent for the parent state machine if the current state machine
+ is started by \c <invoke>
+ \li \c #_internal for the current state machine
+ \li \c #_scxml_sessionid, where \c sessionid is the session ID of the
+ current state machine
+ \li \c #_servicename, where \c servicename is the ID or name of a service
+ started with \c <invoke> by this state machine
+ \endlist
+ */
+
+/*!
* Returns \c true if a message to \a target can be dispatched by this state machine.
*
* Valid targets are:
@@ -1998,6 +2183,13 @@ bool QScxmlStateMachine::isDispatchableTarget(const QString &target) const
}
/*!
+ \qmlproperty list ScxmlStateMachine::invokedServices
+
+ A list of SCXML services that were invoked from the main state machine
+ (possibly recursively).
+*/
+
+/*!
\property QScxmlStateMachine::invokedServices
\brief A list of SCXML services that were invoked from the main
state machine (possibly recursively).
@@ -2030,6 +2222,17 @@ QVector<QScxmlInvokableService *> QScxmlStateMachine::invokedServices() const
*/
/*!
+ \qmlsignal ScxmlStateMachine::log(string label, string msg)
+
+ This signal is emitted if a \c <log> tag is used in the SCXML. \a label is
+ the value of the \e label attribute of the \c <log> tag. \a msg is the value
+ of the evaluated \e expr attribute of the \c <log> tag. If there is no
+ \e expr attribute, a null string will be returned.
+
+ The corresponding signal handler is \c onLog().
+*/
+
+/*!
\fn QScxmlStateMachine::reachedStableState()
This signal is emitted when the event queue is empty at the end of a macro step or when a final
@@ -2037,6 +2240,15 @@ QVector<QScxmlInvokableService *> QScxmlStateMachine::invokedServices() const
*/
/*!
+ \qmlsignal ScxmlStateMachine::reachedStableState()
+
+ This signal is emitted when the event queue is empty at the end of a macro
+ step or when a final state is reached.
+
+ The corresponding signal handler is \c onreachedStableState().
+*/
+
+/*!
\fn QScxmlStateMachine::finished()
This signal is emitted when the state machine reaches a top-level final state.
@@ -2044,6 +2256,24 @@ QVector<QScxmlInvokableService *> QScxmlStateMachine::invokedServices() const
\sa running
*/
+/*!
+ \qmlsignal ScxmlStateMachine::finished()
+
+ This signal is emitted when the state machine reaches a top-level final
+ state.
+
+ The corresponding signal handler is \c onFinished().
+*/
+
+/*!
+ \qmlmethod ScxmlStateMachine::start()
+
+ Starts this state machine. The machine resets its configuration and
+ transitions to the initial state. When a final top-level state
+ is entered, the machine emits the finished() signal.
+
+ \sa stop(), finished()
+*/
/*!
Starts this state machine. The machine will reset its configuration and
@@ -2072,6 +2302,15 @@ void QScxmlStateMachine::start()
}
/*!
+ \qmlmethod ScxmlStateMachine::stop()
+
+ Stops this state machine. The machine will not execute any further state
+ transitions. Its \l running property is set to \c false.
+
+ \sa start(), finished()
+*/
+
+/*!
Stops this state machine. The machine will not execute any further state
transitions. Its \c running property is set to \c false.
diff --git a/src/scxml/qscxmlstatemachine.h b/src/scxml/qscxmlstatemachine.h
index d4435f7..e437eb2 100644
--- a/src/scxml/qscxmlstatemachine.h
+++ b/src/scxml/qscxmlstatemachine.h
@@ -46,11 +46,11 @@
#include <QtScxml/qscxmlevent.h>
#include <QtScxml/qscxmlcompiler.h>
-#include <QString>
-#include <QVector>
-#include <QUrl>
-#include <QVariantList>
-#include <QPointer>
+#include <QtCore/qstring.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qpointer.h>
#include <functional>
diff --git a/src/scxml/qscxmlstatemachineinfo_p.h b/src/scxml/qscxmlstatemachineinfo_p.h
index 7a8ca50..4fa0ca0 100644
--- a/src/scxml/qscxmlstatemachineinfo_p.h
+++ b/src/scxml/qscxmlstatemachineinfo_p.h
@@ -52,7 +52,7 @@
//
#include <QtScxml/qscxmlglobals.h>
-#include <QObject>
+#include <QtCore/qobject.h>
QT_BEGIN_NAMESPACE
diff --git a/src/scxml/qscxmltabledata.h b/src/scxml/qscxmltabledata.h
index 5fcabd1..5c0d345 100644
--- a/src/scxml/qscxmltabledata.h
+++ b/src/scxml/qscxmltabledata.h
@@ -41,7 +41,7 @@
#define QSCXMLTABLEDATA_H
#include <QtScxml/qscxmlexecutablecontent.h>
-#include <QString>
+#include <QtCore/qstring.h>
#ifndef Q_QSCXMLC_OUTPUT_REVISION
#define Q_QSCXMLC_OUTPUT_REVISION 1
diff --git a/tests/3rdparty/scion-tests/scxml-test-framework/test/content-expr-in-send/test0.txml.json b/tests/3rdparty/scion-tests/scxml-test-framework/test/content-expr-in-send/test0.txml.json
index 2b697c0..277863c 100644
--- a/tests/3rdparty/scion-tests/scxml-test-framework/test/content-expr-in-send/test0.txml.json
+++ b/tests/3rdparty/scion-tests/scxml-test-framework/test/content-expr-in-send/test0.txml.json
@@ -1,4 +1,9 @@
{
"initialConfiguration" : ["pass"],
- "events" : []
+ "expectedEvents" : [
+ { "data" : "blah" },
+ { "name" : "timeout", "data" : {"p" : "v"} },
+ { "data" : {"p" : "v"} },
+ { "name" : "timeout" }
+ ]
}
diff --git a/tests/3rdparty/scion-tests/scxml-test-framework/test/content-expr-in-send/test0.txml.scxml b/tests/3rdparty/scion-tests/scxml-test-framework/test/content-expr-in-send/test0.txml.scxml
index 4cfa34a..f62bc55 100644
--- a/tests/3rdparty/scion-tests/scxml-test-framework/test/content-expr-in-send/test0.txml.scxml
+++ b/tests/3rdparty/scion-tests/scxml-test-framework/test/content-expr-in-send/test0.txml.scxml
@@ -3,24 +3,28 @@
name="content-expr-in-send" datamodel="ecmascript">
<state id="top">
<onentry>
- <send event="timeout" delay="2s"/>
- <send event="to_second">
+ <send>
<content>blah</content>
</send>
+ <send event="timeout">
+ <param name="p" expr="'v'"/>
+ </send>
+
</onentry>
+
<state id="first">
- <transition event="to_second" target="second"/>
+ <transition event="timeout" target="second"/>
</state>
<state id="second">
<onentry>
- <send event="to_pass">
+ <send>
<content expr="_event.data"/>
</send>
+ <send event="timeout"/>
</onentry>
+ <transition event="timeout" target="pass"/>
</state>
- <transition event="to_pass" cond="_event.data=='blah'" target="pass"/>
- <transition event="timeout" target="fail"/>
</state>
<final id="pass"><onentry><log label="Outcome" expr="'pass'"/></onentry></final>
diff --git a/tests/auto/scion/tst_scion.cpp b/tests/auto/scion/tst_scion.cpp
index a068005..296c63d 100644
--- a/tests/auto/scion/tst_scion.cpp
+++ b/tests/auto/scion/tst_scion.cpp
@@ -356,11 +356,112 @@ static bool playEvents(QScxmlStateMachine *stateMachine, const QJsonObject &test
return true;
}
+QT_BEGIN_NAMESPACE
+QDebug operator<<(QDebug debug, const QScxmlEvent &event)
+{
+ QJsonObject obj;
+ obj.insert(QLatin1String("name"), event.name());
+ obj.insert(QLatin1String("type"), event.eventType());
+ obj.insert(QLatin1String("data"), QJsonValue::fromVariant(event.data()));
+ obj.insert(QLatin1String("sendid"), event.sendId());
+ obj.insert(QLatin1String("origin"), event.origin());
+ obj.insert(QLatin1String("originType"), event.originType());
+ obj.insert(QLatin1String("invokeid"), event.invokeId());
+ return debug << obj;
+}
+QT_END_NAMESPACE
+
+static int verifyEvent(const QList<QScxmlEvent> &receivedEvents, const QJsonObject &event,
+ int position) {
+ QScxmlEvent::EventType eventType = QScxmlEvent::ExternalEvent;
+ const bool verifyEventType = event.contains(QLatin1String("type"));
+ if (verifyEventType) {
+ QString typeStr = event.value(QLatin1String("type")).toString();
+ if (typeStr.compare(QLatin1String("external"), Qt::CaseInsensitive) == 0)
+ eventType = QScxmlEvent::InternalEvent;
+ else if (typeStr.compare(QLatin1String("platform"), Qt::CaseInsensitive) == 0)
+ eventType = QScxmlEvent::PlatformEvent;
+ else {
+ qWarning() << "unexpected event type in " << event;
+ return -1;
+ }
+ }
+
+ const bool verifyName = event.contains(QLatin1String("name"));
+ const QString name = verifyName ? event.value(QLatin1String("name")).toString() : QString();
+
+ const bool verifyData = event.contains(QLatin1String("data"));
+ const QVariant data = verifyData ? event.value(QLatin1String("data")).toVariant() : QVariant();
+ const bool verifySendId = event.contains(QLatin1String("sendid"));
+ const QString sendId = verifySendId ? event.value(QLatin1String("sendid")).toString()
+ : QString();
+ const bool verifyOrigin = event.contains(QLatin1String("origin"));
+ const QString origin = verifyOrigin ? event.value(QLatin1String("origin")).toString()
+ : QString();
+ const bool verifyOriginType = event.contains(QLatin1String("originType"));
+ const QString originType = verifyOriginType
+ ? event.value(QLatin1String("origintype")).toString()
+ : QString();
+ const bool verifyInvokeId = event.contains(QLatin1String("invokeid"));
+ const QString invokeId = verifyInvokeId ? event.value(QLatin1String("invokeid")).toString()
+ : QString();
+
+ while (position < receivedEvents.length()) {
+ const QScxmlEvent &receivedEvent = receivedEvents[position];
+ if ((verifyName && receivedEvent.name() != name)
+ || (verifyEventType && receivedEvent.eventType() != eventType)
+ || (verifyData && receivedEvent.data() != data)
+ || (verifySendId && receivedEvent.sendId() != sendId)
+ || (verifyOrigin && receivedEvent.origin() != origin)
+ || (verifyOriginType && receivedEvent.originType() != originType)
+ || (verifyInvokeId && receivedEvent.invokeId() != invokeId)) {
+ ++position;
+ } else {
+ return position;
+ }
+ }
+
+ qWarning("Did not receive expected event:");
+ qWarning() << event;
+
+ return -1; // nothing found
+}
+
+static bool verifyEvents(const QList<QScxmlEvent> &receivedEvents,
+ const QJsonObject &testDescription)
+{
+ auto jsonEvents = testDescription.value(QLatin1String("expectedEvents"));
+ if (jsonEvents.isNull())
+ return true;
+
+ auto eventsArray = jsonEvents.toArray();
+
+ int position = 0;
+ for (int i = 0, ei = eventsArray.size(); i != ei; ++i) {
+ position = verifyEvent(receivedEvents, eventsArray.at(i).toObject(), position);
+ if (position < 0) {
+ qWarning("received events:");
+ qWarning() << receivedEvents;
+ qWarning("expected events");
+ qWarning() << eventsArray;
+ return false;
+ } else {
+ ++position; // Don't use the same event twice.
+ }
+ }
+ return true;
+}
+
bool TestScion::runTest(QScxmlStateMachine *stateMachine, const QJsonObject &testDescription)
{
MySignalSpy stableStateSpy(stateMachine, SIGNAL(reachedStableState()));
MySignalSpy finishedSpy(stateMachine, SIGNAL(finished()));
+ QList<QScxmlEvent> receivedEvents;
+ stateMachine->connectToEvent(QLatin1String("*"), this, [&](const QScxmlEvent &event) {
+ receivedEvents.append(event);
+ });
+
if (!stateMachine->init() && stateMachine->name() != QStringLiteral("test487")) {
// test487 relies on a failing init to see if an error event gets posted.
qWarning() << "init failed";
@@ -385,6 +486,8 @@ bool TestScion::runTest(QScxmlStateMachine *stateMachine, const QJsonObject &tes
finishedSpy.fastWait(); // Some tests don't have a final state, so don't check for the
// result
}
+ if (!verifyEvents(receivedEvents, testDescription))
+ return false;
return verifyStates(stateMachine, testDescription, QLatin1String("initialConfiguration"), 0);
}
}
diff --git a/tests/auto/statemachine/invoke.scxml b/tests/auto/statemachine/invoke.scxml
new file mode 100644
index 0000000..1bac47a
--- /dev/null
+++ b/tests/auto/statemachine/invoke.scxml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtScxml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+-->
+<scxml
+ xmlns="http://www.w3.org/2005/07/scxml"
+ version="1.0"
+ name="Directions"
+ initial="anyplace"
+>
+ <state id="anyplace">
+ <invoke type="http://www.w3.org/TR/scxml/">
+ <content>
+ <scxml name="anywhere" version="1.0">
+ <state id="here">
+ <transition event="goThere" target="there"/>
+ </state>
+ <state id="there">
+ <transition event="goHere" target="here"/>
+ </state>
+ </scxml>
+ </content>
+ </invoke>
+ </state>
+</scxml>
diff --git a/tests/auto/statemachine/tst_statemachine.cpp b/tests/auto/statemachine/tst_statemachine.cpp
index 99d6661..ed1f424 100644
--- a/tests/auto/statemachine/tst_statemachine.cpp
+++ b/tests/auto/statemachine/tst_statemachine.cpp
@@ -31,6 +31,7 @@
#include <QXmlStreamReader>
#include <QtScxml/qscxmlcompiler.h>
#include <QtScxml/qscxmlstatemachine.h>
+#include <QtScxml/qscxmlinvokableservice.h>
#include <QtScxml/private/qscxmlstatemachine_p.h>
Q_DECLARE_METATYPE(QScxmlError);
@@ -52,6 +53,8 @@ private Q_SLOTS:
void doneDotStateEvent();
void running();
+
+ void invokeStateMachine();
};
void tst_StateMachine::stateNames_data()
@@ -387,6 +390,25 @@ void tst_StateMachine::running()
QCOMPARE(stateMachine->isRunning(), false);
}
+void tst_StateMachine::invokeStateMachine()
+{
+ QScopedPointer<QScxmlStateMachine> stateMachine(
+ QScxmlStateMachine::fromFile(QString(":/tst_statemachine/invoke.scxml")));
+ QVERIFY(!stateMachine.isNull());
+
+ stateMachine->start();
+ QCOMPARE(stateMachine->isRunning(), true);
+ QTRY_VERIFY(stateMachine->activeStateNames().contains(QString("anyplace")));
+
+ QVector<QScxmlInvokableService *> services = stateMachine->invokedServices();
+ QCOMPARE(services.length(), 1);
+ QVariant subMachineVariant = services[0]->property("stateMachine");
+ QVERIFY(subMachineVariant.isValid());
+ QScxmlStateMachine *subMachine = qvariant_cast<QScxmlStateMachine *>(subMachineVariant);
+ QVERIFY(subMachine);
+ QTRY_VERIFY(subMachine->activeStateNames().contains("here"));
+}
+
QTEST_MAIN(tst_StateMachine)
#include "tst_statemachine.moc"
diff --git a/tests/auto/statemachine/tst_statemachine.qrc b/tests/auto/statemachine/tst_statemachine.qrc
index 9ded2d0..c31fe4c 100644
--- a/tests/auto/statemachine/tst_statemachine.qrc
+++ b/tests/auto/statemachine/tst_statemachine.qrc
@@ -5,5 +5,6 @@
<file>statenamesnested.scxml</file>
<file>ids1.scxml</file>
<file>stateDotDoneEvent.scxml</file>
+ <file>invoke.scxml</file>
</qresource>
</RCC>
diff --git a/tools/tools.pro b/tools/tools.pro
index 1854cfc..6884612 100644
--- a/tools/tools.pro
+++ b/tools/tools.pro
@@ -1,2 +1,2 @@
TEMPLATE = subdirs
-SUBDIRS = qscxmlc
+qtConfig(commandlineparser): SUBDIRS = qscxmlc