Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qdbusxml2cpp.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4#include <qbytearray.h>
6#include <qcoreapplication.h>
7#include <qdebug.h>
8#include <qfile.h>
9#include <qfileinfo.h>
10#include <qloggingcategory.h>
11#include <qstring.h>
12#include <qstringlist.h>
13#include <qtextstream.h>
14#include <qset.h>
15
16#include <qdbusmetatype.h>
17#include <private/qdbusintrospection_p.h>
18
19#include <stdio.h>
20#include <stdlib.h>
21
22#define PROGRAMNAME "qdbusxml2cpp"
23#define PROGRAMVERSION "0.8"
24#define PROGRAMCOPYRIGHT QT_COPYRIGHT
25
26#define ANNOTATION_NO_WAIT "org.freedesktop.DBus.Method.NoReply"
27
28using namespace Qt::StringLiterals;
29
30class QDBusXmlToCpp final
31{
32public:
33 int run(const QCoreApplication &app);
34
35private:
36 class DiagnosticsReporter final : public QDBusIntrospection::DiagnosticsReporter
37 {
38 public:
39 void setFileName(const QString &fileName) { m_fileName = fileName; }
40 bool hadErrors() const { return m_hadErrors; }
41
42 void warning(const QDBusIntrospection::SourceLocation &location, const char *msg,
43 ...) override;
44 void error(const QDBusIntrospection::SourceLocation &location, const char *msg,
45 ...) override;
46 void note(const QDBusIntrospection::SourceLocation &location, const char *msg, ...)
48
49 private:
50 QString m_fileName;
51 bool m_hadErrors = false;
52
53 void report(const QDBusIntrospection::SourceLocation &location, const char *msg, va_list ap,
54 const char *severity);
55 };
56
57 enum ClassType { Proxy, Adaptor };
58
59 void writeAdaptor(const QString &filename, const QDBusIntrospection::Interfaces &interfaces);
60 void writeProxy(const QString &filename, const QDBusIntrospection::Interfaces &interfaces);
61
63 void cleanInterfaces(QDBusIntrospection::Interfaces &interfaces);
64 QTextStream &writeHeader(QTextStream &ts, bool changesWillBeLost);
65 QString classNameForInterface(const QString &interface, ClassType classType);
67 const QString &signature,
68 const QDBusIntrospection::Annotations &annotations,
69 qsizetype paramId = -1, const char *direction = "Out");
70 void
71 writeArgList(QTextStream &ts, const QStringList &argNames,
72 const QDBusIntrospection::Annotations &annotations,
73 const QDBusIntrospection::Arguments &inputArgs,
75 void writeSignalArgList(QTextStream &ts, const QStringList &argNames,
76 const QDBusIntrospection::Annotations &annotations,
77 const QDBusIntrospection::Arguments &outputArgs);
78 QString propertyGetter(const QDBusIntrospection::Property &property);
79 QString propertySetter(const QDBusIntrospection::Property &property);
80
81 QString globalClassName;
82 QString parentClassName;
83 QString inputFile;
84 bool skipNamespaces = false;
85 bool includeMocs = false;
86 QString commandLine;
87 QStringList includes;
88 QStringList globalIncludes;
89 QStringList wantedInterfaces;
90
91 DiagnosticsReporter reporter;
92};
93
94static const char includeList[] =
95 "#include <QtCore/QByteArray>\n"
96 "#include <QtCore/QList>\n"
97 "#include <QtCore/QMap>\n"
98 "#include <QtCore/QString>\n"
99 "#include <QtCore/QStringList>\n"
100 "#include <QtCore/QVariant>\n";
101
102static const char forwardDeclarations[] =
103 "#include <QtCore/qcontainerfwd.h>\n";
104
105void QDBusXmlToCpp::DiagnosticsReporter::warning(const QDBusIntrospection::SourceLocation &location,
106 const char *msg, ...)
107{
108 va_list ap;
109 va_start(ap, msg);
110 report(location, msg, ap, "warning");
111 va_end(ap);
112}
113
114void QDBusXmlToCpp::DiagnosticsReporter::error(const QDBusIntrospection::SourceLocation &location,
115 const char *msg, ...)
116{
117 va_list ap;
118 va_start(ap, msg);
119 report(location, msg, ap, "error");
120 va_end(ap);
121 m_hadErrors = true;
122}
123
124void QDBusXmlToCpp::DiagnosticsReporter::note(const QDBusIntrospection::SourceLocation &location,
125 const char *msg, ...)
126{
127 va_list ap;
128 va_start(ap, msg);
129 report(location, msg, ap, "note");
130 va_end(ap);
131 m_hadErrors = true;
132}
133
134void QDBusXmlToCpp::DiagnosticsReporter::report(const QDBusIntrospection::SourceLocation &location,
135 const char *msg, va_list ap, const char *severity)
136{
137 fprintf(stderr, "%s:%lld:%lld: %s: ", qPrintable(m_fileName),
138 (long long int)location.lineNumber, (long long int)location.columnNumber + 1, severity);
139 vfprintf(stderr, msg, ap);
140}
141
142QDBusIntrospection::Interfaces QDBusXmlToCpp::readInput()
143{
144 QFile input(inputFile);
145 if (inputFile.isEmpty() || inputFile == "-"_L1) {
146 reporter.setFileName("<standard input>"_L1);
147 if (!input.open(stdin, QIODevice::ReadOnly)) {
148 fprintf(stderr, PROGRAMNAME ": could not open standard input: %s\n",
149 qPrintable(input.errorString()));
150 exit(1);
151 }
152 } else {
153 reporter.setFileName(inputFile);
154 if (!input.open(QIODevice::ReadOnly)) {
155 fprintf(stderr, PROGRAMNAME ": could not open input file '%s': %s\n",
156 qPrintable(inputFile), qPrintable(input.errorString()));
157 exit(1);
158 }
159 }
160
161 QByteArray data = input.readAll();
162 auto interfaces = QDBusIntrospection::parseInterfaces(QString::fromUtf8(data), &reporter);
163 if (reporter.hadErrors())
164 exit(1);
165
166 return interfaces;
167}
168
169void QDBusXmlToCpp::cleanInterfaces(QDBusIntrospection::Interfaces &interfaces)
170{
171 if (!wantedInterfaces.isEmpty()) {
173 while (it != interfaces.end())
174 if (!wantedInterfaces.contains(it.key()))
175 it = interfaces.erase(it);
176 else
177 ++it;
178 }
179}
180
182{
183 const QLatin1StringView candidates[] = {
184 "h"_L1,
185 "cpp"_L1,
186 "cc"_L1
187 };
188
189 for (auto candidate : candidates)
190 if (suffix == candidate)
191 return true;
192
193 return false;
194}
195
196// produce a header name from the file name
198{
199 QStringList parts = name.split(u':');
200 QString retval = parts.front();
201
202 if (retval.isEmpty() || retval == "-"_L1)
203 return retval;
204
205 QFileInfo header{retval};
206 if (!isSupportedSuffix(header.suffix()))
207 retval.append(".h"_L1);
208
209 return retval;
210}
211
212// produce a cpp name from the file name
213static QString cpp(const QString &name)
214{
215 QStringList parts = name.split(u':');
216 QString retval = parts.back();
217
218 if (retval.isEmpty() || retval == "-"_L1)
219 return retval;
220
221 QFileInfo source{retval};
222 if (!isSupportedSuffix(source.suffix()))
223 retval.append(".cpp"_L1);
224
225 return retval;
226}
227
228// produce a moc name from the file name
229static QString moc(const QString &name)
230{
231 QString retval;
232 const QStringList fileNames = name.split(u':');
233
234 if (fileNames.size() == 1) {
235 QFileInfo fi{fileNames.front()};
236 if (isSupportedSuffix(fi.suffix())) {
237 // Generates a file that contains the header and the implementation: include "filename.moc"
238 retval += fi.completeBaseName();
239 retval += ".moc"_L1;
240 } else {
241 // Separate source and header files are generated: include "moc_filename.cpp"
242 retval += "moc_"_L1;
243 retval += fi.fileName();
244 retval += ".cpp"_L1;
245 }
246 } else {
247 QString headerName = fileNames.front();
248 QString sourceName = fileNames.back();
249
250 if (sourceName.isEmpty() || sourceName == "-"_L1) {
251 // If only a header is generated, don't include anything
252 } else if (headerName.isEmpty() || headerName == "-"_L1) {
253 // If only source file is generated: include "moc_sourcename.cpp"
254 QFileInfo source{sourceName};
255
256 retval += "moc_"_L1;
257 retval += source.completeBaseName();
258 retval += ".cpp"_L1;
259
260 fprintf(stderr, "warning: no header name is provided, assuming it to be \"%s\"\n",
261 qPrintable(source.completeBaseName() + ".h"_L1));
262 } else {
263 // Both source and header generated: include "moc_headername.cpp"
264 QFileInfo header{headerName};
265
266 retval += "moc_"_L1;
267 retval += header.completeBaseName();
268 retval += ".cpp"_L1;
269 }
270 }
271
272 return retval;
273}
274
275QTextStream &QDBusXmlToCpp::writeHeader(QTextStream &ts, bool changesWillBeLost)
276{
277 ts << "/*\n"
278 " * This file was generated by " PROGRAMNAME " version " PROGRAMVERSION "\n"
279 " * Source file was " << QFileInfo(inputFile).fileName() << "\n"
280 " *\n"
281 " * " PROGRAMNAME " is " PROGRAMCOPYRIGHT "\n"
282 " *\n"
283 " * This is an auto-generated file.\n";
284
285 if (changesWillBeLost)
286 ts << " * Do not edit! All changes made to it will be lost.\n";
287 else
288 ts << " * This file may have been hand-edited. Look for HAND-EDIT comments\n"
289 " * before re-generating it.\n";
290
291 ts << " */\n\n";
292
293 return ts;
294}
295
296QString QDBusXmlToCpp::classNameForInterface(const QString &interface,
297 QDBusXmlToCpp::ClassType classType)
298{
299 if (!globalClassName.isEmpty())
300 return globalClassName;
301
302 const auto parts = QStringView{interface}.split(u'.');
303
304 QString retval;
305 if (classType == Proxy) {
306 for (const auto &part : parts) {
307 retval += part[0].toUpper();
308 retval += part.mid(1);
309 }
310 } else {
311 retval += parts.last()[0].toUpper() + parts.last().mid(1);
312 }
313
314 if (classType == Proxy)
315 retval += "Interface"_L1;
316 else
317 retval += "Adaptor"_L1;
318
319 return retval;
320}
321
322QByteArray QDBusXmlToCpp::qtTypeName(const QDBusIntrospection::SourceLocation &location,
323 const QString &signature,
324 const QDBusIntrospection::Annotations &annotations,
325 qsizetype paramId, const char *direction)
326{
329 QString annotationName = u"org.qtproject.QtDBus.QtTypeName"_s;
330 if (paramId >= 0)
331 annotationName += ".%1%2"_L1.arg(QLatin1StringView(direction)).arg(paramId);
332 auto annotation = annotations.value(annotationName);
333 QString qttype = annotation.value;
334 if (!qttype.isEmpty())
335 return std::move(qttype).toLatin1();
336
337 QString oldAnnotationName = u"com.trolltech.QtDBus.QtTypeName"_s;
338 if (paramId >= 0)
339 oldAnnotationName += ".%1%2"_L1.arg(QLatin1StringView(direction)).arg(paramId);
340 annotation = annotations.value(oldAnnotationName);
341 qttype = annotation.value;
342
343 if (qttype.isEmpty()) {
344 reporter.error(location, "unknown type `%s'\n", qPrintable(signature));
345 reporter.note(location, "you should add <annotation name=\"%s\" value=\"<type>\"/>\n",
346 qPrintable(annotationName));
347
348 exit(1);
349 }
350
351 reporter.warning(annotation.location, "deprecated annotation '%s' found\n",
352 qPrintable(oldAnnotationName));
353 reporter.note(annotation.location, "suggest updating to '%s'\n",
354 qPrintable(annotationName));
355 return std::move(qttype).toLatin1();
356 }
357
358 return QMetaType(type).name();
359}
360
362{
363 return QLatin1StringView(arg) + " &"_L1;
364}
365
367{
368 if (!arg.endsWith('>'))
369 return QLatin1StringView(arg);
370
371 return QLatin1StringView(arg) + " "_L1;
372}
373
375{
376 if (!arg.startsWith('Q'))
377 return QLatin1StringView(arg) + " "_L1;
378 else
379 return "const %1 &"_L1.arg(QLatin1StringView(arg));
380}
381
383 const QDBusIntrospection::Arguments &outputArgs =
385{
386 QStringList retval;
387 const qsizetype numInputArgs = inputArgs.size();
388 const qsizetype numOutputArgs = outputArgs.size();
389 retval.reserve(numInputArgs + numOutputArgs);
390 for (qsizetype i = 0; i < numInputArgs; ++i) {
391 const QDBusIntrospection::Argument &arg = inputArgs.at(i);
392 QString name = arg.name;
393 if (name.isEmpty())
394 name = u"in%1"_s.arg(i);
395 else
396 name.replace(u'-', u'_');
397 while (retval.contains(name))
398 name += "_"_L1;
399 retval << name;
400 }
401 for (qsizetype i = 0; i < numOutputArgs; ++i) {
402 const QDBusIntrospection::Argument &arg = outputArgs.at(i);
403 QString name = arg.name;
404 if (name.isEmpty())
405 name = u"out%1"_s.arg(i);
406 else
407 name.replace(u'-', u'_');
408 while (retval.contains(name))
409 name += "_"_L1;
410 retval << name;
411 }
412 return retval;
413}
414
415void QDBusXmlToCpp::writeArgList(QTextStream &ts, const QStringList &argNames,
416 const QDBusIntrospection::Annotations &annotations,
417 const QDBusIntrospection::Arguments &inputArgs,
418 const QDBusIntrospection::Arguments &outputArgs)
419{
420 // input args:
421 bool first = true;
422 qsizetype argPos = 0;
423 for (qsizetype i = 0; i < inputArgs.size(); ++i) {
424 const QDBusIntrospection::Argument &arg = inputArgs.at(i);
425 QString type = constRefArg(qtTypeName(arg.location, arg.type, annotations, i, "In"));
426
427 if (!first)
428 ts << ", ";
429 ts << type << argNames.at(argPos++);
430 first = false;
431 }
432
433 argPos++;
434
435 // output args
436 // yes, starting from 1
437 for (qsizetype i = 1; i < outputArgs.size(); ++i) {
438 const QDBusIntrospection::Argument &arg = outputArgs.at(i);
439
440 if (!first)
441 ts << ", ";
442 ts << nonConstRefArg(qtTypeName(arg.location, arg.type, annotations, i, "Out"))
443 << argNames.at(argPos++);
444 first = false;
445 }
446}
447
448void QDBusXmlToCpp::writeSignalArgList(QTextStream &ts, const QStringList &argNames,
449 const QDBusIntrospection::Annotations &annotations,
450 const QDBusIntrospection::Arguments &outputArgs)
451{
452 bool first = true;
453 qsizetype argPos = 0;
454 for (qsizetype i = 0; i < outputArgs.size(); ++i) {
455 const QDBusIntrospection::Argument &arg = outputArgs.at(i);
456 QString type = constRefArg(qtTypeName(arg.location, arg.type, annotations, i, "Out"));
457
458 if (!first)
459 ts << ", ";
460 ts << type << argNames.at(argPos++);
461 first = false;
462 }
463}
464
465QString QDBusXmlToCpp::propertyGetter(const QDBusIntrospection::Property &property)
466{
467 auto annotation = property.annotations.value("org.qtproject.QtDBus.PropertyGetter"_L1);
468 if (!annotation.value.isEmpty())
469 return annotation.value;
470
471 annotation = property.annotations.value("com.trolltech.QtDBus.propertyGetter"_L1);
472 if (!annotation.value.isEmpty()) {
473 reporter.warning(annotation.location,
474 "deprecated annotation 'com.trolltech.QtDBus.propertyGetter' found\n");
475 reporter.note(annotation.location,
476 "suggest updating to 'org.qtproject.QtDBus.PropertyGetter'\n");
477 return annotation.value;
478 }
479
480 QString getter = property.name;
481 getter[0] = getter[0].toLower();
482 return getter;
483}
484
485QString QDBusXmlToCpp::propertySetter(const QDBusIntrospection::Property &property)
486{
487 auto annotation = property.annotations.value("org.qtproject.QtDBus.PropertySetter"_L1);
488 if (!annotation.value.isEmpty())
489 return annotation.value;
490
491 annotation = property.annotations.value("com.trolltech.QtDBus.propertySetter"_L1);
492 if (!annotation.value.isEmpty()) {
493 reporter.warning(annotation.location,
494 "deprecated annotation 'com.trolltech.QtDBus.propertySetter' found\n");
495 reporter.note(annotation.location,
496 "suggest updating to 'org.qtproject.QtDBus.PropertySetter'\n");
497 return annotation.value;
498 }
499
500 QString setter = "set"_L1 + property.name;
501 setter[3] = setter[3].toUpper();
502 return setter;
503}
504
506{
507 QString name = method.annotations.value(u"org.qtproject.QtDBus.MethodName"_s).value;
508 if (!name.isEmpty())
509 return name;
510
511 return method.name;
512}
513
515{
516 QString retval;
517 qsizetype i;
518 for (i = 0; i < data.size(); ++i) {
519 retval += u'\"';
520 for ( ; i < data.size() && data[i] != u'\n' && data[i] != u'\r'; ++i)
521 if (data[i] == u'\"')
522 retval += "\\\""_L1;
523 else
524 retval += data[i];
525 if (i+1 < data.size() && data[i] == u'\r' && data[i+1] == u'\n')
526 i++;
527 retval += "\\n\"\n"_L1;
528 }
529 return retval;
530}
531
532static bool openFile(const QString &fileName, QFile &file)
533{
534 if (fileName.isEmpty())
535 return false;
536
537 bool isOk = false;
538 if (fileName == "-"_L1) {
540 } else {
543 }
544
545 if (!isOk)
546 fprintf(stderr, "%s: Unable to open '%s': %s\n",
548 return isOk;
549}
550
551void QDBusXmlToCpp::writeProxy(const QString &filename,
552 const QDBusIntrospection::Interfaces &interfaces)
553{
554 // open the file
555 QString headerName = header(filename);
556 QByteArray headerData;
557 QTextStream hs(&headerData);
558
559 QString cppName = cpp(filename);
560 QByteArray cppData;
561 QTextStream cs(&cppData);
562
563 // write the header:
564 writeHeader(hs, true);
565 if (cppName != headerName)
566 writeHeader(cs, false);
567
568 // include guards:
570 if (!headerName.isEmpty() && headerName != "-"_L1) {
571 includeGuard = headerName.toUpper().replace(u'.', u'_');
573 if (pos != -1)
575 } else {
576 includeGuard = u"QDBUSXML2CPP_PROXY"_s;
577 }
578
579 hs << "#ifndef " << includeGuard << "\n"
580 "#define " << includeGuard << "\n\n";
581
582 // include our stuff:
583 hs << "#include <QtCore/QObject>\n"
584 << includeList;
585#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
586 hs << "#include <QtDBus/QtDBus>\n";
587#else
588 hs << "#include <QtDBus/QDBusAbstractInterface>\n"
589 "#include <QtDBus/QDBusPendingReply>\n";
590#endif
591
592 for (const QString &include : std::as_const(includes)) {
593 hs << "#include \"" << include << "\"\n";
594 if (headerName.isEmpty())
595 cs << "#include \"" << include << "\"\n";
596 }
597
598 for (const QString &include : std::as_const(globalIncludes)) {
599 hs << "#include <" << include << ">\n";
600 if (headerName.isEmpty())
601 cs << "#include <" << include << ">\n";
602 }
603
604 hs << "\n";
605
606 if (cppName != headerName) {
607 if (!headerName.isEmpty() && headerName != "-"_L1)
608 cs << "#include \"" << headerName << "\"\n\n";
609 }
610
611 for (const QDBusIntrospection::Interface *interface : interfaces) {
612 QString className = classNameForInterface(interface->name, Proxy);
613
614 // comment:
615 hs << "/*\n"
616 " * Proxy class for interface " << interface->name << "\n"
617 " */\n";
618 cs << "/*\n"
619 " * Implementation of interface class " << className << "\n"
620 " */\n\n";
621
622 // class header:
623 hs << "class " << className << ": public QDBusAbstractInterface\n"
624 "{\n"
625 " Q_OBJECT\n";
626
627 // the interface name
628 hs << "public:\n"
629 " static inline const char *staticInterfaceName()\n"
630 " { return \"" << interface->name << "\"; }\n\n";
631
632 // constructors/destructors:
633 hs << "public:\n"
634 " " << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr);\n\n"
635 " ~" << className << "();\n\n";
636 cs << className << "::" << className << "(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent)\n"
637 " : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent)\n"
638 "{\n"
639 "}\n\n"
640 << className << "::~" << className << "()\n"
641 "{\n"
642 "}\n\n";
643
644 // properties:
646 QByteArray type = qtTypeName(property.location, property.type, property.annotations);
647 QString getter = propertyGetter(property);
648 QString setter = propertySetter(property);
649
650 hs << " Q_PROPERTY(" << type << " " << property.name;
651
652 // getter:
654 // it's readable
655 hs << " READ " << getter;
656
657 // setter
659 // it's writeable
660 hs << " WRITE " << setter;
661
662 hs << ")\n";
663
664 // getter:
666 hs << " inline " << type << " " << getter << "() const\n"
667 " { return qvariant_cast< " << type << " >(property(\""
668 << property.name << "\")); }\n";
669 }
670
671 // setter:
673 hs << " inline void " << setter << "(" << constRefArg(type) << "value)\n"
674 " { setProperty(\"" << property.name
675 << "\", QVariant::fromValue(value)); }\n";
676 }
677
678 hs << "\n";
679 }
680
681 // methods:
682 hs << "public Q_SLOTS: // METHODS\n";
684 bool isDeprecated = method.annotations.value("org.freedesktop.DBus.Deprecated"_L1).value
685 == "true"_L1;
686 bool isNoReply = method.annotations.value(ANNOTATION_NO_WAIT ""_L1).value == "true"_L1;
687 if (isNoReply && !method.outputArgs.isEmpty()) {
688 reporter.warning(method.location,
689 "method %s in interface %s is marked 'no-reply' but has output "
690 "arguments.\n",
691 qPrintable(method.name), qPrintable(interface->name));
692 continue;
693 }
694
695 if (isDeprecated)
696 hs << " Q_DECL_DEPRECATED ";
697 else
698 hs << " ";
699
700 if (isNoReply) {
701 hs << "Q_NOREPLY inline void ";
702 } else {
703 hs << "inline QDBusPendingReply<";
704 for (qsizetype i = 0; i < method.outputArgs.size(); ++i)
705 hs << (i > 0 ? ", " : "")
706 << templateArg(qtTypeName(method.outputArgs.at(i).location,
707 method.outputArgs.at(i).type, method.annotations,
708 i, "Out"));
709 hs << "> ";
710 }
711
712 hs << methodName(method) << "(";
713
714 QStringList argNames = makeArgNames(method.inputArgs);
715 writeArgList(hs, argNames, method.annotations, method.inputArgs);
716
717 hs << ")\n"
718 " {\n"
719 " QList<QVariant> argumentList;\n";
720
721 if (!method.inputArgs.isEmpty()) {
722 hs << " argumentList";
723 for (qsizetype argPos = 0; argPos < method.inputArgs.size(); ++argPos)
724 hs << " << QVariant::fromValue(" << argNames.at(argPos) << ')';
725 hs << ";\n";
726 }
727
728 if (isNoReply)
729 hs << " callWithArgumentList(QDBus::NoBlock, "
730 "QStringLiteral(\"" << method.name << "\"), argumentList);\n";
731 else
732 hs << " return asyncCallWithArgumentList(QStringLiteral(\""
733 << method.name << "\"), argumentList);\n";
734
735 // close the function:
736 hs << " }\n";
737
738 if (method.outputArgs.size() > 1) {
739 // generate the old-form QDBusReply methods with multiple incoming parameters
740 hs << (isDeprecated ? " Q_DECL_DEPRECATED " : " ") << "inline QDBusReply<"
741 << templateArg(qtTypeName(method.outputArgs.first().location,
742 method.outputArgs.first().type, method.annotations, 0,
743 "Out"))
744 << "> ";
745 hs << method.name << "(";
746
747 QStringList argNames = makeArgNames(method.inputArgs, method.outputArgs);
748 writeArgList(hs, argNames, method.annotations, method.inputArgs, method.outputArgs);
749
750 hs << ")\n"
751 " {\n"
752 " QList<QVariant> argumentList;\n";
753
754 qsizetype argPos = 0;
755 if (!method.inputArgs.isEmpty()) {
756 hs << " argumentList";
757 for (argPos = 0; argPos < method.inputArgs.size(); ++argPos)
758 hs << " << QVariant::fromValue(" << argNames.at(argPos) << ')';
759 hs << ";\n";
760 }
761
762 hs << " QDBusMessage reply = callWithArgumentList(QDBus::Block, "
763 "QStringLiteral(\"" << method.name << "\"), argumentList);\n";
764
765 argPos++;
766 hs << " if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().size() == "
767 << method.outputArgs.size() << ") {\n";
768
769 // yes, starting from 1
770 for (qsizetype i = 1; i < method.outputArgs.size(); ++i)
771 hs << " " << argNames.at(argPos++) << " = qdbus_cast<"
772 << templateArg(qtTypeName(method.outputArgs.at(i).location,
773 method.outputArgs.at(i).type, method.annotations,
774 i, "Out"))
775 << ">(reply.arguments().at(" << i << "));\n";
776 hs << " }\n"
777 " return reply;\n"
778 " }\n";
779 }
780
781 hs << "\n";
782 }
783
784 hs << "Q_SIGNALS: // SIGNALS\n";
785 for (const QDBusIntrospection::Signal &signal : interface->signals_) {
786 hs << " ";
787 if (signal.annotations.value("org.freedesktop.DBus.Deprecated"_L1).value == "true"_L1)
788 hs << "Q_DECL_DEPRECATED ";
789
790 hs << "void " << signal.name << "(";
791
792 QStringList argNames = makeArgNames(signal.outputArgs);
793 writeSignalArgList(hs, argNames, signal.annotations, signal.outputArgs);
794
795 hs << ");\n"; // finished for header
796 }
797
798 // close the class:
799 hs << "};\n\n";
800 }
801
802 if (!skipNamespaces) {
803 QStringList last;
805 do
806 {
807 QStringList current;
809 if (it != interfaces.constEnd()) {
810 current = it->constData()->name.split(u'.');
811 name = current.takeLast();
812 }
813
814 qsizetype i = 0;
815 while (i < current.size() && i < last.size() && current.at(i) == last.at(i))
816 ++i;
817
818 // i parts matched
819 // close last.arguments().size() - i namespaces:
820 for (qsizetype j = i; j < last.size(); ++j)
821 hs << QString((last.size() - j - 1 + i) * 2, u' ') << "}\n";
822
823 // open current.arguments().size() - i namespaces
824 for (qsizetype j = i; j < current.size(); ++j)
825 hs << QString(j * 2, u' ') << "namespace " << current.at(j) << " {\n";
826
827 // add this class:
828 if (!name.isEmpty()) {
829 hs << QString(current.size() * 2, u' ')
830 << "using " << name << " = ::" << classNameForInterface(it->constData()->name, Proxy)
831 << ";\n";
832 }
833
834 if (it == interfaces.constEnd())
835 break;
836 ++it;
837 last = current;
838 } while (true);
839 }
840
841 // close the include guard
842 hs << "#endif\n";
843
844 QString mocName = moc(filename);
845 if (includeMocs && !mocName.isEmpty())
846 cs << "\n"
847 "#include \"" << mocName << "\"\n";
848
849 cs.flush();
850 hs.flush();
851
852 QFile file;
853 const bool headerOpen = openFile(headerName, file);
854 if (headerOpen)
855 file.write(headerData);
856
857 if (headerName == cppName) {
858 if (headerOpen)
859 file.write(cppData);
860 } else {
861 QFile cppFile;
862 if (openFile(cppName, cppFile))
863 cppFile.write(cppData);
864 }
865}
866
867void QDBusXmlToCpp::writeAdaptor(const QString &filename,
868 const QDBusIntrospection::Interfaces &interfaces)
869{
870 // open the file
871 QString headerName = header(filename);
872 QByteArray headerData;
873 QTextStream hs(&headerData);
874
875 QString cppName = cpp(filename);
876 QByteArray cppData;
877 QTextStream cs(&cppData);
878
879 // write the headers
880 writeHeader(hs, false);
881 if (cppName != headerName)
882 writeHeader(cs, true);
883
884 // include guards:
886 if (!headerName.isEmpty() && headerName != "-"_L1) {
887 includeGuard = headerName.toUpper().replace(u'.', u'_');
889 if (pos != -1)
891 } else {
892 includeGuard = u"QDBUSXML2CPP_ADAPTOR"_s;
893 }
894
895 hs << "#ifndef " << includeGuard << "\n"
896 "#define " << includeGuard << "\n\n";
897
898 // include our stuff:
899 hs << "#include <QtCore/QObject>\n";
900 if (cppName == headerName)
901 hs << "#include <QtCore/QMetaObject>\n"
902 "#include <QtCore/QVariant>\n";
903#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
904 hs << "#include <QtDBus/QtDBus>\n";
905#else
906 hs << "#include <QtDBus/QDBusAbstractAdaptor>\n"
907 "#include <QtDBus/QDBusObjectPath>\n";
908#endif
909
910 for (const QString &include : std::as_const(includes)) {
911 hs << "#include \"" << include << "\"\n";
912 if (headerName.isEmpty())
913 cs << "#include \"" << include << "\"\n";
914 }
915
916 for (const QString &include : std::as_const(globalIncludes)) {
917 hs << "#include <" << include << ">\n";
918 if (headerName.isEmpty())
919 cs << "#include <" << include << ">\n";
920 }
921
922 if (cppName != headerName) {
923 if (!headerName.isEmpty() && headerName != "-"_L1)
924 cs << "#include \"" << headerName << "\"\n";
925
926 cs << "#include <QtCore/QMetaObject>\n"
927 << includeList
928 << "\n";
930 } else {
931 hs << includeList;
932 }
933
934 hs << "\n";
935
936 QString parent = parentClassName;
937 if (parentClassName.isEmpty())
938 parent = u"QObject"_s;
939
940 for (const QDBusIntrospection::Interface *interface : interfaces) {
941 QString className = classNameForInterface(interface->name, Adaptor);
942
943 // comment:
944 hs << "/*\n"
945 " * Adaptor class for interface " << interface->name << "\n"
946 " */\n";
947 cs << "/*\n"
948 " * Implementation of adaptor class " << className << "\n"
949 " */\n\n";
950
951 // class header:
952 hs << "class " << className << ": public QDBusAbstractAdaptor\n"
953 "{\n"
954 " Q_OBJECT\n"
955 " Q_CLASSINFO(\"D-Bus Interface\", \"" << interface->name << "\")\n"
956 " Q_CLASSINFO(\"D-Bus Introspection\", \"\"\n"
957 << stringify(interface->introspection)
958 << " \"\")\n"
959 "public:\n"
960 " " << className << "(" << parent << " *parent);\n"
961 " ~" << className << "() override;\n\n";
962
963 if (!parentClassName.isEmpty())
964 hs << " inline " << parent << " *parent() const\n"
965 " { return static_cast<" << parent << " *>(QObject::parent()); }\n\n";
966
967 // constructor/destructor
968 cs << className << "::" << className << "(" << parent << " *parent)\n"
969 " : QDBusAbstractAdaptor(parent)\n"
970 "{\n"
971 " // constructor\n"
972 " setAutoRelaySignals(true);\n"
973 "}\n\n"
974 << className << "::~" << className << "()\n"
975 "{\n"
976 " // destructor\n"
977 "}\n\n";
978
979 hs << "public: // PROPERTIES\n";
981 QByteArray type = qtTypeName(property.location, property.type, property.annotations);
982 QString constRefType = constRefArg(type);
983 QString getter = propertyGetter(property);
984 QString setter = propertySetter(property);
985
986 hs << " Q_PROPERTY(" << type << " " << property.name;
988 hs << " READ " << getter;
990 hs << " WRITE " << setter;
991 hs << ")\n";
992
993 // getter:
995 hs << " " << type << " " << getter << "() const;\n";
996 cs << type << " "
997 << className << "::" << getter << "() const\n"
998 "{\n"
999 " // get the value of property " << property.name << "\n"
1000 " return qvariant_cast< " << type <<" >(parent()->property(\"" << property.name << "\"));\n"
1001 "}\n\n";
1002 }
1003
1004 // setter
1006 hs << " void " << setter << "(" << constRefType << "value);\n";
1007 cs << "void " << className << "::" << setter << "(" << constRefType << "value)\n"
1008 "{\n"
1009 " // set the value of property " << property.name << "\n"
1010 " parent()->setProperty(\"" << property.name << "\", QVariant::fromValue(value";
1011 if (constRefType.contains("QDBusVariant"_L1))
1012 cs << ".variant()";
1013 cs << "));\n"
1014 "}\n\n";
1015 }
1016
1017 hs << "\n";
1018 }
1019
1020 hs << "public Q_SLOTS: // METHODS\n";
1022 bool isNoReply = method.annotations.value(ANNOTATION_NO_WAIT ""_L1).value == "true"_L1;
1023 if (isNoReply && !method.outputArgs.isEmpty()) {
1024 reporter.warning(method.location,
1025 "method %s in interface %s is marked 'no-reply' but has output "
1026 "arguments.\n",
1027 qPrintable(method.name), qPrintable(interface->name));
1028 continue;
1029 }
1030
1031 hs << " ";
1032 QByteArray returnType;
1033 if (isNoReply) {
1034 hs << "Q_NOREPLY void ";
1035 cs << "void ";
1036 } else if (method.outputArgs.isEmpty()) {
1037 hs << "void ";
1038 cs << "void ";
1039 } else {
1040 returnType =
1041 qtTypeName(method.outputArgs.first().location,
1042 method.outputArgs.first().type, method.annotations, 0, "Out");
1043 hs << returnType << " ";
1044 cs << returnType << " ";
1045 }
1046
1048 hs << name << "(";
1049 cs << className << "::" << name << "(";
1050
1051 QStringList argNames = makeArgNames(method.inputArgs, method.outputArgs);
1052 writeArgList(hs, argNames, method.annotations, method.inputArgs, method.outputArgs);
1053 writeArgList(cs, argNames, method.annotations, method.inputArgs, method.outputArgs);
1054
1055 hs << ");\n"; // finished for header
1056 cs << ")\n"
1057 "{\n"
1058 " // handle method call " << interface->name << "." << methodName(method) << "\n";
1059
1060 // make the call
1061 bool usingInvokeMethod = false;
1062 if (parentClassName.isEmpty() && method.inputArgs.size() <= 10
1063 && method.outputArgs.size() <= 1)
1064 usingInvokeMethod = true;
1065
1066 if (usingInvokeMethod) {
1067 // we are using QMetaObject::invokeMethod
1068 if (!returnType.isEmpty())
1069 cs << " " << returnType << " " << argNames.at(method.inputArgs.size())
1070 << ";\n";
1071
1072 static const char invoke[] = " QMetaObject::invokeMethod(parent(), \"";
1073 cs << invoke << name << "\"";
1074
1075 if (!method.outputArgs.isEmpty())
1076 cs << ", Q_RETURN_ARG("
1077 << qtTypeName(method.outputArgs.at(0).location, method.outputArgs.at(0).type,
1078 method.annotations, 0, "Out")
1079 << ", " << argNames.at(method.inputArgs.size()) << ")";
1080
1081 for (qsizetype i = 0; i < method.inputArgs.size(); ++i)
1082 cs << ", Q_ARG("
1083 << qtTypeName(method.inputArgs.at(i).location, method.inputArgs.at(i).type,
1084 method.annotations, i, "In")
1085 << ", " << argNames.at(i) << ")";
1086
1087 cs << ");\n";
1088
1089 if (!returnType.isEmpty())
1090 cs << " return " << argNames.at(method.inputArgs.size()) << ";\n";
1091 } else {
1092 if (parentClassName.isEmpty())
1093 cs << " //";
1094 else
1095 cs << " ";
1096
1097 if (!method.outputArgs.isEmpty())
1098 cs << "return ";
1099
1100 if (parentClassName.isEmpty())
1101 cs << "static_cast<YourObjectType *>(parent())->";
1102 else
1103 cs << "parent()->";
1104 cs << name << "(";
1105
1106 qsizetype argPos = 0;
1107 bool first = true;
1108 for (qsizetype i = 0; i < method.inputArgs.size(); ++i) {
1109 cs << (first ? "" : ", ") << argNames.at(argPos++);
1110 first = false;
1111 }
1112 ++argPos; // skip retval, if any
1113 for (qsizetype i = 1; i < method.outputArgs.size(); ++i) {
1114 cs << (first ? "" : ", ") << argNames.at(argPos++);
1115 first = false;
1116 }
1117
1118 cs << ");\n";
1119 }
1120 cs << "}\n\n";
1121 }
1122
1123 hs << "Q_SIGNALS: // SIGNALS\n";
1124 for (const QDBusIntrospection::Signal &signal : interface->signals_) {
1125 hs << " void " << signal.name << "(";
1126
1127 QStringList argNames = makeArgNames(signal.outputArgs);
1128 writeSignalArgList(hs, argNames, signal.annotations, signal.outputArgs);
1129
1130 hs << ");\n"; // finished for header
1131 }
1132
1133 // close the class:
1134 hs << "};\n\n";
1135 }
1136
1137 // close the include guard
1138 hs << "#endif\n";
1139
1140 QString mocName = moc(filename);
1141 if (includeMocs && !mocName.isEmpty())
1142 cs << "\n"
1143 "#include \"" << mocName << "\"\n";
1144
1145 cs.flush();
1146 hs.flush();
1147
1148 QFile file;
1149 const bool headerOpen = openFile(headerName, file);
1150 if (headerOpen)
1151 file.write(headerData);
1152
1153 if (headerName == cppName) {
1154 if (headerOpen)
1155 file.write(cppData);
1156 } else {
1157 QFile cppFile;
1158 if (openFile(cppName, cppFile))
1159 cppFile.write(cppData);
1160 }
1161}
1162
1164{
1165 QCommandLineParser parser;
1167 "Produces the C++ code to implement the interfaces defined in the input file.\n\n"
1168 "If the file name given to the options -a and -p does not end in .cpp or .h, the\n"
1169 "program will automatically append the suffixes and produce both files.\n"
1170 "You can also use a colon (:) to separate the header name from the source file\n"
1171 "name, as in '-a filename_p.h:filename.cpp'.\n\n"
1172 "If you pass a dash (-) as the argument to either -p or -a, the output is written\n"
1173 "to the standard output."_L1);
1174
1175 parser.addHelpOption();
1176 parser.addVersionOption();
1177 parser.addPositionalArgument(u"xml-or-xml-file"_s, u"XML file to use."_s);
1178 parser.addPositionalArgument(u"interfaces"_s, u"List of interfaces to use."_s,
1179 u"[interfaces ...]"_s);
1180
1181 QCommandLineOption adapterCodeOption(QStringList{u"a"_s, u"adaptor"_s},
1182 u"Write the adaptor code to <filename>"_s, u"filename"_s);
1183 parser.addOption(adapterCodeOption);
1184
1185 QCommandLineOption classNameOption(QStringList{u"c"_s, u"classname"_s},
1186 u"Use <classname> as the class name for the generated classes. "
1187 u"This option can only be used when processing a single interface."_s,
1188 u"classname"_s);
1189 parser.addOption(classNameOption);
1190
1191 QCommandLineOption addIncludeOption(QStringList{u"i"_s, u"include"_s},
1192 u"Add #include \"filename\" to the output"_s, u"filename"_s);
1193 parser.addOption(addIncludeOption);
1194
1195 QCommandLineOption addGlobalIncludeOption(QStringList{u"I"_s, u"global-include"_s},
1196 u"Add #include <filename> to the output"_s, u"filename"_s);
1197 parser.addOption(addGlobalIncludeOption);
1198
1199 QCommandLineOption adapterParentOption(u"l"_s,
1200 u"When generating an adaptor, use <classname> as the parent class"_s, u"classname"_s);
1201 parser.addOption(adapterParentOption);
1202
1203 QCommandLineOption mocIncludeOption(QStringList{u"m"_s, u"moc"_s},
1204 u"Generate #include \"filename.moc\" statements in the .cpp files"_s);
1205 parser.addOption(mocIncludeOption);
1206
1207 QCommandLineOption noNamespaceOption(QStringList{u"N"_s, u"no-namespaces"_s},
1208 u"Don't use namespaces"_s);
1209 parser.addOption(noNamespaceOption);
1210
1211 QCommandLineOption proxyCodeOption(QStringList{u"p"_s, u"proxy"_s},
1212 u"Write the proxy code to <filename>"_s, u"filename"_s);
1213 parser.addOption(proxyCodeOption);
1214
1215 QCommandLineOption verboseOption(QStringList{u"V"_s, u"verbose"_s},
1216 u"Be verbose."_s);
1217 parser.addOption(verboseOption);
1218
1219 parser.process(app);
1220
1221 QString adaptorFile = parser.value(adapterCodeOption);
1222 globalClassName = parser.value(classNameOption);
1223 includes = parser.values(addIncludeOption);
1224 globalIncludes = parser.values(addGlobalIncludeOption);
1225 parentClassName = parser.value(adapterParentOption);
1226 includeMocs = parser.isSet(mocIncludeOption);
1227 skipNamespaces = parser.isSet(noNamespaceOption);
1228 QString proxyFile = parser.value(proxyCodeOption);
1229 bool verbose = parser.isSet(verboseOption);
1230
1231 wantedInterfaces = parser.positionalArguments();
1232 if (!wantedInterfaces.isEmpty()) {
1233 inputFile = wantedInterfaces.takeFirst();
1234
1235 QFileInfo inputInfo(inputFile);
1236 if (!inputInfo.exists() || !inputInfo.isFile() || !inputInfo.isReadable()) {
1237 qCritical("Error: Input %s is not a file or cannot be accessed\n", qPrintable(inputFile));
1238 return 1;
1239 }
1240 }
1241
1242 if (verbose)
1243 QLoggingCategory::setFilterRules(u"dbus.parser.debug=true"_s);
1244
1245 QDBusIntrospection::Interfaces interfaces = readInput();
1246 cleanInterfaces(interfaces);
1247
1248 if (!globalClassName.isEmpty() && interfaces.count() != 1) {
1249 qCritical("Option -c/--classname can only be used with a single interface.\n");
1250 return 1;
1251 }
1252
1254 args.removeFirst();
1255 commandLine = PROGRAMNAME " "_L1 + args.join(u' ');
1256
1257 if (!proxyFile.isEmpty() || adaptorFile.isEmpty())
1258 writeProxy(proxyFile, interfaces);
1259
1260 if (!adaptorFile.isEmpty())
1261 writeAdaptor(adaptorFile, interfaces);
1262
1263 return 0;
1264}
1265
static JNINativeMethod methods[]
\inmodule QtCore
Definition qbytearray.h:57
char at(qsizetype i) const
Returns the byte at index position i in the byte array.
Definition qbytearray.h:600
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:107
The QCommandLineOption class defines a possible command-line option. \inmodule QtCore.
The QCommandLineParser class provides a means for handling the command line options.
QString value(const QString &name) const
Returns the option value found for the given option name optionName, or an empty string if not found.
void addPositionalArgument(const QString &name, const QString &description, const QString &syntax=QString())
Defines an additional argument to the application, for the benefit of the help text.
QStringList positionalArguments() const
Returns a list of positional arguments.
QStringList values(const QString &name) const
Returns a list of option values found for the given option name optionName, or an empty list if not f...
void setApplicationDescription(const QString &description)
Sets the application description shown by helpText().
bool addOption(const QCommandLineOption &commandLineOption)
Adds the option option to look for while parsing.
bool isSet(const QString &name) const
Checks whether the option name was passed to the application.
void process(const QStringList &arguments)
Processes the command line arguments.
QCommandLineOption addVersionOption()
Adds the {-v} / {–version} option, which displays the version string of the application.
QCommandLineOption addHelpOption()
Adds help options to the command-line parser.
\inmodule QtCore
static void setApplicationName(const QString &application)
static void setApplicationVersion(const QString &version)
static QStringList arguments()
static Interfaces parseInterfaces(const QString &xml, DiagnosticsReporter *reporter=nullptr)
Parses the XML document fragment (given by xml) containing several interfaces.
static QMetaType signatureToMetaType(const char *signature)
int run(const QCoreApplication &app)
QString fileName() const
\inmodule QtCore
Definition qfile.h:93
QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:904
void setFileName(const QString &name)
Sets the name of the file.
Definition qfile.cpp:302
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
QString errorString() const
Returns a human-readable description of the last device error that occurred.
QString arg(Args &&...args) const
qsizetype size() const noexcept
Definition qlist.h:397
void removeFirst() noexcept
Definition qlist.h:807
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
static void setFilterRules(const QString &rules)
Configures which categories and message types should be enabled through a set of rules.
T value(const Key &key, const T &defaultValue=T()) const
Definition qmap.h:357
iterator erase(const_iterator it)
Definition qmap.h:619
size_type count(const Key &key) const
Definition qmap.h:404
iterator begin()
Definition qmap.h:598
iterator end()
Definition qmap.h:602
const_iterator constBegin() const
Definition qmap.h:600
const_iterator constEnd() const
Definition qmap.h:604
\inmodule QtCore
Definition qmetatype.h:341
constexpr const char * name() const
Definition qmetatype.h:2680
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:78
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QByteArray toLatin1() const &
Definition qstring.h:630
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.h:296
QString & replace(qsizetype i, qsizetype len, QChar after)
Definition qstring.cpp:3824
QString mid(qsizetype position, qsizetype n=-1) const &
Definition qstring.cpp:5300
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6018
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
Definition qstring.cpp:8870
QString last(qsizetype n) const &
Definition qstring.h:392
QString toUpper() const &
Definition qstring.h:439
\inmodule QtCore
int main()
[0]
QSet< QString >::iterator it
auto signal
direction
QString includeGuard(const QString &filename)
Definition helpers.cpp:20
QMetaType signature()
void getter(const QUntypedPropertyData *d, void *value)
void setter(QUntypedPropertyData *d, const void *value)
#define Q_ATTRIBUTE_FORMAT_PRINTF(A, B)
static const QCssKnownValue properties[NumProperties - 1]
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char * interface
DBusConnection const char DBusError * error
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char * method
#define PROGRAMNAME
static const char includeList[]
static bool isSupportedSuffix(QStringView suffix)
static QString stringify(const QString &data)
#define PROGRAMCOPYRIGHT
static QString moc(const QString &name)
#define ANNOTATION_NO_WAIT
static QString templateArg(const QByteArray &arg)
#define PROGRAMVERSION
static const char forwardDeclarations[]
static QString methodName(const QDBusIntrospection::Method &method)
static QString header(const QString &name)
static QStringList makeArgNames(const QDBusIntrospection::Arguments &inputArgs, const QDBusIntrospection::Arguments &outputArgs=QDBusIntrospection::Arguments())
static QString constRefArg(const QByteArray &arg)
static bool openFile(const QString &fileName, QFile &file)
static QString nonConstRefArg(const QByteArray &arg)
#define qCritical
Definition qlogging.h:167
GLint location
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum type
GLenum GLenum severity
GLuint name
GLint first
GLsizei GLsizei GLchar * source
GLenum GLenum GLenum input
SSL_CTX int void * arg
#define qPrintable(string)
Definition qstring.h:1531
#define QStringLiteral(str)
ptrdiff_t qsizetype
Definition qtypes.h:165
const char property[13]
Definition qwizard.cpp:101
const char className[16]
[1]
Definition qwizard.cpp:100
ASSERT failure in file div cpp
QFile file
[0]
QStringList fileNames
[4]
QApplication app(argc, argv)
[0]
QAction * at
QJSValueList args