Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qdbusreply.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include "qdbusreply.h"
8#include <QDebug>
9
10#ifndef QT_NO_DBUS
11
13
14using namespace Qt::StringLiterals;
15
16/*!
17 \class QDBusReply
18 \inmodule QtDBus
19 \since 4.2
20
21 \brief The QDBusReply class stores the reply for a method call to a remote object.
22
23 QDBusReply<T> is a template class where \a T specifies the expected return type.
24 A QDBusReply object is a subset of the QDBusMessage object that represents a method call's
25 reply. It contains only the first output argument or the error code and is used by
26 QDBusInterface-derived classes to allow returning the error code as the function's return
27 argument.
28
29 It can be used in the following manner:
30 \snippet code/src_qdbus_qdbusreply.cpp 0
31
32 If the remote method call cannot fail, you can skip the error checking:
33 \snippet code/src_qdbus_qdbusreply.cpp 1
34
35 However, if it does fail under those conditions, the value returned by QDBusReply<T>::value() is
36 a default-constructed value. It may be indistinguishable from a valid return value.
37
38 QDBusReply objects are used for remote calls that have no output
39 arguments or return values (i.e., they have a "void" return
40 type). Use the isValid() function to test if the reply succeeded.
41
42 \sa QDBusMessage, QDBusInterface
43*/
44
45/*!
46 \fn template<typename T> QDBusReply<T>::QDBusReply(const QDBusMessage &reply)
47 Automatically construct a QDBusReply object from the reply message \a reply, extracting the
48 first return value from it if it is a success reply.
49*/
50
51/*!
52 \fn template<typename T> QDBusReply<T>::QDBusReply(const QDBusPendingReply<T> &reply)
53 Constructs a QDBusReply object from the pending reply message, \a reply.
54*/
55
56/*!
57 \fn template <typename T> QDBusReply<T>::QDBusReply(const QDBusPendingCall &pcall)
58 Automatically construct a QDBusReply object from the asynchronous
59 pending call \a pcall. If the call isn't finished yet, QDBusReply
60 will call QDBusPendingCall::waitForFinished(), which is a blocking
61 operation.
62
63 If the return types patch, QDBusReply will extract the first
64 return argument from the reply.
65*/
66
67/*!
68 \fn template <typename T> QDBusReply<T>::QDBusReply(const QDBusError &error)
69 Constructs an error reply from the D-Bus error code given by \a error.
70*/
71
72/*!
73 \fn template <typename T> QDBusReply<T>::operator=(const QDBusError &dbusError)
74 Sets this object to contain the error code given by \a dbusError. You
75 can later access it with error().
76*/
77
78/*!
79 \fn template <typename T> QDBusReply<T>::operator=(const QDBusMessage &reply)
80
81 Makes this object contain the \a reply message. If \a reply
82 is an error message, this function will
83 copy the error code and message into this object
84
85 If \a reply is a standard reply message and contains at least
86 one parameter, it will be copied into this object, as long as it
87 is of the correct type. If it's not of the same type as this
88 QDBusError object, this function will instead set an error code
89 indicating a type mismatch.
90*/
91
92/*!
93 \fn template <typename T> QDBusReply<T>::operator=(const QDBusPendingCall &pcall)
94
95 Makes this object contain the reply specified by the pending
96 asynchronous call \a pcall. If the call is not finished yet, this
97 function will call QDBusPendingCall::waitForFinished() to block
98 until the reply arrives.
99
100 If \a pcall finishes with an error message, this function will
101 copy the error code and message into this object
102
103 If \a pcall finished with a standard reply message and contains at
104 least one parameter, it will be copied into this object, as long
105 as it is of the correct type. If it's not of the same type as this
106 QDBusError object, this function will instead set an error code
107 indicating a type mismatch.
108*/
109
110/*!
111 \fn template <typename T> bool QDBusReply<T>::isValid() const
112
113 Returns \c true if no error occurred; otherwise, returns \c false.
114
115 \sa error()
116*/
117
118/*!
119 \fn template<typename T> const QDBusError& QDBusReply<T>::error() const
120
121 Returns the error code that was returned from the remote function call. If the remote call did
122 not return an error (i.e., if it succeeded), then the QDBusError object that is returned will
123 not be a valid error code (QDBusError::isValid() will return false).
124
125 \sa isValid()
126*/
127
128/*!
129 \fn template <typename T> Type QDBusReply<T>::value() const
130 Returns the remote function's calls return value. If the remote call returned with an error,
131 the return value of this function is undefined and may be undistinguishable from a valid return
132 value.
133
134 This function is not available if the remote call returns \c void.
135*/
136
137/*!
138 \fn template <typename T> QDBusReply<T>::operator Type() const
139 Returns the same as value().
140
141 This function is not available if the remote call returns \c void.
142*/
143
144/*!
145 \internal
146 Fills in the QDBusReply data \a error and \a data from the reply message \a reply.
147*/
148void qDBusReplyFill(const QDBusMessage &reply, QDBusError &error, QVariant &data)
149{
150 error = QDBusError(reply);
151
152 if (error.isValid()) {
153 data = QVariant(); // clear it
154 return;
155 }
156
157 if (reply.arguments().size() >= 1 && reply.arguments().at(0).metaType() == data.metaType()) {
158 data = reply.arguments().at(0);
159 return;
160 }
161
162 const char *expectedSignature = QDBusMetaType::typeToSignature(data.metaType());
163 const char *receivedType = nullptr;
164 QByteArray receivedSignature;
165
166 if (reply.arguments().size() >= 1) {
167 if (reply.arguments().at(0).metaType() == QDBusMetaTypeId::argument()) {
168 // compare signatures instead
169 QDBusArgument arg = qvariant_cast<QDBusArgument>(reply.arguments().at(0));
170 receivedSignature = arg.currentSignature().toLatin1();
171 if (receivedSignature == expectedSignature) {
172 // matched. Demarshall it
173 QDBusMetaType::demarshall(arg, data.metaType(), data.data());
174 return;
175 }
176 } else {
177 // not an argument and doesn't match?
178 QMetaType type = reply.arguments().at(0).metaType();
179 receivedType = type.name();
180 receivedSignature = QDBusMetaType::typeToSignature(type);
181 }
182 }
183
184 // error
185 if (receivedSignature.isEmpty())
186 receivedSignature = "<empty signature>";
187 QString errorMsg;
188 if (receivedType) {
189 errorMsg = "Unexpected reply signature: got \"%1\" (%4), expected \"%2\" (%3)"_L1
190 .arg(QLatin1StringView(receivedSignature),
191 QLatin1StringView(expectedSignature),
192 QLatin1StringView(data.typeName()),
193 QLatin1StringView(receivedType));
194 } else {
195 errorMsg = "Unexpected reply signature: got \"%1\", expected \"%2\" (%3)"_L1
196 .arg(QLatin1StringView(receivedSignature),
197 QLatin1StringView(expectedSignature),
198 QLatin1StringView(data.typeName()));
199 }
200
201 error = QDBusError(QDBusError::InvalidSignature, errorMsg);
202 data = QVariant(); // clear it
203}
204
205QT_END_NAMESPACE
206
207#endif // QT_NO_DBUS
\inmodule QtDBus
Combined button and popup list for selecting options.
void qDBusReplyFill(const QDBusMessage &reply, QDBusError &error, QVariant &data)