diff options
-rw-r--r-- | src/scxml/qscxmlcompiler.cpp | 22 | ||||
-rw-r--r-- | src/scxml/qscxmlcppdatamodel.cpp | 14 | ||||
-rw-r--r-- | src/scxml/qscxmlcppdatamodel.h | 3 | ||||
-rw-r--r-- | src/scxml/qscxmldatamodel.cpp | 5 | ||||
-rw-r--r-- | src/scxml/qscxmldatamodel.h | 5 | ||||
-rw-r--r-- | src/scxml/qscxmlecmascriptdatamodel.cpp | 18 | ||||
-rw-r--r-- | src/scxml/qscxmlecmascriptdatamodel.h | 2 | ||||
-rw-r--r-- | src/scxml/qscxmlexecutablecontent.cpp | 8 | ||||
-rw-r--r-- | src/scxml/qscxmlinvokableservice.cpp | 168 | ||||
-rw-r--r-- | src/scxml/qscxmlinvokableservice.h | 94 | ||||
-rw-r--r-- | src/scxml/qscxmlinvokableservice_p.h | 41 | ||||
-rw-r--r-- | src/scxml/qscxmlnulldatamodel.cpp | 3 | ||||
-rw-r--r-- | src/scxml/qscxmlnulldatamodel.h | 2 | ||||
-rw-r--r-- | src/scxml/qscxmlstatemachine.cpp | 13 | ||||
-rw-r--r-- | tools/qscxmlc/decl.t | 2 | ||||
-rw-r--r-- | tools/qscxmlc/scxmlcppdumper.cpp | 16 |
16 files changed, 212 insertions, 204 deletions
diff --git a/src/scxml/qscxmlcompiler.cpp b/src/scxml/qscxmlcompiler.cpp index 691f87a..b8434c6 100644 --- a/src/scxml/qscxmlcompiler.cpp +++ b/src/scxml/qscxmlcompiler.cpp @@ -473,13 +473,14 @@ private: }; #ifndef BUILD_QSCXMLC -class InvokeDynamicScxmlFactory: public QScxmlScxmlServiceFactory +class InvokeDynamicScxmlFactory: public QScxmlInvokableServiceFactory { + Q_OBJECT public: InvokeDynamicScxmlFactory(const QScxmlExecutableContent::InvokeInfo &invokeInfo, const QVector<QScxmlExecutableContent::StringId> &namelist, const QVector<QScxmlExecutableContent::ParameterInfo> ¶ms) - : QScxmlScxmlServiceFactory(invokeInfo, namelist, params) + : QScxmlInvokableServiceFactory(invokeInfo, namelist, params) {} void setContent(const QSharedPointer<DocumentModel::ScxmlDocument> &content) @@ -647,12 +648,12 @@ inline QScxmlInvokableService *InvokeDynamicScxmlFactory::invoke( QScxmlStateMachine *parentStateMachine) { bool ok = true; - auto srcexpr = d->calculateSrcexpr(parentStateMachine, &ok); + auto srcexpr = calculateSrcexpr(parentStateMachine, invokeInfo().expr, &ok); if (!ok) return Q_NULLPTR; if (!srcexpr.isEmpty()) - return invokeDynamic(parentStateMachine, srcexpr); + return invokeDynamicScxmlService(srcexpr, parentStateMachine, this); auto childStateMachine = DynamicStateMachine::build(m_content.data()); @@ -660,15 +661,16 @@ inline QScxmlInvokableService *InvokeDynamicScxmlFactory::invoke( dm->setParent(childStateMachine); childStateMachine->setDataModel(dm); - return invokeStatic(childStateMachine, parentStateMachine); + return invokeStaticScxmlService(childStateMachine, parentStateMachine, this); } #endif // BUILD_QSCXMLC } // anonymous namespace #ifndef BUILD_QSCXMLC -QScxmlScxmlService *QScxmlScxmlServiceFactory::invokeDynamic( - QScxmlStateMachine *parentStateMachine, const QString &sourceUrl) +QScxmlScxmlService *invokeDynamicScxmlService(const QString &sourceUrl, + QScxmlStateMachine *parentStateMachine, + QScxmlInvokableServiceFactory *factory) { QScxmlCompiler::Loader *loader = parentStateMachine->loader(); @@ -708,7 +710,7 @@ QScxmlScxmlService *QScxmlScxmlServiceFactory::invokeDynamic( dm->setParent(childStateMachine); childStateMachine->setDataModel(dm); - return invokeStatic(childStateMachine, parentStateMachine); + return invokeStaticScxmlService(childStateMachine, parentStateMachine, factory); } #endif // BUILD_QSCXMLC @@ -2483,3 +2485,7 @@ QScxmlCompilerPrivate::ParserState::ParserState(QScxmlCompilerPrivate::ParserSta {} QT_END_NAMESPACE + +#ifndef BUILD_QSCXMLC +#include "qscxmlcompiler.moc" +#endif diff --git a/src/scxml/qscxmlcppdatamodel.cpp b/src/scxml/qscxmlcppdatamodel.cpp index bc09d65..69f0fbd 100644 --- a/src/scxml/qscxmlcppdatamodel.cpp +++ b/src/scxml/qscxmlcppdatamodel.cpp @@ -134,11 +134,6 @@ QScxmlCppDataModel::QScxmlCppDataModel(QObject *parent) : QScxmlDataModel(*(new QScxmlCppDataModelPrivate), parent) {} -/*! \internal */ -QScxmlCppDataModel::~QScxmlCppDataModel() -{ -} - /*! * Called during state machine initialization to set up a state machine using the initial values * for data model variables specified by their keys, \a initialDataValues. These @@ -156,24 +151,23 @@ bool QScxmlCppDataModel::setup(const QVariantMap &initialDataValues) void QScxmlCppDataModel::evaluateAssignment(EvaluatorId id, bool *ok) { Q_UNUSED(id); - Q_UNUSED(ok); + *ok = false; Q_UNREACHABLE(); } void QScxmlCppDataModel::evaluateInitialization(EvaluatorId id, bool *ok) { Q_UNUSED(id); - Q_UNUSED(ok); + *ok = false; Q_UNREACHABLE(); } -bool QScxmlCppDataModel::evaluateForeach(EvaluatorId id, bool *ok, ForeachLoopBody *body) +void QScxmlCppDataModel::evaluateForeach(EvaluatorId id, bool *ok, ForeachLoopBody *body) { Q_UNUSED(id); - Q_UNUSED(ok); Q_UNUSED(body); + *ok = false; Q_UNREACHABLE(); - return false; } /*! diff --git a/src/scxml/qscxmlcppdatamodel.h b/src/scxml/qscxmlcppdatamodel.h index fb59336..04607f2 100644 --- a/src/scxml/qscxmlcppdatamodel.h +++ b/src/scxml/qscxmlcppdatamodel.h @@ -59,14 +59,13 @@ class Q_SCXML_EXPORT QScxmlCppDataModel: public QScxmlDataModel Q_DECLARE_PRIVATE(QScxmlCppDataModel) public: explicit QScxmlCppDataModel(QObject *parent = nullptr); - ~QScxmlCppDataModel(); Q_INVOKABLE bool setup(const QVariantMap &initialDataValues) Q_DECL_OVERRIDE; #ifndef Q_QDOC void evaluateAssignment(QScxmlExecutableContent::EvaluatorId id, bool *ok) Q_DECL_OVERRIDE Q_DECL_FINAL; void evaluateInitialization(QScxmlExecutableContent::EvaluatorId id, bool *ok) Q_DECL_OVERRIDE Q_DECL_FINAL; - bool evaluateForeach(QScxmlExecutableContent::EvaluatorId id, bool *ok, ForeachLoopBody *body) Q_DECL_OVERRIDE Q_DECL_FINAL; + void evaluateForeach(QScxmlExecutableContent::EvaluatorId id, bool *ok, ForeachLoopBody *body) Q_DECL_OVERRIDE Q_DECL_FINAL; #endif // Q_QDOC void setScxmlEvent(const QScxmlEvent &scxmlEvent) Q_DECL_OVERRIDE Q_DECL_FINAL; diff --git a/src/scxml/qscxmldatamodel.cpp b/src/scxml/qscxmldatamodel.cpp index 9762e92..6e6d62b 100644 --- a/src/scxml/qscxmldatamodel.cpp +++ b/src/scxml/qscxmldatamodel.cpp @@ -96,11 +96,6 @@ QScxmlDataModel::QScxmlDataModel(QScxmlDataModelPrivate &dd, QObject *parent) : { } -/*! \internal */ -QScxmlDataModel::~QScxmlDataModel() -{ -} - /*! * Sets the state machine this model belongs to to \a stateMachine. There is a * 1:1 relation between state machines and models. After setting the state diff --git a/src/scxml/qscxmldatamodel.h b/src/scxml/qscxmldatamodel.h index 845d8bf..e1a575a 100644 --- a/src/scxml/qscxmldatamodel.h +++ b/src/scxml/qscxmldatamodel.h @@ -64,12 +64,11 @@ public: { public: virtual ~ForeachLoopBody(); - virtual bool run() = 0; + virtual void run(bool *ok) = 0; }; public: explicit QScxmlDataModel(QObject *parent = nullptr); - ~QScxmlDataModel(); void setStateMachine(QScxmlStateMachine *stateMachine); QScxmlStateMachine *stateMachine() const; @@ -83,7 +82,7 @@ public: virtual void evaluateToVoid(QScxmlExecutableContent::EvaluatorId id, bool *ok) = 0; virtual void evaluateAssignment(QScxmlExecutableContent::EvaluatorId id, bool *ok) = 0; virtual void evaluateInitialization(QScxmlExecutableContent::EvaluatorId id, bool *ok) = 0; - virtual bool evaluateForeach(QScxmlExecutableContent::EvaluatorId id, bool *ok, ForeachLoopBody *body) = 0; + virtual void evaluateForeach(QScxmlExecutableContent::EvaluatorId id, bool *ok, ForeachLoopBody *body) = 0; #endif // Q_QDOC virtual void setScxmlEvent(const QScxmlEvent &event) = 0; diff --git a/src/scxml/qscxmlecmascriptdatamodel.cpp b/src/scxml/qscxmlecmascriptdatamodel.cpp index 32c49f0..4b0329e 100644 --- a/src/scxml/qscxmlecmascriptdatamodel.cpp +++ b/src/scxml/qscxmlecmascriptdatamodel.cpp @@ -469,7 +469,7 @@ void QScxmlEcmaScriptDataModel::evaluateInitialization(EvaluatorId id, bool *ok) evaluateAssignment(id, ok); } -bool QScxmlEcmaScriptDataModel::evaluateForeach(EvaluatorId id, bool *ok, ForeachLoopBody *body) +void QScxmlEcmaScriptDataModel::evaluateForeach(EvaluatorId id, bool *ok, ForeachLoopBody *body) { Q_D(QScxmlEcmaScriptDataModel); Q_ASSERT(ok); @@ -480,7 +480,7 @@ bool QScxmlEcmaScriptDataModel::evaluateForeach(EvaluatorId id, bool *ok, Foreac if (!jsArray.isArray()) { d->submitError(QStringLiteral("error.execution"), QStringLiteral("invalid array '%1' in %2").arg(d->string(info.array), d->string(info.context))); *ok = false; - return false; + return; } QString item = d->string(info.item); @@ -490,7 +490,7 @@ bool QScxmlEcmaScriptDataModel::evaluateForeach(EvaluatorId id, bool *ok, Foreac d->submitError(QStringLiteral("error.execution"), QStringLiteral("invalid item '%1' in %2") .arg(d->string(info.item), d->string(info.context))); *ok = false; - return false; + return; } const int length = jsArray.property(QStringLiteral("length")).toInt(); @@ -502,17 +502,17 @@ bool QScxmlEcmaScriptDataModel::evaluateForeach(EvaluatorId id, bool *ok, Foreac QJSValue currentItem = jsArray.property(static_cast<quint32>(currentIndex)); *ok = d->setProperty(item, currentItem, context); if (!*ok) - return false; + return; if (hasIndex) { *ok = d->setProperty(idx, currentIndex, context); if (!*ok) - return false; + return; } - if (!body->run()) - return false; + body->run(ok); + if (!*ok) + return; } - - return true; + *ok = true; } /*! diff --git a/src/scxml/qscxmlecmascriptdatamodel.h b/src/scxml/qscxmlecmascriptdatamodel.h index b1d9f55..808830a 100644 --- a/src/scxml/qscxmlecmascriptdatamodel.h +++ b/src/scxml/qscxmlecmascriptdatamodel.h @@ -63,7 +63,7 @@ public: void evaluateToVoid(QScxmlExecutableContent::EvaluatorId id, bool *ok) Q_DECL_OVERRIDE Q_DECL_FINAL; void evaluateAssignment(QScxmlExecutableContent::EvaluatorId id, bool *ok) Q_DECL_OVERRIDE Q_DECL_FINAL; void evaluateInitialization(QScxmlExecutableContent::EvaluatorId id, bool *ok) Q_DECL_OVERRIDE Q_DECL_FINAL; - bool evaluateForeach(QScxmlExecutableContent::EvaluatorId id, bool *ok, ForeachLoopBody *body) Q_DECL_OVERRIDE Q_DECL_FINAL; + void evaluateForeach(QScxmlExecutableContent::EvaluatorId id, bool *ok, ForeachLoopBody *body) Q_DECL_OVERRIDE Q_DECL_FINAL; #endif // Q_QDOC void setScxmlEvent(const QScxmlEvent &event) Q_DECL_OVERRIDE; diff --git a/src/scxml/qscxmlexecutablecontent.cpp b/src/scxml/qscxmlexecutablecontent.cpp index 5df8b1f..9fbcd15 100644 --- a/src/scxml/qscxmlexecutablecontent.cpp +++ b/src/scxml/qscxmlexecutablecontent.cpp @@ -216,11 +216,9 @@ const InstructionId *QScxmlExecutionEngine::step(const InstructionId *ip, bool * , loopStart(loopStart) {} - bool run() Q_DECL_OVERRIDE + void run(bool *ok) Q_DECL_OVERRIDE { - bool ok = true; - engine->step(loopStart, &ok); - return ok; + engine->step(loopStart, ok); } }; @@ -229,7 +227,7 @@ const InstructionId *QScxmlExecutionEngine::step(const InstructionId *ip, bool * const InstructionId *loopStart = _foreach->blockstart(); ip += _foreach->size(); LoopBody body(this, loopStart); - *ok = dataModel->evaluateForeach(_foreach->doIt, ok, &body) && *ok; + dataModel->evaluateForeach(_foreach->doIt, ok, &body); return ip; } diff --git a/src/scxml/qscxmlinvokableservice.cpp b/src/scxml/qscxmlinvokableservice.cpp index 9af6be7..9dfda21 100644 --- a/src/scxml/qscxmlinvokableservice.cpp +++ b/src/scxml/qscxmlinvokableservice.cpp @@ -59,9 +59,18 @@ QScxmlInvokableServiceFactoryPrivate::QScxmlInvokableServiceFactoryPrivate( , parameters(parameters) {} +QScxmlStaticScxmlServiceFactoryPrivate::QScxmlStaticScxmlServiceFactoryPrivate( + const QMetaObject *metaObject, + const QScxmlExecutableContent::InvokeInfo &invokeInfo, + const QVector<QScxmlExecutableContent::StringId> &names, + const QVector<QScxmlExecutableContent::ParameterInfo> ¶meters) + : QScxmlInvokableServiceFactoryPrivate(invokeInfo, names, parameters), metaObject(metaObject) +{ +} + QScxmlInvokableService::QScxmlInvokableService(QScxmlStateMachine *parentStateMachine, - QObject *parent) : - QObject(*(new QScxmlInvokableServicePrivate(parentStateMachine)), parent) + QScxmlInvokableServiceFactory *factory) : + QObject(*(new QScxmlInvokableServicePrivate(parentStateMachine)), factory) { } @@ -71,58 +80,43 @@ QScxmlStateMachine *QScxmlInvokableService::parentStateMachine() const return d->parentStateMachine; } -void QScxmlInvokableService::finalize(QScxmlExecutableContent::ContainerId finalize) -{ - if (finalize != QScxmlExecutableContent::NoInstruction) { - auto psm = parentStateMachine(); - qCDebug(qscxmlLog) << psm << "running finalize on event"; - auto smp = QScxmlStateMachinePrivate::get(psm); - smp->m_executionEngine->execute(finalize); - } -} - -QScxmlInvokableService::QScxmlInvokableService(QScxmlInvokableServicePrivate &dd, QObject *parent) : - QObject(dd, parent) -{ -} - QScxmlInvokableServiceFactory::QScxmlInvokableServiceFactory( const QScxmlExecutableContent::InvokeInfo &invokeInfo, const QVector<QScxmlExecutableContent::StringId> &names, - const QVector<QScxmlExecutableContent::ParameterInfo> ¶meters) - : d(new QScxmlInvokableServiceFactoryPrivate(invokeInfo, names, parameters)) + const QVector<QScxmlExecutableContent::ParameterInfo> ¶meters, + QObject *parent) + : QObject(*(new QScxmlInvokableServiceFactoryPrivate(invokeInfo, names, parameters)), parent) {} -QScxmlInvokableServiceFactory::~QScxmlInvokableServiceFactory() -{ - delete d; -} - -QScxmlExecutableContent::InvokeInfo QScxmlInvokableServiceFactory::invokeInfo() const +const QScxmlExecutableContent::InvokeInfo &QScxmlInvokableServiceFactory::invokeInfo() const { + Q_D(const QScxmlInvokableServiceFactory); return d->invokeInfo; } -QVector<QScxmlExecutableContent::ParameterInfo> QScxmlInvokableServiceFactory::parameters() const +const QVector<QScxmlExecutableContent::ParameterInfo> & +QScxmlInvokableServiceFactory::parameters() const { + Q_D(const QScxmlInvokableServiceFactory); return d->parameters; } -QVector<QScxmlExecutableContent::StringId> QScxmlInvokableServiceFactory::names() const +const QVector<QScxmlExecutableContent::StringId> &QScxmlInvokableServiceFactory::names() const { + Q_D(const QScxmlInvokableServiceFactory); return d->names; } -QString QScxmlInvokableServiceFactoryPrivate::calculateSrcexpr(QScxmlStateMachine *parent, - bool *ok) const +QString calculateSrcexpr(QScxmlStateMachine *parent, QScxmlExecutableContent::EvaluatorId srcexpr, + bool *ok) { Q_ASSERT(ok); *ok = true; auto dataModel = parent->dataModel(); - if (invokeInfo.expr != QScxmlExecutableContent::NoEvaluator) { + if (srcexpr != QScxmlExecutableContent::NoEvaluator) { *ok = false; - auto v = dataModel->evaluateToString(invokeInfo.expr, ok); + auto v = dataModel->evaluateToString(srcexpr, ok); if (!*ok) return QString(); return v; @@ -217,106 +211,114 @@ QVariantMap QScxmlInvokableServicePrivate::calculateData( return result; } -QScxmlScxmlServicePrivate::QScxmlScxmlServicePrivate(QScxmlStateMachine *stateMachine, - QScxmlStateMachine *parentStateMachine) : - QScxmlInvokableServicePrivate(parentStateMachine), stateMachine(stateMachine) -{} - -QScxmlScxmlServicePrivate::~QScxmlScxmlServicePrivate() +QScxmlScxmlService::~QScxmlScxmlService() { delete stateMachine; } QScxmlScxmlService::QScxmlScxmlService(QScxmlStateMachine *stateMachine, QScxmlStateMachine *parentStateMachine, - QObject *parent) - : QScxmlInvokableService(*(new QScxmlScxmlServicePrivate(stateMachine, parentStateMachine)), - parent) + QScxmlInvokableServiceFactory *factory) + : QScxmlInvokableService(parentStateMachine, factory), stateMachine(stateMachine) { QScxmlStateMachinePrivate::get(stateMachine)->m_parentStateMachine = parentStateMachine; } -bool QScxmlScxmlService::start(const QScxmlExecutableContent::InvokeInfo &invokeInfo, - const QVector<QScxmlExecutableContent::ParameterInfo> ¶meters, - const QVector<QScxmlExecutableContent::StringId> &names) +bool QScxmlScxmlService::start() { - Q_D(QScxmlScxmlService); - qCDebug(qscxmlLog) << parentStateMachine() << "preparing to start" << d->stateMachine; + Q_D(QScxmlInvokableService); + qCDebug(qscxmlLog) << parentStateMachine() << "preparing to start" << stateMachine; + + const QScxmlInvokableServiceFactory *factory + = qobject_cast<QScxmlInvokableServiceFactory *>(parent()); + Q_ASSERT(factory); bool ok = false; - auto id = d->calculateId(parentStateMachine(), invokeInfo, &ok); + auto id = d->calculateId(parentStateMachine(), factory->invokeInfo(), &ok); if (!ok) return false; - auto data = d->calculateData(parentStateMachine(), parameters, names, &ok); + auto data = d->calculateData(parentStateMachine(), factory->parameters(), factory->names(), + &ok); if (!ok) return false; - QScxmlStateMachinePrivate::get(d->stateMachine)->m_sessionId = id; - d->stateMachine->setInitialValues(data); - if (d->stateMachine->init()) { - qCDebug(qscxmlLog) << parentStateMachine() << "starting" << d->stateMachine; - d->stateMachine->start(); + QScxmlStateMachinePrivate::get(stateMachine)->m_sessionId = id; + stateMachine->setInitialValues(data); + if (stateMachine->init()) { + qCDebug(qscxmlLog) << parentStateMachine() << "starting" << stateMachine; + stateMachine->start(); return true; } - qCDebug(qscxmlLog) << parentStateMachine() << "failed to start" << d->stateMachine; + qCDebug(qscxmlLog) << parentStateMachine() << "failed to start" << stateMachine; return false; } QString QScxmlScxmlService::id() const { - Q_D(const QScxmlScxmlService); - return d->stateMachine->sessionId(); + return stateMachine->sessionId(); } QString QScxmlScxmlService::name() const { - Q_D(const QScxmlScxmlService); - return d->stateMachine->name(); + return stateMachine->name(); } void QScxmlScxmlService::postEvent(QScxmlEvent *event) { - Q_D(QScxmlScxmlService); - QScxmlStateMachinePrivate::get(d->stateMachine)->postEvent(event); -} - -QScxmlStateMachine *QScxmlScxmlService::stateMachine() const -{ - Q_D(const QScxmlScxmlService); - return d->stateMachine; -} - -QScxmlScxmlServiceFactory::QScxmlScxmlServiceFactory( - const QScxmlExecutableContent::InvokeInfo &invokeInfo, - const QVector<QScxmlExecutableContent::StringId> &names, - const QVector<QScxmlExecutableContent::ParameterInfo> ¶meters) - : QScxmlInvokableServiceFactory(invokeInfo, names, parameters) -{} - -QScxmlScxmlService *QScxmlScxmlServiceFactory::invokeStatic(QScxmlStateMachine *childStateMachine, - QScxmlStateMachine *parentStateMachine) -{ - QScxmlStateMachinePrivate::get(childStateMachine)->setIsInvoked(true); - return new QScxmlScxmlService(childStateMachine, parentStateMachine); + QScxmlStateMachinePrivate::get(stateMachine)->postEvent(event); } QScxmlDynamicScxmlServiceFactory::QScxmlDynamicScxmlServiceFactory( const QScxmlExecutableContent::InvokeInfo &invokeInfo, const QVector<QScxmlExecutableContent::StringId> &names, - const QVector<QScxmlExecutableContent::ParameterInfo> ¶meters) - : QScxmlScxmlServiceFactory(invokeInfo, names, parameters) + const QVector<QScxmlExecutableContent::ParameterInfo> ¶meters, + QObject *parent) + : QScxmlInvokableServiceFactory(invokeInfo, names, parameters, parent) {} QScxmlInvokableService *QScxmlDynamicScxmlServiceFactory::invoke( QScxmlStateMachine *parentStateMachine) { bool ok = true; - auto srcexpr = d->calculateSrcexpr(parentStateMachine, &ok); + auto srcexpr = calculateSrcexpr(parentStateMachine, invokeInfo().expr, &ok); if (!ok) return Q_NULLPTR; - return invokeDynamic(parentStateMachine, srcexpr); + return invokeDynamicScxmlService(srcexpr, parentStateMachine, this); +} + +QScxmlStaticScxmlServiceFactory::QScxmlStaticScxmlServiceFactory( + const QMetaObject *metaObject, + const QScxmlExecutableContent::InvokeInfo &invokeInfo, + const QVector<QScxmlExecutableContent::StringId> &nameList, + const QVector<QScxmlExecutableContent::ParameterInfo> ¶meters, + QObject *parent) + : QScxmlInvokableServiceFactory(*(new QScxmlStaticScxmlServiceFactoryPrivate( + metaObject, invokeInfo, nameList, parameters)), parent) +{ +} + +QScxmlInvokableService *QScxmlStaticScxmlServiceFactory::invoke( + QScxmlStateMachine *parentStateMachine) +{ + Q_D(const QScxmlStaticScxmlServiceFactory); + QScxmlStateMachine *instance = qobject_cast<QScxmlStateMachine *>( + d->metaObject->newInstance(Q_ARG(QObject *, this))); + return instance ? invokeStaticScxmlService(instance, parentStateMachine, this) : nullptr; +} + +QScxmlInvokableServiceFactory::QScxmlInvokableServiceFactory( + QScxmlInvokableServiceFactoryPrivate &dd, QObject *parent) + : QObject(dd, parent) +{} + +QScxmlScxmlService *invokeStaticScxmlService(QScxmlStateMachine *childStateMachine, + QScxmlStateMachine *parentStateMachine, + QScxmlInvokableServiceFactory *factory) +{ + QScxmlStateMachinePrivate::get(childStateMachine)->setIsInvoked(true); + return new QScxmlScxmlService(childStateMachine, parentStateMachine, factory); } QT_END_NAMESPACE diff --git a/src/scxml/qscxmlinvokableservice.h b/src/scxml/qscxmlinvokableservice.h index 6efc07d..63b9ec3 100644 --- a/src/scxml/qscxmlinvokableservice.h +++ b/src/scxml/qscxmlinvokableservice.h @@ -48,6 +48,7 @@ QT_BEGIN_NAMESPACE class QScxmlEvent; class QScxmlStateMachine; +class QScxmlInvokableServiceFactory; class QScxmlInvokableServicePrivate; class Q_SCXML_EXPORT QScxmlInvokableService : public QObject { @@ -59,101 +60,66 @@ class Q_SCXML_EXPORT QScxmlInvokableService : public QObject public: QScxmlInvokableService(QScxmlStateMachine *parentStateMachine, - QObject *parent = nullptr); + QScxmlInvokableServiceFactory *parent); QScxmlStateMachine *parentStateMachine() const; - virtual bool start(const QScxmlExecutableContent::InvokeInfo &invokeInfo, - const QVector<QScxmlExecutableContent::ParameterInfo> ¶meters, - const QVector<QScxmlExecutableContent::StringId> &names) = 0; + virtual bool start() = 0; virtual QString id() const = 0; virtual QString name() const = 0; virtual void postEvent(QScxmlEvent *event) = 0; - - void finalize(QScxmlExecutableContent::ContainerId finalize); - -protected: - QScxmlInvokableService(QScxmlInvokableServicePrivate &dd, QObject *parent = nullptr); }; class QScxmlInvokableServiceFactoryPrivate; -class Q_SCXML_EXPORT QScxmlInvokableServiceFactory +class Q_SCXML_EXPORT QScxmlInvokableServiceFactory : public QObject { + Q_OBJECT + Q_DECLARE_PRIVATE(QScxmlInvokableServiceFactory) + Q_PROPERTY(QScxmlExecutableContent::InvokeInfo invokeInfo READ invokeInfo CONSTANT) + Q_PROPERTY(QVector<QScxmlExecutableContent::ParameterInfo> parameters READ parameters CONSTANT) + Q_PROPERTY(QVector<QScxmlExecutableContent::StringId> names READ names CONSTANT) + public: QScxmlInvokableServiceFactory( const QScxmlExecutableContent::InvokeInfo &invokeInfo, const QVector<QScxmlExecutableContent::StringId> &names, - const QVector<QScxmlExecutableContent::ParameterInfo> ¶meters); - virtual ~QScxmlInvokableServiceFactory(); + const QVector<QScxmlExecutableContent::ParameterInfo> ¶meters, + QObject *parent = nullptr); virtual QScxmlInvokableService *invoke(QScxmlStateMachine *parentStateMachine) = 0; - QScxmlExecutableContent::InvokeInfo invokeInfo() const; - QVector<QScxmlExecutableContent::ParameterInfo> parameters() const; - QVector<QScxmlExecutableContent::StringId> names() const; + const QScxmlExecutableContent::InvokeInfo &invokeInfo() const; + const QVector<QScxmlExecutableContent::ParameterInfo> ¶meters() const; + const QVector<QScxmlExecutableContent::StringId> &names() const; protected: - QScxmlInvokableServiceFactoryPrivate *d; + QScxmlInvokableServiceFactory(QScxmlInvokableServiceFactoryPrivate &dd, QObject *parent); }; -class QScxmlScxmlServicePrivate; -class Q_SCXML_EXPORT QScxmlScxmlService: public QScxmlInvokableService +class QScxmlStaticScxmlServiceFactoryPrivate; +class Q_SCXML_EXPORT QScxmlStaticScxmlServiceFactory: public QScxmlInvokableServiceFactory { Q_OBJECT - Q_DECLARE_PRIVATE(QScxmlScxmlService) - Q_PROPERTY(QScxmlStateMachine *stateMachine READ stateMachine CONSTANT) -public: - QScxmlScxmlService(QScxmlStateMachine *stateMachine, - QScxmlStateMachine *parentStateMachine, - QObject *parent = nullptr); - - bool start(const QScxmlExecutableContent::InvokeInfo &invokeInfo, - const QVector<QScxmlExecutableContent::ParameterInfo> ¶meters, - const QVector<QScxmlExecutableContent::StringId> &names) Q_DECL_OVERRIDE; - QString id() const Q_DECL_OVERRIDE; - QString name() const Q_DECL_OVERRIDE; - void postEvent(QScxmlEvent *event) Q_DECL_OVERRIDE; - - QScxmlStateMachine *stateMachine() const; -}; - -class Q_SCXML_EXPORT QScxmlScxmlServiceFactory: public QScxmlInvokableServiceFactory -{ -public: - QScxmlScxmlServiceFactory(const QScxmlExecutableContent::InvokeInfo &invokeInfo, - const QVector<QScxmlExecutableContent::StringId> &names, - const QVector<QScxmlExecutableContent::ParameterInfo> ¶meters); - -protected: - QScxmlScxmlService *invokeDynamic(QScxmlStateMachine *parentStateMachine, - const QString &sourceUrl); - QScxmlScxmlService *invokeStatic(QScxmlStateMachine *childStateMachine, - QScxmlStateMachine *parentStateMachine); -}; - -template<class T> -class QScxmlStaticScxmlServiceFactory: public QScxmlScxmlServiceFactory -{ + Q_DECLARE_PRIVATE(QScxmlStaticScxmlServiceFactory) public: QScxmlStaticScxmlServiceFactory( - const QScxmlExecutableContent::InvokeInfo &newInvokeInfo, - const QVector<QScxmlExecutableContent::StringId> &newNameList, - const QVector<QScxmlExecutableContent::ParameterInfo> &newParameters) - : QScxmlScxmlServiceFactory(newInvokeInfo, newNameList, newParameters) - {} - - QScxmlInvokableService *invoke(QScxmlStateMachine *parentStateMachine) Q_DECL_OVERRIDE - { - return invokeStatic(new T, parentStateMachine); - } + const QMetaObject *metaObject, + const QScxmlExecutableContent::InvokeInfo &invokeInfo, + const QVector<QScxmlExecutableContent::StringId> &nameList, + const QVector<QScxmlExecutableContent::ParameterInfo> ¶meters, + QObject *parent = nullptr); + + QScxmlInvokableService *invoke(QScxmlStateMachine *parentStateMachine) Q_DECL_OVERRIDE; }; -class Q_SCXML_EXPORT QScxmlDynamicScxmlServiceFactory: public QScxmlScxmlServiceFactory +class Q_SCXML_EXPORT QScxmlDynamicScxmlServiceFactory: public QScxmlInvokableServiceFactory { + Q_OBJECT public: QScxmlDynamicScxmlServiceFactory( const QScxmlExecutableContent::InvokeInfo &invokeInfo, const QVector<QScxmlExecutableContent::StringId> &names, - const QVector<QScxmlExecutableContent::ParameterInfo> ¶meters); + const QVector<QScxmlExecutableContent::ParameterInfo> ¶meters, + QObject *parent = nullptr); QScxmlInvokableService *invoke(QScxmlStateMachine *parentStateMachine) Q_DECL_OVERRIDE; }; diff --git a/src/scxml/qscxmlinvokableservice_p.h b/src/scxml/qscxmlinvokableservice_p.h index 52bd6d0..e2a9e7b 100644 --- a/src/scxml/qscxmlinvokableservice_p.h +++ b/src/scxml/qscxmlinvokableservice_p.h @@ -71,7 +71,7 @@ public: QScxmlStateMachine *parentStateMachine; }; -class QScxmlInvokableServiceFactoryPrivate +class QScxmlInvokableServiceFactoryPrivate : public QObjectPrivate { public: QScxmlInvokableServiceFactoryPrivate( @@ -79,23 +79,50 @@ public: const QVector<QScxmlExecutableContent::StringId> &names, const QVector<QScxmlExecutableContent::ParameterInfo> ¶meters); - QString calculateSrcexpr(QScxmlStateMachine *parent, bool *ok) const; - QScxmlExecutableContent::InvokeInfo invokeInfo; QVector<QScxmlExecutableContent::StringId> names; QVector<QScxmlExecutableContent::ParameterInfo> parameters; }; -class QScxmlScxmlServicePrivate : public QScxmlInvokableServicePrivate +class Q_SCXML_EXPORT QScxmlScxmlService: public QScxmlInvokableService { + Q_OBJECT + Q_DECLARE_PRIVATE(QScxmlInvokableService) public: - QScxmlScxmlServicePrivate(QScxmlStateMachine *stateMachine, - QScxmlStateMachine *parentStateMachine); - ~QScxmlScxmlServicePrivate(); + QScxmlScxmlService(QScxmlStateMachine *stateMachine, + QScxmlStateMachine *parentStateMachine, + QScxmlInvokableServiceFactory *parent); + ~QScxmlScxmlService(); + + bool start() Q_DECL_OVERRIDE; + QString id() const Q_DECL_OVERRIDE; + QString name() const Q_DECL_OVERRIDE; + void postEvent(QScxmlEvent *event) Q_DECL_OVERRIDE; QScxmlStateMachine *stateMachine; }; +class QScxmlStaticScxmlServiceFactoryPrivate : public QScxmlInvokableServiceFactoryPrivate +{ +public: + QScxmlStaticScxmlServiceFactoryPrivate( + const QMetaObject *metaObject, + const QScxmlExecutableContent::InvokeInfo &invokeInfo, + const QVector<QScxmlExecutableContent::StringId> &names, + const QVector<QScxmlExecutableContent::ParameterInfo> ¶meters); + + const QMetaObject *metaObject; +}; + +QScxmlScxmlService *invokeDynamicScxmlService(const QString &sourceUrl, + QScxmlStateMachine *parentStateMachine, + QScxmlInvokableServiceFactory *factory); +QScxmlScxmlService *invokeStaticScxmlService(QScxmlStateMachine *childStateMachine, + QScxmlStateMachine *parentStateMachine, + QScxmlInvokableServiceFactory *factory); +QString calculateSrcexpr(QScxmlStateMachine *parent, QScxmlExecutableContent::EvaluatorId srcexpr, + bool *ok); + QT_END_NAMESPACE #endif // QSCXMLINVOKABLESERVICE_P_H diff --git a/src/scxml/qscxmlnulldatamodel.cpp b/src/scxml/qscxmlnulldatamodel.cpp index 08a9333..35f1b91 100644 --- a/src/scxml/qscxmlnulldatamodel.cpp +++ b/src/scxml/qscxmlnulldatamodel.cpp @@ -203,7 +203,7 @@ void QScxmlNullDataModel::evaluateInitialization(QScxmlExecutableContent::Evalua QStringLiteral("Cannot initialize values on a null data model")); } -bool QScxmlNullDataModel::evaluateForeach(QScxmlExecutableContent::EvaluatorId id, bool *ok, ForeachLoopBody *body) +void QScxmlNullDataModel::evaluateForeach(QScxmlExecutableContent::EvaluatorId id, bool *ok, ForeachLoopBody *body) { Q_UNUSED(id); Q_UNUSED(body); @@ -211,7 +211,6 @@ bool QScxmlNullDataModel::evaluateForeach(QScxmlExecutableContent::EvaluatorId i QScxmlStateMachinePrivate::get(stateMachine())->submitError( QStringLiteral("error.execution"), QStringLiteral("Cannot run foreach on a null data model")); - return false; } /*! diff --git a/src/scxml/qscxmlnulldatamodel.h b/src/scxml/qscxmlnulldatamodel.h index e4f7942..f5aeb26 100644 --- a/src/scxml/qscxmlnulldatamodel.h +++ b/src/scxml/qscxmlnulldatamodel.h @@ -62,7 +62,7 @@ public: void evaluateToVoid(QScxmlExecutableContent::EvaluatorId id, bool *ok) Q_DECL_OVERRIDE Q_DECL_FINAL; void evaluateAssignment(QScxmlExecutableContent::EvaluatorId id, bool *ok) Q_DECL_OVERRIDE Q_DECL_FINAL; void evaluateInitialization(QScxmlExecutableContent::EvaluatorId id, bool *ok) Q_DECL_OVERRIDE Q_DECL_FINAL; - bool evaluateForeach(QScxmlExecutableContent::EvaluatorId id, bool *ok, ForeachLoopBody *body) Q_DECL_OVERRIDE Q_DECL_FINAL; + void evaluateForeach(QScxmlExecutableContent::EvaluatorId id, bool *ok, ForeachLoopBody *body) Q_DECL_OVERRIDE Q_DECL_FINAL; #endif // Q_QDOC void setScxmlEvent(const QScxmlEvent &event) Q_DECL_OVERRIDE; diff --git a/src/scxml/qscxmlstatemachine.cpp b/src/scxml/qscxmlstatemachine.cpp index ef5a312..1397b71 100644 --- a/src/scxml/qscxmlstatemachine.cpp +++ b/src/scxml/qscxmlstatemachine.cpp @@ -449,7 +449,7 @@ void QScxmlStateMachinePrivate::addService(int invokingState) continue; // service failed to start const QString serviceName = service->name(); m_invokedServices[size_t(id)] = { invokingState, service, serviceName }; - service->start(factory->invokeInfo(), factory->parameters(), factory->names()); + service->start(); } emitInvokedServicesChanged(); } @@ -533,7 +533,16 @@ void QScxmlStateMachinePrivate::postEvent(QScxmlEvent *event) auto factory = serviceFactory(id); if (event->invokeId() == service->id()) { setEvent(event); - service->finalize(factory->invokeInfo().finalize); + + const QScxmlExecutableContent::ContainerId finalize + = factory->invokeInfo().finalize; + if (finalize != QScxmlExecutableContent::NoContainer) { + auto psm = service->parentStateMachine(); + qCDebug(qscxmlLog) << psm << "running finalize on event"; + auto smp = QScxmlStateMachinePrivate::get(psm); + smp->m_executionEngine->execute(finalize); + } + resetEvent(); } if (factory->invokeInfo().autoforward) { diff --git a/tools/qscxmlc/decl.t b/tools/qscxmlc/decl.t index 9482885..648476d 100644 --- a/tools/qscxmlc/decl.t +++ b/tools/qscxmlc/decl.t @@ -5,7 +5,7 @@ class ${classname}: public QScxmlStateMachine ${properties} public: - ${classname}(QObject *parent = 0); + Q_INVOKABLE ${classname}(QObject *parent = 0); ~${classname}(); private: diff --git a/tools/qscxmlc/scxmlcppdumper.cpp b/tools/qscxmlc/scxmlcppdumper.cpp index b539e0d..f5e9b2e 100644 --- a/tools/qscxmlc/scxmlcppdumper.cpp +++ b/tools/qscxmlc/scxmlcppdumper.cpp @@ -375,7 +375,7 @@ int createFactoryId(QStringList &factories, const QString &className, QString line = QStringLiteral("case %1: return new ").arg(QString::number(idx)); if (invokeInfo.expr == QScxmlExecutableContent::NoInstruction) { - line += QStringLiteral("QScxmlStaticScxmlServiceFactory< %1::%2 >(") + line += QStringLiteral("QScxmlStaticScxmlServiceFactory(&%1::%2::staticMetaObject,") .arg(namespacePrefix, className); } else { line += QStringLiteral("QScxmlDynamicScxmlServiceFactory("); @@ -714,6 +714,20 @@ QString CppDumper::generateMetaObject(const QString &className, classDef.qualified = classDef.classname; classDef.superclassList << qMakePair(QByteArray("QScxmlStateMachine"), FunctionDef::Public); classDef.hasQObject = true; + FunctionDef constructor; + constructor.name = className.toUtf8(); + constructor.access = FunctionDef::Public; + constructor.isInvokable = true; + constructor.isConstructor = true; + + ArgumentDef arg; + arg.type.name = "QObject *"; + arg.type.rawName = arg.type.name; + arg.normalizedType = arg.type.name; + arg.name = "parent"; + arg.typeNameForCast = arg.type.name + "*"; + constructor.arguments.append(arg); + classDef.constructorList.append(constructor); // stateNames: int stateIdx = 0; |