3 * Copyright (C) 2006 Trolltech AS. All rights reserved.
4 * Author: Thiago Macieira <thiago.macieira@trolltech.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #include <sys/types.h>
27 #include <QtCore/qbytearray.h>
28 #include <QtCore/qdatetime.h>
29 #include <QtCore/qfile.h>
30 #include <QtCore/qstring.h>
31 #include <QtCore/qstringlist.h>
32 #include <QtCore/qtextstream.h>
33 #include <QtCore/qset.h>
35 #include <dbus/qdbus.h>
36 #include "qdbusmetaobject_p.h"
37 #include "qdbusintrospection_p.h"
39 #define PROGRAMNAME "dbusidl2cpp"
40 #define PROGRAMVERSION "0.4"
41 #define PROGRAMCOPYRIGHT "Copyright (C) 2006 Trolltech AS. All rights reserved."
43 #define ANNOTATION_NO_WAIT "org.freedesktop.DBus.Method.NoReply"
45 static const char cmdlineOptions[] = "a:c:hmNp:vV";
46 static const char *globalClassName;
47 static const char *proxyFile;
48 static const char *adaptorFile;
49 static const char *inputFile;
50 static bool skipNamespaces;
52 static bool includeMocs;
53 static QStringList wantedInterfaces;
55 static const char help[] =
56 "Usage: " PROGRAMNAME " [options...] [idl-or-xml-file] [interfaces...]\n"
57 "Produces the C++ code to implement the interfaces defined in the input file.\n"
58 "If no options are given, the code is written to the standard output.\n"
61 " -a <filename> Write the adaptor code to <filename>\n"
62 " -c <classname> Use <classname> as the class name for the generated classes\n"
63 " -h Show this information\n"
64 " -m Generate #include \"filename.moc\" statements in the .cpp files\n"
65 " -N Don't use namespaces\n"
66 " -p <filename> Write the proxy code to <filename>\n"
68 " -V Show the program version and quit.\n"
70 "If the file name given to the options -a and -p does not end in .cpp or .h, the\n"
71 "program will automatically append the suffixes and produce both files.\n";
73 static const char includeList[] =
74 "#include <QtCore/QByteArray>\n"
75 "#include <QtCore/QList>\n"
76 "#include <QtCore/QMap>\n"
77 "#include <QtCore/QString>\n"
78 "#include <QtCore/QStringList>\n"
79 "#include <QtCore/QVariant>\n";
81 static const char forwardDeclarations[] =
83 "template<class T> class QList;\n"
84 "template<class Key, class Value> class QMap;\n"
86 "class QStringList;\n"
89 static void showHelp()
95 static void showVersion()
97 printf("%s version %s\n", PROGRAMNAME, PROGRAMVERSION);
98 printf("D-Bus binding tool for Qt\n");
102 static void parseCmdLine(int argc, char **argv)
106 while ((c = getopt(argc, argv, cmdlineOptions)) != -1)
110 adaptorFile = optarg;
114 globalClassName = optarg;
126 skipNamespaces = true;
148 inputFile = argv[optind++];
150 while (optind != argc)
151 wantedInterfaces << QString::fromLocal8Bit(argv[optind++]);
154 static QDBusIntrospection::Interfaces readInput()
156 QFile input(QFile::decodeName(inputFile));
157 if (inputFile && QLatin1String("-") != inputFile)
158 input.open(QIODevice::ReadOnly);
160 input.open(stdin, QIODevice::ReadOnly);
162 QByteArray data = input.readAll();
164 // check if the input is already XML
165 data = data.trimmed();
166 if (data.startsWith("<!DOCTYPE ") || data.startsWith("<?xml") ||
167 data.startsWith("<node") || data.startsWith("<interface"))
169 return QDBusIntrospection::parseInterfaces(QString::fromUtf8(data));
171 fprintf(stderr, "Cannot process input. Stop.\n");
175 static void cleanInterfaces(QDBusIntrospection::Interfaces &interfaces)
177 if (!wantedInterfaces.isEmpty()) {
178 QDBusIntrospection::Interfaces::Iterator it = interfaces.begin();
179 while (it != interfaces.end())
180 if (!wantedInterfaces.contains(it.key()))
181 it = interfaces.erase(it);
187 // produce a header name from the file name
188 static QString header(const char *name)
190 if (!name || (name[0] == '-' && name[1] == '\0'))
193 QString retval = QFile::decodeName(name);
194 if (!retval.endsWith(".h") && !retval.endsWith(".cpp") && !retval.endsWith(".cc"))
200 // produce a cpp name from the file name
201 static QString cpp(const char *name)
203 if (!name || (name[0] == '-' && name[1] == '\0'))
206 QString retval = QFile::decodeName(name);
207 if (!retval.endsWith(".h") && !retval.endsWith(".cpp") && !retval.endsWith(".cc"))
208 retval.append(".cpp");
213 static QTextStream &writeHeader(QTextStream &ts, bool changesWillBeLost)
216 << " * This file was generated by " PROGRAMNAME " version " PROGRAMVERSION << endl
217 << " * when processing input file " << (inputFile ? inputFile : "<stdin>") << endl
219 << " * " PROGRAMNAME " is " PROGRAMCOPYRIGHT << endl
221 << " * This is an auto-generated file." << endl;
223 if (changesWillBeLost)
224 ts << " * Do not edit! All changes made to it will be lost." << endl;
232 enum ClassType { Proxy, Adaptor };
233 static QString classNameForInterface(const QString &interface, ClassType classType)
236 return QLatin1String(globalClassName);
238 QStringList parts = interface.split('.');
241 if (classType == Proxy)
242 foreach (QString part, parts) {
243 part[0] = part[0].toUpper();
247 retval = parts.last();
248 retval[0] = retval[0].toUpper();
251 if (classType == Proxy)
252 retval += "Interface";
259 static QByteArray qtTypeName(const QString &signature)
261 QVariant::Type type = QDBusUtil::signatureToType(signature);
262 if (type == QVariant::Invalid)
263 qFatal("Got unknown type `%s'", qPrintable(signature));
265 return QVariant::typeToName(type);
268 static QString nonConstRefArg(const QByteArray &arg)
270 return QLatin1String(arg + " &");
273 static QString templateArg(const QByteArray &arg)
275 if (!arg.endsWith('>'))
276 return QLatin1String(arg);
278 return QLatin1String(arg + ' ');
281 static QString constRefArg(const QByteArray &arg)
283 if (!arg.startsWith('Q'))
284 return QLatin1String(arg + ' ');
286 return QString("const %1 &").arg( QLatin1String(arg) );
289 static QStringList makeArgNames(const QDBusIntrospection::Arguments &inputArgs,
290 const QDBusIntrospection::Arguments &outputArgs =
291 QDBusIntrospection::Arguments())
294 for (int i = 0; i < inputArgs.count(); ++i) {
295 const QDBusIntrospection::Argument &arg = inputArgs.at(i);
296 QString name = arg.name;
298 name = QString("in%1").arg(i);
299 while (retval.contains(name))
303 for (int i = 0; i < outputArgs.count(); ++i) {
304 const QDBusIntrospection::Argument &arg = outputArgs.at(i);
305 QString name = arg.name;
307 name = QString("out%1").arg(i);
308 while (retval.contains(name))
315 static void writeArgList(QTextStream &ts, const QStringList &argNames,
316 const QDBusIntrospection::Arguments &inputArgs,
317 const QDBusIntrospection::Arguments &outputArgs = QDBusIntrospection::Arguments())
322 for (int i = 0; i < inputArgs.count(); ++i) {
323 const QDBusIntrospection::Argument &arg = inputArgs.at(i);
324 QString type = constRefArg(qtTypeName(arg.type));
328 ts << type << argNames.at(argPos++);
335 // yes, starting from 1
336 for (int i = 1; i < outputArgs.count(); ++i) {
337 const QDBusIntrospection::Argument &arg = outputArgs.at(i);
338 QString name = arg.name;
342 ts << nonConstRefArg(qtTypeName(arg.type)) << argNames.at(argPos++);
347 static QString propertyGetter(const QDBusIntrospection::Property &property)
349 QString getter = property.annotations.value("com.trolltech.QtDBus.propertyGetter");
350 if (getter.isEmpty()) {
351 getter = property.name;
352 getter[0] = getter[0].toLower();
357 static QString propertySetter(const QDBusIntrospection::Property &property)
359 QString setter = property.annotations.value("com.trolltech.QtDBus.propertySetter");
360 if (setter.isEmpty()) {
361 setter = "set" + property.name;
362 setter[3] = setter[3].toUpper();
367 static QString stringify(const QString &data)
371 for (i = 0; i < data.length(); ++i) {
373 for ( ; i < data.length() && data[i] != QChar('\n'); ++i)
383 static void writeProxy(const char *proxyFile, const QDBusIntrospection::Interfaces &interfaces)
386 QString headerName = header(proxyFile);
387 QFile file(headerName);
388 if (!headerName.isEmpty())
389 file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text);
391 file.open(stdout, QIODevice::WriteOnly | QIODevice::Text);
392 QTextStream hs(&file);
394 QString cppName = cpp(proxyFile);
396 QTextStream cs(&cppData);
399 writeHeader(hs, true);
402 QString includeGuard;
403 if (!headerName.isEmpty()) {
404 includeGuard = headerName.toUpper().replace(QChar('.'), QChar('_'));
405 int pos = includeGuard.lastIndexOf('/');
407 includeGuard = includeGuard.mid(pos + 1);
409 includeGuard = QString("QDBUSIDL2CPP_PROXY");
411 includeGuard = QString("%1_%2%3")
414 .arg(QDateTime::currentDateTime().toTime_t());
415 hs << "#ifndef " << includeGuard << endl
416 << "#define " << includeGuard << endl
419 // include our stuff:
420 hs << "#include <QtCore/QObject>" << endl
422 << "#include <dbus/qdbus.h>" << endl
425 if (cppName != headerName) {
426 writeHeader(cs, false);
427 cs << "#include \"" << headerName << "\"" << endl
431 foreach (const QDBusIntrospection::Interface *interface, interfaces) {
432 QString className = classNameForInterface(interface->name, Proxy);
436 << " * Proxy class for interface " << interface->name << endl
439 << " * Implementation of interface class " << className << endl
444 hs << "class " << className << ": public QDBusAbstractInterface" << endl
446 << " Q_OBJECT" << endl;
448 // the interface name
449 hs << "public:" << endl
450 << " static inline const char *staticInterfaceName()" << endl
451 << " { return \"" << interface->name << "\"; }" << endl
454 // constructors/destructors:
455 hs << "public:" << endl
456 << " explicit " << className << "(QDBusAbstractInterfacePrivate *p);" << endl
458 << " ~" << className << "();" << endl
460 cs << className << "::" << className << "(QDBusAbstractInterfacePrivate *p)" << endl
461 << " : QDBusAbstractInterface(p)" << endl
465 << className << "::~" << className << "()" << endl
471 foreach (const QDBusIntrospection::Property &property, interface->properties) {
472 QByteArray type = qtTypeName(property.type);
473 QString templateType = templateArg(type);
474 QString constRefType = constRefArg(type);
475 QString getter = propertyGetter(property);
476 QString setter = propertySetter(property);
478 hs << " Q_PROPERTY(" << type << " " << property.name;
481 if (property.access != QDBusIntrospection::Property::Write)
483 hs << " READ " << getter;
486 if (property.access != QDBusIntrospection::Property::Read)
488 hs << " WRITE " << setter;
493 if (property.access != QDBusIntrospection::Property::Write) {
494 hs << " inline " << type << " " << getter << "() const" << endl;
495 if (type != "QVariant")
496 hs << " { return qvariant_cast< " << type << " >(internalPropGet(\""
497 << property.name << "\")); }" << endl;
499 hs << " { return internalPropGet(\"" << property.name << "\"); }" << endl;
503 if (property.access != QDBusIntrospection::Property::Read) {
504 hs << " inline void " << setter << "(" << constRefArg(type) << "value)" << endl
505 << " { internalPropSet(\"" << property.name
506 << "\", qVariantFromValue(value)); }" << endl;
513 hs << "public Q_SLOTS: // METHODS" << endl;
514 foreach (const QDBusIntrospection::Method &method, interface->methods) {
515 bool isAsync = method.annotations.value(ANNOTATION_NO_WAIT) == "true";
516 if (isAsync && !method.outputArgs.isEmpty()) {
517 fprintf(stderr, "warning: method %s in interface %s is marked 'async' but has output arguments.\n",
518 qPrintable(method.name), qPrintable(interface->name));
524 if (method.annotations.value("org.freedesktop.DBus.Deprecated") == "true")
525 hs << "Q_DECL_DEPRECATED ";
528 hs << "Q_ASYNC void ";
529 else if (method.outputArgs.isEmpty())
530 hs << "QDBusReply<void> ";
532 hs << "QDBusReply<" << templateArg(qtTypeName(method.outputArgs.first().type)) << "> ";
535 hs << method.name << "(";
537 QStringList argNames = makeArgNames(method.inputArgs, method.outputArgs);
538 writeArgList(hs, argNames, method.inputArgs, method.outputArgs);
543 if (method.outputArgs.count() > 1)
544 hs << " QDBusMessage reply = call(QLatin1String(\"";
546 hs << " return call(QLatin1String(\"";
548 hs << " call(NoWaitForReply, QLatin1String(\"";
550 // rebuild the method input signature:
551 QString signature = QChar('.');
552 foreach (const QDBusIntrospection::Argument &arg, method.inputArgs)
553 signature += arg.type;
554 if (signature.length() == 1)
556 hs << method.name << signature << "\")";
559 for (int i = 0; i < method.inputArgs.count(); ++i)
560 hs << ", " << argNames.at(argPos++);
562 // close the QDBusIntrospection::call call
566 if (method.outputArgs.count() > 1) {
567 hs << " if (reply.type() == QDBusMessage::ReplyMessage) {" << endl;
569 // yes, starting from 1
570 for (int i = 1; i < method.outputArgs.count(); ++i)
571 hs << " " << argNames.at(argPos++) << " = qvariant_cast<"
572 << templateArg(qtTypeName(method.outputArgs.at(i).type))
573 << ">(reply.at(" << i << "));" << endl;
575 << " return reply;" << endl;
578 // close the function:
583 hs << "Q_SIGNALS: // SIGNALS" << endl;
584 foreach (const QDBusIntrospection::Signal &signal, interface->signals_) {
586 if (signal.annotations.value("org.freedesktop.DBus.Deprecated") == "true")
587 hs << "Q_DECL_DEPRECATED ";
589 hs << "void " << signal.name << "(";
591 QStringList argNames = makeArgNames(signal.outputArgs);
592 writeArgList(hs, argNames, signal.outputArgs);
594 hs << ");" << endl; // finished for header
602 if (!skipNamespaces) {
604 QDBusIntrospection::Interfaces::ConstIterator it = interfaces.constBegin();
609 if (it != interfaces.constEnd()) {
610 current = it->constData()->name.split('.');
611 name = current.takeLast();
615 while (i < current.count() && i < last.count() && current.at(i) == last.at(i))
619 // close last.count() - i namespaces:
620 for (int j = i; j < last.count(); ++j)
621 hs << QString((last.count() - j - 1 + i) * 2, ' ') << "}" << endl;
623 // open current.count() - i namespaces
624 for (int j = i; j < current.count(); ++j)
625 hs << QString(j * 2, ' ') << "namespace " << current.at(j) << " {" << endl;
628 if (!name.isEmpty()) {
629 hs << QString(current.count() * 2, ' ')
630 << "typedef ::" << classNameForInterface(it->constData()->name, Proxy)
631 << " " << name << ";" << endl;
634 if (it == interfaces.constEnd())
641 // close the include guard
642 hs << "#endif" << endl;
646 << "#include \"" << proxyFile << ".moc\"" << endl;
650 if (headerName == cppName)
655 f.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text);
660 static void writeAdaptor(const char *adaptorFile, const QDBusIntrospection::Interfaces &interfaces)
663 QString headerName = header(adaptorFile);
664 QFile file(headerName);
665 if (!headerName.isEmpty())
666 file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text);
668 file.open(stdout, QIODevice::WriteOnly | QIODevice::Text);
669 QTextStream hs(&file);
671 QString cppName = cpp(adaptorFile);
673 QTextStream cs(&cppData);
676 writeHeader(hs, false);
679 QString includeGuard;
680 if (!headerName.isEmpty()) {
681 includeGuard = headerName.toUpper().replace(QChar('.'), QChar('_'));
682 int pos = includeGuard.lastIndexOf('/');
684 includeGuard = includeGuard.mid(pos + 1);
686 includeGuard = QString("QDBUSIDL2CPP_ADAPTOR");
688 includeGuard = QString("%1_%2%3")
691 .arg(QDateTime::currentDateTime().toTime_t());
692 hs << "#ifndef " << includeGuard << endl
693 << "#define " << includeGuard << endl
696 // include our stuff:
697 hs << "#include <QtCore/QObject>" << endl;
698 if (cppName == headerName)
699 hs << "#include <QtCore/QMetaObject>" << endl
700 << "#include <QtCore/QVariant>" << endl;
701 hs << "#include <dbus/qdbus.h>" << endl;
703 if (cppName != headerName) {
704 writeHeader(cs, false);
705 cs << "#include \"" << headerName << "\"" << endl
706 << "#include <QtCore/QMetaObject>" << endl
709 hs << forwardDeclarations;
716 foreach (const QDBusIntrospection::Interface *interface, interfaces) {
717 QString className = classNameForInterface(interface->name, Adaptor);
721 << " * Adaptor class for interface " << interface->name << endl
724 << " * Implementation of adaptor class " << className << endl
729 hs << "class " << className << ": public QDBusAbstractAdaptor" << endl
731 << " Q_OBJECT" << endl
732 << " Q_CLASSINFO(\"D-Bus Interface\", \"" << interface->name << "\")" << endl
733 << " Q_CLASSINFO(\"D-Bus Introspection\", \"\"" << endl
734 << stringify(interface->introspection)
737 << " " << className << "(QObject *parent);" << endl
738 << " virtual ~" << className << "();" << endl
741 // constructor/destructor
742 cs << className << "::" << className << "(QObject *parent)" << endl
743 << " : QDBusAbstractAdaptor(parent)" << endl
745 << " // constructor" << endl
746 << " setAutoRelaySignals(true);" << endl
749 << className << "::~" << className << "()" << endl
751 << " // destructor" << endl
755 hs << "public: // PROPERTIES" << endl;
756 foreach (const QDBusIntrospection::Property &property, interface->properties) {
757 QByteArray type = qtTypeName(property.type);
758 QString constRefType = constRefArg(type);
759 QString getter = propertyGetter(property);
760 QString setter = propertySetter(property);
762 hs << " Q_PROPERTY(" << type << " " << property.name;
763 if (property.access != QDBusIntrospection::Property::Write)
764 hs << " READ " << getter;
765 if (property.access != QDBusIntrospection::Property::Read)
766 hs << " WRITE " << setter;
770 if (property.access != QDBusIntrospection::Property::Write) {
771 hs << " " << type << " " << getter << "() const;" << endl;
773 << className << "::" << getter << "() const" << endl
775 << " // get the value of property " << property.name << endl
776 << " return qvariant_cast< " << type <<" >(parent()->property(\"" << property.name << "\"));" << endl
782 if (property.access != QDBusIntrospection::Property::Read) {
783 hs << " void " << setter << "(" << constRefType << "value);" << endl;
784 cs << "void " << className << "::" << setter << "(" << constRefType << "value)" << endl
786 << " // set the value of property " << property.name << endl
787 << " parent()->setProperty(\"" << property.name << "\", value);" << endl
795 hs << "public Q_SLOTS: // METHODS" << endl;
796 foreach (const QDBusIntrospection::Method &method, interface->methods) {
797 bool isAsync = method.annotations.value(ANNOTATION_NO_WAIT) == "true";
798 if (isAsync && !method.outputArgs.isEmpty()) {
799 fprintf(stderr, "warning: method %s in interface %s is marked 'async' but has output arguments.\n",
800 qPrintable(method.name), qPrintable(interface->name));
805 if (method.annotations.value("org.freedesktop.DBus.Deprecated") == "true")
806 hs << "Q_DECL_DEPRECATED ";
808 QByteArray returnType;
810 hs << "Q_ASYNC void ";
812 } else if (method.outputArgs.isEmpty()) {
816 returnType = qtTypeName(method.outputArgs.first().type);
817 hs << returnType << " ";
818 cs << returnType << " ";
821 QString name = method.name;
823 cs << className << "::" << name << "(";
825 QStringList argNames = makeArgNames(method.inputArgs, method.outputArgs);
826 writeArgList(hs, argNames, method.inputArgs, method.outputArgs);
827 writeArgList(cs, argNames, method.inputArgs, method.outputArgs);
829 hs << ");" << endl; // finished for header
832 << " // handle method call " << interface->name << "." << method.name << endl;
834 // create the return type
835 int j = method.inputArgs.count();
836 if (!returnType.isEmpty())
837 cs << " " << returnType << " " << argNames.at(j) << ";" << endl;
840 if (method.inputArgs.count() <= 10 && method.outputArgs.count() <= 1) {
841 // we can use QMetaObject::invokeMethod
842 static const char invoke[] = " QMetaObject::invokeMethod(parent(), \"";
843 cs << invoke << name << "\"";
845 if (!method.outputArgs.isEmpty())
846 cs << ", Q_RETURN_ARG("
847 << qtTypeName(method.outputArgs.at(0).type)
849 << argNames.at(method.inputArgs.count())
852 for (int i = 0; i < method.inputArgs.count(); ++i)
854 << qtTypeName(method.inputArgs.at(i).type)
863 << " // Alternative:" << endl
865 if (!method.outputArgs.isEmpty())
866 cs << argNames.at(method.inputArgs.count()) << " = ";
867 cs << "static_cast<YourObjectType *>(parent())->" << name << "(";
871 for (int i = 0; i < method.inputArgs.count(); ++i) {
872 cs << (first ? "" : ", ") << argNames.at(argPos++);
875 ++argPos; // skip retval, if any
876 for (int i = 1; i < method.outputArgs.count(); ++i) {
877 cs << (first ? "" : ", ") << argNames.at(argPos++);
882 if (!method.outputArgs.isEmpty())
883 cs << " return " << argNames.at(method.inputArgs.count()) << ";" << endl;
888 hs << "Q_SIGNALS: // SIGNALS" << endl;
889 foreach (const QDBusIntrospection::Signal &signal, interface->signals_) {
891 if (signal.annotations.value("org.freedesktop.DBus.Deprecated") == "true")
892 hs << "Q_DECL_DEPRECATED ";
894 hs << "void " << signal.name << "(";
896 QStringList argNames = makeArgNames(signal.outputArgs);
897 writeArgList(hs, argNames, signal.outputArgs);
899 hs << ");" << endl; // finished for header
907 // close the include guard
908 hs << "#endif" << endl;
912 << "#include \"" << adaptorFile << ".moc\"" << endl;
916 if (headerName == cppName)
921 f.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text);
926 int main(int argc, char **argv)
928 parseCmdLine(argc, argv);
930 QDBusIntrospection::Interfaces interfaces = readInput();
931 cleanInterfaces(interfaces);
933 writeProxy(proxyFile, interfaces);
936 writeAdaptor(adaptorFile, interfaces);
942 \page dbusidl2cpp.html
943 \title QtDBus IDL compiler (dbusidl2cpp)
945 The QtDBus IDL compiler is a tool that can be used to parse interface descriptions and produce
946 static code representing those interfaces, which can then be used to make calls to remote
947 objects or implement said interfaces.
949 \c dbusidl2dcpp has two modes of operation, that correspond to the two possible outputs it can
950 produce: the interface (proxy) class or the adaptor class.The latter consists of both a C++
951 header and a source file, which are meant to be edited and adapted to your needs.
953 The \c dbusidl2dcpp tool is not meant to be run every time you compile your
954 application. Instead, it's meant to be used when developing the code or when the interface
957 The adaptor classes generated by \c dbusidl2cpp are just a skeleton that must be completed. It
958 generates, by default, calls to slots with the same name on the object the adaptor is attached
959 to. However, you may modify those slots or the property accessor functions to suit your needs.