BluezQt

pendingcall.cpp
1/*
2 * BluezQt - Asynchronous Bluez wrapper library
3 *
4 * SPDX-FileCopyrightText: 2014 David Rosca <nowrep@gmail.com>
5 *
6 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
7 */
8
9#include "pendingcall.h"
10#include "bluezqt_dbustypes.h"
11#include "debug.h"
12#include "obexfiletransferentry.h"
13#include "obextransfer.h"
14#include "obextransfer_p.h"
15
16#include <QDBusPendingCallWatcher>
17
18namespace BluezQt
19{
20static PendingCall::Error nameToError(const QString &name)
21{
22 if (name.startsWith(QLatin1String("org.freedesktop.DBus.Error"))) {
24 }
25
26 if (!name.startsWith(QLatin1String("org.bluez.Error"))) {
28 }
29
30#define FROM_BLUEZ_ERROR(string, value) \
31 if (errorName == QLatin1String(string)) { \
32 return value; \
33 }
34
35 const QString &errorName = name.mid(16);
36 FROM_BLUEZ_ERROR("NotReady", PendingCall::NotReady);
37 FROM_BLUEZ_ERROR("Failed", PendingCall::Failed);
38 FROM_BLUEZ_ERROR("Rejected", PendingCall::Rejected);
39 FROM_BLUEZ_ERROR("Canceled", PendingCall::Canceled);
40 FROM_BLUEZ_ERROR("InvalidArguments", PendingCall::InvalidArguments);
41 FROM_BLUEZ_ERROR("AlreadyExists", PendingCall::AlreadyExists);
42 FROM_BLUEZ_ERROR("DoesNotExist", PendingCall::DoesNotExist);
43 FROM_BLUEZ_ERROR("AlreadyConnected", PendingCall::AlreadyConnected);
44 FROM_BLUEZ_ERROR("ConnectFailed", PendingCall::ConnectFailed);
45 FROM_BLUEZ_ERROR("NotConnected", PendingCall::NotConnected);
46 FROM_BLUEZ_ERROR("NotSupported", PendingCall::NotSupported);
47 FROM_BLUEZ_ERROR("NotAuthorized", PendingCall::NotAuthorized);
48 FROM_BLUEZ_ERROR("AuthenticationCanceled", PendingCall::AuthenticationCanceled);
49 FROM_BLUEZ_ERROR("AuthenticationFailed", PendingCall::AuthenticationFailed);
50 FROM_BLUEZ_ERROR("AuthenticationRejected", PendingCall::AuthenticationRejected);
51 FROM_BLUEZ_ERROR("AuthenticationTimeout", PendingCall::AuthenticationTimeout);
52 FROM_BLUEZ_ERROR("ConnectionAttemptFailed", PendingCall::ConnectionAttemptFailed);
53 FROM_BLUEZ_ERROR("InvalidLength", PendingCall::InvalidLength);
54 FROM_BLUEZ_ERROR("NotPermitted", PendingCall::NotPermitted);
55#undef FROM_BLUEZ_ERROR
56
58}
59
60class PendingCallPrivate
61{
62public:
63 explicit PendingCallPrivate(PendingCall *parent);
64
65 void processReply(QDBusPendingCallWatcher *call);
66 void processVoidReply(const QDBusPendingReply<> &reply);
67 void processUint32Reply(const QDBusPendingReply<quint32> &reply);
68 void processStringReply(const QDBusPendingReply<QString> &reply);
69 void processStringListReply(const QDBusPendingReply<QStringList> &reply);
70 void processObjectPathReply(const QDBusPendingReply<QDBusObjectPath> &reply);
71 void processFileTransferListReply(const QDBusPendingReply<QVariantMapList> &reply);
72 void processTransferWithPropertiesReply(const QDBusPendingReply<QDBusObjectPath, QVariantMap> &reply);
73 void processByteArrayReply(const QDBusPendingReply<QByteArray> &reply);
74 void processError(const QDBusError &m_error);
75
76 void emitFinished();
77 void emitInternalError(const QString &errorText);
78 void pendingCallFinished(QDBusPendingCallWatcher *m_watcher);
79
80 PendingCall *q;
81 int m_error;
82 QString m_errorText;
83 QVariant m_userData;
84 QVariantList m_value;
85 PendingCall::ReturnType m_type;
86 QDBusPendingCallWatcher *m_watcher;
87};
88
89PendingCallPrivate::PendingCallPrivate(PendingCall *parent)
90 : q(parent)
91 , m_error(PendingCall::NoError)
92 , m_type(PendingCall::ReturnVoid)
93 , m_watcher(nullptr)
94{
95}
96
97void PendingCallPrivate::processReply(QDBusPendingCallWatcher *call)
98{
99 switch (m_type) {
100 case PendingCall::ReturnVoid:
101 processVoidReply(*call);
102 break;
103
104 case PendingCall::ReturnUint32:
105 processUint32Reply(*call);
106 break;
107
108 case PendingCall::ReturnString:
109 processStringReply(*call);
110 break;
111
112 case PendingCall::ReturnStringList:
113 processStringListReply(*call);
114 break;
115
116 case PendingCall::ReturnObjectPath:
117 processObjectPathReply(*call);
118 break;
119
120 case PendingCall::ReturnFileTransferList:
121 processFileTransferListReply(*call);
122 break;
123
124 case PendingCall::ReturnTransferWithProperties:
125 processTransferWithPropertiesReply(*call);
126 break;
127
128 case PendingCall::ReturnByteArray:
129 processByteArrayReply(*call);
130 break;
131
132 default:
133 break;
134 }
135}
136
137void PendingCallPrivate::processVoidReply(const QDBusPendingReply<> &reply)
138{
139 processError(reply.error());
140}
141
142void PendingCallPrivate::processUint32Reply(const QDBusPendingReply<quint32> &reply)
143{
144 processError(reply.error());
145 if (!reply.isError()) {
146 m_value.append(reply.value());
147 }
148}
149
150void PendingCallPrivate::processStringReply(const QDBusPendingReply<QString> &reply)
151{
152 processError(reply.error());
153 if (!reply.isError()) {
154 m_value.append(reply.value());
155 }
156}
157
158void PendingCallPrivate::processStringListReply(const QDBusPendingReply<QStringList> &reply)
159{
160 processError(reply.error());
161 if (!reply.isError()) {
162 m_value.append(reply.value());
163 }
164}
165
166void PendingCallPrivate::processObjectPathReply(const QDBusPendingReply<QDBusObjectPath> &reply)
167{
168 processError(reply.error());
169 if (!reply.isError()) {
170 m_value.append(QVariant::fromValue(reply.value()));
171 }
172}
173
174void PendingCallPrivate::processFileTransferListReply(const QDBusPendingReply<QVariantMapList> &reply)
175{
176 processError(reply.error());
177 if (!reply.isError()) {
179 items.reserve(reply.value().size());
180 const auto maps = reply.value();
181 for (const QVariantMap &map : maps) {
182 items.append(ObexFileTransferEntry(map));
183 }
184 m_value.append(QVariant::fromValue(items));
185 }
186}
187
188void PendingCallPrivate::processTransferWithPropertiesReply(const QDBusPendingReply<QDBusObjectPath, QVariantMap> &reply)
189{
190 processError(reply.error());
191 if (reply.isError()) {
192 return;
193 }
194
195 ObexTransferPtr transfer = ObexTransferPtr(new ObexTransfer(reply.argumentAt<0>().path(), reply.argumentAt<1>()));
196 transfer->d->q = transfer.toWeakRef();
197 transfer->d->m_suspendable = true;
198 m_value.append(QVariant::fromValue(transfer));
199}
200
201void PendingCallPrivate::processByteArrayReply(const QDBusPendingReply<QByteArray> &reply)
202{
203 processError(reply.error());
204 if (!reply.isError()) {
205 m_value.append(QVariant::fromValue(reply.value()));
206 }
207}
208
209void PendingCallPrivate::processError(const QDBusError &error)
210{
211 if (error.isValid()) {
212 qCWarning(BLUEZQT) << "PendingCall Error:" << error.message();
213 m_error = nameToError(error.name());
214 m_errorText = error.message();
215 }
216}
217
218void PendingCallPrivate::emitFinished()
219{
220 m_watcher->deleteLater();
221 m_watcher = nullptr;
222 Q_EMIT q->finished(q);
223 q->deleteLater();
224}
225
226void PendingCallPrivate::emitInternalError(const QString &errorText)
227{
228 qCWarning(BLUEZQT) << "PendingCall Internal error:" << errorText;
229 m_error = PendingCall::InternalError;
230 m_errorText = errorText;
231 emitFinished();
232}
233
234void PendingCallPrivate::pendingCallFinished(QDBusPendingCallWatcher *watcher)
235{
236 processReply(watcher);
237 emitFinished();
238}
239
240PendingCall::PendingCall(const QDBusPendingCall &call, ReturnType type, QObject *parent)
241 : QObject(parent)
242 , d(new PendingCallPrivate(this))
243{
244 qDBusRegisterMetaType<QVariantMapList>();
245
246 d->m_type = type;
247 d->m_watcher = new QDBusPendingCallWatcher(call, this);
248
249 connect(d->m_watcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *watcher) {
250 d->pendingCallFinished(watcher);
251 });
252}
253
254PendingCall::PendingCall(PendingCall::Error error, const QString &errorText, QObject *parent)
255 : QObject(parent)
256 , d(new PendingCallPrivate(this))
257{
258 d->m_error = error;
259 d->m_errorText = errorText;
260
262 this,
263 [this]() {
264 Q_EMIT finished(this);
265 },
267}
268
269PendingCall::PendingCall(const QDBusPendingCall &call, ExternalProcessor externalProcessor, QObject *parent)
270 : QObject(parent)
271 , d(new PendingCallPrivate(this))
272{
273 qDBusRegisterMetaType<QVariantMapList>();
274
275 d->m_watcher = new QDBusPendingCallWatcher(call, this);
276 connect(d->m_watcher, &QDBusPendingCallWatcher::finished, [externalProcessor, this](QDBusPendingCallWatcher *watcher) {
277 externalProcessor(watcher, std::bind(&PendingCallPrivate::processError, d.get(), std::placeholders::_1), &d->m_value);
278 d->emitFinished();
279 });
280}
281
282PendingCall::~PendingCall() = default;
283
284QVariant PendingCall::value() const
285{
286 if (d->m_value.isEmpty()) {
287 return QVariant();
288 }
289 return d->m_value.first();
290}
291
292QVariantList PendingCall::values() const
293{
294 return d->m_value;
295}
296
297int PendingCall::error() const
298{
299 return d->m_error;
300}
301
302QString PendingCall::errorText() const
303{
304 return d->m_errorText;
305}
306
307bool PendingCall::isFinished() const
308{
309 if (d->m_watcher) {
310 return d->m_watcher->isFinished();
311 }
312 return true;
313}
314
315void PendingCall::waitForFinished()
316{
317 if (d->m_watcher) {
318 d->m_watcher->waitForFinished();
319 }
320}
321
322QVariant PendingCall::userData() const
323{
324 return d->m_userData;
325}
326
327void PendingCall::setUserData(const QVariant &userData)
328{
329 d->m_userData = userData;
330}
331
332} // namespace BluezQt
333
334#include "moc_pendingcall.cpp"
Error
Known error types.
Definition pendingcall.h:49
@ DoesNotExist
Indicates that an agent, service or pairing operation does not exists.
Definition pendingcall.h:65
@ AlreadyExists
Indicates that an agent or pairing record already exists.
Definition pendingcall.h:63
@ NotSupported
Indicates that the action is not supported.
Definition pendingcall.h:77
@ ConnectionAttemptFailed
Indicates that the connection attempt have failed.
Definition pendingcall.h:89
@ NotPermitted
Indicates that the action is not permitted (e.g.
Definition pendingcall.h:93
@ ConnectFailed
Indicates that the connection to the device have failed.
Definition pendingcall.h:73
@ NotReady
Indicates that the device is not ready.
Definition pendingcall.h:53
@ AuthenticationCanceled
Indicates that the authentication was canceled.
Definition pendingcall.h:81
@ AuthenticationTimeout
Indicates that the authentication timed out.
Definition pendingcall.h:87
@ InvalidLength
Indicates that the data provided generates a data packet which is too long.
Definition pendingcall.h:91
@ AuthenticationRejected
Indicates that the authentication was rejected.
Definition pendingcall.h:85
@ Failed
Indicates that the action have failed.
Definition pendingcall.h:55
@ InvalidArguments
Indicates that invalid arguments were passed.
Definition pendingcall.h:61
@ AlreadyConnected
Indicates that the device is already connected.
Definition pendingcall.h:71
@ UnknownError
Indicates an unknown error.
Definition pendingcall.h:99
@ DBusError
Indicates an error with D-Bus.
Definition pendingcall.h:95
@ NotAuthorized
Indicates that the caller is not authorized to do the action.
Definition pendingcall.h:79
@ Rejected
Indicates that the action was rejected.
Definition pendingcall.h:57
@ Canceled
Indicates that the action was canceled.
Definition pendingcall.h:59
@ NotConnected
Indicates that the device is not connected.
Definition pendingcall.h:75
@ AuthenticationFailed
Indicates that the authentication have failed.
Definition pendingcall.h:83
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
QString name(StandardAction id)
void finished(QDBusPendingCallWatcher *self)
QVariant argumentAt(int index) const const
QDBusError error() const const
bool isError() const const
typename Select< 0 >::Type value() const const
void append(QList< T > &&value)
void reserve(qsizetype size)
bool invokeMethod(QObject *context, Functor &&function, FunctorReturnType *ret)
QString mid(qsizetype position, qsizetype n) const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QueuedConnection
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QVariant fromValue(T &&value)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Oct 11 2024 12:18:02 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.