Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qdbuspendingcall.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2016 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include "qdbuspendingcall.h"
7
8#include "qdbusconnection_p.h"
9#include "qdbusmetatype_p.h"
10#include "qdbusutil_p.h"
11#include "qcoreapplication.h"
12#include "qcoreevent.h"
13#include <private/qobject_p.h>
14#include <private/qlocking_p.h>
15
16#ifndef QT_NO_DBUS
17
19
20using namespace Qt::StringLiterals;
21
96{
97 connect(this, SIGNAL(finished()), watcher, SLOT(_q_finished()), Qt::QueuedConnection);
98}
99
101{
102 if (pending) {
103 q_dbus_pending_call_cancel(pending);
104 q_dbus_pending_call_unref(pending);
105 }
106 delete watcherHelper;
107}
108
110{
113 methodIdx = -1;
114 if (!target)
115 return true;; // unsetting
116
117 if (!member || !*member) {
118 // would not be able to deliver a reply
119 qWarning("QDBusPendingCall::setReplyCallback: error: cannot deliver a reply to %s::%s (%s)",
120 target ? target->metaObject()->className() : "(null)",
121 member ? member + 1 : "(null)",
122 target ? qPrintable(target->objectName()) : "no name");
123 return false;
124 }
125
126 QString errorMsg;
128 if (methodIdx == -1) {
129 QByteArray normalizedName = QMetaObject::normalizedSignature(member + 1);
130 methodIdx = QDBusConnectionPrivate::findSlot(target, normalizedName, metaTypes, errorMsg);
131 }
132 if (methodIdx == -1) {
133 // would not be able to deliver a reply
134 qWarning("QDBusPendingCall::setReplyCallback: error: cannot deliver a reply to %s::%s (%s) "
135 "because %s",
136 target->metaObject()->className(), member + 1, qPrintable(target->objectName()),
137 qPrintable(errorMsg));
138 return false;
139 }
140
141 // success
142 // construct the expected signature
143 int count = metaTypes.size() - 1;
144 if (count == 1 && metaTypes.at(1) == QDBusMetaTypeId::message()) {
145 // wildcard slot, can receive anything, so don't set the signature
146 return true;
147 }
148
150 --count;
151
152 setMetaTypes(count, count ? metaTypes.constData() + 1 : nullptr);
153 return true;
154}
155
157{
158 if (count == 0) {
159 expectedReplySignature = ""_L1; // not null
160 return;
161 }
162
163 QByteArray sig;
164 sig.reserve(count + count / 2);
165 for (int i = 0; i < count; ++i) {
166 const char *typeSig = QDBusMetaType::typeToSignature(types[i]);
167 if (Q_UNLIKELY(!typeSig))
168 qFatal("QDBusPendingReply: type %s is not registered with QtDBus", types[i].name());
169 sig += typeSig;
170 }
171
173}
174
176{
177 // MUST BE CALLED WITH A LOCKED MUTEX!
178
180 return; // not yet finished - no message to
181 // validate against
183 return; // we don't have to check the signature of an error reply
184
186 return; // no signature to validate against
187
188 // can't use startsWith here because a null string doesn't start or end with an empty string
190 const auto errorMsg = "Unexpected reply signature: got \"%1\", expected \"%2\""_L1;
194
195 }
196}
197
199{
200 const auto locker = qt_scoped_lock(mutex);
201
203 return; // already finished
204
206}
207
213 : d(other.d)
214{
215}
216
221 : d(dd)
222{
223 if (dd) {
224 bool r = dd->ref.deref();
225 Q_ASSERT(r);
226 Q_UNUSED(r);
227 }
228}
229
237{
238 // d deleted by QExplicitlySharedDataPointer
239}
240
241
253{
254 d = other.d;
255 return *this;
256}
257
295{
296 if (!d)
297 return true; // considered finished
298
299 const auto locker = qt_scoped_lock(d->mutex);
301}
302
304{
305 if (d) d->waitForFinished();
306}
307
318{
319 if (!d)
320 return false;
321 const auto locker = qt_scoped_lock(d->mutex);
323}
324
335{
336 if (!d)
337 return true; // considered finished and an error
338 const auto locker = qt_scoped_lock(d->mutex);
340}
341
351{
352 if (d) {
353 const auto locker = qt_scoped_lock(d->mutex);
354 return QDBusError(d->replyMessage);
355 }
356
357 // not connected, return an error
360 return err;
361}
362
375{
376 if (!d)
378 const auto locker = qt_scoped_lock(d->mutex);
379 return d->replyMessage;
380}
381
382#if 0
383/*
384 Sets the slot \a member in object \a target to be called when the
385 reply arrives. The slot's parameter list must match the reply
386 message's arguments for it to be called.
387
388 It may, optionally, contain a QDBusMessage final parameter. If it
389 is present, the parameter will contain the reply message object.
390
391 The callback will not be called if the reply is an error message.
392
393 This function returns \c true if it could set the callback, false
394 otherwise. It is not a guarantee that the callback will be
395 called.
396
397 \warning QDBusPendingCall only supports one callback per pending
398 asynchronous call, even if multiple QDBusPendingCall
399 objects are referencing the same pending call.
400*/
401bool QDBusPendingCall::setReplyCallback(QObject *target, const char *member)
402{
403 if (!d)
404 return false;
405
406 return d->setReplyCallback(target, member);
407}
408#endif
409
419{
421}
422
436{
437 QDBusPendingCallPrivate *d = nullptr;
438 if (msg.type() == QDBusMessage::ErrorMessage ||
440 d = new QDBusPendingCallPrivate(QDBusMessage(), nullptr);
441 d->replyMessage = msg;
442 d->ref.storeRelaxed(1);
443 }
444
445 return QDBusPendingCall(d);
446}
447
448
450{
451public:
452 void _q_finished();
453
454 Q_DECLARE_PUBLIC(QDBusPendingCallWatcher)
455};
456
458{
460 emit q->finished(q);
461}
462
470{
471 if (d) { // QDBusPendingCall::d
472 const auto locker = qt_scoped_lock(d->mutex);
473 if (!d->watcherHelper) {
476 // cause a signal emission anyways
480 }
481 }
482 d->watcherHelper->add(this);
483 }
484}
485
492{
493}
494
506{
507 if (d) {
509
510 // our signals were queued, so deliver them
513 }
514}
516
517#include "moc_qdbuspendingcall_p.cpp"
518
519#endif // QT_NO_DBUS
520
521#include "moc_qdbuspendingcall.cpp"
bool deref() noexcept
void storeRelaxed(T newValue) noexcept
\inmodule QtCore
Definition qbytearray.h:57
void reserve(qsizetype size)
Attempts to allocate memory for at least size bytes.
Definition qbytearray.h:557
static void sendPostedEvents(QObject *receiver=nullptr, int event_type=0)
Immediately dispatches all events which have been previously queued with QCoreApplication::postEvent(...
static int findSlot(QObject *obj, const QByteArray &normalizedName, QList< QMetaType > &params, QString &errorMsg)
\inmodule QtDBus
Definition qdbuserror.h:21
@ InvalidSignature
Definition qdbuserror.h:43
\inmodule QtDBus
static QDBusMessage createError(const QString &name, const QString &msg)
Constructs a new DBus message representing an error, with the given name and msg.
MessageType type() const
Returns the message type.
QString signature() const
Returns the signature of the signal that was received or for the output arguments of a method call.
static const char * typeToSignature(QMetaType type)
QPointer< QObject > receiver
QDBusPendingCallWatcherHelper * watcherHelper
QWaitCondition waitForFinishedCondition
bool setReplyCallback(QObject *target, const char *member)
QList< QMetaType > metaTypes
void setMetaTypes(int count, const QMetaType *types)
void add(QDBusPendingCallWatcher *watcher)
void waitForFinished()
Suspends the execution of the calling thread until the reply is received and processed.
~QDBusPendingCallWatcher()
Destroys this object.
\inmodule QtDBus
static QDBusPendingCall fromError(const QDBusError &error)
QExplicitlySharedDataPointer< QDBusPendingCallPrivate > d
QDBusPendingCall & operator=(QDBusPendingCall &&other) noexcept
QDBusPendingCall(const QDBusPendingCall &other)
Creates a copy of the other pending asynchronous call.
QDBusError error() const
QDBusMessage reply() const
~QDBusPendingCall()
Destroys this copy of the QDBusPendingCall object.
static QDBusPendingCall fromCompletedCall(const QDBusMessage &message)
friend class QDBusPendingCallWatcher
friend class QDBusPendingCallPrivate
@ MetaCall
Definition qcoreevent.h:97
qsizetype size() const noexcept
Definition qlist.h:386
const_pointer constData() const noexcept
Definition qlist.h:416
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
void clear()
Definition qlist.h:417
\inmodule QtCore
Definition qmetatype.h:320
\inmodule QtCore
Definition qobject.h:90
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
QAtomicInt ref
Definition qshareddata.h:21
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5710
bool isNull() const
Returns true if this string is null; otherwise returns false.
Definition qstring.h:898
static QString static QString qsizetype indexOf(QChar c, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.cpp:4420
bool wait(QMutex *, QDeadlineTimer=QDeadlineTimer(QDeadlineTimer::Forever))
QMetaType message()
QString disconnectedErrorMessage()
Combined button and popup list for selecting options.
@ QueuedConnection
#define Q_UNLIKELY(x)
DBusConnection const char DBusError * error
#define qWarning
Definition qlogging.h:162
#define qFatal
Definition qlogging.h:164
#define SLOT(a)
Definition qobjectdefs.h:51
#define SIGNAL(a)
Definition qobjectdefs.h:52
GLboolean r
[2]
GLsizei GLenum GLenum * types
GLenum GLenum GLsizei count
GLenum target
GLuint name
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define qPrintable(string)
Definition qstring.h:1391
#define emit
#define Q_UNUSED(x)
QFutureWatcher< int > watcher
QSharedPointer< T > other(t)
[5]
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
\threadsafe This is an overloaded member function, provided for convenience. It differs from the abov...
static QByteArray normalizedSignature(const char *method)
Normalizes the signature of the given method.
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent