diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/qscxmlc/decl.t | 5 | ||||
-rw-r--r-- | tools/qscxmlc/doc/qscxmlc.qdoc | 8 | ||||
-rw-r--r-- | tools/qscxmlc/generator.cpp | 36 | ||||
-rw-r--r-- | tools/qscxmlc/generator.h | 3 | ||||
-rw-r--r-- | tools/qscxmlc/moc.h | 4 | ||||
-rw-r--r-- | tools/qscxmlc/qscxmlc.cpp | 4 | ||||
-rw-r--r-- | tools/qscxmlc/scxmlcppdumper.cpp | 64 | ||||
-rw-r--r-- | tools/qscxmlc/scxmlcppdumper.h | 6 |
8 files changed, 117 insertions, 13 deletions
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); |