summaryrefslogtreecommitdiffstats
path: root/scc
diff options
context:
space:
mode:
Diffstat (limited to 'scc')
-rw-r--r--scc/README13
-rw-r--r--scc/doc.txt78
-rw-r--r--scc/examples/algotest/algotest.pro6
-rw-r--r--scc/examples/algotest/main.cpp56
-rw-r--r--scc/examples/algotest/test.scxml145
-rw-r--r--scc/examples/animations/animations.pro6
-rw-r--r--scc/examples/animations/animations.scxml19
-rw-r--r--scc/examples/animations/main.cpp81
-rw-r--r--scc/examples/examples.pro2
-rw-r--r--scc/examples/loginmvc/controller.scxml105
-rw-r--r--scc/examples/loginmvc/frame.ui123
-rw-r--r--scc/examples/loginmvc/loginmvc.pro8
-rw-r--r--scc/examples/loginmvc/main.cpp192
-rw-r--r--scc/main.cpp82
-rw-r--r--scc/scc.prf21
-rw-r--r--scc/scc.pro12
-rw-r--r--scc/scc.qrc3
-rw-r--r--scc/scc.xslt330
18 files changed, 1159 insertions, 123 deletions
diff --git a/scc/README b/scc/README
new file mode 100644
index 0000000..35e0ee0
--- /dev/null
+++ b/scc/README
@@ -0,0 +1,13 @@
+To build:
+ qmake
+ make
+ make install
+
+To use:
+ Add to your .pro file:
+ CONFIG += scc
+ STATECHARTS += path-to-my-statechart.scxml
+
+See the examples, and the documentation (currently only in doc.txt)
+
+
diff --git a/scc/doc.txt b/scc/doc.txt
new file mode 100644
index 0000000..6c82ebb
--- /dev/null
+++ b/scc/doc.txt
@@ -0,0 +1,78 @@
+This document describes the expected behaviour of SCC (the Qt State Chart Compiler) in regards to SCXML tags and features.
+
+SCXML
+ Ignored: version, profile, exmode
+
+STATE
+ Ignored: src
+
+TRANSITION
+ Ignored: anchor
+ Additional: Qt:animation, a location expression that points to a QPropertyAnimation* object
+ Notes: An event in a transition translates to a Qt signal in the state machine object. "*" would occur on any event. Prefix matching is not supported, but * and done events are supported.
+ Conditions are C++ boolean expressions.
+PARALLEL
+ Ignored: src
+
+HISTORY:
+ Notes: The history's default transition cannot have executable content.
+
+LOG:
+ Notes: the level of the log translates to QtMsgType. expr is a c++ expression.
+
+SEND:
+ Partially supported: target (only "_internal")
+ Ignored attributes: type, idlocation, hints
+ Notes: The target attribute can be either empty for a regular event, "_internal" for an internal-queue event, or a location expression to emit a signal in an object.
+
+CANCEL:
+ Notes: ID is a string literal, not an expression
+
+DATA:
+ Ignored attributes: src
+ Additional: Qt:type, to define a C++ type for this data element
+ Notes: A data element is converted to a Qt property of the state-machine object. expr/text are C++ expressions
+
+ASSIGN:
+ Notes: If dataid is present rather than location, the generated code would use the Qt property system to assign the value. expr is a c++ expression.
+
+PARAM
+ Notes: either name, expr or inline-text can appear, as the parameters are translated to a QVariantList.
+
+SCRIPT
+ Notes: raw C++ code
+
+Fully supported:
+ INITIAL, FINAL, ONENTRY, ONEXIT, IF, ELSEIF, ELSE, LOG, CANCEL, DATAMODEL
+
+Unsupported:
+ INVOKE, CONTENT, DONEDATA, FINALIZE, ANCHOR, VALIDATE
+
+Qt:property
+ object
+ property
+ value
+
+Qt:cpp
+ text()
+
+system variables
+ _event
+ _data
+ _name
+
+
+INVOKE
+CONTENT
+VALIDATE
+DONEDATA
+
+
+script
+Qt:cpp
+cond
+(variables)
+param
+log
+if/elseif/else
+assign
diff --git a/scc/examples/algotest/algotest.pro b/scc/examples/algotest/algotest.pro
new file mode 100644
index 0000000..e5a1eba
--- /dev/null
+++ b/scc/examples/algotest/algotest.pro
@@ -0,0 +1,6 @@
+TEMPLATE = app
+SOURCES += main.cpp
+OTHER_FILES += test.scxml
+STATECHARTS += test.scxml
+CONFIG += scc console
+QT -= gui
diff --git a/scc/examples/algotest/main.cpp b/scc/examples/algotest/main.cpp
new file mode 100644
index 0000000..c8b74e1
--- /dev/null
+++ b/scc/examples/algotest/main.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "sc_test.h"
+#include <QCoreApplication>
+#include <QTimer>
+int main(int argc, char *argv[])
+{
+ QCoreApplication a(argc, argv);
+ SMClass_test stateMachine;
+ stateMachine.setupStateMachine();
+ stateMachine.start();
+ QObject::connect(stateMachine.state_Test2Sub1,SIGNAL(entered()),&stateMachine,SIGNAL(event_Event2()));
+ QObject::connect(&stateMachine,SIGNAL(finished()),&a,SLOT(quit()));
+ QTimer::singleShot(100,&stateMachine,SIGNAL(event_Event1()));
+ return a.exec();
+}
+
diff --git a/scc/examples/algotest/test.scxml b/scc/examples/algotest/test.scxml
new file mode 100644
index 0000000..e17f9bf
--- /dev/null
+++ b/scc/examples/algotest/test.scxml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF8"?>
+<!-- A wrapper state that contains all other states in this file
+- it represents the complete state machine --> <scxml xmlns="http://www.w3.org/2005/07/scxml"
+ version="1.0"
+ initial="Main">
+ <state id="Main">
+ <!-- its initial state is Test1 -->
+ <initial>
+ <transition target="Test1"/>
+ </initial>
+
+ <!-- Really simple state showing the basic syntax. -->
+ <state id="Test1">
+ <initial>
+ <transition target="Test1Sub1"/>
+ </initial>
+ <!-- Runs before we go into the substate -->
+ <onentry>
+ <log expr="&quot;Inside Test1&quot;"/>
+ </onentry>
+
+ <!-- Here is our first substate -->
+ <state id="Test1Sub1">
+ <onentry>
+ <log expr="&quot;Inside Test1Sub1.&quot;"/>
+ </onentry>
+ <onexit>
+ <log expr="&quot;Leaving Test1Sub1&quot;"/>
+ </onexit>
+ <!-- Go to Sub2 on Event1 -->
+ <transition event="Event1" target="Test1Sub2"/>
+ </state>
+
+ <!-- Here is the second substate
+ It is final, so Test1 is done when we get here -->
+ <final id="Test1Sub2"/>
+
+ <!-- We get this event when we reach Test1Sub2. -->
+ <transition event="done.state.Test1" target="Test2"/>
+
+ <!-- We run this on the way out of Test1 -->
+ <onexit>
+ <log expr="&quot;Leaving Test1...&quot;"/>
+ </onexit>
+ </state>
+
+ <state id="Test2">
+ <initial>
+ <transition target="Test2Sub1"/>
+ </initial>
+
+ <!-- This time we reference a state
+ defined in an external file. Note that we could have
+ loaded the entire file by leaving off the #Test2Sub1,
+ but in that case we would need to rename one of the
+ Test2Sub1 states (here or in the external file) to
+ avoid the name collision -->
+ <state id="Test2Sub1">
+ <onentry>
+ <log expr="&quot;Inside Test2Sub1&quot;"/>
+ </onentry>
+ <transition event="Event2" target="Test2Sub2"/>
+ </state>
+ <final id="Test2Sub2"/>
+
+ <!-- Test2Sub2 is defined as final, so this
+ event is generated when we reach it -->
+ <transition event="done.state.Test2" target="Test3"/>
+ </state>
+
+ <state id="Test3">
+ <initial>
+ <transition target="Test3Sub1"/>
+ </initial>
+
+ <state id="Test3Sub1">
+ <onentry>
+ <log expr="&quot;Inside Test3Sub1...&quot;"/>
+ <!-- Send our self an event in 5s -->
+ <send event="Timer" delay="1500"/>
+ </onentry>
+ <!-- Transition on to Test4.
+ This will exit both us and our parent. -->
+ <transition event="Timer" target="Test4"/>
+ <onexit>
+ <log expr="&quot;Leaving Test3Sub1...&quot;"/>
+ </onexit>
+ </state>
+
+ <onexit>
+ <log expr="&quot;Leaving Test3...&quot;"/>
+ </onexit>
+ </state>
+
+ <state id="Test4">
+ <onentry>
+ <log expr="&quot;Inside Test4...&quot;"/>
+ </onentry>
+ <initial>
+ <transition target="Test4Sub1"/>
+ </initial>
+
+ <state id="Test4Sub1">
+ <onexit>
+ <log expr="&quot;Leaving Test4Sub1...&quot;"/>
+ </onexit>
+ <!-- This transition causes the state to exit immediately
+ after entering Test4Sub1. The transition has no event
+ or guard so it is always active -->
+ <transition target="Test5"/>
+ </state>
+ </state>
+
+ <state id="Test5">
+ <onentry>
+ <log expr="&quot;Inside Test5...&quot;"/>
+ </onentry>
+ <initial>
+ <transition target="Test5P"/>
+ </initial>
+
+ <!-- Fire off our parallel states -->
+ <parallel id="Test5P">
+ <final id="Test5PSub1"/>
+ <final id="Test5PSub2"/>
+ <onexit>
+ <log expr="&quot;all parallel states done&quot;"/>
+ </onexit>
+ </parallel>
+
+ <!-- The parallel states are all final, so this
+ event is generated immediately. Although not shown,
+ compound states (i.e., <state>s with content)
+ are permitted within <parallel> as well. -->
+ <transition event="done.state.Test5P" target="Done"/>
+ </state>
+
+ <!-- This final state is an immediate child of Main
+ - when we get here, done.state.Main is generated. -->
+ <final id="Done"/>
+ <!-- End of Main > -->
+ <transition event="done.state.Main" target="final" />
+ </state>
+ <final id="final"/>
+</scxml>
diff --git a/scc/examples/animations/animations.pro b/scc/examples/animations/animations.pro
new file mode 100644
index 0000000..d501c13
--- /dev/null
+++ b/scc/examples/animations/animations.pro
@@ -0,0 +1,6 @@
+TEMPLATE = app
+OTHER_FILES += animations.scxml
+STATECHARTS += animations.scxml
+CONFIG += scc console
+SOURCES += main.cpp
+TARGET = animations
diff --git a/scc/examples/animations/animations.scxml b/scc/examples/animations/animations.scxml
new file mode 100644
index 0000000..0aabb64
--- /dev/null
+++ b/scc/examples/animations/animations.scxml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:Qt="http://www.qtsoftware.com scxml-ext"
+ initial="hist">
+ <datamodel>
+ <data id="anim" Qt:type="QPropertyAnimation*" expr="NULL" />
+ <data id="indicator" Qt:type="QObject*" expr="NULL" />
+ </datamodel>
+ <history id="hist" type="deep">
+ <transition target="idle" />
+ </history>
+ <state id="idle">
+ <Qt:property object="_data.indicator" property="opacity" value="0" />
+ <transition target="active" event="ev1()" Qt:animation="_data.anim" />
+ </state>
+ <state id="active">
+ <Qt:property object="_data.indicator" property="opacity" value="1" />
+ <transition target="idle" event="ev1()" Qt:animation="_data.anim" />
+ </state>
+</scxml>
diff --git a/scc/examples/animations/main.cpp b/scc/examples/animations/main.cpp
new file mode 100644
index 0000000..cf816bc
--- /dev/null
+++ b/scc/examples/animations/main.cpp
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "sc_animations.h"
+#include <QApplication>
+#include <QGraphicsView>
+#include <QLabel>
+#include <QGraphicsProxyWidget>
+#include <QShortcut>
+#include <QGraphicsScene>
+#include <QPushButton>
+#include <QVBoxLayout>
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+ SMClass_animations stateMachine;
+ QGraphicsView* gv = new QGraphicsView();
+ QPushButton* b = new QPushButton();
+ QWidget* w = new QWidget();
+ QVBoxLayout* lyt = new QVBoxLayout();
+ lyt->addWidget(gv);
+ lyt->addWidget(b);
+ b->setText("Push Me");
+ QObject::connect(b,SIGNAL(clicked()),&stateMachine,SIGNAL(event_ev1()));
+ w->setLayout(lyt);
+ gv->setScene(new QGraphicsScene());
+ gv->setInteractive(true);
+ gv->setFocus();
+ QGraphicsProxyWidget* wdg = gv->scene()->addWidget(new QLabel("Hello World!"));
+ wdg->setOpacity(0);
+ QPropertyAnimation* anim = new QPropertyAnimation();
+ anim->setPropertyName("opacity");
+ anim->setTargetObject(wdg);
+ anim->setDuration(1000);
+ anim->setEasingCurve(QEasingCurve(QEasingCurve::InOutCubic));
+ stateMachine.set_indicator(wdg);
+ stateMachine.set_anim(anim);
+ stateMachine.setupStateMachine();
+ w->show();
+ stateMachine.start();
+ return a.exec();
+}
+
diff --git a/scc/examples/examples.pro b/scc/examples/examples.pro
new file mode 100644
index 0000000..39b6dbb
--- /dev/null
+++ b/scc/examples/examples.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS = loginmvc animations algotest
diff --git a/scc/examples/loginmvc/controller.scxml b/scc/examples/loginmvc/controller.scxml
new file mode 100644
index 0000000..8bffc1a
--- /dev/null
+++ b/scc/examples/loginmvc/controller.scxml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<scxml xmlns="http://www.w3.org/2005/07/scxml"
+ xmlns:Qt="http://www.qtsoftware.com scxml-ext"
+ initial="root">
+ <datamodel>
+ <data id="username" Qt:type="QString" />
+ <data id="password" Qt:type="QString" />
+ <data id="loginTimeout" Qt:type="int" expr="10000" />
+ <data id="firstTime" Qt:type="bool" expr="true" />
+ <data id="loginButton" Qt:type="QObject*" expr="NULL" />
+ <data id="logoutButton" Qt:type="QObject*" expr="NULL" />
+ <data id="cancelButton" Qt:type="QObject*" expr="NULL" />
+ </datamodel>
+ <parallel id="root">
+ <state id="business_logic">
+ <initial>
+ <transition target="idle">
+ <if cond="_data.firstTime">
+ <send event="notify_welcome()" />
+ <if cond="!_data.username.isEmpty()">
+ <send event="notify_hello(QString)">
+ <param expr="_data.username" />
+ </send>
+ </if>
+ <assign dataid="firstTime" expr="false" />
+ </if>
+ </transition>
+ </initial>
+ <state id="idle">
+ <onentry><log level="0" label="Info" expr="&quot;Now in Idle&quot;" /><raise event="in_idle" /></onentry>
+ <onexit><log level="0" label="Info" expr="&quot;Now not in Idle&quot;" /><raise event="not_in_idle" /></onexit>
+ <transition target="trying_to_login" event="intent_login()" />
+ <Qt:property object="_data.cancelButton" property="enabled" value="false" />
+ </state>
+ <state id="trying_to_login">
+ <Qt:property object="_data.cancelButton" property="enabled" value="true" />
+ <transition event="cancel_login()" target="idle" />
+ <transition event="login_timeout()" target="loginTimeout" />
+ <onentry>
+ <log level="0" label="Info" expr="&quot;Trying to log in&quot;" />
+ <send event="login_action(QString,QString)">
+ <param expr="_data.username" />
+ <param expr="_data.password" />
+ </send>
+ <send id="cancel_login_timeout" event="login_timeout()" delay="_data.loginTimeout" />
+ </onentry>
+ <onexit>
+ <cancel id="cancel_login_timeout" />
+ </onexit>
+ <transition event="login_complete(bool)" cond="_event.data[0].toBool()" target="loggedIn" />
+ <transition event="login_complete(bool)" cond="!_event.data[0].toBool()" target="loginError" />
+ </state>
+ <state id="error" initial="loginError">
+ <Qt:property object="_data.cancelButton" property="enabled" value="false" />
+ <transition event="intent_continue()" target="idle" />
+ <onentry>
+ <raise event="error.login()" />
+ </onentry>
+ <state id="cancelled">
+ <onentry>
+ <send event="notify_cancel()" />
+ </onentry>
+ </state>
+ <state id="loginError">
+ <onentry>
+ <log label="Error" level="1" expr="_data.username + ' ' + _data.password" />
+ <send event="notify_error()" />
+ </onentry>
+ </state>
+ <state id="loginTimeout">
+ <onentry>
+ <log label="Error" level="1" expr="_data.username + ' ' + _data.password" />
+ <send event="notify_timeout()" />
+ </onentry>
+ </state>
+ </state>
+ <state id="loggedIn">
+ <onentry>
+ <send event="notify_loggedIn()" />
+ </onentry>
+ <transition event="intent_continue()" target="active" />
+ </state>
+ <state id="active">
+ <transition event="intent_logout()" target="idle" />
+ <Qt:property object="_data.cancelButton" property="enabled" value="false" />
+ </state>
+ <final id="exit" />
+ </state>
+ <state id="gui" initial="hist">
+ <history id="hist" type="deep">
+ <transition target="gui_idle" />
+ </history>
+ <state id="gui_idle">
+ <Qt:property object="_data.loginButton" property="enabled" value="true" />
+ <Qt:property object="_data.logoutButton" property="enabled" value="false" />
+ <transition target="gui_active" cond="!In(idle)" />
+ </state>
+ <state id="gui_active">
+ <transition target="gui_idle" cond="In(idle)" />
+ <Qt:property object="_data.loginButton" property="enabled" value="false" />
+ <Qt:property object="_data.logoutButton" property="enabled" value="true" />
+ </state>
+ </state>
+ </parallel>
+</scxml>
diff --git a/scc/examples/loginmvc/frame.ui b/scc/examples/loginmvc/frame.ui
new file mode 100644
index 0000000..7f984de
--- /dev/null
+++ b/scc/examples/loginmvc/frame.ui
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Frame</class>
+ <widget class="QFrame" name="Frame">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>337</width>
+ <height>158</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Frame</string>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Username</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="usernameEdit"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Password</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="passwordEdit">
+ <property name="echoMode">
+ <enum>QLineEdit::Password</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Timeout</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QSlider" name="timeoutSlider">
+ <property name="maximum">
+ <number>20000</number>
+ </property>
+ <property name="singleStep">
+ <number>500</number>
+ </property>
+ <property name="pageStep">
+ <number>2000</number>
+ </property>
+ <property name="value">
+ <number>10000</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QWidget" name="widget" native="true">
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="loginButton">
+ <property name="text">
+ <string>Log In</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="logoutButton">
+ <property name="text">
+ <string>Logout</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="cancelButton">
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout"/>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/scc/examples/loginmvc/loginmvc.pro b/scc/examples/loginmvc/loginmvc.pro
new file mode 100644
index 0000000..9af965a
--- /dev/null
+++ b/scc/examples/loginmvc/loginmvc.pro
@@ -0,0 +1,8 @@
+TEMPLATE = app
+CONFIG += console scc
+SOURCES = main.cpp
+FORMS += frame.ui
+QT += network
+STATECHARTS += controller.scxml
+OTHER_FILES += controller.scxml
+CONFIG -= app_bundle
diff --git a/scc/examples/loginmvc/main.cpp b/scc/examples/loginmvc/main.cpp
new file mode 100644
index 0000000..c01a3be
--- /dev/null
+++ b/scc/examples/loginmvc/main.cpp
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QApplication>
+#include "sc_controller.h"
+#include <QLabel>
+#include <QMessageBox>
+#include "ui_frame.h"
+#include <QNetworkAccessManager>
+#include <QNetworkReply>
+#include <QSslSocket>
+class AbstractModel : public QObject
+{
+ Q_OBJECT
+ public:
+ AbstractModel(QObject* o = NULL) : QObject(o)
+ {
+ }
+ public slots:
+ virtual void login(const QString & u, const QString & p) = 0;
+ signals:
+ void loginComplete(bool);
+};
+
+class DummyModel : public AbstractModel
+{
+ Q_OBJECT
+ public:
+ DummyModel(QObject* o = NULL) : AbstractModel(o)
+ {
+ }
+ public slots:
+ void test()
+ {
+ emit loginComplete(user == "user" && password == "password");
+ }
+ virtual void login(const QString & u, const QString & p)
+ {
+ user = u; password = p;
+ QTimer::singleShot(5000,this,SLOT(test()));
+ }
+ signals:
+ void loginComplete(bool);
+ private:
+ QString user,password;
+ QNetworkAccessManager netAccess;
+};
+class GMailModel : public AbstractModel
+{
+ Q_OBJECT
+ public:
+ GMailModel(QObject* o = NULL) : AbstractModel(o)
+ {
+ }
+ public slots:
+ void loginFinished()
+ {
+ QNetworkReply* rep = qobject_cast<QNetworkReply*>(sender());
+ rep->deleteLater();
+ qDebug() << rep->error() << rep->errorString();
+ emit loginComplete(rep->error() == QNetworkReply::NoError);
+ }
+ virtual void login(const QString & u, const QString & p)
+ {
+ QNetworkRequest req;
+ QUrl url("https://mail.google.com/mail/feed/atom");
+ url.setUserName(u);
+ url.setPassword(p);
+ req.setUrl(url);
+ QNetworkReply* reply = netAccess.get(req);
+ reply->ignoreSslErrors();
+ connect(reply,SIGNAL(finished()),this,SLOT(loginFinished()));
+ }
+ private:
+ QNetworkAccessManager netAccess;
+};
+
+class MyView : public QFrame, public virtual Ui::Frame
+{
+ Q_OBJECT
+ public:
+ MyView(QWidget* o = NULL) : QFrame(o)
+ {
+ setupUi(this);
+ connect(loginButton,SIGNAL(clicked()),this,SIGNAL(loginIntent()));
+ connect(logoutButton,SIGNAL(clicked()),this,SIGNAL(logoutIntent()));
+ connect(cancelButton,SIGNAL(clicked()),this,SIGNAL(cancelIntent()));
+ }
+
+ public slots:
+
+ void notifyLogin()
+ {
+ QMessageBox::information(this,"Logged In","You are now logged in!");
+ emit contIntent();
+ }
+ void notifyTimeout()
+ {
+ QMessageBox::information(this,"Timeout...","Sorry, login has timed out");
+ emit contIntent();
+ }
+ void notifyWelcome()
+ {
+ QMessageBox::information(this,"","Welcome!");
+ }
+ void notifyError()
+ {
+ qDebug() << "notifyError";
+ QMessageBox::warning(this,"Not Logged in","Login has failed...");
+ emit contIntent();
+ }
+
+ void notifyHello(const QString & name)
+ {
+ QMessageBox::information(this,"Welcome",QString("Hello ") + name);
+ }
+
+ signals:
+ void loginIntent();
+ void logoutIntent();
+ void cancelIntent();
+ void contIntent();
+};
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+
+ AbstractModel* model = QSslSocket::supportsSsl () ? (AbstractModel*)new GMailModel() : (AbstractModel*)new DummyModel();
+ MyView* view = new MyView();
+ SMClass_controller *controller = new SMClass_controller();
+ controller->setupStateMachine();
+ controller->set_loginButton(view->loginButton);
+ controller->set_logoutButton(view->logoutButton);
+ controller->set_cancelButton(view->cancelButton);
+ QObject::connect(controller,SIGNAL(event_login_action(QString,QString)),model,SLOT(login(QString,QString)));
+ QObject::connect(controller,SIGNAL(event_notify_loggedIn()),view,SLOT(notifyLogin()));
+ QObject::connect(controller,SIGNAL(event_notify_error()),view,SLOT(notifyError()));
+ QObject::connect(controller,SIGNAL(event_notify_hello(QString)),view,SLOT(notifyHello(QString)));
+ QObject::connect(controller,SIGNAL(event_notify_welcome()),view,SLOT(notifyWelcome()));
+ QObject::connect(controller,SIGNAL(event_notify_timeout()),view,SLOT(notifyTimeout()));
+ QObject::connect(model,SIGNAL(loginComplete(bool)),controller,SIGNAL(event_login_complete(bool)));
+ QObject::connect(view,SIGNAL(loginIntent()),controller,SIGNAL(event_intent_login()));
+ QObject::connect(view,SIGNAL(cancelIntent()),controller,SIGNAL(event_cancel_login()));
+ QObject::connect(view,SIGNAL(logoutIntent()),controller,SIGNAL(event_intent_logout()));
+ QObject::connect(view,SIGNAL(contIntent()),controller,SIGNAL(event_intent_continue()));
+ QObject::connect(view->usernameEdit,SIGNAL(textChanged(QString)),controller,SLOT(set_username(QString)));
+ QObject::connect(view->passwordEdit,SIGNAL(textChanged(QString)),controller,SLOT(set_password(QString)));
+ QObject::connect(view->timeoutSlider,SIGNAL(valueChanged(int)),controller,SLOT(set_loginTimeout(int)));
+ controller->start();
+ view->show();
+ QObject::connect(view,SIGNAL(closed()),qApp,SLOT(quit()));
+ return a.exec();
+}
+#include <main.moc>
diff --git a/scc/main.cpp b/scc/main.cpp
index 4ed1aff..e5f4206 100644
--- a/scc/main.cpp
+++ b/scc/main.cpp
@@ -1,23 +1,97 @@
-#include <QtCore/QCoreApplication>
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://www.qtsoftware.com/contact.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QCoreApplication>
#include <QXmlQuery>
#include <QUrl>
#include <QStringList>
#include <QFile>
#include <QFileInfo>
+#include <QDir>
+#include <QDebug>
+#include <QXmlSchema>
+#include <QXmlSchemaValidator>
+void usage()
+{
+ printf("scc [--no-comments] -i input-file -o output-file");
+ exit(-1);
+}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QXmlQuery query(QXmlQuery::XSLT20);
- QUrl target = QUrl::fromLocalFile(a.arguments()[1]);
+ if (a.arguments().count() < 3 || a.arguments().contains("--help"))
+ {
+ usage();
+ }
+ int idxOfInput = a.arguments().indexOf("-i")+1;
+ int idxOfOutput = a.arguments().indexOf("-o")+1;
+ if (idxOfInput <= 1 && idxOfOutput <= 1)
+ {
+ usage();
+ }
+ QString input = a.arguments().at(idxOfInput);
+ QString output = a.arguments().at(idxOfOutput);
+ QUrl target = QUrl::fromLocalFile(QDir::current().absoluteFilePath(".")).resolved(QUrl(input));
+// QXmlSchema schema;
+// QFile schemaFile(":/scxml.xsd");
+// schemaFile.open(QIODevice::ReadOnly);
+// schema.load(&schemaFile);
+// QXmlSchemaValidator validator;
+// if (!validator.validate(target)) {
+// return -1;
+// }
query.setFocus(target);
QFile q(":/scc/scc.xslt");
q.open(QIODevice::ReadOnly);
query.bindVariable("target",QXmlItem(QFileInfo(target.toLocalFile()).baseName()));
+ query.bindVariable("comments",QXmlItem(!a.arguments().contains("--no-comments")));
query.setQuery(QString(q.readAll()));
+ if (!query.isValid())
+ return -1;
+
QString s;
query.evaluateTo(&s);
- s = s.replace("&lt;","<").replace("&gt;",">").replace("&amp;","&");
- QFile f(a.arguments()[2]);
+ s = s.replace("&lt;","<").replace("&quot;","\"").replace("&gt;",">").replace("&amp;","&");
+ QFile f(output);
f.open(QIODevice::WriteOnly);
f.write(s.toUtf8());
return 0;
diff --git a/scc/scc.prf b/scc/scc.prf
new file mode 100644
index 0000000..b6ecc21
--- /dev/null
+++ b/scc/scc.prf
@@ -0,0 +1,21 @@
+isEmpty(QMAKE_SCC) {
+ win32:QMAKE_SCC = $$[QT_INSTALL_BINS]\scc.exe
+ else:QMAKE_SCC = $$[QT_INSTALL_BINS]/scc
+}
+
+isEmpty(QMAKE_MOD_SCC):QMAKE_MOD_SCC = sc_
+
+scc.output = $$QMAKE_MOD_SCC${QMAKE_FILE_BASE}.h
+scc.commands = $$QMAKE_SCC -i ${QMAKE_FILE_NAME} -o ${QMAKE_FILE_OUT}
+scc.depends = ${QMAKE_FILE_NAME} $$QMAKE_SCC
+scc.input = STATECHARTS
+scc.variable_out = SCC_HEADERS HEADERS GENERATED_FILES
+QMAKE_EXTRA_COMPILERS += scc
+load(moc)
+scc_moc.commands = $$moc_header.commands
+scc_moc.output = $$moc_header.output
+scc_moc.input = SCC_HEADERS
+scc_moc.variable_out = GENERATED_SOURCES
+scc_moc.name = $$moc_header.name
+QMAKE_EXTRA_COMPILERS += scc_moc
+
diff --git a/scc/scc.pro b/scc/scc.pro
index db41f1e..32008bb 100644
--- a/scc/scc.pro
+++ b/scc/scc.pro
@@ -1,16 +1,16 @@
# -------------------------------------------------
# Project created by QtCreator 2009-08-02T10:07:01
# -------------------------------------------------
-QT += network \
- xmlpatterns
+QT += xmlpatterns
QT -= gui
TARGET = scc
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
-OTHER_FILES += scc.xslt \
- test.scxml \
- scc-example.hh \
- xipr.xsl
RESOURCES += scc.qrc
+target.path = $$[QT_INSTALL_PREFIX]/bin
+prf.files = scc.prf
+prf.path = $$[QMAKE_MKSPECS]/features
+INSTALLS += target prf
+OTHER_FILES += scc.prf
diff --git a/scc/scc.qrc b/scc/scc.qrc
index a03d93a..0e4ffa0 100644
--- a/scc/scc.qrc
+++ b/scc/scc.qrc
@@ -1,6 +1,5 @@
<RCC>
- <qresource prefix="/scc" >
+ <qresource prefix="/scc">
<file>scc.xslt</file>
- <file>xipr.xsl</file>
</qresource>
</RCC>
diff --git a/scc/scc.xslt b/scc/scc.xslt
index de42521..e023e96 100644
--- a/scc/scc.xslt
+++ b/scc/scc.xslt
@@ -1,73 +1,112 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
-<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
-<xsl:template name="smname"><xsl:choose><xsl:when test="string(/scxml/@name)=''"><xsl:value-of select="$target" /></xsl:when>
- <xsl:otherwise><xsl:value-of select="/scxml/@name" /></xsl:otherwise></xsl:choose>
+<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:s="http://www.w3.org/2005/07/scxml"
+ xmlns:Qt="http://www.qtsoftware.com scxml-ext">
+<xsl:template name="smname"><xsl:choose><xsl:when test="string(/s:scxml/@name)=''"><xsl:value-of select="$target" /></xsl:when>
+ <xsl:otherwise><xsl:value-of select="/sLscxml/@name" /></xsl:otherwise></xsl:choose>
</xsl:template>
-<xsl:template mode="stateid" match="*">
- <xsl:choose >
+<xsl:template name="comment"><xsl:if test="$comments">
+ /*
+ <xsl:element name="{name()}">
+ <xsl:for-each select="@*"><xsl:attribute name="{name()}">
+ <xsl:value-of select="string()" /></xsl:attribute></xsl:for-each><xsl:value-of select="text()" /></xsl:element>
+ */
+</xsl:if></xsl:template>
+<xsl:template mode="stateid" match="s:scxml|s:state|s:parallel|s:final|s:initial|s:history" priority="2">
+ <xsl:choose>
<xsl:when test="name()='scxml'">this</xsl:when>
<xsl:when test="string(@id) != ''" >state_<xsl:value-of select="@id" /></xsl:when>
<xsl:otherwise>state_<xsl:value-of select="generate-id()" /></xsl:otherwise>
</xsl:choose>
</xsl:template>
-<xsl:template mode="execContext" match="if">
- if (<xsl:value-of select="@cond" />) {
+<xsl:template mode="execContext" match="s:if">
+<xsl:call-template name="comment" />
+ if (<xsl:value-of select="@cond" />) {
<xsl:apply-templates mode="execContext" />
- }
+ }
</xsl:template>
-<xsl:template mode="execContext" match="else">
- } else {
+<xsl:template mode="execContext" match="s:else">
+<xsl:call-template name="comment" />
+ } else {
</xsl:template>
-<xsl:template mode="execContext" match="elseif">
- } else if (<xsl:value-of select="@cond" />) {
+<xsl:template mode="execContext" match="s:elseif">
+<xsl:call-template name="comment" />
+ } else if (<xsl:value-of select="@cond" />) {
</xsl:template>
-<xsl:template mode="execContext" match="log">
- QDebug((QtMsgType)<xsl:if test="string(@level)=''">0</xsl:if><xsl:value-of select="@level" />) &lt;&lt; "<xsl:value-of select="@label" />" &lt;&lt; <xsl:value-of select="@expr" />;
+<xsl:template mode="execContext" match="s:log">
+<xsl:call-template name="comment" />
+ QDebug((QtMsgType)<xsl:if test="string(@level)=''">0</xsl:if><xsl:value-of select="@level" />) <xsl:if test="string(@label)!=''">&lt;&lt; "<xsl:value-of select="@label" />" </xsl:if>&lt;&lt; <xsl:value-of select="@expr" />;
</xsl:template>
-<xsl:template mode="execContext" match="assign">
- <xsl:if test="string(@dataid) != ''">
- set_<xsl:value-of select="@dataid" />(<xsl:value-of select="@expr" />);
- </xsl:if>
+<xsl:template mode="execContext" match="s:assign"><xsl:call-template name="comment" />
+<xsl:choose>
+
+ <xsl:when test="string(@dataid) != ''">
+ set_<xsl:value-of select="@dataid" />(<xsl:value-of select="@expr" />);
+ </xsl:when>
+ <xsl:when test="string(@location) != ''">
+ <xsl:value-of select="@location" /> = (<xsl:value-of select="@expr" />);
+ </xsl:when>
+</xsl:choose>
</xsl:template>
-<xsl:template mode="execContext" match="raise|send">
+<xsl:template mode="execContext" match="s:raise|s:send">
+<xsl:call-template name="comment" />
<xsl:choose>
<xsl:when test="name()='raise' or target='_internal'">postInternalEvent(</xsl:when>
<xsl:otherwise><xsl:if test="string(@id)!=''">
- eventSenders[<xsl:value-of select="@id" />] = </xsl:if>new SCC_EventSender(this,<xsl:if test="string(@delay)=''">0</xsl:if>
+ _eventSenders["<xsl:value-of select="@id" />"] = </xsl:if>new SCC_EventSender(this,<xsl:if test="string(@delay)=''">0</xsl:if>
<xsl:value-of select="@delay" />,
</xsl:otherwise>
- </xsl:choose>new QSignalEvent(<xsl:if
+ </xsl:choose>
+ new QSignalEvent(<xsl:if
test="string(@target)=''">this</xsl:if><xsl:value-of
- select="@target" />,(*metaObject()).indexOfSignal("<xsl:value-of select="replace(@event,'\.','__')" />"),QVariantList()<xsl:for-each
- select="param"><xsl:text><![CDATA[<<]]></xsl:text> QVariant(<xsl:value-of select="@expr" /><xsl:value-of select="text()" />)
+ select="@target" />,metaObject()->indexOfSignal(QMetaObject::normalizedSignature("event_<xsl:value-of select="replace(@event,'\.','__')" /><xsl:if test="not(contains(@event,')'))">()</xsl:if>")),QVariantList()<xsl:for-each
+ select="s:param"><xsl:text><![CDATA[<<]]></xsl:text> QVariant(<xsl:choose>
+ <xsl:when test="string(@expr)!=''"><xsl:value-of select="@expr" /></xsl:when>
+ <xsl:when test="string(@name)!=''">get_<xsl:value-of select="@name" />()</xsl:when>
+ <xsl:otherwise><xsl:value-of select="text()" /></xsl:otherwise>
+ </xsl:choose>)
</xsl:for-each>));
</xsl:template>
-<xsl:template mode="execContext" match="cancel">
- { QObject* obj = eventSenders[<xsl:value-of select="@id" />]; if (obj) { (*obj).cancel(); }
+<xsl:template mode="execContext" match="s:cancel">
+<xsl:call-template name="comment" /><![CDATA[
+ {
+ QPointer<SCC_EventSender> es = _eventSenders["]]><xsl:value-of select="@id" />"];
+ if (es)
+ es->cancel();
+ }
</xsl:template>
<xsl:template match="/">
+#ifndef __SMCLASS_<xsl:call-template name="smname" />_H
+#define __SMCLASS_<xsl:call-template name="smname" />_H
#include "QStateMachine"
#include "QSignalTransition"
-<xsl:if test="count(//send[@target!='_internal']) != 0">
#include "QTimer"
-</xsl:if>
-<xsl:if test="count(//final)!=0">
+#include "QMetaMethod"
+#include "QPointer"
+#include "QVariant"
+<xsl:if test="count(//s:final)!=0">
+
#include "QFinalState"
</xsl:if>
-<xsl:if test="count(//history)!=0">
+<xsl:if test="count(//s:history)!=0">
#include "QHistoryState"
</xsl:if>
#include "QHash"
#include "QSignalEvent"
#include "QEventTransition"
-<xsl:if test="count(//log)!=0">
+<xsl:if test="count(//s:log)!=0">
#include "QDebug"
</xsl:if>
-#ifndef __SMCLASS_<xsl:call-template name="smname" />_H
-#define __SMCLASS_<xsl:call-template name="smname" />_H
+<xsl:if test="count(//s:transition[string(@Qt:animation)!=''])!=0">
+#include "QPropertyAnimation"
+</xsl:if>
+
+#define In(state) (configuration().contains(state_##state))
+
+<xsl:value-of select="/s:scxml/Qt:cpp/text()" />
+
class SMClass_<xsl:call-template name="smname" />;
- <xsl:if test="count(//transition[string(@event)='' and string(@cond)=''])!=0">
+ <xsl:if test="count(//s:transition[string(@event)='' and string(@cond)=''])!=0">
class SCC_UnconditionalTransition : public QAbstractTransition
{
public:
@@ -78,34 +117,51 @@ class SMClass_<xsl:call-template name="smname" />;
bool eventTest(QEvent *) { return true; }
};
</xsl:if>
- <xsl:if test="count(//send[string(@target)!='_internal'])!=0">
+ <xsl:if test="count(//s:send[string(@target)!='_internal'])!=0">
+ <![CDATA[
+ #define ARG_FROM_VAR(I) \
+ (acount > I \
+ ? QGenericArgument(((QSignalEvent*)event)->arguments()[I].typeName(),((QSignalEvent*)event)->arguments()[I].data()) \
+ : QGenericArgument())
+
+
class SCC_EventSender : public QTimer
{
Q_OBJECT
private:
QStateMachine* machine;
- QEvent* event;
+ QSignalEvent* event;
public:
- SCC_EventSender(QStateMachine* m, int delay, QEvent* e) : QTimer(m), machine(m), event(e)
+ SCC_EventSender(QStateMachine* m=NULL, int delay=0, QSignalEvent* e=NULL) : QTimer(m), machine(m), event(e)
{
setInterval(delay);
setSingleShot(true);
connect(this,SIGNAL(timeout()),this,SLOT(send()));
+ start();
}
public Q_SLOTS:
void cancel() { stop(); deleteLater(); }
- void send() { machine->postEvent(event); }
+ void send() {
+ QVariantList args = event->arguments();
+ int acount = args.count();
+ event->sender()->metaObject()->method(event->signalIndex()).invoke(event->sender(),
+ ARG_FROM_VAR(0),ARG_FROM_VAR(1),ARG_FROM_VAR(2),ARG_FROM_VAR(3),ARG_FROM_VAR(4),
+ ARG_FROM_VAR(5),ARG_FROM_VAR(6),ARG_FROM_VAR(7),ARG_FROM_VAR(8),ARG_FROM_VAR(9));
+ deleteLater();
+ }
};
- </xsl:if>
- <xsl:if test="count(//transition[string(@cond) != '']) !=0">
+ ]]></xsl:if>
+ <xsl:if test="count(//s:transition[string(@cond) != '' or @event='*']) !=0">
namespace {
- <xsl:for-each select="//transition[string(@cond) != '']">
- class Transition_<xsl:value-of select="generate-id()" /> : public Q<xsl:if test="string(@event) != ''">Signal</xsl:if>Transition
+ <xsl:for-each select="//s:transition[string(@cond) != '' or @event='*']">
+ <xsl:call-template name="comment" />
+ class Transition_<xsl:value-of select="generate-id()" /> : public QSignalTransition
{
SMClass_<xsl:call-template name="smname" />* stateMachine;
public:
Transition_<xsl:value-of select="generate-id()" />(QState* parent)
- : Q<xsl:if test="string(@event) != ''">Signal</xsl:if>Transition(parent),stateMachine((SMClass_<xsl:call-template name="smname" />*)(*parent).machine())
+ : QSignalTransition(parent->machine(),<xsl:choose><xsl:when test="@event='*'">SIGNAL(destroyed())</xsl:when><xsl:otherwise>SIGNAL(event_<xsl:value-of select="@event" />)</xsl:otherwise></xsl:choose>,parent)
+ ,stateMachine((SMClass_<xsl:call-template name="smname" />*)parent->machine())
{
}
@@ -119,145 +175,197 @@ namespace {
class SMClass_<xsl:call-template name="smname" /> : public QStateMachine
{
Q_OBJECT
-<xsl:for-each select="//datamodel/data">
- Q_PROPERTY(<xsl:value-of select="concat(@type,' ')" /> <xsl:value-of select="@id" /> READ get_<xsl:value-of select="@id" /> WRITE set_<xsl:value-of select="@id" /> NOTIFY <xsl:value-of select="@id" />_changed)
+<xsl:for-each select="//s:datamodel/s:data">
+ <xsl:call-template name="comment" />
+ Q_PROPERTY(<xsl:value-of select="concat(@Qt:type,' ')" /> <xsl:value-of select="@id" /> READ get_<xsl:value-of select="@id" /> WRITE set_<xsl:value-of select="@id" /> NOTIFY <xsl:value-of select="@id" />_changed)
</xsl:for-each>
-<xsl:for-each select="//transition/@animation">
- Q_PROPERTY(QAbstractAnimation* <xsl:value-of select="string()" /> READ anim_<xsl:value-of select="string()" /> WRITE setAnim_<xsl:value-of select="string()" />)
+<xsl:for-each select="//s:transition/Qt:animation">
+ <xsl:call-template name="comment" />
+ Q_PROPERTY(QPropertyAnimation* <xsl:value-of select="string()" /> READ anim_<xsl:value-of select="string()" /> WRITE setAnim_<xsl:value-of select="string()" />)
</xsl:for-each>
public:
- SMClass_<xsl:call-template name="smname" />(QObject* o) : QStateMachine(o) {}
- <xsl:for-each select="//state|//parallel|//initial[count(transition/*)!=0]">
- QState* <xsl:apply-templates mode="stateid" select="current()" />;</xsl:for-each>
- <xsl:for-each select="//final">
- QFinalState* <xsl:apply-templates mode="stateid" select="current()" />;
+ SMClass_<xsl:call-template name="smname" />(QObject* o = NULL)
+ : QStateMachine(o)
+ {
+<xsl:for-each select="//s:datamodel/s:data[string-length(concat(string(text()),string(@expr)))!=0]">
+ <xsl:call-template name="comment" />
+ <xsl:if test="string(@expr) != ''">
+ _data.<xsl:value-of select="@id" /> = <xsl:value-of select="@expr"/><xsl:value-of select="text()"/>;
+ </xsl:if>
+</xsl:for-each>
+ }
+ <xsl:for-each select="//s:state|//s:parallel|//s:initial">
+ <xsl:call-template name="comment" />
+ QState* <xsl:apply-templates mode="stateid" select="." />;</xsl:for-each>
+ <xsl:for-each select="//s:final">
+ <xsl:call-template name="comment" />
+ QFinalState* <xsl:apply-templates mode="stateid" select="." />;
</xsl:for-each>
- <xsl:for-each select="//history">
- QHistoryState* <xsl:apply-templates mode="stateid" select="current()" />;
+ <xsl:for-each select="//s:history">
+ <xsl:call-template name="comment" />
+ QHistoryState* <xsl:apply-templates mode="stateid" select="." />;
</xsl:for-each>
- <xsl:for-each select="//transition[string(@cond) != '']">
- bool testCondition_<xsl:value-of select="generate-id()" />(const QEvent &amp; _event)
+ <xsl:for-each select="//s:transition[string(@cond) != '']">
+ <xsl:call-template name="comment" />
+ inline bool testCondition_<xsl:value-of select="generate-id()" />()
{
- Q_UNUSED(_event)
return <xsl:if test="string(@cond)=''">true</xsl:if><xsl:value-of select="@cond"/>;
}
</xsl:for-each>
- <xsl:for-each select="//datamodel/data">
- <xsl:value-of select="@type" /> get_<xsl:value-of select="@id" />() const
+ <xsl:for-each select="//s:datamodel/s:data">
+ <xsl:call-template name="comment" />
+ <xsl:text> </xsl:text><xsl:value-of select="@Qt:type" /> get_<xsl:value-of select="@id" />() const
{
return _data.<xsl:value-of select="@id" />;
}
- void set_<xsl:value-of select="@id" />(const <xsl:value-of select="@type" /> &amp; value)
- {
- _data.<xsl:value-of select="@id" /> = value;
- emit <xsl:value-of select="@id" />_changed(value);
- }
</xsl:for-each>
- <xsl:if test="count(//datamodel/data) != 0">
+ <xsl:if test="count(//s:datamodel/s:data) != 0"><![CDATA[
protected:
struct {
- <xsl:for-each select="//datamodel/data">
- <xsl:text> </xsl:text><xsl:value-of select="@type" /><xsl:text> </xsl:text><xsl:value-of select="@id" />;</xsl:for-each>
+ ]]><xsl:for-each select="//s:datamodel/s:data">
+ <xsl:call-template name="comment" />
+ <xsl:text> </xsl:text><xsl:value-of select="@Qt:type" /><xsl:text> </xsl:text><xsl:value-of select="@id" />;
+ </xsl:for-each>
} _data;
</xsl:if>
- <xsl:if test="(count(//datamodel/data)+count(/scxml/script))!=0">
- void initScript()
+ struct {
+ QString name;
+ QVariantList data;
+ } _event;
+ QString _name;
+ <xsl:if test="(count(//s:datamodel/s:data)+count(/s:scxml/s:script))!=0">
+ public Q_SLOTS:
+</xsl:if>
+<xsl:for-each select="//s:datamodel/s:data">
+ <xsl:call-template name="comment" />
+ void set_<xsl:value-of select="@id" />(<xsl:value-of select="@Qt:type" /> const &amp; value)
{
-<xsl:for-each select="//datamodel/data">
- <xsl:if test="string(@expr) != ''">
- _data.<xsl:value-of select="@id" /> = <xsl:value-of select="@expr"/><xsl:value-of select="text()"/>;
- </xsl:if>
-</xsl:for-each>
- <xsl:value-of select="/scxml/script/text()" />
+ _data.<xsl:value-of select="@id" /> = value;
+ emit <xsl:value-of select="@id" />_changed(value);
}
-</xsl:if>
+ </xsl:for-each>
private Q_SLOTS:
- <xsl:for-each select="//transition|//onentry|//onexit"><xsl:if test="count(*) != 0">
+#ifndef QT_NO_PROPERTIES
+ void assignProperties()
+ {
+ <xsl:for-each select="//Qt:property">
+ <xsl:call-template name="comment" />
+<xsl:text> </xsl:text><xsl:apply-templates mode="stateid" select=".." />->assignProperty(<xsl:value-of
+ select="@object" />,"<xsl:value-of select="@property" />",QVariant(<xsl:value-of select="@value" />));
+ </xsl:for-each>
+#endif
+ }
+ <xsl:for-each select="//s:transition|//s:onentry|//s:onexit"><xsl:if test="count(*) != 0">
+ <xsl:for-each select="..|."><xsl:call-template name="comment" /></xsl:for-each>
void exec_<xsl:value-of select="generate-id()" />()
{
<xsl:apply-templates mode="execContext" />
}
</xsl:if></xsl:for-each>
- Q_SIGNALS:<xsl:for-each select="distinct-values(//node()[not (starts-with(@event,'done.state.') or contains(@event,':'))]/@event)">
- void event_<xsl:value-of select="replace(string(),'\.','__')" />();</xsl:for-each>
- <xsl:for-each select="//datamodel/data">
- void <xsl:value-of select="@id" />_changed(const <xsl:value-of select="@type" /> &amp;);
+ Q_SIGNALS:<xsl:for-each select="distinct-values(//node()[not (starts-with(@event,'done.state.') or @event='*' or contains(@event,':'))]/@event)">
+ void event_<xsl:value-of select="replace(string(),'\.','__')" /><xsl:if test="not(contains(string(),')'))">()</xsl:if>;</xsl:for-each>
+ <xsl:for-each select="//s:datamodel/s:data">
+ <xsl:call-template name="comment" />
+ void <xsl:value-of select="@id" />_changed(<xsl:value-of select="@Qt:type" /> const &amp;);
</xsl:for-each>
- <xsl:if test="count(//property)!=0">
+ <xsl:if test="count(//Qt:property)!=0"><![CDATA[
protected:
-#ifndef QT_NO_PROPERTIES
- virtual void endSelectTransitions(QEvent *event)
+ virtual void beginSelectTransitions(QEvent *event)
{
- <xsl:for-each select="//property">
- (*<xsl:apply-templates mode="stateid" select=".." />).assignProperty(<xsl:value-of
- select="@object" />,"<xsl:value-of select="@name" />",QVariant(<xsl:value-of select="@expr" />));
- </xsl:for-each>
+ if (event && !event->type() == QEvent::None) {
+ switch (event->type()) {
+ case QEvent::Signal: {
+ QSignalEvent* e = (QSignalEvent*)event;
+ _event.data = e->arguments();
+ _event.name = e->sender()->metaObject()->method(e->signalIndex()).signature();
+ if (e->sender() == this)
+ _event.name = _event.name.mid(6);
+ } break;
+ default:
+ break;
+ }
+ } else {
+ _event.name = "";
+ _event.data.clear();
+ }
+ ]]>
+ assignProperties();
}
-#endif
- </xsl:if>
-<xsl:if test="count(//send[string(@target)!='internal']) != 0">
+</xsl:if>
+<xsl:if test="count(//s:send[string(@target)!='internal']) != 0">
private:
- <xsl:text><![CDATA[QHash<QString,SCC_EventSender>]]></xsl:text> _eventSenders;
+ <xsl:text><![CDATA[QHash<QString,QPointer<SCC_EventSender> >]]></xsl:text> _eventSenders;
</xsl:if>
+ protected:
public:
void setupStateMachine()
{
- setObjectName("<xsl:call-template name="smname" />");
- <xsl:for-each select="//state|//parallel|//final|//history|//initial">
- <xsl:apply-templates mode="stateid" select="." /> = new <xsl:choose>
+ _name = "<xsl:call-template name="smname" />";
+ setObjectName(_name);
+ <xsl:for-each select="//s:state|//s:parallel|//s:final|//s:history|//s:initial">
+ <xsl:call-template name="comment" />
+ <xsl:text> </xsl:text><xsl:apply-templates mode="stateid" select="." /> = new <xsl:choose>
<xsl:when test="name()='final'">QFinalState</xsl:when>
<xsl:when test="name()='history'">QHistoryState</xsl:when>
<xsl:otherwise>QState</xsl:otherwise>
</xsl:choose>(<xsl:apply-templates mode="stateid" select=".." />);
- (*<xsl:apply-templates mode="stateid" select="." />).setObjectName("<xsl:value-of select="@id" />");
- <xsl:if
+ <xsl:if test="string(@id)!=''"><xsl:apply-templates mode="stateid" select="." />->setObjectName("<xsl:value-of select="@id" />");</xsl:if>
+ <xsl:if
test="name()='initial' or @id=../@initial">
- (*<xsl:apply-templates mode="stateid" select=".." />).setInitialState(<xsl:apply-templates mode="stateid" select="." />);</xsl:if>
+ <xsl:apply-templates mode="stateid" select=".." />->setInitialState(<xsl:apply-templates mode="stateid" select="." />);
+ </xsl:if>
<xsl:if test="name()='parallel'">
- (*<xsl:apply-templates mode="stateid" select="." />).setChildMode(ParallelStates);
- </xsl:if>
+ <xsl:apply-templates mode="stateid" select="." />->setChildMode(ParallelStates);
+ </xsl:if>
<xsl:if test="name()='history'">
- (*<xsl:apply-templates mode="stateid" select="." />).setHistoryType(QHistoryState::<xsl:choose>
+ <xsl:apply-templates mode="stateid" select="." />->setHistoryType(QHistoryState::<xsl:choose>
<xsl:when test="@type='deep'">Deep</xsl:when>
<xsl:otherwise>Shallow</xsl:otherwise>
</xsl:choose>History);
- </xsl:if>
+ </xsl:if>
</xsl:for-each>
- QAbstractTransition* transition;<xsl:for-each select="//transition">
+ QAbstractTransition* transition;<xsl:for-each select="//s:transition[../name()!='history']">
+ <xsl:call-template name="comment" />
transition = new <xsl:choose>
- <xsl:when test="string(@cond)!=''">Transition_<xsl:value-of
+ <xsl:when test="@event='*' or string(@cond)!=''">Transition_<xsl:value-of
select="generate-id()" />(</xsl:when>
<xsl:when test="starts-with(@event,'q-event:')">QEventTransition(<xsl:value-of
select="substring-after(@event,'q-event:')" />,</xsl:when>
<xsl:when test="starts-with(@event,'done.state.')">QSignalTransition(state_<xsl:value-of
select="substring-after(@event,'done.state.')" />,SIGNAL(finished()),</xsl:when>
- <xsl:when test="string(@event)!=''">QSignalTransition(this,SIGNAL(event_<xsl:value-of select="replace(@event,'\.','__')" />()),</xsl:when>
+ <xsl:when test="string(@event)!=''">QSignalTransition(this,SIGNAL(event_<xsl:value-of select="replace(@event,'\.','__')" /><xsl:if test="not(ends-with(@event,')'))">()</xsl:if>),</xsl:when>
<xsl:otherwise>SCC_UnconditionalTransition(</xsl:otherwise></xsl:choose><xsl:apply-templates mode="stateid" select=".." />);<xsl:if test="count(*) != 0">
connect(transition,SIGNAL(triggered()),this,SLOT(exec_<xsl:value-of select="generate-id()" />()));</xsl:if>
- <xsl:if test="string(@animation) != ''">
- (*transition).addAnimation(<xsl:value-of select="@animation" />);</xsl:if><xsl:if
+ <xsl:if test="string(@Qt:animation) != ''">
+ transition->addAnimation(<xsl:value-of select="@Qt:animation" />);</xsl:if><xsl:if
test="string(@target) != ''"></xsl:if>
<xsl:choose>
<xsl:when test="string(@target)=''" />
<xsl:when test="count(tokenize(@target,'\s+'))=1">
- (*transition).setTargetState(state_<xsl:value-of select="@target" />);</xsl:when>
+ transition->setTargetState(state_<xsl:value-of select="@target" />);</xsl:when>
<xsl:otherwise>(*transition).setTargetStates(QList&lt;QAbstractState*&gt;()<xsl:for-each
select="tokenize(@target,'\s+')"> &lt;&lt; state_<xsl:value-of select="." /></xsl:for-each>);</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
- <xsl:for-each select="//onentry|//onexit"><xsl:if test="count(*) != 0">
+ <xsl:for-each select="//s:history/s:transition">
+ <xsl:apply-templates mode="stateid" select=".." />->setDefaultState(state_<xsl:value-of select="@target" />);
+ </xsl:for-each>
+ <xsl:for-each select="//s:onentry|//s:onexit"><xsl:if test="count(*) != 0">
connect(<xsl:apply-templates mode="stateid" select=".." />, SIGNAL(<xsl:choose>
<xsl:when test="name()='onentry'">entered</xsl:when>
<xsl:when test="name()='onexit'">exited</xsl:when>
</xsl:choose>()),this,SLOT(exec_<xsl:value-of select="generate-id()" />()));</xsl:if></xsl:for-each>
+ <xsl:value-of select="/s:scxml/s:script/text()" />
}
};
- <xsl:for-each select="//transition[string(@cond) != '']">
+ <xsl:for-each select="//s:transition[@event='*' or string(@cond) != '']">
+ <xsl:call-template name="comment" />
bool Transition_<xsl:value-of select="generate-id()" />::eventTest(QEvent* e)
{
- return Q<xsl:if test="string(@event) != ''">Signal</xsl:if>Transition::eventTest(e)
- &amp;&amp; stateMachine-&gt;testCondition_<xsl:value-of select="generate-id()" />(e?(*e):QEvent(QEvent::None));
+ return <xsl:choose><xsl:when test="@event!='*'">Q<xsl:if test="string(@event) != ''">Signal</xsl:if>Transition::eventTest(e)
+ </xsl:when><xsl:otherwise>(*e).type() != QEvent::None</xsl:otherwise></xsl:choose><xsl:if test="string(@cond)!=''">&amp;&amp; stateMachine-&gt;testCondition_<xsl:value-of
+ select="generate-id()" />()</xsl:if>;
}
</xsl:for-each>
#endif