~ubuntu-branches/ubuntu/wily/qtbase-opensource-src/wily

« back to all changes in this revision

Viewing changes to src/dbus/qdbusmessage.cpp

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki
  • Date: 2013-02-05 12:46:17 UTC
  • Revision ID: package-import@ubuntu.com-20130205124617-c8jouts182j002fx
Tags: upstream-5.0.1+dfsg
ImportĀ upstreamĀ versionĀ 5.0.1+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/legal
 
5
**
 
6
** This file is part of the QtDBus module of the Qt Toolkit.
 
7
**
 
8
** $QT_BEGIN_LICENSE:LGPL$
 
9
** Commercial License Usage
 
10
** Licensees holding valid commercial Qt licenses may use this file in
 
11
** accordance with the commercial license agreement provided with the
 
12
** Software or, alternatively, in accordance with the terms contained in
 
13
** a written agreement between you and Digia.  For licensing terms and
 
14
** conditions see http://qt.digia.com/licensing.  For further information
 
15
** use the contact form at http://qt.digia.com/contact-us.
 
16
**
 
17
** GNU Lesser General Public License Usage
 
18
** Alternatively, this file may be used under the terms of the GNU Lesser
 
19
** General Public License version 2.1 as published by the Free Software
 
20
** Foundation and appearing in the file LICENSE.LGPL included in the
 
21
** packaging of this file.  Please review the following information to
 
22
** ensure the GNU Lesser General Public License version 2.1 requirements
 
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 
24
**
 
25
** In addition, as a special exception, Digia gives you certain additional
 
26
** rights.  These rights are described in the Digia Qt LGPL Exception
 
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
28
**
 
29
** GNU General Public License Usage
 
30
** Alternatively, this file may be used under the terms of the GNU
 
31
** General Public License version 3.0 as published by the Free Software
 
32
** Foundation and appearing in the file LICENSE.GPL included in the
 
33
** packaging of this file.  Please review the following information to
 
34
** ensure the GNU General Public License version 3.0 requirements will be
 
35
** met: http://www.gnu.org/copyleft/gpl.html.
 
36
**
 
37
**
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
 
 
42
#include "qdbusmessage.h"
 
43
#include "qdbusmessage_p.h"
 
44
 
 
45
#include <qdebug.h>
 
46
#include <qstringlist.h>
 
47
 
 
48
#include "qdbus_symbols_p.h"
 
49
 
 
50
#include "qdbusargument_p.h"
 
51
#include "qdbuserror.h"
 
52
#include "qdbusmetatype.h"
 
53
#include "qdbusconnection_p.h"
 
54
#include "qdbusutil_p.h"
 
55
 
 
56
#ifndef QT_NO_DBUS
 
57
 
 
58
QT_BEGIN_NAMESPACE
 
59
 
 
60
static inline const char *data(const QByteArray &arr)
 
61
{
 
62
    return arr.isEmpty() ? 0 : arr.constData();
 
63
}
 
64
 
 
65
QDBusMessagePrivate::QDBusMessagePrivate()
 
66
    : msg(0), reply(0), type(DBUS_MESSAGE_TYPE_INVALID),
 
67
      timeout(-1), localReply(0), ref(1), delayedReply(false), localMessage(false),
 
68
      parametersValidated(false), autoStartService(true)
 
69
{
 
70
}
 
71
 
 
72
QDBusMessagePrivate::~QDBusMessagePrivate()
 
73
{
 
74
    if (msg)
 
75
        q_dbus_message_unref(msg);
 
76
    if (reply)
 
77
        q_dbus_message_unref(reply);
 
78
    delete localReply;
 
79
}
 
80
 
 
81
/*!
 
82
    \since 4.3
 
83
     Returns the human-readable message associated with the error that was received.
 
84
*/
 
85
QString QDBusMessage::errorMessage() const
 
86
{
 
87
    if (d_ptr->type == ErrorMessage) {
 
88
        if (!d_ptr->message.isEmpty())
 
89
           return d_ptr->message;
 
90
        if (!d_ptr->arguments.isEmpty())
 
91
            return d_ptr->arguments.at(0).toString();
 
92
    }
 
93
    return QString();
 
94
}
 
