diff options
Diffstat (limited to 'scc')
-rw-r--r-- | scc/README | 13 | ||||
-rw-r--r-- | scc/doc.txt | 78 | ||||
-rw-r--r-- | scc/examples/algotest/algotest.pro | 6 | ||||
-rw-r--r-- | scc/examples/algotest/main.cpp | 56 | ||||
-rw-r--r-- | scc/examples/algotest/test.scxml | 145 | ||||
-rw-r--r-- | scc/examples/animations/animations.pro | 6 | ||||
-rw-r--r-- | scc/examples/animations/animations.scxml | 19 | ||||
-rw-r--r-- | scc/examples/animations/main.cpp | 81 | ||||
-rw-r--r-- | scc/examples/examples.pro | 2 | ||||
-rw-r--r-- | scc/examples/loginmvc/controller.scxml | 105 | ||||
-rw-r--r-- | scc/examples/loginmvc/frame.ui | 123 | ||||
-rw-r--r-- | scc/examples/loginmvc/loginmvc.pro | 8 | ||||
-rw-r--r-- | scc/examples/loginmvc/main.cpp | 192 | ||||
-rw-r--r-- | scc/main.cpp | 82 | ||||
-rw-r--r-- | scc/scc.prf | 21 | ||||
-rw-r--r-- | scc/scc.pro | 12 | ||||
-rw-r--r-- | scc/scc.qrc | 3 | ||||
-rw-r--r-- | scc/scc.xslt | 330 |
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=""Inside Test1""/> + </onentry> + + <!-- Here is our first substate --> + <state id="Test1Sub1"> + <onentry> + <log expr=""Inside Test1Sub1.""/> + </onentry> + <onexit> + <log expr=""Leaving Test1Sub1""/> + </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=""Leaving Test1...""/> + </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=""Inside Test2Sub1""/> + </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=""Inside Test3Sub1...""/> + <!-- 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=""Leaving Test3Sub1...""/> + </onexit> + </state> + + <onexit> + <log expr=""Leaving Test3...""/> + </onexit> + </state> + + <state id="Test4"> + <onentry> + <log expr=""Inside Test4...""/> + </onentry> + <initial> + <transition target="Test4Sub1"/> + </initial> + + <state id="Test4Sub1"> + <onexit> + <log expr=""Leaving Test4Sub1...""/> + </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=""Inside Test5...""/> + </onentry> + <initial> + <transition target="Test5P"/> + </initial> + + <!-- Fire off our parallel states --> + <parallel id="Test5P"> + <final id="Test5PSub1"/> + <final id="Test5PSub2"/> + <onexit> + <log expr=""all parallel states done""/> + </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=""Now in Idle"" /><raise event="in_idle" /></onentry> + <onexit><log level="0" label="Info" expr=""Now not in Idle"" /><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=""Trying to log in"" /> + <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("<","<").replace(">",">").replace("&","&"); - QFile f(a.arguments()[2]); + s = s.replace("<","<").replace(""","\"").replace(">",">").replace("&","&"); + 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" />) << "<xsl:value-of select="@label" />" << <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)!=''"><< "<xsl:value-of select="@label" />" </xsl:if><< <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 & _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" /> & 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 & 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" /> &); + 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 &); </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<QAbstractState*>()<xsl:for-each select="tokenize(@target,'\s+')"> << 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) - && stateMachine->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)!=''">&& stateMachine->testCondition_<xsl:value-of + select="generate-id()" />()</xsl:if>; } </xsl:for-each> #endif |