[Solved] QSCXML and the In() Predicate



  • I'm creating a Qt application that utilizes qscxml and state machines. Certain transitions within my state machine need to fire based upon the current substate of a parallel state, so I have set the cond = "In('state')" on those transitions. Using logging within my state machine, I have confirmed the state that's being referenced is active, however the condition always resolves to be false. Stepping through the code I see that the isInState function within qscxml.cpp always returns false.

    @
    static QScriptValue isInState(QScriptContext context, QScriptEngine engine)
    {
    QScxml
    scxml = qobject_cast<QScxml
    >(context->thisObject().toQObject());
    if (scxml) {
    if (context->argumentCount() > 0) {
    QString name = context->argument(0).toString();
    if (!name.isEmpty()) {
    QSet<QAbstractState*> cfg = scxml->configuration();
    foreach (QAbstractState* st, cfg) {
    if (st->objectName() == name)
    return qScriptValueFromValue<bool>(engine,true);
    }
    }
    }
    }
    return qScriptValueFromValue<bool>(engine,false);
    }
    @

    The scxml pointer is always null. A very simple concept of my scxml is as follows:

    @
    <parallel id = "main">
    <state id = "process1" initial="init1">
    <state id="init1">
    <transition cond = "In('init2')" target = "destination"/>
    </state>
    <state id="destination">
    </state>
    </state>
    <state id = "process2" initial="init2">
    <state id="init2">
    </state>
    </state>
    </parallel>
    @

    The qscxml class seems to recognize In() and does at least attempt to evaluate. Is it not possible to use the In() predicate without modifying the qscxml class, or do I have an error in how I am attempting to use In()?



  • I believe I figured out a solution. The In() predicate is part of the script engine's global object, making it accessible from the script code. Since the object obtained from QScriptContext was the global object, the cast could not be made. I modified the cast to instead be:

    @
    QScxml* scxml = qobject_cast<QScxml*>(context->engine()->globalObject().property("scxml").toQObject());
    @

    Which retrieves the QScriptValue containing the pointer to the script engine, allowing the cast to work. Now my state machine is performing as expected.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.