95
 
 
96
/*!
 
97
    \internal
 
98
    Constructs a DBusMessage object from \a message. The returned value must be de-referenced
 
99
    with q_dbus_message_unref. The \a capabilities flags indicates which capabilities to use.
 
100
 
 
101
    The \a error object is set to indicate the error if anything went wrong with the
 
102
    marshalling. Usually, this error message will be placed in the reply, as if the call failed.
 
103
    The \a error pointer must not be null.
 
104
*/
 
105
DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message, QDBusConnection::ConnectionCapabilities capabilities,
 
106
                                                QDBusError *error)
 
107
{
 
108
    if (!qdbus_loadLibDBus()) {
 
109
        *error = QDBusError(QDBusError::Failed, QLatin1String("Could not open lidbus-1 library"));
 
110
        return 0;
 
111
    }
 
112
 
 
113
    DBusMessage *msg = 0;
 
114
    const QDBusMessagePrivate *d_ptr = message.d_ptr;
 
115
 
 
116
    switch (d_ptr->type) {
 
117
    case DBUS_MESSAGE_TYPE_INVALID:
 
118
        //qDebug() << "QDBusMessagePrivate::toDBusMessage" <<  "message is invalid";
 
119
        break;
 
120
    case DBUS_MESSAGE_TYPE_METHOD_CALL:
 
121
        // only service and interface can be empty -> path and name must not be empty
 
122
        if (!d_ptr->parametersValidated) {
 
123
            if (!QDBusUtil::checkBusName(d_ptr->service, QDBusUtil::EmptyAllowed, error))
 
124
                return 0;
 
125
            if (!QDBusUtil::checkObjectPath(d_ptr->path, QDBusUtil::EmptyNotAllowed, error))
 
126
                return 0;
 
127
            if (!QDBusUtil::checkInterfaceName(d_ptr->interface, QDBusUtil::EmptyAllowed, error))
 
128
                return 0;
 
129
            if (!QDBusUtil::checkMemberName(d_ptr->name, QDBusUtil::EmptyNotAllowed, error, "method"))
 
130
                return 0;
 
131
        }
 
132
 
 
133
        msg = q_dbus_message_new_method_call(data(d_ptr->service.toUtf8()), d_ptr->path.toUtf8(),
 
134
                                             data(d_ptr->interface.toUtf8()), d_ptr->name.toUtf8());
 
135
        q_dbus_message_set_auto_start( msg, d_ptr->autoStartService );
 
136
        break;
 
137
    case DBUS_MESSAGE_TYPE_METHOD_RETURN:
 
138
        msg = q_dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
 
139
        if (!d_ptr->localMessage) {
 
140
            q_dbus_message_set_destination(msg, q_dbus_message_get_sender(d_ptr->reply));
 
141
            q_dbus_message_set_reply_serial(msg, q_dbus_message_get_serial(d_ptr->reply));
 
142
        }
 
143
        break;
 
144
    case DBUS_MESSAGE_TYPE_ERROR:
 
145
        // error name can't be empty
 
146
        if (!d_ptr->parametersValidated
 
147
            && !QDBusUtil::checkErrorName(d_ptr->name, QDBusUtil::EmptyNotAllowed, error))
 
148
            return 0;
 
149
 
 
150
        msg = q_dbus_message_new(DBUS_MESSAGE_TYPE_ERROR);
 
151
        q_dbus_message_set_error_name(msg, d_ptr->name.toUtf8());
 
152
        if (!d_ptr->localMessage) {
 
153
            q_dbus_message_set_destination(msg, q_dbus_message_get_sender(d_ptr->reply));
 
154
            q_dbus_message_set_reply_serial(msg, q_dbus_message_get_serial(d_ptr->reply));
 
155
        }
 
156
        break;
 
157
    case DBUS_MESSAGE_TYPE_SIGNAL:
 
158
        // nothing can be empty here
 
159
        if (!d_ptr->parametersValidated) {
 
160
            if (!QDBusUtil::checkObjectPath(d_ptr->path, QDBusUtil::EmptyNotAllowed, error))
 
161
                return 0;
 
162
            if (!QDBusUtil::checkInterfaceName(d_ptr->interface, QDBusUtil::EmptyAllowed, error))
 
163
                return 0;
 
164
            if (!QDBusUtil::checkMemberName(d_ptr->name, QDBusUtil::EmptyNotAllowed, error, "method"))
 
165
                return 0;
 
166
        }
 
167
 
 
168
        msg = q_dbus_message_new_signal(d_ptr->path.toUtf8(), d_ptr->interface.toUtf8(),
 
169
                                        d_ptr->name.toUtf8());
 
170
        break;
 
171
    default:
 
172
        Q_ASSERT(false);
 
173
        break;
 
174
    }
 
175
 
 
176
    // if we got here, the parameters validated
 
177
    // and since the message parameters cannot be changed once the message is created
 
178
    // we can record this fact
 
179
    d_ptr->parametersValidated = true;
 
180
 
 
181
    QDBusMarshaller marshaller(capabilities);
 
182
    QVariantList::ConstIterator it =  d_ptr->arguments.constBegin();
 
183
    QVariantList::ConstIterator cend = d_ptr->arguments.constEnd();
 
184
    q_dbus_message_iter_init_append(msg, &marshaller.iterator);
 
185
    if (!d_ptr->message.isEmpty())
 
186
        // prepend the error message
 
187
        marshaller.append(d_ptr->message);
 
188
    for ( ; it != cend; ++it)
 
189
        marshaller.appendVariantInternal(*it);
 
190
 
 
191
    // check if everything is ok
 
192
    if (marshaller.ok)
 
193
        return msg;
 
194
 
 
195
    // not ok;
 
196
    q_dbus_message_unref(msg);
 
197
    *error = QDBusError(QDBusError::Failed, QLatin1String("Marshalling failed: ") + marshaller.errorString);
 
198
    return 0;
 
199
}
 
