📄 qdbusxml2cpp.cpp
字号:
} while (true); } // close the include guard hs << "#endif" << endl; QString mocName = moc(filename); if (includeMocs && !mocName.isEmpty()) cs << endl << "#include \"" << mocName << "\"" << endl; cs.flush(); hs.flush(); QFile file; openFile(headerName, file); file.write(headerData); if (headerName == cppName) { file.write(cppData); } else { QFile cppFile; openFile(cppName, cppFile); cppFile.write(cppData); }}static void writeAdaptor(const QString &filename, const QDBusIntrospection::Interfaces &interfaces){ // open the file QString headerName = header(filename); QByteArray headerData; QTextStream hs(&headerData); QString cppName = cpp(filename); QByteArray cppData; QTextStream cs(&cppData); // write the headers writeHeader(hs, false); if (cppName != headerName) writeHeader(cs, true); // include guards: QString includeGuard; if (!headerName.isEmpty() && headerName != QLatin1String("-")) { includeGuard = headerName.toUpper().replace(QLatin1Char('.'), QLatin1Char('_')); int pos = includeGuard.lastIndexOf(QLatin1Char('/')); if (pos != -1) includeGuard = includeGuard.mid(pos + 1); } else { includeGuard = QLatin1String("QDBUSXML2CPP_ADAPTOR"); } includeGuard = QString(QLatin1String("%1_%2")) .arg(includeGuard) .arg(QDateTime::currentDateTime().toTime_t()); hs << "#ifndef " << includeGuard << endl << "#define " << includeGuard << endl << endl; // include our stuff: hs << "#include <QtCore/QObject>" << endl; if (cppName == headerName) hs << "#include <QtCore/QMetaObject>" << endl << "#include <QtCore/QVariant>" << endl; hs << "#include <QtDBus/QtDBus>" << endl; foreach (QString include, includes) { hs << "#include \"" << include << "\"" << endl; if (headerName.isEmpty()) cs << "#include \"" << include << "\"" << endl; } if (cppName != headerName) { if (!headerName.isEmpty() && headerName != QLatin1String("-")) cs << "#include \"" << headerName << "\"" << endl; cs << "#include <QtCore/QMetaObject>" << endl << includeList << endl; hs << forwardDeclarations; } else { hs << includeList; } hs << endl; QString parent = parentClassName; if (parentClassName.isEmpty()) parent = QLatin1String("QObject"); foreach (const QDBusIntrospection::Interface *interface, interfaces) { QString className = classNameForInterface(interface->name, Adaptor); // comment: hs << "/*" << endl << " * Adaptor class for interface " << interface->name << endl << " */" << endl; cs << "/*" << endl << " * Implementation of adaptor class " << className << endl << " */" << endl << endl; // class header: hs << "class " << className << ": public QDBusAbstractAdaptor" << endl << "{" << endl << " Q_OBJECT" << endl << " Q_CLASSINFO(\"D-Bus Interface\", \"" << interface->name << "\")" << endl << " Q_CLASSINFO(\"D-Bus Introspection\", \"\"" << endl << stringify(interface->introspection) << " \"\")" << endl << "public:" << endl << " " << className << "(" << parent << " *parent);" << endl << " virtual ~" << className << "();" << endl << endl; if (!parentClassName.isEmpty()) hs << " inline " << parent << " *parent() const" << endl << " { return static_cast<" << parent << " *>(QObject::parent()); }" << endl << endl; // constructor/destructor cs << className << "::" << className << "(" << parent << " *parent)" << endl << " : QDBusAbstractAdaptor(parent)" << endl << "{" << endl << " // constructor" << endl << " setAutoRelaySignals(true);" << endl << "}" << endl << endl << className << "::~" << className << "()" << endl << "{" << endl << " // destructor" << endl << "}" << endl << endl; hs << "public: // PROPERTIES" << endl; foreach (const QDBusIntrospection::Property &property, interface->properties) { QByteArray type = qtTypeName(property.type, property.annotations); QString constRefType = constRefArg(type); QString getter = propertyGetter(property); QString setter = propertySetter(property); hs << " Q_PROPERTY(" << type << " " << property.name; if (property.access != QDBusIntrospection::Property::Write) hs << " READ " << getter; if (property.access != QDBusIntrospection::Property::Read) hs << " WRITE " << setter; hs << ")" << endl; // getter: if (property.access != QDBusIntrospection::Property::Write) { hs << " " << type << " " << getter << "() const;" << endl; cs << type << " " << className << "::" << getter << "() const" << endl << "{" << endl << " // get the value of property " << property.name << endl << " return qvariant_cast< " << type <<" >(parent()->property(\"" << property.name << "\"));" << endl << "}" << endl << endl; } // setter if (property.access != QDBusIntrospection::Property::Read) { hs << " void " << setter << "(" << constRefType << "value);" << endl; cs << "void " << className << "::" << setter << "(" << constRefType << "value)" << endl << "{" << endl << " // set the value of property " << property.name << endl << " parent()->setProperty(\"" << property.name << "\", value);" << endl << "}" << endl << endl; } hs << endl; } hs << "public Q_SLOTS: // METHODS" << endl; foreach (const QDBusIntrospection::Method &method, interface->methods) { bool isNoReply = method.annotations.value(QLatin1String(ANNOTATION_NO_WAIT)) == QLatin1String("true"); if (isNoReply && !method.outputArgs.isEmpty()) { fprintf(stderr, "warning: method %s in interface %s is marked 'no-reply' but has output arguments.\n", qPrintable(method.name), qPrintable(interface->name)); continue; } hs << " "; if (method.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) == QLatin1String("true")) hs << "Q_DECL_DEPRECATED "; QByteArray returnType; if (isNoReply) { hs << "Q_NOREPLY void "; cs << "void "; } else if (method.outputArgs.isEmpty()) { hs << "void "; cs << "void "; } else { returnType = qtTypeName(method.outputArgs.first().type, method.annotations, 0, "Out"); hs << returnType << " "; cs << returnType << " "; } QString name = method.name; hs << name << "("; cs << className << "::" << name << "("; QStringList argNames = makeArgNames(method.inputArgs, method.outputArgs); writeArgList(hs, argNames, method.annotations, method.inputArgs, method.outputArgs); writeArgList(cs, argNames, method.annotations, method.inputArgs, method.outputArgs); hs << ");" << endl; // finished for header cs << ")" << endl << "{" << endl << " // handle method call " << interface->name << "." << method.name << endl; // make the call bool usingInvokeMethod = false; if (parentClassName.isEmpty() && method.inputArgs.count() <= 10 && method.outputArgs.count() <= 1) usingInvokeMethod = true; if (usingInvokeMethod) { // we are using QMetaObject::invokeMethod if (!returnType.isEmpty()) cs << " " << returnType << " " << argNames.at(method.inputArgs.count()) << ";" << endl; static const char invoke[] = " QMetaObject::invokeMethod(parent(), \""; cs << invoke << name << "\""; if (!method.outputArgs.isEmpty()) cs << ", Q_RETURN_ARG(" << qtTypeName(method.outputArgs.at(0).type, method.annotations, 0, "Out") << ", " << argNames.at(method.inputArgs.count()) << ")"; for (int i = 0; i < method.inputArgs.count(); ++i) cs << ", Q_ARG(" << qtTypeName(method.inputArgs.at(i).type, method.annotations, i, "In") << ", " << argNames.at(i) << ")"; cs << ");" << endl; if (!returnType.isEmpty()) cs << " return " << argNames.at(method.inputArgs.count()) << ";" << endl; } else { if (parentClassName.isEmpty()) cs << " //"; else cs << " "; if (!method.outputArgs.isEmpty()) cs << "return "; if (parentClassName.isEmpty()) cs << "static_cast<YourObjectType *>(parent())->"; else cs << "parent()->"; cs << name << "("; int argPos = 0; bool first = true; for (int i = 0; i < method.inputArgs.count(); ++i) { cs << (first ? "" : ", ") << argNames.at(argPos++); first = false; } ++argPos; // skip retval, if any for (int i = 1; i < method.outputArgs.count(); ++i) { cs << (first ? "" : ", ") << argNames.at(argPos++); first = false; } cs << ");" << endl; } cs << "}" << endl << endl; } hs << "Q_SIGNALS: // SIGNALS" << endl; foreach (const QDBusIntrospection::Signal &signal, interface->signals_) { hs << " "; if (signal.annotations.value(QLatin1String("org.freedesktop.DBus.Deprecated")) == QLatin1String("true")) hs << "Q_DECL_DEPRECATED "; hs << "void " << signal.name << "("; QStringList argNames = makeArgNames(signal.outputArgs); writeArgList(hs, argNames, signal.annotations, signal.outputArgs); hs << ");" << endl; // finished for header } // close the class: hs << "};" << endl << endl; } // close the include guard hs << "#endif" << endl; QString mocName = moc(filename); if (includeMocs && !mocName.isEmpty()) cs << endl << "#include \"" << mocName << "\"" << endl; cs.flush(); hs.flush(); QFile file; openFile(headerName, file); file.write(headerData); if (headerName == cppName) { file.write(cppData); } else { QFile cppFile; openFile(cppName, cppFile); cppFile.write(cppData); }}int main(int argc, char **argv){ QCoreApplication app(argc, argv); parseCmdLine(app.arguments()); QDBusIntrospection::Interfaces interfaces = readInput(); cleanInterfaces(interfaces); if (!proxyFile.isEmpty() || adaptorFile.isEmpty()) writeProxy(proxyFile, interfaces); if (!adaptorFile.isEmpty()) writeAdaptor(adaptorFile, interfaces); return 0;}/*! \page qdbusxml2cpp.html \title QtDBus XML compiler (qdbusxml2cpp) \keyword qdbusxml2cpp The QtDBus XML compiler is a tool that can be used to parse interface descriptions and produce static code representing those interfaces, which can then be used to make calls to remote objects or implement said interfaces. \c qdbusxml2dcpp has two modes of operation, that correspond to the two possible outputs it can produce: the interface (proxy) class or the adaptor class. The latter consists of both a C++ header and a source file, which are meant to be edited and adapted to your needs. The \c qdbusxml2dcpp tool is not meant to be run every time you compile your application. Instead, it's meant to be used when developing the code or when the interface changes. The adaptor classes generated by \c qdbusxml2cpp are just a skeleton that must be completed. It generates, by default, calls to slots with the same name on the object the adaptor is attached to. However, you may modify those slots or the property accessor functions to suit your needs.*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -