From 9be5070e56f170a239dcc075f9dc5b21a1ea8a4d Mon Sep 17 00:00:00 2001 From: Marc Schmitzer Date: Fri, 27 Jan 2012 16:28:18 +0100 Subject: Change parsing of "event" attribute of transitions. Previously, the event prefixes for a transition where obtained by using QString::split(' ') on the value of the "event" attribute. QString::split() also retains empty strings resulting from the split, which has two consequences: 1) If the event attribute is empty or missing, a QStringList containing a single empty string is returned. This makes event-less transitions work, which are executed immediately (if the condition is met). 2) If the event attribute contains multiple prefixes separated by more than one space character, the returned list contains the prefixes *and* one or more empty strings. This makes the transition trigger immediately and on *any* event. Since an extra space is an easy mistake to make and difficult to spot (speaking from experience), this behaviour is rather undesirable. To fix this, this patch changes the parsing of the event attribute to use QString::split(' ', QString::SkipEmptyParts). This fixes (2) but breaks (1). To keep event-less transitions working, QScxmlTransition::eventTest() is changed to match events of type QEvent::None if the transition has no event prefixes. Due to the above change, this is the case when the "event" attribute is ommitted or contains only space characters. NOTE: Strictly speaking, this removes a feature from qscxml. In the previous state, it was possible to create a transition (presumably with a guard condition) that is both executed immediately when its source state is entered *and* triggered by one or more signals. With this change, a transition can only be either immediate or triggered by (an) event(s), not both. The W3C scxml specification seems to specify this behaviour (see http://www.w3.org/TR/scxml/#SelectingTransitions ). --- src/qscxml.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/qscxml.cpp b/src/qscxml.cpp index c44e135..a9896c3 100644 --- a/src/qscxml.cpp +++ b/src/qscxml.cpp @@ -618,10 +618,15 @@ bool QScxmlTransition::eventTest(QEvent *e) QString event; if (e) { - if (e->type() == QScxmlEvent::eventType()) { + bool found = false; + if (e->type() == QEvent::None) { + // QEvent::None events are posted when a state is entered. + // If we have no event prefixes we are triggered by those events. + found = ev.isEmpty(); + } + else if (e->type() == QScxmlEvent::eventType()) { event = ((QScxmlEvent*)e)->eventName(); } - bool found = false; for (int i=0; i < ev.size() && !found; ++i) { QString prefix = ev[i]; found = prefix=="*" || prefix==event || event.startsWith(prefix) @@ -1420,7 +1425,7 @@ void QScxmlLoader::loadState ( curExecContext.script = ""; curTransition = new QScxmlTransition(curState,stateMachine); curTransition->setConditionExpression(r.attributes().value("cond").toString()); - curTransition->setEventPrefixes(r.attributes().value("event").toString().split(' ')); + curTransition->setEventPrefixes(r.attributes().value("event").toString().split(' ', QString::SkipEmptyParts)); foreach(QString pfx, curTransition->eventPrefixes()) { if (pfx != "*") stateMachine->pvt->knownEvents.insert(pfx); -- cgit v1.2.3