200
 
 
201
/*
 
202
struct DBusMessage
 
203
{
 
204
    DBusAtomic refcount;
 
205
    DBusHeader header;
 
206
    DBusString body;
 
207
    char byte_order;
 
208
    unsigned int locked : 1;
 
209
DBUS_DISABLE_CHECKS
 
210
    unsigned int in_cache : 1;
 
211
#endif
 
212
    DBusList *size_counters;
 
213
    long size_counter_delta;
 
214
    dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS;
 
215
    DBusDataSlotList slot_list;
 
216
#ifndef DBUS_DISABLE_CHECKS
 
217
    int generation;
 
218
#endif
 
219
};
 
220
*/
 
221
 
 
222
/*!
 
223
    \internal
 
224
    Constructs a QDBusMessage by parsing the given DBusMessage object.
 
225
*/
 
226
QDBusMessage QDBusMessagePrivate::fromDBusMessage(DBusMessage *dmsg, QDBusConnection::ConnectionCapabilities capabilities)
 
227
{
 
228
    QDBusMessage message;
 
229
    if (!dmsg)
 
230
        return message;
 
231
 
 
232
    message.d_ptr->type = q_dbus_message_get_type(dmsg);
 
233
    message.d_ptr->path = QString::fromUtf8(q_dbus_message_get_path(dmsg));
 
234
    message.d_ptr->interface = QString::fromUtf8(q_dbus_message_get_interface(dmsg));
 
235
    message.d_ptr->name = message.d_ptr->type == DBUS_MESSAGE_TYPE_ERROR ?
 
236
                      QString::fromUtf8(q_dbus_message_get_error_name(dmsg)) :
 
237
                      QString::fromUtf8(q_dbus_message_get_member(dmsg));
 
238
    message.d_ptr->service = QString::fromUtf8(q_dbus_message_get_sender(dmsg));
 
239
    message.d_ptr->signature = QString::fromUtf8(q_dbus_message_get_signature(dmsg));
 
240
    message.d_ptr->msg = q_dbus_message_ref(dmsg);
 
241
 
 
242
    QDBusDemarshaller demarshaller(capabilities);
 
243
    demarshaller.message = q_dbus_message_ref(dmsg);
 
244
    if (q_dbus_message_iter_init(demarshaller.message, &demarshaller.iterator))
 
245
        while (!demarshaller.atEnd())
 
246
            message << demarshaller.toVariantInternal();
 
247
    return message;
 
248
}
 
249
 
 
250
bool QDBusMessagePrivate::isLocal(const QDBusMessage &message)
 
251
{
 
252
    return message.d_ptr->localMessage;
 
253
}
 
254
 
 
255
QDBusMessage QDBusMessagePrivate::makeLocal(const QDBusConnectionPrivate &conn,
 
256
                                            const QDBusMessage &asSent)
 
