diff options
author | Erik Verbruggen <erik.verbruggen@theqtcompany.com> | 2015-09-25 16:54:53 +0200 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@theqtcompany.com> | 2015-10-06 10:29:18 +0300 |
commit | 3ba4e768e98fae888e51795a2f4ac4913d0a0fc0 (patch) | |
tree | 8abf3eff512df697dc26a32952a826f9313698d3 /tools/qscxmlc | |
parent | 378644d9420825993bc8a9ebee93fa713385fc38 (diff) |
Add properties for nested state machines.
Change-Id: I80893af6755ca9b731c0701a38b55b8596f84f94
Reviewed-by: Erik Verbruggen <erik.verbruggen@theqtcompany.com>
Diffstat (limited to 'tools/qscxmlc')
-rw-r--r-- | tools/qscxmlc/qscxmlc.cpp | 26 | ||||
-rw-r--r-- | tools/qscxmlc/scxmlcppdumper.cpp | 135 | ||||
-rw-r--r-- | tools/qscxmlc/scxmlcppdumper.h | 4 |
3 files changed, 126 insertions, 39 deletions
diff --git a/tools/qscxmlc/qscxmlc.cpp b/tools/qscxmlc/qscxmlc.cpp index c0f0d18..b1c073b 100644 --- a/tools/qscxmlc/qscxmlc.cpp +++ b/tools/qscxmlc/qscxmlc.cpp @@ -59,6 +59,15 @@ int write(TranslationUnit *tu) return NoError; } +static void collectAllDocuments(DocumentModel::ScxmlDocument *doc, QMap<DocumentModel::ScxmlDocument *, QString> *docs) +{ + docs->insert(doc, doc->root->name); + foreach (DocumentModel::ScxmlDocument *subDoc, doc->allSubDocuments) { + collectAllDocuments(subDoc, docs); + } +} + + int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); @@ -133,17 +142,8 @@ int main(int argc, char *argv[]) return ScxmlVerificationError; } - struct : public DocumentModel::NodeVisitor { - bool visit(DocumentModel::Invoke *invoke) Q_DECL_OVERRIDE { - if (DocumentModel::ScxmlDocument *doc = invoke->content.data()) { - docs.insert(doc, doc->root->name); - } - return true; - } - - QMap<DocumentModel::ScxmlDocument *, QString> docs; - } collector; - mainDoc->root->accept(&collector); + QMap<DocumentModel::ScxmlDocument *, QString> docs; + collectAllDocuments(mainDoc, &docs); if (mainClassname.isEmpty()) mainClassname = mainDoc->root->name; if (mainClassname.isEmpty()) { @@ -152,13 +152,13 @@ int main(int argc, char *argv[]) if (dot != -1) mainClassname = mainClassname.left(dot); } - collector.docs.insert(mainDoc, mainClassname); + docs.insert(mainDoc, mainClassname); TranslationUnit tu = options; tu.mainDocument = mainDoc; tu.outHFileName = outHFileName; tu.outCppFileName = outCppFileName; - for (QMap<DocumentModel::ScxmlDocument *, QString>::const_iterator i = collector.docs.begin(), ei = collector.docs.end(); i != ei; ++i) { + for (QMap<DocumentModel::ScxmlDocument *, QString>::const_iterator i = docs.begin(), ei = docs.end(); i != ei; ++i) { auto name = i.value(); if (name.isEmpty()) { name = QStringLiteral("%1_StateMachine_%2").arg(mainClassname).arg(tu.classnameForDocument.size() + 1); diff --git a/tools/qscxmlc/scxmlcppdumper.cpp b/tools/qscxmlc/scxmlcppdumper.cpp index fe9cba6..9039c66 100644 --- a/tools/qscxmlc/scxmlcppdumper.cpp +++ b/tools/qscxmlc/scxmlcppdumper.cpp @@ -78,6 +78,7 @@ struct Method { }; struct ClassDump { + bool needsEventFilter = false; StringListDumper implIncludes; QString className; QString dataModelClassName; @@ -91,6 +92,7 @@ struct ClassDump { StringListDumper properties; StringListDumper signalMethods; QList<Method> publicMethods; + QList<Method> protectedMethods; StringListDumper publicSlotDeclarations; StringListDumper publicSlotDefinitions; @@ -176,10 +178,15 @@ class DumperVisitor: public QScxmlExecutableContent::Builder public: DumperVisitor(ClassDump &clazz, TranslationUnit *tu) - : clazz(clazz) + : namespacePrefix(QStringLiteral("::")) + , clazz(clazz) , translationUnit(tu) , m_bindLate(false) - {} + { + if (!tu->namespaceName.isEmpty()) { + namespacePrefix += QStringLiteral("%1::").arg(tu->namespaceName); + } + } void process(ScxmlDocument *doc) { @@ -189,6 +196,7 @@ public: doc->root->accept(this); + addSubStateMachineProperties(doc); addEvents(); generateTables(); @@ -206,12 +214,12 @@ protected: { // init: if (!node->name.isEmpty()) { - clazz.dataMethods << QStringLiteral("QString name() const Q_DECL_OVERRIDE") + clazz.dataMethods << QStringLiteral("QString name() const Q_DECL_OVERRIDE Q_DECL_FINAL") << QStringLiteral("{ return string(%1); }").arg(addString(node->name)) << QString(); clazz.init.impl << QStringLiteral("stateMachine.setObjectName(string(%1));").arg(addString(node->name)); } else { - clazz.dataMethods << QStringLiteral("QString name() const Q_DECL_OVERRIDE") + clazz.dataMethods << QStringLiteral("QString name() const Q_DECL_OVERRIDE Q_DECL_FINAL") << QStringLiteral("{ return QString(); }") << QString(); } @@ -249,7 +257,7 @@ protected: m_dataElements.append(node->dataElements); if (node->script || !m_dataElements.isEmpty() || !node->initialSetup.isEmpty()) { - clazz.dataMethods << QStringLiteral("QScxmlExecutableContent::ContainerId initialSetup() const Q_DECL_OVERRIDE") + clazz.dataMethods << QStringLiteral("QScxmlExecutableContent::ContainerId initialSetup() const Q_DECL_OVERRIDE Q_DECL_FINAL") << QStringLiteral("{ return %1; }").arg(startNewSequence()) << QString(); generate(m_dataElements); @@ -259,7 +267,7 @@ protected: visit(&node->initialSetup); endSequence(); } else { - clazz.dataMethods << QStringLiteral("QScxmlExecutableContent::ContainerId initialSetup() const Q_DECL_OVERRIDE") + clazz.dataMethods << QStringLiteral("QScxmlExecutableContent::ContainerId initialSetup() const Q_DECL_OVERRIDE Q_DECL_FINAL") << QStringLiteral("{ return QScxmlExecutableContent::NoInstruction; }") << QString(); } @@ -611,6 +619,38 @@ private: return init; } + void addSubStateMachineProperties(ScxmlDocument *doc) + { + QStringList serviceProps; + foreach (ScxmlDocument *subDocs, doc->allSubDocuments) { + auto name = subDocs->root->name; + if (name.isEmpty()) + continue; + + serviceProps.append(name); + clazz.classFields << QStringLiteral("%1%2 *%2;").arg(namespacePrefix, name); + clazz.constructor.initializer << QStringLiteral("%1(Q_NULLPTR)").arg(name); + clazz.properties << QStringLiteral("Q_PROPERTY(%1%2 *%2 READ %2() NOTIFY %2Changed())").arg(namespacePrefix, name); + Method getter(QStringLiteral("%1%2 *%2() const").arg(namespacePrefix, name)); + getter.impl << QStringLiteral("%1%2 *%3::%2() const").arg(namespacePrefix, name, clazz.className) + << QStringLiteral("{ return data->%1; }").arg(name); + clazz.publicMethods << getter; + clazz.signalMethods << QStringLiteral("void %1Changed();").arg(name); + } + + if (!serviceProps.isEmpty()) { + Method reg(QStringLiteral("void setService(const QString &id, QScxmlInvokableService *service) Q_DECL_OVERRIDE Q_DECL_FINAL")); + reg.impl << QStringLiteral("void %1::setService(const QString &id, QScxmlInvokableService *service) {").arg(clazz.className); + foreach (const QString &prop, serviceProps) { + reg.impl << QStringLiteral(" SET_SERVICE_PROP(%1, %2, %3%2, %2Changed)") + .arg(addString(prop)) + .arg(prop, namespacePrefix); + } + reg.impl << QStringLiteral("}"); + clazz.protectedMethods.append(reg); + } + } + void addEvents() { QStringList knownEventsList = m_knownEvents.toList(); @@ -632,9 +672,10 @@ private: } if (!m_signals.isEmpty()) { + clazz.needsEventFilter = true; clazz.init.impl << QStringLiteral("stateMachine.setScxmlEventFilter(this);"); auto &dm = clazz.dataMethods; - dm << QStringLiteral("bool handle(QScxmlEvent *event, QScxmlStateMachine *stateMachine) Q_DECL_OVERRIDE {") + dm << QStringLiteral("bool handle(QScxmlEvent *event, QScxmlStateMachine *stateMachine) Q_DECL_OVERRIDE {") << QStringLiteral(" if (event->originType() != QStringLiteral(\"qt:signal\")) { return true; }") << QStringLiteral(" %1 *m = qobject_cast<%1 *>(stateMachine);").arg(clazz.className); foreach (const QString &s, m_signals) { @@ -735,7 +776,7 @@ private: return QString(); }); t << QStringLiteral("};") << QStringLiteral(""); - clazz.dataMethods << QStringLiteral("QScxmlExecutableContent::Instructions instructions() const Q_DECL_OVERRIDE") + clazz.dataMethods << QStringLiteral("QScxmlExecutableContent::Instructions instructions() const Q_DECL_OVERRIDE Q_DECL_FINAL") << QStringLiteral("{ return theInstructions; }") << QString(); } @@ -758,7 +799,7 @@ private: }); } t << QStringLiteral("};") << QStringLiteral(""); - clazz.dataMethods << QStringLiteral("QScxmlExecutableContent::StringId *dataNames(int *count) const Q_DECL_OVERRIDE"); + clazz.dataMethods << QStringLiteral("QScxmlExecutableContent::StringId *dataNames(int *count) const Q_DECL_OVERRIDE Q_DECL_FINAL"); clazz.dataMethods << QStringLiteral("{ *count = %1; return dataIds; }").arg(count); clazz.dataMethods << QString(); } @@ -781,7 +822,7 @@ private: }); } t << QStringLiteral("};") << QStringLiteral(""); - clazz.dataMethods << QStringLiteral("QScxmlExecutableContent::EvaluatorInfo evaluatorInfo(QScxmlExecutableContent::EvaluatorId evaluatorId) const Q_DECL_OVERRIDE"); + clazz.dataMethods << QStringLiteral("QScxmlExecutableContent::EvaluatorInfo evaluatorInfo(QScxmlExecutableContent::EvaluatorId evaluatorId) const Q_DECL_OVERRIDE Q_DECL_FINAL"); clazz.dataMethods << QStringLiteral("{ Q_ASSERT(evaluatorId >= 0); Q_ASSERT(evaluatorId < %1); return evaluators[evaluatorId]; }").arg(evaluators.size()); clazz.dataMethods << QString(); @@ -882,7 +923,7 @@ private: }); } t << QStringLiteral("};") << QStringLiteral(""); - clazz.dataMethods << QStringLiteral("QScxmlExecutableContent::AssignmentInfo assignmentInfo(QScxmlExecutableContent::EvaluatorId assignmentId) const Q_DECL_OVERRIDE"); + clazz.dataMethods << QStringLiteral("QScxmlExecutableContent::AssignmentInfo assignmentInfo(QScxmlExecutableContent::EvaluatorId assignmentId) const Q_DECL_OVERRIDE Q_DECL_FINAL"); clazz.dataMethods << QStringLiteral("{ Q_ASSERT(assignmentId >= 0); Q_ASSERT(assignmentId < %1); return assignments[assignmentId]; }").arg(assignments.size()); clazz.dataMethods << QString(); } @@ -901,7 +942,7 @@ private: return QStringLiteral("{ %1, %2, %3, %4 }").arg(foreach.array).arg(foreach.item).arg(foreach.index).arg(foreach.context); }); t << QStringLiteral("};") << QStringLiteral(""); - clazz.dataMethods << QStringLiteral("QScxmlExecutableContent::ForeachInfo foreachInfo(QScxmlExecutableContent::EvaluatorId foreachId) const Q_DECL_OVERRIDE"); + clazz.dataMethods << QStringLiteral("QScxmlExecutableContent::ForeachInfo foreachInfo(QScxmlExecutableContent::EvaluatorId foreachId) const Q_DECL_OVERRIDE Q_DECL_FINAL"); clazz.dataMethods << QStringLiteral("{ Q_ASSERT(foreachId >= 0); Q_ASSERT(foreachId < %1); return foreaches[foreachId]; }").arg(foreaches.size()); } @@ -1028,10 +1069,11 @@ private: { auto name = translationUnit->classnameForDocument.value(doc); Q_ASSERT(!name.isEmpty()); - return name; + return namespacePrefix + name; } private: + QString namespacePrefix; ClassDump &clazz; TranslationUnit *translationUnit; QHash<AbstractState *, QString> m_mangledNames; @@ -1052,20 +1094,23 @@ void CppDumper::dump(TranslationUnit *unit) m_translationUnit = unit; + QStringList classDecls; QVector<ClassDump> clazzes; auto docs = m_translationUnit->otherDocuments(); clazzes.resize(docs.size() + 1); DumperVisitor(clazzes[0], m_translationUnit).process(unit->mainDocument); for (int i = 0, ei = docs.size(); i != ei; ++i) { auto doc = docs.at(i); - DumperVisitor(clazzes[i + 1], m_translationUnit).process(doc); + ClassDump &clazz = clazzes[i + 1]; + DumperVisitor(clazz, m_translationUnit).process(doc); + classDecls.append(clazz.className); } auto headerName = QFileInfo(unit->outHFileName).fileName(); const QString headerGuard = headerName.toUpper() .replace(QLatin1Char('.'), QLatin1Char('_')) .replace(QLatin1Char('-'), QLatin1Char('_')); - writeHeaderStart(headerGuard); + writeHeaderStart(headerGuard, classDecls); writeImplStart(clazzes); foreach (const ClassDump &clazz, clazzes) { @@ -1073,7 +1118,8 @@ void CppDumper::dump(TranslationUnit *unit) writeImplBody(clazz); } - writeHeaderEnd(headerGuard); + classDecls.append(clazzes.at(0).className); + writeHeaderEnd(headerGuard, classDecls); writeImplEnd(); } @@ -1088,7 +1134,7 @@ QString CppDumper::mangleId(const QString &id) return mangled; } -void CppDumper::writeHeaderStart(const QString &headerGuard) +void CppDumper::writeHeaderStart(const QString &headerGuard, const QStringList &forwardDecls) { h << QStringLiteral("#ifndef ") << headerGuard << endl << QStringLiteral("#define ") << headerGuard << endl @@ -1096,6 +1142,13 @@ void CppDumper::writeHeaderStart(const QString &headerGuard) h << l(headerStart); if (!m_translationUnit->namespaceName.isEmpty()) h << l("namespace ") << m_translationUnit->namespaceName << l(" {") << endl << endl; + + if (!forwardDecls.isEmpty()) { + foreach (const QString &name, forwardDecls) { + h << QStringLiteral("class %1;").arg(name) << endl; + } + h << endl; + } } void CppDumper::writeClass(const ClassDump &clazz) @@ -1114,10 +1167,17 @@ void CppDumper::writeClass(const ClassDump &clazz) } } + if (!clazz.protectedMethods.isEmpty()) { + h << endl + << QStringLiteral("protected:") << endl; + foreach (const Method &m, clazz.protectedMethods) { + h << QStringLiteral(" ") << m.decl << QLatin1Char(';') << endl; + } + } + if (!clazz.signalMethods.isEmpty()) { h << endl - << QStringLiteral("signals:") - << endl; + << QStringLiteral("signals:") << endl; clazz.signalMethods.write(h, QStringLiteral(" "), QStringLiteral("\n")); } @@ -1135,12 +1195,20 @@ void CppDumper::writeClass(const ClassDump &clazz) << l("};") << endl << endl; } -void CppDumper::writeHeaderEnd(const QString &headerGuard) +void CppDumper::writeHeaderEnd(const QString &headerGuard, const QStringList &metatypeDecls) { + QString ns; if (!m_translationUnit->namespaceName.isEmpty()) { h << QStringLiteral("} // %1 namespace ").arg(m_translationUnit->namespaceName) << endl << endl; + ns = QStringLiteral("::%1").arg(m_translationUnit->namespaceName); + } + + foreach (const QString &name, metatypeDecls) { + h << QStringLiteral("Q_DECLARE_METATYPE(%1::%2*);").arg(ns, name) << endl; } + h << endl; + h << QStringLiteral("#endif // ") << headerGuard << endl; } @@ -1168,7 +1236,7 @@ void CppDumper::writeImplStart(const QVector<ClassDump> &allClazzes) void CppDumper::writeImplBody(const ClassDump &clazz) { cpp << l("struct ") << clazz.className << l("::Data: private QScxmlTableData"); - if (!clazz.signalMethods.isEmpty()) { + if (clazz.needsEventFilter) { cpp << QStringLiteral(", public QScxmlEventFilter"); } cpp << l(" {") << endl; @@ -1191,9 +1259,9 @@ void CppDumper::writeImplBody(const ClassDump &clazz) cpp << l("};") << endl << endl; cpp << clazz.className << l("::") << clazz.className << l("(QObject *parent)") << endl - << l(" : QScxmlStateMachine(parent)") << endl - << l(" , data(new Data(*this))") << endl - << l("{ qRegisterMetaType<QAbstractState *>(); }") << endl + << QStringLiteral(" : QScxmlStateMachine(parent)") << endl + << QStringLiteral(" , data(new Data(*this))") << endl + << QStringLiteral("{ qRegisterMetaType<%1 *>(); qRegisterMetaType<QAbstractState *>(); }").arg(clazz.className) << endl << endl; cpp << clazz.className << l("::~") << clazz.className << l("()") << endl << l("{ delete data; }") << endl @@ -1202,6 +1270,25 @@ void CppDumper::writeImplBody(const ClassDump &clazz) m.impl.write(cpp, QStringLiteral(""), QStringLiteral("\n"), clazz.className); cpp << endl; } + if (!clazz.protectedMethods.isEmpty()) { + cpp << "#define SET_SERVICE_PROP(s, n, fq, sig) \\\n" + " if (id == data->string(s)) { \\\n" + " QScxmlInvokableScxml *machine = service ? dynamic_cast<QScxmlInvokableScxml *>(service) : Q_NULLPTR; \\\n" + " fq *casted = machine ? dynamic_cast<fq*>(machine->stateMachine()) : Q_NULLPTR; \\\n" + " if (data->n != casted) { \\\n" + " data->n = casted; \\\n" + " emit sig(); \\\n" + " } \\\n" + " return; \\\n" + " }\n" + << endl; + foreach (const Method &m, clazz.protectedMethods) { + m.impl.write(cpp, QStringLiteral(""), QStringLiteral("\n"), clazz.className); + cpp << endl; + } + cpp << QStringLiteral("#undef SET_SERVICE_PROP") << endl + << endl; + } clazz.publicSlotDefinitions.write(cpp, QStringLiteral("\n"), QStringLiteral("\n")); cpp << endl; diff --git a/tools/qscxmlc/scxmlcppdumper.h b/tools/qscxmlc/scxmlcppdumper.h index 82f9f74..34323cb 100644 --- a/tools/qscxmlc/scxmlcppdumper.h +++ b/tools/qscxmlc/scxmlcppdumper.h @@ -65,9 +65,9 @@ public: static QString mangleId(const QString &id); private: - void writeHeaderStart(const QString &headerGuard); + void writeHeaderStart(const QString &headerGuard, const QStringList &forwardDecls); void writeClass(const ClassDump &clazz); - void writeHeaderEnd(const QString &headerGuard); + void writeHeaderEnd(const QString &headerGuard, const QStringList &metatypeDecls); void writeImplStart(const QVector<ClassDump> &allClazzes); void writeImplBody(const ClassDump &clazz); void writeImplEnd(); |