Merge remote-tracking branch 'origin/api_changes'
[profile/ivi/qtbase.git] / src / dbus / qdbusreply.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtDBus module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qdbusreply.h"
43 #include "qdbusmetatype.h"
44 #include "qdbusmetatype_p.h"
45 #include <QDebug>
46
47 #ifndef QT_NO_DBUS
48
49 QT_BEGIN_NAMESPACE
50
51 /*!
52     \class QDBusReply
53     \inmodule QtDBus
54     \since 4.2
55
56     \brief The QDBusReply class stores the reply for a method call to a remote object.
57
58     A QDBusReply object is a subset of the QDBusMessage object that represents a method call's
59     reply. It contains only the first output argument or the error code and is used by
60     QDBusInterface-derived classes to allow returning the error code as the function's return
61     argument.
62
63     It can be used in the following manner:
64     \snippet doc/src/snippets/code/src_qdbus_qdbusreply.cpp 0
65
66     If the remote method call cannot fail, you can skip the error checking:
67     \snippet doc/src/snippets/code/src_qdbus_qdbusreply.cpp 1
68
69     However, if it does fail under those conditions, the value returned by QDBusReply::value() is
70     a default-constructed value. It may be indistinguishable from a valid return value.
71
72     QDBusReply objects are used for remote calls that have no output
73     arguments or return values (i.e., they have a "void" return
74     type). Use the isValid() function to test if the reply succeeded.
75
76     \sa QDBusMessage, QDBusInterface
77 */
78
79 /*!
80     \fn QDBusReply::QDBusReply(const QDBusMessage &reply)
81     Automatically construct a QDBusReply object from the reply message \a reply, extracting the
82     first return value from it if it is a success reply.
83 */
84
85 /*!
86     \fn QDBusReply::QDBusReply(const QDBusPendingReply<T> &reply)
87     Constructs a QDBusReply object from the pending reply message, \a reply.
88 */
89
90 /*!
91     \fn QDBusReply::QDBusReply(const QDBusPendingCall &pcall)
92     Automatically construct a QDBusReply object from the asynchronous
93     pending call \a pcall. If the call isn't finished yet, QDBusReply
94     will call QDBusPendingCall::waitForFinished(), which is a blocking
95     operation.
96
97     If the return types patch, QDBusReply will extract the first
98     return argument from the reply.
99 */
100
101 /*!
102     \fn QDBusReply::QDBusReply(const QDBusError &error)
103     Constructs an error reply from the D-Bus error code given by \a error.
104 */
105
106 /*!
107     \fn QDBusReply::operator=(const QDBusReply &other)
108     Makes this object be a copy of the object \a other.
109 */
110
111 /*!
112     \fn QDBusReply::operator=(const QDBusError &error)
113     Sets this object to contain the error code given by \a error. You
114     can later access it with error().
115 */
116
117 /*!
118     \fn QDBusReply::operator=(const QDBusMessage &message)
119
120     Makes this object contain the reply specified by message \a
121     message. If \a message is an error message, this function will
122     copy the error code and message into this object
123
124     If \a message is a standard reply message and contains at least
125     one parameter, it will be copied into this object, as long as it
126     is of the correct type. If it's not of the same type as this
127     QDBusError object, this function will instead set an error code
128     indicating a type mismatch.
129 */
130
131 /*!
132     \fn QDBusReply::operator=(const QDBusPendingCall &pcall)
133
134     Makes this object contain the reply specified by the pending
135     asynchronous call \a pcall. If the call is not finished yet, this
136     function will call QDBusPendingCall::waitForFinished() to block
137     until the reply arrives.
138
139     If \a pcall finishes with an error message, this function will
140     copy the error code and message into this object
141
142     If \a pcall finished with a standard reply message and contains at
143     least one parameter, it will be copied into this object, as long
144     as it is of the correct type. If it's not of the same type as this
145     QDBusError object, this function will instead set an error code
146     indicating a type mismatch.
147 */
148
149 /*!
150     \fn bool QDBusReply::isValid() const
151
152     Returns true if no error occurred; otherwise, returns false.
153
154     \sa error()
155 */
156
157 /*!
158     \fn QDBusReply::error()
159
160     Returns the error code that was returned from the remote function call. If the remote call did
161     not return an error (i.e., if it succeeded), then the QDBusError object that is returned will
162     not be a valid error code (QDBusError::isValid() will return false).
163
164     \sa isValid()
165 */
166
167 /*!
168     \fn QDBusReply::value() const
169     Returns the remote function's calls return value. If the remote call returned with an error,
170     the return value of this function is undefined and may be undistinguishable from a valid return
171     value.
172
173     This function is not available if the remote call returns \c void.
174 */
175
176 /*!
177     \fn QDBusReply::operator Type() const
178     Returns the same as value().
179
180     This function is not available if the remote call returns \c void.
181 */
182
183 /*!
184     \internal
185     Fills in the QDBusReply data \a error and \a data from the reply message \a reply.
186 */
187 void qDBusReplyFill(const QDBusMessage &reply, QDBusError &error, QVariant &data)
188 {
189     error = QDBusError(reply);
190
191     if (error.isValid()) {
192         data = QVariant();      // clear it
193         return;
194     }
195
196     if (reply.arguments().count() >= 1 && reply.arguments().at(0).userType() == data.userType()) {
197         data = reply.arguments().at(0);
198         return;
199     }
200
201     const char *expectedSignature = QDBusMetaType::typeToSignature(data.userType());
202     const char *receivedType = 0;
203     QByteArray receivedSignature;
204
205     if (reply.arguments().count() >= 1) {
206         if (reply.arguments().at(0).userType() == QDBusMetaTypeId::argument) {
207             // compare signatures instead
208             QDBusArgument arg = qvariant_cast<QDBusArgument>(reply.arguments().at(0));
209             receivedSignature = arg.currentSignature().toLatin1();
210             if (receivedSignature == expectedSignature) {
211                 // matched. Demarshall it
212                 QDBusMetaType::demarshall(arg, data.userType(), data.data());
213                 return;
214             }
215         } else {
216             // not an argument and doesn't match?
217             int type = reply.arguments().at(0).userType();
218             receivedType = QVariant::typeToName(QVariant::Type(type));
219             receivedSignature = QDBusMetaType::typeToSignature(type);
220         }
221     }
222
223     // error
224     if (receivedSignature.isEmpty())
225         receivedSignature = "no signature";
226     QString errorMsg;
227     if (receivedType) {
228         errorMsg = QString::fromLatin1("Unexpected reply signature: got \"%1\" (%4), "
229                                          "expected \"%2\" (%3)")
230                    .arg(QLatin1String(receivedSignature),
231                         QLatin1String(expectedSignature),
232                         QLatin1String(data.typeName()),
233                         QLatin1String(receivedType));
234     } else {
235         errorMsg = QString::fromLatin1("Unexpected reply signature: got \"%1\", "
236                                          "expected \"%2\" (%3)")
237                    .arg(QLatin1String(receivedSignature),
238                         QLatin1String(expectedSignature),
239                         QLatin1String(data.typeName()));
240     }
241
242     error = QDBusError(QDBusError::InvalidSignature, errorMsg);
243     data = QVariant();      // clear it
244 }
245
246 QT_END_NAMESPACE
247
248 #endif // QT_NO_DBUS