257
{
 
258
    // simulate the message being sent to the bus and then received back
 
259
    // the only field that the bus sets when delivering the message
 
260
    // (as opposed to the message as we send it), is the sender
 
261
    // so we simply set the sender to our unique name
 
262
 
 
263
    // determine if we are carrying any complex types
 
264
    QString computedSignature;
 
265
    QVariantList::ConstIterator it = asSent.d_ptr->arguments.constBegin();
 
266
    QVariantList::ConstIterator end = asSent.d_ptr->arguments.constEnd();
 
267
    for ( ; it != end; ++it) {
 
268
        int id = it->userType();
 
269
        const char *signature = QDBusMetaType::typeToSignature(id);
 
270
        if ((id != QVariant::StringList && id != QVariant::ByteArray &&
 
271
             qstrlen(signature) != 1) || id == qMetaTypeId<QDBusVariant>()) {
 
272
            // yes, we are
 
273
            // we must marshall and demarshall again so as to create QDBusArgument
 
274
            // entries for the complex types
 
275
            QDBusError error;
 
276
            DBusMessage *message = toDBusMessage(asSent, conn.capabilities, &error);
 
277
            if (!message) {
 
278
                // failed to marshall, so it's a call error
 
279
                return QDBusMessage::createError(error);
 
280
            }
 
281
 
 
282
            q_dbus_message_set_sender(message, conn.baseService.toUtf8());
 
283
 
 
284
            QDBusMessage retval = fromDBusMessage(message, conn.capabilities);
 
285
            retval.d_ptr->localMessage = true;
 
286
            q_dbus_message_unref(message);
 
287
            if (retval.d_ptr->service.isEmpty())
 
288
                retval.d_ptr->service = conn.baseService;
 
289
            return retval;
 
290
        } else {
 
291
            computedSignature += QLatin1String(signature);
 
292
        }
 
293
    }
 
294
 
 
295
    // no complex types seen
 
296
    // optimize by using the variant list itself
 
297
    QDBusMessage retval;
 
298
    QDBusMessagePrivate *d = retval.d_ptr;
 
299
    d->arguments = asSent.d_ptr->arguments;
 
300
    d->path = asSent.d_ptr->path;
 
301
    d->interface = asSent.d_ptr->interface;
 
302
    d->name = asSent.d_ptr->name;
 
303
    d->message = asSent.d_ptr->message;
 
304
    d->type = asSent.d_ptr->type;
 
305
 
 
306
    d->service = conn.baseService;
 
307
    d->signature = computedSignature;
 
308
    d->localMessage = true;
 
309
    return retval;
 
310
}
 
311
 
 
312
QDBusMessage QDBusMessagePrivate::makeLocalReply(const QDBusConnectionPrivate &conn,
 
313
                                                 const QDBusMessage &callMsg)
 
314
{
 
315
    // simulate the reply (return or error) message being sent to the bus and
 
316
    // then received back.
 
317
    if (callMsg.d_ptr->localReply)
 
318
        return makeLocal(conn, *callMsg.d_ptr->localReply);
 
319
    return QDBusMessage();      // failed
 
320
}
 
321
 
 
322
/*!
 
323
    \class QDBusMessage
 
324
    \inmodule QtDBus
 
325
    \since 4.2
 
326
 
 
327
    \brief The QDBusMessage class represents one message sent or
 
328
    received over the D-Bus bus.
 
329
 
 
330
    This object can represent any of the four different types of
 
331
    messages (MessageType) that can occur on the bus:
 
332
 
 
333
    \list
 
334
      \li Method calls
 
335
      \li Method return values
 
336
      \li Signal emissions
 
337
      \li Error codes
 
338
    \endlist
 
339
 
 
340
    Objects of this type are created with the static createError(),
 
341
    createMethodCall() and createSignal() functions. Use the
 
342
    QDBusConnection::send() function to send the messages.
 
343
*/
 
344
 
 
345
/*!
 
346
    \enum QDBusMessage::MessageType
 
347
    The possible message types:
 
348
 
 
349
    \value MethodCallMessage    a message representing an outgoing or incoming method call
 
350
    \value SignalMessage        a message representing an outgoing or incoming signal emission
 
351
    \value ReplyMessage         a message representing the return values of a method call
 
352
    \value ErrorMessage         a message representing an error condition in response to a method call
 
353
    \value InvalidMessage       an invalid message: this is never set on messages received from D-Bus
 
354
*/
 
355
 
 
356
/*!
 
357
    Constructs a new DBus message with the given \a path, \a interface
 
358
    and \a name, representing a signal emission.
 
359
 
 
360
    A DBus signal is emitted from one application and is received by
 
361
    all applications that are listening for that signal from that
 
362
    interface.
 
363
 
 
364
    The QDBusMessage object that is returned can be sent using the
 
365
    QDBusConnection::send() function.
 
366
*/
 
367
QDBusMessage QDBusMessage::createSignal(const QString &path, const QString &interface,
 
368
                                        const QString &name)
 
369
{
 
370
    QDBusMessage message;
 
371
    message.d_ptr->type = DBUS_MESSAGE_TYPE_SIGNAL;
 
372
    message.d_ptr->path = path;
 
373
    message.d_ptr->interface = interface;
 
374
    message.d_ptr->name = name;
 
375
 
 
376
    return message;
 
377
}
 
378
 
 
379
/*!
 
380
    Constructs a new DBus message representing a method call.
 
381
    A method call always informs its destination address
 
382
    (\a service, \a path, \a interface and \a method).
 
383
 
 
384
    The DBus bus allows calling a method on a given remote object without specifying the
 
385
    destination interface, if the method name is unique. However, if two interfaces on the
 
386
    remote object export the same method name, the result is undefined (one of the two may be
 
387
    called or an error may be returned).
 
388
 
 
389
    When using DBus in a peer-to-peer context (i.e., not on a bus), the \a service parameter is
 
390
    optional.
 
391
 
 
392
    The QDBusInterface class provides a simpler abstraction to synchronous
 
393
    method calling.
 
394
 
 
395
    This function returns a QDBusMessage object that can be sent with
 
396
    QDBusConnection::call().
 
397
*/
 
398
QDBusMessage QDBusMessage::createMethodCall(const QString &service, const QString &path,
 
399
                                            const QString &interface, const QString &method)
 
400
{
 
401
    QDBusMessage message;
 
402
    message.d_ptr->type = DBUS_MESSAGE_TYPE_METHOD_CALL;
 
403
    message.d_ptr->service = service;
 
404
    message.d_ptr->path = path;
 
405
    message.d_ptr->interface = interface;
 
406
    message.d_ptr->name = method;
 
407
 
 
408
    return message;
 
409
}
 
410
 
 
411
/*!
 
412
    Constructs a new DBus message representing an error,
 
413
    with the given \a name and \a msg.
 
414
*/
 
415
QDBusMessage QDBusMessage::createError(const QString &name, const QString &msg)
 
416
{
 
417
    QDBusMessage error;
 
418
    error.d_ptr->type = DBUS_MESSAGE_TYPE_ERROR;
 
419
    error.d_ptr->name = name;
 
420
    error.d_ptr->message = msg;
 
421
 
 
422
    return error;
 
423
}
 
424
 
 
425
/*!
 
426
    \fn QDBusMessage QDBusMessage::createError(const QDBusError &error)
 
427
 
 
428
    Constructs a new DBus message representing the given \a error.
 
429
*/
 
430
 
 
431
/*!
 
432
  \fn QDBusMessage QDBusMessage::createError(QDBusError::ErrorType type, const QString &msg)
 
433
 
 
434
  Constructs a new DBus message for the error type \a type using
 
435
  the message \a msg. Returns the DBus message.
 
436
*/
 
437
 
 
438
/*!
 
439
    \fn QDBusMessage QDBusMessage::createReply(const QList<QVariant> &arguments) const
 
440
 
 
441
    Constructs a new DBus message representing a reply, with the given
 
442
    \a arguments.
 
443
*/
 
444
QDBusMessage QDBusMessage::createReply(const QVariantList &arguments) const
 
445
{
 
446
    QDBusMessage reply;
 
447
    reply.setArguments(arguments);
 
448
    reply.d_ptr->type = DBUS_MESSAGE_TYPE_METHOD_RETURN;
 
449
    if (d_ptr->msg)
 
450
        reply.d_ptr->reply = q_dbus_message_ref(d_ptr->msg);
 
451
    if (d_ptr->localMessage) {
 
452
        reply.d_ptr->localMessage = true;
 
453
        d_ptr->localReply = new QDBusMessage(reply); // keep an internal copy
 
454
    }
 
455
 
 
456
    // the reply must have a msg or be a local-loop optimization
 
457
    Q_ASSERT(reply.d_ptr->reply || reply.d_ptr->localMessage);
 
458
    return reply;
 
459
}
 
460
 
 
461
/*!
 
462
    Constructs a new DBus message representing an error reply message,
 
463
    with the given \a name and \a msg.
 
464
*/
 
