diff options
author | Liang Qi <liang.qi@qt.io> | 2017-04-21 11:09:50 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2017-04-21 11:09:50 +0200 |
commit | b490e1b782ac28a82d7902f926f6e041ede179ca (patch) | |
tree | b1d8866ef27e5b2dbcdc71c6d3fbc9678a37b639 | |
parent | 45e2a4826705c7489b77d28ae706474b94022624 (diff) | |
parent | 384cb7975d9caa4e508454d811d2e391763e5981 (diff) |
Merge remote-tracking branch 'origin/5.9' into dev
Change-Id: Ic8e60ed0073e89bdc1f0fb274c362668ece37583
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=""submit." + _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 |