diff options
-rw-r--r-- | examples/examples.pro | 2 | ||||
-rw-r--r-- | examples/mediaplayer-qml-cppdatamodel/mediaplayer-cppdatamodel.scxml | 73 | ||||
-rw-r--r-- | examples/mediaplayer-qml-cppdatamodel/mediaplayer-qml-cppdatamodel.cpp | 63 | ||||
-rw-r--r-- | examples/mediaplayer-qml-cppdatamodel/mediaplayer-qml-cppdatamodel.pro | 18 | ||||
-rw-r--r-- | examples/mediaplayer-qml-cppdatamodel/mediaplayer-qml-cppdatamodel.qml | 43 | ||||
-rw-r--r-- | examples/mediaplayer-qml-cppdatamodel/mediaplayer-qml-cppdatamodel.qrc | 6 | ||||
-rw-r--r-- | examples/mediaplayer-qml-cppdatamodel/thedatamodel.cpp | 57 | ||||
-rw-r--r-- | examples/mediaplayer-qml-cppdatamodel/thedatamodel.h | 60 | ||||
-rw-r--r-- | src/scxml/cppdatamodel.cpp | 96 | ||||
-rw-r--r-- | src/scxml/cppdatamodel.h | 66 | ||||
-rw-r--r-- | src/scxml/cppdatamodel_p.h | 39 | ||||
-rw-r--r-- | src/scxml/executablecontent.cpp | 56 | ||||
-rw-r--r-- | src/scxml/executablecontent_p.h | 30 | ||||
-rw-r--r-- | src/scxml/scxml.pro | 7 | ||||
-rw-r--r-- | src/scxml/scxmlparser.cpp | 17 | ||||
-rw-r--r-- | src/scxml/scxmlparser_p.h | 5 | ||||
-rw-r--r-- | tools/qscxmlc/scxmlcppdumper.cpp | 283 |
17 files changed, 818 insertions, 103 deletions
diff --git a/examples/examples.pro b/examples/examples.pro index 7c27353..99ac34d 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -12,4 +12,6 @@ qtHaveModule(qml) { SUBDIRS += trafficlight-qml-dynamic SUBDIRS += mediaplayer-qml-static SUBDIRS += mediaplayer-qml-dynamic + + SUBDIRS += mediaplayer-qml-cppdatamodel } diff --git a/examples/mediaplayer-qml-cppdatamodel/mediaplayer-cppdatamodel.scxml b/examples/mediaplayer-qml-cppdatamodel/mediaplayer-cppdatamodel.scxml new file mode 100644 index 0000000..789f739 --- /dev/null +++ b/examples/mediaplayer-qml-cppdatamodel/mediaplayer-cppdatamodel.scxml @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +--> +<scxml + xmlns="http://www.w3.org/2005/07/scxml" + version="1.0" + name="MediaPlayerStateMachine" + initial="stopped" + datamodel="cplusplus:TheDataModel:thedatamodel.h" +> + <state id="stopped"> + <transition event="tap" cond="isValidMedia()" target="playing"/> + </state> + + <state id="playing"> + <onentry> + <script> + media = eventData().value(QStringLiteral("media")).toString(); + </script> + <send type="qt:signal" event="playbackStarted"> + <param name="media" expr="media"/> + </send> + </onentry> + + <onexit> + <send type="qt:signal" event="playbackStopped"> + <param name="media" expr="media"/> + </send> + </onexit> + + <transition event="tap" cond="!isValidMedia() || media == eventData().value(QStringLiteral("media"))" target="stopped"/> + <transition event="tap" cond="isValidMedia() && media != eventData().value(QStringLiteral("media"))" target="playing"/> + </state> +</scxml> diff --git a/examples/mediaplayer-qml-cppdatamodel/mediaplayer-qml-cppdatamodel.cpp b/examples/mediaplayer-qml-cppdatamodel/mediaplayer-qml-cppdatamodel.cpp new file mode 100644 index 0000000..5c950f9 --- /dev/null +++ b/examples/mediaplayer-qml-cppdatamodel/mediaplayer-qml-cppdatamodel.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QGuiApplication> +#include <QQmlApplicationEngine> +#include <QQmlContext> + +#include "mediaplayer-cppdatamodel.h" +#include "thedatamodel.h" + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + MediaPlayerStateMachine stateMachine; + TheDataModel dataModel; + stateMachine.setDataModel(&dataModel); + stateMachine.init(); + stateMachine.start(); + + QQmlApplicationEngine engine; + engine.rootContext()->setContextProperty(QStringLiteral("mediaPlayerStateMachine"), &stateMachine); + engine.load(QUrl(QStringLiteral("qrc:///mediaplayer-qml-cppdatamodel.qml"))); + + return app.exec(); +} diff --git a/examples/mediaplayer-qml-cppdatamodel/mediaplayer-qml-cppdatamodel.pro b/examples/mediaplayer-qml-cppdatamodel/mediaplayer-qml-cppdatamodel.pro new file mode 100644 index 0000000..efbbea8 --- /dev/null +++ b/examples/mediaplayer-qml-cppdatamodel/mediaplayer-qml-cppdatamodel.pro @@ -0,0 +1,18 @@ +TEMPLATE = app + +QT += qml scxml + +SOURCES += mediaplayer-qml-cppdatamodel.cpp \ + thedatamodel.cpp + +HEADERS += thedatamodel.h + +RESOURCES += mediaplayer-qml-cppdatamodel.qrc + +STATECHARTS = mediaplayer-cppdatamodel.scxml + +load(qscxmlc) + +target.path = $$[QT_INSTALL_EXAMPLES]/scxml/mediaplayer-qml-cppdatamodel +INSTALLS += target + diff --git a/examples/mediaplayer-qml-cppdatamodel/mediaplayer-qml-cppdatamodel.qml b/examples/mediaplayer-qml-cppdatamodel/mediaplayer-qml-cppdatamodel.qml new file mode 100644 index 0000000..3db05f7 --- /dev/null +++ b/examples/mediaplayer-qml-cppdatamodel/mediaplayer-qml-cppdatamodel.qml @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +Mediaplayer { + stateMachine: mediaPlayerStateMachine +} diff --git a/examples/mediaplayer-qml-cppdatamodel/mediaplayer-qml-cppdatamodel.qrc b/examples/mediaplayer-qml-cppdatamodel/mediaplayer-qml-cppdatamodel.qrc new file mode 100644 index 0000000..0de7eb7 --- /dev/null +++ b/examples/mediaplayer-qml-cppdatamodel/mediaplayer-qml-cppdatamodel.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/"> + <file alias="Mediaplayer.qml">../mediaplayer-common/Mediaplayer.qml</file> + <file>mediaplayer-qml-cppdatamodel.qml</file> + </qresource> +</RCC> diff --git a/examples/mediaplayer-qml-cppdatamodel/thedatamodel.cpp b/examples/mediaplayer-qml-cppdatamodel/thedatamodel.cpp new file mode 100644 index 0000000..a018f68 --- /dev/null +++ b/examples/mediaplayer-qml-cppdatamodel/thedatamodel.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "thedatamodel.h" + +#include <QScxmlEvent> + +TheDataModel::~TheDataModel() +{} + +bool TheDataModel::isValidMedia() const +{ + QString eventMedia = eventData().value(QStringLiteral("media")).toString(); + return eventMedia.size() > 0; +} + +QVariantMap TheDataModel::eventData() const +{ + return event().data().value<QVariantMap>(); +} diff --git a/examples/mediaplayer-qml-cppdatamodel/thedatamodel.h b/examples/mediaplayer-qml-cppdatamodel/thedatamodel.h new file mode 100644 index 0000000..e67cde6 --- /dev/null +++ b/examples/mediaplayer-qml-cppdatamodel/thedatamodel.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef THEDATAMODEL_H +#define THEDATAMODEL_H + +#include "cppdatamodel.h" + +class TheDataModel: public Scxml::QScxmlCppDataModel +{ + Q_SCXML_DATAMODEL + +public: + ~TheDataModel(); + +private: + bool isValidMedia() const; + QVariantMap eventData() const; + + QString media; +}; + +#endif // THEDATAMODEL_H diff --git a/src/scxml/cppdatamodel.cpp b/src/scxml/cppdatamodel.cpp new file mode 100644 index 0000000..06e8b40 --- /dev/null +++ b/src/scxml/cppdatamodel.cpp @@ -0,0 +1,96 @@ +/**************************************************************************** + ** + ** Copyright (c) 2015 Digia Plc + ** For any questions to Digia, please use contact form at http://qt.digia.com/ + ** + ** All Rights Reserved. + ** + ** NOTICE: All information contained herein is, and remains + ** the property of Digia Plc and its suppliers, + ** if any. The intellectual and technical concepts contained + ** herein are proprietary to Digia Plc + ** and its suppliers and may be covered by Finnish and Foreign Patents, + ** patents in process, and are protected by trade secret or copyright law. + ** Dissemination of this information or reproduction of this material + ** is strictly forbidden unless prior written permission is obtained + ** from Digia Plc. + ****************************************************************************/ + +#include "cppdatamodel_p.h" +#include "scxmlstatemachine.h" + +QT_USE_NAMESPACE +using namespace Scxml; + +QScxmlCppDataModel::QScxmlCppDataModel() + : data(new QScxmlCppDataModelPrivate) +{} + +QScxmlCppDataModel::~QScxmlCppDataModel() +{ + delete data; +} + +void QScxmlCppDataModel::setup(const QVariantMap &initialDataValues) +{ + Q_UNUSED(initialDataValues); +} + +void QScxmlCppDataModel::evaluateAssignment(EvaluatorId id, bool *ok) +{ + Q_UNUSED(id); + Q_UNUSED(ok); + Q_UNREACHABLE(); +} + +void QScxmlCppDataModel::evaluateInitialization(EvaluatorId id, bool *ok) +{ + Q_UNUSED(id); + Q_UNUSED(ok); + Q_UNREACHABLE(); +} + +bool QScxmlCppDataModel::evaluateForeach(EvaluatorId id, bool *ok, ForeachLoopBody *body) +{ + Q_UNUSED(id); + Q_UNUSED(ok); + Q_UNUSED(body); + Q_UNREACHABLE(); + return false; +} + +void QScxmlCppDataModel::setEvent(const QScxmlEvent &event) +{ + data->event = event; +} + +const QScxmlEvent &QScxmlCppDataModel::event() const +{ + return data->event; +} + +QVariant QScxmlCppDataModel::property(const QString &name) const +{ + Q_UNUSED(name); + return QVariant(); +} + +bool QScxmlCppDataModel::hasProperty(const QString &name) const +{ + Q_UNUSED(name); + return false; +} + +void QScxmlCppDataModel::setProperty(const QString &name, const QVariant &value, const QString &context, bool *ok) +{ + Q_UNUSED(name); + Q_UNUSED(value); + Q_UNUSED(context); + Q_UNUSED(ok); + Q_UNREACHABLE(); +} + +bool QScxmlCppDataModel::In(const QString &stateName) const +{ + return stateMachine()->isActive(stateName); +} diff --git a/src/scxml/cppdatamodel.h b/src/scxml/cppdatamodel.h new file mode 100644 index 0000000..a1f0c99 --- /dev/null +++ b/src/scxml/cppdatamodel.h @@ -0,0 +1,66 @@ +/**************************************************************************** + ** + ** Copyright (c) 2015 Digia Plc + ** For any questions to Digia, please use contact form at http://qt.digia.com/ + ** + ** All Rights Reserved. + ** + ** NOTICE: All information contained herein is, and remains + ** the property of Digia Plc and its suppliers, + ** if any. The intellectual and technical concepts contained + ** herein are proprietary to Digia Plc + ** and its suppliers and may be covered by Finnish and Foreign Patents, + ** patents in process, and are protected by trade secret or copyright law. + ** Dissemination of this information or reproduction of this material + ** is strictly forbidden unless prior written permission is obtained + ** from Digia Plc. + ****************************************************************************/ + +#ifndef CPPDATAMODEL_H +#define CPPDATAMODEL_H + +#include "datamodel.h" + +#define Q_SCXML_DATAMODEL \ + public: \ + QString evaluateToString(Scxml::EvaluatorId id, bool *ok) Q_DECL_OVERRIDE; \ + bool evaluateToBool(Scxml::EvaluatorId id, bool *ok) Q_DECL_OVERRIDE; \ + QVariant evaluateToVariant(Scxml::EvaluatorId id, bool *ok) Q_DECL_OVERRIDE; \ + void evaluateToVoid(Scxml::EvaluatorId id, bool *ok) Q_DECL_OVERRIDE; + +QT_BEGIN_NAMESPACE + +namespace Scxml { + +class QScxmlCppDataModelPrivate; +class Q_SCXML_EXPORT QScxmlCppDataModel: public QScxmlDataModel +{ +public: + QScxmlCppDataModel(); + ~QScxmlCppDataModel(); + + void setup(const QVariantMap &initialDataValues) Q_DECL_OVERRIDE; + + void evaluateAssignment(EvaluatorId id, bool *ok) Q_DECL_OVERRIDE; + void evaluateInitialization(EvaluatorId id, bool *ok) Q_DECL_OVERRIDE; + bool evaluateForeach(EvaluatorId id, bool *ok, ForeachLoopBody *body) Q_DECL_OVERRIDE; + + void setEvent(const QScxmlEvent &event) Q_DECL_OVERRIDE; + const QScxmlEvent &event() const; + + QVariant property(const QString &name) const Q_DECL_OVERRIDE; + bool hasProperty(const QString &name) const Q_DECL_OVERRIDE; + void setProperty(const QString &name, const QVariant &value, const QString &context, + bool *ok) Q_DECL_OVERRIDE; + + bool In(const QString &stateName) const; + +private: + QScxmlCppDataModelPrivate *data; +}; + +} // Scxml namespace + +QT_END_NAMESPACE + +#endif // CPPDATAMODEL_H diff --git a/src/scxml/cppdatamodel_p.h b/src/scxml/cppdatamodel_p.h new file mode 100644 index 0000000..8e40d68 --- /dev/null +++ b/src/scxml/cppdatamodel_p.h @@ -0,0 +1,39 @@ +/**************************************************************************** + ** + ** Copyright (c) 2015 Digia Plc + ** For any questions to Digia, please use contact form at http://qt.digia.com/ + ** + ** All Rights Reserved. + ** + ** NOTICE: All information contained herein is, and remains + ** the property of Digia Plc and its suppliers, + ** if any. The intellectual and technical concepts contained + ** herein are proprietary to Digia Plc + ** and its suppliers and may be covered by Finnish and Foreign Patents, + ** patents in process, and are protected by trade secret or copyright law. + ** Dissemination of this information or reproduction of this material + ** is strictly forbidden unless prior written permission is obtained + ** from Digia Plc. + ****************************************************************************/ + +#ifndef CPPDATAMODEL_P_H +#define CPPDATAMODEL_P_H + +#include "cppdatamodel.h" +#include "QScxmlEvent" + +QT_BEGIN_NAMESPACE + +namespace Scxml { + +class Q_SCXML_EXPORT QScxmlCppDataModelPrivate +{ +public: + QScxmlEvent event; +}; + +} // Scxml namespace + +QT_END_NAMESPACE + +#endif // CPPDATAMODEL_P_H diff --git a/src/scxml/executablecontent.cpp b/src/scxml/executablecontent.cpp index 9749e8e..d741f14 100644 --- a/src/scxml/executablecontent.cpp +++ b/src/scxml/executablecontent.cpp @@ -133,7 +133,7 @@ public: } case Instruction::JavaScript: { - qDebug() << "Executing javascript step"; + qDebug() << "Executing script step"; JavaScript *javascript = reinterpret_cast<JavaScript *>(instr); ip += javascript->size(); bool ok = true; @@ -295,6 +295,7 @@ bool ExecutionEngine::execute(ContainerId id, const QVariant &extraData) Builder::Builder() : m_initialSetup(ExecutableContent::NoInstruction) + , m_isCppDataModel(false) { m_activeSequences.reserve(4); } @@ -335,8 +336,7 @@ void Builder::visit(DocumentModel::Log *node) void Builder::visit(DocumentModel::Script *node) { auto instr = m_instructions.add<JavaScript>(); - auto ctxt = createContext(QStringLiteral("script"), QStringLiteral("source"), node->content); - instr->go = addEvaluator(node->content, ctxt); + instr->go = createEvaluatorVoid(QStringLiteral("script"), QStringLiteral("source"), node->content); } void Builder::visit(DocumentModel::Assign *node) @@ -504,8 +504,14 @@ InstructionSequence *Builder::endSequence() EvaluatorId Builder::createEvaluatorString(const QString &instrName, const QString &attrName, const QString &expr) { if (!expr.isEmpty()) { - QString loc = createContext(instrName, attrName, expr); - return addEvaluator(expr, loc); + if (isCppDataModel()) { + auto id = m_evaluators.add(QScxmlEvaluatorInfo(), false); + m_stringEvaluators.insert(id, expr); + return id; + } else { + QString loc = createContext(instrName, attrName, expr); + return addEvaluator(expr, loc); + } } return NoEvaluator; @@ -514,18 +520,46 @@ EvaluatorId Builder::createEvaluatorString(const QString &instrName, const QStri EvaluatorId Builder::createEvaluatorBool(const QString &instrName, const QString &attrName, const QString &cond) { if (!cond.isEmpty()) { - QString loc = createContext(instrName, attrName, cond); - return addEvaluator(cond, loc); + if (isCppDataModel()) { + auto id = m_evaluators.add(QScxmlEvaluatorInfo(), false); + m_boolEvaluators.insert(id, cond); + return id; + } else { + QString loc = createContext(instrName, attrName, cond); + return addEvaluator(cond, loc); + } } return NoEvaluator; } -EvaluatorId Builder::createEvaluatorVariant(const QString &instrName, const QString &attrName, const QString &cond) +EvaluatorId Builder::createEvaluatorVariant(const QString &instrName, const QString &attrName, const QString &expr) { - if (!cond.isEmpty()) { - QString loc = createContext(instrName, attrName, cond); - return addEvaluator(cond, loc); + if (!expr.isEmpty()) { + if (isCppDataModel()) { + auto id = m_evaluators.add(QScxmlEvaluatorInfo(), false); + m_variantEvaluators.insert(id, expr); + return id; + } else { + QString loc = createContext(instrName, attrName, expr); + return addEvaluator(expr, loc); + } + } + + return NoEvaluator; +} + +EvaluatorId Builder::createEvaluatorVoid(const QString &instrName, const QString &attrName, const QString &stuff) +{ + if (!stuff.isEmpty()) { + if (isCppDataModel()) { + auto id = m_evaluators.add(QScxmlEvaluatorInfo(), false); + m_voidEvaluators.insert(id, stuff); + return id; + } else { + QString loc = createContext(instrName, attrName, stuff); + return addEvaluator(stuff, loc); + } } return NoEvaluator; diff --git a/src/scxml/executablecontent_p.h b/src/scxml/executablecontent_p.h index 3f06a7c..b3237b7 100644 --- a/src/scxml/executablecontent_p.h +++ b/src/scxml/executablecontent_p.h @@ -322,7 +322,8 @@ protected: InstructionSequence *endSequence(); EvaluatorId createEvaluatorString(const QString &instrName, const QString &attrName, const QString &expr); EvaluatorId createEvaluatorBool(const QString &instrName, const QString &attrName, const QString &cond); - EvaluatorId createEvaluatorVariant(const QString &instrName, const QString &attrName, const QString &cond); + EvaluatorId createEvaluatorVariant(const QString &instrName, const QString &attrName, const QString &expr); + EvaluatorId createEvaluatorVoid(const QString &instrName, const QString &attrName, const QString &stuff); virtual QString createContextString(const QString &instrName) const = 0; virtual QString createContext(const QString &instrName, const QString &attrName, const QString &attrValue) const = 0; @@ -341,6 +342,24 @@ protected: void setName(const QString &name) { m_name = name; } + bool isCppDataModel() const + { return m_isCppDataModel; } + + void setIsCppDataModel(bool onoff) + { m_isCppDataModel = onoff; } + + QMap<EvaluatorId, QString> boolEvaluators() const + { return m_boolEvaluators; } + + QMap<EvaluatorId, QString> stringEvaluators() const + { return m_stringEvaluators; } + + QMap<EvaluatorId, QString> variantEvaluators() const + { return m_variantEvaluators; } + + QMap<EvaluatorId, QString> voidEvaluators() const + { return m_voidEvaluators; } + private: template <typename T, typename U> class Table { @@ -348,8 +367,8 @@ private: QMap<T, int> indexForElement; public: - U add(const T &s) { - int pos = indexForElement.value(s, -1); + U add(const T &s, bool uniqueOnly = true) { + int pos = uniqueOnly ? indexForElement.value(s, -1) : -1; if (pos == -1) { pos = elements.size(); elements.append(s); @@ -464,9 +483,14 @@ private: Table<QScxmlEvaluatorInfo, EvaluatorId> m_evaluators; Table<QScxmlAssignmentInfo, EvaluatorId> m_assignments; Table<QScxmlForeachInfo, EvaluatorId> m_foreaches; + QMap<EvaluatorId, QString> m_boolEvaluators; + QMap<EvaluatorId, QString> m_stringEvaluators; + QMap<EvaluatorId, QString> m_variantEvaluators; + QMap<EvaluatorId, QString> m_voidEvaluators; ExecutableContent::StringIds m_dataIds; ContainerId m_initialSetup; QString m_name; + bool m_isCppDataModel; }; } // ExecutableContent namespace diff --git a/src/scxml/scxml.pro b/src/scxml/scxml.pro index 149c5e2..ebdd0d8 100644 --- a/src/scxml/scxml.pro +++ b/src/scxml/scxml.pro @@ -22,7 +22,9 @@ HEADERS += \ scxmlevent_p.h \ datamodel.h \ scxmlqstates.h \ - scxmlqstates_p.h + scxmlqstates_p.h \ + cppdatamodel_p.h \ + cppdatamodel.h SOURCES += \ scxmlparser.cpp \ @@ -33,4 +35,5 @@ SOURCES += \ executablecontent.cpp \ scxmlevent.cpp \ datamodel.cpp \ - scxmlqstates.cpp + scxmlqstates.cpp \ + cppdatamodel.cpp diff --git a/src/scxml/scxmlparser.cpp b/src/scxml/scxmlparser.cpp index 0f28d88..4b1a6af 100644 --- a/src/scxml/scxmlparser.cpp +++ b/src/scxml/scxmlparser.cpp @@ -867,6 +867,8 @@ inline ScxmlInvokableService *InvokeDynamicScxmlFactory::invoke(StateMachine *pa case DocumentModel::Scxml::JSDataModel: dataModel = new QScxmlEcmaScriptDataModel; break; + case DocumentModel::Scxml::CppDataModel: + break; default: Q_UNREACHABLE(); } @@ -1387,6 +1389,21 @@ void ScxmlParserPrivate::parse() scxml->dataModel = DocumentModel::Scxml::NullDataModel; } else if (datamodel == QLatin1String("ecmascript")) { scxml->dataModel = DocumentModel::Scxml::JSDataModel; + } else if (datamodel.startsWith(QLatin1String("cplusplus"))) { + scxml->dataModel = DocumentModel::Scxml::CppDataModel; + int firstColon = datamodel.indexOf(QLatin1Char(':')); + if (firstColon == -1) { + scxml->cppDataModelClassName = attributes.value(QStringLiteral("name")) + QStringLiteral("DataModel"); + scxml->cppDataModelHeaderName = scxml->cppDataModelClassName + QStringLiteral(".h"); + } else { + int lastColon = datamodel.lastIndexOf(QLatin1Char(':')); + if (lastColon == -1) { + lastColon = datamodel.length(); + } else { + scxml->cppDataModelHeaderName = datamodel.mid(lastColon + 1).toString(); + } + scxml->cppDataModelClassName = datamodel.mid(firstColon + 1, lastColon - firstColon - 1).toString(); + } } else { addError(QStringLiteral("Unsupported data model '%1' in scxml") .arg(datamodel.toString())); diff --git a/src/scxml/scxmlparser_p.h b/src/scxml/scxmlparser_p.h index d8834d5..f0bac94 100644 --- a/src/scxml/scxmlparser_p.h +++ b/src/scxml/scxmlparser_p.h @@ -338,7 +338,8 @@ struct Scxml: public StateContainer, public Node { enum DataModelType { NullDataModel, - JSDataModel + JSDataModel, + CppDataModel }; enum BindingMethod { EarlyBinding, @@ -349,6 +350,8 @@ struct Scxml: public StateContainer, public Node QString name; QString qtClassname; DataModelType dataModel; + QString cppDataModelClassName; + QString cppDataModelHeaderName; BindingMethod binding; QVector<StateOrTransition *> children; QVector<DataElement *> dataElements; diff --git a/tools/qscxmlc/scxmlcppdumper.cpp b/tools/qscxmlc/scxmlcppdumper.cpp index f8ebe4e..bc88146 100644 --- a/tools/qscxmlc/scxmlcppdumper.cpp +++ b/tools/qscxmlc/scxmlcppdumper.cpp @@ -74,6 +74,7 @@ struct StringListDumper { struct Method { StringListDumper initializer; Method(const QString &decl = QString()): decl(decl) {} + Method(const StringListDumper &impl): impl(impl) {} QString decl; // void f(int i = 0); StringListDumper impl; // void f(int i) { m_i = ++i; } }; @@ -81,6 +82,7 @@ struct Method { struct ClassDump { StringListDumper implIncludes; QString className; + QString dataModelClassName; StringListDumper classFields; StringListDumper tables; Method init; @@ -93,6 +95,8 @@ struct ClassDump { QList<Method> publicMethods; StringListDumper publicSlotDeclarations; StringListDumper publicSlotDefinitions; + + QList<Method> dataModelMethods; }; namespace { @@ -210,7 +214,12 @@ protected: << QStringLiteral("{ return QString(); }") << QString(); } - clazz.init.impl << QStringLiteral("stateMachine.setDataModel(&dataModel);"); + if (node->dataModel == Scxml::CppDataModel) { + setIsCppDataModel(true); + clazz.dataModelClassName = node->cppDataModelClassName; + } else { + clazz.init.impl << QStringLiteral("stateMachine.setDataModel(&dataModel);"); + } QString binding; switch (node->binding) { @@ -258,20 +267,21 @@ protected: m_parents.removeLast(); { // the data model: - QString dmName; switch (node->dataModel) { case Scxml::NullDataModel: - dmName = QStringLiteral("Null"); + clazz.classFields << QStringLiteral("Scxml::QScxmlNullDataModel dataModel;"); clazz.implIncludes << QStringLiteral("QtScxml/nulldatamodel.h"); break; case Scxml::JSDataModel: - dmName = QStringLiteral("EcmaScript"); + clazz.classFields << QStringLiteral("Scxml::QScxmlEcmaScriptDataModel dataModel;"); clazz.implIncludes << QStringLiteral("QtScxml/ecmascriptdatamodel.h"); break; + case Scxml::CppDataModel: + clazz.implIncludes << node->cppDataModelHeaderName; + break; default: Q_UNREACHABLE(); } - clazz.classFields << QStringLiteral("Scxml::QScxml") + dmName + QStringLiteral("DataModel dataModel;"); } return false; } @@ -730,6 +740,171 @@ private: << QString(); } + { // dataIds + int count; + auto dataIds = td->dataNames(&count); + clazz.classFields << QStringLiteral("static Scxml::ExecutableContent::StringId dataIds[];"); + t << QStringLiteral("Scxml::ExecutableContent::StringId %1::Data::dataIds[] = {").arg(clazz.className); + if (isCppDataModel()) { + t << QStringLiteral("-1"); + } else { + generateList(t, [&dataIds, count](int idx) -> QString { + if (count == 0 && idx == 0) // prevent generation of empty array + return QStringLiteral("-1"); + if (idx < count) + return QString::number(dataIds[idx]); + else + return QString(); + }); + } + t << QStringLiteral("};") << QStringLiteral(""); + clazz.dataMethods << QStringLiteral("Scxml::ExecutableContent::StringId *dataNames(int *count) const Q_DECL_OVERRIDE"); + clazz.dataMethods << QStringLiteral("{ *count = %1; return dataIds; }").arg(count); + clazz.dataMethods << QString(); + } + + { // evaluators + auto evaluators = td->evaluators(); + clazz.classFields << QStringLiteral("static Scxml::QScxmlEvaluatorInfo evaluators[];"); + t << QStringLiteral("Scxml::QScxmlEvaluatorInfo %1::Data::evaluators[] = {").arg(clazz.className); + if (isCppDataModel()) { + t << QStringLiteral("{ -1, -1 }"); + } else { + generateList(t, [&evaluators](int idx) -> QString { + if (evaluators.isEmpty() && idx == 0) // prevent generation of empty array + return QStringLiteral("{ -1, -1 }"); + if (idx >= evaluators.size()) + return QString(); + + auto eval = evaluators.at(idx); + return QStringLiteral("{ %1, %2 }").arg(eval.expr).arg(eval.context); + }); + } + t << QStringLiteral("};") << QStringLiteral(""); + clazz.dataMethods << QStringLiteral("Scxml::QScxmlEvaluatorInfo evaluatorInfo(Scxml::EvaluatorId evaluatorId) const Q_DECL_OVERRIDE"); + clazz.dataMethods << QStringLiteral("{ Q_ASSERT(evaluatorId >= 0); Q_ASSERT(evaluatorId < %1); return evaluators[evaluatorId]; }").arg(evaluators.size()); + clazz.dataMethods << QString(); + + if (isCppDataModel()) { + { + StringListDumper stringEvals; + stringEvals << QStringLiteral("QString %1::evaluateToString(Scxml::EvaluatorId id, bool *ok) {").arg(clazz.dataModelClassName) + << QStringLiteral(" *ok = true;") + << QStringLiteral(" switch (id) {"); + auto evals = stringEvaluators(); + for (auto it = evals.constBegin(), eit = evals.constEnd(); it != eit; ++it) { + stringEvals << QStringLiteral(" case %1:").arg(it.key()) + << QStringLiteral(" return [this](){ return %1; }();").arg(it.value()); + } + stringEvals << QStringLiteral(" default:") + << QStringLiteral(" Q_UNREACHABLE();") + << QStringLiteral(" *ok = false;") + << QStringLiteral(" return QString();") + << QStringLiteral(" }"); + stringEvals << QStringLiteral("}"); + clazz.dataModelMethods.append(Method(stringEvals)); + } + + { + StringListDumper boolEvals; + boolEvals << QStringLiteral("bool %1::evaluateToBool(Scxml::EvaluatorId id, bool *ok) {").arg(clazz.dataModelClassName) + << QStringLiteral(" *ok = true;") + << QStringLiteral(" switch (id) {"); + auto evals = boolEvaluators(); + for (auto it = evals.constBegin(), eit = evals.constEnd(); it != eit; ++it) { + boolEvals << QStringLiteral(" case %1:").arg(it.key()) + << QStringLiteral(" return [this](){ return %1; }();").arg(it.value()); + } + boolEvals << QStringLiteral(" default:") + << QStringLiteral(" Q_UNREACHABLE();") + << QStringLiteral(" *ok = false;") + << QStringLiteral(" return false;") + << QStringLiteral(" }"); + boolEvals << QStringLiteral("}"); + clazz.dataModelMethods.append(Method(boolEvals)); + } + + { + StringListDumper variantEvals; + variantEvals << QStringLiteral("QVariant %1::evaluateToVariant(Scxml::EvaluatorId id, bool *ok) {").arg(clazz.dataModelClassName) + << QStringLiteral(" *ok = true;") + << QStringLiteral(" switch (id) {"); + auto evals = variantEvaluators(); + for (auto it = evals.constBegin(), eit = evals.constEnd(); it != eit; ++it) { + variantEvals << QStringLiteral(" case %1:").arg(it.key()) + << QStringLiteral(" return [this](){ return %1; }();").arg(it.value()); + } + variantEvals << QStringLiteral(" default:") + << QStringLiteral(" Q_UNREACHABLE();") + << QStringLiteral(" *ok = false;") + << QStringLiteral(" return QVariant();") + << QStringLiteral(" }"); + variantEvals << QStringLiteral("}"); + clazz.dataModelMethods.append(Method(variantEvals)); + } + + { + StringListDumper voidEvals; + voidEvals << QStringLiteral("void %1::evaluateToVoid(Scxml::EvaluatorId id, bool *ok) {").arg(clazz.dataModelClassName) + << QStringLiteral(" *ok = true;") + << QStringLiteral(" switch (id) {"); + auto evals = voidEvaluators(); + for (auto it = evals.constBegin(), eit = evals.constEnd(); it != eit; ++it) { + voidEvals << QStringLiteral(" case %1:").arg(it.key()) + << QStringLiteral(" [this](){ %1 }();").arg(it.value()) + << QStringLiteral(" break;"); + } + voidEvals << QStringLiteral(" default:") + << QStringLiteral(" Q_UNREACHABLE();") + << QStringLiteral(" *ok = false;") + << QStringLiteral(" }"); + voidEvals << QStringLiteral("}"); + clazz.dataModelMethods.append(Method(voidEvals)); + } + } + } + + { // assignments + auto assignments = td->assignments(); + clazz.classFields << QStringLiteral("static Scxml::QScxmlAssignmentInfo assignments[];"); + t << QStringLiteral("Scxml::QScxmlAssignmentInfo %1::Data::assignments[] = {").arg(clazz.className); + if (isCppDataModel()) { + t << QStringLiteral("{ -1, -1, -1 }"); + } else { + generateList(t, [&assignments](int idx) -> QString { + if (assignments.isEmpty() && idx == 0) // prevent generation of empty array + return QStringLiteral("{ -1, -1, -1 }"); + if (idx >= assignments.size()) + return QString(); + + auto ass = assignments.at(idx); + return QStringLiteral("{ %1, %2, %3 }").arg(ass.dest).arg(ass.expr).arg(ass.context); + }); + } + t << QStringLiteral("};") << QStringLiteral(""); + clazz.dataMethods << QStringLiteral("Scxml::QScxmlAssignmentInfo assignmentInfo(Scxml::EvaluatorId assignmentId) const Q_DECL_OVERRIDE"); + clazz.dataMethods << QStringLiteral("{ Q_ASSERT(assignmentId >= 0); Q_ASSERT(assignmentId < %1); return assignments[assignmentId]; }").arg(assignments.size()); + clazz.dataMethods << QString(); + } + + { // foreaches + auto foreaches = td->foreaches(); + clazz.classFields << QStringLiteral("static Scxml::QScxmlForeachInfo foreaches[];"); + t << QStringLiteral("Scxml::QScxmlForeachInfo %1::Data::foreaches[] = {").arg(clazz.className); + generateList(t, [&foreaches](int idx) -> QString { + if (foreaches.isEmpty() && idx == 0) // prevent generation of empty array + return QStringLiteral("{ -1, -1, -1, -1 }"); + if (idx >= foreaches.size()) + return QString(); + + auto foreach = foreaches.at(idx); + return QStringLiteral("{ %1, %2, %3, %4 }").arg(foreach.array).arg(foreach.item).arg(foreach.index).arg(foreach.context); + }); + t << QStringLiteral("};") << QStringLiteral(""); + clazz.dataMethods << QStringLiteral("Scxml::QScxmlForeachInfo foreachInfo(Scxml::EvaluatorId foreachId) const Q_DECL_OVERRIDE"); + clazz.dataMethods << QStringLiteral("{ Q_ASSERT(foreachId >= 0); Q_ASSERT(foreachId < %1); return foreaches[foreachId]; }").arg(foreaches.size()); + } + { // strings t << QStringLiteral("#define STR_LIT(idx, ofs, len) \\") << QStringLiteral(" Q_STATIC_STRING_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \\") @@ -745,19 +920,21 @@ private: if (idx >= strings.size()) return QString(); - auto s = strings.at(idx); + int length = strings.at(idx).size(); QString str = QStringLiteral("STR_LIT(%1, %2, %3)").arg(QString::number(idx), QString::number(ucharCount), - QString::number(s.size())); - ucharCount += s.size() + 1; + QString::number(length)); + ucharCount += length + 1; return str; }); t << QStringLiteral("},"); if (strings.isEmpty()) { t << QStringLiteral("QT_UNICODE_LITERAL_II(\"\")"); } else { - foreach (const QString &s, strings) { - t << QStringLiteral("QT_UNICODE_LITERAL_II(\"%1\") // %2").arg(toHex(s) + QStringLiteral("\\x00"), cEscape(s)); + for (int i = 0, ei = strings.size(); i < ei; ++i) { + QString s = strings.at(i); + QString comment = cEscape(s); + t << QStringLiteral("QT_UNICODE_LITERAL_II(\"%1\") // %2").arg(toHex(s) + QStringLiteral("\\x00"), comment); } } t << QStringLiteral("};") << QStringLiteral(""); @@ -836,81 +1013,6 @@ private: clazz.dataMethods << QStringLiteral("}"); clazz.dataMethods << QString(); } - - { // dataIds - int count; - auto dataIds = td->dataNames(&count); - clazz.classFields << QStringLiteral("static Scxml::ExecutableContent::StringId dataIds[];"); - t << QStringLiteral("Scxml::ExecutableContent::StringId %1::Data::dataIds[] = {").arg(clazz.className); - generateList(t, [&dataIds, count](int idx) -> QString { - if (count == 0 && idx == 0) // prevent generation of empty array - return QStringLiteral("-1"); - if (idx < count) - return QString::number(dataIds[idx]); - else - return QString(); - }); - t << QStringLiteral("};") << QStringLiteral(""); - clazz.dataMethods << QStringLiteral("Scxml::ExecutableContent::StringId *dataNames(int *count) const Q_DECL_OVERRIDE"); - clazz.dataMethods << QStringLiteral("{ *count = %1; return dataIds; }").arg(count); - clazz.dataMethods << QString(); - } - - { // evaluators - auto evaluators = td->evaluators(); - clazz.classFields << QStringLiteral("static Scxml::QScxmlEvaluatorInfo evaluators[];"); - t << QStringLiteral("Scxml::QScxmlEvaluatorInfo %1::Data::evaluators[] = {").arg(clazz.className); - generateList(t, [&evaluators](int idx) -> QString { - if (evaluators.isEmpty() && idx == 0) // prevent generation of empty array - return QStringLiteral("{ -1, -1 }"); - if (idx >= evaluators.size()) - return QString(); - - auto eval = evaluators.at(idx); - return QStringLiteral("{ %1, %2 }").arg(eval.expr).arg(eval.context); - }); - t << QStringLiteral("};") << QStringLiteral(""); - clazz.dataMethods << QStringLiteral("Scxml::QScxmlEvaluatorInfo evaluatorInfo(Scxml::EvaluatorId evaluatorId) const Q_DECL_OVERRIDE"); - clazz.dataMethods << QStringLiteral("{ Q_ASSERT(evaluatorId >= 0); Q_ASSERT(evaluatorId < %1); return evaluators[evaluatorId]; }").arg(evaluators.size()); - clazz.dataMethods << QString(); - } - - { // assignments - auto assignments = td->assignments(); - clazz.classFields << QStringLiteral("static Scxml::QScxmlAssignmentInfo assignments[];"); - t << QStringLiteral("Scxml::QScxmlAssignmentInfo %1::Data::assignments[] = {").arg(clazz.className); - generateList(t, [&assignments](int idx) -> QString { - if (assignments.isEmpty() && idx == 0) // prevent generation of empty array - return QStringLiteral("{ -1, -1, -1 }"); - if (idx >= assignments.size()) - return QString(); - - auto ass = assignments.at(idx); - return QStringLiteral("{ %1, %2, %3 }").arg(ass.dest).arg(ass.expr).arg(ass.context); - }); - t << QStringLiteral("};") << QStringLiteral(""); - clazz.dataMethods << QStringLiteral("Scxml::QScxmlAssignmentInfo assignmentInfo(Scxml::EvaluatorId assignmentId) const Q_DECL_OVERRIDE"); - clazz.dataMethods << QStringLiteral("{ Q_ASSERT(assignmentId >= 0); Q_ASSERT(assignmentId < %1); return assignments[assignmentId]; }").arg(assignments.size()); - clazz.dataMethods << QString(); - } - - { // foreaches - auto foreaches = td->foreaches(); - clazz.classFields << QStringLiteral("static Scxml::QScxmlForeachInfo foreaches[];"); - t << QStringLiteral("Scxml::QScxmlForeachInfo %1::Data::foreaches[] = {").arg(clazz.className); - generateList(t, [&foreaches](int idx) -> QString { - if (foreaches.isEmpty() && idx == 0) // prevent generation of empty array - return QStringLiteral("{ -1, -1, -1, -1 }"); - if (idx >= foreaches.size()) - return QString(); - - auto foreach = foreaches.at(idx); - return QStringLiteral("{ %1, %2, %3, %4 }").arg(foreach.array).arg(foreach.item).arg(foreach.index).arg(foreach.context); - }); - t << QStringLiteral("};") << QStringLiteral(""); - clazz.dataMethods << QStringLiteral("Scxml::QScxmlForeachInfo foreachInfo(Scxml::EvaluatorId foreachId) const Q_DECL_OVERRIDE"); - clazz.dataMethods << QStringLiteral("{ Q_ASSERT(foreachId >= 0); Q_ASSERT(foreachId < %1); return foreaches[foreachId]; }").arg(foreaches.size()); - } } QString qba(const QString &bytes) @@ -960,7 +1062,9 @@ void CppDumper::dump(TranslationUnit *unit) } auto headerName = QFileInfo(unit->outHFileName).fileName(); - const QString headerGuard = headerName.toUpper().replace(QLatin1Char('.'), QLatin1Char('_')); + const QString headerGuard = headerName.toUpper() + .replace(QLatin1Char('.'), QLatin1Char('_')) + .replace(QLatin1Char('-'), QLatin1Char('_')); writeHeaderStart(headerGuard); writeImplStart(clazzes); @@ -1099,6 +1203,13 @@ void CppDumper::writeImplBody(const ClassDump &clazz) cpp << endl; clazz.tables.write(cpp, QStringLiteral(""), QStringLiteral("\n")); + + if (!clazz.dataModelMethods.isEmpty()) { + foreach (const Method &m, clazz.dataModelMethods) { + m.impl.write(cpp, QStringLiteral(""), QStringLiteral("\n")); + cpp << endl; + } + } } void CppDumper::writeImplEnd() |