465
QDBusMessage QDBusMessage::createErrorReply(const QString name, const QString &msg) const
 
466
{
 
467
    QDBusMessage reply = QDBusMessage::createError(name, msg);
 
468
    if (d_ptr->msg)
 
469
        reply.d_ptr->reply = q_dbus_message_ref(d_ptr->msg);
 
470
    if (d_ptr->localMessage) {
 
471
        reply.d_ptr->localMessage = true;
 
472
        d_ptr->localReply = new QDBusMessage(reply); // keep an internal copy
 
473
    }
 
474
 
 
475
    // the reply must have a msg or be a local-loop optimization
 
476
    Q_ASSERT(reply.d_ptr->reply || reply.d_ptr->localMessage);
 
477
    return reply;
 
478
}
 
479
 
 
480
/*!
 
481
   \fn QDBusMessage QDBusMessage::createReply(const QVariant &argument) const
 
482
 
 
483
    Constructs a new DBus message representing a reply, with the
 
484
    given \a argument.
 
485
*/
 
486
 
 
487
/*!
 
488
    \fn QDBusMessage QDBusMessage::createErrorReply(const QDBusError &error) const
 
489
 
 
490
    Constructs a new DBus message representing an error reply message,
 
491
    from the given \a error object.
 
492
*/
 
493
 
 
494
/*!
 
495
  \fn QDBusMessage QDBusMessage::createErrorReply(QDBusError::ErrorType type, const QString &msg) const
 
496
 
 
497
  Constructs a new DBus reply message for the error type \a type using
 
498
  the message \a msg. Returns the DBus message.
 
499
*/
 
500
QDBusMessage QDBusMessage::createErrorReply(QDBusError::ErrorType atype, const QString &amsg) const
 
501
{
 
502
    QDBusMessage msg = createErrorReply(QDBusError::errorString(atype), amsg);
 
503
    msg.d_ptr->parametersValidated = true;
 
504
    return msg;
 
505
}
 
506
 
 
507
 
 
508
/*!
 
509
    Constructs an empty, invalid QDBusMessage object.
 
510
 
 
511
    \sa createError(), createMethodCall(), createSignal()
 
512
*/
 
513
QDBusMessage::QDBusMessage()
 
514
{
 
515
    d_ptr = new QDBusMessagePrivate;
 
516
}
 
517
 
 
518
/*!
 
519
    Constructs a copy of the object given by \a other.
 
520
 
 
521
    Note: QDBusMessage objects are shared. Modifications made to the
 
522
    copy will affect the original one as well. See setDelayedReply()
 
523
    for more information.
 
524
*/
 
525
QDBusMessage::QDBusMessage(const QDBusMessage &other)
 
526
{
 
527
    d_ptr = other.d_ptr;
 
528
    d_ptr->ref.ref();
 
529
}
 
530
 
 
531
/*!
 
532
    Disposes of the object and frees any resources that were being held.
 
533
*/
 
534
QDBusMessage::~QDBusMessage()
 
535
{
 
536
    if (!d_ptr->ref.deref())
 
537
        delete d_ptr;
 
538
}
 
539
 
 
540
/*!
 
541
    Copies the contents of the object given by \a other.
 
542
 
 
543
    Note: QDBusMessage objects are shared. Modifications made to the
 
544
    copy will affect the original one as well. See setDelayedReply()
 
545
    for more information.
 
546
*/
 
547
QDBusMessage &QDBusMessage::operator=(const QDBusMessage &other)
 
548
{
 
549
    qAtomicAssign(d_ptr, other.d_ptr);
 
550
    return *this;
 
551
}
 
552
 
 
553
/*!
 
554
    Returns the name of the service or the bus address of the remote method call.
 
555
*/
 
556
QString QDBusMessage::service() const
 
557
{
 
558
    return d_ptr->service;
 
559
}
 
560
 
 
561
/*!
 
562
    Returns the path of the object that this message is being sent to (in the case of a
 
563
    method call) or being received from (for a signal).
 
564
*/
 
565
QString QDBusMessage::path() const
 
566
{
 
567
    return d_ptr->path;
 
568
}
 
569
 
 
570
/*!
 
571
    Returns the interface of the method being called (in the case of a method call) or of
 
572
    the signal being received from.
 
573
*/
 
574
QString QDBusMessage::interface() const
 
575
{
 
576
    return d_ptr->interface;
 
577
}
 
578
 
 
579
/*!
 
580
    Returns the name of the signal that was emitted or the name of the method that was called.
 
581
*/
 
