diff options
Diffstat (limited to 'src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp')
-rw-r--r-- | src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp | 736 |
1 files changed, 414 insertions, 322 deletions
diff --git a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp index 04233df1fe..d637854d2b 100644 --- a/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp +++ b/src/tools/qdbusxml2cpp/qdbusxml2cpp.cpp @@ -21,24 +21,75 @@ #define PROGRAMNAME "qdbusxml2cpp" #define PROGRAMVERSION "0.8" -#define PROGRAMCOPYRIGHT "Copyright (C) 2022 The Qt Company Ltd." +#define PROGRAMCOPYRIGHT QT_COPYRIGHT #define ANNOTATION_NO_WAIT "org.freedesktop.DBus.Method.NoReply" using namespace Qt::StringLiterals; -static QString globalClassName; -static QString parentClassName; -static QString proxyFile; -static QString adaptorFile; -static QString inputFile; -static bool skipNamespaces; -static bool verbose; -static bool includeMocs; -static QString commandLine; -static QStringList includes; -static QStringList globalIncludes; -static QStringList wantedInterfaces; +class QDBusXmlToCpp final +{ +public: + int run(const QCoreApplication &app); + +private: + class DiagnosticsReporter final : public QDBusIntrospection::DiagnosticsReporter + { + public: + void setFileName(const QString &fileName) { m_fileName = fileName; } + bool hadErrors() const { return m_hadErrors; } + + void warning(const QDBusIntrospection::SourceLocation &location, const char *msg, + ...) override; + void error(const QDBusIntrospection::SourceLocation &location, const char *msg, + ...) override; + void note(const QDBusIntrospection::SourceLocation &location, const char *msg, ...) + Q_ATTRIBUTE_FORMAT_PRINTF(3, 4); + + private: + QString m_fileName; + bool m_hadErrors = false; + + void report(const QDBusIntrospection::SourceLocation &location, const char *msg, va_list ap, + const char *severity); + }; + + enum ClassType { Proxy, Adaptor }; + + void writeAdaptor(const QString &filename, const QDBusIntrospection::Interfaces &interfaces); + void writeProxy(const QString &filename, const QDBusIntrospection::Interfaces &interfaces); + + QDBusIntrospection::Interfaces readInput(); + void cleanInterfaces(QDBusIntrospection::Interfaces &interfaces); + QTextStream &writeHeader(QTextStream &ts, bool changesWillBeLost); + QString classNameForInterface(const QString &interface, ClassType classType); + QByteArray qtTypeName(const QDBusIntrospection::SourceLocation &location, + const QString &signature, + const QDBusIntrospection::Annotations &annotations, + qsizetype paramId = -1, const char *direction = "Out"); + void + writeArgList(QTextStream &ts, const QStringList &argNames, + const QDBusIntrospection::Annotations &annotations, + const QDBusIntrospection::Arguments &inputArgs, + const QDBusIntrospection::Arguments &outputArgs = QDBusIntrospection::Arguments()); + void writeSignalArgList(QTextStream &ts, const QStringList &argNames, + const QDBusIntrospection::Annotations &annotations, + const QDBusIntrospection::Arguments &outputArgs); + QString propertyGetter(const QDBusIntrospection::Property &property); + QString propertySetter(const QDBusIntrospection::Property &property); + + QString globalClassName; + QString parentClassName; + QString inputFile; + bool skipNamespaces = false; + bool includeMocs = false; + QString commandLine; + QStringList includes; + QStringList globalIncludes; + QStringList wantedInterfaces; + + DiagnosticsReporter reporter; +}; static const char includeList[] = "#include <QtCore/QByteArray>\n" @@ -51,29 +102,71 @@ static const char includeList[] = static const char forwardDeclarations[] = "#include <QtCore/qcontainerfwd.h>\n"; -static QDBusIntrospection::Interfaces readInput() +void QDBusXmlToCpp::DiagnosticsReporter::warning(const QDBusIntrospection::SourceLocation &location, + const char *msg, ...) +{ + va_list ap; + va_start(ap, msg); + report(location, msg, ap, "warning"); + va_end(ap); +} + +void QDBusXmlToCpp::DiagnosticsReporter::error(const QDBusIntrospection::SourceLocation &location, + const char *msg, ...) +{ + va_list ap; + va_start(ap, msg); + report(location, msg, ap, "error"); + va_end(ap); + m_hadErrors = true; +} + +void QDBusXmlToCpp::DiagnosticsReporter::note(const QDBusIntrospection::SourceLocation &location, + const char *msg, ...) +{ + va_list ap; + va_start(ap, msg); + report(location, msg, ap, "note"); + va_end(ap); + m_hadErrors = true; +} + +void QDBusXmlToCpp::DiagnosticsReporter::report(const QDBusIntrospection::SourceLocation &location, + const char *msg, va_list ap, const char *severity) +{ + fprintf(stderr, "%s:%lld:%lld: %s: ", qPrintable(m_fileName), + (long long int)location.lineNumber, (long long int)location.columnNumber + 1, severity); + vfprintf(stderr, msg, ap); +} + +QDBusIntrospection::Interfaces QDBusXmlToCpp::readInput() { QFile input(inputFile); - if (inputFile.isEmpty() || inputFile == "-"_L1) - input.open(stdin, QIODevice::ReadOnly); - else - input.open(QIODevice::ReadOnly); + if (inputFile.isEmpty() || inputFile == "-"_L1) { + reporter.setFileName("<standard input>"_L1); + if (!input.open(stdin, QIODevice::ReadOnly)) { + fprintf(stderr, PROGRAMNAME ": could not open standard input: %s\n", + qPrintable(input.errorString())); + exit(1); + } + } else { + reporter.setFileName(inputFile); + if (!input.open(QIODevice::ReadOnly)) { + fprintf(stderr, PROGRAMNAME ": could not open input file '%s': %s\n", + qPrintable(inputFile), qPrintable(input.errorString())); + exit(1); + } + } QByteArray data = input.readAll(); + auto interfaces = QDBusIntrospection::parseInterfaces(QString::fromUtf8(data), &reporter); + if (reporter.hadErrors()) + exit(1); - // check if the input is already XML - data = data.trimmed(); - if (data.startsWith("<!DOCTYPE ") || data.startsWith("<?xml") || - data.startsWith("<node") || data.startsWith("<interface")) - // already XML - return QDBusIntrospection::parseInterfaces(QString::fromUtf8(data)); - - fprintf(stderr, "%s: Cannot process input: '%s'. Stop.\n", - PROGRAMNAME, qPrintable(inputFile)); - exit(1); + return interfaces; } -static void cleanInterfaces(QDBusIntrospection::Interfaces &interfaces) +void QDBusXmlToCpp::cleanInterfaces(QDBusIntrospection::Interfaces &interfaces) { if (!wantedInterfaces.isEmpty()) { QDBusIntrospection::Interfaces::Iterator it = interfaces.begin(); @@ -179,30 +272,29 @@ static QString moc(const QString &name) return retval; } -static QTextStream &writeHeader(QTextStream &ts, bool changesWillBeLost) +QTextStream &QDBusXmlToCpp::writeHeader(QTextStream &ts, bool changesWillBeLost) { - ts << "/*" << Qt::endl - << " * This file was generated by " PROGRAMNAME " version " PROGRAMVERSION << Qt::endl - << " * Command line was: " << commandLine << Qt::endl - << " *" << Qt::endl - << " * " PROGRAMNAME " is " PROGRAMCOPYRIGHT << Qt::endl - << " *" << Qt::endl - << " * This is an auto-generated file." << Qt::endl; + ts << "/*\n" + " * This file was generated by " PROGRAMNAME " version " PROGRAMVERSION "\n" + " * Source file was " << QFileInfo(inputFile).fileName() << "\n" + " *\n" + " * " PROGRAMNAME " is " PROGRAMCOPYRIGHT "\n" + " *\n" + " * This is an auto-generated file.\n"; if (changesWillBeLost) - ts << " * Do not edit! All changes made to it will be lost." << Qt::endl; + ts << " * Do not edit! All changes made to it will be lost.\n"; else - ts << " * This file may have been hand-edited. Look for HAND-EDIT comments" << Qt::endl - << " * before re-generating it." << Qt::endl; + ts << " * This file may have been hand-edited. Look for HAND-EDIT comments\n" + " * before re-generating it.\n"; - ts << " */" << Qt::endl - << Qt::endl; + ts << " */\n\n"; return ts; } -enum ClassType { Proxy, Adaptor }; -static QString classNameForInterface(const QString &interface, ClassType classType) +QString QDBusXmlToCpp::classNameForInterface(const QString &interface, + QDBusXmlToCpp::ClassType classType) { if (!globalClassName.isEmpty()) return globalClassName; @@ -227,39 +319,39 @@ static QString classNameForInterface(const QString &interface, ClassType classTy return retval; } -static QByteArray qtTypeName(const QString &where, const QString &signature, - const QDBusIntrospection::Annotations &annotations, qsizetype paramId = -1, - const char *direction = "Out") +QByteArray QDBusXmlToCpp::qtTypeName(const QDBusIntrospection::SourceLocation &location, + const QString &signature, + const QDBusIntrospection::Annotations &annotations, + qsizetype paramId, const char *direction) { int type = QDBusMetaType::signatureToMetaType(signature.toLatin1()).id(); if (type == QMetaType::UnknownType) { - QString annotationName = QString::fromLatin1("org.qtproject.QtDBus.QtTypeName"); + QString annotationName = u"org.qtproject.QtDBus.QtTypeName"_s; if (paramId >= 0) - annotationName += QString::fromLatin1(".%1%2").arg(QLatin1StringView(direction)).arg(paramId); - QString qttype = annotations.value(annotationName); + annotationName += ".%1%2"_L1.arg(QLatin1StringView(direction)).arg(paramId); + auto annotation = annotations.value(annotationName); + QString qttype = annotation.value; if (!qttype.isEmpty()) return std::move(qttype).toLatin1(); - QString oldAnnotationName = QString::fromLatin1("com.trolltech.QtDBus.QtTypeName"); + QString oldAnnotationName = u"com.trolltech.QtDBus.QtTypeName"_s; if (paramId >= 0) - oldAnnotationName += QString::fromLatin1(".%1%2").arg(QLatin1StringView(direction)).arg(paramId); - qttype = annotations.value(oldAnnotationName); + oldAnnotationName += ".%1%2"_L1.arg(QLatin1StringView(direction)).arg(paramId); + annotation = annotations.value(oldAnnotationName); + qttype = annotation.value; if (qttype.isEmpty()) { - fprintf(stderr, "%s: Got unknown type `%s' processing '%s'\n", - PROGRAMNAME, qPrintable(signature), qPrintable(inputFile)); - fprintf(stderr, - "You should add <annotation name=\"%s\" value=\"<type>\"/> to the XML " - "description for '%s'\n", - qPrintable(annotationName), qPrintable(where)); + reporter.error(location, "unknown type `%s'\n", qPrintable(signature)); + reporter.note(location, "you should add <annotation name=\"%s\" value=\"<type>\"/>\n", + qPrintable(annotationName)); exit(1); } - fprintf(stderr, "%s: Warning: deprecated annotation '%s' found while processing '%s'; " - "suggest updating to '%s'\n", - PROGRAMNAME, qPrintable(oldAnnotationName), qPrintable(inputFile), - qPrintable(annotationName)); + reporter.warning(annotation.location, "deprecated annotation '%s' found\n", + qPrintable(oldAnnotationName)); + reporter.note(annotation.location, "suggest updating to '%s'\n", + qPrintable(annotationName)); return std::move(qttype).toLatin1(); } @@ -320,17 +412,17 @@ static QStringList makeArgNames(const QDBusIntrospection::Arguments &inputArgs, return retval; } -static void writeArgList(QTextStream &ts, const QStringList &argNames, - const QDBusIntrospection::Annotations &annotations, - const QDBusIntrospection::Arguments &inputArgs, - const QDBusIntrospection::Arguments &outputArgs = QDBusIntrospection::Arguments()) +void QDBusXmlToCpp::writeArgList(QTextStream &ts, const QStringList &argNames, + const QDBusIntrospection::Annotations &annotations, + const QDBusIntrospection::Arguments &inputArgs, + const QDBusIntrospection::Arguments &outputArgs) { // input args: bool first = true; qsizetype argPos = 0; for (qsizetype i = 0; i < inputArgs.size(); ++i) { const QDBusIntrospection::Argument &arg = inputArgs.at(i); - QString type = constRefArg(qtTypeName(arg.name, arg.type, annotations, i, "In")); + QString type = constRefArg(qtTypeName(arg.location, arg.type, annotations, i, "In")); if (!first) ts << ", "; @@ -347,22 +439,21 @@ static void writeArgList(QTextStream &ts, const QStringList &argNames, if (!first) ts << ", "; - ts << nonConstRefArg(qtTypeName(arg.name, arg.type, annotations, i, "Out")) + ts << nonConstRefArg(qtTypeName(arg.location, arg.type, annotations, i, "Out")) << argNames.at(argPos++); first = false; } } -static void writeSignalArgList(QTextStream &ts, const QStringList &argNames, - const QDBusIntrospection::Annotations &annotations, - const QDBusIntrospection::Arguments &outputArgs) +void QDBusXmlToCpp::writeSignalArgList(QTextStream &ts, const QStringList &argNames, + const QDBusIntrospection::Annotations &annotations, + const QDBusIntrospection::Arguments &outputArgs) { bool first = true; qsizetype argPos = 0; for (qsizetype i = 0; i < outputArgs.size(); ++i) { const QDBusIntrospection::Argument &arg = outputArgs.at(i); - QString type = constRefArg( - qtTypeName(arg.name, arg.type, annotations, i, "Out")); + QString type = constRefArg(qtTypeName(arg.location, arg.type, annotations, i, "Out")); if (!first) ts << ", "; @@ -371,49 +462,49 @@ static void writeSignalArgList(QTextStream &ts, const QStringList &argNames, } } -static QString propertyGetter(const QDBusIntrospection::Property &property) +QString QDBusXmlToCpp::propertyGetter(const QDBusIntrospection::Property &property) { - QString getter = property.annotations.value("org.qtproject.QtDBus.PropertyGetter"_L1); - if (!getter.isEmpty()) - return getter; - - getter = property.annotations.value("com.trolltech.QtDBus.propertyGetter"_L1); - if (!getter.isEmpty()) { - fprintf(stderr, "%s: Warning: deprecated annotation 'com.trolltech.QtDBus.propertyGetter' found" - " while processing '%s';" - " suggest updating to 'org.qtproject.QtDBus.PropertyGetter'\n", - PROGRAMNAME, qPrintable(inputFile)); - return getter; + auto annotation = property.annotations.value("org.qtproject.QtDBus.PropertyGetter"_L1); + if (!annotation.value.isEmpty()) + return annotation.value; + + annotation = property.annotations.value("com.trolltech.QtDBus.propertyGetter"_L1); + if (!annotation.value.isEmpty()) { + reporter.warning(annotation.location, + "deprecated annotation 'com.trolltech.QtDBus.propertyGetter' found\n"); + reporter.note(annotation.location, + "suggest updating to 'org.qtproject.QtDBus.PropertyGetter'\n"); + return annotation.value; } - getter = property.name; + QString getter = property.name; getter[0] = getter[0].toLower(); return getter; } -static QString propertySetter(const QDBusIntrospection::Property &property) +QString QDBusXmlToCpp::propertySetter(const QDBusIntrospection::Property &property) { - QString setter = property.annotations.value("org.qtproject.QtDBus.PropertySetter"_L1); - if (!setter.isEmpty()) - return setter; - - setter = property.annotations.value("com.trolltech.QtDBus.propertySetter"_L1); - if (!setter.isEmpty()) { - fprintf(stderr, "%s: Warning: deprecated annotation 'com.trolltech.QtDBus.propertySetter' found" - " while processing '%s';" - " suggest updating to 'org.qtproject.QtDBus.PropertySetter'\n", - PROGRAMNAME, qPrintable(inputFile)); - return setter; + auto annotation = property.annotations.value("org.qtproject.QtDBus.PropertySetter"_L1); + if (!annotation.value.isEmpty()) + return annotation.value; + + annotation = property.annotations.value("com.trolltech.QtDBus.propertySetter"_L1); + if (!annotation.value.isEmpty()) { + reporter.warning(annotation.location, + "deprecated annotation 'com.trolltech.QtDBus.propertySetter' found\n"); + reporter.note(annotation.location, + "suggest updating to 'org.qtproject.QtDBus.PropertySetter'\n"); + return annotation.value; } - setter = "set"_L1 + property.name; + QString setter = "set"_L1 + property.name; setter[3] = setter[3].toUpper(); return setter; } static QString methodName(const QDBusIntrospection::Method &method) { - QString name = method.annotations.value(QStringLiteral("org.qtproject.QtDBus.MethodName")); + QString name = method.annotations.value(u"org.qtproject.QtDBus.MethodName"_s).value; if (!name.isEmpty()) return name; @@ -457,7 +548,8 @@ static bool openFile(const QString &fileName, QFile &file) return isOk; } -static void writeProxy(const QString &filename, const QDBusIntrospection::Interfaces &interfaces) +void QDBusXmlToCpp::writeProxy(const QString &filename, + const QDBusIntrospection::Interfaces &interfaces) { // open the file QString headerName = header(filename); @@ -484,81 +576,74 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf includeGuard = u"QDBUSXML2CPP_PROXY"_s; } - hs << "#ifndef " << includeGuard << Qt::endl - << "#define " << includeGuard << Qt::endl - << Qt::endl; + hs << "#ifndef " << includeGuard << "\n" + "#define " << includeGuard << "\n\n"; // include our stuff: - hs << "#include <QtCore/QObject>" << Qt::endl + hs << "#include <QtCore/QObject>\n" << includeList; #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) - hs << "#include <QtDBus/QtDBus>" << Qt::endl; + hs << "#include <QtDBus/QtDBus>\n"; #else - hs << "#include <QtDBus/QDBusAbstractInterface>" << Qt::endl; - hs << "#include <QtDBus/QDBusPendingReply>" << Qt::endl; + hs << "#include <QtDBus/QDBusAbstractInterface>\n" + "#include <QtDBus/QDBusPendingReply>\n"; #endif for (const QString &include : std::as_const(includes)) { - hs << "#include \"" << include << "\"" << Qt::endl; + hs << "#include \"" << include << "\"\n"; if (headerName.isEmpty()) - cs << "#include \"" << include << "\"" << Qt::endl; + cs << "#include \"" << include << "\"\n"; } for (const QString &include : std::as_const(globalIncludes)) { - hs << "#include <" << include << ">" << Qt::endl; + hs << "#include <" << include << ">\n"; if (headerName.isEmpty()) - cs << "#include <" << include << ">" << Qt::endl; + cs << "#include <" << include << ">\n"; } - hs << Qt::endl; + hs << "\n"; if (cppName != headerName) { if (!headerName.isEmpty() && headerName != "-"_L1) - cs << "#include \"" << headerName << "\"" << Qt::endl << Qt::endl; + cs << "#include \"" << headerName << "\"\n\n"; } for (const QDBusIntrospection::Interface *interface : interfaces) { QString className = classNameForInterface(interface->name, Proxy); // comment: - hs << "/*" << Qt::endl - << " * Proxy class for interface " << interface->name << Qt::endl - << " */" << Qt::endl; - cs << "/*" << Qt::endl - << " * Implementation of interface class " << className << Qt::endl - << " */" << Qt::endl - << Qt::endl; + hs << "/*\n" + " * Proxy class for interface " << interface->name << "\n" + " */\n"; + cs << "/*\n" + " * Implementation of interface class " << className << "\n" + " */\n\n"; // class header: - hs << "class " << className << ": public QDBusAbstractInterface" << Qt::endl - << "{" << Qt::endl - << " Q_OBJECT" << Qt::endl; + hs << "class " << className << ": public QDBusAbstractInterface\n" + "{\n" + " Q_OBJECT\n"; // the interface name - hs << "public:" << Qt::endl - << " static inline const char *staticInterfaceName()" << Qt::endl - << " { return \"" << interface->name << "\"; }" << Qt::endl - << Qt::endl; + hs << "public:\n" + " static inline const char *staticInterfaceName()\n" + " { return \"" << interface->name << "\"; }\n\n"; // constructors/destructors: - hs << "public:" << Qt::endl - << " " << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);" << Qt::endl - << Qt::endl - << " ~" << className << "();" << Qt::endl - << Qt::endl; - cs << className << "::" << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)" << Qt::endl - << " : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)" << Qt::endl - << "{" << Qt::endl - << "}" << Qt::endl - << Qt::endl - << className << "::~" << className << "()" << Qt::endl - << "{" << Qt::endl - << "}" << Qt::endl - << Qt::endl; + hs << "public:\n" + " " << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);\n\n" + " ~" << className << "();\n\n"; + cs << className << "::" << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)\n" + " : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)\n" + "{\n" + "}\n\n" + << className << "::~" << className << "()\n" + "{\n" + "}\n\n"; // properties: for (const QDBusIntrospection::Property &property : interface->properties) { - QByteArray type = qtTypeName(property.name, property.type, property.annotations); + QByteArray type = qtTypeName(property.location, property.type, property.annotations); QString getter = propertyGetter(property); QString setter = propertySetter(property); @@ -574,35 +659,36 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf // it's writeable hs << " WRITE " << setter; - hs << ")" << Qt::endl; + hs << ")\n"; // getter: if (property.access != QDBusIntrospection::Property::Write) { - hs << " inline " << type << " " << getter << "() const" << Qt::endl - << " { return qvariant_cast< " << type << " >(property(\"" - << property.name << "\")); }" << Qt::endl; + hs << " inline " << type << " " << getter << "() const\n" + " { return qvariant_cast< " << type << " >(property(\"" + << property.name << "\")); }\n"; } // setter: if (property.access != QDBusIntrospection::Property::Read) { - hs << " inline void " << setter << "(" << constRefArg(type) << "value)" << Qt::endl - << " { setProperty(\"" << property.name - << "\", QVariant::fromValue(value)); }" << Qt::endl; + hs << " inline void " << setter << "(" << constRefArg(type) << "value)\n" + " { setProperty(\"" << property.name + << "\", QVariant::fromValue(value)); }\n"; } - hs << Qt::endl; + hs << "\n"; } // methods: - hs << "public Q_SLOTS: // METHODS" << Qt::endl; + hs << "public Q_SLOTS: // METHODS\n"; for (const QDBusIntrospection::Method &method : interface->methods) { - bool isDeprecated = method.annotations.value("org.freedesktop.DBus.Deprecated"_L1) == "true"_L1; - bool isNoReply = - method.annotations.value(ANNOTATION_NO_WAIT ""_L1) == "true"_L1; + bool isDeprecated = method.annotations.value("org.freedesktop.DBus.Deprecated"_L1).value + == "true"_L1; + bool isNoReply = method.annotations.value(ANNOTATION_NO_WAIT ""_L1).value == "true"_L1; if (isNoReply && !method.outputArgs.isEmpty()) { - fprintf(stderr, "%s: warning while processing '%s': method %s in interface %s is marked 'no-reply' but has output arguments.\n", - PROGRAMNAME, qPrintable(inputFile), qPrintable(method.name), - qPrintable(interface->name)); + reporter.warning(method.location, + "method %s in interface %s is marked 'no-reply' but has output " + "arguments.\n", + qPrintable(method.name), qPrintable(interface->name)); continue; } @@ -617,8 +703,9 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf hs << "inline QDBusPendingReply<"; for (qsizetype i = 0; i < method.outputArgs.size(); ++i) hs << (i > 0 ? ", " : "") - << templateArg(qtTypeName(method.outputArgs.at(i).name, method.outputArgs.at(i).type, - method.annotations, i, "Out")); + << templateArg(qtTypeName(method.outputArgs.at(i).location, + method.outputArgs.at(i).type, method.annotations, + i, "Out")); hs << "> "; } @@ -627,75 +714,77 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf QStringList argNames = makeArgNames(method.inputArgs); writeArgList(hs, argNames, method.annotations, method.inputArgs); - hs << ")" << Qt::endl - << " {" << Qt::endl - << " QList<QVariant> argumentList;" << Qt::endl; + hs << ")\n" + " {\n" + " QList<QVariant> argumentList;\n"; if (!method.inputArgs.isEmpty()) { hs << " argumentList"; for (qsizetype argPos = 0; argPos < method.inputArgs.size(); ++argPos) hs << " << QVariant::fromValue(" << argNames.at(argPos) << ')'; - hs << ";" << Qt::endl; + hs << ";\n"; } if (isNoReply) hs << " callWithArgumentList(QDBus::NoBlock, " - << "QStringLiteral(\"" << method.name << "\"), argumentList);" << Qt::endl; + "QStringLiteral(\"" << method.name << "\"), argumentList);\n"; else hs << " return asyncCallWithArgumentList(QStringLiteral(\"" - << method.name << "\"), argumentList);" << Qt::endl; + << method.name << "\"), argumentList);\n"; // close the function: - hs << " }" << Qt::endl; + hs << " }\n"; if (method.outputArgs.size() > 1) { // generate the old-form QDBusReply methods with multiple incoming parameters hs << (isDeprecated ? " Q_DECL_DEPRECATED " : " ") << "inline QDBusReply<" - << templateArg(qtTypeName(method.outputArgs.first().name, method.outputArgs.first().type, - method.annotations, 0, "Out")) + << templateArg(qtTypeName(method.outputArgs.first().location, + method.outputArgs.first().type, method.annotations, 0, + "Out")) << "> "; hs << method.name << "("; QStringList argNames = makeArgNames(method.inputArgs, method.outputArgs); writeArgList(hs, argNames, method.annotations, method.inputArgs, method.outputArgs); - hs << ")" << Qt::endl - << " {" << Qt::endl - << " QList<QVariant> argumentList;" << Qt::endl; + hs << ")\n" + " {\n" + " QList<QVariant> argumentList;\n"; qsizetype argPos = 0; if (!method.inputArgs.isEmpty()) { hs << " argumentList"; for (argPos = 0; argPos < method.inputArgs.size(); ++argPos) hs << " << QVariant::fromValue(" << argNames.at(argPos) << ')'; - hs << ";" << Qt::endl; + hs << ";\n"; } hs << " QDBusMessage reply = callWithArgumentList(QDBus::Block, " - << "QStringLiteral(\"" << method.name << "\"), argumentList);" << Qt::endl; + "QStringLiteral(\"" << method.name << "\"), argumentList);\n"; argPos++; hs << " if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().size() == " - << method.outputArgs.size() << ") {" << Qt::endl; + << method.outputArgs.size() << ") {\n"; // yes, starting from 1 for (qsizetype i = 1; i < method.outputArgs.size(); ++i) hs << " " << argNames.at(argPos++) << " = qdbus_cast<" - << templateArg(qtTypeName(method.outputArgs.at(i).name, method.outputArgs.at(i).type, - method.annotations, i, "Out")) - << ">(reply.arguments().at(" << i << "));" << Qt::endl; - hs << " }" << Qt::endl - << " return reply;" << Qt::endl - << " }" << Qt::endl; + << templateArg(qtTypeName(method.outputArgs.at(i).location, + method.outputArgs.at(i).type, method.annotations, + i, "Out")) + << ">(reply.arguments().at(" << i << "));\n"; + hs << " }\n" + " return reply;\n" + " }\n"; } - hs << Qt::endl; + hs << "\n"; } - hs << "Q_SIGNALS: // SIGNALS" << Qt::endl; + hs << "Q_SIGNALS: // SIGNALS\n"; for (const QDBusIntrospection::Signal &signal : interface->signals_) { hs << " "; - if (signal.annotations.value("org.freedesktop.DBus.Deprecated"_L1) == "true"_L1) + if (signal.annotations.value("org.freedesktop.DBus.Deprecated"_L1).value == "true"_L1) hs << "Q_DECL_DEPRECATED "; hs << "void " << signal.name << "("; @@ -703,12 +792,11 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf QStringList argNames = makeArgNames(signal.outputArgs); writeSignalArgList(hs, argNames, signal.annotations, signal.outputArgs); - hs << ");" << Qt::endl; // finished for header + hs << ");\n"; // finished for header } // close the class: - hs << "};" << Qt::endl - << Qt::endl; + hs << "};\n\n"; } if (!skipNamespaces) { @@ -730,17 +818,17 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf // i parts matched // close last.arguments().size() - i namespaces: for (qsizetype j = i; j < last.size(); ++j) - hs << QString((last.size() - j - 1 + i) * 2, u' ') << "}" << Qt::endl; + hs << QString((last.size() - j - 1 + i) * 2, u' ') << "}\n"; // open current.arguments().size() - i namespaces for (qsizetype j = i; j < current.size(); ++j) - hs << QString(j * 2, u' ') << "namespace " << current.at(j) << " {" << Qt::endl; + hs << QString(j * 2, u' ') << "namespace " << current.at(j) << " {\n"; // add this class: if (!name.isEmpty()) { hs << QString(current.size() * 2, u' ') << "using " << name << " = ::" << classNameForInterface(it->constData()->name, Proxy) - << ";" << Qt::endl; + << ";\n"; } if (it == interfaces.constEnd()) @@ -751,12 +839,12 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf } // close the include guard - hs << "#endif" << Qt::endl; + hs << "#endif\n"; QString mocName = moc(filename); if (includeMocs && !mocName.isEmpty()) - cs << Qt::endl - << "#include \"" << mocName << "\"" << Qt::endl; + cs << "\n" + "#include \"" << mocName << "\"\n"; cs.flush(); hs.flush(); @@ -776,7 +864,8 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf } } -static void writeAdaptor(const QString &filename, const QDBusIntrospection::Interfaces &interfaces) +void QDBusXmlToCpp::writeAdaptor(const QString &filename, + const QDBusIntrospection::Interfaces &interfaces) { // open the file QString headerName = header(filename); @@ -803,47 +892,46 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte includeGuard = u"QDBUSXML2CPP_ADAPTOR"_s; } - hs << "#ifndef " << includeGuard << Qt::endl - << "#define " << includeGuard << Qt::endl - << Qt::endl; + hs << "#ifndef " << includeGuard << "\n" + "#define " << includeGuard << "\n\n"; // include our stuff: - hs << "#include <QtCore/QObject>" << Qt::endl; + hs << "#include <QtCore/QObject>\n"; if (cppName == headerName) - hs << "#include <QtCore/QMetaObject>" << Qt::endl - << "#include <QtCore/QVariant>" << Qt::endl; + hs << "#include <QtCore/QMetaObject>\n" + "#include <QtCore/QVariant>\n"; #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) - hs << "#include <QtDBus/QtDBus>" << Qt::endl; + hs << "#include <QtDBus/QtDBus>\n"; #else - hs << "#include <QtDBus/QDBusAbstractAdaptor>" << Qt::endl; - hs << "#include <QtDBus/QDBusObjectPath>" << Qt::endl; + hs << "#include <QtDBus/QDBusAbstractAdaptor>\n" + "#include <QtDBus/QDBusObjectPath>\n"; #endif for (const QString &include : std::as_const(includes)) { - hs << "#include \"" << include << "\"" << Qt::endl; + hs << "#include \"" << include << "\"\n"; if (headerName.isEmpty()) - cs << "#include \"" << include << "\"" << Qt::endl; + cs << "#include \"" << include << "\"\n"; } for (const QString &include : std::as_const(globalIncludes)) { - hs << "#include <" << include << ">" << Qt::endl; + hs << "#include <" << include << ">\n"; if (headerName.isEmpty()) - cs << "#include <" << include << ">" << Qt::endl; + cs << "#include <" << include << ">\n"; } if (cppName != headerName) { if (!headerName.isEmpty() && headerName != "-"_L1) - cs << "#include \"" << headerName << "\"" << Qt::endl; + cs << "#include \"" << headerName << "\"\n"; - cs << "#include <QtCore/QMetaObject>" << Qt::endl + cs << "#include <QtCore/QMetaObject>\n" << includeList - << Qt::endl; + << "\n"; hs << forwardDeclarations; } else { hs << includeList; } - hs << Qt::endl; + hs << "\n"; QString parent = parentClassName; if (parentClassName.isEmpty()) @@ -853,49 +941,44 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte QString className = classNameForInterface(interface->name, Adaptor); // comment: - hs << "/*" << Qt::endl - << " * Adaptor class for interface " << interface->name << Qt::endl - << " */" << Qt::endl; - cs << "/*" << Qt::endl - << " * Implementation of adaptor class " << className << Qt::endl - << " */" << Qt::endl - << Qt::endl; + hs << "/*\n" + " * Adaptor class for interface " << interface->name << "\n" + " */\n"; + cs << "/*\n" + " * Implementation of adaptor class " << className << "\n" + " */\n\n"; // class header: - hs << "class " << className << ": public QDBusAbstractAdaptor" << Qt::endl - << "{" << Qt::endl - << " Q_OBJECT" << Qt::endl - << " Q_CLASSINFO(\"D-Bus Interface\", \"" << interface->name << "\")" << Qt::endl - << " Q_CLASSINFO(\"D-Bus Introspection\", \"\"" << Qt::endl + hs << "class " << className << ": public QDBusAbstractAdaptor\n" + "{\n" + " Q_OBJECT\n" + " Q_CLASSINFO(\"D-Bus Interface\", \"" << interface->name << "\")\n" + " Q_CLASSINFO(\"D-Bus Introspection\", \"\"\n" << stringify(interface->introspection) - << " \"\")" << Qt::endl - << "public:" << Qt::endl - << " " << className << "(" << parent << " *parent);" << Qt::endl - << " virtual ~" << className << "();" << Qt::endl - << Qt::endl; + << " \"\")\n" + "public:\n" + " " << className << "(" << parent << " *parent);\n" + " ~" << className << "() override;\n\n"; if (!parentClassName.isEmpty()) - hs << " inline " << parent << " *parent() const" << Qt::endl - << " { return static_cast<" << parent << " *>(QObject::parent()); }" << Qt::endl - << Qt::endl; + hs << " inline " << parent << " *parent() const\n" + " { return static_cast<" << parent << " *>(QObject::parent()); }\n\n"; // constructor/destructor - cs << className << "::" << className << "(" << parent << " *parent)" << Qt::endl - << " : QDBusAbstractAdaptor(parent)" << Qt::endl - << "{" << Qt::endl - << " // constructor" << Qt::endl - << " setAutoRelaySignals(true);" << Qt::endl - << "}" << Qt::endl - << Qt::endl - << className << "::~" << className << "()" << Qt::endl - << "{" << Qt::endl - << " // destructor" << Qt::endl - << "}" << Qt::endl - << Qt::endl; - - hs << "public: // PROPERTIES" << Qt::endl; + cs << className << "::" << className << "(" << parent << " *parent)\n" + " : QDBusAbstractAdaptor(parent)\n" + "{\n" + " // constructor\n" + " setAutoRelaySignals(true);\n" + "}\n\n" + << className << "::~" << className << "()\n" + "{\n" + " // destructor\n" + "}\n\n"; + + hs << "public: // PROPERTIES\n"; for (const QDBusIntrospection::Property &property : interface->properties) { - QByteArray type = qtTypeName(property.name, property.type, property.annotations); + QByteArray type = qtTypeName(property.location, property.type, property.annotations); QString constRefType = constRefArg(type); QString getter = propertyGetter(property); QString setter = propertySetter(property); @@ -905,44 +988,43 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte hs << " READ " << getter; if (property.access != QDBusIntrospection::Property::Read) hs << " WRITE " << setter; - hs << ")" << Qt::endl; + hs << ")\n"; // getter: if (property.access != QDBusIntrospection::Property::Write) { - hs << " " << type << " " << getter << "() const;" << Qt::endl; + hs << " " << type << " " << getter << "() const;\n"; cs << type << " " - << className << "::" << getter << "() const" << Qt::endl - << "{" << Qt::endl - << " // get the value of property " << property.name << Qt::endl - << " return qvariant_cast< " << type <<" >(parent()->property(\"" << property.name << "\"));" << Qt::endl - << "}" << Qt::endl - << Qt::endl; + << className << "::" << getter << "() const\n" + "{\n" + " // get the value of property " << property.name << "\n" + " return qvariant_cast< " << type <<" >(parent()->property(\"" << property.name << "\"));\n" + "}\n\n"; } // setter if (property.access != QDBusIntrospection::Property::Read) { - hs << " void " << setter << "(" << constRefType << "value);" << Qt::endl; - cs << "void " << className << "::" << setter << "(" << constRefType << "value)" << Qt::endl - << "{" << Qt::endl - << " // set the value of property " << property.name << Qt::endl - << " parent()->setProperty(\"" << property.name << "\", QVariant::fromValue(value"; + hs << " void " << setter << "(" << constRefType << "value);\n"; + cs << "void " << className << "::" << setter << "(" << constRefType << "value)\n" + "{\n" + " // set the value of property " << property.name << "\n" + " parent()->setProperty(\"" << property.name << "\", QVariant::fromValue(value"; if (constRefType.contains("QDBusVariant"_L1)) cs << ".variant()"; - cs << "));" << Qt::endl - << "}" << Qt::endl - << Qt::endl; + cs << "));\n" + "}\n\n"; } - hs << Qt::endl; + hs << "\n"; } - hs << "public Q_SLOTS: // METHODS" << Qt::endl; + hs << "public Q_SLOTS: // METHODS\n"; for (const QDBusIntrospection::Method &method : interface->methods) { - bool isNoReply = - method.annotations.value(ANNOTATION_NO_WAIT ""_L1) == "true"_L1; + bool isNoReply = method.annotations.value(ANNOTATION_NO_WAIT ""_L1).value == "true"_L1; if (isNoReply && !method.outputArgs.isEmpty()) { - fprintf(stderr, "%s: warning while processing '%s': method %s in interface %s is marked 'no-reply' but has output arguments.\n", - PROGRAMNAME, qPrintable(inputFile), qPrintable(method.name), qPrintable(interface->name)); + reporter.warning(method.location, + "method %s in interface %s is marked 'no-reply' but has output " + "arguments.\n", + qPrintable(method.name), qPrintable(interface->name)); continue; } @@ -955,8 +1037,9 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte hs << "void "; cs << "void "; } else { - returnType = qtTypeName(method.outputArgs.first().name, method.outputArgs.first().type, - method.annotations, 0, "Out"); + returnType = + qtTypeName(method.outputArgs.first().location, + method.outputArgs.first().type, method.annotations, 0, "Out"); hs << returnType << " "; cs << returnType << " "; } @@ -969,10 +1052,10 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte writeArgList(hs, argNames, method.annotations, method.inputArgs, method.outputArgs); writeArgList(cs, argNames, method.annotations, method.inputArgs, method.outputArgs); - hs << ");" << Qt::endl; // finished for header - cs << ")" << Qt::endl - << "{" << Qt::endl - << " // handle method call " << interface->name << "." << methodName(method) << Qt::endl; + hs << ");\n"; // finished for header + cs << ")\n" + "{\n" + " // handle method call " << interface->name << "." << methodName(method) << "\n"; // make the call bool usingInvokeMethod = false; @@ -984,27 +1067,27 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte // we are using QMetaObject::invokeMethod if (!returnType.isEmpty()) cs << " " << returnType << " " << argNames.at(method.inputArgs.size()) - << ";" << Qt::endl; + << ";\n"; static const char invoke[] = " QMetaObject::invokeMethod(parent(), \""; cs << invoke << name << "\""; if (!method.outputArgs.isEmpty()) cs << ", Q_RETURN_ARG(" - << qtTypeName(method.outputArgs.at(0).name, method.outputArgs.at(0).type, method.annotations, - 0, "Out") + << qtTypeName(method.outputArgs.at(0).location, method.outputArgs.at(0).type, + method.annotations, 0, "Out") << ", " << argNames.at(method.inputArgs.size()) << ")"; for (qsizetype i = 0; i < method.inputArgs.size(); ++i) cs << ", Q_ARG(" - << qtTypeName(method.inputArgs.at(i).name, method.inputArgs.at(i).type, method.annotations, - i, "In") + << qtTypeName(method.inputArgs.at(i).location, method.inputArgs.at(i).type, + method.annotations, i, "In") << ", " << argNames.at(i) << ")"; - cs << ");" << Qt::endl; + cs << ");\n"; if (!returnType.isEmpty()) - cs << " return " << argNames.at(method.inputArgs.size()) << ";" << Qt::endl; + cs << " return " << argNames.at(method.inputArgs.size()) << ";\n"; } else { if (parentClassName.isEmpty()) cs << " //"; @@ -1032,34 +1115,32 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte first = false; } - cs << ");" << Qt::endl; + cs << ");\n"; } - cs << "}" << Qt::endl - << Qt::endl; + cs << "}\n\n"; } - hs << "Q_SIGNALS: // SIGNALS" << Qt::endl; + hs << "Q_SIGNALS: // SIGNALS\n"; for (const QDBusIntrospection::Signal &signal : interface->signals_) { hs << " void " << signal.name << "("; QStringList argNames = makeArgNames(signal.outputArgs); writeSignalArgList(hs, argNames, signal.annotations, signal.outputArgs); - hs << ");" << Qt::endl; // finished for header + hs << ");\n"; // finished for header } // close the class: - hs << "};" << Qt::endl - << Qt::endl; + hs << "};\n\n"; } // close the include guard - hs << "#endif" << Qt::endl; + hs << "#endif\n"; QString mocName = moc(filename); if (includeMocs && !mocName.isEmpty()) - cs << Qt::endl - << "#include \"" << mocName << "\"" << Qt::endl; + cs << "\n" + "#include \"" << mocName << "\"\n"; cs.flush(); hs.flush(); @@ -1079,12 +1160,8 @@ static void writeAdaptor(const QString &filename, const QDBusIntrospection::Inte } } -int main(int argc, char **argv) +int QDBusXmlToCpp::run(const QCoreApplication &app) { - QCoreApplication app(argc, argv); - QCoreApplication::setApplicationName(QStringLiteral(PROGRAMNAME)); - QCoreApplication::setApplicationVersion(QStringLiteral(PROGRAMVERSION)); - QCommandLineParser parser; parser.setApplicationDescription( "Produces the C++ code to implement the interfaces defined in the input file.\n\n" @@ -1097,57 +1174,59 @@ int main(int argc, char **argv) parser.addHelpOption(); parser.addVersionOption(); - parser.addPositionalArgument(QStringLiteral("xml-or-xml-file"), QStringLiteral("XML file to use.")); - parser.addPositionalArgument(QStringLiteral("interfaces"), QStringLiteral("List of interfaces to use."), - QStringLiteral("[interfaces ...]")); + parser.addPositionalArgument(u"xml-or-xml-file"_s, u"XML file to use."_s); + parser.addPositionalArgument(u"interfaces"_s, u"List of interfaces to use."_s, + u"[interfaces ...]"_s); - QCommandLineOption adapterCodeOption(QStringList() << QStringLiteral("a") << QStringLiteral("adaptor"), - QStringLiteral("Write the adaptor code to <filename>"), QStringLiteral("filename")); + QCommandLineOption adapterCodeOption(QStringList{u"a"_s, u"adaptor"_s}, + u"Write the adaptor code to <filename>"_s, u"filename"_s); parser.addOption(adapterCodeOption); - QCommandLineOption classNameOption(QStringList() << QStringLiteral("c") << QStringLiteral("classname"), - QStringLiteral("Use <classname> as the class name for the generated classes"), QStringLiteral("classname")); + QCommandLineOption classNameOption(QStringList{u"c"_s, u"classname"_s}, + u"Use <classname> as the class name for the generated classes. " + u"This option can only be used when processing a single interface."_s, + u"classname"_s); parser.addOption(classNameOption); - QCommandLineOption addIncludeOption(QStringList() << QStringLiteral("i") << QStringLiteral("include"), - QStringLiteral("Add #include \"filename\" to the output"), QStringLiteral("filename")); + QCommandLineOption addIncludeOption(QStringList{u"i"_s, u"include"_s}, + u"Add #include \"filename\" to the output"_s, u"filename"_s); parser.addOption(addIncludeOption); - QCommandLineOption addGlobalIncludeOption(QStringList() << QStringLiteral("I") << QStringLiteral("global-include"), - QStringLiteral("Add #include <filename> to the output"), QStringLiteral("filename")); + QCommandLineOption addGlobalIncludeOption(QStringList{u"I"_s, u"global-include"_s}, + u"Add #include <filename> to the output"_s, u"filename"_s); parser.addOption(addGlobalIncludeOption); - QCommandLineOption adapterParentOption(QStringLiteral("l"), - QStringLiteral("When generating an adaptor, use <classname> as the parent class"), QStringLiteral("classname")); + QCommandLineOption adapterParentOption(u"l"_s, + u"When generating an adaptor, use <classname> as the parent class"_s, u"classname"_s); parser.addOption(adapterParentOption); - QCommandLineOption mocIncludeOption(QStringList() << QStringLiteral("m") << QStringLiteral("moc"), - QStringLiteral("Generate #include \"filename.moc\" statements in the .cpp files")); + QCommandLineOption mocIncludeOption(QStringList{u"m"_s, u"moc"_s}, + u"Generate #include \"filename.moc\" statements in the .cpp files"_s); parser.addOption(mocIncludeOption); - QCommandLineOption noNamespaceOption(QStringList() << QStringLiteral("N") << QStringLiteral("no-namespaces"), - QStringLiteral("Don't use namespaces")); + QCommandLineOption noNamespaceOption(QStringList{u"N"_s, u"no-namespaces"_s}, + u"Don't use namespaces"_s); parser.addOption(noNamespaceOption); - QCommandLineOption proxyCodeOption(QStringList() << QStringLiteral("p") << QStringLiteral("proxy"), - QStringLiteral("Write the proxy code to <filename>"), QStringLiteral("filename")); + QCommandLineOption proxyCodeOption(QStringList{u"p"_s, u"proxy"_s}, + u"Write the proxy code to <filename>"_s, u"filename"_s); parser.addOption(proxyCodeOption); - QCommandLineOption verboseOption(QStringList() << QStringLiteral("V") << QStringLiteral("verbose"), - QStringLiteral("Be verbose.")); + QCommandLineOption verboseOption(QStringList{u"V"_s, u"verbose"_s}, + u"Be verbose."_s); parser.addOption(verboseOption); parser.process(app); - adaptorFile = parser.value(adapterCodeOption); + QString adaptorFile = parser.value(adapterCodeOption); globalClassName = parser.value(classNameOption); includes = parser.values(addIncludeOption); globalIncludes = parser.values(addGlobalIncludeOption); parentClassName = parser.value(adapterParentOption); includeMocs = parser.isSet(mocIncludeOption); skipNamespaces = parser.isSet(noNamespaceOption); - proxyFile = parser.value(proxyCodeOption); - verbose = parser.isSet(verboseOption); + QString proxyFile = parser.value(proxyCodeOption); + bool verbose = parser.isSet(verboseOption); wantedInterfaces = parser.positionalArguments(); if (!wantedInterfaces.isEmpty()) { @@ -1161,11 +1240,16 @@ int main(int argc, char **argv) } if (verbose) - QLoggingCategory::setFilterRules(QStringLiteral("dbus.parser.debug=true")); + QLoggingCategory::setFilterRules(u"dbus.parser.debug=true"_s); QDBusIntrospection::Interfaces interfaces = readInput(); cleanInterfaces(interfaces); + if (!globalClassName.isEmpty() && interfaces.count() != 1) { + qCritical("Option -c/--classname can only be used with a single interface.\n"); + return 1; + } + QStringList args = app.arguments(); args.removeFirst(); commandLine = PROGRAMNAME " "_L1 + args.join(u' '); @@ -1179,3 +1263,11 @@ int main(int argc, char **argv) return 0; } +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + QCoreApplication::setApplicationName(QStringLiteral(PROGRAMNAME)); + QCoreApplication::setApplicationVersion(QStringLiteral(PROGRAMVERSION)); + + return QDBusXmlToCpp().run(app); +} |