From 38be0d13830efd2d98281c645c3a60afe05ffece Mon Sep 17 00:00:00 2001 From: Qt by Nokia Date: Wed, 27 Apr 2011 12:05:43 +0200 Subject: Initial import from the monolithic Qt. This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12 --- src/dbus/dbus.pro | 90 ++ src/dbus/qdbus_symbols.cpp | 118 ++ src/dbus/qdbus_symbols_p.h | 375 +++++ src/dbus/qdbusabstractadaptor.cpp | 384 ++++++ src/dbus/qdbusabstractadaptor.h | 80 ++ src/dbus/qdbusabstractadaptor_p.h | 138 ++ src/dbus/qdbusabstractinterface.cpp | 776 +++++++++++ src/dbus/qdbusabstractinterface.h | 165 +++ src/dbus/qdbusabstractinterface_p.h | 104 ++ src/dbus/qdbusargument.cpp | 1362 +++++++++++++++++++ src/dbus/qdbusargument.h | 405 ++++++ src/dbus/qdbusargument_p.h | 222 +++ src/dbus/qdbusconnection.cpp | 1154 ++++++++++++++++ src/dbus/qdbusconnection.h | 199 +++ src/dbus/qdbusconnection_p.h | 347 +++++ src/dbus/qdbusconnectioninterface.cpp | 419 ++++++ src/dbus/qdbusconnectioninterface.h | 132 ++ src/dbus/qdbusconnectionmanager_p.h | 88 ++ src/dbus/qdbuscontext.cpp | 208 +++ src/dbus/qdbuscontext.h | 87 ++ src/dbus/qdbuscontext_p.h | 83 ++ src/dbus/qdbusdemarshaller.cpp | 364 +++++ src/dbus/qdbuserror.cpp | 368 +++++ src/dbus/qdbuserror.h | 126 ++ src/dbus/qdbusextratypes.cpp | 242 ++++ src/dbus/qdbusextratypes.h | 193 +++ src/dbus/qdbusintegrator.cpp | 2411 +++++++++++++++++++++++++++++++++ src/dbus/qdbusintegrator_p.h | 162 +++ src/dbus/qdbusinterface.cpp | 328 +++++ src/dbus/qdbusinterface.h | 82 ++ src/dbus/qdbusinterface_p.h | 82 ++ src/dbus/qdbusinternalfilters.cpp | 503 +++++++ src/dbus/qdbusintrospection.cpp | 429 ++++++ src/dbus/qdbusintrospection_p.h | 180 +++ src/dbus/qdbusmacros.h | 70 + src/dbus/qdbusmarshaller.cpp | 573 ++++++++ src/dbus/qdbusmessage.cpp | 805 +++++++++++ src/dbus/qdbusmessage.h | 132 ++ src/dbus/qdbusmessage_p.h | 110 ++ src/dbus/qdbusmetaobject.cpp | 703 ++++++++++ src/dbus/qdbusmetaobject_p.h | 94 ++ src/dbus/qdbusmetatype.cpp | 483 +++++++ src/dbus/qdbusmetatype.h | 100 ++ src/dbus/qdbusmetatype_p.h | 75 + src/dbus/qdbusmisc.cpp | 201 +++ src/dbus/qdbuspendingcall.cpp | 539 ++++++++ src/dbus/qdbuspendingcall.h | 125 ++ src/dbus/qdbuspendingcall_p.h | 141 ++ src/dbus/qdbuspendingreply.cpp | 281 ++++ src/dbus/qdbuspendingreply.h | 217 +++ src/dbus/qdbusreply.cpp | 248 ++++ src/dbus/qdbusreply.h | 199 +++ src/dbus/qdbusserver.cpp | 140 ++ src/dbus/qdbusserver.h | 84 ++ src/dbus/qdbusservicewatcher.cpp | 381 ++++++ src/dbus/qdbusservicewatcher.h | 106 ++ src/dbus/qdbusthreaddebug_p.h | 235 ++++ src/dbus/qdbusunixfiledescriptor.cpp | 316 +++++ src/dbus/qdbusunixfiledescriptor.h | 103 ++ src/dbus/qdbusutil.cpp | 568 ++++++++ src/dbus/qdbusutil_p.h | 167 +++ src/dbus/qdbusxmlgenerator.cpp | 308 +++++ src/dbus/qdbusxmlparser.cpp | 378 ++++++ src/dbus/qdbusxmlparser_p.h | 88 ++ 64 files changed, 20376 insertions(+) create mode 100644 src/dbus/dbus.pro create mode 100644 src/dbus/qdbus_symbols.cpp create mode 100644 src/dbus/qdbus_symbols_p.h create mode 100644 src/dbus/qdbusabstractadaptor.cpp create mode 100644 src/dbus/qdbusabstractadaptor.h create mode 100644 src/dbus/qdbusabstractadaptor_p.h create mode 100644 src/dbus/qdbusabstractinterface.cpp create mode 100644 src/dbus/qdbusabstractinterface.h create mode 100644 src/dbus/qdbusabstractinterface_p.h create mode 100644 src/dbus/qdbusargument.cpp create mode 100644 src/dbus/qdbusargument.h create mode 100644 src/dbus/qdbusargument_p.h create mode 100644 src/dbus/qdbusconnection.cpp create mode 100644 src/dbus/qdbusconnection.h create mode 100644 src/dbus/qdbusconnection_p.h create mode 100644 src/dbus/qdbusconnectioninterface.cpp create mode 100644 src/dbus/qdbusconnectioninterface.h create mode 100644 src/dbus/qdbusconnectionmanager_p.h create mode 100644 src/dbus/qdbuscontext.cpp create mode 100644 src/dbus/qdbuscontext.h create mode 100644 src/dbus/qdbuscontext_p.h create mode 100644 src/dbus/qdbusdemarshaller.cpp create mode 100644 src/dbus/qdbuserror.cpp create mode 100644 src/dbus/qdbuserror.h create mode 100644 src/dbus/qdbusextratypes.cpp create mode 100644 src/dbus/qdbusextratypes.h create mode 100644 src/dbus/qdbusintegrator.cpp create mode 100644 src/dbus/qdbusintegrator_p.h create mode 100644 src/dbus/qdbusinterface.cpp create mode 100644 src/dbus/qdbusinterface.h create mode 100644 src/dbus/qdbusinterface_p.h create mode 100644 src/dbus/qdbusinternalfilters.cpp create mode 100644 src/dbus/qdbusintrospection.cpp create mode 100644 src/dbus/qdbusintrospection_p.h create mode 100644 src/dbus/qdbusmacros.h create mode 100644 src/dbus/qdbusmarshaller.cpp create mode 100644 src/dbus/qdbusmessage.cpp create mode 100644 src/dbus/qdbusmessage.h create mode 100644 src/dbus/qdbusmessage_p.h create mode 100644 src/dbus/qdbusmetaobject.cpp create mode 100644 src/dbus/qdbusmetaobject_p.h create mode 100644 src/dbus/qdbusmetatype.cpp create mode 100644 src/dbus/qdbusmetatype.h create mode 100644 src/dbus/qdbusmetatype_p.h create mode 100644 src/dbus/qdbusmisc.cpp create mode 100644 src/dbus/qdbuspendingcall.cpp create mode 100644 src/dbus/qdbuspendingcall.h create mode 100644 src/dbus/qdbuspendingcall_p.h create mode 100644 src/dbus/qdbuspendingreply.cpp create mode 100644 src/dbus/qdbuspendingreply.h create mode 100644 src/dbus/qdbusreply.cpp create mode 100644 src/dbus/qdbusreply.h create mode 100644 src/dbus/qdbusserver.cpp create mode 100644 src/dbus/qdbusserver.h create mode 100644 src/dbus/qdbusservicewatcher.cpp create mode 100644 src/dbus/qdbusservicewatcher.h create mode 100644 src/dbus/qdbusthreaddebug_p.h create mode 100644 src/dbus/qdbusunixfiledescriptor.cpp create mode 100644 src/dbus/qdbusunixfiledescriptor.h create mode 100644 src/dbus/qdbusutil.cpp create mode 100644 src/dbus/qdbusutil_p.h create mode 100644 src/dbus/qdbusxmlgenerator.cpp create mode 100644 src/dbus/qdbusxmlparser.cpp create mode 100644 src/dbus/qdbusxmlparser_p.h (limited to 'src/dbus') diff --git a/src/dbus/dbus.pro b/src/dbus/dbus.pro new file mode 100644 index 0000000000..08c9ea1fb2 --- /dev/null +++ b/src/dbus/dbus.pro @@ -0,0 +1,90 @@ +TARGET = QtDBus +QPRO_PWD = $$PWD +QT = core \ + xml +CONFIG += link_pkgconfig +DEFINES += QT_BUILD_DBUS_LIB \ + DBUS_API_SUBJECT_TO_CHANGE +QMAKE_CXXFLAGS += $$QT_CFLAGS_DBUS +contains(QT_CONFIG, dbus-linked) { + LIBS_PRIVATE += $$QT_LIBS_DBUS + DEFINES += QT_LINKED_LIBDBUS +} + +# INCLUDEPATH += . +unix|win32-g++* { + QMAKE_PKGCONFIG_DESCRIPTION = Qt \ + DBus \ + module + QMAKE_PKGCONFIG_REQUIRES = QtCore \ + QtXml +} +win32 { + wince*:LIBS_PRIVATE += -lws2 + else:LIBS_PRIVATE += -lws2_32 \ + -ladvapi32 \ + -lnetapi32 \ + -luser32 + CONFIG(debug, debug|release):LIBS_PRIVATE += -ldbus-1d + else:LIBS_PRIVATE += -ldbus-1 +} +include(../qbase.pri) +PUB_HEADERS = qdbusargument.h \ + qdbusconnectioninterface.h \ + qdbusmacros.h \ + qdbuserror.h \ + qdbusextratypes.h \ + qdbusmessage.h \ + qdbusserver.h \ + qdbusconnection.h \ + qdbusabstractinterface.h \ + qdbusinterface.h \ + qdbusabstractadaptor.h \ + qdbusreply.h \ + qdbusmetatype.h \ + qdbuspendingcall.h \ + qdbuspendingreply.h \ + qdbuscontext.h +HEADERS += $$PUB_HEADERS \ + qdbusconnection_p.h \ + qdbusmessage_p.h \ + qdbusinterface_p.h \ + qdbusxmlparser_p.h \ + qdbusabstractadaptor_p.h \ + qdbusargument_p.h \ + qdbusutil_p.h \ + qdbusabstractinterface_p.h \ + qdbuscontext_p.h \ + qdbusthreaddebug_p.h \ + qdbusintegrator_p.h \ + qdbuspendingcall_p.h \ + qdbus_symbols_p.h \ + qdbusservicewatcher.h \ + qdbusunixfiledescriptor.h +SOURCES += qdbusconnection.cpp \ + qdbusconnectioninterface.cpp \ + qdbuserror.cpp \ + qdbusintegrator.cpp \ + qdbusmessage.cpp \ + qdbusserver.cpp \ + qdbusabstractinterface.cpp \ + qdbusinterface.cpp \ + qdbusxmlparser.cpp \ + qdbusutil.cpp \ + qdbusintrospection.cpp \ + qdbusabstractadaptor.cpp \ + qdbusinternalfilters.cpp \ + qdbusmetaobject.cpp \ + qdbusxmlgenerator.cpp \ + qdbusmisc.cpp \ + qdbusargument.cpp \ + qdbusreply.cpp \ + qdbusmetatype.cpp \ + qdbusextratypes.cpp \ + qdbusmarshaller.cpp \ + qdbuscontext.cpp \ + qdbuspendingcall.cpp \ + qdbuspendingreply.cpp \ + qdbus_symbols.cpp \ + qdbusservicewatcher.cpp \ + qdbusunixfiledescriptor.cpp diff --git a/src/dbus/qdbus_symbols.cpp b/src/dbus/qdbus_symbols.cpp new file mode 100644 index 0000000000..a62d52e04e --- /dev/null +++ b/src/dbus/qdbus_symbols.cpp @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDBus module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include + +#ifndef QT_NO_DBUS + +QT_BEGIN_NAMESPACE + +void *qdbus_resolve_me(const char *name); + +#if !defined QT_LINKED_LIBDBUS + +static QLibrary *qdbus_libdbus = 0; + +void qdbus_unloadLibDBus() +{ + delete qdbus_libdbus; + qdbus_libdbus = 0; +} + +bool qdbus_loadLibDBus() +{ + static volatile bool triedToLoadLibrary = false; +#ifndef QT_NO_THREAD + QMutexLocker locker(QMutexPool::globalInstanceGet((void *)&qdbus_resolve_me)); +#endif + QLibrary *&lib = qdbus_libdbus; + if (triedToLoadLibrary) + return lib && lib->isLoaded(); + + lib = new QLibrary; + triedToLoadLibrary = true; + + static int majorversions[] = { 3, 2, -1 }; + lib->unload(); + lib->setFileName(QLatin1String("dbus-1")); + for (uint i = 0; i < sizeof(majorversions) / sizeof(majorversions[0]); ++i) { + lib->setFileNameAndVersion(lib->fileName(), majorversions[i]); + if (lib->load() && lib->resolve("dbus_connection_open_private")) + return true; + + lib->unload(); + } + + delete lib; + lib = 0; + return false; +} + +void *qdbus_resolve_conditionally(const char *name) +{ + if (qdbus_loadLibDBus()) + return qdbus_libdbus->resolve(name); + return 0; +} + +void *qdbus_resolve_me(const char *name) +{ + void *ptr = 0; + if (!qdbus_loadLibDBus()) + qFatal("Cannot find libdbus-1 in your system to resolve symbol '%s'.", name); + + ptr = qdbus_libdbus->resolve(name); + if (!ptr) + qFatal("Cannot resolve '%s' in your libdbus-1.", name); + + return ptr; +} + +Q_DESTRUCTOR_FUNCTION(qdbus_unloadLibDBus) + +#endif // QT_LINKED_LIBDBUS + +QT_END_NAMESPACE + +#endif // QT_NO_DBUS diff --git a/src/dbus/qdbus_symbols_p.h b/src/dbus/qdbus_symbols_p.h new file mode 100644 index 0000000000..039657ef0b --- /dev/null +++ b/src/dbus/qdbus_symbols_p.h @@ -0,0 +1,375 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDBus module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the public API. This header file may +// change from version to version without notice, or even be +// removed. +// +// We mean it. +// +// + +#ifndef QDBUS_SYMBOLS_P_H +#define QDBUS_SYMBOLS_P_H + +#include +#include + +#ifndef QT_NO_DBUS + +QT_BEGIN_NAMESPACE + +#if !defined QT_LINKED_LIBDBUS + +void *qdbus_resolve_conditionally(const char *name); // doesn't print a warning +void *qdbus_resolve_me(const char *name); // prints a warning +bool qdbus_loadLibDBus(); + +# define DEFINEFUNC(ret, func, args, argcall, funcret) \ + typedef ret (* _q_PTR_##func) args; \ + static inline ret q_##func args \ + { \ + static _q_PTR_##func ptr; \ + if (!ptr) \ + ptr = (_q_PTR_##func) qdbus_resolve_me(#func); \ + funcret ptr argcall; \ + } + +#else // defined QT_LINKED_LIBDBUS + +inline bool qdbus_loadLibDBus() { return true; } + +# define DEFINEFUNC(ret, func, args, argcall, funcret) \ + static inline ret q_##func args { funcret func argcall; } + +#endif // defined QT_LINKED_LIBDBUS + +/* dbus-bus.h */ +DEFINEFUNC(void, dbus_bus_add_match, (DBusConnection *connection, + const char *rule, + DBusError *error), + (connection, rule, error), ) +DEFINEFUNC(void, dbus_bus_remove_match, (DBusConnection *connection, + const char *rule, + DBusError *error), + (connection, rule, error), ) +DEFINEFUNC(dbus_bool_t, dbus_bus_register,(DBusConnection *connection, + DBusError *error), + (connection, error), return) +DEFINEFUNC(DBusConnection *, dbus_bus_get_private, (DBusBusType type, + DBusError *error), + (type, error), return) +DEFINEFUNC(const char*, dbus_bus_get_unique_name, (DBusConnection *connection), + (connection), return) + +/* dbus-connection.h */ +DEFINEFUNC(dbus_bool_t , dbus_connection_add_filter, (DBusConnection *connection, + DBusHandleMessageFunction function, + void *user_data, + DBusFreeFunction free_data_function), + (connection, function, user_data, free_data_function), return) +DEFINEFUNC(void , dbus_connection_close, (DBusConnection *connection), + (connection), return) +DEFINEFUNC(DBusDispatchStatus , dbus_connection_dispatch, (DBusConnection *connection), + (connection), return) +DEFINEFUNC(DBusDispatchStatus , dbus_connection_get_dispatch_status, (DBusConnection *connection), + (connection), return) +DEFINEFUNC(dbus_bool_t , dbus_connection_get_is_connected, (DBusConnection *connection), + (connection), return) +DEFINEFUNC(DBusConnection* , dbus_connection_open_private, (const char *address, + DBusError *error), + (address, error), return) +DEFINEFUNC(DBusConnection* , dbus_connection_ref, (DBusConnection *connection), + (connection), return) +DEFINEFUNC(dbus_bool_t , dbus_connection_send, (DBusConnection *connection, + DBusMessage *message, + dbus_uint32_t *client_serial), + (connection, message, client_serial), return) +DEFINEFUNC(dbus_bool_t , dbus_connection_send_with_reply, (DBusConnection *connection, + DBusMessage *message, + DBusPendingCall **pending_return, + int timeout_milliseconds), + (connection, message, pending_return, timeout_milliseconds), return) +DEFINEFUNC(DBusMessage * , dbus_connection_send_with_reply_and_block, (DBusConnection *connection, + DBusMessage *message, + int timeout_milliseconds, + DBusError *error), + (connection, message, timeout_milliseconds, error), return) +DEFINEFUNC(void , dbus_connection_set_exit_on_disconnect, (DBusConnection *connection, + dbus_bool_t exit_on_disconnect), + (connection, exit_on_disconnect), ) +DEFINEFUNC(dbus_bool_t , dbus_connection_set_timeout_functions, (DBusConnection *connection, + DBusAddTimeoutFunction add_function, + DBusRemoveTimeoutFunction remove_function, + DBusTimeoutToggledFunction toggled_function, + void *data, + DBusFreeFunction free_data_function), + (connection, add_function, remove_function, toggled_function, data, free_data_function), return) +DEFINEFUNC(dbus_bool_t , dbus_connection_set_watch_functions, (DBusConnection *connection, + DBusAddWatchFunction add_function, + DBusRemoveWatchFunction remove_function, + DBusWatchToggledFunction toggled_function, + void *data, + DBusFreeFunction free_data_function), + (connection, add_function, remove_function, toggled_function, data, free_data_function), return) +DEFINEFUNC(void , dbus_connection_set_wakeup_main_function, (DBusConnection *connection, + DBusWakeupMainFunction wakeup_main_function, + void *data, + DBusFreeFunction free_data_function), + (connection, wakeup_main_function, data, free_data_function), ) +DEFINEFUNC(void , dbus_connection_set_dispatch_status_function, (DBusConnection *connection, + DBusDispatchStatusFunction function, + void *data, + DBusFreeFunction free_data_function), + (connection, function, data, free_data_function), ) + +DEFINEFUNC(void , dbus_connection_unref, (DBusConnection *connection), + (connection), ) +DEFINEFUNC(dbus_bool_t , dbus_timeout_get_enabled, (DBusTimeout *timeout), + (timeout), return) +DEFINEFUNC(int , dbus_timeout_get_interval, (DBusTimeout *timeout), + (timeout), return) +DEFINEFUNC(dbus_bool_t , dbus_timeout_handle, (DBusTimeout *timeout), + (timeout), return) + +DEFINEFUNC(dbus_bool_t , dbus_watch_get_enabled, (DBusWatch *watch), + (watch), return) +DEFINEFUNC(int , dbus_watch_get_fd, (DBusWatch *watch), + (watch), return) +DEFINEFUNC(unsigned int , dbus_watch_get_flags, (DBusWatch *watch), + (watch), return) +DEFINEFUNC(dbus_bool_t , dbus_watch_handle, (DBusWatch *watch, + unsigned int flags), + (watch, flags), return) + +/* dbus-errors.h */ +DEFINEFUNC(void , dbus_error_free, (DBusError *error), + (error), ) +DEFINEFUNC(void , dbus_error_init, (DBusError *error), + (error), ) +DEFINEFUNC(dbus_bool_t , dbus_error_is_set, (const DBusError *error), + (error), return) + +/* dbus-memory.h */ +DEFINEFUNC(void , dbus_free, (void *memory), (memory), ) + +/* dbus-message.h */ +DEFINEFUNC(DBusMessage* , dbus_message_copy, (const DBusMessage *message), + (message), return) +DEFINEFUNC(dbus_bool_t , dbus_message_get_auto_start, (DBusMessage *message), + (message), return) +DEFINEFUNC(const char* , dbus_message_get_error_name, (DBusMessage *message), + (message), return) +DEFINEFUNC(const char* , dbus_message_get_interface, (DBusMessage *message), + (message), return) +DEFINEFUNC(const char* , dbus_message_get_member, (DBusMessage *message), + (message), return) +DEFINEFUNC(dbus_bool_t , dbus_message_get_no_reply, (DBusMessage *message), + (message), return) +DEFINEFUNC(const char* , dbus_message_get_path, (DBusMessage *message), + (message), return) +DEFINEFUNC(const char* , dbus_message_get_sender, (DBusMessage *message), + (message), return) +DEFINEFUNC(dbus_uint32_t , dbus_message_get_serial, (DBusMessage *message), + (message), return) +DEFINEFUNC(const char* , dbus_message_get_signature, (DBusMessage *message), + (message), return) +DEFINEFUNC(int , dbus_message_get_type, (DBusMessage *message), + (message), return) +DEFINEFUNC(dbus_bool_t , dbus_message_iter_append_basic, (DBusMessageIter *iter, + int type, + const void *value), + (iter, type, value), return) +DEFINEFUNC(dbus_bool_t , dbus_message_iter_append_fixed_array, (DBusMessageIter *iter, + int element_type, + const void *value, + int n_elements), + (iter, element_type, value, n_elements), return) +DEFINEFUNC(dbus_bool_t , dbus_message_iter_close_container, (DBusMessageIter *iter, + DBusMessageIter *sub), + (iter, sub), return) +DEFINEFUNC(int , dbus_message_iter_get_arg_type, (DBusMessageIter *iter), + (iter), return) +DEFINEFUNC(void , dbus_message_iter_get_basic, (DBusMessageIter *iter, + void *value), + (iter, value), ) +DEFINEFUNC(int , dbus_message_iter_get_element_type, (DBusMessageIter *iter), + (iter), return) +DEFINEFUNC(void , dbus_message_iter_get_fixed_array, (DBusMessageIter *iter, + void *value, + int *n_elements), + (iter, value, n_elements), return) +DEFINEFUNC(char* , dbus_message_iter_get_signature, (DBusMessageIter *iter), + (iter), return) +DEFINEFUNC(dbus_bool_t , dbus_message_iter_init, (DBusMessage *message, + DBusMessageIter *iter), + (message, iter), return) +DEFINEFUNC(void , dbus_message_iter_init_append, (DBusMessage *message, + DBusMessageIter *iter), + (message, iter), return) +DEFINEFUNC(dbus_bool_t , dbus_message_iter_next, (DBusMessageIter *iter), + (iter), return) +DEFINEFUNC(dbus_bool_t , dbus_message_iter_open_container, (DBusMessageIter *iter, + int type, + const char *contained_signature, + DBusMessageIter *sub), + (iter, type, contained_signature, sub), return) +DEFINEFUNC(void , dbus_message_iter_recurse, (DBusMessageIter *iter, + DBusMessageIter *sub), + (iter, sub), ) +DEFINEFUNC(DBusMessage* , dbus_message_new, (int message_type), + (message_type), return) +DEFINEFUNC(DBusMessage* , dbus_message_new_method_call, (const char *bus_name, + const char *path, + const char *interface, + const char *method), + (bus_name, path, interface, method), return) +DEFINEFUNC(DBusMessage* , dbus_message_new_signal, (const char *path, + const char *interface, + const char *name), + (path, interface, name), return) +DEFINEFUNC(DBusMessage* , dbus_message_ref, (DBusMessage *message), + (message), return) +DEFINEFUNC(void , dbus_message_set_auto_start, (DBusMessage *message, + dbus_bool_t auto_start), + (message, auto_start), return) +DEFINEFUNC(dbus_bool_t , dbus_message_set_destination, (DBusMessage *message, + const char *destination), + (message, destination), return) +DEFINEFUNC(dbus_bool_t , dbus_message_set_error_name, (DBusMessage *message, + const char *name), + (message, name), return) +DEFINEFUNC(void , dbus_message_set_no_reply, (DBusMessage *message, + dbus_bool_t no_reply), + (message, no_reply), return) +DEFINEFUNC(dbus_bool_t , dbus_message_set_path, (DBusMessage *message, + const char *object_path), + (message, object_path), return) +DEFINEFUNC(dbus_bool_t , dbus_message_set_reply_serial, (DBusMessage *message, + dbus_uint32_t reply_serial), + (message, reply_serial), return) +DEFINEFUNC(dbus_bool_t , dbus_message_set_sender, (DBusMessage *message, + const char *sender), + (message, sender), return) +DEFINEFUNC(void , dbus_message_unref, (DBusMessage *message), + (message), ) + +/* dbus-misc.h */ +DEFINEFUNC(void , dbus_get_version , (int *major_version_p, + int *minor_version_p, + int *micro_version_p), + (major_version_p, minor_version_p, micro_version_p), ) + +/* dbus-pending-call.h */ +DEFINEFUNC(dbus_bool_t , dbus_pending_call_set_notify, (DBusPendingCall *pending, + DBusPendingCallNotifyFunction function, + void *user_data, + DBusFreeFunction free_user_data), + (pending, function, user_data, free_user_data), return) +DEFINEFUNC(void , dbus_pending_call_block, (DBusPendingCall *pending), + (pending), ) +DEFINEFUNC(void , dbus_pending_call_cancel, (DBusPendingCall *pending), + (pending), ) +DEFINEFUNC(dbus_bool_t , dbus_pending_call_get_completed, (DBusPendingCall *pending), + (pending), return) +DEFINEFUNC(DBusMessage* , dbus_pending_call_steal_reply, (DBusPendingCall *pending), + (pending), return) +DEFINEFUNC(void , dbus_pending_call_unref, (DBusPendingCall *pending), + (pending), return) + +/* dbus-server.h */ +DEFINEFUNC(dbus_bool_t , dbus_server_allocate_data_slot, (dbus_int32_t *slot_p), + (slot_p), return) +DEFINEFUNC(void , dbus_server_disconnect, (DBusServer *server), + (server), ) +DEFINEFUNC(char* , dbus_server_get_address, (DBusServer *server), + (server), return) +DEFINEFUNC(dbus_bool_t , dbus_server_get_is_connected, (DBusServer *server), + (server), return) +DEFINEFUNC(DBusServer* , dbus_server_listen, (const char *address, + DBusError *error), + (address, error), return) +DEFINEFUNC(dbus_bool_t , dbus_server_set_data, (DBusServer *server, + int slot, + void *data, + DBusFreeFunction free_data_func), + (server, slot, data, free_data_func), return) +DEFINEFUNC(void , dbus_server_set_new_connection_function, (DBusServer *server, + DBusNewConnectionFunction function, + void *data, + DBusFreeFunction free_data_function), + (server, function, data, free_data_function), ) +DEFINEFUNC(dbus_bool_t , dbus_server_set_timeout_functions, (DBusServer *server, + DBusAddTimeoutFunction add_function, + DBusRemoveTimeoutFunction remove_function, + DBusTimeoutToggledFunction toggled_function, + void *data, + DBusFreeFunction free_data_function), + (server, add_function, remove_function, toggled_function, data, free_data_function), return) +DEFINEFUNC(dbus_bool_t , dbus_server_set_watch_functions, (DBusServer *server, + DBusAddWatchFunction add_function, + DBusRemoveWatchFunction remove_function, + DBusWatchToggledFunction toggled_function, + void *data, + DBusFreeFunction free_data_function), + (server, add_function, remove_function, toggled_function, data, free_data_function), return) +DEFINEFUNC(void , dbus_server_unref, (DBusServer *server), + (server), ) + +/* dbus-thread.h */ +DEFINEFUNC(dbus_bool_t , dbus_threads_init_default, (), (), return) + + +/* D-Bus 1.4 symbols */ +#if !defined(QT_LINKED_LIBDBUS) || (DBUS_VERSION >= 0x010400) +DEFINEFUNC(dbus_bool_t , dbus_connection_can_send_type , (DBusConnection *connection, + int type), + (connection, type), return) +#endif + +QT_END_NAMESPACE + +#endif // QT_NO_DBUS +#endif // QDBUS_SYMBOLS_P_H diff --git a/src/dbus/qdbusabstractadaptor.cpp b/src/dbus/qdbusabstractadaptor.cpp new file mode 100644 index 0000000000..c75bbaa639 --- /dev/null +++ b/src/dbus/qdbusabstractadaptor.cpp @@ -0,0 +1,384 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDBus module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdbusabstractadaptor.h" + +#include +#include +#include +#include +#include + +#include "qdbusconnection.h" + +#include "qdbusconnection_p.h" // for qDBusParametersForMethod +#include "qdbusabstractadaptor_p.h" +#include "qdbusmetatype_p.h" + +#ifndef QT_NO_DBUS + +QT_BEGIN_NAMESPACE + +QDBusAdaptorConnector *qDBusFindAdaptorConnector(QObject *obj) +{ + if (!obj) + return 0; + const QObjectList &children = obj->children(); + QObjectList::ConstIterator it = children.constBegin(); + QObjectList::ConstIterator end = children.constEnd(); + for ( ; it != end; ++it) { + QDBusAdaptorConnector *connector = qobject_cast(*it); + if (connector) { + connector->polish(); + return connector; + } + } + return 0; +} + +QDBusAdaptorConnector *qDBusFindAdaptorConnector(QDBusAbstractAdaptor *adaptor) +{ + return qDBusFindAdaptorConnector(adaptor->parent()); +} + +QDBusAdaptorConnector *qDBusCreateAdaptorConnector(QObject *obj) +{ + QDBusAdaptorConnector *connector = qDBusFindAdaptorConnector(obj); + if (connector) + return connector; + return new QDBusAdaptorConnector(obj); +} + +QString QDBusAbstractAdaptorPrivate::retrieveIntrospectionXml(QDBusAbstractAdaptor *adaptor) +{ + return adaptor->d_func()->xml; +} + +void QDBusAbstractAdaptorPrivate::saveIntrospectionXml(QDBusAbstractAdaptor *adaptor, + const QString &xml) +{ + adaptor->d_func()->xml = xml; +} + +/*! + \class QDBusAbstractAdaptor + \inmodule QtDBus + \since 4.2 + + \brief The QDBusAbstractAdaptor class is the base class of D-Bus adaptor classes. + + The QDBusAbstractAdaptor class is the starting point for all objects intending to provide + interfaces to the external world using D-Bus. This is accomplished by attaching a one or more + classes derived from QDBusAbstractAdaptor to a normal QObject and then registering that QObject + with QDBusConnection::registerObject. QDBusAbstractAdaptor objects are intended to be + light-weight wrappers, mostly just relaying calls into the real object (its parent) and the + signals from it. + + Each QDBusAbstractAdaptor-derived class should define the D-Bus interface it is implementing + using the Q_CLASSINFO macro in the class definition. Note that only one interface can be + exposed in this way. + + QDBusAbstractAdaptor uses the standard QObject mechanism of signals, slots and properties to + determine what signals, methods and properties to export to the bus. Any signal emitted by + QDBusAbstractAdaptor-derived classes will be automatically be relayed through any D-Bus + connections the object is registered on. + + Classes derived from QDBusAbstractAdaptor must be created on the heap using the \a new operator + and must not be deleted by the user (they will be deleted automatically when the object they are + connected to is also deleted). + + \sa {usingadaptors.html}{Using adaptors}, QDBusConnection +*/ + +/*! + Constructs a QDBusAbstractAdaptor with \a obj as the parent object. +*/ +QDBusAbstractAdaptor::QDBusAbstractAdaptor(QObject* obj) + : QObject(*new QDBusAbstractAdaptorPrivate, obj) +{ + QDBusAdaptorConnector *connector = qDBusCreateAdaptorConnector(obj); + + connector->waitingForPolish = true; + QMetaObject::invokeMethod(connector, "polish", Qt::QueuedConnection); +} + +/*! + Destroys the adaptor. + + \warning Adaptors are destroyed automatically when the real object they refer to is + destroyed. Do not delete the adaptors yourself. +*/ +QDBusAbstractAdaptor::~QDBusAbstractAdaptor() +{ +} + +/*! + Toggles automatic signal relaying from the real object (see object()). + + Automatic signal relaying consists of signal-to-signal connection of the signals on the parent + that have the exact same method signatue in both classes. + + If \a enable is set to true, connect the signals; if set to false, disconnect all signals. +*/ +void QDBusAbstractAdaptor::setAutoRelaySignals(bool enable) +{ + const QMetaObject *us = metaObject(); + const QMetaObject *them = parent()->metaObject(); + bool connected = false; + for (int idx = staticMetaObject.methodCount(); idx < us->methodCount(); ++idx) { + QMetaMethod mm = us->method(idx); + + if (mm.methodType() != QMetaMethod::Signal) + continue; + + // try to connect/disconnect to a signal on the parent that has the same method signature + QByteArray sig = QMetaObject::normalizedSignature(mm.signature()); + if (them->indexOfSignal(sig) == -1) + continue; + sig.prepend(QSIGNAL_CODE + '0'); + parent()->disconnect(sig, this, sig); + if (enable) + connected = connect(parent(), sig, sig) || connected; + } + d_func()->autoRelaySignals = connected; +} + +/*! + Returns true if automatic signal relaying from the real object (see object()) is enabled, + otherwiser returns false. + + \sa setAutoRelaySignals() +*/ +bool QDBusAbstractAdaptor::autoRelaySignals() const +{ + return d_func()->autoRelaySignals; +} + +QDBusAdaptorConnector::QDBusAdaptorConnector(QObject *obj) + : QObject(obj), waitingForPolish(false) +{ +} + +QDBusAdaptorConnector::~QDBusAdaptorConnector() +{ +} + +void QDBusAdaptorConnector::addAdaptor(QDBusAbstractAdaptor *adaptor) +{ + // find the interface name + const QMetaObject *mo = adaptor->metaObject(); + int ciid = mo->indexOfClassInfo(QCLASSINFO_DBUS_INTERFACE); + if (ciid != -1) { + QMetaClassInfo mci = mo->classInfo(ciid); + if (*mci.value()) { + // find out if this interface exists first + const char *interface = mci.value(); + AdaptorMap::Iterator it = qLowerBound(adaptors.begin(), adaptors.end(), + QByteArray(interface)); + if (it != adaptors.end() && qstrcmp(interface, it->interface) == 0) { + // exists. Replace it (though it's probably the same) + if (it->adaptor != adaptor) { + // reconnect the signals + disconnectAllSignals(it->adaptor); + connectAllSignals(adaptor); + } + it->adaptor = adaptor; + } else { + // create a new one + AdaptorData entry; + entry.interface = interface; + entry.adaptor = adaptor; + adaptors << entry; + + // connect the adaptor's signals to our relaySlot slot + connectAllSignals(adaptor); + } + } + } +} + +void QDBusAdaptorConnector::disconnectAllSignals(QObject *obj) +{ + QMetaObject::disconnect(obj, -1, this, metaObject()->methodOffset()); +} + +void QDBusAdaptorConnector::connectAllSignals(QObject *obj) +{ + QMetaObject::connect(obj, -1, this, metaObject()->methodOffset(), Qt::DirectConnection); +} + +void QDBusAdaptorConnector::polish() +{ + if (!waitingForPolish) + return; // avoid working multiple times if multiple adaptors were added + + waitingForPolish = false; + const QObjectList &objs = parent()->children(); + QObjectList::ConstIterator it = objs.constBegin(); + QObjectList::ConstIterator end = objs.constEnd(); + for ( ; it != end; ++it) { + QDBusAbstractAdaptor *adaptor = qobject_cast(*it); + if (adaptor) + addAdaptor(adaptor); + } + + // sort the adaptor list + qSort(adaptors); +} + +void QDBusAdaptorConnector::relaySlot(void **argv) +{ + QObjectPrivate *d = static_cast(d_ptr.data()); + relay(d->currentSender->sender, d->currentSender->signal, argv); +} + +void QDBusAdaptorConnector::relay(QObject *senderObj, int lastSignalIdx, void **argv) +{ + if (lastSignalIdx < QObject::staticMetaObject.methodCount()) + // QObject signal (destroyed(QObject *)) -- ignore + return; + + const QMetaObject *senderMetaObject = senderObj->metaObject(); + QMetaMethod mm = senderMetaObject->method(lastSignalIdx); + + QObject *realObject = senderObj; + if (qobject_cast(senderObj)) + // it's an adaptor, so the real object is in fact its parent + realObject = realObject->parent(); + + // break down the parameter list + QList types; + int inputCount = qDBusParametersForMethod(mm, types); + if (inputCount == -1) + // invalid signal signature + // qDBusParametersForMethod has already complained + return; + if (inputCount + 1 != types.count() || + types.at(inputCount) == QDBusMetaTypeId::message) { + // invalid signal signature + // qDBusParametersForMethod has not yet complained about this one + qWarning("QDBusAbstractAdaptor: Cannot relay signal %s::%s", + senderMetaObject->className(), mm.signature()); + return; + } + + QVariantList args; + for (int i = 1; i < types.count(); ++i) + args << QVariant(types.at(i), argv[i]); + + // now emit the signal with all the information + emit relaySignal(realObject, senderMetaObject, lastSignalIdx, args); +} + +// our Meta Object +// modify carefully: this has been hand-edited! +// the relaySlot slot has local ID 0 (we use this when calling QMetaObject::connect) +// it also gets called with the void** array + +static const uint qt_meta_data_QDBusAdaptorConnector[] = { + // content: + 1, // revision + 0, // classname + 0, 0, // classinfo + 3, 10, // methods + 0, 0, // properties + 0, 0, // enums/sets + + // slots: signature, parameters, type, tag, flags + 106, 22, 22, 22, 0x0a, + 118, 22, 22, 22, 0x0a, + + // signals: signature, parameters, type, tag, flags + 47, 23, 22, 22, 0x05, + + 0 // eod +}; + +static const char qt_meta_stringdata_QDBusAdaptorConnector[] = { + "QDBusAdaptorConnector\0\0obj,metaobject,sid,args\0" + "relaySignal(QObject*,const QMetaObject*,int,QVariantList)\0\0relaySlot()\0" + "polish()\0" +}; + +const QMetaObject QDBusAdaptorConnector::staticMetaObject = { + { &QObject::staticMetaObject, qt_meta_stringdata_QDBusAdaptorConnector, + qt_meta_data_QDBusAdaptorConnector, 0 } +}; + +const QMetaObject *QDBusAdaptorConnector::metaObject() const +{ + return &staticMetaObject; +} + +void *QDBusAdaptorConnector::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_QDBusAdaptorConnector)) + return static_cast(const_cast(this)); + return QObject::qt_metacast(_clname); +} + +int QDBusAdaptorConnector::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QObject::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: relaySlot(_a); break; // HAND EDIT: add the _a parameter + case 1: polish(); break; + case 2: relaySignal((*reinterpret_cast< QObject*(*)>(_a[1])),(*reinterpret_cast< const QMetaObject*(*)>(_a[2])),(*reinterpret_cast< int(*)>(_a[3])),(*reinterpret_cast< const QVariantList(*)>(_a[4]))); break; + } + _id -= 3; + } + return _id; +} + +// SIGNAL 0 +void QDBusAdaptorConnector::relaySignal(QObject * _t1, const QMetaObject * _t2, int _t3, const QVariantList & _t4) +{ + void *_a[] = { 0, const_cast(reinterpret_cast(&_t1)), const_cast(reinterpret_cast(&_t2)), const_cast(reinterpret_cast(&_t3)), const_cast(reinterpret_cast(&_t4)) }; + QMetaObject::activate(this, &staticMetaObject, 2, _a); +} + +QT_END_NAMESPACE + +#endif // QT_NO_DBUS diff --git a/src/dbus/qdbusabstractadaptor.h b/src/dbus/qdbusabstractadaptor.h new file mode 100644 index 0000000000..a9241a1f61 --- /dev/null +++ b/src/dbus/qdbusabstractadaptor.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDBus module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDBUSABSTRACTADAPTOR_H +#define QDBUSABSTRACTADAPTOR_H + +#include +#include + +#ifndef QT_NO_DBUS + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(DBus) + +class QDBusAbstractAdaptorPrivate; +class Q_DBUS_EXPORT QDBusAbstractAdaptor: public QObject +{ + Q_OBJECT +protected: + QDBusAbstractAdaptor(QObject *parent); + +public: + ~QDBusAbstractAdaptor(); + +protected: + void setAutoRelaySignals(bool enable); + bool autoRelaySignals() const; + +private: + Q_DECLARE_PRIVATE(QDBusAbstractAdaptor) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QT_NO_DBUS + +#endif diff --git a/src/dbus/qdbusabstractadaptor_p.h b/src/dbus/qdbusabstractadaptor_p.h new file mode 100644 index 0000000000..678fc2ddf6 --- /dev/null +++ b/src/dbus/qdbusabstractadaptor_p.h @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDBus module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the public API. This header file may +// change from version to version without notice, or even be +// removed. +// +// We mean it. +// +// + +#ifndef QDBUSABSTRACTADAPTORPRIVATE_H +#define QDBUSABSTRACTADAPTORPRIVATE_H + +#include + +#include +#include +#include +#include +#include +#include +#include "private/qobject_p.h" + +#define QCLASSINFO_DBUS_INTERFACE "D-Bus Interface" +#define QCLASSINFO_DBUS_INTROSPECTION "D-Bus Introspection" + +#ifndef QT_NO_DBUS + +QT_BEGIN_NAMESPACE + +class QDBusAbstractAdaptor; +class QDBusAdaptorConnector; +class QDBusAdaptorManager; +class QDBusConnectionPrivate; + +class QDBusAbstractAdaptorPrivate: public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QDBusAbstractAdaptor) +public: + QDBusAbstractAdaptorPrivate() : autoRelaySignals(false) {} + QString xml; + bool autoRelaySignals; + + static QString retrieveIntrospectionXml(QDBusAbstractAdaptor *adaptor); + static void saveIntrospectionXml(QDBusAbstractAdaptor *adaptor, const QString &xml); +}; + +class QDBusAdaptorConnector: public QObject +{ + Q_OBJECT_FAKE + +public: // typedefs + struct AdaptorData + { + const char *interface; + QDBusAbstractAdaptor *adaptor; + + inline bool operator<(const AdaptorData &other) const + { return QByteArray(interface) < other.interface; } + inline bool operator<(const QString &other) const + { return QLatin1String(interface) < other; } + inline bool operator<(const QByteArray &other) const + { return interface < other; } + }; + typedef QVector AdaptorMap; + +public: // methods + explicit QDBusAdaptorConnector(QObject *parent); + ~QDBusAdaptorConnector(); + + void addAdaptor(QDBusAbstractAdaptor *adaptor); + void connectAllSignals(QObject *object); + void disconnectAllSignals(QObject *object); + void relay(QObject *sender, int id, void **); + +//public slots: + void relaySlot(void **); + void polish(); + +protected: +//signals: + void relaySignal(QObject *obj, const QMetaObject *metaObject, int sid, const QVariantList &args); + +public: // member variables + AdaptorMap adaptors; + bool waitingForPolish : 1; +}; + +extern QDBusAdaptorConnector *qDBusFindAdaptorConnector(QObject *object); +extern QDBusAdaptorConnector *qDBusCreateAdaptorConnector(QObject *object); + +QT_END_NAMESPACE + +#endif // QT_NO_DBUS +#endif // QDBUSABSTRACTADAPTORPRIVATE_H diff --git a/src/dbus/qdbusabstractinterface.cpp b/src/dbus/qdbusabstractinterface.cpp new file mode 100644 index 0000000000..9e82c09ed0 --- /dev/null +++ b/src/dbus/qdbusabstractinterface.cpp @@ -0,0 +1,776 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDBus module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdbusabstractinterface.h" +#include "qdbusabstractinterface_p.h" + +#include + +#include "qdbusargument.h" +#include "qdbuspendingcall.h" +#include "qdbusmessage_p.h" +#include "qdbusmetaobject_p.h" +#include "qdbusmetatype_p.h" +#include "qdbusutil_p.h" + +#include + +#ifndef QT_NO_DBUS + +QT_BEGIN_NAMESPACE + +static QDBusError checkIfValid(const QString &service, const QString &path, + const QString &interface, bool isDynamic, bool isPeer) +{ + // We should be throwing exceptions here... oh well + QDBusError error; + + // dynamic interfaces (QDBusInterface) can have empty interfaces, but not service and object paths + // non-dynamic is the opposite: service and object paths can be empty, but not the interface + if (!isDynamic) { + // use assertion here because this should never happen, at all + Q_ASSERT_X(!interface.isEmpty(), "QDBusAbstractInterface", "Interface name cannot be empty"); + } + if (!QDBusUtil::checkBusName(service, (isDynamic && !isPeer) ? QDBusUtil::EmptyNotAllowed : QDBusUtil::EmptyAllowed, &error)) + return error; + if (!QDBusUtil::checkObjectPath(path, isDynamic ? QDBusUtil::EmptyNotAllowed : QDBusUtil::EmptyAllowed, &error)) + return error; + if (!QDBusUtil::checkInterfaceName(interface, QDBusUtil::EmptyAllowed, &error)) + return error; + + // no error + return QDBusError(); +} + +QDBusAbstractInterfacePrivate::QDBusAbstractInterfacePrivate(const QString &serv, + const QString &p, + const QString &iface, + const QDBusConnection& con, + bool isDynamic) + : connection(con), service(serv), path(p), interface(iface), + lastError(checkIfValid(serv, p, iface, isDynamic, (connectionPrivate() && + connectionPrivate()->mode == QDBusConnectionPrivate::PeerMode))), + isValid(!lastError.isValid()) +{ + if (!isValid) + return; + + if (!connection.isConnected()) { + lastError = QDBusError(QDBusError::Disconnected, + QLatin1String("Not connected to D-Bus server")); + } else if (!service.isEmpty()) { + currentOwner = connectionPrivate()->getNameOwner(service); // verify the name owner + if (currentOwner.isEmpty()) { + lastError = connectionPrivate()->lastError; + } + } +} + +bool QDBusAbstractInterfacePrivate::canMakeCalls() const +{ + // recheck only if we have a wildcard (i.e. empty) service or path + // if any are empty, set the error message according to QDBusUtil + if (service.isEmpty() && connectionPrivate()->mode != QDBusConnectionPrivate::PeerMode) + return QDBusUtil::checkBusName(service, QDBusUtil::EmptyNotAllowed, &lastError); + if (path.isEmpty()) + return QDBusUtil::checkObjectPath(path, QDBusUtil::EmptyNotAllowed, &lastError); + return true; +} + +void QDBusAbstractInterfacePrivate::property(const QMetaProperty &mp, QVariant &where) const +{ + if (!isValid || !canMakeCalls()) { // can't make calls + where.clear(); + return; + } + + // is this metatype registered? + const char *expectedSignature = ""; + if (mp.type() != 0xff) { + expectedSignature = QDBusMetaType::typeToSignature(where.userType()); + if (expectedSignature == 0) { + qWarning("QDBusAbstractInterface: type %s must be registered with QtDBus before it can be " + "used to read property %s.%s", + mp.typeName(), qPrintable(interface), mp.name()); + lastError = QDBusError(QDBusError::Failed, + QString::fromLatin1("Unregistered type %1 cannot be handled") + .arg(QLatin1String(mp.typeName()))); + where.clear(); + return; + } + } + + // try to read this property + QDBusMessage msg = QDBusMessage::createMethodCall(service, path, + QLatin1String(DBUS_INTERFACE_PROPERTIES), + QLatin1String("Get")); + QDBusMessagePrivate::setParametersValidated(msg, true); + msg << interface << QString::fromUtf8(mp.name()); + QDBusMessage reply = connection.call(msg, QDBus::Block); + + if (reply.type() != QDBusMessage::ReplyMessage) { + lastError = reply; + where.clear(); + return; + } + if (reply.signature() != QLatin1String("v")) { + QString errmsg = QLatin1String("Invalid signature `%1' in return from call to " + DBUS_INTERFACE_PROPERTIES); + lastError = QDBusError(QDBusError::InvalidSignature, errmsg.arg(reply.signature())); + where.clear(); + return; + } + + QByteArray foundSignature; + const char *foundType = 0; + QVariant value = qvariant_cast(reply.arguments().at(0)).variant(); + + if (value.userType() == where.userType() || mp.type() == 0xff + || (expectedSignature[0] == 'v' && expectedSignature[1] == '\0')) { + // simple match + where = value; + return; + } + + if (value.userType() == qMetaTypeId()) { + QDBusArgument arg = qvariant_cast(value); + + foundType = "user type"; + foundSignature = arg.currentSignature().toLatin1(); + if (foundSignature == expectedSignature) { + // signatures match, we can demarshall + QDBusMetaType::demarshall(arg, where.userType(), where.data()); + return; + } + } else { + foundType = value.typeName(); + foundSignature = QDBusMetaType::typeToSignature(value.userType()); + } + + // there was an error... + QString errmsg = QLatin1String("Unexpected `%1' (%2) when retrieving property `%3.%4' " + "(expected type `%5' (%6))"); + lastError = QDBusError(QDBusError::InvalidSignature, + errmsg.arg(QString::fromLatin1(foundType), + QString::fromLatin1(foundSignature), + interface, + QString::fromUtf8(mp.name()), + QString::fromLatin1(mp.typeName()), + QString::fromLatin1(expectedSignature))); + where.clear(); + return; +} + +bool QDBusAbstractInterfacePrivate::setProperty(const QMetaProperty &mp, const QVariant &value) +{ + if (!isValid || !canMakeCalls()) // can't make calls + return false; + + // send the value + QDBusMessage msg = QDBusMessage::createMethodCall(service, path, + QLatin1String(DBUS_INTERFACE_PROPERTIES), + QLatin1String("Set")); + QDBusMessagePrivate::setParametersValidated(msg, true); + msg << interface << QString::fromUtf8(mp.name()) << QVariant::fromValue(QDBusVariant(value)); + QDBusMessage reply = connection.call(msg, QDBus::Block); + + if (reply.type() != QDBusMessage::ReplyMessage) { + lastError = reply; + return false; + } + return true; +} + +void QDBusAbstractInterfacePrivate::_q_serviceOwnerChanged(const QString &name, + const QString &oldOwner, + const QString &newOwner) +{ + Q_UNUSED(oldOwner); + //qDebug() << "QDBusAbstractInterfacePrivate serviceOwnerChanged" << name << oldOwner << newOwner; + if (name == service) { + currentOwner = newOwner; + } +} + +QDBusAbstractInterfaceBase::QDBusAbstractInterfaceBase(QDBusAbstractInterfacePrivate &d, QObject *parent) + : QObject(d, parent) +{ +} + +int QDBusAbstractInterfaceBase::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + int saved_id = _id; + _id = QObject::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + + if (_c == QMetaObject::ReadProperty || _c == QMetaObject::WriteProperty) { + QMetaProperty mp = metaObject()->property(saved_id); + int &status = *reinterpret_cast(_a[2]); + QVariant &variant = *reinterpret_cast(_a[1]); + + if (_c == QMetaObject::WriteProperty) { + status = d_func()->setProperty(mp, variant) ? 1 : 0; + } else { + d_func()->property(mp, variant); + status = variant.isValid() ? 1 : 0; + } + _id = -1; + } + return _id; +} + +/*! + \class QDBusAbstractInterface + \inmodule QtDBus + \since 4.2 + + \brief The QDBusAbstractInterface class is the base class for all D-Bus interfaces in the QtDBus binding, allowing access to remote interfaces + + Generated-code classes also derive from QDBusAbstractInterface, + all methods described here are also valid for generated-code + classes. In addition to those described here, generated-code + classes provide member functions for the remote methods, which + allow for compile-time checking of the correct parameters and + return values, as well as property type-matching and signal + parameter-matching. + + \sa {qdbusxml2cpp.html}{The QDBus compiler}, QDBusInterface +*/ + +/*! + \internal + This is the constructor called from QDBusInterface::QDBusInterface. +*/ +QDBusAbstractInterface::QDBusAbstractInterface(QDBusAbstractInterfacePrivate &d, QObject *parent) + : QDBusAbstractInterfaceBase(d, parent) +{ + // keep track of the service owner + if (d.isValid && + d.connection.isConnected() + && !d.service.isEmpty() + && !d.service.startsWith(QLatin1Char(':'))) + d_func()->connection.connect(QLatin1String(DBUS_SERVICE_DBUS), // service + QString(), // path + QLatin1String(DBUS_INTERFACE_DBUS), // interface + QLatin1String("NameOwnerChanged"), + QStringList() << d.service, + QString(), // signature + this, SLOT(_q_serviceOwnerChanged(QString,QString,QString))); +} + +/*! + \internal + This is the constructor called from static classes derived from + QDBusAbstractInterface (i.e., those generated by dbusxml2cpp). +*/ +QDBusAbstractInterface::QDBusAbstractInterface(const QString &service, const QString &path, + const char *interface, const QDBusConnection &con, + QObject *parent) + : QDBusAbstractInterfaceBase(*new QDBusAbstractInterfacePrivate(service, path, QString::fromLatin1(interface), + con, false), parent) +{ + // keep track of the service owner + if (d_func()->isValid && + d_func()->connection.isConnected() + && !service.isEmpty() + && !service.startsWith(QLatin1Char(':'))) + d_func()->connection.connect(QLatin1String(DBUS_SERVICE_DBUS), // service + QString(), // path + QLatin1String(DBUS_INTERFACE_DBUS), // interface + QLatin1String("NameOwnerChanged"), + QStringList() << service, + QString(), //signature + this, SLOT(_q_serviceOwnerChanged(QString,QString,QString))); +} + +/*! + Releases this object's resources. +*/ +QDBusAbstractInterface::~QDBusAbstractInterface() +{ +} + +/*! + Returns true if this is a valid reference to a remote object. It returns false if + there was an error during the creation of this interface (for instance, if the remote + application does not exist). + + Note: when dealing with remote objects, it is not always possible to determine if it + exists when creating a QDBusInterface. +*/ +bool QDBusAbstractInterface::isValid() const +{ + return !d_func()->currentOwner.isEmpty(); +} + +/*! + Returns the connection this interface is assocated with. +*/ +QDBusConnection QDBusAbstractInterface::connection() const +{ + return d_func()->connection; +} + +/*! + Returns the name of the service this interface is associated with. +*/ +QString QDBusAbstractInterface::service() const +{ + return d_func()->service; +} + +/*! + Returns the object path that this interface is associated with. +*/ +QString QDBusAbstractInterface::path() const +{ + return d_func()->path; +} + +/*! + Returns the name of this interface. +*/ +QString QDBusAbstractInterface::interface() const +{ + return d_func()->interface; +} + +/*! + Returns the error the last operation produced, or an invalid error if the last operation did not + produce an error. +*/ +QDBusError QDBusAbstractInterface::lastError() const +{ + return d_func()->lastError; +} + +/*! + Places a call to the remote method specified by \a method on this interface, using \a args as + arguments. This function returns the message that was received as a reply, which can be a normal + QDBusMessage::ReplyMessage (indicating success) or QDBusMessage::ErrorMessage (if the call + failed). The \a mode parameter specifies how this call should be placed. + + If the call succeeds, lastError() will be cleared; otherwise, it will contain the error this + call produced. + + Normally, you should place calls using call(). + + \warning If you use \c UseEventLoop, your code must be prepared to deal with any reentrancy: + other method calls and signals may be delivered before this function returns, as well + as other Qt queued signals and events. + + \threadsafe +*/ +QDBusMessage QDBusAbstractInterface::callWithArgumentList(QDBus::CallMode mode, + const QString& method, + const QList& args) +{ + Q_D(QDBusAbstractInterface); + + if (!d->isValid || !d->canMakeCalls()) + return QDBusMessage::createError(d->lastError); + + QString m = method; + // split out the signature from the method + int pos = method.indexOf(QLatin1Char('.')); + if (pos != -1) + m.truncate(pos); + + if (mode == QDBus::AutoDetect) { + // determine if this a sync or async call + mode = QDBus::Block; + const QMetaObject *mo = metaObject(); + QByteArray match = m.toLatin1() + '('; + + for (int i = staticMetaObject.methodCount(); i < mo->methodCount(); ++i) { + QMetaMethod mm = mo->method(i); + if (QByteArray(mm.signature()).startsWith(match)) { + // found a method with the same name as what we're looking for + // hopefully, nobody is overloading asynchronous and synchronous methods with + // the same name + + QList tags = QByteArray(mm.tag()).split(' '); + if (tags.contains("Q_NOREPLY")) + mode = QDBus::NoBlock; + + break; + } + } + } + +// qDebug() << "QDBusAbstractInterface" << "Service" << service() << "Path:" << path(); + QDBusMessage msg = QDBusMessage::createMethodCall(service(), path(), interface(), m); + QDBusMessagePrivate::setParametersValidated(msg, true); + msg.setArguments(args); + + QDBusMessage reply = d->connection.call(msg, mode); + if (thread() == QThread::currentThread()) + d->lastError = reply; // will clear if reply isn't an error + + // ensure that there is at least one element + if (reply.arguments().isEmpty()) + reply << QVariant(); + + return reply; +} + +/*! + \since 4.5 + Places a call to the remote method specified by \a method on this + interface, using \a args as arguments. This function returns a + QDBusPendingCall object that can be used to track the status of the + reply and access its contents once it has arrived. + + Normally, you should place calls using asyncCall(). + + \threadsafe +*/ +QDBusPendingCall QDBusAbstractInterface::asyncCallWithArgumentList(const QString& method, + const QList& args) +{ + Q_D(QDBusAbstractInterface); + + if (!d->isValid || !d->canMakeCalls()) + return QDBusPendingCall::fromError(d->lastError); + + QDBusMessage msg = QDBusMessage::createMethodCall(service(), path(), interface(), method); + QDBusMessagePrivate::setParametersValidated(msg, true); + msg.setArguments(args); + return d->connection.asyncCall(msg); +} + +/*! + Places a call to the remote method specified by \a method + on this interface, using \a args as arguments. This function + returns immediately after queueing the call. The reply from + the remote function is delivered to the \a returnMethod on + object \a receiver. If an error occurs, the \a errorMethod + on object \a receiver is called instead. + + This function returns true if the queueing succeeds. It does + not indicate that the executed call succeeded. If it fails, + the \a errorMethod is called. If the queueing failed, this + function returns false and no slot will be called. + + The \a returnMethod must have as its parameters the types returned + by the function call. Optionally, it may have a QDBusMessage + parameter as its last or only parameter. The \a errorMethod must + have a QDBusError as its only parameter. + + \since 4.3 + \sa QDBusError, QDBusMessage + */ +bool QDBusAbstractInterface::callWithCallback(const QString &method, + const QList &args, + QObject *receiver, + const char *returnMethod, + const char *errorMethod) +{ + Q_D(QDBusAbstractInterface); + + if (!d->isValid || !d->canMakeCalls()) + return false; + + QDBusMessage msg = QDBusMessage::createMethodCall(service(), + path(), + interface(), + method); + QDBusMessagePrivate::setParametersValidated(msg, true); + msg.setArguments(args); + + d->lastError = 0; + return d->connection.callWithCallback(msg, + receiver, + returnMethod, + errorMethod); +} + +/*! + \overload + + This function is deprecated. Please use the overloaded version. + + Places a call to the remote method specified by \a method + on this interface, using \a args as arguments. This function + returns immediately after queueing the call. The reply from + the remote function or any errors emitted by it are delivered + to the \a slot slot on object \a receiver. + + This function returns true if the queueing succeeded: it does + not indicate that the call succeeded. If it failed, the slot + will be called with an error message. lastError() will not be + set under those circumstances. + + \sa QDBusError, QDBusMessage +*/ +bool QDBusAbstractInterface::callWithCallback(const QString &method, + const QList &args, + QObject *receiver, + const char *slot) +{ + return callWithCallback(method, args, receiver, slot, 0); +} + +/*! + \internal + Catch signal connections. +*/ +void QDBusAbstractInterface::connectNotify(const char *signal) +{ + // someone connecting to one of our signals + Q_D(QDBusAbstractInterface); + if (!d->isValid) + return; + + // we end up recursing here, so optimize away + if (qstrcmp(signal + 1, "destroyed(QObject*)") == 0) + return; + + QDBusConnectionPrivate *conn = d->connectionPrivate(); + if (conn) { + conn->connectRelay(d->service, d->path, d->interface, + this, signal); + } +} + +/*! + \internal + Catch signal disconnections. +*/ +void QDBusAbstractInterface::disconnectNotify(const char *signal) +{ + // someone disconnecting from one of our signals + Q_D(QDBusAbstractInterface); + if (!d->isValid) + return; + + QDBusConnectionPrivate *conn = d->connectionPrivate(); + if (conn) + conn->disconnectRelay(d->service, d->path, d->interface, + this, signal); +} + +/*! + \internal + Get the value of the property \a propname. +*/ +QVariant QDBusAbstractInterface::internalPropGet(const char *propname) const +{ + // assume this property exists and is readable + // we're only called from generated code anyways + + return property(propname); +} + +/*! + \internal + Set the value of the property \a propname to \a value. +*/ +void QDBusAbstractInterface::internalPropSet(const char *propname, const QVariant &value) +{ + setProperty(propname, value); +} + +/*! + Calls the method \a method on this interface and passes the parameters to this function to the + method. + + The parameters to \c call are passed on to the remote function via D-Bus as input + arguments. Output arguments are returned in the QDBusMessage reply. If the reply is an error + reply, lastError() will also be set to the contents of the error message. + + This function can be used with up to 8 parameters, passed in arguments \a arg1, \a arg2, + \a arg3, \a arg4, \a arg5, \a arg6, \a arg7 and \a arg8. If you need more than 8 + parameters or if you have a variable number of parameters to be passed, use + callWithArgumentList(). + + It can be used the following way: + + \snippet doc/src/snippets/code/src_qdbus_qdbusabstractinterface.cpp 0 + + This example illustrates function calling with 0, 1 and 2 parameters and illustrates different + parameter types passed in each (the first call to \c "ProcessWorkUnicode" will contain one + Unicode string, the second call to \c "ProcessWork" will contain one string and one byte array). +*/ +QDBusMessage QDBusAbstractInterface::call(const QString &method, const QVariant &arg1, + const QVariant &arg2, + const QVariant &arg3, + const QVariant &arg4, + const QVariant &arg5, + const QVariant &arg6, + const QVariant &arg7, + const QVariant &arg8) +{ + return call(QDBus::AutoDetect, method, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); +} + +/*! + \overload + + Calls the method \a method on this interface and passes the + parameters to this function to the method. If \a mode is \c + NoWaitForReply, then this function will return immediately after + placing the call, without waiting for a reply from the remote + method. Otherwise, \a mode indicates whether this function should + activate the Qt Event Loop while waiting for the reply to arrive. + + This function can be used with up to 8 parameters, passed in arguments \a arg1, \a arg2, + \a arg3, \a arg4, \a arg5, \a arg6, \a arg7 and \a arg8. If you need more than 8 + parameters or if you have a variable number of parameters to be passed, use + callWithArgumentList(). + + If this function reenters the Qt event loop in order to wait for the + reply, it will exclude user input. During the wait, it may deliver + signals and other method calls to your application. Therefore, it + must be prepared to handle a reentrancy whenever a call is placed + with call(). +*/ +QDBusMessage QDBusAbstractInterface::call(QDBus::CallMode mode, const QString &method, + const QVariant &arg1, + const QVariant &arg2, + const QVariant &arg3, + const QVariant &arg4, + const QVariant &arg5, + const QVariant &arg6, + const QVariant &arg7, + const QVariant &arg8) +{ + QList argList; + int count = 0 + arg1.isValid() + arg2.isValid() + arg3.isValid() + arg4.isValid() + + arg5.isValid() + arg6.isValid() + arg7.isValid() + arg8.isValid(); + + switch (count) { + case 8: + argList.prepend(arg8); + case 7: + argList.prepend(arg7); + case 6: + argList.prepend(arg6); + case 5: + argList.prepend(arg5); + case 4: + argList.prepend(arg4); + case 3: + argList.prepend(arg3); + case 2: + argList.prepend(arg2); + case 1: + argList.prepend(arg1); + } + + return callWithArgumentList(mode, method, argList); +} + + +/*! + \since 4.5 + Calls the method \a method on this interface and passes the parameters to this function to the + method. + + The parameters to \c call are passed on to the remote function via D-Bus as input + arguments. The returned QDBusPendingCall object can be used to find out information about + the reply. + + This function can be used with up to 8 parameters, passed in arguments \a arg1, \a arg2, + \a arg3, \a arg4, \a arg5, \a arg6, \a arg7 and \a arg8. If you need more than 8 + parameters or if you have a variable number of parameters to be passed, use + asyncCallWithArgumentList(). + + It can be used the following way: + + \snippet doc/src/snippets/code/src_qdbus_qdbusabstractinterface.cpp 1 + + This example illustrates function calling with 0, 1 and 2 parameters and illustrates different + parameter types passed in each (the first call to \c "ProcessWorkUnicode" will contain one + Unicode string, the second call to \c "ProcessWork" will contain one string and one byte array). +*/ +QDBusPendingCall QDBusAbstractInterface::asyncCall(const QString &method, const QVariant &arg1, + const QVariant &arg2, + const QVariant &arg3, + const QVariant &arg4, + const QVariant &arg5, + const QVariant &arg6, + const QVariant &arg7, + const QVariant &arg8) +{ + QList argList; + int count = 0 + arg1.isValid() + arg2.isValid() + arg3.isValid() + arg4.isValid() + + arg5.isValid() + arg6.isValid() + arg7.isValid() + arg8.isValid(); + + switch (count) { + case 8: + argList.prepend(arg8); + case 7: + argList.prepend(arg7); + case 6: + argList.prepend(arg6); + case 5: + argList.prepend(arg5); + case 4: + argList.prepend(arg4); + case 3: + argList.prepend(arg3); + case 2: + argList.prepend(arg2); + case 1: + argList.prepend(arg1); + } + + return asyncCallWithArgumentList(method, argList); +} + +/*! + \internal +*/ +QDBusMessage QDBusAbstractInterface::internalConstCall(QDBus::CallMode mode, + const QString &method, + const QList &args) const +{ + // ### move the code here, and make the other functions call this + return const_cast(this)->callWithArgumentList(mode, method, args); +} + +QT_END_NAMESPACE + +#endif // QT_NO_DBUS + +#include "moc_qdbusabstractinterface.cpp" diff --git a/src/dbus/qdbusabstractinterface.h b/src/dbus/qdbusabstractinterface.h new file mode 100644 index 0000000000..ec7cd8ed89 --- /dev/null +++ b/src/dbus/qdbusabstractinterface.h @@ -0,0 +1,165 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDBus module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDBUSABSTRACTINTERFACE_H +#define QDBUSABSTRACTINTERFACE_H + +#include +#include +#include +#include + +#include +#include +#include + +#ifndef QT_NO_DBUS + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(DBus) + +class QDBusError; +class QDBusPendingCall; + +class QDBusAbstractInterfacePrivate; + +class Q_DBUS_EXPORT QDBusAbstractInterfaceBase: public QObject +{ +public: + int qt_metacall(QMetaObject::Call, int, void**); +protected: + QDBusAbstractInterfaceBase(QDBusAbstractInterfacePrivate &dd, QObject *parent); +private: + Q_DECLARE_PRIVATE(QDBusAbstractInterface) +}; + +class Q_DBUS_EXPORT QDBusAbstractInterface: +#ifdef Q_QDOC + public QObject +#else + public QDBusAbstractInterfaceBase +#endif +{ + Q_OBJECT + +public: + virtual ~QDBusAbstractInterface(); + bool isValid() const; + + QDBusConnection connection() const; + + QString service() const; + QString path() const; + QString interface() const; + + QDBusError lastError() const; + + QDBusMessage call(const QString &method, + const QVariant &arg1 = QVariant(), + const QVariant &arg2 = QVariant(), + const QVariant &arg3 = QVariant(), + const QVariant &arg4 = QVariant(), + const QVariant &arg5 = QVariant(), + const QVariant &arg6 = QVariant(), + const QVariant &arg7 = QVariant(), + const QVariant &arg8 = QVariant()); + + QDBusMessage call(QDBus::CallMode mode, + const QString &method, + const QVariant &arg1 = QVariant(), + const QVariant &arg2 = QVariant(), + const QVariant &arg3 = QVariant(), + const QVariant &arg4 = QVariant(), + const QVariant &arg5 = QVariant(), + const QVariant &arg6 = QVariant(), + const QVariant &arg7 = QVariant(), + const QVariant &arg8 = QVariant()); + + QDBusMessage callWithArgumentList(QDBus::CallMode mode, + const QString &method, + const QList &args); + + bool callWithCallback(const QString &method, + const QList &args, + QObject *receiver, const char *member, const char *errorSlot); + bool callWithCallback(const QString &method, + const QList &args, + QObject *receiver, const char *member); + + QDBusPendingCall asyncCall(const QString &method, + const QVariant &arg1 = QVariant(), + const QVariant &arg2 = QVariant(), + const QVariant &arg3 = QVariant(), + const QVariant &arg4 = QVariant(), + const QVariant &arg5 = QVariant(), + const QVariant &arg6 = QVariant(), + const QVariant &arg7 = QVariant(), + const QVariant &arg8 = QVariant()); + QDBusPendingCall asyncCallWithArgumentList(const QString &method, + const QList &args); + +protected: + QDBusAbstractInterface(const QString &service, const QString &path, const char *interface, + const QDBusConnection &connection, QObject *parent); + QDBusAbstractInterface(QDBusAbstractInterfacePrivate &, QObject *parent); + + void connectNotify(const char *signal); + void disconnectNotify(const char *signal); + QVariant internalPropGet(const char *propname) const; + void internalPropSet(const char *propname, const QVariant &value); + QDBusMessage internalConstCall(QDBus::CallMode mode, + const QString &method, + const QList &args = QList()) const; + +private: + Q_DECLARE_PRIVATE(QDBusAbstractInterface) + Q_PRIVATE_SLOT(d_func(), void _q_serviceOwnerChanged(QString,QString,QString)) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QT_NO_DBUS +#endif diff --git a/src/dbus/qdbusabstractinterface_p.h b/src/dbus/qdbusabstractinterface_p.h new file mode 100644 index 0000000000..fd6c69a51a --- /dev/null +++ b/src/dbus/qdbusabstractinterface_p.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDBus module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the public API. This header file may +// change from version to version without notice, or even be +// removed. +// +// We mean it. +// +// + +#ifndef QDBUSABSTRACTINTERFACEPRIVATE_H +#define QDBUSABSTRACTINTERFACEPRIVATE_H + +#include +#include +#include +#include "qdbusconnection_p.h" +#include "private/qobject_p.h" + +#define ANNOTATION_NO_WAIT "org.freedesktop.DBus.Method.NoReply" + +#ifndef QT_NO_DBUS + +QT_BEGIN_NAMESPACE + +class QDBusAbstractInterfacePrivate : public QObjectPrivate +{ +public: + Q_DECLARE_PUBLIC(QDBusAbstractInterface) + + mutable QDBusConnection connection; // mutable because we want to make calls from const functions + QString service; + QString currentOwner; + QString path; + QString interface; + mutable QDBusError lastError; + + // this is set during creation and never changed + // it can't be const because QDBusInterfacePrivate has one more check + bool isValid; + + QDBusAbstractInterfacePrivate(const QString &serv, const QString &p, + const QString &iface, const QDBusConnection& con, bool dynamic); + virtual ~QDBusAbstractInterfacePrivate() { } + bool canMakeCalls() const; + + // these functions do not check if the property is valid + void property(const QMetaProperty &mp, QVariant &where) const; + bool setProperty(const QMetaProperty &mp, const QVariant &value); + + // return conn's d pointer + inline QDBusConnectionPrivate *connectionPrivate() const + { return QDBusConnectionPrivate::d(connection); } + + void _q_serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner); +}; + +QT_END_NAMESPACE + +#endif // QT_NO_DBUS +#endif diff --git a/src/dbus/qdbusargument.cpp b/src/dbus/qdbusargument.cpp new file mode 100644 index 0000000000..806b7fec16 --- /dev/null +++ b/src/dbus/qdbusargument.cpp @@ -0,0 +1,1362 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDBus module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdbusargument.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "qdbusargument_p.h" +#include "qdbusmetatype_p.h" +#include "qdbusutil_p.h" + +#ifndef QT_NO_DBUS + +QT_BEGIN_NAMESPACE + +QDBusArgumentPrivate::~QDBusArgumentPrivate() +{ + if (message) + q_dbus_message_unref(message); +} + +QByteArray QDBusArgumentPrivate::createSignature(int id) +{ + if (!qdbus_loadLibDBus()) + return ""; + + QByteArray signature; + QDBusMarshaller *marshaller = new QDBusMarshaller(0); + marshaller->ba = &signature; + + // run it + void *null = 0; + QVariant v(id, null); + QDBusArgument arg(marshaller); + QDBusMetaType::marshall(arg, v.userType(), v.constData()); + arg.d = 0; + + // delete it + bool ok = marshaller->ok; + delete marshaller; + + if (signature.isEmpty() || !ok || !QDBusUtil::isValidSingleSignature(QString::fromLatin1(signature))) { + qWarning("QDBusMarshaller: type `%s' produces invalid D-BUS signature `%s' " + "(Did you forget to call beginStructure() ?)", + QVariant::typeToName( QVariant::Type(id) ), + signature.isEmpty() ? "" : signature.constData()); + return ""; + } else if ((signature.at(0) != DBUS_TYPE_ARRAY && signature.at(0) != DBUS_STRUCT_BEGIN_CHAR) || + (signature.at(0) == DBUS_TYPE_ARRAY && (signature.at(1) == DBUS_TYPE_BYTE || + signature.at(1) == DBUS_TYPE_STRING))) { + qWarning("QDBusMarshaller: type `%s' attempts to redefine basic D-BUS type '%s' (%s) " + "(Did you forget to call beginStructure() ?)", + QVariant::typeToName( QVariant::Type(id) ), + signature.constData(), + QVariant::typeToName( QVariant::Type(QDBusMetaType::signatureToType(signature))) ); + return ""; + } + return signature; +} + +bool QDBusArgumentPrivate::checkWrite(QDBusArgumentPrivate *&d) +{ + if (!d) + return false; + if (d->direction == Marshalling) { + if (!d->marshaller()->ok) + return false; + + if (d->message && d->ref != 1) { + QDBusMarshaller *dd = new QDBusMarshaller(d->capabilities); + dd->message = q_dbus_message_copy(d->message); + q_dbus_message_iter_init_append(dd->message, &dd->iterator); + + if (!d->ref.deref()) + delete d; + d = dd; + } + return true; + } + +#ifdef QT_DEBUG + qFatal("QDBusArgument: write from a read-only object"); +#else + qWarning("QDBusArgument: write from a read-only object"); +#endif + return false; +} + +bool QDBusArgumentPrivate::checkRead(QDBusArgumentPrivate *d) +{ + if (!d) + return false; + if (d->direction == Demarshalling) + return true; + +#ifdef QT_DEBUG + qFatal("QDBusArgument: read from a write-only object"); +#else + qWarning("QDBusArgument: read from a write-only object"); +#endif + + return false; +} + +bool QDBusArgumentPrivate::checkReadAndDetach(QDBusArgumentPrivate *&d) +{ + if (!checkRead(d)) + return false; // don't bother + + if (d->ref == 1) + return true; // no need to detach + + QDBusDemarshaller *dd = new QDBusDemarshaller(d->capabilities); + dd->message = q_dbus_message_ref(d->message); + dd->iterator = static_cast(d)->iterator; + + if (!d->ref.deref()) + delete d; + d = dd; + return true; +} + +/*! + \class QDBusArgument + \inmodule QtDBus + \since 4.2 + + \brief The QDBusArgument class is used to marshall and demarshall D-Bus arguments. + + The class is used to send arguments over D-Bus to remote + applications and to receive them back. D-Bus offers an extensible + type system, based on a few primitive types and associations of + them. See the \l {qdbustypesystem.html}{QtDBus type system} page + for more information on the type system. + + QDBusArgument is the central class in the QtDBus type system, + providing functions to marshall and demarshall the primitive + types. The compound types are then created by association of one + or more of the primitive types in arrays, dictionaries or + structures. + + The following example illustrates how a structure containing an + integer and a string can be constructed using the \l + {qdbustypesystem.html}{QtDBus type system}: + + \snippet doc/src/snippets/code/src_qdbus_qdbusargument.cpp 0 + + The type has to be registered with qDBusRegisterMetaType() before + it can be used with QDBusArgument. Therefore, somewhere in your + program, you should add the following code: + + \snippet doc/src/snippets/code/src_qdbus_qdbusargument.cpp 1 + + Once registered, a type can be used in outgoing method calls + (placed with QDBusAbstractInterface::call()), signal emissions + from registered objects or in incoming calls from remote + applications. + + It is important to note that the \c{operator<<} and \c{operator>>} + streaming functions must always produce the same number of entries + in case of structures, both in reading and in writing (marshalling + and demarshalling), otherwise calls and signals may start to + silently fail. + + The following example illustrates this wrong usage + in context of a class that may contain invalid data: + + \badcode + // Wrongly marshall the MyTime data into a D-Bus argument + QDBusArgument &operator<<(QDBusArgument &argument, const MyTime &mytime) + { + argument.beginStructure(); + if (mytime.isValid) + argument << true << mytime.hour + << mytime.minute << mytime.second; + else + argument << false; + argument.endStructure(); + return argument; + } + \endcode + + In this example, both the \c{operator<<} and the \c{operator>>} + functions may produce a different number of reads/writes. This can + confuse the QtDBus type system and should be avoided. + + \sa QDBusAbstractInterface, {qdbustypesystem.html}{The QtDBus type + system}, {usingadaptors.html}{Using Adaptors}, qdbus_cast() +*/ + +/*! + \enum QDBusArgument::ElementType + \since 4.5 + + This enum describes the type of element held by the argument. + + \value BasicType A basic element, which is understood by + QVariant. The following types are considered basic: bool, + byte, short, ushort, int, uint, qint64, quint64, double, + QString, QByteArray, QDBusObjectPath, QDBusSignature + + \value VariantType The variant element (QDBusVariant) + + \value ArrayType An array element, usually represented by QList + or QVector. Note: QByteArray and associative maps are not + considered arrays, even if the D-Bus protocol transports them as such. + + \value StructureType A custom type represented by a structure, + like QDateTime, QPoint, etc. + + \value MapType An associative container, like QMap or + QHash + + \value MapEntryType One entry in an associative container: both + the key and the value form one map-entry type. + + \value UnknownType The type is unknown or we have reached the end + of the list. + + \sa currentType() +*/ + +/*! + \fn qdbus_cast(const QDBusArgument &argument) + \relates QDBusArgument + \since 4.2 + + Attempts to demarshall the contents of \a argument into the type + \c{T}. For example: + + \snippet doc/src/snippets/code/src_qdbus_qdbusargument.cpp 2 + + Note that it is equivalent to the following: + + \snippet doc/src/snippets/code/src_qdbus_qdbusargument.cpp 3 +*/ + +/*! + Constructs an empty QDBusArgument argument. + + An empty QDBusArgument object does not allow either reading or + writing to be performed. +*/ +QDBusArgument::QDBusArgument() +{ + if (!qdbus_loadLibDBus()) { + d = 0; + return; + } + + QDBusMarshaller *dd = new QDBusMarshaller(0); + d = dd; + + // create a new message with any type, we won't sent it anyways + dd->message = q_dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL); + q_dbus_message_iter_init_append(dd->message, &dd->iterator); +} + +/*! + Constructs a copy of the \a other QDBusArgument object. + + Both objects will therefore contain the same state from this point + forward. QDBusArguments are explicitly shared and, therefore, any + modification to either copy will affect the other one too. +*/ +QDBusArgument::QDBusArgument(const QDBusArgument &other) + : d(other.d) +{ + if (d) + d->ref.ref(); +} + +/*! + \internal +*/ +QDBusArgument::QDBusArgument(QDBusArgumentPrivate *dd) + : d(dd) +{ +} + +/*! + Copies the \a other QDBusArgument object into this one. + + Both objects will therefore contain the same state from this point + forward. QDBusArguments are explicitly shared and, therefore, any + modification to either copy will affect the other one too. +*/ +QDBusArgument &QDBusArgument::operator=(const QDBusArgument &other) +{ + qAtomicAssign(d, other.d); + return *this; +} + +/*! + Disposes of the resources associated with this QDBusArgument + object. +*/ +QDBusArgument::~QDBusArgument() +{ + if (d && !d->ref.deref()) + delete d; +} + +/*! + Appends the primitive value \a arg of type \c{BYTE} to the D-Bus stream. +*/ +QDBusArgument &QDBusArgument::operator<<(uchar arg) +{ + if (QDBusArgumentPrivate::checkWrite(d)) + d->marshaller()->append(arg); + return *this; +} + +/*! + \overload + Appends the primitive value \a arg of type \c{BOOLEAN} to the D-Bus stream. +*/ +QDBusArgument &QDBusArgument::operator<<(bool arg) +{ + if (QDBusArgumentPrivate::checkWrite(d)) + d->marshaller()->append(arg); + return *this; +} + +/*! + \overload + Appends the primitive value \a arg of type \c{INT16} to the D-Bus stream. +*/ +QDBusArgument &QDBusArgument::operator<<(short arg) +{ + if (QDBusArgumentPrivate::checkWrite(d)) + d->marshaller()->append(arg); + return *this; +} + +/*! + \overload + Appends the primitive value \a arg of type \c{UINT16} to the D-Bus stream. +*/ +QDBusArgument &QDBusArgument::operator<<(ushort arg) +{ + if (QDBusArgumentPrivate::checkWrite(d)) + d->marshaller()->append(arg); + return *this; +} + +/*! + \overload + Appends the primitive value \a arg of type \c{INT32} to the D-Bus stream. +*/ +QDBusArgument &QDBusArgument::operator<<(int arg) +{ + if (QDBusArgumentPrivate::checkWrite(d)) + d->marshaller()->append(arg); + return *this; +} + +/*! + \overload + Appends the primitive value \a arg of type \c{UINT32} to the D-Bus stream. +*/ +QDBusArgument &QDBusArgument::operator<<(uint arg) +{ + if (QDBusArgumentPrivate::checkWrite(d)) + d->marshaller()->append(arg); + return *this; +} + +/*! + \overload + Appends the primitive value \a arg of type \c{INT64} to the D-Bus stream. +*/ +QDBusArgument &QDBusArgument::operator<<(qlonglong arg) +{ + if (QDBusArgumentPrivate::checkWrite(d)) + d->marshaller()->append(arg); + return *this; +} + +/*! + \overload + Appends the primitive value \a arg of type \c{UINT64} to the D-Bus stream. +*/ +QDBusArgument &QDBusArgument::operator<<(qulonglong arg) +{ + if (QDBusArgumentPrivate::checkWrite(d)) + d->marshaller()->append(arg); + return *this; +} + +/*! + \overload + Appends the primitive value \a arg of type \c{DOUBLE} (double-precision + floating-point) to the D-Bus stream. +*/ +QDBusArgument &QDBusArgument::operator<<(double arg) +{ + if (QDBusArgumentPrivate::checkWrite(d)) + d->marshaller()->append(arg); + return *this; +} + +/*! + \overload + Appends the primitive value \a arg of type \c{STRING} (Unicode character + string) to the D-Bus stream. +*/ +QDBusArgument &QDBusArgument::operator<<(const QString &arg) +{ + if (QDBusArgumentPrivate::checkWrite(d)) + d->marshaller()->append(arg); + return *this; +} + +/*! + \overload + \internal + Appends the primitive value \a arg of type \c{OBJECT_PATH} (path to a D-Bus + object) to the D-Bus stream. +*/ +QDBusArgument &QDBusArgument::operator<<(const QDBusObjectPath &arg) +{ + if (QDBusArgumentPrivate::checkWrite(d)) + d->marshaller()->append(arg); + return *this; +} + +/*! + \overload + \internal + Appends the primitive value \a arg of type \c{SIGNATURE} (D-Bus type + signature) to the D-Bus stream. +*/ +QDBusArgument &QDBusArgument::operator<<(const QDBusSignature &arg) +{ + if (QDBusArgumentPrivate::checkWrite(d)) + d->marshaller()->append(arg); + return *this; +} + +/*! + \overload + \since 4.8 + \internal + Appends the primitive value \a arg of type \c{UNIX_FILE_DESCRIPTOR} (Unix + File Descriptor) to the D-Bus stream. +*/ +QDBusArgument &QDBusArgument::operator<<(const QDBusUnixFileDescriptor &arg) +{ + if (QDBusArgumentPrivate::checkWrite(d)) + d->marshaller()->append(arg); + return *this; +} + +/*! + \overload + Appends the primitive value \a arg of type \c{VARIANT} to the D-Bus stream. + + A D-Bus variant type can contain any type, including other + variants. It is similar to the Qt QVariant type. +*/ +QDBusArgument &QDBusArgument::operator<<(const QDBusVariant &arg) +{ + if (QDBusArgumentPrivate::checkWrite(d)) + d->marshaller()->append(arg); + return *this; +} + +/*! + \overload + Appends the QStringList given by \a arg as \c{ARRAY of STRING} + to the D-Bus stream. + + QStringList and QByteArray are the only two non-primitive types + that are supported directly by QDBusArgument because of their + widespread usage in Qt applications. + + Other arrays are supported through compound types in QtDBus. +*/ +QDBusArgument &QDBusArgument::operator<<(const QStringList &arg) +{ + if (QDBusArgumentPrivate::checkWrite(d)) + d->marshaller()->append(arg); + return *this; +} + +/*! + \overload + Appends the QByteArray given by \a arg as \c{ARRAY of BYTE} + to the D-Bus stream. + + QStringList and QByteArray are the only two non-primitive types + that are supported directly by QDBusArgument because of their + widespread usage in Qt applications. + + Other arrays are supported through compound types in QtDBus. +*/ +QDBusArgument &QDBusArgument::operator<<(const QByteArray &arg) +{ + if (QDBusArgumentPrivate::checkWrite(d)) + d->marshaller()->append(arg); + return *this; +} + +/*! + \internal + \since 4.5 + + Appends the variant \a v. + + \sa asVariant() +*/ +void QDBusArgument::appendVariant(const QVariant &v) +{ + if (QDBusArgumentPrivate::checkWrite(d)) + d->marshaller()->appendVariantInternal(v); +} + +/*! + \internal + Returns the type signature of the D-Bus type this QDBusArgument + object is currently pointing to. +*/ +QString QDBusArgument::currentSignature() const +{ + if (!d) + return QString(); + if (d->direction == QDBusArgumentPrivate::Demarshalling) + return d->demarshaller()->currentSignature(); + else + return d->marshaller()->currentSignature(); +} + +/*! + \since 4.5 + Returns the classification of the current element type. If an + error decoding the type occurs or if we're at the end of the + argument, this function returns QDBusArgument::UnknownType. + + This function only makes sense when demarshalling arguments. If it + is used while marshalling, it will always return UnknownType. +*/ +QDBusArgument::ElementType QDBusArgument::currentType() const +{ + if (!d) + return UnknownType; + if (d->direction == QDBusArgumentPrivate::Demarshalling) + return d->demarshaller()->currentType(); + return UnknownType; +} + +/*! + Extracts one D-BUS primitive argument of type \c{BYTE} from the + D-BUS stream and puts it into \a arg. +*/ +const QDBusArgument &QDBusArgument::operator>>(uchar &arg) const +{ + if (QDBusArgumentPrivate::checkReadAndDetach(d)) + arg = d->demarshaller()->toByte(); + return *this; +} + +/*! + \overload + Extracts one D-Bus primitive argument of type \c{BOOLEAN} from the + D-Bus stream. +*/ +const QDBusArgument &QDBusArgument::operator>>(bool &arg) const +{ + if (QDBusArgumentPrivate::checkReadAndDetach(d)) + arg = d->demarshaller()->toBool(); + return *this; +} + +/*! + \overload + Extracts one D-Bus primitive argument of type \c{UINT16} from the + D-Bus stream. +*/ +const QDBusArgument &QDBusArgument::operator>>(ushort &arg) const +{ + if (QDBusArgumentPrivate::checkReadAndDetach(d)) + arg = d->demarshaller()->toUShort(); + return *this; +} + +/*! + \overload + Extracts one D-Bus primitive argument of type \c{INT16} from the + D-Bus stream. +*/ +const QDBusArgument &QDBusArgument::operator>>(short &arg) const +{ + if (QDBusArgumentPrivate::checkReadAndDetach(d)) + arg = d->demarshaller()->toShort(); + return *this; +} + +/*! + \overload + Extracts one D-Bus primitive argument of type \c{INT32} from the + D-Bus stream. +*/ +const QDBusArgument &QDBusArgument::operator>>(int &arg) const +{ + if (QDBusArgumentPrivate::checkReadAndDetach(d)) + arg = d->demarshaller()->toInt(); + return *this; +} + +/*! + \overload + Extracts one D-Bus primitive argument of type \c{UINT32} from the + D-Bus stream. +*/ +const QDBusArgument &QDBusArgument::operator>>(uint &arg) const +{ + if (QDBusArgumentPrivate::checkReadAndDetach(d)) + arg = d->demarshaller()->toUInt(); + return *this; +} + +/*! + \overload + Extracts one D-Bus primitive argument of type \c{INT64} from the + D-Bus stream. +*/ +const QDBusArgument &QDBusArgument::operator>>(qlonglong &arg) const +{ + if (QDBusArgumentPrivate::checkReadAndDetach(d)) + arg = d->demarshaller()->toLongLong(); + return *this; +} + +/*! + \overload + Extracts one D-Bus primitive argument of type \c{UINT64} from the + D-Bus stream. +*/ +const QDBusArgument &QDBusArgument::operator>>(qulonglong &arg) const +{ + if (QDBusArgumentPrivate::checkReadAndDetach(d)) + arg = d->demarshaller()->toULongLong(); + return *this; +} + +/*! + \overload + Extracts one D-Bus primitive argument of type \c{DOUBLE} + (double-precision floating pount) from the D-Bus stream. +*/ +const QDBusArgument &QDBusArgument::operator>>(double &arg) const +{ + if (QDBusArgumentPrivate::checkReadAndDetach(d)) + arg = d->demarshaller()->toDouble(); + return *this; +} + +/*! + \overload + Extracts one D-Bus primitive argument of type \c{STRING} (Unicode + character string) from the D-Bus stream. +*/ +const QDBusArgument &QDBusArgument::operator>>(QString &arg) const +{ + if (QDBusArgumentPrivate::checkReadAndDetach(d)) + arg = d->demarshaller()->toString(); + return *this; +} + +/*! + \overload + \internal + Extracts one D-Bus primitive argument of type \c{OBJECT_PATH} + (D-Bus path to an object) from the D-Bus stream. +*/ +const QDBusArgument &QDBusArgument::operator>>(QDBusObjectPath &arg) const +{ + if (QDBusArgumentPrivate::checkReadAndDetach(d)) + arg = d->demarshaller()->toObjectPath(); + return *this; +} + +/*! + \overload + \internal + Extracts one D-Bus primitive argument of type \c{SIGNATURE} (D-Bus + type signature) from the D-Bus stream. +*/ +const QDBusArgument &QDBusArgument::operator>>(QDBusSignature &arg) const +{ + if (QDBusArgumentPrivate::checkReadAndDetach(d)) + arg = d->demarshaller()->toSignature(); + return *this; +} + +/*! + \overload + \since 4.8 + \internal + Extracts one D-Bus primitive argument of type \c{UNIX_FILE_DESCRIPTOR} + (Unix file descriptor) from the D-Bus stream. +*/ +const QDBusArgument &QDBusArgument::operator>>(QDBusUnixFileDescriptor &arg) const +{ + if (QDBusArgumentPrivate::checkReadAndDetach(d)) + arg = d->demarshaller()->toUnixFileDescriptor(); + return *this; +} + +/*! + \overload + Extracts one D-Bus primitive argument of type \c{VARIANT} from the + D-Bus stream. + + A D-Bus variant type can contain any type, including other + variants. It is similar to the Qt QVariant type. + + In case the variant contains a type not directly supported by + QDBusArgument, the value of the returned QDBusVariant will contain + another QDBusArgument. It is your responsibility to further + demarshall it into another type. +*/ +const QDBusArgument &QDBusArgument::operator>>(QDBusVariant &arg) const +{ + if (QDBusArgumentPrivate::checkReadAndDetach(d)) + arg = d->demarshaller()->toVariant(); + return *this; +} + +/*! + \overload + Extracts an array of strings from the D-Bus stream and return it + as a QStringList. + + QStringList and QByteArray are the only two non-primitive types + that are supported directly by QDBusArgument because of their + widespread usage in Qt applications. + + Other arrays are supported through compound types in QtDBus. +*/ +const QDBusArgument &QDBusArgument::operator>>(QStringList &arg) const +{ + if (QDBusArgumentPrivate::checkReadAndDetach(d)) + arg = d->demarshaller()->toStringList(); + return *this; +} + +/*! + \overload + Extracts an array of bytes from the D-Bus stream and return it + as a QByteArray. + + QStringList and QByteArray are the only two non-primitive types + that are supported directly by QDBusArgument because of their + widespread usage in Qt applications. + + Other arrays are supported through compound types in QtDBus. +*/ +const QDBusArgument &QDBusArgument::operator>>(QByteArray &arg) const +{ + if (QDBusArgumentPrivate::checkReadAndDetach(d)) + arg = d->demarshaller()->toByteArray(); + return *this; +} + +/*! + Opens a new D-Bus structure suitable for appending new arguments. + + This function is used usually in \c{operator<<} streaming + operators, as in the following example: + + \snippet doc/src/snippets/code/src_qdbus_qdbusargument.cpp 4 + + Structures can contain other structures, so the following code is + also valid: + + \snippet doc/src/snippets/code/src_qdbus_qdbusargument.cpp 5 + + \sa endStructure(), beginArray(), beginMap() +*/ +void QDBusArgument::beginStructure() +{ + if (QDBusArgumentPrivate::checkWrite(d)) + d = d->marshaller()->beginStructure(); +} + +/*! + Closes a D-Bus structure opened with beginStructure(). This function must be called + same number of times that beginStructure() is called. + + \sa beginStructure(), endArray(), endMap() +*/ +void QDBusArgument::endStructure() +{ + if (QDBusArgumentPrivate::checkWrite(d)) + d = d->marshaller()->endStructure(); +} + +/*! + Opens a new D-Bus array suitable for appending elements of meta-type \a id. + + This function is used usually in \c{operator<<} streaming + operators, as in the following example: + + \snippet doc/src/snippets/code/src_qdbus_qdbusargument.cpp 6 + + If the type you want to marshall is a QList, QVector or any of the + Qt's \l {Container Classes} that take one template parameter, + you need not declare an \c{operator<<} function for it, since + QtDBus provides generic templates to do the job of marshalling + the data. The same applies for STL's sequence containers, such + as \c {std::list}, \c {std::vector}, etc. + + \sa endArray(), beginStructure(), beginMap() +*/ +void QDBusArgument::beginArray(int id) +{ + if (QDBusArgumentPrivate::checkWrite(d)) + d = d->marshaller()->beginArray(id); +} + +/*! + Closes a D-Bus array opened with beginArray(). This function must be called + same number of times that beginArray() is called. + + \sa beginArray(), endStructure(), endMap() +*/ +void QDBusArgument::endArray() +{ + if (QDBusArgumentPrivate::checkWrite(d)) + d = d->marshaller()->endArray(); +} + +/*! + Opens a new D-Bus map suitable for + appending elements. Maps are containers that associate one entry + (the key) to another (the value), such as Qt's QMap or QHash. The + ids of the map's key and value meta types must be passed in \a kid + and \a vid respectively. + + This function is used usually in \c{operator<<} streaming + operators, as in the following example: + + \snippet doc/src/snippets/code/src_qdbus_qdbusargument.cpp 7 + + If the type you want to marshall is a QMap or QHash, you need not + declare an \c{operator<<} function for it, since QtDBus provides + generic templates to do the job of marshalling the data. + + \sa endMap(), beginStructure(), beginArray(), beginMapEntry() +*/ +void QDBusArgument::beginMap(int kid, int vid) +{ + if (QDBusArgumentPrivate::checkWrite(d)) + d = d->marshaller()->beginMap(kid, vid); +} + +/*! + Closes a D-Bus map opened with beginMap(). This function must be called + same number of times that beginMap() is called. + + \sa beginMap(), endStructure(), endArray() +*/ +void QDBusArgument::endMap() +{ + if (QDBusArgumentPrivate::checkWrite(d)) + d = d->marshaller()->endMap(); +} + +/*! + Opens a D-Bus map entry suitable for + appending the key and value entries. This function is only valid + when a map has been opened with beginMap(). + + See beginMap() for an example of usage of this function. + + \sa endMapEntry(), beginMap() +*/ +void QDBusArgument::beginMapEntry() +{ + if (QDBusArgumentPrivate::checkWrite(d)) + d = d->marshaller()->beginMapEntry(); +} + +/*! + Closes a D-Bus map entry opened with beginMapEntry(). This function must be called + same number of times that beginMapEntry() is called. + + \sa beginMapEntry() +*/ +void QDBusArgument::endMapEntry() +{ + if (QDBusArgumentPrivate::checkWrite(d)) + d = d->marshaller()->endMapEntry(); +} + +/*! + Opens a D-Bus structure suitable for extracting elements. + + This function is used usually in \c{operator>>} streaming + operators, as in the following example: + + \snippet doc/src/snippets/code/src_qdbus_qdbusargument.cpp 8 + + \sa endStructure(), beginArray(), beginMap() +*/ +void QDBusArgument::beginStructure() const +{ + if (QDBusArgumentPrivate::checkReadAndDetach(d)) + d = d->demarshaller()->beginStructure(); +} + +/*! + Closes the D-Bus structure and allow extracting of the next element + after the structure. + + \sa beginStructure() +*/ +void QDBusArgument::endStructure() const +{ + if (QDBusArgumentPrivate::checkReadAndDetach(d)) + d = d->demarshaller()->endStructure(); +} + +/*! + Recurses into the D-Bus array to allow extraction of + the array elements. + + This function is used usually in \c{operator>>} streaming + operators, as in the following example: + + \snippet doc/src/snippets/code/src_qdbus_qdbusargument.cpp 9 + + If the type you want to demarshall is a QList, QVector or any of the + Qt's \l {Container Classes} that take one template parameter, you + need not declare an \c{operator>>} function for it, since QtDBus + provides generic templates to do the job of demarshalling the data. + The same applies for STL's sequence containers, such as \c {std::list}, + \c {std::vector}, etc. + + \sa atEnd(), beginStructure(), beginMap() +*/ +void QDBusArgument::beginArray() const +{ + if (QDBusArgumentPrivate::checkReadAndDetach(d)) + d = d->demarshaller()->beginArray(); +} + +/*! + Closes the D-Bus array and allow extracting of the next element + after the array. + + \sa beginArray() +*/ +void QDBusArgument::endArray() const +{ + if (QDBusArgumentPrivate::checkReadAndDetach(d)) + d = d->demarshaller()->endArray(); +} + +/*! + Recurses into the D-Bus map to allow extraction of + the map's elements. + + This function is used usually in \c{operator>>} streaming + operators, as in the following example: + + \snippet doc/src/snippets/code/src_qdbus_qdbusargument.cpp 10 + + If the type you want to demarshall is a QMap or QHash, you need not + declare an \c{operator>>} function for it, since QtDBus provides + generic templates to do the job of demarshalling the data. + + \sa endMap(), beginStructure(), beginArray(), beginMapEntry() +*/ +void QDBusArgument::beginMap() const +{ + if (QDBusArgumentPrivate::checkReadAndDetach(d)) + d = d->demarshaller()->beginMap(); +} + +/*! + Closes the D-Bus map and allow extracting of the next element + after the map. + + \sa beginMap() +*/ +void QDBusArgument::endMap() const +{ + if (QDBusArgumentPrivate::checkReadAndDetach(d)) + d = d->demarshaller()->endMap(); +} + +/*! + Recurses into the D-Bus map entry to allow extraction + of the key and value pair. + + See beginMap() for an example of how this function is usually used. + + \sa endMapEntry(), beginMap() +*/ +void QDBusArgument::beginMapEntry() const +{ + if (QDBusArgumentPrivate::checkReadAndDetach(d)) + d = d->demarshaller()->beginMapEntry(); +} + +/*! + Closes the D-Bus map entry and allow extracting of the next element + on the map. + + \sa beginMapEntry() +*/ +void QDBusArgument::endMapEntry() const +{ + if (QDBusArgumentPrivate::checkReadAndDetach(d)) + d = d->demarshaller()->endMapEntry(); +} + +/*! + Returns true if there are no more elements to be extracted from + this QDBusArgument. This function is usually used in QDBusArgument + objects returned from beginMap() and beginArray(). +*/ +bool QDBusArgument::atEnd() const +{ + if (QDBusArgumentPrivate::checkRead(d)) + return d->demarshaller()->atEnd(); + + return true; // at least, stop reading +} + +/*! + \since 4.5 + + Returns the current argument in the form of a QVariant. Basic + types will be decoded and returned in the QVariant, but for + complex types, this function will return a QDBusArgument object in + the QVariant. It is the caller's responsibility to decode the + argument (for example, by calling asVariant() in it). + + For example, if the current argument is an INT32, this function + will return a QVariant with an argument of type QVariant::Int. For + an array of INT32, it will return a QVariant containing a + QDBusArgument. + + If an error occurs or if there are no more arguments to decode + (i.e., we are at the end of the argument list), this function will + return an invalid QVariant. + + \sa atEnd() +*/ +QVariant QDBusArgument::asVariant() const +{ + if (QDBusArgumentPrivate::checkRead(d)) + return d->demarshaller()->toVariantInternal(); + + return QVariant(); +} + +QT_END_NAMESPACE + +// for optimization purposes, we include the marshallers here +#include "qdbusmarshaller.cpp" +#include "qdbusdemarshaller.cpp" + +QT_BEGIN_NAMESPACE + +// QDBusArgument operators + +const QDBusArgument &operator>>(const QDBusArgument &a, QVariant &v) +{ + QDBusVariant dbv; + a >> dbv; + v = dbv.variant(); + return a; +} + +// QVariant types +#ifndef QDBUS_NO_SPECIALTYPES +const QDBusArgument &operator>>(const QDBusArgument &a, QDate &date) +{ + int y, m, d; + a.beginStructure(); + a >> y >> m >> d; + a.endStructure(); + + if (y != 0 && m != 0 && d != 0) + date.setYMD(y, m, d); + else + date = QDate(); + return a; +} + +QDBusArgument &operator<<(QDBusArgument &a, const QDate &date) +{ + a.beginStructure(); + if (date.isValid()) + a << date.year() << date.month() << date.day(); + else + a << 0 << 0 << 0; + a.endStructure(); + return a; +} + +const QDBusArgument &operator>>(const QDBusArgument &a, QTime &time) +{ + int h, m, s, ms; + a.beginStructure(); + a >> h >> m >> s >> ms; + a.endStructure(); + + if (h < 0) + time = QTime(); + else + time.setHMS(h, m, s, ms); + return a; +} + +QDBusArgument &operator<<(QDBusArgument &a, const QTime &time) +{ + a.beginStructure(); + if (time.isValid()) + a << time.hour() << time.minute() << time.second() << time.msec(); + else + a << -1 << -1 << -1 << -1; + a.endStructure(); + return a; +} + +const QDBusArgument &operator>>(const QDBusArgument &a, QDateTime &dt) +{ + QDate date; + QTime time; + int timespec; + + a.beginStructure(); + a >> date >> time >> timespec; + a.endStructure(); + + dt = QDateTime(date, time, Qt::TimeSpec(timespec)); + return a; +} + +QDBusArgument &operator<<(QDBusArgument &a, const QDateTime &dt) +{ + a.beginStructure(); + a << dt.date() << dt.time() << int(dt.timeSpec()); + a.endStructure(); + return a; +} + +const QDBusArgument &operator>>(const QDBusArgument &a, QRect &rect) +{ + int x, y, width, height; + a.beginStructure(); + a >> x >> y >> width >> height; + a.endStructure(); + + rect.setRect(x, y, width, height); + return a; +} + +QDBusArgument &operator<<(QDBusArgument &a, const QRect &rect) +{ + a.beginStructure(); + a << rect.x() << rect.y() << rect.width() << rect.height(); + a.endStructure(); + + return a; +} + +const QDBusArgument &operator>>(const QDBusArgument &a, QRectF &rect) +{ + double x, y, width, height; + a.beginStructure(); + a >> x >> y >> width >> height; + a.endStructure(); + + rect.setRect(qreal(x), qreal(y), qreal(width), qreal(height)); + return a; +} + +QDBusArgument &operator<<(QDBusArgument &a, const QRectF &rect) +{ + a.beginStructure(); + a << double(rect.x()) << double(rect.y()) << double(rect.width()) << double(rect.height()); + a.endStructure(); + + return a; +} + +const QDBusArgument &operator>>(const QDBusArgument &a, QSize &size) +{ + a.beginStructure(); + a >> size.rwidth() >> size.rheight(); + a.endStructure(); + + return a; +} + +QDBusArgument &operator<<(QDBusArgument &a, const QSize &size) +{ + a.beginStructure(); + a << size.width() << size.height(); + a.endStructure(); + + return a; +} + +const QDBusArgument &operator>>(const QDBusArgument &a, QSizeF &size) +{ + double width, height; + a.beginStructure(); + a >> width >> height; + a.endStructure(); + + size.setWidth(qreal(width)); + size.setHeight(qreal(height)); + return a; +} + +QDBusArgument &operator<<(QDBusArgument &a, const QSizeF &size) +{ + a.beginStructure(); + a << double(size.width()) << double(size.height()); + a.endStructure(); + + return a; +} + +const QDBusArgument &operator>>(const QDBusArgument &a, QPoint &pt) +{ + a.beginStructure(); + a >> pt.rx() >> pt.ry(); + a.endStructure(); + + return a; +} + +QDBusArgument &operator<<(QDBusArgument &a, const QPoint &pt) +{ + a.beginStructure(); + a << pt.x() << pt.y(); + a.endStructure(); + + return a; +} + +const QDBusArgument &operator>>(const QDBusArgument &a, QPointF &pt) +{ + double x, y; + a.beginStructure(); + a >> x >> y; + a.endStructure(); + + pt.setX(qreal(x)); + pt.setY(qreal(y)); + return a; +} + +QDBusArgument &operator<<(QDBusArgument &a, const QPointF &pt) +{ + a.beginStructure(); + a << double(pt.x()) << double(pt.y()); + a.endStructure(); + + return a; +} + +const QDBusArgument &operator>>(const QDBusArgument &a, QLine &line) +{ + QPoint p1, p2; + a.beginStructure(); + a >> p1 >> p2; + a.endStructure(); + + line = QLine(p1, p2); + return a; +} + +QDBusArgument &operator<<(QDBusArgument &a, const QLine &line) +{ + a.beginStructure(); + a << line.p1() << line.p2(); + a.endStructure(); + + return a; +} + +const QDBusArgument &operator>>(const QDBusArgument &a, QLineF &line) +{ + QPointF p1, p2; + a.beginStructure(); + a >> p1 >> p2; + a.endStructure(); + + line = QLineF(p1, p2); + return a; +} + +QDBusArgument &operator<<(QDBusArgument &a, const QLineF &line) +{ + a.beginStructure(); + a << line.p1() << line.p2(); + a.endStructure(); + + return a; +} +#endif + +QT_END_NAMESPACE + +#endif // QT_NO_DBUS diff --git a/src/dbus/qdbusargument.h b/src/dbus/qdbusargument.h new file mode 100644 index 0000000000..f80723e6b4 --- /dev/null +++ b/src/dbus/qdbusargument.h @@ -0,0 +1,405 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDBus module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDBUSARGUMENT_H +#define QDBUSARGUMENT_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef QT_NO_DBUS + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(DBus) + +class QDBusUnixFileDescriptor; + +class QDBusArgumentPrivate; +class QDBusDemarshaller; +class QDBusMarshaller; +class Q_DBUS_EXPORT QDBusArgument +{ +public: + enum ElementType { + BasicType, + VariantType, + ArrayType, + StructureType, + MapType, + MapEntryType, + UnknownType = -1 + }; + + QDBusArgument(); + QDBusArgument(const QDBusArgument &other); + QDBusArgument &operator=(const QDBusArgument &other); + ~QDBusArgument(); + + // used for marshalling (Qt -> D-BUS) + QDBusArgument &operator<<(uchar arg); + QDBusArgument &operator<<(bool arg); + QDBusArgument &operator<<(short arg); + QDBusArgument &operator<<(ushort arg); + QDBusArgument &operator<<(int arg); + QDBusArgument &operator<<(uint arg); + QDBusArgument &operator<<(qlonglong arg); + QDBusArgument &operator<<(qulonglong arg); + QDBusArgument &operator<<(double arg); + QDBusArgument &operator<<(const QString &arg); + QDBusArgument &operator<<(const QDBusVariant &arg); + QDBusArgument &operator<<(const QDBusObjectPath &arg); + QDBusArgument &operator<<(const QDBusSignature &arg); + QDBusArgument &operator<<(const QDBusUnixFileDescriptor &arg); + QDBusArgument &operator<<(const QStringList &arg); + QDBusArgument &operator<<(const QByteArray &arg); + + void beginStructure(); + void endStructure(); + void beginArray(int elementMetaTypeId); + void endArray(); + void beginMap(int keyMetaTypeId, int valueMetaTypeId); + void endMap(); + void beginMapEntry(); + void endMapEntry(); + + void appendVariant(const QVariant &v); + + // used for de-marshalling (D-BUS -> Qt) + QString currentSignature() const; + ElementType currentType() const; + + const QDBusArgument &operator>>(uchar &arg) const; + const QDBusArgument &operator>>(bool &arg) const; + const QDBusArgument &operator>>(short &arg) const; + const QDBusArgument &operator>>(ushort &arg) const; + const QDBusArgument &operator>>(int &arg) const; + const QDBusArgument &operator>>(uint &arg) const; + const QDBusArgument &operator>>(qlonglong &arg) const; + const QDBusArgument &operator>>(qulonglong &arg) const; + const QDBusArgument &operator>>(double &arg) const; + const QDBusArgument &operator>>(QString &arg) const; + const QDBusArgument &operator>>(QDBusVariant &arg) const; + const QDBusArgument &operator>>(QDBusObjectPath &arg) const; + const QDBusArgument &operator>>(QDBusSignature &arg) const; + const QDBusArgument &operator>>(QDBusUnixFileDescriptor &arg) const; + const QDBusArgument &operator>>(QStringList &arg) const; + const QDBusArgument &operator>>(QByteArray &arg) const; + + void beginStructure() const; + void endStructure() const; + void beginArray() const; + void endArray() const; + void beginMap() const; + void endMap() const; + void beginMapEntry() const; + void endMapEntry() const; + bool atEnd() const; + + QVariant asVariant() const; + +protected: + QDBusArgument(QDBusArgumentPrivate *d); + friend class QDBusArgumentPrivate; + mutable QDBusArgumentPrivate *d; +}; + +template inline T qdbus_cast(const QDBusArgument &arg +#ifndef Q_QDOC +, T * = 0 +#endif + ) +{ + T item; + arg >> item; + return item; +} + +template inline T qdbus_cast(const QVariant &v +#ifndef Q_QDOC +, T * = 0 +#endif + ) +{ + int id = v.userType(); + if (id == qMetaTypeId()) + return qdbus_cast(qvariant_cast(v)); + else + return qvariant_cast(v); +} + +// specialize for QVariant, allowing it to be used in place of QDBusVariant +template<> inline QVariant qdbus_cast(const QDBusArgument &arg, QVariant *) +{ + QDBusVariant item; + arg >> item; + return item.variant(); +} +template<> inline QVariant qdbus_cast(const QVariant &v, QVariant *) +{ + return qdbus_cast(v).variant(); +} + +Q_DBUS_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, QVariant &v); + +// QVariant types +#ifndef QDBUS_NO_SPECIALTYPES + +Q_DBUS_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, QDate &date); +Q_DBUS_EXPORT QDBusArgument &operator<<(QDBusArgument &a, const QDate &date); + +Q_DBUS_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, QTime &time); +Q_DBUS_EXPORT QDBusArgument &operator<<(QDBusArgument &a, const QTime &time); + +Q_DBUS_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, QDateTime &dt); +Q_DBUS_EXPORT QDBusArgument &operator<<(QDBusArgument &a, const QDateTime &dt); + +Q_DBUS_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, QRect &rect); +Q_DBUS_EXPORT QDBusArgument &operator<<(QDBusArgument &a, const QRect &rect); + +Q_DBUS_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, QRectF &rect); +Q_DBUS_EXPORT QDBusArgument &operator<<(QDBusArgument &a, const QRectF &rect); + +Q_DBUS_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, QSize &size); +Q_DBUS_EXPORT QDBusArgument &operator<<(QDBusArgument &a, const QSize &size); + +Q_DBUS_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, QSizeF &size); +Q_DBUS_EXPORT QDBusArgument &operator<<(QDBusArgument &a, const QSizeF &size); + +Q_DBUS_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, QPoint &pt); +Q_DBUS_EXPORT QDBusArgument &operator<<(QDBusArgument &a, const QPoint &pt); + +Q_DBUS_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, QPointF &pt); +Q_DBUS_EXPORT QDBusArgument &operator<<(QDBusArgument &a, const QPointF &pt); + +Q_DBUS_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, QLine &line); +Q_DBUS_EXPORT QDBusArgument &operator<<(QDBusArgument &a, const QLine &line); + +Q_DBUS_EXPORT const QDBusArgument &operator>>(const QDBusArgument &a, QLineF &line); +Q_DBUS_EXPORT QDBusArgument &operator<<(QDBusArgument &a, const QLineF &line); +#endif + +template