582
QString QDBusMessage::member() const
 
583
{
 
584
    if (d_ptr->type != ErrorMessage)
 
585
        return d_ptr->name;
 
586
    return QString();
 
587
}
 
588
 
 
589
/*!
 
590
    Returns the name of the error that was received.
 
591
*/
 
592
QString QDBusMessage::errorName() const
 
593
{
 
594
    if (d_ptr->type == ErrorMessage)
 
595
        return d_ptr->name;
 
596
    return QString();
 
597
}
 
598
 
 
599
/*!
 
600
    Returns the signature of the signal that was received or for the output arguments
 
601
    of a method call.
 
602
*/
 
603
QString QDBusMessage::signature() const
 
604
{
 
605
    return d_ptr->signature;
 
606
}
 
607
 
 
608
/*!
 
609
    Returns the flag that indicates if this message should see a reply
 
610
    or not. This is only meaningful for \l {MethodCallMessage}{method
 
611
    call messages}: any other kind of message cannot have replies and
 
612
    this function will always return false for them.
 
613
*/
 
614
bool QDBusMessage::isReplyRequired() const
 
615
{
 
616
    if (!d_ptr->msg)
 
617
        return d_ptr->localMessage; // if it's a local message, reply is required
 
618
    return !q_dbus_message_get_no_reply(d_ptr->msg);
 
619
}
 
620
 
 
621
/*!
 
622
    Sets whether the message will be replied later (if \a enable is
 
623
    true) or if an automatic reply should be generated by QtDBus
 
624
    (if \a enable is false).
 
625
 
 
626
    In D-Bus, all method calls must generate a reply to the caller, unless the
 
627
    caller explicitly indicates otherwise (see isReplyRequired()). QtDBus
 
628
    automatically generates such replies for any slots being called, but it
 
629
    also allows slots to indicate whether they will take responsibility
 
630
    of sending the reply at a later time, after the function has finished
 
631
    processing.
 
632
 
 
633
    \sa {Delayed Replies}
 
634
*/
 
635
void QDBusMessage::setDelayedReply(bool enable) const
 
636
{
 
637
    d_ptr->delayedReply = enable;
 
638
}
 
639
 
 
640
/*!
 
641
    Returns the delayed reply flag, as set by setDelayedReply(). By default, this
 
642
    flag is false, which means QtDBus will generate automatic replies
 
643
    when necessary.
 
644
*/
 
645
bool QDBusMessage::isDelayedReply() const
 
646
{
 
647
    return d_ptr->delayedReply;
 
648
}
 
649
 
 
650
/*!
 
651
    Sets the auto start flag to \a enable. This flag only makes sense
 
652
    for method call messages, where it tells the D-Bus server to
 
653
    either auto start the service responsible for the service name, or
 
654
    not to auto start it.
 
655
 
 
656
    By default this flag is true, i.e. a service is autostarted.
 
657
    This means:
 
658
 
 
659
    When the service that this method call is sent to is already
 
660
    running, the method call is sent to it. If the service is not
 
661
    running yet, the D-Bus daemon is requested to autostart the
 
662
    service that is assigned to this service name. This is
 
663
    handled by .service files that are placed in a directory known
 
664
    to the D-Bus server. These files then each contain a service
 
665
    name and the path to a program that should be executed when
 
666
    this service name is requested.
 
667
 
 
668
    \since 4.7
 
669
*/
 
670
void QDBusMessage::setAutoStartService(bool enable)
 
671
{
 
672
    d_ptr->autoStartService = enable;
 
673
}
 
674
 
 
675
/*!
 
676
    Returns the auto start flag, as set by setAutoStartService(). By default, this
 
677
    flag is true, which means QtDBus will auto start a service, if it is
 
678
    not running already.
 
679
 
 
680
    \sa setAutoStartService()
 
681
 
 
682
    \since 4.7
 
683
*/
 
684
bool QDBusMessage::autoStartService() const
 
685
{
 
686
    return d_ptr->autoStartService;
 
687
}
 
688
 
 
689
/*!
 
690
    Sets the arguments that are going to be sent over D-Bus to \a arguments. Those
 
691
    will be the arguments to a method call or the parameters in the signal.
 
692
 
 
693
    \sa arguments()
 
694
*/
 
695
void QDBusMessage::setArguments(const QList<QVariant> &arguments)
 
