source: trunk/src/dbus/qdbusinterface.cpp@ 5

Last change on this file since 5 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 8.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtDBus module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qdbusinterface.h"
43
44#include <qdbus_symbols_p.h>
45#include <QtCore/qpointer.h>
46#include <QtCore/qstringlist.h>
47
48#include "qdbusmetatype_p.h"
49#include "qdbusinterface_p.h"
50#include "qdbusconnection_p.h"
51
52QT_BEGIN_NAMESPACE
53
54QDBusInterfacePrivate::QDBusInterfacePrivate(const QString &serv, const QString &p,
55 const QString &iface, const QDBusConnection &con)
56 : QDBusAbstractInterfacePrivate(serv, p, iface, con, true), metaObject(0)
57{
58 // QDBusAbstractInterfacePrivate's constructor checked the parameters for us
59 if (connection.isConnected()) {
60 metaObject = connectionPrivate()->findMetaObject(service, path, interface, lastError);
61
62 if (!metaObject) {
63 // creation failed, somehow
64 isValid = false;
65 if (!lastError.isValid())
66 lastError = QDBusError(QDBusError::InternalError, QLatin1String("Unknown error"));
67 }
68 }
69}
70
71QDBusInterfacePrivate::~QDBusInterfacePrivate()
72{
73 if (metaObject && !metaObject->cached)
74 delete metaObject;
75}
76
77
78/*!
79 \class QDBusInterface
80 \inmodule QtDBus
81 \since 4.2
82
83 \brief The QDBusInterface class is a proxy for interfaces on remote objects.
84
85 QDBusInterface is a generic accessor class that is used to place calls to remote objects,
86 connect to signals exported by remote objects and get/set the value of remote properties. This
87 class is useful for dynamic access to remote objects: that is, when you do not have a generated
88 code that represents the remote interface.
89
90 Calls are usually placed by using the call() function, which constructs the message, sends it
91 over the bus, waits for the reply and decodes the reply. Signals are connected to by using the
92 normal QObject::connect() function. Finally, properties are accessed using the
93 QObject::property() and QObject::setProperty() functions.
94
95 The following code snippet demonstrates how to perform a
96 mathematical operation of \tt{"2 + 2"} in a remote application
97 called \c com.example.Calculator, accessed via the session bus.
98
99 \snippet doc/src/snippets/code/src_qdbus_qdbusinterface.cpp 0
100
101 \sa {QtDBus XML compiler (qdbusxml2cpp)}
102*/
103
104/*!
105 Creates a dynamic QDBusInterface object associated with the
106 interface \a interface on object at path \a path on service \a
107 service, using the given \a connection. If \a interface is an
108 empty string, the object created will refer to the merging of all
109 interfaces found in that object.
110
111 \a parent is passed to the base class constructor.
112
113 If the remote service \a service is not present or if an error
114 occurs trying to obtain the description of the remote interface
115 \a interface, the object created will not be valid (see
116 isValid()).
117*/
118QDBusInterface::QDBusInterface(const QString &service, const QString &path, const QString &interface,
119 const QDBusConnection &connection, QObject *parent)
120 : QDBusAbstractInterface(*new QDBusInterfacePrivate(service, path, interface, connection),
121 parent)
122{
123}
124
125/*!
126 Destroy the object interface and frees up any resource used.
127*/
128QDBusInterface::~QDBusInterface()
129{
130 // resources are freed in QDBusInterfacePrivate::~QDBusInterfacePrivate()
131}
132
133/*!
134 \internal
135 Overrides QObject::metaObject to return our own copy.
136*/
137const QMetaObject *QDBusInterface::metaObject() const
138{
139 return d_func()->isValid ? d_func()->metaObject : &QDBusAbstractInterface::staticMetaObject;
140}
141
142/*!
143 \internal
144 Override QObject::qt_metacast to catch the interface name too.
145*/
146void *QDBusInterface::qt_metacast(const char *_clname)
147{
148 if (!_clname) return 0;
149 if (!strcmp(_clname, "QDBusInterface"))
150 return static_cast<void*>(const_cast<QDBusInterface*>(this));
151 if (d_func()->interface.toLatin1() == _clname)
152 return static_cast<void*>(const_cast<QDBusInterface*>(this));
153 return QDBusAbstractInterface::qt_metacast(_clname);
154}
155
156/*!
157 \internal
158 Dispatch the call through the private.
159*/
160int QDBusInterface::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
161{
162 _id = QDBusAbstractInterface::qt_metacall(_c, _id, _a);
163 if (_id < 0 || !d_func()->isValid)
164 return _id;
165 return d_func()->metacall(_c, _id, _a);
166}
167
168int QDBusInterfacePrivate::metacall(QMetaObject::Call c, int id, void **argv)
169{
170 Q_Q(QDBusInterface);
171
172 if (c == QMetaObject::InvokeMetaMethod) {
173 int offset = metaObject->methodOffset();
174 QMetaMethod mm = metaObject->method(id + offset);
175
176 if (mm.methodType() == QMetaMethod::Signal) {
177 // signal relay from D-Bus world to Qt world
178 QMetaObject::activate(q, metaObject, id, argv);
179
180 } else if (mm.methodType() == QMetaMethod::Slot) {
181 // method call relay from Qt world to D-Bus world
182 // get D-Bus equivalent signature
183 QString methodName = QLatin1String(metaObject->dbusNameForMethod(id));
184 const int *inputTypes = metaObject->inputTypesForMethod(id);
185 int inputTypesCount = *inputTypes;
186
187 // we will assume that the input arguments were passed correctly
188 QVariantList args;
189 for (int i = 1; i <= inputTypesCount; ++i)
190 args << QVariant(inputTypes[i], argv[i]);
191
192 // make the call
193 QPointer<QDBusInterface> qq = q;
194 QDBusMessage reply = q->callWithArgumentList(QDBus::Block, methodName, args);
195 args.clear();
196
197 // we ignore return values
198
199 // access to "this" or to "q" below this point must check for "qq"
200 // we may have been deleted!
201
202 if (!qq.isNull())
203 lastError = reply;
204
205 // done
206 return -1;
207 }
208 } else if (c == QMetaObject::ReadProperty) {
209 // Qt doesn't support non-readable properties
210 // we have to re-check
211 QMetaProperty mp = metaObject->property(id + metaObject->propertyOffset());
212 if (!mp.isReadable())
213 return -1; // don't read
214
215 QVariant *value = reinterpret_cast<QVariant*>(argv[1]);
216 argv[1] = 0;
217 *value = property(mp);
218
219 return -1; // handled, error or not
220 } else if (c == QMetaObject::WriteProperty) {
221 // QMetaProperty::write has already checked that we're writable
222 // it has also checked that the type is right
223 QVariant *value = reinterpret_cast<QVariant *>(argv[1]);
224 QMetaProperty mp = metaObject->property(id + metaObject->propertyOffset());
225
226 setProperty(mp, *value);
227 return -1;
228 }
229 return id;
230}
231
232QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.