diff options
Diffstat (limited to 'src/qscxml.cpp')
-rw-r--r-- | src/qscxml.cpp | 180 |
1 files changed, 103 insertions, 77 deletions
diff --git a/src/qscxml.cpp b/src/qscxml.cpp index 3896bda..68412ed 100644 --- a/src/qscxml.cpp +++ b/src/qscxml.cpp @@ -70,6 +70,7 @@ #include <QState> #include <QMetaMethod> #include <QScriptProgram> +#include <QScriptClass> @@ -199,6 +200,8 @@ class QScxmlPrivate QSet<QString> knownEvents; + QScriptClass* scriptClass; + static QHash<QString,QScxml*> sessions; }; QHash<QString,QScxml*> QScxmlPrivate::sessions; @@ -439,19 +442,41 @@ static QScriptValue invoke(QScriptContext *context, QScriptEngine *engine) return QScriptValue(); } +static QScriptValue notifyChange(QScriptContext *context, QScriptEngine * engine) +{ + if (context->argumentCount() > 0) { + QScriptValue val = context->argument(0); + if (val.data().isObject()) { + QString key = val.data().property("key").toString(); + if (key != "") { + notifyDataChange(engine,key,val.data().property("value")); + } + } + } + return QScriptValue(); +} +static void notifyDataChange (QScriptEngine* engine, const QString & id, const QScriptValue & v) +{ + QScxml* scxml = qobject_cast<QScxml*>(engine->globalObject().property("scxml").toQObject()); + if (scxml) { + scxml->dataChanged(id,v.toVariant()); + } +} + + static QScriptValue dataAccess(QScriptContext *context, QScriptEngine * engine) { if (context->argumentCount() == 0) { // getter - return context->callee().property("value"); + return context->callee().data().property("value"); } else if (context->argumentCount() == 1) { // setter QScriptValue val = context->argument(0); - context->callee().setProperty("value",val); - qDebug() << "data set" << val.toVariant() << context->callee().property("key").toString(); + context->callee().data().setProperty("value",val); + val.setData(context->callee().data()); QScxml* scxml = qobject_cast<QScxml*>(engine->globalObject().property("scxml").toQObject()); if (scxml) { - scxml->dataChanged(context->callee().property("key").toString(),val.toVariant()); + scxml->dataChanged(context->callee().data().property("key").toString(),val.toVariant()); } return val; } else @@ -494,9 +519,9 @@ void QScxmlPrivate::initScriptEngine(QScxml* thiz) scxmlObj.setProperty("setTimeout",scriptEng->newFunction(QScxmlFunctions::setTimeout)); scxmlObj.setProperty("clearTimeout",scriptEng->newFunction(QScxmlFunctions::clearTimeout)); scxmlObj.setProperty("connectSignalToEvent",scriptEng->newFunction(QScxmlFunctions::connectSignalToEvent)); + scxmlObj.setProperty("notifyChange",scriptEng->newFunction(QScxmlFunctions::notifyChange)); QScriptValue dmObj = scriptEng->newObject(); dataObj = scriptEng->newObject(); - dataObj.setProperty("_values",scriptEng->newObject()); glob.setProperty("_data",dataObj); glob.setProperty("_global",scriptEng->globalObject()); glob.setProperty("scxml",scxmlObj); @@ -595,9 +620,9 @@ QScxmlTransition::QScxmlTransition (QState* state,QScxml* machine) { } -void QScxmlTransition::setConditionExpression(const QString & c) +void QScxmlTransition::setConditionExpression(const QString & cond) { - prog = QScriptProgram(c,scxml->baseUrl().toLocalFile()); + prog = QScriptProgram(cond,scxml->baseUrl().toLocalFile()); } QString QScxmlTransition::conditionExpression() const @@ -936,10 +961,7 @@ void QScxml::postNamedEvent(const QString & event) void QScxml::setData(const QString & id, const QVariant & val) { - QScriptValue accessor = pvt->dataObj.property(id); - if (accessor.isFunction()) { - accessor.setProperty("value",scriptEngine()->newVariant(val)); - } + pvt->dataObj.setProperty(id,scriptEngine()->newVariant(val)); } /*! @@ -1100,78 +1122,80 @@ QEvent::Type QScxmlEvent::eventType() static QEvent::Type _t = (QEvent::Type)QEvent::registerEventType(QEvent::User+200); return _t; } -const char SCXML_NAMESPACE [] = "http://www.w3.org/2005/07/scxml"; +namespace { + const char SCXML_NAMESPACE [] = "http://www.w3.org/2005/07/scxml"; -struct ScTransitionInfo -{ - - QScxmlTransition* transition; - QStringList targets; - QString script; - ScTransitionInfo() : transition(NULL) {} -}; + struct ScTransitionInfo + { -class QScxmlScriptExec : public QObject -{ - Q_OBJECT - QScriptProgram prog; - QScxml* scxml; - public: - QScxmlScriptExec(const QString & scr, QScxml* scx) : - prog(QScriptProgram(scr,scx->baseUrl().toLocalFile())),scxml(scx) - { - } - public Q_SLOTS: - void exec() - { - scxml->executeScript(prog); - } -}; + QScxmlTransition* transition; + QStringList targets; + QString script; + ScTransitionInfo() : transition(NULL) {} + }; -struct ScStateInfo -{ - QString initial; -}; + class QScxmlScriptExec : public QObject + { + Q_OBJECT + QScriptProgram prog; + QScxml* scxml; + public: + QScxmlScriptExec(const QString & scr, QScxml* scx) : + prog(QScriptProgram(scr,scx->baseUrl().toLocalFile())),scxml(scx) + { + } + public Q_SLOTS: + void exec() + { + scxml->executeScript(prog); + } + }; -struct ScHistoryInfo -{ - QHistoryState* hstate; - QString defaultStateID; -}; + struct ScStateInfo + { + QString initial; + }; -struct ScExecContext -{ - QScxml* sm; - QString script; - enum {None, StateEntry,StateExit,Transition } type; - QScxmlTransition* trans; - QAbstractState* state; - ScExecContext() : sm(NULL),type(None),trans(NULL),state(NULL) + struct ScHistoryInfo { - } + QHistoryState* hstate; + QString defaultStateID; + }; - void applyScript() + struct ScExecContext { - if (!script.isEmpty()) { - QScxmlScriptExec* exec = new QScxmlScriptExec(script,sm); - switch(type) { - case StateEntry: - QObject::connect(state,SIGNAL(entered()),exec,SLOT(exec())); - break; - case StateExit: - QObject::connect(state,SIGNAL(exited()),exec,SLOT(exec())); - break; - case Transition: - QObject::connect(trans,SIGNAL(triggered()),exec,SLOT(exec())); - break; - default: - delete exec; - break; + QScxml* sm; + QString script; + enum {None, StateEntry,StateExit,Transition } type; + QScxmlTransition* trans; + QAbstractState* state; + ScExecContext() : sm(NULL),type(None),trans(NULL),state(NULL) + { + } + + void applyScript() + { + if (!script.isEmpty()) { + QScxmlScriptExec* exec = new QScxmlScriptExec(script,sm); + switch(type) { + case StateEntry: + QObject::connect(state,SIGNAL(entered()),exec,SLOT(exec())); + break; + case StateExit: + QObject::connect(state,SIGNAL(exited()),exec,SLOT(exec())); + break; + case Transition: + QObject::connect(trans,SIGNAL(triggered()),exec,SLOT(exec())); + break; + default: + delete exec; + break; + } } } - } + }; }; class QScxmlLoader @@ -1436,21 +1460,24 @@ void QScxmlLoader::loadState ( curTransition->setObjectName(QString ("%1 to %2 on %3 if %4").arg(curState->objectName()).arg(inf.targets.join(" ")).arg(curTransition->eventPrefixes().join(" ")).arg(curTransition->conditionExpression())); } } else if (r.name().toString().compare("data",Qt::CaseInsensitive) == 0) { - QScriptValue val = qScriptValueFromValue<QString>(stateMachine->scriptEngine(),"") ; + QScriptEngine* engine = stateMachine->scriptEngine(); + QScriptValue val = qScriptValueFromValue<QString>(engine,"") ; QString id = r.attributes().value("id").toString(); if (r.attributes().value("src").length()) val = evaluateFile(QFileInfo(filename).dir().absoluteFilePath(r.attributes().value("src").toString())); else { if (r.attributes().value("expr").length()) { - val = stateMachine->scriptEngine()->evaluate(r.attributes().value("expr").toString()); + val = engine->evaluate(r.attributes().value("expr").toString()); } else { QString t = r.readElementText(); if (!t.isEmpty()) - val = stateMachine->scriptEngine()->evaluate(t); + val = engine->evaluate(t); } } - QScriptValue func = stateMachine->scriptEngine()->newFunction(QScxmlFunctions::dataAccess); - func.setProperty("key",id); + QScriptValue func = engine->newFunction(QScxmlFunctions::dataAccess); + QScriptValue accessor = engine->newObject(); + accessor.setProperty("key",id); + func.setData(accessor); stateMachine->pvt->dataObj.setProperty(id,func,QScriptValue::PropertyGetter|QScriptValue::PropertySetter); stateMachine->pvt->dataObj.setProperty(id,val); } else if (r.name().toString().compare("param",Qt::CaseInsensitive) == 0) { @@ -1532,7 +1559,6 @@ void QScxmlLoader::loadState ( } } } - QMap<QString,QVariant> QScxml::data() const { QMap<QString,QVariant> d; |