696
{
 
697
    // FIXME: should we detach?
 
698
    d_ptr->arguments = arguments;
 
699
}
 
700
 
 
701
/*!
 
702
    Returns the list of arguments that are going to be sent or were received from
 
703
    D-Bus.
 
704
*/
 
705
QList<QVariant> QDBusMessage::arguments() const
 
706
{
 
707
    return d_ptr->arguments;
 
708
}
 
709
 
 
710
/*!
 
711
    Appends the argument \a arg to the list of arguments to be sent over D-Bus in
 
712
    a method call or signal emission.
 
713
*/
 
714
 
 
715
QDBusMessage &QDBusMessage::operator<<(const QVariant &arg)
 
716
{
 
717
    // FIXME: should we detach?
 
718
    d_ptr->arguments.append(arg);
 
719
    return *this;
 
720
}
 
721
 
 
722
/*!
 
723
    Returns the message type.
 
724
*/
 
725
QDBusMessage::MessageType QDBusMessage::type() const
 
726
{
 
727
    switch (d_ptr->type) {
 
728
    case DBUS_MESSAGE_TYPE_METHOD_CALL:
 
729
        return MethodCallMessage;
 
730
    case DBUS_MESSAGE_TYPE_METHOD_RETURN:
 
731
        return ReplyMessage;
 
732
    case DBUS_MESSAGE_TYPE_ERROR:
 
733
        return ErrorMessage;
 
734
    case DBUS_MESSAGE_TYPE_SIGNAL:
 
735
        return SignalMessage;
 
736
    default:
 
737
        break;
 
738
    }
 
739
    return InvalidMessage;
 
740
}
 
741
 
 
742
/*!
 
743
    Sends the message without waiting for a reply. This is suitable
 
744
    for errors, signals, and return values as well as calls whose
 
745
    return values are not necessary.
 
746
 
 
747
    Returns true if the message was queued successfully;
 
748
    otherwise returns false.
 
749
 
 
750
    \sa QDBusConnection::send()
 
751
*/
 
752
#ifndef QT_NO_DEBUG_STREAM
 
753
static QDebug operator<<(QDebug dbg, QDBusMessage::MessageType t)
 
754
{
 
755
    switch (t)
 
756
    {
 
757
    case QDBusMessage::MethodCallMessage:
 
758
        return dbg << "MethodCall";
 
759
    case QDBusMessage::ReplyMessage:
 
760
        return dbg << "MethodReturn";
 
761
    case QDBusMessage::SignalMessage:
 
762
        return dbg << "Signal";
 
763
    case QDBusMessage::ErrorMessage:
 
764
        return dbg << "Error";
 
765
    default:
 
766
        return dbg << "Invalid";
 
767
    }
 
768
}
 
769
 
 
770
static void debugVariantList(QDebug dbg, const QVariantList &list)
 
771
{
 
772
    bool first = true;
 
773
    QVariantList::ConstIterator it = list.constBegin();
 
774
    QVariantList::ConstIterator end = list.constEnd();
 
775
    for ( ; it != end; ++it) {
 
776
        if (!first)
 
777
            dbg.nospace() << ", ";
 
778
        dbg.nospace() << qPrintable(QDBusUtil::argumentToString(*it));
 
779
        first = false;
 
780
    }
 
781
}
 
782
 
 
783
QDebug operator<<(QDebug dbg, const QDBusMessage &msg)
 
784
{
 
785
    dbg.nospace() << "QDBusMessage(type=" << msg.type()
 
786
                  << ", service=" << msg.service();
 
787
    if (msg.type() == QDBusMessage::MethodCallMessage ||
 
788
        msg.type() == QDBusMessage::SignalMessage)
 
789
        dbg.nospace() << ", path=" << msg.path()
 
790
                      << ", interface=" << msg.interface()
 
791
                      << ", member=" << msg.member();
 
792
    if (msg.type() == QDBusMessage::ErrorMessage)
 
793
        dbg.nospace() << ", error name=" << msg.errorName()
 
794
                      << ", error message=" << msg.errorMessage();
 
795
    dbg.nospace() << ", signature=" << msg.signature()
 
796
                  << ", contents=(";
 
797
    debugVariantList(dbg, msg.arguments());
 
798
    dbg.nospace() << ") )";
 
799
    return dbg.space();
 
800
}
 
801
#endif
 
802
 
 
803
QT_END_NAMESPACE
 
804
 
 
805
#endif // QT_NO_DBUS