swift
Loading...
Searching...
No Matches
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
27namespace swift::misc
28{
34 {
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)
59 {
60 continue;
61 }
62 if (method.tag() && strcmp(method.tag(), "SWIFT_NO_RELAY") == 0)
63 {
64 continue;
65 }
66
67 const QByteArray signature = method.methodSignature().prepend(
68 "2"); // the reason for this "2" can be found in the definition of SIGNAL() macro
69 const bool c = this->connection().connect(this->service(), this->path(), this->interface(),
70 method.name(), this->parent(), signature);
71 if (!c)
72 {
73 CLogMessage(this).error(u"Cannot connect signal: %1") << QString(signature);
74 }
75 }
76 }
77
79 template <typename... Args>
80 void callDBus(QLatin1String method, Args &&...args)
81 {
82 const QList<QVariant> argumentList { QVariant::fromValue(std::forward<Args>(args))... };
83 this->callWithArgumentList(QDBus::NoBlock, method, argumentList);
84 }
85
87 template <typename Ret, typename... Args>
88 Ret callDBusRet(QLatin1String method, Args &&...args)
89 {
90 QList<QVariant> argumentList { QVariant::fromValue(std::forward<Args>(args))... };
91 QDBusPendingReply<Ret> pr = this->asyncCallWithArgumentList(method, argumentList);
92 pr.waitForFinished();
93 if (pr.isError())
94 {
95 CLogMessage(this).debug(u"CGenericDBusInterface::callDBusRet(%1) returned: %2")
96 << method << pr.error().message();
97 }
98 return pr;
99 }
100
103 template <typename Func, typename... Args>
104 QDBusPendingCallWatcher *callDBusAsync(QLatin1String method, Func callback, Args &&...args)
105 {
106 QList<QVariant> argumentList { QVariant::fromValue(std::forward<Args>(args))... };
107 QDBusPendingCall pc = this->asyncCallWithArgumentList(method, argumentList);
108 auto pcw = new QDBusPendingCallWatcher(pc, this);
110 return pcw;
111 }
112
114 template <typename Ret, typename... Args>
116 {
117 auto sharedPromise = QSharedPointer<CPromise<Ret>>::create();
118 this->callDBusAsync(
119 method, [=](auto pcw) { sharedPromise->setResult(QDBusPendingReply<Ret>(*pcw)); },
120 std::forward<Args>(args)...);
121 return sharedPromise->future();
122 }
123
127 {
129 for (auto w : watchers)
130 {
131 delete w;
132 }
133 }
134 };
135} // namespace swift::misc
136
137#endif // SWIFT_MISC_GENERICDBUSINTERFACE_H
CGenericDBusInterface(const QString &serviceName, const QString &path, const QString &interfaceName, const QDBusConnection &connection, QObject *parent=nullptr)
Constructor.
QDBusPendingCallWatcher * callDBusAsync(QLatin1String method, Func callback, Args &&...args)
Call DBus with asynchronous return value Callback can be any callable object taking a single argument...
void callDBus(QLatin1String method, Args &&...args)
Call DBus, no return value.
QFuture< Ret > callDBusFuture(QLatin1String method, Args &&...args)
Call DBus with asynchronous return as a future.
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.
Class for emitting a log message.
Definition logmessage.h:27
Derived & debug()
Set the severity to debug.
Derived & error(const char16_t(&format)[N])
Set the severity to error, providing a format string.
Free functions in swift::misc.
QByteArray & prepend(QByteArrayView ba)
QDBusPendingCall asyncCallWithArgumentList(const QString &method, const QList< QVariant > &args)
QDBusMessage callWithArgumentList(QDBus::CallMode mode, const QString &method, const QList< QVariant > &args)
QDBusConnection connection() const const
QString interface() const const
QString path() const const
QString service() const const
QString message() const const
void finished(QDBusPendingCallWatcher *self)
QDBusError error() const const
bool isError() const const
QByteArray methodSignature() const const
QMetaMethod::MethodType methodType() const const
QByteArray name() const const
const char * tag() const const
const char * className() const const
int methodOffset() const const
const QMetaObject * superClass() const const
QObject(QObject *parent)
Q_OBJECTQ_OBJECT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QList< T > findChildren(QAnyStringView name, Qt::FindChildOptions options) const const
virtual const QMetaObject * metaObject() const const
QObject * parent() const const
FindDirectChildrenOnly
QVariant fromValue(T &&value)
#define SWIFT_MISC_EXPORT
Export a class or function from the library.