swift
genericdbusinterface.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (C) 2013 swift Project Community / Contributors
2 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-swift-pilot-client-1
3 
5 
6 #ifndef SWIFT_MISC_GENERICDBUSINTERFACE_H
7 #define SWIFT_MISC_GENERICDBUSINTERFACE_H
8 
9 #include <QDBusAbstractInterface>
10 #include <QDBusPendingCall>
11 #include <QDBusPendingReply>
12 #include <QMetaMethod>
13 #include <QObject>
14 #include <QSharedPointer>
15 
16 #include "misc/logmessage.h"
17 #include "misc/promise.h"
18 
19 #ifndef Q_MOC_RUN
24 # define SWIFT_NO_RELAY
25 #endif
26 
27 namespace swift::misc
28 {
33  class SWIFT_MISC_EXPORT CGenericDBusInterface : public QDBusAbstractInterface
34  {
35  Q_OBJECT
36 
37  public:
39  CGenericDBusInterface(const QString &serviceName, const QString &path, const QString &interfaceName,
40  const QDBusConnection &connection, QObject *parent = nullptr)
41  : QDBusAbstractInterface(serviceName, path, interfaceName.toUtf8().constData(), connection, parent)
42  {}
43 
47  {
48  const QMetaObject *metaObject = this->parent()->metaObject();
49  const QMetaObject *superMetaObject = metaObject;
50  while (strcmp(superMetaObject->superClass()->className(), "QObject") != 0)
51  {
52  superMetaObject = superMetaObject->superClass();
53  }
54 
55  for (int i = superMetaObject->methodOffset(), count = metaObject->methodCount(); i < count; ++i)
56  {
57  const QMetaMethod method = metaObject->method(i);
58  if (method.methodType() != QMetaMethod::Signal) { continue; }
59  if (method.tag() && strcmp(method.tag(), "SWIFT_NO_RELAY") == 0) { continue; }
60 
61  const QByteArray signature = method.methodSignature().prepend(
62  "2"); // the reason for this "2" can be found in the definition of SIGNAL() macro
63  const bool c = this->connection().connect(this->service(), this->path(), this->interface(),
64  method.name(), this->parent(), signature);
65  if (!c) { CLogMessage(this).error(u"Cannot connect signal: %1") << QString(signature); }
66  }
67  }
68 
70  template <typename... Args>
71  void callDBus(QLatin1String method, Args &&...args)
72  {
73  const QList<QVariant> argumentList { QVariant::fromValue(std::forward<Args>(args))... };
74  this->callWithArgumentList(QDBus::NoBlock, method, argumentList);
75  }
76 
78  template <typename Ret, typename... Args>
79  Ret callDBusRet(QLatin1String method, Args &&...args)
80  {
81  QList<QVariant> argumentList { QVariant::fromValue(std::forward<Args>(args))... };
82  QDBusPendingReply<Ret> pr = this->asyncCallWithArgumentList(method, argumentList);
83  pr.waitForFinished();
84  if (pr.isError())
85  {
86  CLogMessage(this).debug(u"CGenericDBusInterface::callDBusRet(%1) returned: %2")
87  << method << pr.error().message();
88  }
89  return pr;
90  }
91 
94  template <typename Func, typename... Args>
95  QDBusPendingCallWatcher *callDBusAsync(QLatin1String method, Func callback, Args &&...args)
96  {
97  QList<QVariant> argumentList { QVariant::fromValue(std::forward<Args>(args))... };
98  QDBusPendingCall pc = this->asyncCallWithArgumentList(method, argumentList);
99  auto pcw = new QDBusPendingCallWatcher(pc, this);
100  connect(pcw, &QDBusPendingCallWatcher::finished, callback);
101  return pcw;
102  }
103 
105  template <typename Ret, typename... Args>
106  QFuture<Ret> callDBusFuture(QLatin1String method, Args &&...args)
107  {
108  auto sharedPromise = QSharedPointer<CPromise<Ret>>::create();
109  this->callDBusAsync(
110  method, [=](auto pcw) { sharedPromise->setResult(QDBusPendingReply<Ret>(*pcw)); },
111  std::forward<Args>(args)...);
112  return sharedPromise->future();
113  }
114 
118  {
119  auto watchers = this->findChildren<QDBusPendingCallWatcher *>(QString(), Qt::FindDirectChildrenOnly);
120  for (auto w : watchers) { delete w; }
121  }
122  };
123 } // namespace swift::misc
124 
125 #endif // SWIFT_MISC_GENERICDBUSINTERFACE_H
Used for hand written interface based on virtual methods.
CGenericDBusInterface(const QString &serviceName, const QString &path, const QString &interfaceName, const QDBusConnection &connection, QObject *parent=nullptr)
Constructor.
QFuture< Ret > callDBusFuture(QLatin1String method, Args &&...args)
Call DBus with asynchronous return as a future.
void callDBus(QLatin1String method, Args &&...args)
Call DBus, no return value.
void relayParentSignals()
For each signal in parent, attempt to connect to it an interface signal of the same name.
Ret callDBusRet(QLatin1String method, Args &&...args)
Call DBus with synchronous return value.
void cancelAllPendingAsyncCalls()
Cancel all asynchronous DBus calls which are currently pending.
QDBusPendingCallWatcher * callDBusAsync(QLatin1String method, Func callback, Args &&...args)
Call DBus with asynchronous return value Callback can be any callable object taking a single argument...
Class for emitting a log message.
Definition: logmessage.h:27
Derived & error(const char16_t(&format)[N])
Set the severity to error, providing a format string.
Derived & debug()
Set the severity to debug.
QString message() const
Private.
Free functions in swift::misc.
#define SWIFT_MISC_EXPORT
Export a class or function from the library.