summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--mkspecs/features/qscxmlc.prf2
-rw-r--r--src/imports/scxmlstatemachine/statemachineloader.cpp10
-rw-r--r--src/scxml/qscxmlinvokableservice.cpp29
-rw-r--r--src/scxml/qscxmlinvokableservice_p.h5
-rw-r--r--src/scxml/qscxmlstatemachine.cpp6
-rw-r--r--tests/auto/statemachine/invoke.scxml73
-rw-r--r--tests/auto/statemachine/tst_statemachine.cpp22
-rw-r--r--tests/auto/statemachine/tst_statemachine.qrc1
-rw-r--r--tools/qscxmlc/decl.t5
-rw-r--r--tools/qscxmlc/doc/qscxmlc.qdoc8
-rw-r--r--tools/qscxmlc/generator.cpp36
-rw-r--r--tools/qscxmlc/generator.h3
-rw-r--r--tools/qscxmlc/moc.h4
-rw-r--r--tools/qscxmlc/qscxmlc.cpp4
-rw-r--r--tools/qscxmlc/scxmlcppdumper.cpp64
-rw-r--r--tools/qscxmlc/scxmlcppdumper.h6
17 files changed, 246 insertions, 34 deletions
diff --git a/.qmake.conf b/.qmake.conf
index 165ecba..ab3b383 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -2,4 +2,4 @@ load(qt_build_config)
CONFIG += qt_example_installs
CONFIG += warning_clean
-MODULE_VERSION = 5.8.1
+MODULE_VERSION = 5.9.0
diff --git a/mkspecs/features/qscxmlc.prf b/mkspecs/features/qscxmlc.prf
index 25f1f10..ae1b3ba 100644
--- a/mkspecs/features/qscxmlc.prf
+++ b/mkspecs/features/qscxmlc.prf
@@ -13,7 +13,7 @@ QSCXMLC_DIR = $$QSCXMLC_DIR$$SUFFIX
qscxmlc.name = QSCXMLC ${QMAKE_FILE_IN}.h
qscxmlc.input = STATECHARTS
qscxmlc.variable_out = QSCXMLC_HEADERS
-qscxmlc.commands = $$QMAKE_QSCXMLC ${QMAKE_FILE_IN} --header ${QMAKE_FILE_OUT} --impl $$QSCXMLC_DIR/${QMAKE_FILE_BASE}$${first(QMAKE_EXT_CPP)}
+qscxmlc.commands = $$QMAKE_QSCXMLC ${QMAKE_FILE_IN} --header ${QMAKE_FILE_OUT} --impl $$QSCXMLC_DIR/${QMAKE_FILE_BASE}$${first(QMAKE_EXT_CPP)} $$QSCXMLC_ARGUMENTS
!isEmpty(QSCXMLC_NAMESPACE): qscxmlc.commands = $${qscxmlc.commands} --namespace $$QSCXMLC_NAMESPACE
qscxmlc.output = $$QSCXMLC_DIR/${QMAKE_FILE_BASE}$${first(QMAKE_EXT_H)}
qscxmlc.CONFIG += target_predeps
diff --git a/src/imports/scxmlstatemachine/statemachineloader.cpp b/src/imports/scxmlstatemachine/statemachineloader.cpp
index 247d989..f4c1740 100644
--- a/src/imports/scxmlstatemachine/statemachineloader.cpp
+++ b/src/imports/scxmlstatemachine/statemachineloader.cpp
@@ -156,21 +156,21 @@ void QScxmlStateMachineLoader::setDataModel(QScxmlDataModel *dataModel)
bool QScxmlStateMachineLoader::parse(const QUrl &source)
{
if (!QQmlFile::isSynchronous(source)) {
- qmlInfo(this) << QStringLiteral("ERROR: cannot open '%1' for reading: only synchronous access is supported.")
+ qmlWarning(this) << QStringLiteral("Cannot open '%1' for reading: only synchronous access is supported.")
.arg(source.url());
return false;
}
QQmlFile scxmlFile(QQmlEngine::contextForObject(this)->engine(), source);
if (scxmlFile.isError()) {
// the synchronous case can only fail when the file is not found (or not readable).
- qmlInfo(this) << QStringLiteral("ERROR: cannot open '%1' for reading.").arg(source.url());
+ qmlWarning(this) << QStringLiteral("Cannot open '%1' for reading.").arg(source.url());
return false;
}
QByteArray data(scxmlFile.dataByteArray());
QBuffer buf(&data);
if (!buf.open(QIODevice::ReadOnly)) {
- qmlInfo(this) << QStringLiteral("ERROR: cannot open input buffer for reading");
+ qmlWarning(this) << QStringLiteral("Cannot open input buffer for reading");
return false;
}
@@ -189,12 +189,12 @@ bool QScxmlStateMachineLoader::parse(const QUrl &source)
QMetaObject::invokeMethod(m_stateMachine, "start", Qt::QueuedConnection);
return true;
} else {
- qmlInfo(this) << QStringLiteral("Something went wrong while parsing '%1':")
+ qmlWarning(this) << QStringLiteral("Something went wrong while parsing '%1':")
.arg(source.url())
<< endl;
const auto errors = m_stateMachine->parseErrors();
for (const QScxmlError &error : errors) {
- qmlInfo(this) << error.toString();
+ qmlWarning(this) << error.toString();
}
emit stateMachineChanged();
diff --git a/src/scxml/qscxmlinvokableservice.cpp b/src/scxml/qscxmlinvokableservice.cpp
index a897eaa..4cf9bd9 100644
--- a/src/scxml/qscxmlinvokableservice.cpp
+++ b/src/scxml/qscxmlinvokableservice.cpp
@@ -319,7 +319,7 @@ QVariantMap QScxmlInvokableServicePrivate::calculateData(
QScxmlScxmlService::~QScxmlScxmlService()
{
- delete stateMachine;
+ delete m_stateMachine;
}
/*!
@@ -329,7 +329,7 @@ QScxmlScxmlService::~QScxmlScxmlService()
QScxmlScxmlService::QScxmlScxmlService(QScxmlStateMachine *stateMachine,
QScxmlStateMachine *parentStateMachine,
QScxmlInvokableServiceFactory *factory)
- : QScxmlInvokableService(parentStateMachine, factory), stateMachine(stateMachine)
+ : QScxmlInvokableService(parentStateMachine, factory), m_stateMachine(stateMachine)
{
QScxmlStateMachinePrivate::get(stateMachine)->m_parentStateMachine = parentStateMachine;
}
@@ -340,7 +340,7 @@ QScxmlScxmlService::QScxmlScxmlService(QScxmlStateMachine *stateMachine,
bool QScxmlScxmlService::start()
{
Q_D(QScxmlInvokableService);
- qCDebug(qscxmlLog) << parentStateMachine() << "preparing to start" << stateMachine;
+ qCDebug(qscxmlLog) << parentStateMachine() << "preparing to start" << m_stateMachine;
const QScxmlInvokableServiceFactory *factory
= qobject_cast<QScxmlInvokableServiceFactory *>(parent());
@@ -355,15 +355,15 @@ bool QScxmlScxmlService::start()
if (!ok)
return false;
- QScxmlStateMachinePrivate::get(stateMachine)->m_sessionId = id;
- stateMachine->setInitialValues(data);
- if (stateMachine->init()) {
- qCDebug(qscxmlLog) << parentStateMachine() << "starting" << stateMachine;
- stateMachine->start();
+ QScxmlStateMachinePrivate::get(m_stateMachine)->m_sessionId = id;
+ m_stateMachine->setInitialValues(data);
+ if (m_stateMachine->init()) {
+ qCDebug(qscxmlLog) << parentStateMachine() << "starting" << m_stateMachine;
+ m_stateMachine->start();
return true;
}
- qCDebug(qscxmlLog) << parentStateMachine() << "failed to start" << stateMachine;
+ qCDebug(qscxmlLog) << parentStateMachine() << "failed to start" << m_stateMachine;
return false;
}
@@ -372,7 +372,7 @@ bool QScxmlScxmlService::start()
*/
QString QScxmlScxmlService::id() const
{
- return stateMachine->sessionId();
+ return m_stateMachine->sessionId();
}
/*!
@@ -380,7 +380,7 @@ QString QScxmlScxmlService::id() const
*/
QString QScxmlScxmlService::name() const
{
- return stateMachine->name();
+ return m_stateMachine->name();
}
/*!
@@ -388,7 +388,12 @@ QString QScxmlScxmlService::name() const
*/
void QScxmlScxmlService::postEvent(QScxmlEvent *event)
{
- QScxmlStateMachinePrivate::get(stateMachine)->postEvent(event);
+ QScxmlStateMachinePrivate::get(m_stateMachine)->postEvent(event);
+}
+
+QScxmlStateMachine *QScxmlScxmlService::stateMachine() const
+{
+ return m_stateMachine;
}
/*!
diff --git a/src/scxml/qscxmlinvokableservice_p.h b/src/scxml/qscxmlinvokableservice_p.h
index e2a9e7b..37ca870 100644
--- a/src/scxml/qscxmlinvokableservice_p.h
+++ b/src/scxml/qscxmlinvokableservice_p.h
@@ -88,6 +88,7 @@ class Q_SCXML_EXPORT QScxmlScxmlService: public QScxmlInvokableService
{
Q_OBJECT
Q_DECLARE_PRIVATE(QScxmlInvokableService)
+ Q_PROPERTY(QScxmlStateMachine *stateMachine READ stateMachine CONSTANT)
public:
QScxmlScxmlService(QScxmlStateMachine *stateMachine,
QScxmlStateMachine *parentStateMachine,
@@ -98,8 +99,10 @@ public:
QString id() const Q_DECL_OVERRIDE;
QString name() const Q_DECL_OVERRIDE;
void postEvent(QScxmlEvent *event) Q_DECL_OVERRIDE;
+ QScxmlStateMachine *stateMachine() const;
- QScxmlStateMachine *stateMachine;
+private:
+ QScxmlStateMachine *m_stateMachine;
};
class QScxmlStaticScxmlServiceFactoryPrivate : public QScxmlInvokableServiceFactoryPrivate
diff --git a/src/scxml/qscxmlstatemachine.cpp b/src/scxml/qscxmlstatemachine.cpp
index dad5bbb..53d1bdd 100644
--- a/src/scxml/qscxmlstatemachine.cpp
+++ b/src/scxml/qscxmlstatemachine.cpp
@@ -414,7 +414,10 @@ QScxmlStateMachinePrivate::QScxmlStateMachinePrivate(const QMetaObject *metaObje
, m_eventLoopHook(this)
, m_metaObject(metaObject)
, m_infoSignalProxy(nullptr)
-{}
+{
+ static int metaType = qRegisterMetaType<QScxmlStateMachine *>();
+ Q_UNUSED(metaType);
+}
QScxmlStateMachinePrivate::~QScxmlStateMachinePrivate()
{
@@ -1889,6 +1892,7 @@ QString QScxmlStateMachine::name() const
* priority of the event.
*
* When a delay is set, the event will be queued for delivery after the timeout has passed.
+ * The state machine takes ownership of \a event and deletes it after processing.
*/
void QScxmlStateMachine::submitEvent(QScxmlEvent *event)
{
diff --git a/tests/auto/statemachine/invoke.scxml b/tests/auto/statemachine/invoke.scxml
new file mode 100644
index 0000000..1bac47a
--- /dev/null
+++ b/tests/auto/statemachine/invoke.scxml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtScxml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, 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="Directions"
+ initial="anyplace"
+>
+ <state id="anyplace">
+ <invoke type="http://www.w3.org/TR/scxml/">
+ <content>
+ <scxml name="anywhere" version="1.0">
+ <state id="here">
+ <transition event="goThere" target="there"/>
+ </state>
+ <state id="there">
+ <transition event="goHere" target="here"/>
+ </state>
+ </scxml>
+ </content>
+ </invoke>
+ </state>
+</scxml>
diff --git a/tests/auto/statemachine/tst_statemachine.cpp b/tests/auto/statemachine/tst_statemachine.cpp
index 99d6661..ed1f424 100644
--- a/tests/auto/statemachine/tst_statemachine.cpp
+++ b/tests/auto/statemachine/tst_statemachine.cpp
@@ -31,6 +31,7 @@
#include <QXmlStreamReader>
#include <QtScxml/qscxmlcompiler.h>
#include <QtScxml/qscxmlstatemachine.h>
+#include <QtScxml/qscxmlinvokableservice.h>
#include <QtScxml/private/qscxmlstatemachine_p.h>
Q_DECLARE_METATYPE(QScxmlError);
@@ -52,6 +53,8 @@ private Q_SLOTS:
void doneDotStateEvent();
void running();
+
+ void invokeStateMachine();
};
void tst_StateMachine::stateNames_data()
@@ -387,6 +390,25 @@ void tst_StateMachine::running()
QCOMPARE(stateMachine->isRunning(), false);
}
+void tst_StateMachine::invokeStateMachine()
+{
+ QScopedPointer<QScxmlStateMachine> stateMachine(
+ QScxmlStateMachine::fromFile(QString(":/tst_statemachine/invoke.scxml")));
+ QVERIFY(!stateMachine.isNull());
+
+ stateMachine->start();
+ QCOMPARE(stateMachine->isRunning(), true);
+ QTRY_VERIFY(stateMachine->activeStateNames().contains(QString("anyplace")));
+
+ QVector<QScxmlInvokableService *> services = stateMachine->invokedServices();
+ QCOMPARE(services.length(), 1);
+ QVariant subMachineVariant = services[0]->property("stateMachine");
+ QVERIFY(subMachineVariant.isValid());
+ QScxmlStateMachine *subMachine = qvariant_cast<QScxmlStateMachine *>(subMachineVariant);
+ QVERIFY(subMachine);
+ QTRY_VERIFY(subMachine->activeStateNames().contains("here"));
+}
+
QTEST_MAIN(tst_StateMachine)
#include "tst_statemachine.moc"
diff --git a/tests/auto/statemachine/tst_statemachine.qrc b/tests/auto/statemachine/tst_statemachine.qrc
index 9ded2d0..c31fe4c 100644
--- a/tests/auto/statemachine/tst_statemachine.qrc
+++ b/tests/auto/statemachine/tst_statemachine.qrc
@@ -5,5 +5,6 @@
<file>statenamesnested.scxml</file>
<file>ids1.scxml</file>
<file>stateDotDoneEvent.scxml</file>
+ <file>invoke.scxml</file>
</qresource>
</RCC>
diff --git a/tools/qscxmlc/decl.t b/tools/qscxmlc/decl.t
index 648476d..baf1600 100644
--- a/tools/qscxmlc/decl.t
+++ b/tools/qscxmlc/decl.t
@@ -8,6 +8,11 @@ public:
Q_INVOKABLE ${classname}(QObject *parent = 0);
~${classname}();
+${accessors}
+
+Q_SIGNALS:
+${signals}
+
private:
struct Data;
friend struct Data;
diff --git a/tools/qscxmlc/doc/qscxmlc.qdoc b/tools/qscxmlc/doc/qscxmlc.qdoc
index 07b5c8d..bf38a63 100644
--- a/tools/qscxmlc/doc/qscxmlc.qdoc
+++ b/tools/qscxmlc/doc/qscxmlc.qdoc
@@ -58,7 +58,8 @@
\section1 Command-Line Options
- The \c qscxmlc tool supports the following command-line options:
+ The \c qscxmlc tool supports the following command-line options, which can be specified using
+ the \c QSCXMLC_ARGUMENTS variable in the project file:
\table
\header
@@ -83,5 +84,10 @@
\li The class name of the generated state machine. If none is specified, the value of the
name attribute of the <scxml> tag is taken. If that attribute is not specified either,
the basename (excluding path) is taken from the input file name.
+ \row
+ \li \c --statemethods
+ \li Generate extra accessor and signal methods for states. This way you can connect to
+ state changes with plain QObject::connect() and directly call a method to find out if
+ a state is currently active.
\endtable
*/
diff --git a/tools/qscxmlc/generator.cpp b/tools/qscxmlc/generator.cpp
index 9082efa..02e41c8 100644
--- a/tools/qscxmlc/generator.cpp
+++ b/tools/qscxmlc/generator.cpp
@@ -587,6 +587,7 @@ void Generator::generateCode()
for (int signalindex = 0; signalindex < cdef->signalList.size(); ++signalindex)
generateSignal(&cdef->signalList[signalindex], signalindex);
+ fprintf(out, "\n");
//
// Generate plugin meta data
//
@@ -1149,7 +1150,7 @@ void Generator::generateStaticMetacall()
//---- Changed from the original in moc
if (f.implementation) {
- fprintf(out, f.implementation, methodindex);
+ fprintf(out, f.implementation, "_o", methodindex);
fprintf(out, " break;\n");
continue;
}
@@ -1223,7 +1224,7 @@ void Generator::generateStaticMetacall()
bool anythingUsed = false;
for (int methodindex = 0; methodindex < cdef->signalList.size(); ++methodindex) {
const FunctionDef &f = cdef->signalList.at(methodindex);
- if (f.wasCloned || !f.inPrivateClass.isEmpty() || f.isStatic || f.implementation)
+ if (f.wasCloned || !f.inPrivateClass.isEmpty() || f.isStatic || f.mangledName.isEmpty())
continue;
anythingUsed = true;
fprintf(out, " {\n");
@@ -1246,8 +1247,9 @@ void Generator::generateStaticMetacall()
else
fprintf(out, ");\n");
fprintf(out, " if (*reinterpret_cast<_t *>(func) == static_cast<_t>(&%s::%s)) {\n",
- cdef->classname.constData(), f.name.constData());
+ cdef->classname.constData(), f.mangledName.constData());
fprintf(out, " *result = %d;\n", methodindex);
+ fprintf(out, " return;\n");
fprintf(out, " }\n }\n");
}
if (!anythingUsed)
@@ -1521,6 +1523,34 @@ void Generator::generateSignal(FunctionDef *def,int index)
fprintf(out, "}\n");
}
+void Generator::generateAccessorDefs()
+{
+ for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
+ const PropertyDef &p = cdef->propertyList.at(propindex);
+ if (p.read.isEmpty() || p.mangledName.isEmpty())
+ continue;
+
+ fprintf(out, "bool %s::%s() const\n{\n return %s;\n}\n\n", cdef->classname.constData(),
+ p.mangledName.constData(), p.read.constData());
+ }
+}
+
+void Generator::generateSignalDefs()
+{
+ for (int methodindex = 0; methodindex < cdef->signalList.size(); ++methodindex) {
+ const FunctionDef &f = cdef->signalList.at(methodindex);
+ if (!f.implementation || f.mangledName.isEmpty())
+ continue;
+
+ fprintf(out, "void %s::%s(bool _t1)\n{\n", cdef->classname.constData(),
+ f.mangledName.constData());
+ fprintf(out, " void *_a[] = { Q_NULLPTR, "
+ "const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };\n ");
+ fprintf(out, f.implementation, "this", methodindex);
+ fprintf(out, "\n}\n\n");
+ }
+}
+
#if 0
static void writePluginMetaData(FILE *out, const QJsonObject &data)
{
diff --git a/tools/qscxmlc/generator.h b/tools/qscxmlc/generator.h
index 21d82d3..9109188 100644
--- a/tools/qscxmlc/generator.h
+++ b/tools/qscxmlc/generator.h
@@ -46,6 +46,9 @@ public:
QByteArray> &knownQObjectClasses, const QHash<QByteArray, QByteArray> &knownGadgets,
QIODevice &outfile);
void generateCode();
+ void generateAccessorDefs();
+ void generateSignalDefs();
+
private:
bool registerableMetaType(const QByteArray &propertyType);
void registerClassInfoStrings();
diff --git a/tools/qscxmlc/moc.h b/tools/qscxmlc/moc.h
index 36cff5f..a2ecb88 100644
--- a/tools/qscxmlc/moc.h
+++ b/tools/qscxmlc/moc.h
@@ -83,6 +83,7 @@ struct FunctionDef
QByteArray normalizedType;
QByteArray tag;
QByteArray name;
+ QByteArray mangledName;
bool returnTypeIsVolatile;
QList<ArgumentDef> arguments;
@@ -114,7 +115,8 @@ struct FunctionDef
struct PropertyDef
{
PropertyDef():notifyId(-1), constant(false), final(false), gspec(ValueSpec), revision(0){}
- QByteArray name, type, member, read, write, reset, designable, scriptable, editable, stored, user, notify, inPrivateClass;
+ QByteArray name, mangledName, type, member, read, write, reset, designable, scriptable,
+ editable, stored, user, notify, inPrivateClass;
int notifyId;
bool constant;
bool final;
diff --git a/tools/qscxmlc/qscxmlc.cpp b/tools/qscxmlc/qscxmlc.cpp
index 89abdaa..ce45ed0 100644
--- a/tools/qscxmlc/qscxmlc.cpp
+++ b/tools/qscxmlc/qscxmlc.cpp
@@ -122,6 +122,8 @@ int run(const QStringList &arguments)
QCommandLineOption optionClassName(QLatin1String("classname"),
QCoreApplication::translate("main", "Generate <name> for state machine class name."),
QCoreApplication::translate("main", "name"));
+ QCommandLineOption optionStateMethods(QLatin1String("statemethods"),
+ QCoreApplication::translate("main", "Generate read and notify methods for states"));
cmdParser.addPositionalArgument(QLatin1String("input"),
QCoreApplication::translate("main", "Input SCXML file."));
@@ -130,6 +132,7 @@ int run(const QStringList &arguments)
cmdParser.addOption(optionOutputHeaderName);
cmdParser.addOption(optionOutputSourceName);
cmdParser.addOption(optionClassName);
+ cmdParser.addOption(optionStateMethods);
cmdParser.process(arguments);
@@ -149,6 +152,7 @@ int run(const QStringList &arguments)
const QString scxmlFileName = inputFiles.at(0);
TranslationUnit options;
+ options.stateMethods = cmdParser.isSet(optionStateMethods);
if (cmdParser.isSet(optionNamespace))
options.namespaceName = cmdParser.value(optionNamespace);
QString outFileName = cmdParser.value(optionOutputBaseName);
diff --git a/tools/qscxmlc/scxmlcppdumper.cpp b/tools/qscxmlc/scxmlcppdumper.cpp
index db03d70..40ae1dd 100644
--- a/tools/qscxmlc/scxmlcppdumper.cpp
+++ b/tools/qscxmlc/scxmlcppdumper.cpp
@@ -506,6 +506,13 @@ void CppDumper::writeClass(const QString &className, const GeneratedTableData::M
Replacements r;
r[QStringLiteral("classname")] = className;
r[QStringLiteral("properties")] = generatePropertyDecls(info);
+ if (m_translationUnit->stateMethods) {
+ r[QStringLiteral("accessors")] = generateAccessorDecls(info);
+ r[QStringLiteral("signals")] = generateSignalDecls(info);
+ } else {
+ r[QStringLiteral("accessors")] = QString();
+ r[QStringLiteral("signals")] = QString();
+ }
genTemplate(h, QStringLiteral(":/decl.t"), r);
}
@@ -699,8 +706,42 @@ QString CppDumper::generatePropertyDecls(const GeneratedTableData::MetaDataInfo
QString decls;
for (const QString &stateName : info.stateNames) {
- if (!stateName.isEmpty())
+ if (stateName.isEmpty())
+ continue;
+
+ if (m_translationUnit->stateMethods) {
+ decls += QString::fromLatin1(" Q_PROPERTY(bool %1 READ %2 NOTIFY %3)\n")
+ .arg(stateName, mangleIdentifier(stateName),
+ mangleIdentifier(stateName + QStringLiteral("Changed")));
+ } else {
decls += QString::fromLatin1(" Q_PROPERTY(bool %1)\n").arg(stateName);
+ }
+ }
+
+ return decls;
+}
+
+QString CppDumper::generateAccessorDecls(const GeneratedTableData::MetaDataInfo &info)
+{
+ QString decls;
+
+ for (const QString &stateName : info.stateNames) {
+ if (!stateName.isEmpty())
+ decls += QString::fromLatin1(" bool %1() const;\n").arg(mangleIdentifier(stateName));
+ }
+
+ return decls;
+}
+
+QString CppDumper::generateSignalDecls(const GeneratedTableData::MetaDataInfo &info)
+{
+ QString decls;
+
+ for (const QString &stateName : info.stateNames) {
+ if (!stateName.isEmpty()) {
+ decls += QString::fromLatin1(" void %1(bool);\n")
+ .arg(mangleIdentifier(stateName + QStringLiteral("Changed")));
+ }
}
return decls;
@@ -735,16 +776,18 @@ QString CppDumper::generateMetaObject(const QString &className,
if (stateName.isEmpty())
continue;
- QByteArray mangledStateName = stateName.toUtf8();
+ QByteArray utf8StateName = stateName.toUtf8();
FunctionDef signal;
signal.type.name = "void";
signal.type.rawName = signal.type.name;
signal.normalizedType = signal.type.name;
- signal.name = mangledStateName + "Changed";
+ signal.name = utf8StateName + "Changed";
+ if (m_translationUnit->stateMethods)
+ signal.mangledName = mangleIdentifier(stateName + QStringLiteral("Changed")).toUtf8();
signal.access = FunctionDef::Public;
signal.isSignal = true;
- signal.implementation = "QMetaObject::activate(_o, &staticMetaObject, %d, _a);";
+ signal.implementation = "QMetaObject::activate(%s, &staticMetaObject, %d, _a);";
ArgumentDef arg;
arg.type.name = "bool";
@@ -758,9 +801,11 @@ QString CppDumper::generateMetaObject(const QString &className,
++classDef.notifyableProperties;
PropertyDef prop;
prop.name = stateName.toUtf8();
+ if (m_translationUnit->stateMethods)
+ prop.mangledName = mangleIdentifier(stateName).toUtf8();
prop.type = "bool";
prop.read = "isActive(" + QByteArray::number(stateIdx++) + ")";
- prop.notify = mangledStateName + "Changed";
+ prop.notify = utf8StateName + "Changed";
prop.notifyId = classDef.signalList.size() - 1;
prop.gspec = PropertyDef::ValueSpec;
prop.scriptable = "true";
@@ -773,8 +818,13 @@ QString CppDumper::generateMetaObject(const QString &className,
QBuffer buf;
buf.open(QIODevice::WriteOnly);
- Generator(&classDef, QList<QByteArray>(), knownQObjectClasses,
- QHash<QByteArray, QByteArray>(), buf).generateCode();
+ Generator generator(&classDef, QList<QByteArray>(), knownQObjectClasses,
+ QHash<QByteArray, QByteArray>(), buf);
+ generator.generateCode();
+ if (m_translationUnit->stateMethods) {
+ generator.generateAccessorDefs();
+ generator.generateSignalDefs();
+ }
buf.close();
return QString::fromUtf8(buf.buffer());
}
diff --git a/tools/qscxmlc/scxmlcppdumper.h b/tools/qscxmlc/scxmlcppdumper.h
index bd49cea..a987f80 100644
--- a/tools/qscxmlc/scxmlcppdumper.h
+++ b/tools/qscxmlc/scxmlcppdumper.h
@@ -41,12 +41,14 @@ QT_BEGIN_NAMESPACE
struct TranslationUnit
{
TranslationUnit()
- : mainDocument(Q_NULLPTR)
+ : stateMethods(false)
+ , mainDocument(Q_NULLPTR)
{}
QString scxmlFileName;
QString outHFileName, outCppFileName;
QString namespaceName;
+ bool stateMethods;
DocumentModel::ScxmlDocument *mainDocument;
QList<DocumentModel::ScxmlDocument *> allDocuments;
QHash<DocumentModel::ScxmlDocument *, QString> classnameForDocument;
@@ -79,6 +81,8 @@ private:
private:
QString generatePropertyDecls(const QScxmlInternal::GeneratedTableData::MetaDataInfo &info);
+ QString generateAccessorDecls(const QScxmlInternal::GeneratedTableData::MetaDataInfo &info);
+ QString generateSignalDecls(const QScxmlInternal::GeneratedTableData::MetaDataInfo &info);
QString generateMetaObject(const QString &className,
const QScxmlInternal::GeneratedTableData::MetaDataInfo &info);