diff options
-rw-r--r-- | examples/scc/algotest/algotest.pro (renamed from scc/examples/algotest/algotest.pro) | 0 | ||||
-rw-r--r-- | examples/scc/algotest/main.cpp (renamed from scc/examples/algotest/main.cpp) | 0 | ||||
-rw-r--r-- | examples/scc/algotest/test.scxml (renamed from scc/examples/algotest/test.scxml) | 0 | ||||
-rw-r--r-- | examples/scc/animations/animations.pro (renamed from scc/examples/animations/animations.pro) | 0 | ||||
-rw-r--r-- | examples/scc/animations/animations.scxml (renamed from scc/examples/animations/animations.scxml) | 0 | ||||
-rw-r--r-- | examples/scc/animations/main.cpp (renamed from scc/examples/animations/main.cpp) | 0 | ||||
-rw-r--r-- | examples/scc/examples.pro (renamed from scc/examples/examples.pro) | 0 | ||||
-rw-r--r-- | examples/scc/loginmvc/controller.scxml (renamed from scc/examples/loginmvc/controller.scxml) | 0 | ||||
-rw-r--r-- | examples/scc/loginmvc/frame.ui (renamed from scc/examples/loginmvc/frame.ui) | 0 | ||||
-rw-r--r-- | examples/scc/loginmvc/loginmvc.pro (renamed from scc/examples/loginmvc/loginmvc.pro) | 0 | ||||
-rw-r--r-- | examples/scc/loginmvc/main.cpp (renamed from scc/examples/loginmvc/main.cpp) | 0 | ||||
-rw-r--r-- | qmlscxml/qmlscxml.cpp | 221 | ||||
-rw-r--r-- | qmlscxml/qmlscxml.h | 62 | ||||
-rw-r--r-- | qmlscxml/qmlscxml.pri | 7 | ||||
-rw-r--r-- | src/qscxml.cpp | 3 |
15 files changed, 291 insertions, 2 deletions
diff --git a/scc/examples/algotest/algotest.pro b/examples/scc/algotest/algotest.pro index e5a1eba..e5a1eba 100644 --- a/scc/examples/algotest/algotest.pro +++ b/examples/scc/algotest/algotest.pro diff --git a/scc/examples/algotest/main.cpp b/examples/scc/algotest/main.cpp index 4fe6364..4fe6364 100644 --- a/scc/examples/algotest/main.cpp +++ b/examples/scc/algotest/main.cpp diff --git a/scc/examples/algotest/test.scxml b/examples/scc/algotest/test.scxml index e17f9bf..e17f9bf 100644 --- a/scc/examples/algotest/test.scxml +++ b/examples/scc/algotest/test.scxml diff --git a/scc/examples/animations/animations.pro b/examples/scc/animations/animations.pro index d501c13..d501c13 100644 --- a/scc/examples/animations/animations.pro +++ b/examples/scc/animations/animations.pro diff --git a/scc/examples/animations/animations.scxml b/examples/scc/animations/animations.scxml index 0aabb64..0aabb64 100644 --- a/scc/examples/animations/animations.scxml +++ b/examples/scc/animations/animations.scxml diff --git a/scc/examples/animations/main.cpp b/examples/scc/animations/main.cpp index 296e582..296e582 100644 --- a/scc/examples/animations/main.cpp +++ b/examples/scc/animations/main.cpp diff --git a/scc/examples/examples.pro b/examples/scc/examples.pro index 39b6dbb..39b6dbb 100644 --- a/scc/examples/examples.pro +++ b/examples/scc/examples.pro diff --git a/scc/examples/loginmvc/controller.scxml b/examples/scc/loginmvc/controller.scxml index 8bffc1a..8bffc1a 100644 --- a/scc/examples/loginmvc/controller.scxml +++ b/examples/scc/loginmvc/controller.scxml diff --git a/scc/examples/loginmvc/frame.ui b/examples/scc/loginmvc/frame.ui index 4b57955..4b57955 100644 --- a/scc/examples/loginmvc/frame.ui +++ b/examples/scc/loginmvc/frame.ui diff --git a/scc/examples/loginmvc/loginmvc.pro b/examples/scc/loginmvc/loginmvc.pro index 9af965a..9af965a 100644 --- a/scc/examples/loginmvc/loginmvc.pro +++ b/examples/scc/loginmvc/loginmvc.pro diff --git a/scc/examples/loginmvc/main.cpp b/examples/scc/loginmvc/main.cpp index a8e9ee9..a8e9ee9 100644 --- a/scc/examples/loginmvc/main.cpp +++ b/examples/scc/loginmvc/main.cpp diff --git a/qmlscxml/qmlscxml.cpp b/qmlscxml/qmlscxml.cpp new file mode 100644 index 0000000..2183945 --- /dev/null +++ b/qmlscxml/qmlscxml.cpp @@ -0,0 +1,221 @@ +#include "qmlscxml.h" +#include "qscxml.h" +#include <QDebug> +#include "qmlpropertymap.h" + +class QmlScxmlEventProxy : public QObject +{ + Q_OBJECT + QScxml* scxml; + QString eventName; + public: + QmlScxmlEventProxy (const QString & name, QScxml* scx): QObject(scx) + ,scxml(scx),eventName(name) + { + connect(scxml,SIGNAL(eventTriggered(QString)),this,SLOT(onEvent(QString))); + } + + Q_SIGNALS: + void triggered(); + + public Q_SLOTS: + void raise() + { + scxml->postNamedEvent(eventName); + } + + void onEvent(const QString & e) + { + if (e == eventName) { + emit triggered(); + } + } +}; +QmlScxml::QmlScxml(QObject* o) : QObject(o) + ,m_states(NULL),m_events(NULL),m_data(NULL),m_cur(NULL),scxml(NULL) +{ +} +QmlScxml::~QmlScxml() +{ +} +QObject* QmlScxml::states() const +{ + return m_states; +} +QObject* QmlScxml::events() const +{ + return m_events; +} +QObject* QmlScxml::data() const +{ + return m_data; +} +QObject* QmlScxml::current() const +{ + return m_cur; +} +QUrl QmlScxml::source() const +{ + return m_source; +} + +namespace { + QString _q_fixName(QString oldName) { + QString newName; + bool beginWord = false; + if (oldName == oldName.toUpper()) + oldName = oldName.toLower(); + + foreach (QChar c, oldName) { + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { + newName += beginWord ? c.toUpper() : (newName=="" ? c.toLower() :c); + beginWord = false; + } else if (newName != "") { + if (c >= '0' && c <= '9') { + newName += c; + } else + beginWord = true; + } + } + return newName; + } +}; +void QmlScxml::setSource(const QUrl & u) +{ + qDebug() << u; + if (u != m_source) { + m_source = u; + if (scxml) { + delete scxml; + scxml= NULL; + } + scxml = QScxml::load(u.toLocalFile(),this); + if (scxml) { + connect(scxml,SIGNAL(started()),this,SIGNAL(runningChanged())); + connect(scxml,SIGNAL(stopped()),this,SIGNAL(runningChanged())); + connect(scxml,SIGNAL(finished()),this,SIGNAL(finished())); + connect(scxml,SIGNAL(eventTriggered(QString)),this,SIGNAL(trigger(QString))); + connect(scxml,SIGNAL(configurationChanged()),this,SLOT(checkConfig())); + if (m_states) + delete m_states; + if (m_events) + delete m_events; + if (m_data) + delete m_data; + if (m_cur) + delete m_cur; + m_idForState.clear(); + m_states = new QmlPropertyMap(this); + m_events = new QmlPropertyMap(this); + m_data = new QmlPropertyMap(this); + m_cur = new QmlPropertyMap(this); + QMap<QString,QVariant> curData = scxml->data(); + for (QMap<QString,QVariant>::iterator it = curData.begin(); it != curData.end(); ++it) { + m_data->insert(it.key(),it.value()); + } + + connect(m_data,SIGNAL(valueChanged(QString)),this,SLOT(onDataChanged(QString))); + QList<QAbstractState*> states = scxml->findChildren<QAbstractState*>(); + m_oldConfig = scxml->configuration(); + foreach (QAbstractState* s, states) { + QString name = _q_fixName(s->objectName()); + if (name != "") { + m_states->insert(name,QVariant::fromValue<QObject*>(s)); + m_cur->insert(name,m_oldConfig.contains(s)); + m_idForState[s] = name; + } + } + QMap<QString,QString> prefixMap; + QStringList knownEvents = scxml->knownEventNames(); + foreach (QString ev, knownEvents) { + prefixMap[_q_fixName(ev)] = ev; + } + for (QMap<QString,QString>::iterator it = prefixMap.begin(); it != prefixMap.end(); ++it) { + if (it.key() != "" && it.value() != "") { + m_events->insert(it.key(),QVariant::fromValue<QObject*>(new QmlScxmlEventProxy(it.value(),scxml))); + } + } + emit statesChanged(m_states); + emit eventsChanged(m_events); + emit dataChanged(m_data); + emit currentChanged(m_cur); + scxml->start(); + } + emit sourceChanged(u); + } +} + +void QmlScxml::onDataChanged(const QString & key) +{ + m_data->blockSignals(true); + scxml->setData(key,(*m_data)[key]); + m_data->blockSignals(false); +} +void QmlScxml::onDataChanged(const QString & key, const QVariant & value) +{ + if (m_data) { + (*m_data)[key] = value; + } +} + +void QmlScxml::checkConfig() +{ + QSet<QAbstractState*> config = scxml->configuration(); + if (config != m_oldConfig) { + QSet<QAbstractState*> intersecting = config & m_oldConfig; + QSet<QAbstractState*> toRemove = m_oldConfig - intersecting; + QSet<QAbstractState*> toAdd = config - intersecting; + + for (QSet<QAbstractState*>::iterator it = toRemove.begin(); it != toRemove.end(); ++it) { + QString name = m_idForState[*it]; + if (name != "") { + (*m_cur)[name] = false; + } + } + for (QSet<QAbstractState*>::iterator it = toAdd.begin(); it != toAdd.end(); ++it) { + QString name = m_idForState[*it]; + if (name != "") { + (*m_cur)[name] = true; + } + } + m_oldConfig = config; + emit currentChanged(m_cur); + } +} + + +bool QmlScxml::isRunning() const +{ + return scxml?scxml->isRunning():false; +} +void QmlScxml::setRunning(bool r) +{ + if (scxml) { + if (r) { + scxml->start(); + } else { + scxml->stop(); + } + } +} +void QmlScxml::raise(const QString & e) +{ + if (scxml) { + scxml->postNamedEvent(e); + } +} +void QmlScxml::stop() +{ + if (scxml) { + scxml->stop(); + } +} +void QmlScxml::start() +{ + if (scxml) { + scxml->start(); + } +} +QML_DEFINE_TYPE(Scxml, 1,0, Scxml, QmlScxml); + +#include <qmlscxml.moc> diff --git a/qmlscxml/qmlscxml.h b/qmlscxml/qmlscxml.h new file mode 100644 index 0000000..b44b45f --- /dev/null +++ b/qmlscxml/qmlscxml.h @@ -0,0 +1,62 @@ +#ifndef QMLSCXML_H +#define QMLSCXML_H + +#include <QObject> +#include <QSet> +#include "qml.h" + +class QAbstractState; +class QmlScxml : public QObject +{ + Q_OBJECT + Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) + Q_PROPERTY(QObject* states READ states NOTIFY statesChanged) + Q_PROPERTY(QObject* events READ events NOTIFY eventsChanged) + Q_PROPERTY(QObject* data READ data NOTIFY dataChanged) + Q_PROPERTY(QObject* current READ current NOTIFY currentChanged) + Q_PROPERTY(bool running READ isRunning WRITE setRunning NOTIFY runningChanged) + +public: + QmlScxml(QObject* o = NULL); + virtual ~QmlScxml(); + QObject* states() const; + QObject* events() const; + QObject* data() const; + QObject* current() const; + QUrl source() const; + void setSource(const QUrl &); + bool isRunning() const; + void setRunning(bool); + +public slots: + void raise(const QString &); + void stop(); + void start(); + +signals: + void sourceChanged(const QUrl &); + void statesChanged(QObject*); + void eventsChanged(QObject*); + void dataChanged(QObject*); + void currentChanged(QObject*); + void trigger(const QString & e); + void runningChanged(); + void finished(); +private slots: + void onDataChanged(const QString &, const QVariant &); + void onDataChanged(const QString &); + void checkConfig(); +private: + class QmlPropertyMap* m_states; + class QmlPropertyMap* m_events; + class QmlPropertyMap* m_data; + class QmlPropertyMap* m_cur; + QMap<QAbstractState*,QString> m_idForState; + QUrl m_source; + QSet<QAbstractState*> m_oldConfig; + class QScxml* scxml; +}; + +QML_DECLARE_TYPE(QmlScxml); + +#endif // QMLSCXML_H diff --git a/qmlscxml/qmlscxml.pri b/qmlscxml/qmlscxml.pri new file mode 100644 index 0000000..2931219 --- /dev/null +++ b/qmlscxml/qmlscxml.pri @@ -0,0 +1,7 @@ +DEPENDPATH += $$PWD +INCLUDEPATH += $$PWD + +# Input +SOURCES += qmlscxml.cpp +HEADERS += qmlscxml.h +include($$PWD/../src/qscxml.pri) diff --git a/src/qscxml.cpp b/src/qscxml.cpp index cbb9c7c..d6142e5 100644 --- a/src/qscxml.cpp +++ b/src/qscxml.cpp @@ -928,7 +928,6 @@ void QScxml::endMicrostep(QEvent*) pvt->snapshotStack.remove(0,pvt->snapshotStack.size()-100); } pvt->curSnapshot.clear(); - qDebug() << configuration(); emit configurationChanged(); /* if (e->type() == QScxmlEvent::eventType()) { @@ -991,7 +990,7 @@ void QScxml::setData(const QString & id, const QVariant & val) void QScxml::executeScript (const QScriptProgram & s) { - qDebug() << "Executing\n--------------------------\n"<<s.sourceCode(); +// qDebug() << "Executing\n--------------------------\n"<<s.sourceCode(); pvt->scriptEng->evaluate (s); if (pvt->scriptEng->hasUncaughtException()) { QScxmlEvent* e = new QScxmlEvent("error.illegalvalue", |