mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-05-01 06:47:58 +02:00
2006-03-06 Thiago Macieira <thiago.macieira@trolltech.com>
* qt/*: * dbus/qdbus.h: Sync with KDE Subversion revision 516237. This represents the first feature-complete version of the Qt4 bindings since I took ove maintainership.
This commit is contained in:
parent
305ce15e4f
commit
9393d6b459
34 changed files with 3615 additions and 935 deletions
|
|
@ -1,3 +1,10 @@
|
|||
2006-03-06 Thiago Macieira <thiago.macieira@trolltech.com>
|
||||
|
||||
* qt/*:
|
||||
* dbus/qdbus.h: Sync with KDE Subversion revision 516237. This
|
||||
represents the first feature-complete version of the Qt4
|
||||
bindings since I took ove maintainership.
|
||||
|
||||
2006-03-06 Thiago Macieira <thiago.macieira@trolltech.com>
|
||||
|
||||
* qt/Doxyfile: Adding a Doxyfile for the Qt4 bindings
|
||||
|
|
|
|||
16
dbus/qdbus.h
16
dbus/qdbus.h
|
|
@ -26,17 +26,29 @@
|
|||
#include <QtCore/qglobal.h>
|
||||
|
||||
#ifndef DBUS_COMPILATION
|
||||
# define QDBUS_EXPORT Q_DECL_IMPORT
|
||||
# include <dbus/qdbusabstractadaptor.h>
|
||||
# include <dbus/qdbusconnection.h>
|
||||
# include <dbus/qdbuserror.h>
|
||||
# include <dbus/qdbusinterface.h>
|
||||
# include <dbus/qdbusintrospection.h>
|
||||
# include <dbus/qdbusmessage.h>
|
||||
# include <dbus/qdbusobject.h>
|
||||
# include <dbus/qdbusreply.h>
|
||||
# include <dbus/qdbusserver.h>
|
||||
# include <dbus/qdbustype.h>
|
||||
# include <dbus/qdbusutil.h>
|
||||
#else
|
||||
# define QDBUS_EXPORT Q_DECL_EXPORT
|
||||
# include <qt/qdbusabstractadaptor.h>
|
||||
# include <qt/qdbusconnection.h>
|
||||
# include <qt/qdbuserror.h>
|
||||
# include <qt/qdbusinterface.h>
|
||||
# include <qt/qdbusintrospection.h>
|
||||
# include <qt/qdbusmessage.h>
|
||||
# include <qt/qdbusobject.h>
|
||||
# include <qt/qdbusreply.h>
|
||||
# include <qt/qdbusserver.h>
|
||||
# include <qt/qdbustype.h>
|
||||
# include <qt/qdbusutil.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -18,12 +18,14 @@ dbusinclude_HEADERS= \
|
|||
qdbusstandardinterfaces.h \
|
||||
qdbusutil.h \
|
||||
qdbusintrospection.h \
|
||||
qdbusabstractadaptor.h
|
||||
qdbusabstractadaptor.h \
|
||||
qdbusreply.h
|
||||
|
||||
libdbus_qt4_1_la_SOURCES = \
|
||||
qdbusconnection.cpp \
|
||||
qdbuserror.cpp \
|
||||
qdbusintegrator.cpp \
|
||||
qdbusinternalfilters.cpp \
|
||||
qdbusmarshall.cpp \
|
||||
qdbusmessage.cpp \
|
||||
qdbusserver.cpp \
|
||||
|
|
@ -38,6 +40,7 @@ libdbus_qt4_1_la_SOURCES = \
|
|||
qdbusthread.cpp \
|
||||
\
|
||||
qdbusabstractadaptor.h \
|
||||
qdbusabstractadaptor_p.h \
|
||||
qdbusconnection.h \
|
||||
qdbusconnection_p.h \
|
||||
qdbuserror.h \
|
||||
|
|
@ -45,11 +48,12 @@ libdbus_qt4_1_la_SOURCES = \
|
|||
qdbusinterface_p.h \
|
||||
qdbusintrospection.h \
|
||||
qdbusmacros.h \
|
||||
qdbusmarshall.h \
|
||||
qdbusmarshall_p.h \
|
||||
qdbusmessage.h \
|
||||
qdbusmessage_p.h \
|
||||
qdbusobject.h \
|
||||
qdbusobject_p.h \
|
||||
qdbusreply.h \
|
||||
qdbusserver.h \
|
||||
qdbusstandardinterfaces.h \
|
||||
qdbustype.h \
|
||||
|
|
@ -57,15 +61,17 @@ libdbus_qt4_1_la_SOURCES = \
|
|||
qdbusxmlparser_p.h
|
||||
|
||||
|
||||
qdbusabstractadaptor.lo: qdbusabstractadaptor.moc
|
||||
qdbusabstractadaptor.lo: qdbusabstractadaptor.moc qdbusabstractadaptor_p.moc
|
||||
qdbusserver.lo: qdbusserver.moc
|
||||
qdbusconnection.lo: qdbusconnection_p.moc
|
||||
|
||||
CLEANFILES=qdbusabstractadaptor.moc qdbusserver.moc qdbusconnection.moc
|
||||
CLEANFILES=qdbusabstractadaptor.moc qdbusserver.moc qdbusconnection.moc qdbusabstractadaptor_p.moc
|
||||
|
||||
libdbus_qt4_1_la_LIBADD= $(DBUS_QT_LIBS) $(top_builddir)/dbus/libdbus-1.la
|
||||
libdbus_qt4_1_la_LDFLAGS= -version-info 1:0 -no-undefined
|
||||
|
||||
EXTRA_DIST = Doxyfile
|
||||
|
||||
%.moc: %.h
|
||||
$(QT_MOC) $< > $@
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -26,19 +26,622 @@
|
|||
#include <QtCore/qmetaobject.h>
|
||||
#include <QtCore/qtimer.h>
|
||||
|
||||
QDBusAbstractAdaptor::QDBusAbstractAdaptor(QObject* parent)
|
||||
: QObject(parent)
|
||||
#include "qdbusconnection.h"
|
||||
|
||||
#include "qdbusconnection_p.h" // for qDBusParametersForMethod
|
||||
#include "qdbusabstractadaptor_p.h"
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
struct QDBusAdaptorInit
|
||||
{
|
||||
QTimer::singleShot(0, this, SLOT(polish()));
|
||||
QSignalSpyCallbackSet callbacks;
|
||||
QDBusAdaptorInit()
|
||||
{
|
||||
extern void qt_register_signal_spy_callbacks(const QSignalSpyCallbackSet &callback_set);
|
||||
callbacks.signal_begin_callback = QDBusAdaptorConnector::signalBeginCallback;
|
||||
callbacks.signal_end_callback = QDBusAdaptorConnector::signalEndCallback;
|
||||
callbacks.slot_begin_callback = 0;
|
||||
callbacks.slot_end_callback = 0;
|
||||
qt_register_signal_spy_callbacks(callbacks);
|
||||
|
||||
//QDBusAdaptorConnector::id = QObject::registerUserData();
|
||||
}
|
||||
};
|
||||
|
||||
Q_GLOBAL_STATIC(QDBusAdaptorInit, qAdaptorInit)
|
||||
|
||||
QDBusAdaptorConnector *qDBusFindAdaptorConnector(QObject *obj)
|
||||
{
|
||||
qAdaptorInit();
|
||||
|
||||
#if 0
|
||||
if (caller->metaObject() == QDBusAdaptorConnector::staticMetaObject)
|
||||
return 0; // it's a QDBusAdaptorConnector
|
||||
#endif
|
||||
|
||||
if (!obj)
|
||||
return 0;
|
||||
QDBusAdaptorConnector *connector = qFindChild<QDBusAdaptorConnector *>(obj);
|
||||
if (connector)
|
||||
connector->polish();
|
||||
return connector;
|
||||
}
|
||||
|
||||
QDBusAdaptorConnector *qDBusCreateAdaptorConnector(QObject *obj)
|
||||
{
|
||||
qAdaptorInit();
|
||||
|
||||
QDBusAdaptorConnector *connector = qDBusFindAdaptorConnector(obj);
|
||||
if (connector)
|
||||
return connector;
|
||||
return new QDBusAdaptorConnector(obj);
|
||||
}
|
||||
|
||||
QString QDBusAbstractAdaptorPrivate::retrieveIntrospectionXml(QDBusAbstractAdaptor *adaptor)
|
||||
{
|
||||
return adaptor->d->xml;
|
||||
}
|
||||
|
||||
void QDBusAbstractAdaptorPrivate::saveIntrospectionXml(QDBusAbstractAdaptor *adaptor,
|
||||
const QString &xml)
|
||||
{
|
||||
adaptor->d->xml = xml;
|
||||
}
|
||||
|
||||
/*!
|
||||
\page UsingAdaptors Using Adaptors
|
||||
|
||||
Adaptors are special classes that are attached to any QObject-derived class and provide the
|
||||
interface to the external world using D-Bus. Adaptors are intended to be light-weight classes
|
||||
whose main purpose is to relay calls to and from the real object, possibly validating or
|
||||
converting the input from the external world and, thus, protecting the real object.
|
||||
|
||||
Unlike multiple inheritance, adaptors can be added at any time to any object (but not removed),
|
||||
which allows for greater flexibility when exporting existing classes. Another advantage of
|
||||
adaptors is to provide similar but not identical functionality in methods of the same name in
|
||||
different interfaces, a case which can be quite common when adding a new version of a standard
|
||||
interface to an object.
|
||||
|
||||
In order to use an adaptor, one must create a class which inherits QDBusAbstractAdaptor. Since
|
||||
that is a standard QObject-derived class, the Q_OBJECT macro must appear in the declaration and
|
||||
the source file must be processed with the \link moc \endlink tool. The class must also contain
|
||||
one or more Q_CLASSINFO entries with the "D-Bus Interface" name, declaring which interfaces it
|
||||
is exporting.
|
||||
|
||||
Any public slot in the class will be accessible through the bus over messages of the MethodCall
|
||||
type. (See \link DeclaringSlots \endlink for more information). Signals in the class will be
|
||||
automatically relayed over D-Bus. However, not all types are allowed signals or slots' parameter
|
||||
lists: see \link AllowedParameters \endlink for more information.
|
||||
|
||||
Also, any property declared with Q_PROPERTY will be automatically exposed over the Properties
|
||||
interface on D-Bus. Since the QObject property system does not allow for non-readable
|
||||
properties, it is not possible to declare write-only properties using adaptors.
|
||||
|
||||
More information:
|
||||
- \subpage DeclaringSlots
|
||||
- \subpage DeclaringSignals
|
||||
- \subpage AllowedParameters
|
||||
- \subpage UsingAnnotations
|
||||
- \subpage AdaptorExample
|
||||
|
||||
\sa QDBusAbstractAdaptor
|
||||
*/
|
||||
|
||||
/*!
|
||||
\page AdaptorExample Example of an interface implemented with an adaptor
|
||||
|
||||
A sample usage of QDBusAbstractAdaptor is as follows:
|
||||
\code
|
||||
class MainApplicationAdaptor: public QDBusAbstractAdaptor
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "com.example.DBus.MainApplication")
|
||||
Q_CLASSINFO("D-Bus Interface", "org.kde.DBus.MainApplication")
|
||||
Q_PROPERTY(QString caption READ caption WRITE setCaption)
|
||||
Q_PROPERTY(QString organizationName READ organizationName)
|
||||
Q_PROPERTY(QString organizationDomain READ organizationDomain)
|
||||
|
||||
private:
|
||||
MyApplication *app;
|
||||
|
||||
public:
|
||||
MyInterfaceAdaptor(MyApplication *application)
|
||||
: QDBusAbstractAdaptor(application), app(application)
|
||||
{
|
||||
connect(application, SIGNAL(aboutToQuit()), SIGNAL(aboutToQuit());
|
||||
connect(application, SIGNAL(focusChanged(QWidget*, QWidget*)),
|
||||
SLOT(focusChangedSlot(QWidget*, QWidget*)));
|
||||
}
|
||||
|
||||
QString caption()
|
||||
{
|
||||
if (app->hasMainWindow())
|
||||
return app->mainWindow()->caption();
|
||||
return QString();
|
||||
}
|
||||
|
||||
void setCaption(const QString &newCaption)
|
||||
{
|
||||
if (app->hasMainWindow())
|
||||
app->mainWindow()->setCaption(newCaption);
|
||||
}
|
||||
|
||||
QString organizationName()
|
||||
{
|
||||
return app->organizationName();
|
||||
}
|
||||
|
||||
QString organizationDomain()
|
||||
{
|
||||
return app->organizationDomain();
|
||||
}
|
||||
|
||||
public slots:
|
||||
async void quit()
|
||||
{ app->quit(); }
|
||||
|
||||
void reparseConfiguration()
|
||||
{ app->reparseConfiguration(); }
|
||||
|
||||
QString mainWindowObject()
|
||||
{
|
||||
if (app->hasMainWindow())
|
||||
return QString("/%1/mainwindow").arg(app->applicationName());
|
||||
return QString();
|
||||
}
|
||||
|
||||
void setSessionManagement(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
app->enableSessionManagement();
|
||||
else
|
||||
app->disableSessionManagement();
|
||||
}
|
||||
|
||||
private slots:
|
||||
void focusChangedSlot(QWidget *, QWidget *now)
|
||||
{
|
||||
if (now == app->mainWindow())
|
||||
emit mainWindowHasFocus();
|
||||
}
|
||||
|
||||
signals:
|
||||
void aboutToQuit();
|
||||
void mainWindowHasFocus();
|
||||
};
|
||||
\endcode
|
||||
|
||||
The code above would create an interface that could be represented more or less in the following
|
||||
canonical representation:
|
||||
\code
|
||||
interface com.example.DBus.MainApplication
|
||||
{
|
||||
property readwrite STRING caption
|
||||
property read STRING organizationName
|
||||
property read STRING organizationDomain
|
||||
|
||||
method quit() annotation("org.freedesktop.DBus.Method.NoReply", "true")
|
||||
method reparseConfiguration()
|
||||
method mainWindowObject(out STRING)
|
||||
method disableSessionManagement(in BOOLEAN enable)
|
||||
|
||||
signal aboutToQuit()
|
||||
signal mainWindowHasFocus()
|
||||
}
|
||||
|
||||
interface org.kde.DBus.MainApplication
|
||||
{
|
||||
....
|
||||
}
|
||||
\endcode
|
||||
|
||||
This adaptor could be used in the application's constructor as follows:
|
||||
\code
|
||||
MyApplication::MyApplication()
|
||||
{
|
||||
[...]
|
||||
|
||||
// create the MainApplication adaptor:
|
||||
new MainApplicationAdaptor(this);
|
||||
|
||||
// connect to D-Bus:
|
||||
QDBusConnection connection = QDBusConnection::addConnection(QDBusConnection::SessionBus);
|
||||
|
||||
// register us as an object:
|
||||
connection.registerObject("/MainApplication", this);
|
||||
|
||||
[...]
|
||||
}
|
||||
\endcode
|
||||
|
||||
Break-down analysis:
|
||||
- \subpage AdaptorExampleHeader
|
||||
- \subpage AdaptorExampleProperties
|
||||
- \subpage AdaptorExampleConstructor
|
||||
- \subpage AdaptorExampleSlots
|
||||
- \subpage AdaptorExampleSignals
|
||||
*/
|
||||
|
||||
/*!
|
||||
\page AdaptorExampleHeader The header
|
||||
|
||||
The header of the example is:
|
||||
\code
|
||||
class MainApplicationAdaptor: public QDBusAbstractAdaptor
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "com.example.DBus.MainApplication")
|
||||
Q_CLASSINFO("D-Bus Interface", "org.kde.DBus.MainApplication")
|
||||
\endcode
|
||||
|
||||
The code does the following:
|
||||
- it declares the adaptor MainApplicationAdaptor, which descends from QDBusAbstractAdaptor
|
||||
- it declares the Qt Meta Object data using the #Q_OBJECT macro
|
||||
- it declares the names of two D-Bus interfaces it implements. Those interfaces are equal in all
|
||||
aspects.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\page AdaptorExampleProperties The properties
|
||||
|
||||
The properties are declared as follows:
|
||||
\code
|
||||
Q_PROPERTY(QString caption READ caption WRITE setCaption)
|
||||
Q_PROPERTY(QString organizationName READ organizationName)
|
||||
Q_PROPERTY(QString organizationDomain READ organizationDomain)
|
||||
\endcode
|
||||
|
||||
And are implemented as follows:
|
||||
\code
|
||||
QString caption()
|
||||
{
|
||||
if (app->hasMainWindow())
|
||||
return app->mainWindow()->caption();
|
||||
return QString();
|
||||
}
|
||||
|
||||
void setCaption(const QString &newCaption)
|
||||
{
|
||||
if (app->hasMainWindow())
|
||||
app->mainWindow()->setCaption(newCaption);
|
||||
}
|
||||
|
||||
QString organizationName()
|
||||
{
|
||||
return app->organizationName();
|
||||
}
|
||||
|
||||
QString organizationDomain()
|
||||
{
|
||||
return app->organizationDomain();
|
||||
}
|
||||
\endcode
|
||||
|
||||
The code declares three properties: one of them is a read-write property called "caption" of
|
||||
string type. The other two are read-only, also of the string type.
|
||||
|
||||
The properties organizationName and organizationDomain are simple relays of the app object's
|
||||
organizationName and organizationDomain properties. However, the caption property requires
|
||||
verifying if the application has a main window associated with it: if there isn't any, the
|
||||
caption property is empty. Note how it is possible to access data defined in other objects
|
||||
through the getter/setter functions.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\page AdaptorExampleConstructor The constructor
|
||||
|
||||
The constructor:
|
||||
\code
|
||||
MyInterfaceAdaptor(MyApplication *application)
|
||||
: QDBusAbstractAdaptor(application), app(application)
|
||||
{
|
||||
connect(application, SIGNAL(aboutToQuit()), SIGNAL(aboutToQuit());
|
||||
connect(application, SIGNAL(focusChanged(QWidget*, QWidget*)),
|
||||
SLOT(focusChangedSlot(QWidget*, QWidget*)));
|
||||
}
|
||||
\endcode
|
||||
|
||||
The constructor does the following:
|
||||
- it initialises its base class (QDBusAbstractAdaptor) with the parent object it is related to.
|
||||
- it stores the app pointer in a member variable. Note that it would be possible to access the
|
||||
same object using the QDBusAbstractAdaptor::object() function, but it would be necessary to
|
||||
use \a static_cast<> to properly access the methods in MyApplication that are not part of
|
||||
QObject.
|
||||
- it connects the application's signal \a aboutToQuit to its own signal \a aboutToQuit.
|
||||
- it connects the application's signal \a focusChanged to a private slot to do some further
|
||||
processing before emitting a D-Bus signal.
|
||||
|
||||
Note that there is no destructor in the example. An eventual destructor could be used to emit
|
||||
one last signal before the object is destroyed, for instance.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\page AdaptorExampleSlots Slots/methods
|
||||
|
||||
The public slots in the example (which will be exported as D-Bus methods) are the following:
|
||||
\code
|
||||
public slots:
|
||||
async void quit()
|
||||
{ app->quit(); }
|
||||
|
||||
void reparseConfiguration()
|
||||
{ app->reparseConfiguration(); }
|
||||
|
||||
QString mainWindowObject()
|
||||
{
|
||||
if (app->hasMainWindow())
|
||||
return QString("/%1/mainwindow").arg(app->applicationName());
|
||||
return QString();
|
||||
}
|
||||
|
||||
void setSessionManagement(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
app->enableSessionManagement();
|
||||
else
|
||||
app->disableSessionManagement();
|
||||
}
|
||||
\endcode
|
||||
|
||||
This snippet of code defines 4 methods with different properties each:
|
||||
- \p quit: this method takes no parameters and is defined to be asynchronous. That is, callers
|
||||
are expected to use "fire-and-forget" mechanism when calling this method, since it provides no
|
||||
useful reply. This is represented in D-Bus by the use of the
|
||||
org.freedesktop.DBus.Method.NoReply annotation. See #Q_ASYNC for more information on
|
||||
asynchronous methods
|
||||
|
||||
- \p reparseConfiguration: this simple method, with no input or output arguments simply relays
|
||||
the call to the application's reparseConfiguration member function.
|
||||
|
||||
- \p mainWindowObject: this method takes no input parameter, but returns one string output
|
||||
argument, containing the path to the main window object (if the application has a main
|
||||
window), or an empty string if it has no main window. Note that this method could have also
|
||||
been written: void mainWindowObject(QString &path).
|
||||
|
||||
- \p setSessionManagement: this method takes one input argument (a boolean) and, depending on
|
||||
its value, it calls one function or another in the application.
|
||||
|
||||
\sa #Q_ASYNC
|
||||
*/
|
||||
|
||||
/*!
|
||||
\page AdaptorExampleSignals Signals
|
||||
|
||||
The signals in this example are defined as follows:
|
||||
\code
|
||||
signals:
|
||||
void aboutToQuit();
|
||||
void mainWindowHasFocus();
|
||||
\endcode
|
||||
|
||||
However, signal definition isn't enough: signals have to be emitted. One simple way of emitting
|
||||
signals is to connect another signal to them, so that Qt's signal handling system chains them
|
||||
automatically. This is what is done for the \a aboutToQuit signal (see \ref
|
||||
AdaptorExampleConstructor).
|
||||
|
||||
When this is the case, one can use the QDBusAbstractAdaptor::setAutoRelaySignals to
|
||||
automatically connect every signal from the real object to the adaptor.
|
||||
|
||||
When simple signal-to-signal connection isn't enough, one can use a private slot do do some
|
||||
work. This is what was done for the mainWindowHasFocus signal:
|
||||
\code
|
||||
private slots:
|
||||
void focusChangedSlot(QWidget *, QWidget *now)
|
||||
{
|
||||
if (now == app->mainWindow())
|
||||
emit mainWindowHasFocus();
|
||||
}
|
||||
\endcode
|
||||
|
||||
This private slot (which will not be exported as a method via D-Bus) was connected to the
|
||||
\a focusChanged signal in the adaptor's constructor. It is therefore able to shape the
|
||||
application's signal into what the interface expects it to be.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\page DeclaringSlots Declaring slots
|
||||
|
||||
Slots in D-Bus adaptors are declared just like normal, public slots, but their parameters must
|
||||
follow certain rules (see \ref AllowedParameters for more information). Slots whose parameters
|
||||
do not follow those rules or that are not public will not be accessible via D-Bus.
|
||||
|
||||
Slots can be of three kinds:
|
||||
-# Asynchronous
|
||||
-# Input-only
|
||||
-# Input-and-output
|
||||
|
||||
\par Asynchronous slots
|
||||
Asynchronous slots are those that do not normally return any reply to the caller. For that
|
||||
reason, they cannot take any output parameters. In most cases, by the time the first line
|
||||
of the slot is run, the caller function has already resumed working.
|
||||
|
||||
\par
|
||||
However, slots must rely on that behavior. Scheduling and message-dispatching issues could
|
||||
change the order in which the slot is run. Code intending to synchronize with the caller
|
||||
should provide its own method of synchronization.
|
||||
|
||||
\par
|
||||
Asynchronous slots are marked by the keyword \p #async or \p #Q_ASYNC in the method
|
||||
signature, before the \p void return type and the slot name. (See the \p quit slot in the
|
||||
\ref AdaptorExample "adaptor example").
|
||||
|
||||
\par Input-only slots
|
||||
Input-only slots are normal slots that take parameters passed by value or by constant
|
||||
reference. However, unlike asynchronous slots, the caller is usually waiting for completion
|
||||
of the callee before resuming operation. Therefore, non-asynchronous slots should not block
|
||||
or should state it its documentation that they may do so.
|
||||
|
||||
\par
|
||||
Input-only slots have no special marking in their signature, except that they take only
|
||||
parameters passed by value or by constant reference. Optionally, slots can take a
|
||||
QDBusMessage parameter as a last parameter, which can be used to perform additional
|
||||
analysis of the method call message.
|
||||
|
||||
\par Input and output slots
|
||||
Like input-only slots, input-and-output slots are those that the caller is waiting for a
|
||||
reply. Unlike input-only ones, though, this reply will contain data. Slots that output data
|
||||
may contain non-constant references and may return a value as well. However, the output
|
||||
parameters must all appear at the end of the argument list and may not have input arguments
|
||||
interleaved. Optionally, a QDBusMessage argument may appear between the input and the
|
||||
output arguments.
|
||||
|
||||
\note When a caller places a method call and waits for a reply, it will only wait for so long.
|
||||
Slots intending to take a long time to complete should make that fact clear in
|
||||
documentation so that callers properly set higher timeouts.
|
||||
|
||||
Method replies are generated automatically with the contents of the output parameters (if there
|
||||
were any) by the QtDBus implementation. Slots need not worry about constructing proper
|
||||
QDBusMessage objects and sending them over the connection.
|
||||
|
||||
However, the possibility of doing so remains there. Should the slot find out it needs to send a
|
||||
special reply or even an error, it can do so by using QDBusMessage::methodReply or
|
||||
QDBusMessage::error on the QDBusMessage parameter and send it with QDBusConnection::send. The
|
||||
QtDBus implementation will not generate any reply if the slot did so.
|
||||
|
||||
\sa \ref UsingAdaptors, \ref DeclaringSignals, \ref AllowedParameters, QDBusConnection,
|
||||
QDBusMessage
|
||||
*/
|
||||
|
||||
/*!
|
||||
\page DeclaringSignals Declaring signals
|
||||
|
||||
Any signal in a class derived from QDBusAbstractAdaptor will be automatically relayed into
|
||||
D-Bus, provided that the signal's parameters conform to certain rules (see \ref
|
||||
AllowedParameters for more information). No special code is necessary to make this relay.
|
||||
|
||||
However, signals must still be emitted. The easiest way to emit an adaptor signal is to connect
|
||||
another signal to it, so that the Qt signal/slot mechanism automatically emits the adaptor
|
||||
signal too. This can be done in the adaptor's constructor, as has been done in the \ref
|
||||
AdaptorExample "adaptor example".
|
||||
|
||||
The convenience function QDBusAbstractAdaptor::setAutoRelaySignals can also be used to connect
|
||||
or disconnect every signal in the real object to the same signal in the adaptor. It will inspect
|
||||
the list of signals in both classes and connect those that have exact parameter match.
|
||||
|
||||
\sa \ref UsingAdaptors, \ref DeclaringSlots, \ref AllowedParameters, QDBusAbstractAdaptor
|
||||
*/
|
||||
|
||||
/*!
|
||||
\page AllowedParameters Allowed parameter types
|
||||
|
||||
D-Bus has a very limited set of types that can be sent and received over the bus. They are
|
||||
listed below, along with the D-Bus type they relate to:
|
||||
- unsigned char / uchar (BYTE)
|
||||
- short (INT16)
|
||||
- unsigned short / ushort (UINT16)
|
||||
- int (INT32)
|
||||
- unsigned int / uint (UINT32)
|
||||
- qlonglong (INT64)
|
||||
- qulonglong (UINT64)
|
||||
- bool (BOOLEAN)
|
||||
- double (DOUBLE)
|
||||
- QString (STRING)
|
||||
- QByteArray (ARRAY of BYTE)
|
||||
- QStringList (ARRAY of STRING)
|
||||
- QVariant / QDBusVariant (VARIANT)
|
||||
- QVariantList (ARRAY of VARIANT)
|
||||
- QVariantMap (ARRAY of DICT_ENTRY of (STRING, VARIANT))
|
||||
|
||||
The last two types may be used to receive any array (except string and byte arrays), any structs
|
||||
and any maps. However, it is currently not possible to generate external function definitions
|
||||
containing specific types of lists, structs and maps.
|
||||
|
||||
All of the types above may be passed by value or by constant reference for input arguments to
|
||||
slots as well as the output arguments to signals. When used as output arguments for slots, they
|
||||
can all be used as non-constant references or the return type.
|
||||
|
||||
Additionally, slots can have one parameter of type \p const \p QDBusMessage \p \&, which must
|
||||
appear at the end of the input parameter list, before any output parameters. Signals cannot have
|
||||
this parameter.
|
||||
|
||||
\warning You may not use any type that is not on the list above, including \a typedefs to the
|
||||
types listed. This also includes QList<QVariant> and QMap<QString,QVariant>.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\page UsingAnnotations Using annotations in adaptors
|
||||
|
||||
It is currently not possible to specify arbitrary annotations in adaptors.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QDBusAbstractAdaptor
|
||||
\brief Abstract adaptor for 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 (see object()) 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.
|
||||
|
||||
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 \ref UsingAdaptors, QDBusConnection
|
||||
*/
|
||||
|
||||
/*!
|
||||
Constructs a QDBusAbstractAdaptor with \a parent as the object we refer to.
|
||||
|
||||
\param parent the real object we're the adaptor for
|
||||
|
||||
\warning Use object() to retrieve the object passed as \a parent to this constructor. The real
|
||||
parent object (as retrieved by QObject::parent()) may be something else.
|
||||
*/
|
||||
QDBusAbstractAdaptor::QDBusAbstractAdaptor(QObject* parent)
|
||||
: d(new QDBusAbstractAdaptorPrivate)
|
||||
{
|
||||
QDBusAdaptorConnector *connector = qDBusCreateAdaptorConnector(parent);
|
||||
setParent(connector);
|
||||
|
||||
connector->waitingForPolish = true;
|
||||
QTimer::singleShot(0, connector, SLOT(polish()));
|
||||
}
|
||||
|
||||
/*!
|
||||
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()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the QObject that we're the adaptor for. This is the same object that was passed as an
|
||||
argument to the QDBusAbstractAdaptor constructor.
|
||||
*/
|
||||
QObject* QDBusAbstractAdaptor::object() const
|
||||
{
|
||||
return parent()->parent();
|
||||
}
|
||||
|
||||
/*!
|
||||
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.
|
||||
|
||||
\param enable if 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();
|
||||
for (int idx = staticMetaObject.methodCount(); idx < us->methodCount(); ++idx) {
|
||||
QMetaMethod mm = us->method(idx);
|
||||
|
||||
|
|
@ -46,19 +649,165 @@ void QDBusAbstractAdaptor::setAutoRelaySignals(bool enable)
|
|||
continue;
|
||||
|
||||
// try to connect/disconnect to a signal on the parent that has the same method signature
|
||||
QByteArray sig = mm.signature();
|
||||
QByteArray sig = QMetaObject::normalizedSignature(mm.signature());
|
||||
if (them->indexOfSignal(sig) == -1)
|
||||
continue;
|
||||
sig.prepend(QSIGNAL_CODE + '0');
|
||||
object()->disconnect(sig, this, sig);
|
||||
if (enable)
|
||||
connect(parent(), sig, sig);
|
||||
else
|
||||
parent()->disconnect(sig, this, sig);
|
||||
connect(object(), sig, sig, Qt::QueuedConnection);
|
||||
}
|
||||
}
|
||||
|
||||
void QDBusAbstractAdaptor::polish()
|
||||
QDBusAdaptorConnector::QDBusAdaptorConnector(QObject *parent)
|
||||
: QObject(parent), waitingForPolish(false), lastSignalIdx(0), argv(0)
|
||||
{
|
||||
// future work:
|
||||
// connect every signal in this adaptor to a slot that will relay them into D-Bus
|
||||
}
|
||||
|
||||
QDBusAdaptorConnector::~QDBusAdaptorConnector()
|
||||
{
|
||||
}
|
||||
|
||||
void QDBusAdaptorConnector::addAdaptor(QDBusAbstractAdaptor *adaptor)
|
||||
{
|
||||
// find the interface name
|
||||
const QMetaObject *mo = adaptor->metaObject();
|
||||
while (mo != &QDBusAbstractAdaptor::staticMetaObject) {
|
||||
int ciend = mo->classInfoCount();
|
||||
for (int i = mo->classInfoOffset(); i < ciend; ++i) {
|
||||
QMetaClassInfo mci = mo->classInfo(i);
|
||||
if (strcmp(mci.name(), QCLASSINFO_DBUS_INTERFACE) == 0 && *mci.value()) {
|
||||
// find out if this interface exists first
|
||||
QString interface = QString::fromUtf8(mci.value());
|
||||
AdaptorMap::Iterator it = qLowerBound(adaptors.begin(), adaptors.end(), interface);
|
||||
if (it != adaptors.end() && it->interface == interface) {
|
||||
// exists. Replace it (though it's probably the same)
|
||||
it->adaptor = adaptor;
|
||||
it->metaObject = mo;
|
||||
} else {
|
||||
// create a new one
|
||||
AdaptorData entry;
|
||||
entry.interface = interface;
|
||||
entry.adaptor = adaptor;
|
||||
entry.metaObject = mo;
|
||||
adaptors << entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mo = mo->superClass();
|
||||
}
|
||||
|
||||
// connect the adaptor's signals to our relaySlot slot
|
||||
mo = adaptor->metaObject();
|
||||
for (int i = QDBusAbstractAdaptor::staticMetaObject.methodCount();
|
||||
i < mo->methodCount(); ++i) {
|
||||
QMetaMethod mm = mo->method(i);
|
||||
|
||||
if (mm.methodType() != QMetaMethod::Signal)
|
||||
continue;
|
||||
|
||||
QByteArray sig = mm.signature();
|
||||
sig.prepend(QSIGNAL_CODE + '0');
|
||||
disconnect(adaptor, sig, this, SLOT(relaySlot()));
|
||||
connect(adaptor, sig, this, SLOT(relaySlot()));
|
||||
}
|
||||
}
|
||||
|
||||
void QDBusAdaptorConnector::polish()
|
||||
{
|
||||
if (!waitingForPolish)
|
||||
return; // avoid working multiple times if multiple adaptors were added
|
||||
|
||||
waitingForPolish = false;
|
||||
const QObjectList &objs = children();
|
||||
foreach (QObject *obj, objs) {
|
||||
Q_ASSERT(qobject_cast<QDBusAbstractAdaptor *>(obj));
|
||||
|
||||
QDBusAbstractAdaptor *adaptor = static_cast<QDBusAbstractAdaptor *>(obj);
|
||||
addAdaptor(adaptor);
|
||||
}
|
||||
|
||||
// sort the adaptor list
|
||||
qSort(adaptors);
|
||||
}
|
||||
|
||||
void QDBusAdaptorConnector::relaySlot()
|
||||
{
|
||||
relay(sender());
|
||||
}
|
||||
|
||||
void QDBusAdaptorConnector::relay(QObject *sender)
|
||||
{
|
||||
// we're being called because there is a signal being emitted that we must relay
|
||||
Q_ASSERT(lastSignalIdx);
|
||||
Q_ASSERT(argv);
|
||||
Q_ASSERT(senderMetaObject);
|
||||
|
||||
if (senderMetaObject != sender->metaObject()) {
|
||||
qWarning("Inconsistency detected: QDBusAdaptorConnector::relay got called with unexpected sender object!");
|
||||
} else {
|
||||
QMetaMethod mm = senderMetaObject->method(lastSignalIdx);
|
||||
QObject *object = static_cast<QDBusAbstractAdaptor *>(sender)->object();
|
||||
|
||||
// break down the parameter list
|
||||
QList<int> types;
|
||||
QByteArray signature = QMetaObject::normalizedSignature(mm.signature());
|
||||
int inputCount = qDBusParametersForMethod(signature, types);
|
||||
if (inputCount == -1)
|
||||
// invalid signal signature
|
||||
// qDBusParametersForMethod has already complained
|
||||
return;
|
||||
if (inputCount + 1 != types.count() ||
|
||||
types.at(inputCount) == QDBusConnectionPrivate::messageMetaType) {
|
||||
// invalid signal signature
|
||||
// qDBusParametersForMethod has not yet complained about this one
|
||||
qWarning("Cannot relay signal %s::%s", senderMetaObject->className(), mm.signature());
|
||||
return;
|
||||
}
|
||||
|
||||
signature.truncate(signature.indexOf('(')); // remove parameter decoration
|
||||
|
||||
QVariantList args;
|
||||
for (int i = 1; i < types.count(); ++i)
|
||||
args << QVariant(types.at(i), argv[i]);
|
||||
|
||||
// find all the interfaces this signal belongs to
|
||||
for (const QMetaObject *mo = senderMetaObject; mo != &QDBusAbstractAdaptor::staticMetaObject;
|
||||
mo = mo->superClass()) {
|
||||
if (lastSignalIdx < mo->methodOffset())
|
||||
break;
|
||||
|
||||
for (int i = mo->classInfoOffset(); i < mo->classInfoCount(); ++i) {
|
||||
QMetaClassInfo mci = mo->classInfo(i);
|
||||
if (qstrcmp(mci.name(), QCLASSINFO_DBUS_INTERFACE) == 0 && *mci.value())
|
||||
// now emit the signal with all the information
|
||||
emit relaySignal(object, mci.value(), signature.constData(), args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QDBusAdaptorConnector::signalBeginCallback(QObject *caller, int method_index, void **argv)
|
||||
{
|
||||
QDBusAdaptorConnector *data = qobject_cast<QDBusAdaptorConnector *>(caller->parent());
|
||||
if (data) {
|
||||
data->lastSignalIdx = method_index;
|
||||
data->argv = argv;
|
||||
data->senderMetaObject = caller->metaObject();
|
||||
data->polish(); // make sure it's polished
|
||||
}
|
||||
}
|
||||
|
||||
void QDBusAdaptorConnector::signalEndCallback(QObject *caller, int)
|
||||
{
|
||||
QDBusAdaptorConnector *data = qobject_cast<QDBusAdaptorConnector *>(caller->parent());
|
||||
if (data) {
|
||||
data->lastSignalIdx = 0;
|
||||
data->argv = 0;
|
||||
data->senderMetaObject = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#include "qdbusabstractadaptor.moc"
|
||||
#include "qdbusabstractadaptor_p.moc"
|
||||
|
|
|
|||
|
|
@ -27,18 +27,24 @@
|
|||
#include <QtCore/qobject.h>
|
||||
#include "qdbusmacros.h"
|
||||
|
||||
class QDBusAbstractAdaptorPrivate;
|
||||
class QDBUS_EXPORT QDBusAbstractAdaptor: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
protected:
|
||||
QDBusAbstractAdaptor(QObject *parent);
|
||||
|
||||
public:
|
||||
QDBusAbstractAdaptor(QObject* parent);
|
||||
~QDBusAbstractAdaptor();
|
||||
|
||||
QObject *object() const;
|
||||
|
||||
protected:
|
||||
void setAutoRelaySignals(bool enable);
|
||||
|
||||
private slots:
|
||||
void polish();
|
||||
private:
|
||||
friend class QDBusAbstractAdaptorPrivate;
|
||||
QDBusAbstractAdaptorPrivate *d;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
127
qt/qdbusabstractadaptor_p.h
Normal file
127
qt/qdbusabstractadaptor_p.h
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
/* -*- mode: C++; set-fill-width: 100 -*-
|
||||
*
|
||||
* Copyright (C) 2006 Trolltech AS. All rights reserved.
|
||||
* Author: Thiago Macieira <thiago.macieira@trolltech.com>
|
||||
*
|
||||
* Licensed under the Academic Free License version 2.1
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
// 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 <QtCore/qobject.h>
|
||||
#include <QtCore/qmap.h>
|
||||
#include <QtCore/qhash.h>
|
||||
#include <QtCore/qreadwritelock.h>
|
||||
#include <QtCore/qvariant.h>
|
||||
#include <QtCore/qvector.h>
|
||||
|
||||
#define QCLASSINFO_DBUS_INTERFACE "D-Bus Interface"
|
||||
#define QCLASSINFO_DBUS_INTROSPECTION "D-Bus Introspection"
|
||||
|
||||
class QDBusAbstractAdaptor;
|
||||
class QDBusAdaptorConnector;
|
||||
class QDBusAdaptorManager;
|
||||
class QDBusConnectionPrivate;
|
||||
|
||||
#if QT_VERSION < 0x040200
|
||||
/* mirrored in qobject_p.h, DON'T CHANGE without prior warning */
|
||||
struct QSignalSpyCallbackSet
|
||||
{
|
||||
typedef void (*BeginCallback)(QObject *caller, int method_index, void **argv);
|
||||
typedef void (*EndCallback)(QObject *caller, int method_index);
|
||||
BeginCallback signal_begin_callback,
|
||||
slot_begin_callback;
|
||||
EndCallback signal_end_callback,
|
||||
slot_end_callback;
|
||||
};
|
||||
#else
|
||||
# error Qt 4.2.0 is supposed to have a better solution!
|
||||
CHOKE!
|
||||
#endif // Qt 4.2.0
|
||||
|
||||
class QDBusAbstractAdaptorPrivate
|
||||
{
|
||||
public:
|
||||
QString xml;
|
||||
|
||||
static QString retrieveIntrospectionXml(QDBusAbstractAdaptor *adaptor);
|
||||
static void saveIntrospectionXml(QDBusAbstractAdaptor *adaptor, const QString &xml);
|
||||
};
|
||||
|
||||
class QDBusAdaptorConnector: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public: // typedefs
|
||||
struct AdaptorData
|
||||
{
|
||||
QString interface;
|
||||
QDBusAbstractAdaptor *adaptor;
|
||||
const QMetaObject *metaObject;
|
||||
|
||||
inline bool operator<(const AdaptorData &other) const
|
||||
{ return interface < other.interface; }
|
||||
inline bool operator<(const QString &other) const
|
||||
{ return interface < other; }
|
||||
};
|
||||
typedef QVector<AdaptorData> AdaptorMap;
|
||||
|
||||
public: // methods
|
||||
explicit QDBusAdaptorConnector(QObject *parent);
|
||||
~QDBusAdaptorConnector();
|
||||
|
||||
void addAdaptor(QDBusAbstractAdaptor *adaptor);
|
||||
void relay(QObject *sender);
|
||||
|
||||
public slots:
|
||||
void relaySlot();
|
||||
void polish();
|
||||
|
||||
signals:
|
||||
void relaySignal(QObject *obj, const char *interface, const char *name, const QVariantList &args);
|
||||
|
||||
public: // member variables
|
||||
AdaptorMap adaptors;
|
||||
bool waitingForPolish : 1;
|
||||
|
||||
int lastSignalIdx;
|
||||
void **argv;
|
||||
const QMetaObject *senderMetaObject;
|
||||
|
||||
public: // static members
|
||||
static void signalBeginCallback(QObject *caller, int method_index, void **argv);
|
||||
static void signalEndCallback(QObject *caller, int method_index);
|
||||
//static int id;
|
||||
};
|
||||
|
||||
extern QDBusAdaptorConnector *qDBusFindAdaptorConnector(QObject *object);
|
||||
extern QDBusAdaptorConnector *qDBusCreateAdaptorConnector(QObject *object);
|
||||
|
||||
#endif // QDBUSABSTRACTADAPTORPRIVATE_H
|
||||
|
|
@ -33,12 +33,10 @@
|
|||
#include "qdbusobject_p.h"
|
||||
#include "qdbusutil.h"
|
||||
|
||||
QT_STATIC_CONST_IMPL char *QDBusConnection::default_connection_name = "qt_dbus_default_connection";
|
||||
|
||||
class QDBusConnectionManager
|
||||
{
|
||||
public:
|
||||
QDBusConnectionManager(): default_connection(0) {}
|
||||
QDBusConnectionManager() {}
|
||||
~QDBusConnectionManager();
|
||||
void bindToApplication();
|
||||
QDBusConnectionPrivate *connection(const QString &name) const;
|
||||
|
|
@ -46,7 +44,7 @@ public:
|
|||
void setConnection(const QString &name, QDBusConnectionPrivate *c);
|
||||
|
||||
private:
|
||||
QDBusConnectionPrivate *default_connection;
|
||||
mutable QMutex mutex;
|
||||
QHash<QString, QDBusConnectionPrivate *> connectionHash;
|
||||
};
|
||||
|
||||
|
|
@ -54,29 +52,22 @@ Q_GLOBAL_STATIC(QDBusConnectionManager, manager);
|
|||
|
||||
QDBusConnectionPrivate *QDBusConnectionManager::connection(const QString &name) const
|
||||
{
|
||||
return name == QLatin1String(QDBusConnection::default_connection_name) ?
|
||||
default_connection : connectionHash.value(name, 0);
|
||||
QMutexLocker locker(&mutex);
|
||||
return connectionHash.value(name, 0);
|
||||
}
|
||||
|
||||
void QDBusConnectionManager::removeConnection(const QString &name)
|
||||
{
|
||||
QMutexLocker locker(&mutex);
|
||||
|
||||
QDBusConnectionPrivate *d = 0;
|
||||
if (name == QLatin1String(QDBusConnection::default_connection_name)) {
|
||||
d = default_connection;
|
||||
default_connection = 0;
|
||||
} else {
|
||||
d = connectionHash.take(name);
|
||||
}
|
||||
if (!d->ref.deref())
|
||||
d = connectionHash.take(name);
|
||||
if (d && !d->ref.deref())
|
||||
delete d;
|
||||
}
|
||||
|
||||
QDBusConnectionManager::~QDBusConnectionManager()
|
||||
{
|
||||
if (default_connection) {
|
||||
delete default_connection;
|
||||
default_connection = 0;
|
||||
}
|
||||
for (QHash<QString, QDBusConnectionPrivate *>::const_iterator it = connectionHash.constBegin();
|
||||
it != connectionHash.constEnd(); ++it) {
|
||||
delete it.value();
|
||||
|
|
@ -86,9 +77,7 @@ QDBusConnectionManager::~QDBusConnectionManager()
|
|||
|
||||
void QDBusConnectionManager::bindToApplication()
|
||||
{
|
||||
if (default_connection) {
|
||||
default_connection->bindToApplication();
|
||||
}
|
||||
QMutexLocker locker(&mutex);
|
||||
for (QHash<QString, QDBusConnectionPrivate *>::const_iterator it = connectionHash.constBegin();
|
||||
it != connectionHash.constEnd(); ++it) {
|
||||
(*it)->bindToApplication();
|
||||
|
|
@ -102,13 +91,117 @@ void qDBusBindToApplication()
|
|||
|
||||
void QDBusConnectionManager::setConnection(const QString &name, QDBusConnectionPrivate *c)
|
||||
{
|
||||
if (name == QLatin1String(QDBusConnection::default_connection_name))
|
||||
default_connection = c;
|
||||
else
|
||||
connectionHash[name] = c;
|
||||
connectionHash[name] = c;
|
||||
c->name = name;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn QDBusConnection QDBus::sessionBus()
|
||||
|
||||
Returns a QDBusConnection object opened with the session bus. The object reference returned
|
||||
by this function is valid until the QCoreApplication's destructor is run, when the
|
||||
connection will be closed and the object, deleted.
|
||||
*/
|
||||
/*!
|
||||
\fn QDBusConnection QDBus::systemBus()
|
||||
|
||||
Returns a QDBusConnection object opened with the system bus. The object reference returned
|
||||
by this function is valid until the QCoreApplication's destructor is run, when the
|
||||
connection will be closed and the object, deleted.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QDBusConnection
|
||||
\brief A connection to the D-Bus bus daemon.
|
||||
|
||||
This class is the initial point in a D-Bus session. Using it, you can get access to remote
|
||||
objects, interfaces; connect remote signals to your object's slots; register objects, etc.
|
||||
|
||||
D-Bus connections are created using the QDBusConnection::addConnection function, which opens a
|
||||
connection to the server daemon and does the initial handshaking, associating that connection
|
||||
with a name. Further attempts to connect using the same name will return the same
|
||||
connection.
|
||||
|
||||
The connection is then torn down using the QDBusConnection::closeConnection function.
|
||||
|
||||
As a convenience for the two most common connection types, the QDBus::sessionBus and
|
||||
QDBus::systemBus functions return open connections to the session server daemon and the system
|
||||
server daemon, respectively. Those connections are opened when first used and are closed when
|
||||
the QCoreApplication destructor is run.
|
||||
|
||||
D-Bus also supports peer-to-peer connections, without the need for a bus server daemon. Using
|
||||
this facility, two applications can talk to each other and exchange messages. This can be
|
||||
achieved by passing an address to QDBusConnection::addConnection(const QString &, const QString
|
||||
&) function, which was opened by another D-Bus application using QDBusServer.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum QDBusConnection::BusType
|
||||
Specifies the type of the bus connection. The valid bus types are:
|
||||
|
||||
\value SessionBus the session bus, associated with the running desktop session
|
||||
\value SystemBus the system bus, used to communicate with system-wide processes
|
||||
\value ActivationBus the activation bus, whose purpose I have no idea...
|
||||
|
||||
On the Session Bus, one can find other applications by the same user that are sharing the same
|
||||
desktop session (hence the name). On the System Bus, however, processes shared for the whole
|
||||
system are usually found.
|
||||
|
||||
\todo Find out what the ActivationBus is for
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum QDBusConnection::NameRequestMode
|
||||
Specifies the flags for when requesting a name in the bus.
|
||||
|
||||
\bug Change the enum into flags and update with the new flags from the spec.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum QDBusConnection::RegisterOption
|
||||
Specifies the options for registering objects with the connection. The possible values are:
|
||||
|
||||
\value ExportAdaptors export the contents of adaptors found in this object
|
||||
|
||||
\value ExportSlots export this object's scriptable slots
|
||||
\value ExportSignals export this object's scriptable signals
|
||||
\value ExportProperties export this object's scriptable properties
|
||||
\value ExportContents shorthand form for ExportSlots | ExportSignals |
|
||||
ExportProperties
|
||||
|
||||
\value ExportNonScriptableSlots export all of this object's slots, including
|
||||
non-scriptable ones
|
||||
\value ExportNonScriptableSignals export all of this object's signals, including
|
||||
non-scriptable ones
|
||||
\value ExportNonScriptableProperties export all of this object's properties, including
|
||||
non-scriptable ones
|
||||
\value ExportNonScriptableContents export all of this object's slots, signals and
|
||||
properties, including non-scriptable ones
|
||||
|
||||
\value ExportChildObjects export this object's child objects
|
||||
|
||||
\note It is currently not possible to export signals from objects. If you pass the flag
|
||||
ExportSignals or ExportNonScriptableSignals, the registerObject() function will print a warning.
|
||||
|
||||
\sa QDBusConnection::registerObject, QDBusAbstractAdaptor, \ref UsingAdaptors
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum QDBusConnection::UnregisterMode
|
||||
The mode for unregistering an object path:
|
||||
|
||||
\value UnregisterNode unregister this node only: do not unregister child objects
|
||||
\value UnregisterTree unregister this node and all its sub-tree
|
||||
|
||||
Note, however, if this object was registered with the ExportChildObjects option, UnregisterNode
|
||||
will unregister the child objects too.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Creates a QDBusConnection object attached to the connection with name \p name.
|
||||
|
||||
This does not open the connection. You have to call QDBusConnection::addConnection to open it.
|
||||
*/
|
||||
QDBusConnection::QDBusConnection(const QString &name)
|
||||
{
|
||||
d = manager()->connection(name);
|
||||
|
|
@ -116,6 +209,9 @@ QDBusConnection::QDBusConnection(const QString &name)
|
|||
d->ref.ref();
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a copy of the \p other connection.
|
||||
*/
|
||||
QDBusConnection::QDBusConnection(const QDBusConnection &other)
|
||||
{
|
||||
d = other.d;
|
||||
|
|
@ -123,12 +219,21 @@ QDBusConnection::QDBusConnection(const QDBusConnection &other)
|
|||
d->ref.ref();
|
||||
}
|
||||
|
||||
/*!
|
||||
Disposes of this object. This does not close the connection: you have to call
|
||||
QDBusConnection::closeConnection to do that.
|
||||
*/
|
||||
QDBusConnection::~QDBusConnection()
|
||||
{
|
||||
if (d && !d->ref.deref())
|
||||
delete d;
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a copy of the connection \p other in this object. The connection this object referenced
|
||||
before the copy is not spontaneously disconnected. See QDBusConnection::closeConnection for more
|
||||
information.
|
||||
*/
|
||||
QDBusConnection &QDBusConnection::operator=(const QDBusConnection &other)
|
||||
{
|
||||
if (other.d)
|
||||
|
|
@ -141,13 +246,17 @@ QDBusConnection &QDBusConnection::operator=(const QDBusConnection &other)
|
|||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
Opens a connection of type \p type to one of the known busses and associate with it the
|
||||
connection name \p name. Returns a QDBusConnection object associated with that connection.
|
||||
*/
|
||||
QDBusConnection QDBusConnection::addConnection(BusType type, const QString &name)
|
||||
{
|
||||
// Q_ASSERT_X(QCoreApplication::instance(), "QDBusConnection::addConnection",
|
||||
// "Cannot create connection without a Q[Core]Application instance");
|
||||
|
||||
QDBusConnectionPrivate *d = manager()->connection(name);
|
||||
if (d)
|
||||
if (d || name.isEmpty())
|
||||
return QDBusConnection(name);
|
||||
|
||||
d = new QDBusConnectionPrivate;
|
||||
|
|
@ -170,6 +279,10 @@ QDBusConnection QDBusConnection::addConnection(BusType type, const QString &name
|
|||
return QDBusConnection(name);
|
||||
}
|
||||
|
||||
/*!
|
||||
Opens a peer-to-peer connection on address \p address and associate with it the
|
||||
connection name \p name. Returns a QDBusConnection object associated with that connection.
|
||||
*/
|
||||
QDBusConnection QDBusConnection::addConnection(const QString &address,
|
||||
const QString &name)
|
||||
{
|
||||
|
|
@ -177,7 +290,7 @@ QDBusConnection QDBusConnection::addConnection(const QString &address,
|
|||
// "Cannot create connection without a Q[Core]Application instance");
|
||||
|
||||
QDBusConnectionPrivate *d = manager()->connection(name);
|
||||
if (d)
|
||||
if (d || name.isEmpty())
|
||||
return QDBusConnection(name);
|
||||
|
||||
d = new QDBusConnectionPrivate;
|
||||
|
|
@ -189,6 +302,13 @@ QDBusConnection QDBusConnection::addConnection(const QString &address,
|
|||
return QDBusConnection(name);
|
||||
}
|
||||
|
||||
/*!
|
||||
Closes the connection of name \p name.
|
||||
|
||||
Note that if there are still QDBusConnection objects associated with the same connection, the
|
||||
connection will not be closed until all references are dropped. However, no further references
|
||||
can be created using the QDBusConnection::QDBusConnection constructor.
|
||||
*/
|
||||
void QDBusConnection::closeConnection(const QString &name)
|
||||
{
|
||||
manager()->removeConnection(name);
|
||||
|
|
@ -200,6 +320,12 @@ void QDBusConnectionPrivate::timerEvent(QTimerEvent *e)
|
|||
dbus_timeout_handle(timeout);
|
||||
}
|
||||
|
||||
/*!
|
||||
Sends the message over this connection, without waiting for a reply. This is suitable for errors,
|
||||
signals, and return values as well as calls whose return values are not necessary.
|
||||
|
||||
\returns true if the message was queued successfully, false otherwise
|
||||
*/
|
||||
bool QDBusConnection::send(const QDBusMessage &message) const
|
||||
{
|
||||
if (!d || !d->connection)
|
||||
|
|
@ -207,6 +333,16 @@ bool QDBusConnection::send(const QDBusMessage &message) const
|
|||
return d->send(message);
|
||||
}
|
||||
|
||||
/*!
|
||||
Sends the message over this connection and returns immediately after queueing it. When the reply
|
||||
is received, the slot \p method is called in the object \p receiver. This function is suitable
|
||||
for method calls only.
|
||||
|
||||
This function guarantees that the slot will be called exactly once with the reply, as long as
|
||||
the parameter types match. If they don't, the reply cannot be delivered.
|
||||
|
||||
\returns true if the message was queued successfully, false otherwise.
|
||||
*/
|
||||
int QDBusConnection::sendWithReplyAsync(const QDBusMessage &message, QObject *receiver,
|
||||
const char *method) const
|
||||
{
|
||||
|
|
@ -216,15 +352,27 @@ int QDBusConnection::sendWithReplyAsync(const QDBusMessage &message, QObject *re
|
|||
return d->sendWithReplyAsync(message, receiver, method);
|
||||
}
|
||||
|
||||
/*!
|
||||
Sends the message over this connection and blocks, waiting for a reply. This function is
|
||||
suitable for method calls only. It returns the reply message as its return value, which will be
|
||||
either of type QDBusMessage::ReplyMessage or QDBusMessage::ErrorMessage.
|
||||
|
||||
See the QDBusInterface::call function for a more friendly way of placing calls.
|
||||
|
||||
\warning This function reenters the Qt event loop in order to wait for the reply, excluding 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 sendWithReply().
|
||||
*/
|
||||
QDBusMessage QDBusConnection::sendWithReply(const QDBusMessage &message) const
|
||||
{
|
||||
if (!d || !d->connection)
|
||||
return QDBusMessage::fromDBusMessage(0);
|
||||
return QDBusMessage::fromDBusMessage(0, *this);
|
||||
|
||||
if (!QCoreApplication::instance()) {
|
||||
DBusMessage *msg = message.toDBusMessage();
|
||||
if (!msg)
|
||||
return QDBusMessage::fromDBusMessage(0);
|
||||
return QDBusMessage::fromDBusMessage(0, *this);
|
||||
|
||||
DBusMessage *reply = dbus_connection_send_with_reply_and_block(d->connection, msg,
|
||||
-1, &d->error);
|
||||
|
|
@ -234,108 +382,229 @@ QDBusMessage QDBusConnection::sendWithReply(const QDBusMessage &message) const
|
|||
if (lastError().isValid())
|
||||
return QDBusMessage::fromError(lastError());
|
||||
|
||||
return QDBusMessage::fromDBusMessage(reply);
|
||||
return QDBusMessage::fromDBusMessage(reply, *this);
|
||||
} else {
|
||||
QDBusReplyWaiter waiter;
|
||||
if (d->sendWithReplyAsync(message, &waiter, SLOT(reply(const QDBusMessage&))) > 0) {
|
||||
// enter the event loop and wait for a reply
|
||||
waiter.exec(QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents);
|
||||
|
||||
|
||||
d->lastError = waiter.replyMsg; // set or clear error
|
||||
return waiter.replyMsg;
|
||||
}
|
||||
|
||||
return QDBusMessage::fromDBusMessage(0);
|
||||
return QDBusMessage::fromDBusMessage(0, *this);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Connects the signal to the slot \p slot in object \p receiver.
|
||||
|
||||
\param service the service that will emit the signal, or QString() to wait for the signal
|
||||
coming from any remote application
|
||||
\param path the path that will emit the signal, or QString() to wait for the signal
|
||||
coming from any object path (usually associated with an empty \p service)
|
||||
\param interface the name of the interface to for this signal
|
||||
\param name the name of the signal
|
||||
\param receiver the object to connect to
|
||||
\param slot the slot that will be invoked when the signal is emitted
|
||||
\returns true if the connection was successful
|
||||
|
||||
\note The signal will only be delivered to the slot if the parameters match. This verification
|
||||
can be done only when the signal is received, not at connection time.
|
||||
|
||||
\bug does not allow an empty service
|
||||
*/
|
||||
bool QDBusConnection::connect(const QString &service, const QString &path, const QString& interface,
|
||||
const QString &name, QObject *receiver, const char *slot)
|
||||
{
|
||||
return connect(service, path, interface, name, QString(), receiver, slot);
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
Connects the signal to the slot \p slot in object \p receiver. Unlike the other
|
||||
QDBusConnection::connect overload, this function allows one to specify the parameter signature
|
||||
to be connected. The function will then verify that this signature can be delivered to the slot
|
||||
specified by \p slot and return false otherwise.
|
||||
|
||||
\bug does not validate signature vs slot yet
|
||||
*/
|
||||
bool QDBusConnection::connect(const QString &service, const QString &path, const QString& interface,
|
||||
const QString &name, const QString &signature,
|
||||
QObject *receiver, const char *slot)
|
||||
{
|
||||
if (!receiver || !slot || !d || !d->connection)
|
||||
if (!receiver || !slot || !d || !d->connection || !QDBusUtil::isValidInterfaceName(interface))
|
||||
return false;
|
||||
|
||||
QString source = getNameOwner(service);
|
||||
if (source.isEmpty())
|
||||
return false;
|
||||
QString source;
|
||||
if (!service.isEmpty()) {
|
||||
source = getNameOwner(service);
|
||||
if (source.isEmpty())
|
||||
return false;
|
||||
}
|
||||
source += path;
|
||||
|
||||
// check the slot
|
||||
QDBusConnectionPrivate::SignalHook hook;
|
||||
if ((hook.midx = QDBusConnectionPrivate::findSlot(receiver, slot + 1, hook.params)) == -1)
|
||||
return false;
|
||||
|
||||
|
||||
hook.interface = interface;
|
||||
hook.name = name;
|
||||
hook.signature = signature;
|
||||
hook.obj = QPointer<QObject>(receiver);
|
||||
hook.obj = receiver;
|
||||
|
||||
d->signalHooks.insertMulti(source, hook);
|
||||
d->connect(receiver, SIGNAL(destroyed(QObject*)), SLOT(objectDestroyed(QObject*)));
|
||||
// avoid duplicating:
|
||||
QDBusConnectionPrivate::SignalHookHash::ConstIterator it = d->signalHooks.find(source);
|
||||
for ( ; it != d->signalHooks.end() && it.key() == source; ++it) {
|
||||
const QDBusConnectionPrivate::SignalHook &entry = it.value();
|
||||
if (entry.interface == hook.interface &&
|
||||
entry.name == hook.name &&
|
||||
entry.signature == hook.signature &&
|
||||
entry.obj == hook.obj &&
|
||||
entry.midx == hook.midx) {
|
||||
// no need to compare the parameters if it's the same slot
|
||||
return true; // already there
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
d->connectSignal(source, hook);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QDBusConnection::registerObject(const QString &path, QObject *object, RegisterOptions options)
|
||||
{
|
||||
return registerObject(path, QString(), object, options);
|
||||
}
|
||||
/*!
|
||||
Registers the object \p object at path \p path and returns true if the registration was
|
||||
successful.
|
||||
|
||||
bool QDBusConnection::registerObject(const QString &path, const QString &interface,
|
||||
QObject *object, RegisterOptions options)
|
||||
This function does not replace existing objects: if there is already an object registered at
|
||||
path \p path, this function will return false. Use unregisterObject() to unregister it first.
|
||||
|
||||
You cannot register an object as a child object of an object that was registered with
|
||||
QDBusConnection::ExportChildObjects.
|
||||
*/
|
||||
bool QDBusConnection::registerObject(const QString &path, QObject *object, RegisterOptions options)
|
||||
{
|
||||
if (!d || !d->connection || !object || !options || !QDBusUtil::isValidObjectPath(path))
|
||||
return false;
|
||||
|
||||
QString iface = interface;
|
||||
if (options & ExportForAnyInterface)
|
||||
iface.clear();
|
||||
|
||||
QDBusConnectionPrivate::ObjectDataHash& hook = d->objectHooks[path];
|
||||
|
||||
// if we're replacing and matching any interface, then we're replacing every interface
|
||||
// this catches ExportAdaptors | Reexport too
|
||||
if (( options & ( ExportForAnyInterface | Reexport )) == ( ExportForAnyInterface | Reexport ))
|
||||
hook.clear();
|
||||
|
||||
// we're not matching any interface, but if we're not replacing, make sure it doesn't exist yet
|
||||
else if (( options & Reexport ) == 0 && hook.find(iface) != hook.end())
|
||||
if (options & ExportSignals) {
|
||||
qWarning("Cannot export signals from objects. Use an adaptor for that purpose.");
|
||||
return false;
|
||||
}
|
||||
|
||||
QDBusConnectionPrivate::ObjectData& data = hook[iface];
|
||||
QStringList pathComponents = path.split(QLatin1Char('/'));
|
||||
if (pathComponents.last().isEmpty())
|
||||
pathComponents.removeLast();
|
||||
QWriteLocker locker(&d->lock);
|
||||
|
||||
data.flags = options;
|
||||
data.obj = object;
|
||||
// lower-bound search for where this object should enter in the tree
|
||||
QDBusConnectionPrivate::ObjectTreeNode *node = &d->rootNode;
|
||||
int i = 1;
|
||||
while (node) {
|
||||
if (pathComponents.count() == i) {
|
||||
// this node exists
|
||||
// consider it free if there's no object here and the user is not trying to
|
||||
// replace the object sub-tree
|
||||
if ((options & ExportChildObjects && !node->children.isEmpty()) || node->obj)
|
||||
return false;
|
||||
|
||||
d->connect(object, SIGNAL(destroyed(QObject*)), SLOT(objectDestroyed(QObject*)));
|
||||
qDebug("REGISTERED FOR %s", path.toLocal8Bit().constData());
|
||||
// we can add the object here
|
||||
node->obj = object;
|
||||
node->flags = options;
|
||||
|
||||
return true; // todo - check for slots etc.
|
||||
d->registerObject(node);
|
||||
qDebug("REGISTERED FOR %s", path.toLocal8Bit().constData());
|
||||
return true;
|
||||
}
|
||||
|
||||
// find the position where we'd insert the node
|
||||
QVector<QDBusConnectionPrivate::ObjectTreeNode::Data>::Iterator it =
|
||||
qLowerBound(node->children.begin(), node->children.end(), pathComponents.at(i));
|
||||
if (it != node->children.constEnd() && it->name == pathComponents.at(i)) {
|
||||
// match: this node exists
|
||||
node = it->node;
|
||||
|
||||
// are we allowed to go deeper?
|
||||
if (node->flags & ExportChildObjects) {
|
||||
// we're not
|
||||
qDebug("Cannot register object at %s because %s exports its own child objects",
|
||||
qPrintable(path), qPrintable(pathComponents.at(i)));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// add entry
|
||||
QDBusConnectionPrivate::ObjectTreeNode::Data entry;
|
||||
entry.name = pathComponents.at(i);
|
||||
entry.node = new QDBusConnectionPrivate::ObjectTreeNode;
|
||||
node->children.insert(it, entry);
|
||||
|
||||
node = entry.node;
|
||||
}
|
||||
|
||||
// iterate
|
||||
++i;
|
||||
}
|
||||
|
||||
Q_ASSERT_X(false, "QDBusConnection::registerObject", "The impossible happened");
|
||||
return false;
|
||||
}
|
||||
|
||||
void QDBusConnection::unregisterObject(const QString &path)
|
||||
/*!
|
||||
Unregisters an object that was registered with the registerObject() function and, if \p mode is
|
||||
QDBusConnection::UnregisterTree, all of its sub-objects too.
|
||||
|
||||
Note that you cannot unregister objects that were not registered with registerObject().
|
||||
*/
|
||||
void QDBusConnection::unregisterObject(const QString &path, UnregisterMode mode)
|
||||
{
|
||||
if (!d || !d->connection)
|
||||
if (!d || !d->connection || !QDBusUtil::isValidObjectPath(path))
|
||||
return;
|
||||
|
||||
d->objectHooks.remove(path);
|
||||
QStringList pathComponents = path.split(QLatin1Char('/'));
|
||||
QWriteLocker locker(&d->lock);
|
||||
QDBusConnectionPrivate::ObjectTreeNode *node = &d->rootNode;
|
||||
int i = 1;
|
||||
|
||||
// find the object
|
||||
while (node) {
|
||||
if (pathComponents.count() == i) {
|
||||
// found it
|
||||
node->obj = 0;
|
||||
node->flags = 0;
|
||||
|
||||
if (mode == UnregisterTree) {
|
||||
// clear the sub-tree as well
|
||||
node->clear(); // can't disconnect the objects because we really don't know if they can
|
||||
// be found somewhere else in the path too
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
QVector<QDBusConnectionPrivate::ObjectTreeNode::Data>::ConstIterator it =
|
||||
qLowerBound(node->children.constBegin(), node->children.constEnd(), pathComponents.at(i));
|
||||
if (it == node->children.constEnd() || it->name != pathComponents.at(i))
|
||||
break; // node not found
|
||||
|
||||
node = it->node;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a QDBusInterface associated with the interface \p interface on object at path \p path on
|
||||
service \p service.
|
||||
*/
|
||||
QDBusInterface QDBusConnection::findInterface(const QString& service, const QString& path,
|
||||
const QString& interface)
|
||||
{
|
||||
// create one
|
||||
QDBusInterfacePrivate *priv = new QDBusInterfacePrivate;
|
||||
priv->conn = *this;
|
||||
QDBusInterfacePrivate *priv = new QDBusInterfacePrivate(*this);
|
||||
|
||||
if (!QDBusUtil::isValidObjectPath(path) || !QDBusUtil::isValidInterfaceName(interface))
|
||||
if (!(interface.isEmpty() || QDBusUtil::isValidInterfaceName(interface)) ||
|
||||
!QDBusUtil::isValidObjectPath(path))
|
||||
return QDBusInterface(priv);
|
||||
|
||||
// check if it's there first
|
||||
|
|
@ -352,28 +621,64 @@ QDBusInterface QDBusConnection::findInterface(const QString& service, const QStr
|
|||
return QDBusInterface(priv); // will increment priv's refcount
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn QDBusConnection::findInterface(const QString &service, const QString &path)
|
||||
Returns an interface of type \p Interface associated with the object on path \p path at service
|
||||
\p service.
|
||||
|
||||
\p Interface must be a class derived from QDBusInterface.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Returns a QDBusObject associated with the object on path \p path at service \p service.
|
||||
*/
|
||||
QDBusObject QDBusConnection::findObject(const QString& service, const QString& path)
|
||||
{
|
||||
QDBusObjectPrivate* priv = 0;
|
||||
if (d && QDBusUtil::isValidObjectPath(path)) {
|
||||
QString owner = getNameOwner(service);
|
||||
|
||||
|
||||
if (!owner.isEmpty())
|
||||
priv = new QDBusObjectPrivate(d, owner, path);
|
||||
}
|
||||
return QDBusObject(priv, *this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Returns true if this QDBusConnection object is connected.
|
||||
|
||||
\note If it isn't connected, calling QDBusConnection::addConnection on the same connection name
|
||||
will not make be connected. You need to call the QDBusConnection constructor again.
|
||||
*/
|
||||
bool QDBusConnection::isConnected( ) const
|
||||
{
|
||||
return d && d->connection && dbus_connection_get_is_connected(d->connection);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the last error that happened in this connection.
|
||||
|
||||
This function is provided for low-level code. If you're using QDBusInterface::call, error codes are
|
||||
reported by its return value.
|
||||
|
||||
\sa QDBusInterface, QDBusMessage
|
||||
*/
|
||||
QDBusError QDBusConnection::lastError() const
|
||||
{
|
||||
return d ? d->lastError : QDBusError();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the unique connection name for this connection, if this QDBusConnection object is
|
||||
connected, or an empty QString otherwise.
|
||||
|
||||
A Unique Connection Name is a string in the form ":x.xxx" (where x are decimal digits) that is
|
||||
assigned by the D-Bus server daemon upon connection. It uniquely identifies this client in the
|
||||
bus.
|
||||
|
||||
This function returns an empty QString for peer-to-peer connections.
|
||||
*/
|
||||
QString QDBusConnection::baseService() const
|
||||
{
|
||||
return d && d->connection ?
|
||||
|
|
@ -381,6 +686,25 @@ QString QDBusConnection::baseService() const
|
|||
: QString();
|
||||
}
|
||||
|
||||
/*!
|
||||
Sends a request to the D-Bus server daemon to request the service name \p name. The flags \p
|
||||
mode indicate how to proceed if the name is already taken or when another D-Bus client requests
|
||||
the same name.
|
||||
|
||||
Service names are used to publish well-known services on the D-Bus bus, by associating a
|
||||
friendly name to this connection. Other D-Bus clients will then be able to contact this
|
||||
connection and the objects registered on it by using this name instead of the unique connection
|
||||
name (see baseService()). This also allows one application to always have the same name, while
|
||||
its unique connection name changes.
|
||||
|
||||
This function has no meaning in peer-to-peer connections.
|
||||
|
||||
This function returns true if the name is assigned to this connection now (including the case
|
||||
when it was already assigned).
|
||||
|
||||
\todo probably move to the QObject representing the bus
|
||||
\todo update the NameRequestMode flags
|
||||
*/
|
||||
bool QDBusConnection::requestName(const QString &name, NameRequestMode mode)
|
||||
{
|
||||
static const int DBusModes[] = { DBUS_NAME_FLAG_ALLOW_REPLACEMENT, 0,
|
||||
|
|
@ -392,6 +716,17 @@ bool QDBusConnection::requestName(const QString &name, NameRequestMode mode)
|
|||
retval == DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
|
||||
}
|
||||
|
||||
/*!
|
||||
Releases a name that had been requested using requestName(). This function returns true if the
|
||||
name has been released, false otherwise.
|
||||
|
||||
This function has no meaning in peer-to-peer connections.
|
||||
|
||||
You cannot cause a name owned by another application to be released using releaseName(). Use
|
||||
requestName() instead to assign it to your application.
|
||||
|
||||
\todo probably move to the QObject representing the bus
|
||||
*/
|
||||
bool QDBusConnection::releaseName(const QString &name)
|
||||
{
|
||||
int retval = dbus_bus_release_name(d->connection, name.toUtf8(), &d->error);
|
||||
|
|
@ -401,15 +736,23 @@ bool QDBusConnection::releaseName(const QString &name)
|
|||
return retval == DBUS_RELEASE_NAME_REPLY_RELEASED;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the unique connection name of the client that currently has the \p name
|
||||
requested. Returns an empty QString in case there is no such name on the bus or if \p name is
|
||||
not a well-formed bus name.
|
||||
|
||||
\todo probably move to the QObject representing the bus
|
||||
*/
|
||||
QString QDBusConnection::getNameOwner(const QString& name)
|
||||
{
|
||||
if (QDBusUtil::isValidUniqueConnectionName(name))
|
||||
return name;
|
||||
if (!d || !QDBusUtil::isValidBusName(name))
|
||||
return QString();
|
||||
|
||||
QDBusMessage msg = QDBusMessage::methodCall(DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
|
||||
DBUS_INTERFACE_DBUS, "GetNameOwner");
|
||||
|
||||
QDBusMessage msg = QDBusMessage::methodCall(QLatin1String(DBUS_SERVICE_DBUS),
|
||||
QLatin1String(DBUS_PATH_DBUS), QLatin1String(DBUS_INTERFACE_DBUS),
|
||||
QLatin1String("GetNameOwner"));
|
||||
msg << name;
|
||||
QDBusMessage reply = sendWithReply(msg);
|
||||
if (!lastError().isValid() && reply.type() == QDBusMessage::ReplyMessage)
|
||||
|
|
@ -417,4 +760,56 @@ QString QDBusConnection::getNameOwner(const QString& name)
|
|||
return QString();
|
||||
}
|
||||
|
||||
#include "qdbusconnection_p.moc"
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
template<int type>
|
||||
struct DefaultBus
|
||||
{
|
||||
DefaultBus()
|
||||
{
|
||||
QDBusConnection con = QDBusConnection::addConnection(QDBusConnection::BusType(type),
|
||||
QLatin1String(busName));
|
||||
bus = new QDBusConnection(con);
|
||||
qAddPostRoutine(clear);
|
||||
}
|
||||
|
||||
~DefaultBus()
|
||||
{
|
||||
delete bus;
|
||||
}
|
||||
|
||||
static void clear()
|
||||
{
|
||||
delete bus;
|
||||
bus = 0;
|
||||
QDBusConnection::closeConnection(QLatin1String(busName));
|
||||
}
|
||||
|
||||
static QDBusConnection *bus;
|
||||
static const char busName[];
|
||||
};
|
||||
|
||||
Q_GLOBAL_STATIC(DefaultBus<QDBusConnection::SessionBus>, sessionBusPtr);
|
||||
Q_GLOBAL_STATIC(DefaultBus<QDBusConnection::SystemBus>, systemBusPtr);
|
||||
|
||||
template<>
|
||||
QT_STATIC_CONST_IMPL char DefaultBus<QDBusConnection::SessionBus>::busName[] = "qt_default_session_bus";
|
||||
template<>
|
||||
QT_STATIC_CONST_IMPL char DefaultBus<QDBusConnection::SystemBus>::busName[] = "qt_default_system_bus";
|
||||
|
||||
template<> QDBusConnection *DefaultBus<QDBusConnection::SessionBus>::bus = 0;
|
||||
template<> QDBusConnection *DefaultBus<QDBusConnection::SystemBus>::bus = 0;
|
||||
|
||||
namespace QDBus {
|
||||
QDBusConnection &sessionBus()
|
||||
{
|
||||
return *sessionBusPtr()->bus;
|
||||
}
|
||||
|
||||
QDBusConnection &systemBus()
|
||||
{
|
||||
return *systemBusPtr()->bus;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,23 +41,38 @@ class QDBUS_EXPORT QDBusConnection
|
|||
{
|
||||
public:
|
||||
enum BusType { SessionBus, SystemBus, ActivationBus };
|
||||
enum NameRequestMode { NoReplace = 0, ProhibitReplace = 1, ReplaceExisting = 2 };
|
||||
enum RegisterOption {
|
||||
ExportAdaptors = 0x01,
|
||||
|
||||
QDBusConnection(const QString &name = QLatin1String(default_connection_name));
|
||||
ExportSlots = 0x10,
|
||||
ExportSignals = 0x20,
|
||||
ExportProperties = 0x40,
|
||||
ExportContents = 0xf0,
|
||||
|
||||
ExportNonScriptableSlots = 0x110,
|
||||
ExportNonScriptableSignals = 0x220,
|
||||
ExportNonScriptableProperties = 0x440,
|
||||
ExportNonScriptableContents = 0xff0,
|
||||
|
||||
ExportChildObjects = 0x1000
|
||||
};
|
||||
enum UnregisterMode {
|
||||
UnregisterNode,
|
||||
UnregisterTree
|
||||
};
|
||||
|
||||
Q_DECLARE_FLAGS(RegisterOptions, RegisterOption);
|
||||
|
||||
QDBusConnection(const QString &name);
|
||||
QDBusConnection(const QDBusConnection &other);
|
||||
~QDBusConnection();
|
||||
|
||||
QDBusConnection &operator=(const QDBusConnection &other);
|
||||
|
||||
bool isConnected() const;
|
||||
QDBusError lastError() const;
|
||||
|
||||
enum NameRequestMode { NoReplace = 0, ProhibitReplace = 1, ReplaceExisting = 2 };
|
||||
bool requestName(const QString &name, NameRequestMode mode = NoReplace);
|
||||
bool releaseName(const QString& name);
|
||||
QString getNameOwner(const QString& name);
|
||||
|
||||
|
||||
QString baseService() const;
|
||||
QDBusError lastError() const;
|
||||
|
||||
bool send(const QDBusMessage &message) const;
|
||||
QDBusMessage sendWithReply(const QDBusMessage &message) const;
|
||||
|
|
@ -70,48 +85,45 @@ public:
|
|||
const QString &name, const QString& signature,
|
||||
QObject *receiver, const char *slot);
|
||||
|
||||
enum RegisterOption {
|
||||
ExportForAnyInterface = 0x01,
|
||||
ExportAdaptors = 0x03,
|
||||
|
||||
ExportOwnSlots = 0x10,
|
||||
ExportOwnSignals = 0x20,
|
||||
ExportOwnProperties = 0x40,
|
||||
ExportOwnContents = 0xf0,
|
||||
|
||||
ExportNonScriptableSlots = 0x100,
|
||||
ExportNonScriptableSignals = 0x200,
|
||||
ExportNonScriptableProperties = 0x400,
|
||||
ExportNonScriptables = 0xf00,
|
||||
|
||||
ExportChildObjects = 0x1000,
|
||||
|
||||
Reexport = 0x100000,
|
||||
};
|
||||
Q_DECLARE_FLAGS(RegisterOptions, RegisterOption);
|
||||
|
||||
bool registerObject(const QString &path, const QString &interface, QObject *object,
|
||||
RegisterOptions options = ExportOwnContents);
|
||||
bool registerObject(const QString &path, QObject *object,
|
||||
RegisterOptions options = ExportAdaptors);
|
||||
void unregisterObject(const QString &path);
|
||||
void unregisterObject(const QString &path, UnregisterMode = UnregisterNode);
|
||||
|
||||
QDBusObject findObject(const QString& service, const QString& path);
|
||||
QDBusInterface findInterface(const QString& service, const QString& path, const QString& interface);
|
||||
|
||||
|
||||
#ifndef QT_NO_MEMBER_TEMPLATES
|
||||
template<class Interface>
|
||||
inline Interface findInterface(const QString &service, const QString &path)
|
||||
{ return Interface(findObject(service, path)); }
|
||||
#endif
|
||||
|
||||
bool requestName(const QString &name, NameRequestMode mode = NoReplace);
|
||||
bool releaseName(const QString& name);
|
||||
QString getNameOwner(const QString& name);
|
||||
|
||||
static QDBusConnection addConnection(BusType type,
|
||||
const QString &name = QLatin1String(default_connection_name));
|
||||
const QString &name);
|
||||
static QDBusConnection addConnection(const QString &address,
|
||||
const QString &name = QLatin1String(default_connection_name));
|
||||
static void closeConnection(const QString &name = QLatin1String(default_connection_name));
|
||||
|
||||
QT_STATIC_CONST char *default_connection_name;
|
||||
const QString &name);
|
||||
static void closeConnection(const QString &name);
|
||||
|
||||
private:
|
||||
friend class QDBusObject;
|
||||
QDBusConnectionPrivate *d;
|
||||
};
|
||||
|
||||
namespace QDBus {
|
||||
QDBusConnection &sessionBus();
|
||||
QDBusConnection &systemBus();
|
||||
}
|
||||
|
||||
template<class Interface>
|
||||
inline Interface qDBusConnectionFindInterface(QDBusConnection &connection, const QString &service,
|
||||
const QString &path)
|
||||
{
|
||||
return Interface(connection.findObject(service, path));
|
||||
}
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QDBusConnection::RegisterOptions)
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -40,13 +40,14 @@
|
|||
#include "qdbuserror.h"
|
||||
|
||||
#include <QtCore/qatomic.h>
|
||||
#include <QtCore/qmutex.h>
|
||||
#include <QtCore/qeventloop.h>
|
||||
#include <QtCore/qhash.h>
|
||||
#include <QtCore/qmutex.h>
|
||||
#include <QtCore/qobject.h>
|
||||
#include <QtCore/qpointer.h>
|
||||
#include <QtCore/qreadwritelock.h>
|
||||
#include <QtCore/qvarlengtharray.h>
|
||||
#include <QtCore/qeventloop.h>
|
||||
#include <QtCore/qmutex.h>
|
||||
#include <QtCore/qvector.h>
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
|
|
@ -79,16 +80,38 @@ public:
|
|||
|
||||
struct SignalHook
|
||||
{
|
||||
inline SignalHook() : obj(0), midx(-1) { }
|
||||
QString interface, name, signature;
|
||||
QPointer<QObject> obj;
|
||||
QObject* obj;
|
||||
int midx;
|
||||
QList<int> params;
|
||||
};
|
||||
|
||||
struct ObjectData
|
||||
struct ObjectTreeNode
|
||||
{
|
||||
QPointer<QObject> obj;
|
||||
struct Data
|
||||
{
|
||||
QString name;
|
||||
ObjectTreeNode *node;
|
||||
|
||||
inline bool operator<(const QString &other) const
|
||||
{ return name < other; }
|
||||
};
|
||||
|
||||
inline ObjectTreeNode() : obj(0), flags(0) { }
|
||||
inline ~ObjectTreeNode() { clear(); }
|
||||
inline void clear()
|
||||
{
|
||||
foreach (const Data &entry, children) {
|
||||
entry.node->clear();
|
||||
delete entry.node;
|
||||
}
|
||||
children.clear();
|
||||
}
|
||||
|
||||
QObject* obj;
|
||||
int flags;
|
||||
QVector<Data> children;
|
||||
};
|
||||
|
||||
public:
|
||||
|
|
@ -96,11 +119,9 @@ public:
|
|||
typedef QMultiHash<int, Watcher> WatcherHash;
|
||||
typedef QHash<int, DBusTimeout *> TimeoutHash;
|
||||
typedef QMultiHash<QString, SignalHook> SignalHookHash;
|
||||
typedef QHash<QString, ObjectData> ObjectDataHash;
|
||||
typedef QHash<QString, ObjectDataHash> ObjectHookHash;
|
||||
typedef QHash<QString, QSharedDataPointer<QDBusIntrospection::Interface> > KnownInterfacesHash;
|
||||
typedef QHash<QString, QDBusIntrospection::Object* > KnownObjectsHash;
|
||||
|
||||
|
||||
public:
|
||||
// public methods
|
||||
QDBusConnectionPrivate(QObject *parent = 0);
|
||||
|
|
@ -113,11 +134,13 @@ public:
|
|||
void closeConnection();
|
||||
void timerEvent(QTimerEvent *e);
|
||||
|
||||
bool handleSignal(const QString &path, const QDBusMessage &msg);
|
||||
bool send(const QDBusMessage &message) const;
|
||||
int sendWithReplyAsync(const QDBusMessage &message, QObject *receiver,
|
||||
const char *method) const;
|
||||
void connectSignal(const QString &key, const SignalHook &hook);
|
||||
void registerObject(const ObjectTreeNode *node);
|
||||
|
||||
bool handleSignal(const QString &path, const QDBusMessage &msg);
|
||||
bool handleSignal(const QDBusMessage &msg);
|
||||
bool handleObjectCall(const QDBusMessage &message);
|
||||
bool handleError();
|
||||
|
|
@ -127,13 +150,14 @@ public:
|
|||
QSharedDataPointer<QDBusIntrospection::Interface> findInterface(const QString& name);
|
||||
QDBusIntrospection::Object* findObject(const QString& service,
|
||||
const QString& path);
|
||||
|
||||
bool activateReply(QObject *object, int idx, const QList<int>& metaTypes,
|
||||
const QDBusMessage &msg);
|
||||
|
||||
bool activateSignal(const SignalHook& hook, const QDBusMessage &msg);
|
||||
bool activateCall(QObject* object, int flags, const QDBusMessage &msg);
|
||||
bool activateAdaptor(QObject *object, int flags, const QDBusMessage &msg);
|
||||
bool activateObject(const ObjectData& data, const QDBusMessage &msg);
|
||||
bool activateObject(const ObjectTreeNode *node, const QDBusMessage &msg);
|
||||
bool activateInternalFilters(const ObjectTreeNode *node, const QDBusMessage &msg);
|
||||
|
||||
void postCallDeliveryEvent(CallDeliveryEvent *data);
|
||||
CallDeliveryEvent *postedCallDeliveryEvent();
|
||||
void deliverCall(const CallDeliveryEvent &data) const;
|
||||
|
||||
protected:
|
||||
|
|
@ -144,14 +168,17 @@ public slots:
|
|||
void socketRead(int);
|
||||
void socketWrite(int);
|
||||
void objectDestroyed(QObject *o);
|
||||
void relaySignal(QObject *obj, const char *interface, const char *name, const QVariantList &args);
|
||||
|
||||
public:
|
||||
// public member variables
|
||||
QString name; // this connection's name
|
||||
|
||||
DBusError error;
|
||||
QDBusError lastError;
|
||||
|
||||
QAtomic ref;
|
||||
QMutex mutex;
|
||||
QReadWriteLock lock;
|
||||
ConnectionMode mode;
|
||||
DBusConnection *connection;
|
||||
DBusServer *server;
|
||||
|
|
@ -159,9 +186,13 @@ public:
|
|||
WatcherHash watchers;
|
||||
TimeoutHash timeouts;
|
||||
SignalHookHash signalHooks;
|
||||
ObjectHookHash objectHooks;
|
||||
QList<DBusTimeout *> pendingTimeouts;
|
||||
|
||||
ObjectTreeNode rootNode;
|
||||
|
||||
QMutex callDeliveryMutex;
|
||||
CallDeliveryEvent *callDeliveryState; // protected by the callDeliveryMutex mutex
|
||||
|
||||
public:
|
||||
// public mutable member variables
|
||||
mutable KnownInterfacesHash knownInterfaces;
|
||||
|
|
@ -182,6 +213,18 @@ public:
|
|||
|
||||
public slots:
|
||||
void reply(const QDBusMessage &msg);
|
||||
};
|
||||
};
|
||||
|
||||
extern int qDBusParametersForMethod(const QByteArray &sig, QList<int>& metaTypes);
|
||||
extern int qDBusNameToTypeId(const char *name);
|
||||
extern bool qDBusCheckAsyncTag(const char *tag);
|
||||
|
||||
// in qdbusinternalfilters.cpp
|
||||
extern void qDBusIntrospectObject(const QDBusConnectionPrivate::ObjectTreeNode *node,
|
||||
const QDBusMessage &msg);
|
||||
extern void qDBusPropertyGet(const QDBusConnectionPrivate::ObjectTreeNode *node,
|
||||
const QDBusMessage &msg);
|
||||
extern void qDBusPropertySet(const QDBusConnectionPrivate::ObjectTreeNode *node,
|
||||
const QDBusMessage &msg);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -29,6 +29,30 @@
|
|||
#include <dbus/dbus.h>
|
||||
#include "qdbusmessage.h"
|
||||
|
||||
/*!
|
||||
\class QDBusError
|
||||
\brief Represents an error received from the D-Bus bus or from remote applications found in the bus.
|
||||
|
||||
When dealing with the D-Bus bus service or with remote applications over D-Bus, a number of
|
||||
error conditions can happen. This error conditions are sometimes signalled by a returned error
|
||||
value or by a QDBusError.
|
||||
|
||||
C++ and Java exceptions are a valid analogy for D-Bus errors: instead of returning normally with
|
||||
a return value, remote applications and the bus may decide to throw an error condition. However,
|
||||
the QtDBus implementation does not use the C++ exception-throwing mechanism, so you will receive
|
||||
QDBusErrors in the return reply (see QDBusReply::error()).
|
||||
|
||||
QDBusError objects are used to inspect the error name and message as received from the bus and
|
||||
remote applications. You should not create such objects yourself to signal error conditions when
|
||||
called from D-Bus: instead, use QDBusMessage::error and QDBusConnection::send.
|
||||
|
||||
\sa QDBusConnection::send, QDBusMessage, QDBusReply
|
||||
*/
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Constructs a QDBusError from a DBusError structure.
|
||||
*/
|
||||
QDBusError::QDBusError(const DBusError *error)
|
||||
{
|
||||
if (!error || !dbus_error_is_set(error))
|
||||
|
|
@ -38,6 +62,10 @@ QDBusError::QDBusError(const DBusError *error)
|
|||
msg = QString::fromUtf8(error->message);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Constructs a QDBusError from a QDBusMessage.
|
||||
*/
|
||||
QDBusError::QDBusError(const QDBusMessage &qdmsg)
|
||||
{
|
||||
if (qdmsg.type() != QDBusMessage::ErrorMessage)
|
||||
|
|
@ -48,6 +76,31 @@ QDBusError::QDBusError(const QDBusMessage &qdmsg)
|
|||
msg = qdmsg[0].toString();
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn QDBusError::QDBusError(const QString &name, const QString &message)
|
||||
\internal
|
||||
|
||||
Constructs an error by passing the name and message.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusError::name() const
|
||||
Returns this error's name. Error names are similar to D-Bus Interface names, like
|
||||
"org.freedesktop.DBus.InvalidArgs".
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusError::message() const
|
||||
Returns the message that the callee associated with this error. Error messages are
|
||||
implementation defined and usually contain a human-readable error code, though this does not
|
||||
mean it is suitable for your end-users.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusError::isValid() const
|
||||
Returns true if this is a valid error condition (i.e., if there was an error), false otherwise.
|
||||
*/
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const QDBusError &msg)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -36,6 +36,9 @@ class QDBUS_EXPORT QDBusError
|
|||
public:
|
||||
QDBusError(const DBusError *error = 0);
|
||||
QDBusError(const QDBusMessage& msg);
|
||||
inline QDBusError(const QString &name, const QString &message)
|
||||
: nm(name), msg(message)
|
||||
{ }
|
||||
|
||||
inline QString name() const { return nm; }
|
||||
inline QString message() const { return msg; }
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@
|
|||
#include <qcoreevent.h>
|
||||
#include <qdebug.h>
|
||||
#include <qmetaobject.h>
|
||||
#include <qobject.h>
|
||||
#include <qsocketnotifier.h>
|
||||
#include <qcoreevent.h>
|
||||
#include <qtimer.h>
|
||||
|
||||
#include "qdbusvariant.h"
|
||||
|
|
@ -36,9 +36,17 @@
|
|||
#include "qdbusobject_p.h"
|
||||
#include "qdbusmessage.h"
|
||||
#include "qdbusabstractadaptor.h"
|
||||
#include "qdbusabstractadaptor_p.h"
|
||||
|
||||
#ifndef USE_OUTSIDE_DISPATCH
|
||||
# define USE_OUTSIDE_DISPATCH 0
|
||||
#endif
|
||||
|
||||
int QDBusConnectionPrivate::messageMetaType = 0;
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
struct QDBusPendingCall
|
||||
{
|
||||
QPointer<QObject> receiver;
|
||||
|
|
@ -48,6 +56,9 @@ struct QDBusPendingCall
|
|||
const QDBusConnectionPrivate *connection;
|
||||
};
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
class CallDeliveryEvent: public QEvent
|
||||
{
|
||||
public:
|
||||
|
|
@ -59,11 +70,23 @@ public:
|
|||
QPointer<QObject> object;
|
||||
QDBusMessage message;
|
||||
QList<int> metaTypes;
|
||||
|
||||
|
||||
int flags;
|
||||
int slotIdx;
|
||||
};
|
||||
|
||||
#if __BYTE_ORDER != __LITTLE_ENDIAN
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
union integer
|
||||
{
|
||||
short s;
|
||||
unsigned short us;
|
||||
unsigned char uc;
|
||||
};
|
||||
#endif
|
||||
|
||||
static dbus_bool_t qDBusAddTimeout(DBusTimeout *timeout, void *data)
|
||||
{
|
||||
Q_ASSERT(timeout);
|
||||
|
|
@ -209,6 +232,30 @@ static void qDBusNewConnection(DBusServer *server, DBusConnection *c, void *data
|
|||
qDebug("SERVER: GOT A NEW CONNECTION"); // TODO
|
||||
}
|
||||
|
||||
#if USE_OUTSIDE_DISPATCH
|
||||
# define HANDLED DBUS_HANDLER_RESULT_HANDLED_OUTSIDE_DISPATCH
|
||||
static DBusHandlerResult qDBusSignalFilterOutside(DBusConnection *connection,
|
||||
DBusMessage *message, void *data)
|
||||
{
|
||||
Q_ASSERT(data);
|
||||
Q_UNUSED(connection);
|
||||
Q_UNUSED(message);
|
||||
|
||||
QDBusConnectionPrivate *d = static_cast<QDBusConnectionPrivate *>(data);
|
||||
if (d->mode == QDBusConnectionPrivate::InvalidMode)
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; // internal error, actually
|
||||
|
||||
CallDeliveryEvent *e = d->postedCallDeliveryEvent();
|
||||
|
||||
d->deliverCall(*e);
|
||||
delete e;
|
||||
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
#else
|
||||
# define HANDLED DBUS_HANDLER_RESULT_HANDLED
|
||||
#endif
|
||||
|
||||
static DBusHandlerResult qDBusSignalFilter(DBusConnection *connection,
|
||||
DBusMessage *message, void *data)
|
||||
{
|
||||
|
|
@ -219,23 +266,52 @@ static DBusHandlerResult qDBusSignalFilter(DBusConnection *connection,
|
|||
if (d->mode == QDBusConnectionPrivate::InvalidMode)
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
|
||||
int msgType = dbus_message_get_type(message);
|
||||
bool handled = false;
|
||||
|
||||
QDBusMessage amsg = QDBusMessage::fromDBusMessage(message);
|
||||
QDBusMessage amsg = QDBusMessage::fromDBusMessage(message, QDBusConnection(d->name));
|
||||
qDebug() << "got message:" << amsg;
|
||||
|
||||
bool handled = false;
|
||||
int msgType = dbus_message_get_type(message);
|
||||
if (msgType == DBUS_MESSAGE_TYPE_SIGNAL) {
|
||||
handled = d->handleSignal(amsg);
|
||||
} else if (msgType == DBUS_MESSAGE_TYPE_METHOD_CALL) {
|
||||
handled = d->handleObjectCall(amsg);
|
||||
}
|
||||
|
||||
return handled ? DBUS_HANDLER_RESULT_HANDLED :
|
||||
DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
return handled ? HANDLED :
|
||||
DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
static bool checkAsyncTag(const char *tag)
|
||||
static void huntAndDestroy(QObject *needle, QDBusConnectionPrivate::ObjectTreeNode *haystack)
|
||||
{
|
||||
foreach (const QDBusConnectionPrivate::ObjectTreeNode::Data &entry, haystack->children)
|
||||
huntAndDestroy(needle, entry.node);
|
||||
|
||||
if (needle == haystack->obj) {
|
||||
haystack->obj = 0;
|
||||
haystack->flags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void huntAndEmit(DBusConnection *connection, DBusMessage *msg,
|
||||
QObject *needle, QDBusConnectionPrivate::ObjectTreeNode *haystack,
|
||||
const QString &path = QString())
|
||||
{
|
||||
foreach (const QDBusConnectionPrivate::ObjectTreeNode::Data &entry, haystack->children)
|
||||
huntAndEmit(connection, msg, needle, entry.node, path + QLatin1String("/") + entry.name);
|
||||
|
||||
if (needle == haystack->obj && haystack->flags & QDBusConnection::ExportAdaptors) {
|
||||
QByteArray p = path.toLatin1();
|
||||
if (p.isEmpty())
|
||||
p = "/";
|
||||
qDebug() << p;
|
||||
DBusMessage *msg2 = dbus_message_copy(msg);
|
||||
dbus_message_set_path(msg2, p);
|
||||
dbus_connection_send(connection, msg2, 0);
|
||||
dbus_message_unref(msg2);
|
||||
}
|
||||
}
|
||||
|
||||
bool qDBusCheckAsyncTag(const char *tag)
|
||||
{
|
||||
if (!tag || !*tag)
|
||||
return false;
|
||||
|
|
@ -288,27 +364,11 @@ static bool typesMatch(int metaId, QVariant::Type variantType)
|
|||
return false; // no match
|
||||
}
|
||||
|
||||
static int returnTypeId(const char *name)
|
||||
int qDBusNameToTypeId(const char *name)
|
||||
{
|
||||
if (!name || !*name)
|
||||
return QMetaType::Void;
|
||||
|
||||
// force normalizedSignature to work for us
|
||||
QVarLengthArray<char, 32> buf(strlen(name) + 3);
|
||||
buf.append("_(", 2);
|
||||
buf.append(name, strlen(name));
|
||||
buf.append(')');
|
||||
|
||||
QByteArray normalized = QMetaObject::normalizedSignature( buf.data() );
|
||||
normalized.truncate(normalized.length() - 1);
|
||||
return QMetaType::type(normalized.constData() + 2);
|
||||
}
|
||||
|
||||
static int typeId(const char *type)
|
||||
{
|
||||
int id = static_cast<int>( QVariant::nameToType(type) );
|
||||
int id = static_cast<int>( QVariant::nameToType(name) );
|
||||
if (id == QVariant::UserType)
|
||||
id = QMetaType::type(type);
|
||||
id = QMetaType::type(name);
|
||||
|
||||
switch (id) {
|
||||
case QVariant::Bool:
|
||||
|
|
@ -334,11 +394,10 @@ static int typeId(const char *type)
|
|||
default:
|
||||
if (id == qMetaTypeId<QDBusVariant>() || id == QDBusConnectionPrivate::messageMetaType)
|
||||
return id;
|
||||
|
||||
|
||||
return 0; // invalid
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// calculates the metatypes for the method
|
||||
// the slot must have the parameters in the following form:
|
||||
|
|
@ -352,7 +411,7 @@ static int typeId(const char *type)
|
|||
// metaTypes.count() >= retval + 1 in all cases
|
||||
//
|
||||
// sig must be the normalised signature for the method
|
||||
static int parametersForMethod(const QByteArray &sig, QList<int>& metaTypes)
|
||||
int qDBusParametersForMethod(const QByteArray &sig, QList<int>& metaTypes)
|
||||
{
|
||||
if (sig.indexOf('<') != -1) {
|
||||
qWarning("Could not parse the method '%s'", sig.constData());
|
||||
|
|
@ -376,21 +435,15 @@ static int parametersForMethod(const QByteArray &sig, QList<int>& metaTypes)
|
|||
|
||||
if (type.endsWith('&')) {
|
||||
type.truncate(type.length() - 1);
|
||||
int id = typeId(type);
|
||||
int id = qDBusNameToTypeId(type);
|
||||
if (id == 0) {
|
||||
qWarning("Could not parse the method '%s'", sig.constData());
|
||||
// invalid type in method parameter list
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
metaTypes.append( id );
|
||||
|
||||
if (metaTypes.last() == 0) {
|
||||
qWarning("Could not parse the method '%s'", sig.constData());
|
||||
// void?
|
||||
return -1;
|
||||
}
|
||||
|
||||
seenMessage = true; // it cannot appear anymore anyways
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -400,13 +453,13 @@ static int parametersForMethod(const QByteArray &sig, QList<int>& metaTypes)
|
|||
return -1; // not allowed
|
||||
}
|
||||
|
||||
int id = typeId(type);
|
||||
int id = qDBusNameToTypeId(type);
|
||||
if (id == 0) {
|
||||
qWarning("Could not parse the method '%s'", sig.constData());
|
||||
// invalid type in method parameter list
|
||||
return -1;
|
||||
}
|
||||
metaTypes.append(id);
|
||||
metaTypes.append(id);
|
||||
++inputCount;
|
||||
|
||||
if (id == QDBusConnectionPrivate::messageMetaType)
|
||||
|
|
@ -417,14 +470,14 @@ static int parametersForMethod(const QByteArray &sig, QList<int>& metaTypes)
|
|||
}
|
||||
|
||||
static int findSlot(const QMetaObject *mo, const QByteArray &name, int flags,
|
||||
const QDBusTypeList &types, QList<int>& metaTypes, int &msgPos)
|
||||
const QDBusTypeList &types, QList<int>& metaTypes)
|
||||
{
|
||||
// find the first slot
|
||||
const QMetaObject *super = mo;
|
||||
while (qstrcmp(super->className(), "QObject") != 0 &&
|
||||
qstrcmp(super->className(), "QDBusAbstractAdaptor") != 0)
|
||||
while (super != &QObject::staticMetaObject &&
|
||||
super != &QDBusAbstractAdaptor::staticMetaObject)
|
||||
super = super->superClass();
|
||||
|
||||
|
||||
int attributeMask = (flags & QDBusConnection::ExportNonScriptableSlots) ?
|
||||
0 : QMetaMethod::Scriptable;
|
||||
|
||||
|
|
@ -446,48 +499,46 @@ static int findSlot(const QMetaObject *mo, const QByteArray &name, int flags,
|
|||
if (paren != name.length() || !sig.startsWith( name ))
|
||||
continue;
|
||||
|
||||
int returnType = returnTypeId(mm.typeName());
|
||||
bool isAsync = checkAsyncTag(mm.tag());
|
||||
int returnType = qDBusNameToTypeId(mm.typeName());
|
||||
bool isAsync = qDBusCheckAsyncTag(mm.tag());
|
||||
|
||||
// consistency check:
|
||||
if (isAsync && returnType != QMetaType::Void)
|
||||
continue;
|
||||
|
||||
int inputCount = parametersForMethod(sig, metaTypes);
|
||||
int inputCount = qDBusParametersForMethod(sig, metaTypes);
|
||||
if (inputCount == -1)
|
||||
continue; // problem parsing
|
||||
|
||||
metaTypes[0] = returnType;
|
||||
msgPos = 0;
|
||||
bool hasMessage = false;
|
||||
if (inputCount > 0 &&
|
||||
metaTypes.at(inputCount) == QDBusConnectionPrivate::messageMetaType) {
|
||||
// no input parameters is allowed as long as the message meta type is there
|
||||
msgPos = inputCount;
|
||||
// "no input parameters" is allowed as long as the message meta type is there
|
||||
hasMessage = true;
|
||||
--inputCount;
|
||||
}
|
||||
|
||||
if (inputCount) {
|
||||
// try to match the parameters
|
||||
if (inputCount < types.count())
|
||||
continue; // not enough parameters
|
||||
// try to match the parameters
|
||||
if (inputCount != types.count())
|
||||
continue; // not enough parameters
|
||||
|
||||
bool matches = true;
|
||||
int i;
|
||||
for (i = 0; i < types.count(); ++i)
|
||||
if ( !typesMatch(metaTypes.at(i + 1), types.at(i).qvariantType()) ) {
|
||||
matches = false;
|
||||
break;
|
||||
}
|
||||
bool matches = true;
|
||||
int i;
|
||||
for (i = 0; i < types.count(); ++i)
|
||||
if ( !typesMatch(metaTypes.at(i + 1), types.at(i).qvariantType()) ) {
|
||||
matches = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!matches)
|
||||
continue; // we didn't match them all
|
||||
if (!matches)
|
||||
continue; // we didn't match them all
|
||||
|
||||
// consistency check:
|
||||
if (isAsync && metaTypes.count() > i + 1)
|
||||
continue;
|
||||
}
|
||||
// consistency check:
|
||||
if (isAsync && metaTypes.count() > i + 1)
|
||||
continue;
|
||||
|
||||
if (!msgPos && (mm.attributes() & attributeMask) != attributeMask)
|
||||
if (hasMessage && (mm.attributes() & attributeMask) != attributeMask)
|
||||
continue; // not exported
|
||||
|
||||
// if we got here, this slot matched
|
||||
|
|
@ -496,7 +547,33 @@ static int findSlot(const QMetaObject *mo, const QByteArray &name, int flags,
|
|||
|
||||
// no slot matched
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static CallDeliveryEvent* prepareReply(QObject *object, int idx, const QList<int> &metaTypes,
|
||||
const QDBusMessage &msg)
|
||||
{
|
||||
Q_ASSERT(object);
|
||||
|
||||
int n = metaTypes.count() - 1;
|
||||
if (metaTypes[n] == QDBusConnectionPrivate::messageMetaType)
|
||||
--n;
|
||||
|
||||
// check that types match
|
||||
for (int i = 0; i < n; ++i)
|
||||
if (!typesMatch(metaTypes.at(i + 1), msg.at(i).type()))
|
||||
return 0; // no match
|
||||
|
||||
// we can deliver
|
||||
// prepare for the call
|
||||
CallDeliveryEvent *data = new CallDeliveryEvent;
|
||||
data->object = object;
|
||||
data->flags = 0;
|
||||
data->message = msg;
|
||||
data->metaTypes = metaTypes;
|
||||
data->slotIdx = idx;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
bool QDBusConnectionPrivate::activateSignal(const QDBusConnectionPrivate::SignalHook& hook,
|
||||
const QDBusMessage &msg)
|
||||
|
|
@ -508,44 +585,13 @@ bool QDBusConnectionPrivate::activateSignal(const QDBusConnectionPrivate::Signal
|
|||
// Slots can have less parameters than there are on the message
|
||||
// Slots can optionally have one final parameter that is a QDBusMessage
|
||||
// Slots receive read-only copies of the message (i.e., pass by value or by const-ref)
|
||||
return activateReply(hook.obj, hook.midx, hook.params, msg);
|
||||
}
|
||||
|
||||
bool QDBusConnectionPrivate::activateReply(QObject *object, int idx, const QList<int> &metaTypes,
|
||||
const QDBusMessage &msg)
|
||||
{
|
||||
// This is called by qDBusResultReceived and is used to deliver the return value
|
||||
// of a remote function call.
|
||||
//
|
||||
// There is only one connection and it is specified by idx
|
||||
// The slot must have the same parameter types that the message does
|
||||
// The slot may have less parameters than the message
|
||||
// The slot may optionally have one final parameter that is QDBusMessage
|
||||
// The slot receives read-only copies of the message (i.e., pass by value or by const-ref)
|
||||
Q_ASSERT(object);
|
||||
|
||||
int n = metaTypes.count() - 1;
|
||||
if (metaTypes[n] == QDBusConnectionPrivate::messageMetaType)
|
||||
--n;
|
||||
|
||||
// check that types match
|
||||
for (int i = 0; i < n; ++i)
|
||||
if (!typesMatch(metaTypes.at(i + 1), msg.at(i).type()))
|
||||
return false; // no match
|
||||
|
||||
// we can deliver
|
||||
// prepare for the call
|
||||
CallDeliveryEvent *data = new CallDeliveryEvent;
|
||||
data->conn = this;
|
||||
data->object = object;
|
||||
data->flags = 0;
|
||||
data->message = msg;
|
||||
data->metaTypes = metaTypes;
|
||||
data->slotIdx = idx;
|
||||
|
||||
QCoreApplication::postEvent( this, data );
|
||||
|
||||
return true;
|
||||
CallDeliveryEvent *call = prepareReply(hook.obj, hook.midx, hook.params, msg);
|
||||
if (call) {
|
||||
call->conn = this;
|
||||
postCallDeliveryEvent(call);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QDBusConnectionPrivate::activateCall(QObject* object, int flags,
|
||||
|
|
@ -574,22 +620,25 @@ bool QDBusConnectionPrivate::activateCall(QObject* object, int flags,
|
|||
// in the message's first position. If there are non-const reference parameters to the
|
||||
// slot, they must appear at the end and will be placed in the subsequent message
|
||||
// positions.
|
||||
|
||||
Q_ASSERT(object);
|
||||
|
||||
if (!object)
|
||||
return false;
|
||||
|
||||
QList<int> metaTypes;
|
||||
int idx;
|
||||
int msgPos;
|
||||
|
||||
|
||||
{
|
||||
const QMetaObject *mo = object->metaObject();
|
||||
QDBusTypeList typeList(msg.signature().toUtf8());
|
||||
|
||||
// find a slot that matches according to the rules above
|
||||
idx = ::findSlot(mo, msg.name().toUtf8(), flags, typeList, metaTypes, msgPos);
|
||||
if (idx == -1)
|
||||
// no match
|
||||
return false;
|
||||
idx = ::findSlot(mo, msg.name().toUtf8(), flags, typeList, metaTypes);
|
||||
if (idx == -1) {
|
||||
// try with no parameters, but with a QDBusMessage
|
||||
idx = ::findSlot(mo, msg.name().toUtf8(), flags, QDBusTypeList(), metaTypes);
|
||||
if (metaTypes.count() != 2 || metaTypes.at(1) != messageMetaType)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// found the slot to be called
|
||||
|
|
@ -606,12 +655,34 @@ bool QDBusConnectionPrivate::activateCall(QObject* object, int flags,
|
|||
call->metaTypes = metaTypes;
|
||||
call->slotIdx = idx;
|
||||
|
||||
QCoreApplication::postEvent( this, call );
|
||||
postCallDeliveryEvent(call);
|
||||
|
||||
// ready
|
||||
return true;
|
||||
}
|
||||
|
||||
void QDBusConnectionPrivate::postCallDeliveryEvent(CallDeliveryEvent *data)
|
||||
{
|
||||
#if USE_OUTSIDE_DISPATCH
|
||||
callDeliveryMutex.lock();
|
||||
callDeliveryState = data;
|
||||
#else
|
||||
QCoreApplication::postEvent( this, data );
|
||||
#endif
|
||||
}
|
||||
|
||||
CallDeliveryEvent *QDBusConnectionPrivate::postedCallDeliveryEvent()
|
||||
{
|
||||
CallDeliveryEvent *e = callDeliveryState;
|
||||
Q_ASSERT(e && e->conn == this);
|
||||
|
||||
// release it:
|
||||
callDeliveryState = 0;
|
||||
callDeliveryMutex.unlock();
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
void QDBusConnectionPrivate::deliverCall(const CallDeliveryEvent& data) const
|
||||
{
|
||||
// resume state:
|
||||
|
|
@ -622,12 +693,6 @@ void QDBusConnectionPrivate::deliverCall(const CallDeliveryEvent& data) const
|
|||
params.reserve(metaTypes.count());
|
||||
|
||||
#if __BYTE_ORDER != __LITTLE_ENDIAN
|
||||
union integer
|
||||
{
|
||||
short s;
|
||||
unsigned short us;
|
||||
unsigned char uc;
|
||||
}
|
||||
QVarLengthArray<integer, 4> auxParameters;
|
||||
#endif
|
||||
// let's create the parameter list
|
||||
|
|
@ -637,20 +702,20 @@ void QDBusConnectionPrivate::deliverCall(const CallDeliveryEvent& data) const
|
|||
|
||||
// add the input parameters
|
||||
int i;
|
||||
for (i = 0; i < msg.count(); ++i) {
|
||||
int id = metaTypes[i + 1];
|
||||
for (i = 1; i <= msg.count(); ++i) {
|
||||
int id = metaTypes[i];
|
||||
if (id == QDBusConnectionPrivate::messageMetaType)
|
||||
break;
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
params.append(const_cast<void *>( msg.at(i).constData() ));
|
||||
params.append(const_cast<void *>( msg.at(i - 1).constData() ));
|
||||
#else
|
||||
if (id == msg.at(i).type())
|
||||
params.append(const_cast<void *>( msg.at(i).constData() ));
|
||||
if (id == int(msg.at(i).type()))
|
||||
params.append(const_cast<void *>( msg.at(i - 1).constData() ));
|
||||
else {
|
||||
// need some help
|
||||
integer aux;
|
||||
const QVariant &var = msg.at(i);
|
||||
const QVariant &var = msg.at(i - 1);
|
||||
if (id == QMetaType::Short)
|
||||
aux.s = var.toInt();
|
||||
else if (id == QMetaType::UShort)
|
||||
|
|
@ -664,7 +729,7 @@ void QDBusConnectionPrivate::deliverCall(const CallDeliveryEvent& data) const
|
|||
}
|
||||
|
||||
bool takesMessage = false;
|
||||
if (metaTypes.count() > i + 1 && metaTypes[i + 1] == QDBusConnectionPrivate::messageMetaType) {
|
||||
if (metaTypes.count() > i && metaTypes[i] == QDBusConnectionPrivate::messageMetaType) {
|
||||
params.append(const_cast<void*>(static_cast<const void*>(&msg)));
|
||||
takesMessage = true;
|
||||
++i;
|
||||
|
|
@ -699,14 +764,15 @@ void QDBusConnectionPrivate::deliverCall(const CallDeliveryEvent& data) const
|
|||
// normal reply
|
||||
QDBusMessage reply = QDBusMessage::methodReply(msg);
|
||||
reply += outputArgs;
|
||||
|
||||
|
||||
qDebug() << "Automatically sending reply:" << reply;
|
||||
send(reply);
|
||||
}
|
||||
else {
|
||||
// generate internal error
|
||||
QDBusMessage reply = QDBusMessage::error(msg, "com.trolltech.QtDBus.InternalError",
|
||||
"Failed to deliver message");
|
||||
QDBusMessage reply = QDBusMessage::error(msg,
|
||||
QLatin1String("com.trolltech.QtDBus.InternalError"),
|
||||
QLatin1String("Failed to deliver message"));
|
||||
qDebug("Internal error: Failed to deliver message");
|
||||
send(reply);
|
||||
}
|
||||
|
|
@ -737,12 +803,14 @@ QDBusConnectionPrivate::QDBusConnectionPrivate(QObject *parent)
|
|||
Q_UNUSED(threads);
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
rootNode.flags = 0;
|
||||
}
|
||||
|
||||
QDBusConnectionPrivate::~QDBusConnectionPrivate()
|
||||
{
|
||||
Q_ASSERT(knownObjects.isEmpty());
|
||||
|
||||
|
||||
if (dbus_error_is_set(&error))
|
||||
dbus_error_free(&error);
|
||||
|
||||
|
|
@ -751,15 +819,18 @@ QDBusConnectionPrivate::~QDBusConnectionPrivate()
|
|||
KnownInterfacesHash::iterator it = knownInterfaces.begin();
|
||||
while (it != knownInterfaces.end()) {
|
||||
const QSharedDataPointer<QDBusIntrospection::Interface>& item = *it;
|
||||
|
||||
|
||||
const_cast<QDBusIntrospection::Interface*>(item.constData())->ref.deref();
|
||||
|
||||
it = knownInterfaces.erase(it);
|
||||
}
|
||||
|
||||
rootNode.clear(); // free resources
|
||||
}
|
||||
|
||||
void QDBusConnectionPrivate::closeConnection()
|
||||
{
|
||||
QWriteLocker locker(&lock);
|
||||
ConnectionMode oldMode = mode;
|
||||
mode = InvalidMode; // prevent reentrancy
|
||||
if (oldMode == ServerMode) {
|
||||
|
|
@ -835,21 +906,8 @@ void QDBusConnectionPrivate::socketWrite(int fd)
|
|||
|
||||
void QDBusConnectionPrivate::objectDestroyed(QObject *obj)
|
||||
{
|
||||
ObjectHookHash::iterator it = objectHooks.begin();
|
||||
while (it != objectHooks.end()) {
|
||||
ObjectDataHash::iterator dit = it->begin();
|
||||
while (dit != it->end()) {
|
||||
if (static_cast<QObject *>(dit.value().obj) == obj)
|
||||
dit = it->erase(dit);
|
||||
else
|
||||
++dit;
|
||||
}
|
||||
|
||||
if (it->isEmpty())
|
||||
it = objectHooks.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
QWriteLocker locker(&lock);
|
||||
huntAndDestroy(obj, &rootNode);
|
||||
|
||||
SignalHookHash::iterator sit = signalHooks.begin();
|
||||
while (sit != signalHooks.end()) {
|
||||
|
|
@ -858,41 +916,28 @@ void QDBusConnectionPrivate::objectDestroyed(QObject *obj)
|
|||
else
|
||||
++sit;
|
||||
}
|
||||
|
||||
obj->disconnect(this);
|
||||
}
|
||||
|
||||
bool QDBusConnectionPrivate::activateAdaptor(QObject* object, int flags,
|
||||
const QDBusMessage &msg)
|
||||
void QDBusConnectionPrivate::relaySignal(QObject *obj, const char *interface, const char *name,
|
||||
const QVariantList &args)
|
||||
{
|
||||
// This is called by QDBusConnectionPrivate::handleObjectCall to place a call to a slot
|
||||
// on the object.
|
||||
//
|
||||
// The call is routed through the adaptor sub-objects
|
||||
|
||||
Q_ASSERT(object);
|
||||
flags |= QDBusConnection::ExportNonScriptableSlots;
|
||||
|
||||
const QObjectList& children = object->children();
|
||||
QObjectList::const_iterator child = children.begin(),
|
||||
end = children.end();
|
||||
for ( ; child != end; ++child) {
|
||||
// check if this is an adaptor
|
||||
if (!qobject_cast<QDBusAbstractAdaptor *>(*child))
|
||||
continue; // not adaptor
|
||||
|
||||
const QMetaObject *mo = (*child)->metaObject();
|
||||
int ciend = mo->classInfoCount();
|
||||
for (int i = 0; i < ciend; ++i) {
|
||||
QMetaClassInfo mci = mo->classInfo(i);
|
||||
if (strcmp(mci.name(), "DBus Interface") == 0 && *mci.value()) {
|
||||
// one interface.
|
||||
// is this it?
|
||||
if (msg.interface().isEmpty() || msg.interface() == mci.value())
|
||||
return activateCall(*child, flags, msg);
|
||||
}
|
||||
}
|
||||
QReadLocker locker(&lock);
|
||||
QDBusMessage message = QDBusMessage::signal(QLatin1String("/"), QLatin1String(interface),
|
||||
QLatin1String(name));
|
||||
message += args;
|
||||
DBusMessage *msg = message.toDBusMessage();
|
||||
if (!msg) {
|
||||
qWarning("Could not emit signal %s.%s", interface, name);
|
||||
return;
|
||||
}
|
||||
return false;
|
||||
|
||||
qDebug() << "Emitting signal" << message;
|
||||
qDebug() << "for paths:";
|
||||
dbus_message_set_no_reply(msg, true); // the reply would not be delivered to anything
|
||||
huntAndEmit(connection, msg, obj, &rootNode);
|
||||
dbus_message_unref(msg);
|
||||
}
|
||||
|
||||
int QDBusConnectionPrivate::registerMessageMetaType()
|
||||
|
|
@ -905,85 +950,174 @@ int QDBusConnectionPrivate::findSlot(QObject* obj, const char *slotName, QList<i
|
|||
{
|
||||
Q_ASSERT(slotName);
|
||||
QByteArray normalizedName = QMetaObject::normalizedSignature(slotName);
|
||||
int midx = obj->metaObject()->indexOfMethod(normalizedName);
|
||||
int midx = obj->metaObject()->indexOfSlot(normalizedName);
|
||||
if (midx == -1) {
|
||||
qWarning("No such slot '%s' while connecting D-Bus", slotName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int inputCount = parametersForMethod(normalizedName, params);
|
||||
int inputCount = qDBusParametersForMethod(normalizedName, params);
|
||||
if ( inputCount == -1 || inputCount + 1 != params.count() )
|
||||
return -1; // failed to parse or invalid arguments or output arguments
|
||||
|
||||
|
||||
return midx;
|
||||
}
|
||||
|
||||
bool QDBusConnectionPrivate::activateObject(const QDBusConnectionPrivate::ObjectData &hook,
|
||||
const QDBusMessage &msg)
|
||||
bool QDBusConnectionPrivate::activateInternalFilters(const ObjectTreeNode *node, const QDBusMessage &msg)
|
||||
{
|
||||
if (!hook.obj)
|
||||
return false; // object is gone
|
||||
// object may be null
|
||||
|
||||
if (hook.flags & QDBusConnection::ExportAdaptors)
|
||||
return activateAdaptor(hook.obj, hook.flags, msg);
|
||||
else
|
||||
return activateCall(hook.obj, hook.flags, msg);
|
||||
if (msg.interface() == QLatin1String(DBUS_INTERFACE_INTROSPECTABLE)) {
|
||||
if (msg.method() == QLatin1String("Introspect") && msg.signature().isEmpty())
|
||||
qDBusIntrospectObject(node, msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (node->obj && msg.interface() == QLatin1String(DBUS_INTERFACE_PROPERTIES)) {
|
||||
if (msg.method() == QLatin1String("Get") && msg.signature() == QLatin1String("ss"))
|
||||
qDBusPropertyGet(node, msg);
|
||||
else if (msg.method() == QLatin1String("Set") && msg.signature() == QLatin1String("ssv"))
|
||||
qDBusPropertySet(node, msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QDBusConnectionPrivate::activateObject(const ObjectTreeNode *node, const QDBusMessage &msg)
|
||||
{
|
||||
// This is called by QDBusConnectionPrivate::handleObjectCall to place a call to a slot
|
||||
// on the object.
|
||||
//
|
||||
// The call is routed through the adaptor sub-objects if we have any
|
||||
|
||||
// object may be null
|
||||
|
||||
QDBusAdaptorConnector *connector;
|
||||
if (node->flags & QDBusConnection::ExportAdaptors &&
|
||||
(connector = qDBusFindAdaptorConnector(node->obj))) {
|
||||
int newflags = node->flags | QDBusConnection::ExportNonScriptableSlots;
|
||||
|
||||
if (msg.interface().isEmpty()) {
|
||||
// place the call in all interfaces
|
||||
// let the first one that handles it to work
|
||||
foreach (const QDBusAdaptorConnector::AdaptorData &entry, connector->adaptors)
|
||||
if (activateCall(entry.adaptor, newflags, msg))
|
||||
return true;
|
||||
} else {
|
||||
// check if we have an interface matching the name that was asked:
|
||||
QDBusAdaptorConnector::AdaptorMap::ConstIterator it;
|
||||
it = qLowerBound(connector->adaptors.constBegin(), connector->adaptors.constEnd(),
|
||||
msg.interface());
|
||||
if (it != connector->adaptors.end() && it->interface == msg.interface())
|
||||
if (activateCall(it->adaptor, newflags, msg))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// no adaptors matched
|
||||
// try our standard filters
|
||||
if (activateInternalFilters(node, msg))
|
||||
return true;
|
||||
|
||||
// try the object itself:
|
||||
if (node->flags & QDBusConnection::ExportSlots && activateCall(node->obj, node->flags, msg))
|
||||
return true;
|
||||
|
||||
// nothing matched
|
||||
qDebug("Call failed: no match for %s%s%s at %s",
|
||||
qPrintable(msg.interface()), msg.interface().isEmpty() ? "" : ".",
|
||||
qPrintable(msg.name()),
|
||||
qPrintable(msg.path()));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QDBusConnectionPrivate::handleObjectCall(const QDBusMessage &msg)
|
||||
{
|
||||
ObjectHookHash::ConstIterator it = objectHooks.find(msg.path());
|
||||
if (it == objectHooks.constEnd())
|
||||
return false;
|
||||
|
||||
bool ok = false;
|
||||
const ObjectDataHash& hook = it.value();
|
||||
ObjectDataHash::ConstIterator hit;
|
||||
if (msg.interface().isEmpty()) {
|
||||
// we must go through all the objects and interfaces
|
||||
|
||||
for (hit = hook.begin(); hit != hook.end(); ++hit) {
|
||||
ok = activateObject(hit.value(), msg);
|
||||
if (ok)
|
||||
break; // processed
|
||||
}
|
||||
} else {
|
||||
// find the interface:
|
||||
hit = hook.find(msg.interface());
|
||||
if (hit != hook.end())
|
||||
ok = activateObject(hit.value(), msg);
|
||||
QReadLocker locker(&lock);
|
||||
|
||||
if (!ok) {
|
||||
// try adaptors (or any interface)
|
||||
hit = hook.find(QString());
|
||||
if (hit != hook.end())
|
||||
ok = activateObject(hit.value(), msg);
|
||||
// walk the object tree
|
||||
QStringList path = msg.path().split(QLatin1Char('/'));
|
||||
if (path.last().isEmpty())
|
||||
path.removeLast(); // happens if path is "/"
|
||||
int i = 1;
|
||||
ObjectTreeNode *node = &rootNode;
|
||||
|
||||
// try our own tree first
|
||||
while (node && !(node->flags & QDBusConnection::ExportChildObjects) ) {
|
||||
if (i == path.count()) {
|
||||
// found our object
|
||||
return activateObject(node, msg);
|
||||
}
|
||||
|
||||
QVector<ObjectTreeNode::Data>::ConstIterator it =
|
||||
qLowerBound(node->children.constBegin(), node->children.constEnd(), path.at(i));
|
||||
if (it != node->children.constEnd() && it->name == path.at(i))
|
||||
// match
|
||||
node = it->node;
|
||||
else
|
||||
node = 0;
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
// any object in the tree can tell us to switch to its own object tree:
|
||||
if (node && node->flags & QDBusConnection::ExportChildObjects) {
|
||||
QObject *obj = node->obj;
|
||||
|
||||
while (obj) {
|
||||
if (i == path.count()) {
|
||||
// we're at the correct level
|
||||
ObjectTreeNode fakenode(*node);
|
||||
fakenode.obj = obj;
|
||||
return activateObject(&fakenode, msg);
|
||||
}
|
||||
|
||||
const QObjectList &children = obj->children();
|
||||
|
||||
// find a child with the proper name
|
||||
QObject *next = 0;
|
||||
foreach (QObject *child, children)
|
||||
if (child->objectName() == path.at(i)) {
|
||||
next = child;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!next)
|
||||
break;
|
||||
|
||||
++i;
|
||||
obj = next;
|
||||
}
|
||||
}
|
||||
|
||||
qDebug(ok ? "Call scheduled" : "Call failed");
|
||||
return ok;
|
||||
qDebug("Call failed: no object found at %s", qPrintable(msg.path()));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QDBusConnectionPrivate::handleSignal(const QString &path, const QDBusMessage &msg)
|
||||
{
|
||||
QReadLocker locker(&lock);
|
||||
|
||||
bool result = false;
|
||||
SignalHookHash::const_iterator it = signalHooks.find(path);
|
||||
qDebug("looking for: %s", path.toLocal8Bit().constData());
|
||||
qDebug() << signalHooks.keys();
|
||||
for ( ; it != signalHooks.constEnd() && it.key() == path; ++ it) {
|
||||
const SignalHook &hook = it.value();
|
||||
if ( hook.obj.isNull() )
|
||||
continue;
|
||||
if ( !hook.name.isEmpty() && hook.name != msg.name() )
|
||||
continue;
|
||||
if ( !hook.interface.isEmpty() && hook.interface != msg.interface() )
|
||||
continue;
|
||||
if ( !hook.signature.isEmpty() && hook.signature != msg.signature() )
|
||||
continue;
|
||||
if ( hook.signature.isEmpty() && !hook.signature.isNull() && !msg.signature().isEmpty())
|
||||
continue;
|
||||
|
||||
activateSignal(hook, msg);
|
||||
// yes, |=
|
||||
result |= activateSignal(hook, msg);
|
||||
}
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool QDBusConnectionPrivate::handleSignal(const QDBusMessage& msg)
|
||||
|
|
@ -1057,7 +1191,11 @@ void QDBusConnectionPrivate::setConnection(DBusConnection *dbc)
|
|||
qWarning("QDBusConnectionPrivate::SetConnection: Unable to get base service");
|
||||
}
|
||||
|
||||
#if USE_OUTSIDE_DISPATCH
|
||||
dbus_connection_add_filter_outside(connection, qDBusSignalFilter, qDBusSignalFilterOutside, this, 0);
|
||||
#else
|
||||
dbus_connection_add_filter(connection, qDBusSignalFilter, this, 0);
|
||||
#endif
|
||||
|
||||
qDebug("base service: %s", service);
|
||||
}
|
||||
|
|
@ -1070,8 +1208,20 @@ static void qDBusResultReceived(DBusPendingCall *pending, void *user_data)
|
|||
|
||||
if (!call->receiver.isNull() && call->methodIdx != -1) {
|
||||
DBusMessage *reply = dbus_pending_call_steal_reply(pending);
|
||||
connection->activateReply(call->receiver, call->methodIdx, call->metaTypes,
|
||||
QDBusMessage::fromDBusMessage(reply));
|
||||
|
||||
// Deliver the return values of a remote function call.
|
||||
//
|
||||
// There is only one connection and it is specified by idx
|
||||
// The slot must have the same parameter types that the message does
|
||||
// The slot may have less parameters than the message
|
||||
// The slot may optionally have one final parameter that is QDBusMessage
|
||||
// The slot receives read-only copies of the message (i.e., pass by value or by const-ref)
|
||||
CallDeliveryEvent *e = prepareReply(call->receiver, call->methodIdx, call->metaTypes,
|
||||
QDBusMessage::fromDBusMessage(reply,
|
||||
QDBusConnection(connection->name)));
|
||||
if (e)
|
||||
connection->deliverCall(*e);
|
||||
delete e;
|
||||
}
|
||||
dbus_pending_call_unref(pending);
|
||||
delete call;
|
||||
|
|
@ -1122,10 +1272,31 @@ int QDBusConnectionPrivate::sendWithReplyAsync(const QDBusMessage &message, QObj
|
|||
return 0;
|
||||
}
|
||||
|
||||
void QDBusConnectionPrivate::connectSignal(const QString &key, const SignalHook &hook)
|
||||
{
|
||||
signalHooks.insertMulti(key, hook);
|
||||
connect(hook.obj, SIGNAL(destroyed(QObject*)), SLOT(objectDestroyed(QObject*)));
|
||||
}
|
||||
|
||||
void QDBusConnectionPrivate::registerObject(const ObjectTreeNode *node)
|
||||
{
|
||||
connect(node->obj, SIGNAL(destroyed(QObject*)), SLOT(objectDestroyed(QObject*)));
|
||||
|
||||
if (node->flags & QDBusConnection::ExportAdaptors) {
|
||||
QDBusAdaptorConnector *connector = qDBusCreateAdaptorConnector(node->obj);
|
||||
|
||||
// disconnect and reconnect to avoid duplicates
|
||||
connector->disconnect(SIGNAL(relaySignal(QObject *,const char*, const char*,QVariantList)),
|
||||
this, SLOT(relaySignal(QObject*, const char*, const char*,QVariantList)));
|
||||
connect(connector, SIGNAL(relaySignal(QObject *,const char*, const char*,QVariantList)),
|
||||
SLOT(relaySignal(QObject*, const char*, const char*,QVariantList)));
|
||||
}
|
||||
}
|
||||
|
||||
QSharedDataPointer<QDBusIntrospection::Interface>
|
||||
QDBusConnectionPrivate::findInterface(const QString& name)
|
||||
{
|
||||
QMutexLocker locker(&mutex);
|
||||
QWriteLocker locker(&lock);
|
||||
QSharedDataPointer<QDBusIntrospection::Interface> data = knownInterfaces.value(name);
|
||||
if (!data) {
|
||||
data = new QDBusIntrospection::Interface;
|
||||
|
|
@ -1140,7 +1311,7 @@ QDBusConnectionPrivate::findInterface(const QString& name)
|
|||
QDBusIntrospection::Object*
|
||||
QDBusConnectionPrivate::findObject(const QString& service, const QString& path)
|
||||
{
|
||||
QMutexLocker locker(&mutex);
|
||||
QWriteLocker locker(&lock);
|
||||
QDBusIntrospection::Object* data = knownObjects.value(service + path);
|
||||
if (!data) {
|
||||
data = new QDBusIntrospection::Object;
|
||||
|
|
@ -1149,7 +1320,7 @@ QDBusConnectionPrivate::findObject(const QString& service, const QString& path)
|
|||
|
||||
knownObjects.insert(service + path, data);
|
||||
}
|
||||
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
|
@ -1159,7 +1330,7 @@ void QDBusConnectionPrivate::disposeOfLocked(QDBusIntrospection::Object* p)
|
|||
// no one else is using it
|
||||
// get rid of the reference
|
||||
QString objName = p->service + p->path;
|
||||
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
// debug code
|
||||
Q_ASSERT(p == knownObjects.take(objName));
|
||||
|
|
@ -1169,11 +1340,11 @@ void QDBusConnectionPrivate::disposeOfLocked(QDBusIntrospection::Object* p)
|
|||
#endif
|
||||
|
||||
// remove sub-objects too
|
||||
if (!objName.endsWith('/'))
|
||||
objName.append('/');
|
||||
if (!objName.endsWith(QLatin1Char('/')))
|
||||
objName.append(QLatin1Char('/'));
|
||||
foreach (QString subObjName, p->childObjects)
|
||||
disposeOfLocked(knownObjects.value(objName + subObjName));
|
||||
|
||||
|
||||
delete p;
|
||||
}
|
||||
}
|
||||
|
|
@ -1183,7 +1354,7 @@ void QDBusConnectionPrivate::disposeOf(QDBusObjectPrivate* p)
|
|||
// We're called from QDBusConnectionPrivate's destructor
|
||||
// that means the object it represents is going out of scope
|
||||
|
||||
QMutexLocker locker(&mutex);
|
||||
QWriteLocker locker(&lock);
|
||||
disposeOfLocked( const_cast<QDBusIntrospection::Object*>(p->data) );
|
||||
}
|
||||
|
||||
|
|
@ -1192,3 +1363,4 @@ void QDBusReplyWaiter::reply(const QDBusMessage &msg)
|
|||
replyMsg = msg;
|
||||
QTimer::singleShot(0, this, SLOT(quit()));
|
||||
}
|
||||
#include "qdbusconnection_p.moc"
|
||||
|
|
|
|||
|
|
@ -28,31 +28,115 @@
|
|||
|
||||
#include "qdbusinterface_p.h"
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
struct EmptyInterfaceInitializer
|
||||
{
|
||||
QDBusIntrospection::Interface *data;
|
||||
EmptyInterfaceInitializer()
|
||||
{
|
||||
data = new QDBusIntrospection::Interface;
|
||||
data->ref = 1;
|
||||
data->introspection = QLatin1String("");
|
||||
}
|
||||
|
||||
~EmptyInterfaceInitializer()
|
||||
{
|
||||
Q_ASSERT(data->ref == 1);
|
||||
delete data;
|
||||
data = 0;
|
||||
}
|
||||
};
|
||||
|
||||
Q_GLOBAL_STATIC(EmptyInterfaceInitializer, emptyDataInit);
|
||||
|
||||
const QDBusIntrospection::Interface*
|
||||
QDBusInterfacePrivate::emptyData()
|
||||
{
|
||||
return emptyDataInit()->data;
|
||||
}
|
||||
|
||||
/*!
|
||||
\class QDBusInterface
|
||||
\brief Base class for all D-Bus interfaces in the QtDBus binding, allowing access to remote interfaces.
|
||||
|
||||
QDBusInterface is a generic accessor class that is used to place calls to remote objects,
|
||||
connect to signals exported by remote objects and get/set the value of remote properties. This
|
||||
class is useful for dynamic access to remote objects: that is, when you do not have a generated
|
||||
code that represents the remote interface.
|
||||
|
||||
Generated-code classes also derive from QDBusInterface, 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.
|
||||
|
||||
Calls are usually placed by using the call() function, which constructs the message, sends it
|
||||
over the bus, waits for the reply and decodes the reply. Signals are connected to by using the
|
||||
connect() family of functions, whose behavior is similar to QObject::connect(). Finally,
|
||||
properties are accessed using the property() and setProperty() functions, whose behaviour is
|
||||
also similar to QObject::property() and QObject::setProperty().
|
||||
|
||||
\sa \ref StandardInterfaces, \ref dbusidl2cpp
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum QDBusInterface::CallMode
|
||||
\todo turn this into flags and add UseEventLoop/NoUseEventLoop
|
||||
|
||||
Specifies how a call should be placed. The valid options are:
|
||||
\value NoWaitForReply place the call but don't wait for the reply (the reply's contents
|
||||
will be discarded)
|
||||
\value WaitForReply place the call and wait for the method to finish before returning
|
||||
(the reply's contents will be returned)
|
||||
\value NoUseEventLoop don't use an event loop to wait for a reply, but instead block on
|
||||
network operations while waiting. This option means the
|
||||
user-interface may not be updated for the duration of the call.
|
||||
\value UseEventLoop use the Qt event loop to wait for a reply. This option means the
|
||||
user-interface will update, but it also means other events may
|
||||
happen, like signal delivery and other D-Bus method calls.
|
||||
|
||||
When using UseEventLoop, applications must be prepared for reentrancy in any function.
|
||||
*/
|
||||
|
||||
QDBusInterface::QDBusInterface(QDBusInterfacePrivate* p)
|
||||
: d(p)
|
||||
{
|
||||
d->ref.ref();
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a QDBusInterface object by associating it with the interface \p name in the remote
|
||||
object \p obj.
|
||||
*/
|
||||
QDBusInterface::QDBusInterface(const QDBusObject& obj, const QString& name)
|
||||
: d(0)
|
||||
{
|
||||
*this = obj.connection().findInterface(obj.service(), obj.path(), name);
|
||||
}
|
||||
|
||||
QDBusInterface::QDBusInterface(QDBusConnection& conn, const QString& service, const QString& path,
|
||||
const QString& name)
|
||||
/*!
|
||||
Constructs a copy QDBusInterface object.
|
||||
*/
|
||||
QDBusInterface::QDBusInterface(const QDBusInterface &other)
|
||||
: d(0)
|
||||
{
|
||||
*this = conn.findInterface(service, path, name);
|
||||
*this = other;
|
||||
}
|
||||
|
||||
/*!
|
||||
Releases this object's resources.
|
||||
*/
|
||||
QDBusInterface::~QDBusInterface()
|
||||
{
|
||||
if (!d->ref.deref())
|
||||
delete d;
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a copy QDBusInterface object.
|
||||
*/
|
||||
QDBusInterface& QDBusInterface::operator=(const QDBusInterface& other)
|
||||
{
|
||||
other.d->ref.ref();
|
||||
|
|
@ -63,67 +147,132 @@ QDBusInterface& QDBusInterface::operator=(const QDBusInterface& other)
|
|||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn QDBusInterface::object()
|
||||
Returns the object associated with this interface.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusInterface::object() const
|
||||
\overload
|
||||
Returns the object associated with this interface.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn "QDBusInterface::operator QDBusObject"
|
||||
\overload
|
||||
Returns the object associated with this interface.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn "QDBusInterface::operator const QDBusObject"
|
||||
\overload
|
||||
Returns the object associated with this interface.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Returns the connection this interface is assocated with.
|
||||
*/
|
||||
QDBusConnection QDBusInterface::connection() const
|
||||
{
|
||||
return d->conn;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the name of the service this interface is associated with.
|
||||
*/
|
||||
QString QDBusInterface::service() const
|
||||
{
|
||||
return d->service;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the object path that this interface is associated with.
|
||||
*/
|
||||
QString QDBusInterface::path() const
|
||||
{
|
||||
return d->path;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the name of this interface.
|
||||
*/
|
||||
QString QDBusInterface::interface() const
|
||||
{
|
||||
return d->data->name;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the XML document fragment that describes the introspection of this interface. This is
|
||||
the raw XML form of the structures returned by interfaceData().
|
||||
*/
|
||||
QString QDBusInterface::introspectionData() const
|
||||
{
|
||||
d->introspect();
|
||||
return d->data->introspection;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the interface data for this interface. This is the parsed form of the XML introspection
|
||||
data, as returned by introspectionData().
|
||||
*/
|
||||
const QDBusIntrospection::Interface& QDBusInterface::interfaceData() const
|
||||
{
|
||||
d->introspect();
|
||||
return *d->data;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the annotations present in this interface, if any.
|
||||
This information can also be found in the data returned by interfaceData().
|
||||
*/
|
||||
const QDBusIntrospection::Annotations& QDBusInterface::annotationData() const
|
||||
{
|
||||
d->introspect();
|
||||
return d->data->annotations;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a map of all the methods found in this interface.
|
||||
This information can also be found in the data returned by interfaceData().
|
||||
*/
|
||||
const QDBusIntrospection::Methods& QDBusInterface::methodData() const
|
||||
{
|
||||
d->introspect();
|
||||
return d->data->methods;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a map of all the signals found in this interface.
|
||||
This information can also be found in the data returned by interfaceData().
|
||||
*/
|
||||
const QDBusIntrospection::Signals& QDBusInterface::signalData() const
|
||||
{
|
||||
d->introspect();
|
||||
return d->data->signals_;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a map of all the properties found in this interface.
|
||||
This information can also be found in the data returned by interfaceData().
|
||||
*/
|
||||
const QDBusIntrospection::Properties& QDBusInterface::propertyData() const
|
||||
{
|
||||
d->introspect();
|
||||
return d->data->properties;
|
||||
}
|
||||
|
||||
/*!
|
||||
Places a call to the remote method specified by \p method on this interface, using \p a_args as
|
||||
arguments.
|
||||
|
||||
Normally, you should place calls using call().
|
||||
*/
|
||||
QDBusMessage QDBusInterface::callWithArgs(const QDBusIntrospection::Method& method,
|
||||
const QList<QVariant>& a_args,
|
||||
CallMode mode)
|
||||
{
|
||||
QString signature(""); // empty, not null
|
||||
QString signature = QLatin1String(""); // empty, not null
|
||||
QVariantList args = a_args;
|
||||
|
||||
if (!method.inputArgs.isEmpty())
|
||||
|
|
@ -142,29 +291,45 @@ QDBusMessage QDBusInterface::callWithArgs(const QDBusIntrospection::Method& meth
|
|||
else
|
||||
args.clear();
|
||||
|
||||
if (method.annotations.value(ANNOTATION_NO_WAIT, "false") == "true")
|
||||
if (method.annotations.value(QLatin1String(ANNOTATION_NO_WAIT)) == QLatin1String("true"))
|
||||
mode = NoWaitForReply;
|
||||
|
||||
return callWithArgs(method.name, signature, args, mode);
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
Places a call to the remote method specified by \p method on this interface, using \p args as
|
||||
arguments.
|
||||
|
||||
Normally, you should place calls using call().
|
||||
*/
|
||||
QDBusMessage QDBusInterface::callWithArgs(const QString& method, const QList<QVariant>& args,
|
||||
CallMode mode)
|
||||
{
|
||||
QString m = method, sig;
|
||||
// split out the signature from the method
|
||||
int pos = method.indexOf('.');
|
||||
int pos = method.indexOf(QLatin1Char('.'));
|
||||
if (pos != -1) {
|
||||
m.truncate(pos);
|
||||
sig = method.mid(pos + 1);
|
||||
}
|
||||
}
|
||||
return callWithArgs(m, sig, args, mode);
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
Places a call to the remote method specified by \p method on this interface, using \p args as
|
||||
arguments. The \p signature parameter specifies how the arguments should be marshalled over the
|
||||
connection. (It also serves to distinguish between overloading of remote methods by name)
|
||||
|
||||
Normally, you should place calls using call().
|
||||
*/
|
||||
QDBusMessage QDBusInterface::callWithArgs(const QString& method, const QString& signature,
|
||||
const QList<QVariant>& args, CallMode mode)
|
||||
{
|
||||
QDBusMessage msg = QDBusMessage::methodCall(service(), path(), interface(), method, signature);
|
||||
QDBusMessage msg = QDBusMessage::methodCall(service(), path(), interface(), method);
|
||||
msg.setSignature(signature);
|
||||
msg.QList<QVariant>::operator=(args);
|
||||
|
||||
QDBusMessage reply;
|
||||
|
|
@ -182,9 +347,14 @@ QDBusMessage QDBusInterface::callWithArgs(const QString& method, const QString&
|
|||
return reply;
|
||||
}
|
||||
|
||||
/*!
|
||||
Connects the D-Bus signal specified by \p sig to the given slot \p slot in the object \p obj.
|
||||
|
||||
This function is similar to QObject::connect.
|
||||
*/
|
||||
bool QDBusInterface::connect(const QDBusIntrospection::Signal& sig, QObject* obj, const char *slot)
|
||||
{
|
||||
QString signature(""); // empty, not null
|
||||
QString signature = QLatin1String(""); // empty, not null
|
||||
|
||||
if (!sig.outputArgs.isEmpty())
|
||||
{
|
||||
|
|
@ -203,54 +373,135 @@ bool QDBusInterface::connect(const QDBusIntrospection::Signal& sig, QObject* obj
|
|||
return connect(sig.name, signature, obj, slot);
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
Connects the D-Bus signal specified by \p signalName to the given slot \p slot in the object \p
|
||||
obj.
|
||||
|
||||
This function is similar to QObject::connect.
|
||||
*/
|
||||
bool QDBusInterface::connect(const QString& signalName, QObject* obj, const char *slot)
|
||||
{
|
||||
QString s = signalName, sig;
|
||||
// split out the signature from the name
|
||||
int pos = signalName.indexOf('.');
|
||||
int pos = signalName.indexOf(QLatin1Char('.'));
|
||||
if (pos != -1) {
|
||||
s.truncate(pos);
|
||||
sig = signalName.mid(pos + 1);
|
||||
sig = QLatin1String("") + signalName.mid(pos + 1);
|
||||
}
|
||||
return connect(s, sig, obj, slot);
|
||||
}
|
||||
|
||||
/*!
|
||||
\overload
|
||||
Connects the D-Bus signal specified by \p signalName to the given slot \p slot in the object \p
|
||||
obj. The \p signature parameter allows one to connect to the signal only if it is emitted with
|
||||
the parameters matching the given type signature.
|
||||
|
||||
This function is similar to QObject::connect.
|
||||
*/
|
||||
bool QDBusInterface::connect(const QString& signalName, const QString& signature,
|
||||
QObject* obj, const char *slot)
|
||||
{
|
||||
return d->conn.connect(service(), path(), interface(), signalName, signature, obj, slot);
|
||||
}
|
||||
|
||||
QVariant QDBusInterface::propertyGet(const QDBusIntrospection::Property& prop)
|
||||
/*!
|
||||
Retrieves the value of the property \p prop in the remote object. This function returns an error
|
||||
if you try to read the value of a write-only property.
|
||||
*/
|
||||
QDBusReply<QDBusVariant> QDBusInterface::property(const QDBusIntrospection::Property& prop)
|
||||
{
|
||||
// sanity checking
|
||||
if (prop.access == QDBusIntrospection::Property::Write)
|
||||
return QVariant(); // write-only prop
|
||||
// write-only prop
|
||||
return QDBusError(QLatin1String(DBUS_ERROR_ACCESS_DENIED),
|
||||
QString::fromLatin1("Property %1 in interface %2 in object %3 is write-only")
|
||||
.arg(prop.name, interface(), path()));
|
||||
|
||||
QDBusPropertiesInterface pi(object());
|
||||
return pi.get(interface(), prop.name);
|
||||
}
|
||||
|
||||
QVariant QDBusInterface::propertyGet(const QString& propName)
|
||||
/*!
|
||||
\overload
|
||||
Retrieves the value of the property \p propname in the remote object. This function returns an
|
||||
error if you try to read the value of a write-only property.
|
||||
*/
|
||||
QDBusReply<QDBusVariant> QDBusInterface::property(const QString& propName)
|
||||
{
|
||||
// can't do sanity checking
|
||||
QDBusPropertiesInterface pi(object());
|
||||
return pi.get(interface(), propName);
|
||||
}
|
||||
|
||||
void QDBusInterface::propertySet(const QDBusIntrospection::Property& prop, QVariant newValue)
|
||||
/*!
|
||||
Sets the value of the property \p prop to \p newValue in the remote object. This function
|
||||
automatically changes the type of \p newValue to the property's type, but the call will fail if
|
||||
the types don't match.
|
||||
|
||||
This function returns an error if the property is read-only.
|
||||
*/
|
||||
QDBusReply<void> QDBusInterface::setProperty(const QDBusIntrospection::Property& prop,
|
||||
const QDBusVariant &newValue)
|
||||
{
|
||||
// sanity checking
|
||||
if (prop.access == QDBusIntrospection::Property::Read)
|
||||
return;
|
||||
// read-only prop
|
||||
return QDBusError(QLatin1String(DBUS_ERROR_ACCESS_DENIED),
|
||||
QString::fromLatin1("Property %1 in interface %2 in object %3 is read-only")
|
||||
.arg(prop.name, interface(), path()));
|
||||
|
||||
// set the property type
|
||||
QDBusVariant value = newValue;
|
||||
value.type = prop.type;
|
||||
|
||||
QDBusPropertiesInterface pi(object());
|
||||
pi.set(interface(), prop.name, newValue);
|
||||
return pi.set(interface(), prop.name, value);
|
||||
}
|
||||
|
||||
void QDBusInterface::propertySet(const QString& propName, QVariant newValue)
|
||||
/*!
|
||||
\overload
|
||||
Sets the value of the property \p propName to \p newValue in the remote object. This function
|
||||
will not change \p newValue's type to match the property, so it is your responsibility to make
|
||||
sure it is of the correct type.
|
||||
|
||||
This function returns an error if the property is read-only.
|
||||
*/
|
||||
QDBusReply<void> QDBusInterface::setProperty(const QString& propName, const QDBusVariant &newValue)
|
||||
{
|
||||
// can't do sanity checking
|
||||
QDBusPropertiesInterface pi(object());
|
||||
pi.set(interface(), propName, newValue);
|
||||
return pi.set(interface(), propName, newValue);
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn QDBusMessage QDBusInterface::call(const QDBusIntrospection::Method &method, ...)
|
||||
|
||||
Calls the method \p method on this interface and passes the parameters to this function to the
|
||||
method.
|
||||
|
||||
The parameters to \a call are passed on to the remote function via D-Bus as input
|
||||
arguments. Output arguments are returned in the QDBusMessage reply.
|
||||
|
||||
\warning This function reenters the Qt event loop in order to wait for the reply, excluding 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().
|
||||
*/
|
||||
|
||||
/*!
|
||||
\overload
|
||||
\fn QDBusMessage QDBusInterface::call(const QString &method, ...)
|
||||
|
||||
Calls the method \p method on this interface and passes the parameters to this function to the
|
||||
method.
|
||||
|
||||
The parameters to \a call are passed on to the remote function via D-Bus as input
|
||||
arguments. Output arguments are returned in the QDBusMessage reply.
|
||||
|
||||
\warning This function reenters the Qt event loop in order to wait for the reply, excluding 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().
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#include "qdbusmessage.h"
|
||||
#include "qdbusobject.h"
|
||||
#include "qdbusintrospection.h"
|
||||
#include "qdbusreply.h"
|
||||
#include "qdbusvariant.h"
|
||||
#include <QtCore/qstring.h>
|
||||
#include <QtCore/qvariant.h>
|
||||
#include <QtCore/qlist.h>
|
||||
|
|
@ -35,9 +37,6 @@
|
|||
class QDBusConnection;
|
||||
|
||||
class QDBusInterfacePrivate;
|
||||
/**
|
||||
* Base class for all DBUS interfaces in the QtDBUS binding.
|
||||
*/
|
||||
class QDBUS_EXPORT QDBusInterface
|
||||
{
|
||||
friend class QDBusConnection;
|
||||
|
|
@ -49,171 +48,65 @@ public:
|
|||
};
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct an interface of the given name
|
||||
*/
|
||||
QDBusInterface(const QDBusObject& obj, const QString& name);
|
||||
|
||||
/**
|
||||
* @overload.
|
||||
* Construct an interface of the given name
|
||||
*/
|
||||
QDBusInterface(QDBusConnection& conn, const QString& service, const QString& path, const QString& name);
|
||||
|
||||
/**
|
||||
* Construct a copy of the interface.
|
||||
*/
|
||||
QDBusInterface(const QDBusInterface&);
|
||||
|
||||
/**
|
||||
* Destructs this interface.
|
||||
*/
|
||||
virtual ~QDBusInterface();
|
||||
|
||||
/**
|
||||
* Copy the interface.
|
||||
*/
|
||||
QDBusInterface& operator=(const QDBusInterface&);
|
||||
|
||||
/**
|
||||
* Returns the object associated with this interface.
|
||||
*/
|
||||
inline QDBusObject object()
|
||||
{ return QDBusObject(*this); }
|
||||
|
||||
inline const QDBusObject object() const
|
||||
{ return QDBusObject(*this); }
|
||||
|
||||
/**
|
||||
* Returns the connection this interface is on.
|
||||
*/
|
||||
inline operator QDBusObject()
|
||||
{ return QDBusObject(*this); }
|
||||
|
||||
inline operator const QDBusObject() const
|
||||
{ return QDBusObject(*this); }
|
||||
|
||||
|
||||
QDBusConnection connection() const;
|
||||
|
||||
/**
|
||||
* Returns the name of the service this interface is associated with.
|
||||
*/
|
||||
QString service() const;
|
||||
|
||||
/**
|
||||
* Returns the object path that this interface is associated with.
|
||||
*/
|
||||
QString path() const;
|
||||
|
||||
/**
|
||||
* Returns the name of this interface.
|
||||
*/
|
||||
QString interface() const;
|
||||
|
||||
/**
|
||||
* Returns the introspection XML fragment data of this interface.
|
||||
*/
|
||||
virtual QString introspectionData() const;
|
||||
|
||||
/**
|
||||
* Returns the interface data for this interface.
|
||||
*/
|
||||
const QDBusIntrospection::Interface& interfaceData() const;
|
||||
|
||||
/**
|
||||
* Returns the annotations present in this interface, if any.
|
||||
*/
|
||||
const QDBusIntrospection::Annotations& annotationData() const;
|
||||
|
||||
/**
|
||||
* List all methods in this interface.
|
||||
*/
|
||||
const QDBusIntrospection::Methods& methodData() const;
|
||||
|
||||
/**
|
||||
* List all signals in this interface.
|
||||
*/
|
||||
const QDBusIntrospection::Signals& signalData() const;
|
||||
|
||||
/**
|
||||
* List all properties in this interface.
|
||||
*/
|
||||
const QDBusIntrospection::Properties& propertyData() const;
|
||||
|
||||
/**
|
||||
* Call the given method.
|
||||
*/
|
||||
QDBusMessage callWithArgs(const QDBusIntrospection::Method& method,
|
||||
const QList<QVariant>& args = QList<QVariant>(),
|
||||
CallMode mode = WaitForReply);
|
||||
|
||||
/**
|
||||
* Call the given method.
|
||||
*/
|
||||
QDBusMessage callWithArgs(const QString& method, const QList<QVariant>& args = QList<QVariant>(),
|
||||
CallMode mode = WaitForReply);
|
||||
|
||||
/**
|
||||
* Call the given method.
|
||||
*/
|
||||
QDBusMessage callWithArgs(const QString& method, const QString& signature,
|
||||
const QList<QVariant>& args = QList<QVariant>(),
|
||||
CallMode mode = WaitForReply);
|
||||
|
||||
/**
|
||||
* Connects the DBUS signal to the given slot.
|
||||
*/
|
||||
bool connect(const QDBusIntrospection::Signal&, QObject* obj, const char *slot);
|
||||
|
||||
/**
|
||||
* Connects the DBUS signal to the given slot.
|
||||
*/
|
||||
bool connect(const QString& signalName, QObject* obj, const char *slot);
|
||||
|
||||
/**
|
||||
* Connects the DBUS signal to the given slot.
|
||||
*/
|
||||
bool connect(const QString& signalName, const QString& signature,
|
||||
QObject* obj, const char *slot);
|
||||
|
||||
/**
|
||||
* Gets the value of the given property.
|
||||
*/
|
||||
QVariant propertyGet(const QDBusIntrospection::Property&);
|
||||
QDBusReply<QDBusVariant> property(const QDBusIntrospection::Property&);
|
||||
QDBusReply<QDBusVariant> property(const QString& property);
|
||||
|
||||
/**
|
||||
* Gets the value of the given property.
|
||||
*/
|
||||
QVariant propertyGet(const QString& property);
|
||||
QDBusReply<void> setProperty(const QDBusIntrospection::Property&, const QDBusVariant& newValue);
|
||||
QDBusReply<void> setProperty(const QString& property, const QDBusVariant& newValue);
|
||||
|
||||
/**
|
||||
* Sets the value of the given property.
|
||||
*/
|
||||
void propertySet(const QDBusIntrospection::Property&, QVariant newValue);
|
||||
|
||||
/**
|
||||
* Sets the value of the given property.
|
||||
*/
|
||||
void propertySet(const QString& property, QVariant newValue);
|
||||
|
||||
/**
|
||||
* Casts to QDBusObject.
|
||||
*/
|
||||
inline operator QDBusObject()
|
||||
{ return QDBusObject(*this); }
|
||||
|
||||
/**
|
||||
* Casts to const QDBusObject.
|
||||
*/
|
||||
inline operator const QDBusObject() const
|
||||
{ return QDBusObject(*this); }
|
||||
|
||||
/**
|
||||
* Call the given method.
|
||||
*/
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
template<typename MethodType>
|
||||
inline QDBusMessage call(MethodType m)
|
||||
{
|
||||
return callWithArgs(m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the given method.
|
||||
*/
|
||||
template<typename MethodType, typename T1>
|
||||
inline QDBusMessage call(MethodType m, T1 t1)
|
||||
{
|
||||
|
|
@ -222,9 +115,6 @@ public:
|
|||
return callWithArgs(m, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the given method.
|
||||
*/
|
||||
template<typename MethodType, typename T1, typename T2>
|
||||
inline QDBusMessage call(MethodType m, T1 t1, T2 t2)
|
||||
{
|
||||
|
|
@ -233,9 +123,6 @@ public:
|
|||
return callWithArgs(m, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the given method.
|
||||
*/
|
||||
template<typename MethodType, typename T1, typename T2, typename T3>
|
||||
inline QDBusMessage call(MethodType m, T1 t1, T2 t2, T3 t3)
|
||||
{
|
||||
|
|
@ -244,9 +131,6 @@ public:
|
|||
return callWithArgs(m, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the given method.
|
||||
*/
|
||||
template<typename MethodType, typename T1, typename T2, typename T3, typename T4>
|
||||
inline QDBusMessage call(MethodType m, T1 t1, T2 t2, T3 t3, T4 t4)
|
||||
{
|
||||
|
|
@ -255,9 +139,6 @@ public:
|
|||
return callWithArgs(m, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the given method.
|
||||
*/
|
||||
template<typename MethodType, typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
inline QDBusMessage call(MethodType m, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
|
||||
{
|
||||
|
|
@ -266,9 +147,6 @@ public:
|
|||
return callWithArgs(m, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the given method.
|
||||
*/
|
||||
template<typename MethodType, typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||
typename T6>
|
||||
inline QDBusMessage call(MethodType m, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
|
||||
|
|
@ -278,9 +156,6 @@ public:
|
|||
return callWithArgs(m, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the given method.
|
||||
*/
|
||||
template<typename MethodType, typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||
typename T6, typename T7>
|
||||
inline QDBusMessage call(MethodType m, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
|
||||
|
|
@ -290,9 +165,6 @@ public:
|
|||
return callWithArgs(m, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the given method.
|
||||
*/
|
||||
template<typename MethodType, typename T1, typename T2, typename T3, typename T4, typename T5,
|
||||
typename T6, typename T7, typename T8>
|
||||
inline QDBusMessage call(MethodType m, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
|
||||
|
|
@ -301,6 +173,11 @@ public:
|
|||
args << t1 << t2 << t3 << t4 << t5 << t6 << t7 << t8;
|
||||
return callWithArgs(m, args);
|
||||
}
|
||||
#else
|
||||
// fool Doxygen
|
||||
inline QDBusMessage call(const QDBusIntrospection::Method &method, ...);
|
||||
inline QDBusMessage call(const QString &method, ...);
|
||||
#endif
|
||||
|
||||
private:
|
||||
QDBusInterface(QDBusInterfacePrivate*);
|
||||
|
|
|
|||
|
|
@ -56,11 +56,16 @@ public:
|
|||
//QConstSharedDataPointer<QDBusIntrospection::Interface> data;
|
||||
const QDBusIntrospection::Interface* data;
|
||||
|
||||
inline QDBusInterfacePrivate(const QDBusConnection &other) : conn(other), data(emptyData())
|
||||
{ }
|
||||
|
||||
inline bool needsIntrospection() const
|
||||
{ return data->introspection.isNull(); }
|
||||
{ return data && data->introspection.isNull(); }
|
||||
|
||||
inline void introspect()
|
||||
{ if (needsIntrospection()) QDBusObject(conn, service, path).introspect(); }
|
||||
{ if (needsIntrospection()) conn.findObject(service, path).introspect(); }
|
||||
|
||||
static const QDBusIntrospection::Interface *emptyData();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
369
qt/qdbusinternalfilters.cpp
Normal file
369
qt/qdbusinternalfilters.cpp
Normal file
|
|
@ -0,0 +1,369 @@
|
|||
/* -*- mode: C++ -*-
|
||||
*
|
||||
* Copyright (C) 2006 Trolltech AS. All rights reserved.
|
||||
* Author: Thiago Macieira <thiago.macieira@trolltech.com>
|
||||
*
|
||||
* Licensed under the Academic Free License version 2.1
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qdbusconnection_p.h"
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
#include <QtCore/qcoreapplication.h>
|
||||
#include <QtCore/qmetaobject.h>
|
||||
|
||||
#include "qdbusstandardinterfaces.h"
|
||||
#include "qdbusabstractadaptor.h"
|
||||
#include "qdbusabstractadaptor_p.h"
|
||||
#include "qdbusinterface_p.h" // for ANNOTATION_NO_WAIT
|
||||
#include "qdbusmessage.h"
|
||||
#include "qdbustype.h"
|
||||
#include "qdbusvariant.h"
|
||||
|
||||
// implement the D-Bus org.freedesktop.DBus.Introspectable interface
|
||||
// we do that by analysing the metaObject of all the adaptor interfaces
|
||||
|
||||
static inline QString dbusMemberName(const char *qtMemberName)
|
||||
{
|
||||
QString retval = QLatin1String(qtMemberName);
|
||||
if (!retval.isEmpty())
|
||||
retval[0] = retval[0].toUpper();
|
||||
return retval;
|
||||
}
|
||||
|
||||
static QString generateInterfaceXml(const QMetaObject *mo, int flags, int methodOffset, int propOffset)
|
||||
{
|
||||
QString retval;
|
||||
|
||||
// start with properties:
|
||||
if (flags & QDBusConnection::ExportProperties) {
|
||||
for (int i = propOffset; i < mo->propertyCount(); ++i) {
|
||||
static const char *accessvalues[] = {0, "read", "write", "readwrite"};
|
||||
|
||||
QMetaProperty mp = mo->property(i);
|
||||
|
||||
if (!mp.isScriptable() && (flags & QDBusConnection::ExportNonScriptableProperties) !=
|
||||
QDBusConnection::ExportNonScriptableProperties)
|
||||
continue;
|
||||
|
||||
int access = 0;
|
||||
if (mp.isReadable())
|
||||
access |= 1;
|
||||
if (mp.isWritable())
|
||||
access |= 2;
|
||||
|
||||
int typeId = qDBusNameToTypeId(mp.typeName());
|
||||
if (!typeId)
|
||||
continue;
|
||||
|
||||
retval += QString(QLatin1String(" <property name=\"%1\" type=\"%2\" access=\"%3\" />\n"))
|
||||
.arg(dbusMemberName(mp.name()))
|
||||
.arg(QLatin1String(QDBusType::dbusSignature( QVariant::Type(typeId) )))
|
||||
.arg(QLatin1String( accessvalues[access] ));
|
||||
}
|
||||
}
|
||||
|
||||
// now add methods:
|
||||
for (int i = methodOffset; i < mo->methodCount(); ++i) {
|
||||
QMetaMethod mm = mo->method(i);
|
||||
QByteArray signature = mm.signature();
|
||||
int paren = signature.indexOf('(');
|
||||
|
||||
bool isSignal;
|
||||
if (mm.methodType() == QMetaMethod::Signal)
|
||||
// adding a signal
|
||||
isSignal = true;
|
||||
else if (mm.methodType() == QMetaMethod::Slot && mm.access() == QMetaMethod::Public)
|
||||
isSignal = false;
|
||||
else
|
||||
continue; // neither signal nor public slot
|
||||
|
||||
if ((isSignal && !(flags & QDBusConnection::ExportSignals)) ||
|
||||
(!isSignal && !(flags & QDBusConnection::ExportSlots)))
|
||||
continue;
|
||||
|
||||
QString xml = QString(QLatin1String(" <%1 name=\"%2\">\n"))
|
||||
.arg(isSignal ? QLatin1String("signal") : QLatin1String("method"))
|
||||
.arg(dbusMemberName(signature.left(paren)));
|
||||
|
||||
// check the return type first
|
||||
int typeId = qDBusNameToTypeId(mm.typeName());
|
||||
if (typeId)
|
||||
xml += QString(QLatin1String(" <arg type=\"%1\" direction=\"out\"/>\n"))
|
||||
.arg(QLatin1String(QDBusType::dbusSignature( QVariant::Type(typeId) )));
|
||||
else if (*mm.typeName())
|
||||
continue; // wasn't a valid type
|
||||
|
||||
QList<QByteArray> names = mm.parameterNames();
|
||||
QList<int> types;
|
||||
int inputCount = qDBusParametersForMethod(QMetaObject::normalizedSignature(signature),
|
||||
types);
|
||||
if (inputCount == -1)
|
||||
continue; // invalid form
|
||||
if (isSignal && inputCount + 1 != types.count())
|
||||
continue; // signal with output arguments?
|
||||
if (isSignal && types.at(inputCount) == QDBusConnectionPrivate::messageMetaType)
|
||||
continue; // signal with QDBusMessage argument?
|
||||
|
||||
int j;
|
||||
bool isScriptable = mm.attributes() & QMetaMethod::Scriptable;
|
||||
for (j = 1; j < types.count(); ++j) {
|
||||
// input parameter for a slot or output for a signal
|
||||
if (types.at(j) == QDBusConnectionPrivate::messageMetaType) {
|
||||
isScriptable = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
QString name;
|
||||
if (!names.at(j - 1).isEmpty())
|
||||
name = QString(QLatin1String("name=\"%1\" ")).arg(QLatin1String(names.at(j - 1)));
|
||||
|
||||
bool isOutput = isSignal || j > inputCount;
|
||||
|
||||
xml += QString(QLatin1String(" <arg %1type=\"%2\" direction=\"%3\"/>\n"))
|
||||
.arg(name)
|
||||
.arg(QLatin1String(QDBusType::dbusSignature( QVariant::Type(types.at(j)) )))
|
||||
.arg(isOutput ? QLatin1String("out") : QLatin1String("in"));
|
||||
}
|
||||
|
||||
if (!isScriptable &&
|
||||
!(flags & (QDBusConnection::ExportNonScriptableSlots | QDBusConnection::ExportNonScriptableSignals)))
|
||||
continue;
|
||||
|
||||
if (qDBusCheckAsyncTag(mm.tag()))
|
||||
// add the no-reply annotation
|
||||
xml += QLatin1String(" <annotation name=\"" ANNOTATION_NO_WAIT "\""
|
||||
" value=\"true\"/>\n");
|
||||
|
||||
retval += xml;
|
||||
retval += QString(QLatin1String(" </%1>\n"))
|
||||
.arg(isSignal ? QLatin1String("signal") : QLatin1String("method"));
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static QString generateMetaObjectXml(QString interface, const QMetaObject *mo, const QMetaObject *base,
|
||||
int flags)
|
||||
{
|
||||
if (interface.isEmpty()) {
|
||||
// generate the interface name from the meta object
|
||||
int idx = mo->indexOfClassInfo(QCLASSINFO_DBUS_INTERFACE);
|
||||
if (idx >= mo->classInfoOffset()) {
|
||||
interface = QLatin1String(mo->classInfo(idx).value());
|
||||
} else {
|
||||
interface = QLatin1String(mo->className());
|
||||
interface.replace(QLatin1String("::"), QLatin1String("."));
|
||||
|
||||
if (interface.startsWith( QLatin1String("QDBus") )) {
|
||||
interface.prepend( QLatin1String("com.trolltech.QtDBus.") );
|
||||
} else if (interface.startsWith( QLatin1Char('Q') )) {
|
||||
// assume it's Qt
|
||||
interface.prepend( QLatin1String("com.trolltech.Qt.") );
|
||||
} else if (!QCoreApplication::instance() ||
|
||||
QCoreApplication::instance()->applicationName().isEmpty()) {
|
||||
interface.prepend( QLatin1String("local.") );
|
||||
} else {
|
||||
interface.prepend(QLatin1Char('.')).prepend( QCoreApplication::instance()->applicationName() );
|
||||
QStringList domainName = QCoreApplication::instance()->organizationDomain().split(QLatin1Char('.'));
|
||||
foreach (const QString &part, domainName)
|
||||
interface.prepend(QLatin1Char('.')).prepend(part);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString xml;
|
||||
int idx = mo->indexOfClassInfo(QCLASSINFO_DBUS_INTROSPECTION);
|
||||
if (idx >= mo->classInfoOffset())
|
||||
xml = QString::fromUtf8(mo->classInfo(idx).value());
|
||||
else
|
||||
xml = generateInterfaceXml(mo, flags, base->methodCount(), base->propertyCount());
|
||||
|
||||
return QString(QLatin1String(" <interface name=\"%1\">\n%2 </interface>"))
|
||||
.arg(interface, xml);
|
||||
}
|
||||
|
||||
static QString generateSubObjectXml(QObject *object)
|
||||
{
|
||||
QString retval;
|
||||
foreach (QObject *child, object->children()) {
|
||||
QString name = child->objectName();
|
||||
if (!name.isEmpty())
|
||||
retval += QString(QLatin1String(" <node name=\"%1\"/>\n"))
|
||||
.arg(name);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void qDBusIntrospectObject(const QDBusConnectionPrivate::ObjectTreeNode *node,
|
||||
const QDBusMessage &msg)
|
||||
{
|
||||
// object may be null
|
||||
|
||||
QString xml_data(QLatin1String(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE));
|
||||
xml_data += QLatin1String("<node>\n");
|
||||
|
||||
if (node->obj) {
|
||||
xml_data += QLatin1String( QDBusIntrospectableInterface::staticIntrospectionData() );
|
||||
xml_data += QLatin1String( QDBusPropertiesInterface::staticIntrospectionData() );
|
||||
|
||||
if (node->flags & QDBusConnection::ExportContents) {
|
||||
const QMetaObject *mo = node->obj->metaObject();
|
||||
for ( ; mo != &QObject::staticMetaObject; mo = mo->superClass())
|
||||
xml_data += generateMetaObjectXml(QString(), mo, &QObject::staticMetaObject,
|
||||
node->flags);
|
||||
}
|
||||
|
||||
// does this object have adaptors?
|
||||
QDBusAdaptorConnector *connector;
|
||||
if (node->flags & QDBusConnection::ExportAdaptors &&
|
||||
(connector = qDBusFindAdaptorConnector(node->obj))) {
|
||||
|
||||
// trasverse every adaptor in this object
|
||||
QDBusAdaptorConnector::AdaptorMap::ConstIterator it = connector->adaptors.constBegin();
|
||||
QDBusAdaptorConnector::AdaptorMap::ConstIterator end = connector->adaptors.constEnd();
|
||||
for ( ; it != end; ++it) {
|
||||
// add the interface:
|
||||
QString ifaceXml = QDBusAbstractAdaptorPrivate::retrieveIntrospectionXml(it->adaptor);
|
||||
if (ifaceXml.isEmpty()) {
|
||||
// add the interface's contents:
|
||||
ifaceXml += generateMetaObjectXml(it->interface, it->metaObject,
|
||||
&QDBusAbstractAdaptor::staticMetaObject,
|
||||
QDBusConnection::ExportNonScriptableContents);
|
||||
|
||||
QDBusAbstractAdaptorPrivate::saveIntrospectionXml(it->adaptor, ifaceXml);
|
||||
}
|
||||
|
||||
xml_data += ifaceXml;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (node->flags & QDBusConnection::ExportChildObjects) {
|
||||
xml_data += generateSubObjectXml(node->obj);
|
||||
} else {
|
||||
// generate from the object tree
|
||||
foreach (const QDBusConnectionPrivate::ObjectTreeNode::Data &entry, node->children) {
|
||||
if (entry.node && (entry.node->obj || !entry.node->children.isEmpty()))
|
||||
xml_data += QString(QLatin1String(" <node name=\"%1\"/>\n"))
|
||||
.arg(entry.name);
|
||||
}
|
||||
}
|
||||
|
||||
xml_data += QLatin1String("</node>\n");
|
||||
|
||||
// now send it
|
||||
QDBusMessage reply = QDBusMessage::methodReply(msg);
|
||||
reply << xml_data;
|
||||
msg.connection().send(reply);
|
||||
}
|
||||
|
||||
// implement the D-Bus interface org.freedesktop.DBus.Properties
|
||||
|
||||
static void sendPropertyError(const QDBusMessage &msg, const QString &interface_name)
|
||||
{
|
||||
QDBusMessage error = QDBusMessage::error(msg, QLatin1String(DBUS_ERROR_INVALID_ARGS),
|
||||
QString::fromLatin1("Interface %1 was not found in object %2")
|
||||
.arg(interface_name)
|
||||
.arg(msg.path()));
|
||||
msg.connection().send(error);
|
||||
}
|
||||
|
||||
void qDBusPropertyGet(const QDBusConnectionPrivate::ObjectTreeNode *node, const QDBusMessage &msg)
|
||||
{
|
||||
Q_ASSERT(msg.count() == 2);
|
||||
QString interface_name = msg.at(0).toString();
|
||||
QByteArray property_name = msg.at(1).toString().toUtf8();
|
||||
|
||||
QDBusAdaptorConnector *connector;
|
||||
QVariant value;
|
||||
if (node->flags & QDBusConnection::ExportAdaptors &&
|
||||
(connector = qDBusFindAdaptorConnector(node->obj))) {
|
||||
|
||||
// find the class that implements interface_name
|
||||
QDBusAdaptorConnector::AdaptorMap::ConstIterator it;
|
||||
it = qLowerBound(connector->adaptors.constBegin(), connector->adaptors.constEnd(),
|
||||
interface_name);
|
||||
if (it != connector->adaptors.end() && it->interface == interface_name)
|
||||
value = it->adaptor->property(property_name);
|
||||
}
|
||||
|
||||
if (!value.isValid() && node->flags & QDBusConnection::ExportProperties) {
|
||||
// try the object itself
|
||||
int pidx = node->obj->metaObject()->indexOfProperty(property_name);
|
||||
if (pidx != -1) {
|
||||
QMetaProperty mp = node->obj->metaObject()->property(pidx);
|
||||
if (mp.isScriptable() || (node->flags & QDBusConnection::ExportNonScriptableProperties) ==
|
||||
QDBusConnection::ExportNonScriptableProperties)
|
||||
value = mp.read(node->obj);
|
||||
}
|
||||
}
|
||||
|
||||
if (!value.isValid()) {
|
||||
// the property was not found
|
||||
sendPropertyError(msg, interface_name);
|
||||
return;
|
||||
}
|
||||
|
||||
QDBusMessage reply = QDBusMessage::methodReply(msg);
|
||||
reply.setSignature(QLatin1String("v"));
|
||||
reply << value;
|
||||
msg.connection().send(reply);
|
||||
}
|
||||
|
||||
void qDBusPropertySet(const QDBusConnectionPrivate::ObjectTreeNode *node, const QDBusMessage &msg)
|
||||
{
|
||||
Q_ASSERT(msg.count() == 3);
|
||||
QString interface_name = msg.at(0).toString();
|
||||
QByteArray property_name = msg.at(1).toString().toUtf8();
|
||||
QVariant value = msg.at(2).value<QDBusVariant>();
|
||||
|
||||
QDBusAdaptorConnector *connector;
|
||||
if (node->flags & QDBusConnection::ExportAdaptors &&
|
||||
(connector = qDBusFindAdaptorConnector(node->obj))) {
|
||||
|
||||
// find the class that implements interface_name
|
||||
QDBusAdaptorConnector::AdaptorMap::ConstIterator it;
|
||||
it = qLowerBound(connector->adaptors.constBegin(), connector->adaptors.constEnd(),
|
||||
interface_name);
|
||||
if (it != connector->adaptors.end() && it->interface == interface_name)
|
||||
if (it->adaptor->setProperty(property_name, value)) {
|
||||
msg.connection().send(QDBusMessage::methodReply(msg));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!value.isValid() && node->flags & QDBusConnection::ExportProperties) {
|
||||
// try the object itself
|
||||
int pidx = node->obj->metaObject()->indexOfProperty(property_name);
|
||||
if (pidx != -1) {
|
||||
QMetaProperty mp = node->obj->metaObject()->property(pidx);
|
||||
if (mp.isScriptable() || (node->flags & QDBusConnection::ExportNonScriptableProperties) ==
|
||||
QDBusConnection::ExportNonScriptableProperties) {
|
||||
|
||||
if (mp.write(node->obj, value)) {
|
||||
msg.connection().send(QDBusMessage::methodReply(msg));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the property was not found or not written to
|
||||
sendPropertyError(msg, interface_name);
|
||||
}
|
||||
|
|
@ -53,6 +53,11 @@
|
|||
The argument name. The argument name is optional, so this may be a null QString.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusIntrospection::Argument::operator==
|
||||
Compares this object against \p other and return true if they are the same.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\struct QDBusIntrospection::Method
|
||||
\brief Information about one method.
|
||||
|
|
@ -83,6 +88,11 @@
|
|||
is of the same format as a D-Bus interface name. The value is arbitrary.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusIntrospection::Method::operator==
|
||||
Compares this object against \p other and return true if they are the same.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\struct QDBusIntrospection::Signal
|
||||
\brief Information about one signal.
|
||||
|
|
@ -91,6 +101,11 @@
|
|||
its \a name, its output arguments, and, optionally, annotations.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\var QDBusIntrospection::Signal::name
|
||||
The signal's name.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\var QDBusIntrospection::Signal::outputArgs
|
||||
A list of the signal's arguments.
|
||||
|
|
@ -102,6 +117,11 @@
|
|||
is of the same format as a D-Bus interface name. The value is arbitrary.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusIntrospection::Signal::operator==
|
||||
Compares this object against \p other and return true if they are the same.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\struct QDBusIntrospection::Property
|
||||
\brief Information about one property.
|
||||
|
|
@ -139,6 +159,11 @@
|
|||
is of the same format as a D-Bus interface name. The value is arbitrary.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusIntrospection::Property::operator==
|
||||
Compares this object against \p other and return true if they are the same.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\struct QDBusIntrospection::Interface
|
||||
\brief Information about one interface on the bus.
|
||||
|
|
@ -185,6 +210,14 @@
|
|||
The properties available in this interface. Property names are unique.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusIntrospection::Interface::operator==
|
||||
Compares this object against \p other and return true if they are the same.
|
||||
|
||||
Note that two interfaces are considered to be the same if they have the same name. The internal
|
||||
structures in the objects are not compared.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\struct QDBusIntrospection::Object
|
||||
\brief Information about one object on the bus.
|
||||
|
|
@ -233,6 +266,7 @@
|
|||
/*!
|
||||
\struct QDBusIntrospection::ObjectTree
|
||||
\brief Complete information about one object node and its descendency.
|
||||
|
||||
This struct contains the same data as QDBusIntrospection::Object, plus the actual data for the
|
||||
interfaces and child (sub) objects that was available in the XML document.
|
||||
*/
|
||||
|
|
@ -296,8 +330,8 @@
|
|||
/*!
|
||||
Parses the XML document fragment containing one interface.
|
||||
|
||||
The first element tag in this XML data must be either <node> or <interface>. If it is
|
||||
<node>, then the <interface> tag must be a child tag of the <node> one.
|
||||
The first element tag in this XML data must be either \<node\> or \<interface\>. If it is
|
||||
\<node\>, then the \<interface\> tag must be a child tag of the \<node\> one.
|
||||
|
||||
If there are multiple interfaces in this XML data, it is undefined which one will be
|
||||
returned.
|
||||
|
|
@ -320,8 +354,8 @@ QDBusIntrospection::parseInterface(const QString &xml)
|
|||
/*!
|
||||
Parses the XML document fragment containing several interfaces.
|
||||
|
||||
If the first element tag in this document fragment is <node>, the interfaces parsed will
|
||||
be those found as child elements of the <node> tag.
|
||||
If the first element tag in this document fragment is \<node\>, the interfaces parsed will
|
||||
be those found as child elements of the \<node\> tag.
|
||||
|
||||
\param xml the XML data to be parsed
|
||||
\returns the parsed interfaces
|
||||
|
|
@ -336,7 +370,7 @@ QDBusIntrospection::parseInterfaces(const QString &xml)
|
|||
/*!
|
||||
Parses the XML document fragment containing one object.
|
||||
|
||||
The first element tag in this document must be <node>. If that tag does not contain
|
||||
The first element tag in this document must be \<node\>. If that tag does not contain
|
||||
a name attribute, the \a path argument will be used to determine the path of this
|
||||
object node.
|
||||
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ public:
|
|||
Properties properties;
|
||||
|
||||
inline bool operator==(const Interface &other) const
|
||||
{ return name == other.name; }
|
||||
{ return !name.isEmpty() && name == other.name; }
|
||||
};
|
||||
|
||||
struct Object: public QSharedData
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
/* qdbusmessage.h QDBusMessage object
|
||||
*
|
||||
* Copyright (C) 2005 Harald Fernengel <harry@kdevelop.org>
|
||||
* Copyright (C) 2006 Trolltech AS. All rights reserved.
|
||||
* Author: Thiago Macieira <thiago.macieira@trolltech.com>
|
||||
*
|
||||
* Licensed under the Academic Free License version 2.1
|
||||
*
|
||||
|
|
@ -15,22 +17,60 @@
|
|||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* along with this program; if not, write to the Free Software Foundation
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
/*!
|
||||
\file qdbusmacros.h
|
||||
*/
|
||||
|
||||
#ifndef QDBUSMACROS_H
|
||||
#define QDBUSMACROS_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#ifndef QDBUS_EXPORT
|
||||
#ifdef QDBUS_MAKEDLL
|
||||
#ifdef DBUS_COMPILATION
|
||||
/// \internal
|
||||
# define QDBUS_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
/// \internal
|
||||
# define QDBUS_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
|
||||
#ifndef Q_MOC_RUN
|
||||
/*!
|
||||
\relates QDBusAbstractAdaptor
|
||||
\brief Marks a method as "asynchronous"
|
||||
|
||||
The Q_ASYNC macro can be used to mark a method to be called and not wait for it to finish
|
||||
processing before returning from QDBusInterface::call. The called method cannot return any
|
||||
output arguments and, if it does, any such arguments will be discarded.
|
||||
|
||||
You can use this macro in your own adaptors by placing it before your method's return value
|
||||
(which must be "void") in the class declaration, as shown in the example:
|
||||
\code
|
||||
Q_ASYNC void myMethod();
|
||||
\endcode
|
||||
|
||||
Its presence in the method implementation (outside the class declaration) is optional.
|
||||
|
||||
\sa #async, \ref UsingAdaptors
|
||||
*/
|
||||
# define Q_ASYNC
|
||||
#endif
|
||||
#ifndef QT_NO_KEYWORDS
|
||||
|
||||
/*!
|
||||
\relates QDBusAbstractAdaptor
|
||||
\brief Marks a method as "asynchronous"
|
||||
|
||||
This macro is the same as #Q_ASYNC and is provided as a shorthand. However, it is not defined if
|
||||
QT_NO_KEYWORDS is defined, which makes Qt not use its extensions to the C++ language (keywords
|
||||
emit, signals, slots).
|
||||
*/
|
||||
# define async Q_ASYNC
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "qdbusmarshall.h"
|
||||
#include "qdbusmarshall_p.h"
|
||||
#include "qdbustype.h"
|
||||
#include "qdbusvariant.h"
|
||||
|
||||
|
|
@ -349,8 +349,10 @@ static void qAppendVariantToMessage(DBusMessageIter *it, const QDBusType & /* ty
|
|||
}
|
||||
else {
|
||||
v = var;
|
||||
t = QDBusType::guessFromVariant(v);
|
||||
}
|
||||
|
||||
if (!t.isValid())
|
||||
t = QDBusType::guessFromVariant(v);
|
||||
|
||||
// now add this variant
|
||||
DBusMessageIter sub;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* qdbusmarshall.h QDBusMarshall object
|
||||
/* qdbusmarshall_p.h QDBusMarshall object
|
||||
*
|
||||
* Copyright (C) 2005 Harald Fernengel <harry@kdevelop.org>
|
||||
* Copyright (C) 2006 Trolltech AS. All rights reserved.
|
||||
|
|
@ -22,8 +22,20 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#ifndef QDBUSMARSHALL_H
|
||||
#define QDBUSMARSHALL_H
|
||||
//
|
||||
// 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 QDBUSMARSHALLPRIVATE_H
|
||||
#define QDBUSMARSHALLPRIVATE_H
|
||||
|
||||
struct DBusMessage;
|
||||
|
||||
|
|
@ -31,6 +43,9 @@ template <typename T> class QList;
|
|||
class QVariant;
|
||||
class QString;
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
class QDBusMarshall
|
||||
{
|
||||
public:
|
||||
|
|
@ -29,13 +29,13 @@
|
|||
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
#include "qdbusmarshall.h"
|
||||
#include "qdbuserror.h"
|
||||
#include "qdbusmarshall_p.h"
|
||||
#include "qdbusmessage_p.h"
|
||||
|
||||
QDBusMessagePrivate::QDBusMessagePrivate(QDBusMessage *qq)
|
||||
: msg(0), reply(0), q(qq), type(DBUS_MESSAGE_TYPE_INVALID), timeout(-1), ref(1),
|
||||
repliedTo(false)
|
||||
: connection(QString()), msg(0), reply(0), q(qq), type(DBUS_MESSAGE_TYPE_INVALID),
|
||||
timeout(-1), ref(1), repliedTo(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -63,6 +63,17 @@ QDBusMessagePrivate::~QDBusMessagePrivate()
|
|||
methodReply and error.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum QDBusMessage::MessageType
|
||||
The possible message types:
|
||||
|
||||
\value MethodCallMessage a message representing an outgoing or incoming method call
|
||||
\value SignalMessage a message representing an outgoing or incoming signal emission
|
||||
\value ReplyMessage a message representing the return values of a method call
|
||||
\value ErrorMessage a message representing an error condition in response to a method call
|
||||
\value InvalidMessage an invalid message: this is never set on messages received from D-Bus
|
||||
*/
|
||||
|
||||
/*!
|
||||
Constructs a new DBus message representing a signal emission. A DBus signal is emitted
|
||||
from one application and is received by all applications that are listening for that signal
|
||||
|
|
@ -111,14 +122,11 @@ QDBusMessage QDBusMessage::signal(const QString &path, const QString &interface,
|
|||
\param path the path of the object on the remote service to be called
|
||||
\param interface the remote interface that is wanted (can be null)
|
||||
\param method the remote method to be called (a.k.a., name)
|
||||
\param sig the DBus signature (set to null to discard processing and guess the
|
||||
method signature from the arguments; empty means no arguments)
|
||||
\returns a QDBusMessage object that can be sent with QDBusConnection::send,
|
||||
QDBusConnection::sendWithReply, or QDBusConnection::sendWithReplyAsync
|
||||
*/
|
||||
QDBusMessage QDBusMessage::methodCall(const QString &service, const QString &path,
|
||||
const QString &interface, const QString &method,
|
||||
const QString &sig)
|
||||
const QString &interface, const QString &method)
|
||||
{
|
||||
QDBusMessage message;
|
||||
message.d->type = DBUS_MESSAGE_TYPE_METHOD_CALL;
|
||||
|
|
@ -126,7 +134,6 @@ QDBusMessage QDBusMessage::methodCall(const QString &service, const QString &pat
|
|||
message.d->path = path;
|
||||
message.d->interface = interface;
|
||||
message.d->name = method;
|
||||
message.d->signature = sig;
|
||||
|
||||
return message;
|
||||
}
|
||||
|
|
@ -142,6 +149,7 @@ QDBusMessage QDBusMessage::methodReply(const QDBusMessage &other)
|
|||
Q_ASSERT(other.d->msg);
|
||||
|
||||
QDBusMessage message;
|
||||
message.d->connection = other.d->connection;
|
||||
message.d->type = DBUS_MESSAGE_TYPE_METHOD_RETURN;
|
||||
message.d->reply = dbus_message_ref(other.d->msg);
|
||||
other.d->repliedTo = true;
|
||||
|
|
@ -164,6 +172,7 @@ QDBusMessage QDBusMessage::error(const QDBusMessage &other, const QString &name,
|
|||
Q_ASSERT(other.d->msg);
|
||||
|
||||
QDBusMessage message;
|
||||
message.d->connection = other.d->connection;
|
||||
message.d->type = DBUS_MESSAGE_TYPE_ERROR;
|
||||
message.d->name = name;
|
||||
message.d->message = msg;
|
||||
|
|
@ -186,6 +195,7 @@ QDBusMessage QDBusMessage::error(const QDBusMessage &other, const QDBusError &er
|
|||
Q_ASSERT(other.d->msg);
|
||||
|
||||
QDBusMessage message;
|
||||
message.d->connection = other.d->connection;
|
||||
message.d->type = DBUS_MESSAGE_TYPE_ERROR;
|
||||
message.d->name = error.name();
|
||||
message.d->message = error.message();
|
||||
|
|
@ -234,6 +244,11 @@ QDBusMessage &QDBusMessage::operator=(const QDBusMessage &other)
|
|||
return *this;
|
||||
}
|
||||
|
||||
static inline const char *data(const QByteArray &arr)
|
||||
{
|
||||
return arr.isEmpty() ? 0 : arr.constData();
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Constructs a DBusMessage object from this object. The returned value must be de-referenced
|
||||
|
|
@ -245,20 +260,18 @@ DBusMessage *QDBusMessage::toDBusMessage() const
|
|||
|
||||
switch (d->type) {
|
||||
case DBUS_MESSAGE_TYPE_METHOD_CALL:
|
||||
msg = dbus_message_new_method_call(d->service.toUtf8().constData(),
|
||||
d->path.toUtf8().constData(), d->interface.toUtf8().constData(),
|
||||
d->name.toUtf8().constData());
|
||||
msg = dbus_message_new_method_call(data(d->service.toUtf8()), data(d->path.toUtf8()),
|
||||
data(d->interface.toUtf8()), data(d->name.toUtf8()));
|
||||
break;
|
||||
case DBUS_MESSAGE_TYPE_SIGNAL:
|
||||
msg = dbus_message_new_signal(d->path.toUtf8().constData(),
|
||||
d->interface.toUtf8().constData(), d->name.toUtf8().constData());
|
||||
msg = dbus_message_new_signal(data(d->path.toUtf8()), data(d->interface.toUtf8()),
|
||||
data(d->name.toUtf8()));
|
||||
break;
|
||||
case DBUS_MESSAGE_TYPE_METHOD_RETURN:
|
||||
msg = dbus_message_new_method_return(d->reply);
|
||||
break;
|
||||
case DBUS_MESSAGE_TYPE_ERROR:
|
||||
msg = dbus_message_new_error(d->reply, d->name.toUtf8().constData(),
|
||||
d->message.toUtf8().constData());
|
||||
msg = dbus_message_new_error(d->reply, data(d->name.toUtf8()), data(d->message.toUtf8()));
|
||||
break;
|
||||
}
|
||||
if (!msg)
|
||||
|
|
@ -272,12 +285,13 @@ DBusMessage *QDBusMessage::toDBusMessage() const
|
|||
\internal
|
||||
Constructs a QDBusMessage by parsing the given DBusMessage object.
|
||||
*/
|
||||
QDBusMessage QDBusMessage::fromDBusMessage(DBusMessage *dmsg)
|
||||
QDBusMessage QDBusMessage::fromDBusMessage(DBusMessage *dmsg, const QDBusConnection &connection)
|
||||
{
|
||||
QDBusMessage message;
|
||||
if (!dmsg)
|
||||
return message;
|
||||
|
||||
message.d->connection = connection;
|
||||
message.d->type = dbus_message_get_type(dmsg);
|
||||
message.d->path = QString::fromUtf8(dbus_message_get_path(dmsg));
|
||||
message.d->interface = QString::fromUtf8(dbus_message_get_interface(dmsg));
|
||||
|
|
@ -333,12 +347,12 @@ QString QDBusMessage::name() const
|
|||
}
|
||||
|
||||
/*!
|
||||
\fn QDBusMessage::member
|
||||
\fn QDBusMessage::member() const
|
||||
Returns the name of the method being called.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusMessage::method
|
||||
\fn QDBusMessage::method() const
|
||||
\overload
|
||||
Returns the name of the method being called.
|
||||
*/
|
||||
|
|
@ -352,7 +366,7 @@ QString QDBusMessage::service() const
|
|||
}
|
||||
|
||||
/*!
|
||||
\fn QDBusMessage::sender
|
||||
\fn QDBusMessage::sender() const
|
||||
Returns the unique name of the remote sender.
|
||||
*/
|
||||
|
||||
|
|
@ -386,18 +400,6 @@ bool QDBusMessage::noReply() const
|
|||
return dbus_message_get_no_reply(d->msg);
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the flag that indicates whether we're expecting a reply from the callee. This flag only
|
||||
makes sense for MethodCall messages.
|
||||
|
||||
\param enable whether to enable the flag (i.e., we are not expecting a reply)
|
||||
*/
|
||||
void QDBusMessage::setNoReply(bool enable)
|
||||
{
|
||||
if (d->msg)
|
||||
dbus_message_set_no_reply(d->msg, enable);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the unique serial number assigned to this message
|
||||
or 0 if the message was not sent yet.
|
||||
|
|
@ -442,6 +444,24 @@ QString QDBusMessage::signature() const
|
|||
return d->signature;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the signature for the output arguments of this method call. This function has no meaning
|
||||
in other types of messages or when dealing with received method calls.
|
||||
*/
|
||||
void QDBusMessage::setSignature(const QString &signature)
|
||||
{
|
||||
d->signature = signature;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the connection this message was received on or an unconnected QDBusConnection object if
|
||||
this isn't a message that has been received.
|
||||
*/
|
||||
QDBusConnection QDBusMessage::connection() const
|
||||
{
|
||||
return d->connection;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the message type.
|
||||
*/
|
||||
|
|
@ -461,6 +481,144 @@ QDBusMessage::MessageType QDBusMessage::type() const
|
|||
}
|
||||
}
|
||||
|
||||
// Document QDBusReply here
|
||||
/*!
|
||||
\class QDBusReply
|
||||
\brief The reply for a method call to a remote object.
|
||||
|
||||
A QDBusReply object is a subset of the QDBusMessage object that represents a method call's
|
||||
reply. It contains only the first output argument or the error code and is used by
|
||||
QDBusInterface-derived classes to allow returning the error code as the function's return
|
||||
argument.
|
||||
|
||||
It can be used in the following manner:
|
||||
\code
|
||||
QDBusReply<QString> reply = interface.call("RemoteMethod");
|
||||
if (reply.isSuccess())
|
||||
// use the returned value
|
||||
useValue(reply.value());
|
||||
else
|
||||
// call failed. Show an error condition.
|
||||
showError(reply.error());
|
||||
\endcode
|
||||
|
||||
If the remote method call cannot fail, you can skip the error checking:
|
||||
\code
|
||||
QString reply = interface.call("RemoteMethod");
|
||||
\endcode
|
||||
|
||||
However, if it does fail under those conditions, the value returned by QDBusReply::value() is
|
||||
undefined. It may be undistinguishable from a valid return value.
|
||||
|
||||
QDBusReply objects are used for remote calls that have no output arguments or return values
|
||||
(i.e., they have a "void" return type). In this case, you can only test if the reply succeeded
|
||||
or not, by calling isError() and isSuccess(), and inspecting the error condition by calling
|
||||
error(). You cannot call value().
|
||||
|
||||
\sa QDBusMessage, QDBusInterface, \ref StandardInterfaces
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusReply::QDBusReply(const QDBusMessage &reply)
|
||||
Automatically construct a QDBusReply object from the reply message \p reply, extracting the
|
||||
first return value from it if it is a success reply.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusReply::QDBusReply(const QDBusError &error)
|
||||
Construct an error reply from the D-Bus error.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusReply::isError() const
|
||||
Returns true if this reply is an error reply. You can extract the error contents using the
|
||||
error() function.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusReply::isSuccess() const
|
||||
Returns true if this reply is a normal error reply (not an error). You can extract the returned
|
||||
value with value()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusReply::error()
|
||||
Returns the error code that was returned from the remote function call. If the remote call did
|
||||
not return an error (i.e., if it succeeded), then the QDBusError object that is returned will
|
||||
not be a valid error code (QDBusError::isValid() will return false).
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusReply::value()
|
||||
Returns the remote function's calls return value. If the remote call returned with an error,
|
||||
the return value of this function is undefined and may be undistinguishable from a valid return
|
||||
value.
|
||||
|
||||
This function is not available if the remote call returns "void".
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusReply::operator Type()
|
||||
Returns the same as value().
|
||||
|
||||
This function is not available if the remote call returns "void".
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusReply::fromVariant(const QDBusReply<QDBusVariant> &variantReply)>
|
||||
Converts the QDBusReply<QDBusVariant> object to this type by converting the variant contained in
|
||||
\p variantReply to the template's type and copying the error condition.
|
||||
|
||||
If the QDBusVariant in variantReply is not convertible to this type, it will assume an undefined
|
||||
value.
|
||||
*/
|
||||
|
||||
// document QDBusVariant here too
|
||||
/*!
|
||||
\class QDBusVariant
|
||||
\brief Represents the D-Bus type VARIANT.
|
||||
|
||||
This class represents a D-Bus argument of type VARIANT, which is composed of a type description
|
||||
and its value.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\var QDBusVariant::type
|
||||
Contains the VARIANT's type. It will contain an invalid type if this QDBusVariant argument was
|
||||
constructed, as opposed to being received over the D-Bus connection.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\var QDBusVariant::value
|
||||
Contain's the VARIANT's value.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusVariant::QDBusVariant()
|
||||
Constructs an empty variant. An empty variant cannot be sent over D-Bus without being
|
||||
initialized first.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusVariant::QDBusVariant(const QVariant &variant)
|
||||
Constructs a D-Bus Variant from the QVariant value \p variant. The D-Bus type, if not set, will
|
||||
be guessed from the QVariant value when actually sending the argument over D-Bus by calling
|
||||
QDBusType::guessFromVariant. You should explicitly set the type if are unsure the automatic
|
||||
guessing will produce the correct type.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusVariant::QDBusVariant(const QVariant &variant, const QDBusType &forcetype)
|
||||
Constructs a D-Bus Variant from the QVariant of value \p variant and sets the type to \p
|
||||
forcetype. The actual transformation of the QVariant to the proper D-Bus type will happen only
|
||||
when sending this argument over D-Bus.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusVariant::operator const QVariant &() const
|
||||
Returns the value #value.
|
||||
*/
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, QDBusMessage::MessageType t)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
class QDBusMessagePrivate;
|
||||
class QDBusError;
|
||||
class QDBusConnection;
|
||||
struct DBusMessage;
|
||||
|
||||
class QDBUS_EXPORT QDBusMessage: public QList<QVariant>
|
||||
|
|
@ -52,8 +53,7 @@ public:
|
|||
static QDBusMessage signal(const QString &path, const QString &interface,
|
||||
const QString &name);
|
||||
static QDBusMessage methodCall(const QString &destination, const QString &path,
|
||||
const QString &interface, const QString &method,
|
||||
const QString &signature = QString());
|
||||
const QString &interface, const QString &method);
|
||||
static QDBusMessage methodReply(const QDBusMessage &other);
|
||||
static QDBusMessage error(const QDBusMessage &other, const QString &name,
|
||||
const QString &message = QString());
|
||||
|
|
@ -72,13 +72,15 @@ public:
|
|||
void setTimeout(int ms);
|
||||
|
||||
bool noReply() const;
|
||||
void setNoReply(bool enable);
|
||||
|
||||
QString signature() const;
|
||||
void setSignature(const QString &signature);
|
||||
|
||||
QDBusConnection connection() const;
|
||||
|
||||
//protected:
|
||||
DBusMessage *toDBusMessage() const;
|
||||
static QDBusMessage fromDBusMessage(DBusMessage *dmsg);
|
||||
static QDBusMessage fromDBusMessage(DBusMessage *dmsg, const QDBusConnection &connection);
|
||||
static QDBusMessage fromError(const QDBusError& error);
|
||||
int serialNumber() const;
|
||||
int replySerialNumber() const;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <qatomic.h>
|
||||
#include <qstring.h>
|
||||
#include "qdbusconnection.h"
|
||||
struct DBusMessage;
|
||||
|
||||
class QDBusMessagePrivate
|
||||
|
|
@ -36,6 +37,7 @@ public:
|
|||
~QDBusMessagePrivate();
|
||||
|
||||
QString service, path, interface, name, message, signature;
|
||||
QDBusConnection connection;
|
||||
DBusMessage *msg;
|
||||
DBusMessage *reply;
|
||||
QDBusMessage *q;
|
||||
|
|
|
|||
|
|
@ -33,32 +33,50 @@
|
|||
#include "qdbusobject_p.h"
|
||||
#include "qdbusutil.h"
|
||||
|
||||
/*!
|
||||
\class QDBusObject
|
||||
\brief Base object for referencing remote D-Bus Objects
|
||||
|
||||
This class provides the basic functionality for referencing remote objects. It does not,
|
||||
however, allow you to place calls to the remote object: you have to use the QDBusInterface class
|
||||
for that.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
QDBusObject::QDBusObject(QDBusObjectPrivate* p, const QDBusConnection& conn)
|
||||
:d(p), m_conn(conn)
|
||||
{
|
||||
}
|
||||
|
||||
QDBusObject::QDBusObject(const QDBusConnection& conn, const QString& service, const QString& path)
|
||||
: m_conn(conn)
|
||||
{
|
||||
*this = m_conn.findObject(service, path);
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a QDBusObject that references the same object that the QDBusInterface class does.
|
||||
*/
|
||||
QDBusObject::QDBusObject(const QDBusInterface& iface)
|
||||
: m_conn(iface.connection())
|
||||
{
|
||||
*this = m_conn.findObject(iface.service(), iface.path());
|
||||
}
|
||||
|
||||
/*!
|
||||
Copy constructor: creates a copy of the \p other object.
|
||||
*/
|
||||
QDBusObject::QDBusObject(const QDBusObject& other)
|
||||
: d(other.d), m_conn(other.m_conn)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Destroys this object and frees any resource it held.
|
||||
*/
|
||||
QDBusObject::~QDBusObject()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Assignment operator: copy the contents of the \p other QDBusObject.
|
||||
*/
|
||||
QDBusObject& QDBusObject::operator=(const QDBusObject& other)
|
||||
{
|
||||
#if 0
|
||||
|
|
@ -74,21 +92,38 @@ QDBusObject& QDBusObject::operator=(const QDBusObject& other)
|
|||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the connection this object is bound to.
|
||||
*/
|
||||
QDBusConnection QDBusObject::connection() const
|
||||
{
|
||||
return m_conn;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the service this object is associated to.
|
||||
\sa connection
|
||||
*/
|
||||
QString QDBusObject::service() const
|
||||
{
|
||||
return d ? d->data->service : QString();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the path on the remote service this object is on.
|
||||
\sa connection, service
|
||||
*/
|
||||
QString QDBusObject::path() const
|
||||
{
|
||||
return d ? d->data->path : QString();
|
||||
}
|
||||
|
||||
/*!
|
||||
Places an Introspect call to the remote object and return the XML data that describes its
|
||||
contents. This is the raw XML data of the structures introspectionData() returns.
|
||||
|
||||
\bug We should not cache here. The remote object can change.
|
||||
*/
|
||||
QString QDBusObject::introspect() const
|
||||
{
|
||||
if (!d)
|
||||
|
|
@ -97,17 +132,22 @@ QString QDBusObject::introspect() const
|
|||
|
||||
if (d->data->introspection.isNull()) {
|
||||
// Try to introspect
|
||||
QDBusIntrospectableInterface iface = *this;
|
||||
QString xml = iface.introspect();
|
||||
QDBusIntrospectableInterface iface(*this);
|
||||
QDBusReply<QString> reply = iface.introspect();
|
||||
|
||||
if (!m_conn.lastError().isValid()) {
|
||||
if (reply.isSuccess()) {
|
||||
// this will change the contents of d->data
|
||||
QDBusXmlParser::parse(d, xml);
|
||||
QDBusXmlParser::parse(d, reply);
|
||||
}
|
||||
}
|
||||
return d->data->introspection;
|
||||
}
|
||||
|
||||
/*!
|
||||
Places an Introspect call to the remote object and return the parsed structures representing the
|
||||
object's interfaces and child objects. The raw XML data corresponding to this function's
|
||||
structures can be obtained using introspect().
|
||||
*/
|
||||
QSharedDataPointer<QDBusIntrospection::Object> QDBusObject::introspectionData() const
|
||||
{
|
||||
QSharedDataPointer<QDBusIntrospection::Object> retval;
|
||||
|
|
@ -116,12 +156,23 @@ QSharedDataPointer<QDBusIntrospection::Object> QDBusObject::introspectionData()
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a list of all the interfaces in this object. This is the same value as the found in the
|
||||
\ref QDBusIntrospection::Object::interfaces "interfaces" member of the value returned by
|
||||
introspectionData().
|
||||
*/
|
||||
QStringList QDBusObject::interfaces() const
|
||||
{
|
||||
introspect();
|
||||
return d ? d->data->interfaces : QStringList();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a map of all the children object in this object along with pre-created QDBusObjects for
|
||||
referencing them.
|
||||
|
||||
\todo Write this function!
|
||||
*/
|
||||
QMap<QString, QDBusObject> QDBusObject::children() const
|
||||
{
|
||||
QMap<QString, QDBusObject> retval;
|
||||
|
|
@ -141,6 +192,10 @@ QMap<QString, QDBusObject> QDBusObject::children() const
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if we're referencing a valid object service and path. This does not mean the object
|
||||
actually exists in the remote application or that the remote application exists.
|
||||
*/
|
||||
bool QDBusObject::isValid() const
|
||||
{
|
||||
return d && m_conn.isConnected() && QDBusUtil::isValidBusName(d->data->service) &&
|
||||
|
|
@ -148,6 +203,9 @@ bool QDBusObject::isValid() const
|
|||
}
|
||||
|
||||
#if 0 // we don't have a way of determining if an object exists or not
|
||||
/*!
|
||||
Returns true if the object being referenced exists.
|
||||
*/
|
||||
bool QDBusObject::exists() const
|
||||
{
|
||||
if (!isValid())
|
||||
|
|
@ -167,7 +225,24 @@ bool QDBusObject::exists() const
|
|||
}
|
||||
|
||||
if (err.name == DBUS_ERROR_SERVICE_UNKNOWN ||
|
||||
err.name == DBUS_ERROR_BAD_ADDRESS
|
||||
err.name == DBUS_ERROR_BAD_ADDRESS)
|
||||
return !m_conn.lastError().isValid();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\fn QDBusObject::operator Interface()
|
||||
Cast this object to an interface, if possible.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusObject::operator const Interface()
|
||||
Cast this object to an interface, if possible.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn qdbus_cast
|
||||
\relates QDBusObject
|
||||
|
||||
Casts a QDBusObject to the QDBusInterface-derived class of type Interface.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -43,102 +43,43 @@ template<class Interface>
|
|||
inline const Interface qdbus_cast(const QDBusObject& obj, Interface * = 0);
|
||||
|
||||
class QDBusObjectPrivate;
|
||||
/**
|
||||
* QDBusObject
|
||||
* Base object for DBUS objects imported and exported.
|
||||
*/
|
||||
class QDBUS_EXPORT QDBusObject
|
||||
{
|
||||
friend class QDBusConnection;
|
||||
public:
|
||||
// public constructors
|
||||
/**
|
||||
* Construct a QDBusObject referencing the remote object given.
|
||||
*/
|
||||
QDBusObject(const QDBusConnection& conn, const QString& service, const QString& path);
|
||||
|
||||
/**
|
||||
* Copy constructor.
|
||||
*/
|
||||
QDBusObject(const QDBusObject& other);
|
||||
|
||||
/**
|
||||
* Construct from an interface.
|
||||
*/
|
||||
QDBusObject(const QDBusInterface& iface);
|
||||
|
||||
// public destructors
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
~QDBusObject();
|
||||
|
||||
public:
|
||||
// public functions
|
||||
|
||||
/**
|
||||
* Assignment operator
|
||||
*/
|
||||
QDBusObject& operator=(const QDBusObject&);
|
||||
|
||||
/**
|
||||
* Returns the connection this object is bound to.
|
||||
*/
|
||||
QDBusConnection connection() const;
|
||||
|
||||
/**
|
||||
* Returns the service this object is associated to.
|
||||
*/
|
||||
QString service() const;
|
||||
|
||||
/**
|
||||
* Returns the path on the service this object is on.
|
||||
*/
|
||||
QString path() const;
|
||||
|
||||
/**
|
||||
* Returns the introspection XML data of this object node.
|
||||
*/
|
||||
QString introspect() const;
|
||||
|
||||
/**
|
||||
* Returns the introspection data for this object node.
|
||||
*/
|
||||
QSharedDataPointer<QDBusIntrospection::Object> introspectionData() const;
|
||||
|
||||
/**
|
||||
* Returns all the interfaces in this object.
|
||||
*/
|
||||
QStringList interfaces() const;
|
||||
|
||||
/**
|
||||
* Returns all the children object in this object.
|
||||
*/
|
||||
QMap<QString, QDBusObject> children() const;
|
||||
|
||||
/**
|
||||
* Returns true if the object being referenced exists.
|
||||
*/
|
||||
//bool exists() const;
|
||||
|
||||
/**
|
||||
* Returns true if we're referencing a valid object.
|
||||
*/
|
||||
bool isValid() const;
|
||||
|
||||
/**
|
||||
* Cast this object to an interface, if possible.
|
||||
*/
|
||||
#ifndef QT_NO_MEMBER_TEMPLATES
|
||||
template<typename Interface>
|
||||
inline operator Interface()
|
||||
{ return qdbus_cast<Interface>(*this); }
|
||||
|
||||
/**
|
||||
* Cast this object to an interface, if possible.
|
||||
*/
|
||||
template<typename Interface>
|
||||
inline operator const Interface() const
|
||||
{ return qdbus_cast<Interface>(*this); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
QDBusObject(QDBusObjectPrivate*, const QDBusConnection& conn);
|
||||
|
|
|
|||
110
qt/qdbusreply.h
Normal file
110
qt/qdbusreply.h
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
/* qdbusreply.h QDBusReply object - a reply from D-Bus
|
||||
*
|
||||
* Copyright (C) 2006 Trolltech AS. All rights reserved.
|
||||
* Author: Thiago Macieira <thiago.macieira@trolltech.com>
|
||||
*
|
||||
* Licensed under the Academic Free License version 2.1
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QDBUSREPLY_H
|
||||
#define QDBUSREPLY_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
#include <QtCore/qvariant.h>
|
||||
|
||||
#include "qdbusmacros.h"
|
||||
#include "qdbusmessage.h"
|
||||
#include "qdbuserror.h"
|
||||
#include "qdbusvariant.h"
|
||||
|
||||
template<typename T>
|
||||
class QDBUS_EXPORT QDBusReply
|
||||
{
|
||||
typedef T Type;
|
||||
public:
|
||||
|
||||
inline QDBusReply(const QDBusMessage &reply)
|
||||
: m_error(reply)
|
||||
{
|
||||
if (isSuccess())
|
||||
m_data = qvariant_cast<Type>(reply.at(0));
|
||||
}
|
||||
inline QDBusReply(const QDBusError &error)
|
||||
: m_error(error)
|
||||
{
|
||||
}
|
||||
|
||||
inline bool isError() const { return m_error.isValid(); }
|
||||
inline bool isSuccess() const { return !m_error.isValid(); }
|
||||
|
||||
inline const QDBusError& error() { return m_error; }
|
||||
|
||||
inline Type value()
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
inline operator Type ()
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
static QDBusReply<T> fromVariant(const QDBusReply<QDBusVariant> &variantReply)
|
||||
{
|
||||
QDBusReply<T> retval;
|
||||
retval.m_error = variantReply.m_error;
|
||||
if (retval.isSuccess()) {
|
||||
retval.m_data = qvariant_cast<Type>(variantReply.value);
|
||||
if (!qVariantCanConvert<Type>(variantReply.value))
|
||||
retval.m_error = QDBusError(QLatin1String(DBUS_ERROR_INVALID_SIGNATURE),
|
||||
QLatin1String("Unexpected reply signature"));
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
private:
|
||||
QDBusError m_error;
|
||||
Type m_data;
|
||||
};
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
// specialize for void:
|
||||
template<>
|
||||
class QDBUS_EXPORT QDBusReply<void>
|
||||
{
|
||||
public:
|
||||
inline QDBusReply(const QDBusMessage &reply)
|
||||
: m_error(reply)
|
||||
{
|
||||
}
|
||||
inline QDBusReply(const QDBusError &error)
|
||||
: m_error(error)
|
||||
{
|
||||
}
|
||||
|
||||
inline bool isError() const { return m_error.isValid(); }
|
||||
inline bool isSuccess() const { return !m_error.isValid(); }
|
||||
|
||||
inline const QDBusError& error() { return m_error; }
|
||||
|
||||
private:
|
||||
QDBusError m_error;
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -24,18 +24,205 @@
|
|||
|
||||
#include "qdbusstandardinterfaces.h"
|
||||
|
||||
/*!
|
||||
\page StandardInterfaces Standard D-Bus Interfaces
|
||||
|
||||
The standard, well-known interfaces provided by D-Bus are as follows:
|
||||
\value org.freedesktop.DBus.Peer Peer detection
|
||||
\value org.freedesktop.DBus.Introspectable Introspection of remote object's contents
|
||||
\value org.freedesktop.DBus.Properties Access to remote object's properties
|
||||
|
||||
The QtDBus implementation provides easy access to those three interfaces with the
|
||||
QDBusPeerInterface, QDBusIntrospectableInterface and QDBusPropertiesInterface classes. As a
|
||||
convenience form, they can also be accessed by the classes org::freedesktop::DBus::Peer,
|
||||
org::freedesktop::DBus::Introspectable and org::freedesktop::DBus::Properties.
|
||||
|
||||
Those three classes also illustrate code-generation by the \ref dbusidl2cpp tool: the methods
|
||||
defined in those three interfaces are provided as member functions in the QtDBus classes, which
|
||||
are capable of type-checking the parameters at compile-time, in order to guarantee that they
|
||||
conform to the types expected by the remote objects.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\typedef org::freedesktop::DBus::Peer
|
||||
*/
|
||||
|
||||
/*!
|
||||
\typedef org::freedesktop::DBus::Introspectable
|
||||
*/
|
||||
|
||||
/*!
|
||||
\typedef org::freedesktop::DBus::Properties
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QDBusPeerInterface
|
||||
\brief Provides access to the \a org.freedesktop.DBus.Peer interface.
|
||||
|
||||
This interface has only one method: ping(). Calling this method will generate a success reply if
|
||||
the target service exists or a failure if it doesn't. The target object path is irrelevant in
|
||||
this case.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusPeerInterface::staticInterfaceName
|
||||
Returns the interface name: "org.freedesktop.DBus.Peer"
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusPeerInterface::staticIntrospectionData
|
||||
Returns the XML fragment corresponding to this interface's definition.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusPeerInterface::QDBusPeerInterface(const QDBusObject &)
|
||||
Creates a QDBusPeerInterface object accessing interface the \a org.freedesktop.DBus.Peer
|
||||
interface on object \p obj.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusPeerInterface::introspectionData() const
|
||||
Returns the XML fragment corresponding to this interface's definition.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusPeerInterface::ping
|
||||
Emits an \a org.freedesktop.DBus.Peer.Ping call to the remote object.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Destroys this object.
|
||||
*/
|
||||
QDBusPeerInterface::~QDBusPeerInterface()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\class QDBusIntrospectableInterface
|
||||
\brief Provides access to the \a org.freedesktop.DBus.Introspectable interface.
|
||||
|
||||
The \a Introspectable interface is used to obtain information about the remote object's
|
||||
internals. Its one method, \a introspect(), returns a XML document describing the interfaces and
|
||||
child objects of a remote object in the D-Bus bus.
|
||||
|
||||
The QtDBus implementation automatically introspects remote objects in order to construct the
|
||||
introspection structures found in QDBusIntrospection and QDBusInterface.
|
||||
|
||||
\sa QDBusInterface, QDBusIntrospection, QDBusObject::interfaces, QDBusObject::childObjects,
|
||||
QDBusObject::introspect
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusIntrospectableInterface::staticInterfaceName
|
||||
Returns the interface name: "org.freedesktop.DBus.Introspection"
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusIntrospectableInterface::staticIntrospectionData
|
||||
Returns the XML fragment corresponding to this interface's definition.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusIntrospectableInterface::QDBusIntrospectableInterface(const QDBusObject &)
|
||||
Creates a QDBusIntrospectableInterface object accessing interface the \a
|
||||
org.freedesktop.DBus.Introspectable interface on object \p obj.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusIntrospectableInterface::introspectionData() const
|
||||
Returns the XML fragment corresponding to this interface's definition.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusIntrospectableInterface::introspect
|
||||
Places an \a org.freedesktop.DBus.Introspectable.Introspect call to the remote object and
|
||||
return the XML result.
|
||||
*/
|
||||
|
||||
/*!
|
||||
Destroys the object.
|
||||
*/
|
||||
QDBusIntrospectableInterface::~QDBusIntrospectableInterface()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
\class QDBusPropertiesInterface
|
||||
\brief Provides access to the \a org.freedesktop.DBus.Properties interface
|
||||
|
||||
D-Bus interfaces can export properties, much like the ones used in QObject. In order to access
|
||||
those properties, two methods are defined in the \a org.freedesktop.DBus.Properties interface:
|
||||
get() and set(), which are similar in functionality to QObject::property and
|
||||
QObject::setProperty.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusPropertiesInterface::staticInterfaceName
|
||||
Returns the interface name: "org.freedesktop.DBus.Properties"
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusPropertiesInterface::staticIntrospectionData
|
||||
Returns the XML fragment corresponding to this interface's definition.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusPropertiesInterface::QDBusPropertiesInterface(const QDBusObject &)
|
||||
Creates a QDBusPropertiesInterface object accessing interface the \a
|
||||
org.freedesktop.DBus.Properties interface on object \p obj.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusPropertiesInterface::introspectionData() const
|
||||
Returns the XML fragment corresponding to this interface's definition.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusPropertiesInterface::set(const QString &interfaceName, const QString &propertyName,
|
||||
const QDBusVariant &value)
|
||||
Sets the property named \a propertyName in interface \a interfaceName in the remote object this
|
||||
QDBusPropertiesInterface object points to to the value specified by \a value. This function is
|
||||
analogous to QObject::setProperty.
|
||||
|
||||
If the type of the \a value parameter is not what the remote interface declared, the result is
|
||||
undefined. See QDBusInterface::properties for information on remote properties.
|
||||
|
||||
\sa QDBusInterface::setProperty
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusPropertiesInterface::get(const QString &interfaceName, const QString &propertyName)
|
||||
Retrieves the value of property named \a propertyName in interface \a interfaceName in the
|
||||
remote object this QDBusPropertiesInterface object points to. This function is analogous to
|
||||
QObject::property.
|
||||
|
||||
\sa QDBusInterface::property
|
||||
*/
|
||||
|
||||
/*!
|
||||
Destroys the object.
|
||||
*/
|
||||
QDBusPropertiesInterface::~QDBusPropertiesInterface()
|
||||
{
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*!
|
||||
\class QDBusBusInterface
|
||||
\internal
|
||||
\brief Provides access to the \a org.freedesktop.DBus interface found in the D-Bus server
|
||||
daemon.
|
||||
|
||||
The org.freedesktop.DBus interface is found only in the D-Bus daemon server. It is used to
|
||||
communicate with it and to request information about the bus itself and other applications in
|
||||
it.
|
||||
|
||||
Normally, you don't need to use this interface in your application. Instead, use the methods in
|
||||
QDBusConnection.
|
||||
|
||||
\sa QDBusConnection
|
||||
*/
|
||||
|
||||
QDBusBusInterface::~QDBusBusInterface()
|
||||
{
|
||||
}
|
||||
|
|
@ -112,3 +299,4 @@ const char* QDBusBusInterface::staticIntrospectionData()
|
|||
"</signal>"
|
||||
"</interface>";
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#define QDBUS_STANDARD_INTERFACES_H
|
||||
|
||||
#include "qdbusinterface.h"
|
||||
#include "qdbusreply.h"
|
||||
#include <QtCore/qstring.h>
|
||||
#include <QtCore/qstringlist.h>
|
||||
#include <dbus/dbus.h>
|
||||
|
|
@ -41,27 +42,23 @@ public:
|
|||
static inline const char* staticIntrospectionData()
|
||||
{
|
||||
return
|
||||
"<interface name=\"org.freedesktop.DBus.Peer\">"
|
||||
"<method name=\"Ping\" />"
|
||||
"</interface>";
|
||||
" <interface name=\"org.freedesktop.DBus.Peer\">\n"
|
||||
" <method name=\"Ping\" />\n"
|
||||
" </interface>\n";
|
||||
}
|
||||
|
||||
public:
|
||||
explicit QDBusPeerInterface(const QDBusObject& obj)
|
||||
: QDBusInterface(obj, staticInterfaceName())
|
||||
{ }
|
||||
|
||||
QDBusPeerInterface(QDBusConnection& conn, const QString& service, const QString& path)
|
||||
: QDBusInterface(conn, service, path, staticInterfaceName())
|
||||
: QDBusInterface(obj, QLatin1String(staticInterfaceName()))
|
||||
{ }
|
||||
|
||||
~QDBusPeerInterface();
|
||||
|
||||
inline virtual QString introspectionData() const
|
||||
{ return staticIntrospectionData(); }
|
||||
{ return QString::fromLatin1(staticIntrospectionData()); }
|
||||
|
||||
inline void ping()
|
||||
{ call(QLatin1String("Ping")); }
|
||||
inline QDBusReply<void> ping()
|
||||
{ return call(QLatin1String("Ping")); }
|
||||
};
|
||||
|
||||
class QDBUS_EXPORT QDBusIntrospectableInterface: public QDBusInterface
|
||||
|
|
@ -73,28 +70,24 @@ public:
|
|||
static inline const char* staticIntrospectionData()
|
||||
{
|
||||
return
|
||||
"<interface name=\"org.freedesktop.DBus.Introspectable\">"
|
||||
"<method name=\"Introspect\">"
|
||||
"<arg name=\"xml_data\" type=\"s\" direction=\"out\" />"
|
||||
"</method>"
|
||||
"</interface>";
|
||||
" <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
|
||||
" <method name=\"Introspect\">\n"
|
||||
" <arg name=\"xml_data\" type=\"s\" direction=\"out\"/>\n"
|
||||
" </method>\n"
|
||||
" </interface>\n";
|
||||
}
|
||||
public:
|
||||
explicit QDBusIntrospectableInterface(const QDBusObject& obj)
|
||||
: QDBusInterface(obj, staticInterfaceName())
|
||||
{ }
|
||||
|
||||
QDBusIntrospectableInterface(QDBusConnection& conn, const QString& service, const QString& path)
|
||||
: QDBusInterface(conn, service, path, staticInterfaceName())
|
||||
: QDBusInterface(obj, QLatin1String(staticInterfaceName()))
|
||||
{ }
|
||||
|
||||
~QDBusIntrospectableInterface();
|
||||
|
||||
inline virtual QString introspectionData() const
|
||||
{ return staticIntrospectionData(); }
|
||||
|
||||
inline QString introspect()
|
||||
{ return call(QLatin1String("Introspect")).at(0).toString(); }
|
||||
{ return QLatin1String(staticIntrospectionData()); }
|
||||
|
||||
inline QDBusReply<QString> introspect()
|
||||
{ return call(QLatin1String("Introspect")); }
|
||||
};
|
||||
|
||||
class QDBUS_EXPORT QDBusPropertiesInterface: public QDBusInterface
|
||||
|
|
@ -106,39 +99,38 @@ public:
|
|||
static inline const char* staticIntrospectionData()
|
||||
{
|
||||
return
|
||||
"<interface name=\"org.freedesktop.DBus.Properties\">"
|
||||
"<method name=\"Get\">"
|
||||
"<arg name=\"interface_name\" type=\"s\" direction=\"in\"/>"
|
||||
"<arg name=\"property_name\" type=\"s\" direction=\"in\"/>"
|
||||
"<arg name=\"value\" type=\"v\" direction=\"out\"/>"
|
||||
"</method>"
|
||||
"<method name=\"Set\">"
|
||||
"<arg name=\"interface_name\" type=\"s\" direction=\"in\"/>"
|
||||
"<arg name=\"property_name\" type=\"s\" direction=\"in\"/>"
|
||||
"<arg name=\"value\" type=\"v\" direction=\"in\"/>"
|
||||
"</method>";
|
||||
" <interface name=\"org.freedesktop.DBus.Properties\">\n"
|
||||
" <method name=\"Get\">\n"
|
||||
" <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\n"
|
||||
" <arg name=\"property_name\" type=\"s\" direction=\"in\"/>\n"
|
||||
" <arg name=\"value\" type=\"v\" direction=\"out\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"Set\">\n"
|
||||
" <arg name=\"interface_name\" type=\"s\" direction=\"in\"/>\n"
|
||||
" <arg name=\"property_name\" type=\"s\" direction=\"in\"/>\n"
|
||||
" <arg name=\"value\" type=\"v\" direction=\"in\"/>\n"
|
||||
" </method>\n"
|
||||
" </interface>\n";
|
||||
}
|
||||
public:
|
||||
explicit QDBusPropertiesInterface(const QDBusObject& obj)
|
||||
: QDBusInterface(obj, staticInterfaceName())
|
||||
{ }
|
||||
|
||||
QDBusPropertiesInterface(QDBusConnection& conn, const QString& service, const QString& path)
|
||||
: QDBusInterface(conn, service, path, staticInterfaceName())
|
||||
: QDBusInterface(obj, QLatin1String(staticInterfaceName()))
|
||||
{ }
|
||||
|
||||
~QDBusPropertiesInterface();
|
||||
|
||||
|
||||
inline virtual QString introspectionData() const
|
||||
{ return staticIntrospectionData(); }
|
||||
{ return QString::fromLatin1(staticIntrospectionData()); }
|
||||
|
||||
inline void set(const QString& interfaceName, const QString& propertyName, QVariant value)
|
||||
{ call(QLatin1String("Set.ssv"), interfaceName, propertyName, value); }
|
||||
inline QDBusReply<void> set(const QString& interfaceName, const QString& propertyName,
|
||||
const QDBusVariant &value)
|
||||
{ return call(QLatin1String("Set.ssv"), interfaceName, propertyName, value); }
|
||||
|
||||
inline QVariant get(const QString& interfaceName, const QString& propertyName)
|
||||
{ return call(QLatin1String("Get.ss"), interfaceName, propertyName).at(0); }
|
||||
inline QDBusReply<QDBusVariant> get(const QString& interfaceName, const QString& propertyName)
|
||||
{ return call(QLatin1String("Get.ss"), interfaceName, propertyName); }
|
||||
};
|
||||
|
||||
#if 0
|
||||
class QDBUS_EXPORT QDBusBusInterface: public QDBusInterface
|
||||
{
|
||||
public:
|
||||
|
|
@ -152,58 +144,54 @@ public:
|
|||
: QDBusInterface(obj, staticInterfaceName())
|
||||
{ }
|
||||
|
||||
QDBusBusInterface(QDBusConnection& conn, const QString& service, const QString& path)
|
||||
: QDBusInterface(conn, service, path, staticInterfaceName())
|
||||
{ }
|
||||
|
||||
~QDBusBusInterface();
|
||||
|
||||
inline virtual QString introspectionData() const
|
||||
{ return staticIntrospectionData(); }
|
||||
|
||||
inline unsigned requestName(const QString& name, unsigned flags)
|
||||
{ return call(QLatin1String("RequestName.su"), name, flags).at(0).toUInt(); }
|
||||
inline QDBusReply<unsigned> requestName(const QString& name, unsigned flags)
|
||||
{ return call(QLatin1String("RequestName.su"), name, flags); }
|
||||
|
||||
inline unsigned releaseName(const QString& name)
|
||||
{ return call(QLatin1String("ReleaseName.s"), name).at(0).toUInt(); }
|
||||
inline QDBusReply<unsigned> releaseName(const QString& name)
|
||||
{ return call(QLatin1String("ReleaseName.s"), name); }
|
||||
|
||||
inline unsigned startServiceByName(const QString& name, unsigned flags)
|
||||
{ return call(QLatin1String("StartServiceByName.su"), name, flags).at(0).toUInt(); }
|
||||
inline QDBusReply<unsigned> startServiceByName(const QString& name, unsigned flags)
|
||||
{ return call(QLatin1String("StartServiceByName.su"), name, flags); }
|
||||
|
||||
inline QString Hello()
|
||||
{ return call(QLatin1String("Hello")).at(0).toString(); }
|
||||
inline QDBusReply<QString> Hello()
|
||||
{ return call(QLatin1String("Hello")); }
|
||||
|
||||
inline bool nameHasOwner(const QString& name)
|
||||
{ return call(QLatin1String("NameHasOwner.s"), name).at(0).toBool(); }
|
||||
inline QDBusReply<bool> nameHasOwner(const QString& name)
|
||||
{ return call(QLatin1String("NameHasOwner.s"), name); }
|
||||
|
||||
inline QStringList listNames()
|
||||
{ return call(QLatin1String("ListNames")).at(0).toStringList(); }
|
||||
inline QDBusReply<QStringList> listNames()
|
||||
{ return call(QLatin1String("ListNames")); }
|
||||
|
||||
inline void addMatch(const QString& rule)
|
||||
{ call(QLatin1String("AddMatch"), rule); }
|
||||
inline QDBusReply<void> addMatch(const QString& rule)
|
||||
{ return call(QLatin1String("AddMatch"), rule); }
|
||||
|
||||
inline void removeMatch(const QString& rule)
|
||||
{ call(QLatin1String("RemoveMatch"), rule); }
|
||||
inline QDBusReply<void> removeMatch(const QString& rule)
|
||||
{ return call(QLatin1String("RemoveMatch"), rule); }
|
||||
|
||||
inline QString getNameOwner(const QString& name)
|
||||
{ return call(QLatin1String("GetNameOwner.s"), name).at(0).toString(); }
|
||||
inline QDBusReply<QString> getNameOwner(const QString& name)
|
||||
{ return call(QLatin1String("GetNameOwner.s"), name); }
|
||||
|
||||
inline QStringList listQueuedOwners(const QString& name)
|
||||
{ return call(QLatin1String("ListQueuedOwners.s"), name).at(0).toStringList(); }
|
||||
inline QDBusReply<QStringList> listQueuedOwners(const QString& name)
|
||||
{ return call(QLatin1String("ListQueuedOwners.s"), name); }
|
||||
|
||||
inline quint32 getConnectionUnixUser(const QString& connectionName)
|
||||
{ return call(QLatin1String("GetConnectionUnixUser.s"), connectionName).at(0).toUInt(); }
|
||||
inline QDBusReply<quint32> getConnectionUnixUser(const QString& connectionName)
|
||||
{ return call(QLatin1String("GetConnectionUnixUser.s"), connectionName); }
|
||||
|
||||
inline quint32 getConnectionUnixProcessID(const QString& connectionName)
|
||||
{ return call(QLatin1String("GetConnectionUnixProcessID.s"), connectionName).at(0).toUInt(); }
|
||||
inline QDBusReply<quint32> getConnectionUnixProcessID(const QString& connectionName)
|
||||
{ return call(QLatin1String("GetConnectionUnixProcessID.s"), connectionName); }
|
||||
|
||||
inline QByteArray getConnectionSELinuxSecurityContext(const QString& connectionName)
|
||||
{ return call(QLatin1String("GetConnectionSELinuxSecurityContext.s"), connectionName).at(0).toByteArray(); }
|
||||
inline QDBusReply<QByteArray> getConnectionSELinuxSecurityContext(const QString& connectionName)
|
||||
{ return call(QLatin1String("GetConnectionSELinuxSecurityContext.s"), connectionName); }
|
||||
|
||||
inline void reloadConfig()
|
||||
{ call(QLatin1String("ReloadConfig")); }
|
||||
inline QDBusReply<void> reloadConfig()
|
||||
{ return call(QLatin1String("ReloadConfig")); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
namespace org {
|
||||
namespace freedesktop {
|
||||
|
|
|
|||
212
qt/qdbustype.cpp
212
qt/qdbustype.cpp
|
|
@ -92,79 +92,6 @@ public:
|
|||
virtual QString addElementsToStruct(const QStringList& subTypes) ;
|
||||
};
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Parse the signature and return the max length that is valid
|
||||
*/
|
||||
static int parse(const char* signature)
|
||||
{
|
||||
if (!signature || !*signature)
|
||||
return 0; // not valid
|
||||
|
||||
switch (signature[0]) {
|
||||
case DBUS_TYPE_BOOLEAN:
|
||||
case DBUS_TYPE_BYTE:
|
||||
case DBUS_TYPE_INT16:
|
||||
case DBUS_TYPE_INT32:
|
||||
case DBUS_TYPE_UINT16:
|
||||
case DBUS_TYPE_UINT32:
|
||||
case DBUS_TYPE_INT64:
|
||||
case DBUS_TYPE_UINT64:
|
||||
case DBUS_TYPE_DOUBLE:
|
||||
case DBUS_TYPE_STRING:
|
||||
case DBUS_TYPE_OBJECT_PATH:
|
||||
case DBUS_TYPE_SIGNATURE:
|
||||
case DBUS_TYPE_VARIANT:
|
||||
return 1;
|
||||
|
||||
case DBUS_TYPE_ARRAY: {
|
||||
// check if it's a dict-entry array
|
||||
if (signature[1] == DBUS_DICT_ENTRY_BEGIN_CHAR) {
|
||||
// the first type must be ok and primitive (length 1)
|
||||
char c[2] = { signature[2], 0 };
|
||||
if (parse(c) != 1)
|
||||
return 0; // not valid
|
||||
|
||||
// the rest must be a valid type too
|
||||
int len = parse(signature + 3);
|
||||
if (len == 0)
|
||||
return 0; // not valid
|
||||
|
||||
// check the closing brace
|
||||
if (signature[len + 3] != DBUS_DICT_ENTRY_END_CHAR)
|
||||
return 0; // not valid
|
||||
|
||||
// it's valid
|
||||
return len + 4;
|
||||
}
|
||||
|
||||
// it's not a dict-entry, so it's ok as long as the internal type is ok too
|
||||
int len = parse(signature + 1);
|
||||
return len ? len + 1 : 0;
|
||||
}
|
||||
|
||||
case DBUS_STRUCT_BEGIN_CHAR: {
|
||||
// check that each entry is valid
|
||||
int i = 1;
|
||||
while (i) {
|
||||
if (i > 1 && signature[i] == DBUS_STRUCT_END_CHAR)
|
||||
break; // this is valid
|
||||
|
||||
int len = parse(signature + i);
|
||||
if (len)
|
||||
i += len;
|
||||
else
|
||||
i = 0;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
default:
|
||||
return 0; // not valid
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static QString findInMap(char type, const QDBusPrettyTypeBase::Entry* map)
|
||||
{
|
||||
for ( ; map->signature; ++map)
|
||||
|
|
@ -197,10 +124,10 @@ inline QString QDBusPrettyTypeBase::toString(const QDBusType& type)
|
|||
case DBUS_TYPE_DICT_ENTRY: {
|
||||
Q_ASSERT_X(subTypes.size() == 2, "QDBusType::toString",
|
||||
"maps must have exactly two elements");
|
||||
|
||||
|
||||
QString key = findInMap( subTypes.at(0).dbusType(), map );
|
||||
QString value = toString( subTypes.at(1) );
|
||||
|
||||
|
||||
Q_ASSERT(!key.isNull());
|
||||
|
||||
return addElementsToMap( key, value );
|
||||
|
|
@ -264,14 +191,14 @@ QString QDBusConventionalNames::addElementsToArray(const QString& subType)
|
|||
const QDBusPrettyTypeBase::Entry* QDBusQtNames::entryMap()
|
||||
{
|
||||
static QDBusPrettyTypeBase::Entry translation[] = {
|
||||
{ "quint8", DBUS_TYPE_BYTE },
|
||||
{ "uchar", DBUS_TYPE_BYTE },
|
||||
{ "bool", DBUS_TYPE_BOOLEAN },
|
||||
{ "qint16", DBUS_TYPE_INT16 },
|
||||
{ "quint16", DBUS_TYPE_UINT16 },
|
||||
{ "qint32", DBUS_TYPE_INT32 },
|
||||
{ "quint32", DBUS_TYPE_UINT32 },
|
||||
{ "qint64", DBUS_TYPE_INT64 },
|
||||
{ "quint64", DBUS_TYPE_UINT64 },
|
||||
{ "short", DBUS_TYPE_INT16 },
|
||||
{ "ushort", DBUS_TYPE_UINT16 },
|
||||
{ "int", DBUS_TYPE_INT32 },
|
||||
{ "uint", DBUS_TYPE_UINT32 },
|
||||
{ "qlonglong", DBUS_TYPE_INT64 },
|
||||
{ "qulonglong", DBUS_TYPE_UINT64 },
|
||||
{ "double", DBUS_TYPE_DOUBLE },
|
||||
{ "QString", DBUS_TYPE_STRING },
|
||||
{ "QString", DBUS_TYPE_OBJECT_PATH },
|
||||
|
|
@ -283,8 +210,8 @@ const QDBusPrettyTypeBase::Entry* QDBusQtNames::entryMap()
|
|||
|
||||
static inline QString templateArg(const QString& input)
|
||||
{
|
||||
if (input.endsWith('>'))
|
||||
return input + ' ';
|
||||
if (input.endsWith(QLatin1Char('>')))
|
||||
return input + QLatin1Char(' ');
|
||||
return input;
|
||||
}
|
||||
|
||||
|
|
@ -292,11 +219,14 @@ QString QDBusQtNames::addElementsToStruct(const QStringList& subTypes)
|
|||
{
|
||||
Q_UNUSED(subTypes);
|
||||
|
||||
return QLatin1String("QList"); // CHANGEME in the future
|
||||
return QLatin1String("QVariantList"); // CHANGEME in the future
|
||||
}
|
||||
|
||||
QString QDBusQtNames::addElementsToMap(const QString& key, const QString& value)
|
||||
{
|
||||
if (key == QLatin1String("QString") && value == QLatin1String("QDBusVariant"))
|
||||
return QLatin1String("QVariantMap");
|
||||
|
||||
return QString( QLatin1String("QMap<%1, %2>") )
|
||||
.arg(key)
|
||||
.arg( templateArg(value) );
|
||||
|
|
@ -304,10 +234,13 @@ QString QDBusQtNames::addElementsToMap(const QString& key, const QString& value)
|
|||
|
||||
QString QDBusQtNames::addElementsToArray(const QString& subType)
|
||||
{
|
||||
if (subType == QLatin1String("quint8"))
|
||||
if (subType == QLatin1String("uchar"))
|
||||
// special case
|
||||
return QLatin1String("QByteArray");
|
||||
|
||||
else if (subType == QLatin1String("QString"))
|
||||
// special case
|
||||
return QLatin1String("QStringList");
|
||||
|
||||
return QString( QLatin1String("QList<%1>") )
|
||||
.arg( templateArg(subType) );
|
||||
}
|
||||
|
|
@ -323,16 +256,19 @@ QString QDBusQVariantNames::addElementsToMap(const QString& key, const QString&
|
|||
{
|
||||
Q_UNUSED(key);
|
||||
Q_UNUSED(value);
|
||||
|
||||
|
||||
return QLatin1String("QVariantMap");
|
||||
}
|
||||
|
||||
QString QDBusQVariantNames::addElementsToArray(const QString& subType)
|
||||
{
|
||||
if (subType == QLatin1String("quint8"))
|
||||
if (subType == QLatin1String("uchar"))
|
||||
// special case
|
||||
return QLatin1String("QByteArray");
|
||||
|
||||
else if (subType == QLatin1String("QString"))
|
||||
// special case
|
||||
return QLatin1String("QStringList");
|
||||
|
||||
return QLatin1String("QVariantList");
|
||||
}
|
||||
|
||||
|
|
@ -354,15 +290,42 @@ public:
|
|||
|
||||
/*!
|
||||
\class QDBusType
|
||||
\brief Represents one single D-Bus type.
|
||||
|
||||
Represents one single DBus type.
|
||||
D-Bus provides a set of primitive types that map to normal, C++ types and to QString, as well as
|
||||
the possibility to extend the set with the so-called "container" types. The available types are
|
||||
as follows:
|
||||
|
||||
- Primitive (or basic): integers of 16, 32 and 64 bits, both signed and unsigned; byte (8 bits);
|
||||
double-precision floating point and Unicode strings
|
||||
- Arrays: a homogeneous, ordered list of zero or more entries
|
||||
- Maps: an unordered list of (key, value) pairs, where key must be a primitive type and value
|
||||
can be any D-Bus type
|
||||
- Structs: an ordered list of a fixed number of entries of any type
|
||||
- Variants: a "wildcard" container that can assume the value of any other type, including
|
||||
structs and arrays
|
||||
|
||||
Any type can be placed inside an array (including other arrays), but only entries of the same
|
||||
type can be placed inside the same array. The analogous type for D-Bus arrays are the Qt
|
||||
#QList template classes.
|
||||
|
||||
Structs have a fixed number of entries and each entry has a fixed type. They are analogous to C
|
||||
and C++ structs (hence the name).
|
||||
|
||||
Maps or dictionaries are analogous to the Qt #QMap template class, with the additional
|
||||
restriction that the key type must be a primitive one. D-Bus implements maps by using arrays of
|
||||
a special type (a "dictionary entry"), so inspecting a QDBusType of a Map will reveal that it is
|
||||
an array (see isArray()).
|
||||
|
||||
Variants contain exactly one entry, but the type can vary freely. It is analogous to the Qt
|
||||
class #QVariant, but the QtDBus implementation uses #QDBusVariant to represent D-Bus Variants.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\enum QDBusType::StringFormat
|
||||
|
||||
This enum is used in QDBusType::toString to determine which type of formatting
|
||||
to apply to the DBus types:
|
||||
to apply to the D-Bus types:
|
||||
|
||||
\value ConventionalNames Use the DBus conventional names, such as STRING, BOOLEAN or
|
||||
ARRAY of BYTE.
|
||||
|
|
@ -380,8 +343,6 @@ QDBusType::QDBusType()
|
|||
|
||||
/*!
|
||||
Constructs the type based on the given DBus type.
|
||||
|
||||
\param type the type
|
||||
*/
|
||||
QDBusType::QDBusType(int type)
|
||||
{
|
||||
|
|
@ -392,7 +353,6 @@ QDBusType::QDBusType(int type)
|
|||
/*!
|
||||
Constructs the type based on the given QVariant type.
|
||||
|
||||
\param type the type
|
||||
\sa QVariant::Type
|
||||
*/
|
||||
QDBusType::QDBusType(QVariant::Type type)
|
||||
|
|
@ -430,7 +390,7 @@ QDBusType::QDBusType(QVariant::Type type)
|
|||
/*!
|
||||
Parses the given DBus signature and constructs the type it represents.
|
||||
|
||||
\param signature the signature to parse. It must represent one single type, but can
|
||||
\param signature the signature to parse. It must represent one single type, but can be
|
||||
a container type.
|
||||
*/
|
||||
QDBusType::QDBusType(const char* signature)
|
||||
|
|
@ -447,8 +407,8 @@ QDBusType::QDBusType(const char* signature)
|
|||
|
||||
/*!
|
||||
Parses the given DBus signature and constructs the type it represents.
|
||||
|
||||
\param signature the signature to parse. It must represent one single type, but can
|
||||
|
||||
\param str the signature to parse. It must represent one single type, but can
|
||||
a container type.
|
||||
*/
|
||||
QDBusType::QDBusType(const QString& str)
|
||||
|
|
@ -458,8 +418,8 @@ QDBusType::QDBusType(const QString& str)
|
|||
|
||||
/*!
|
||||
Parses the given DBus signature and constructs the type it represents.
|
||||
|
||||
\param signature the signature to parse. It must represent one single type, but can
|
||||
|
||||
\param str the signature to parse. It must represent one single type, but can
|
||||
a container type.
|
||||
*/
|
||||
QDBusType::QDBusType(const QByteArray& str)
|
||||
|
|
@ -468,6 +428,7 @@ QDBusType::QDBusType(const QByteArray& str)
|
|||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Creates a QDBusType object based on the current element pointed to by \a iter.
|
||||
|
||||
\param iter the iterator. Can be pointing to container types.
|
||||
|
|
@ -479,7 +440,7 @@ QDBusType::QDBusType(DBusSignatureIter* iter)
|
|||
// we have to recurse
|
||||
if ( d->code == DBUS_TYPE_VARIANT )
|
||||
return; // no we don't. dbus_type_is_container lies to us
|
||||
|
||||
|
||||
// we have to recurse
|
||||
DBusSignatureIter subiter;
|
||||
dbus_signature_iter_recurse(iter, &subiter);
|
||||
|
|
@ -545,11 +506,11 @@ QByteArray QDBusType::dbusSignature() const
|
|||
QByteArray retval;
|
||||
switch (d->code) {
|
||||
// can only be array, map or struct
|
||||
|
||||
|
||||
case DBUS_TYPE_ARRAY:
|
||||
Q_ASSERT_X(d->subTypes.size() == 1, "QDBusType::dbusSignature",
|
||||
"more than one element in array");
|
||||
|
||||
|
||||
retval += DBUS_TYPE_ARRAY;
|
||||
retval += d->subTypes.at(0).dbusSignature();
|
||||
break;
|
||||
|
|
@ -563,7 +524,7 @@ QByteArray QDBusType::dbusSignature() const
|
|||
|
||||
Q_ASSERT(key != DBUS_TYPE_INVALID);
|
||||
Q_ASSERT(!value.isEmpty());
|
||||
|
||||
|
||||
retval.reserve(value.length() + 3);
|
||||
retval = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING;
|
||||
retval += key;
|
||||
|
|
@ -593,7 +554,7 @@ QVariant::Type QDBusType::qvariantType() const
|
|||
{
|
||||
if (d && d->qvariantType != QVariant::Invalid)
|
||||
return d->qvariantType;
|
||||
|
||||
|
||||
// check the special array cases:
|
||||
if (isArray()) {
|
||||
QDBusType t = arrayElement();
|
||||
|
|
@ -619,7 +580,7 @@ bool QDBusType::isValid() const
|
|||
|
||||
/*!
|
||||
Returns true if this type is a basic one.
|
||||
|
||||
|
||||
\sa dbus_type_is_basic
|
||||
*/
|
||||
bool QDBusType::isBasic() const
|
||||
|
|
@ -629,7 +590,7 @@ bool QDBusType::isBasic() const
|
|||
|
||||
/*!
|
||||
Returns true if this type is a container.
|
||||
|
||||
|
||||
\sa dbus_type_is_container
|
||||
*/
|
||||
bool QDBusType::isContainer() const
|
||||
|
|
@ -639,7 +600,7 @@ bool QDBusType::isContainer() const
|
|||
|
||||
/*!
|
||||
Returns the subtypes of this type, if this is a container.
|
||||
|
||||
|
||||
\sa isContainer
|
||||
*/
|
||||
QDBusTypeList QDBusType::subTypes() const
|
||||
|
|
@ -728,7 +689,7 @@ QString QDBusType::toString(StringFormat sf) const
|
|||
switch (sf) {
|
||||
case ConventionalNames:
|
||||
return QDBusConventionalNames().toString(*this);
|
||||
|
||||
|
||||
case QtNames:
|
||||
return QDBusQtNames().toString(*this);
|
||||
|
||||
|
|
@ -778,7 +739,7 @@ QVariant::Type QDBusType::qvariantType(const char* signature)
|
|||
case DBUS_TYPE_INT16:
|
||||
case DBUS_TYPE_INT32:
|
||||
return QVariant::Int;
|
||||
|
||||
|
||||
case DBUS_TYPE_BYTE:
|
||||
case DBUS_TYPE_UINT16:
|
||||
case DBUS_TYPE_UINT32:
|
||||
|
|
@ -803,7 +764,7 @@ QVariant::Type QDBusType::qvariantType(const char* signature)
|
|||
|
||||
case DBUS_TYPE_VARIANT:
|
||||
return QVariant::UserType; // must set user-type too
|
||||
|
||||
|
||||
case DBUS_TYPE_ARRAY: // special case
|
||||
// check if it's a string list
|
||||
if (qvariantType(signature + 1) == QVariant::String)
|
||||
|
|
@ -872,7 +833,7 @@ int QDBusType::dbusType(QVariant::Type t)
|
|||
case QVariant::Map:
|
||||
// internal type information has been lost
|
||||
return DBUS_TYPE_DICT_ENTRY;
|
||||
|
||||
|
||||
case QVariant::List:
|
||||
case QVariant::StringList:
|
||||
case QVariant::ByteArray:
|
||||
|
|
@ -896,7 +857,7 @@ int QDBusType::dbusType(QVariant::Type t)
|
|||
Converts the QVariant::Type to a DBus type signature.
|
||||
|
||||
\param t the type to convert
|
||||
*/
|
||||
*/
|
||||
const char* QDBusType::dbusSignature(QVariant::Type t)
|
||||
{
|
||||
switch (t)
|
||||
|
|
@ -946,11 +907,11 @@ const char* QDBusType::dbusSignature(QVariant::Type t)
|
|||
case QVariant::StringList:
|
||||
return DBUS_TYPE_ARRAY_AS_STRING
|
||||
DBUS_TYPE_STRING_AS_STRING; // as
|
||||
|
||||
|
||||
case QVariant::ByteArray:
|
||||
return DBUS_TYPE_ARRAY_AS_STRING
|
||||
DBUS_TYPE_BYTE_AS_STRING; // ay
|
||||
|
||||
|
||||
case QVariant::List:
|
||||
// not a string list
|
||||
// internal list data has been lost
|
||||
|
|
@ -966,6 +927,14 @@ const char* QDBusType::dbusSignature(QVariant::Type t)
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\enum QDBusType::VariantListMode
|
||||
Defines how the guessFromVariant() function will behave when the QVariant is of type
|
||||
QVariant::List.
|
||||
|
||||
\todo Improve the algorithm
|
||||
*/
|
||||
|
||||
/*!
|
||||
Guesses the DBus type from the given variant.
|
||||
*/
|
||||
|
|
@ -1014,7 +983,7 @@ QDBusType QDBusType::guessFromVariant(const QVariant& variant, VariantListMode m
|
|||
t.d->subTypes << guessFromVariant(v, mode);
|
||||
|
||||
return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (variant.type() == QVariant::Map) {
|
||||
// investigate deeper
|
||||
|
|
@ -1061,25 +1030,25 @@ QDBusType QDBusType::guessFromVariant(const QVariant& variant, VariantListMode m
|
|||
}
|
||||
else
|
||||
return QDBusType(variant.type());
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\class QDBusTypeList
|
||||
\brief A list of DBus types.
|
||||
|
||||
|
||||
Represents zero or more DBus types in sequence, such as those used in argument lists
|
||||
or in subtypes of structs and maps.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusTypeList::QDBusTypeList()
|
||||
|
||||
|
||||
Default constructor.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QDBusTypeList::QDBusTypeList(const QDBusTypeList& other)
|
||||
|
||||
|
||||
Copy constructor.
|
||||
\param other the list to copy
|
||||
*/
|
||||
|
|
@ -1099,7 +1068,7 @@ QDBusTypeList::QDBusTypeList(const char* signature)
|
|||
{
|
||||
if (!signature || !*signature)
|
||||
return; // empty
|
||||
|
||||
|
||||
// validate it first
|
||||
if ( !dbus_signature_validate(signature, 0) )
|
||||
return;
|
||||
|
|
@ -1114,6 +1083,7 @@ QDBusTypeList::QDBusTypeList(const char* signature)
|
|||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Constructs a type list by parsing the elements on this iterator level.
|
||||
|
||||
\param iter the iterator containing the elements on this level
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ public:
|
|||
QtNames,
|
||||
QVariantNames
|
||||
};
|
||||
|
||||
|
||||
QDBusType();
|
||||
explicit QDBusType(int type);
|
||||
explicit QDBusType(QVariant::Type type);
|
||||
|
|
@ -110,9 +110,6 @@ public:
|
|||
|
||||
bool canBeMap() const;
|
||||
|
||||
inline QDBusTypeList& operator<<(const QDBusType& item)
|
||||
{ QList<QDBusType>::operator<<(item); return *this; }
|
||||
|
||||
QByteArray dbusSignature() const;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -30,13 +30,22 @@
|
|||
|
||||
namespace QDBusUtil
|
||||
{
|
||||
/*!
|
||||
Returns true if this is \p ifaceName is a valid interface name.
|
||||
|
||||
Valid interface names must:
|
||||
- not be empty
|
||||
- not exceed 255 characters in length
|
||||
- be composed of dot-separated string components that contain only ASCII letters, digits and the
|
||||
underscore ("_") character
|
||||
- contain at least two such components
|
||||
*/
|
||||
bool isValidInterfaceName(const QString& ifaceName)
|
||||
{
|
||||
if (ifaceName.isEmpty() || ifaceName.length() > DBUS_MAXIMUM_NAME_LENGTH)
|
||||
return false;
|
||||
|
||||
QStringList parts = ifaceName.split('.');
|
||||
QStringList parts = ifaceName.split(QLatin1Char('.'));
|
||||
if (parts.count() < 2)
|
||||
return false; // at least two parts
|
||||
|
||||
|
|
@ -47,37 +56,55 @@ namespace QDBusUtil
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if \p connName is a valid unique connection name.
|
||||
|
||||
Unique connection names start with a colon (":") and are followed by a list of dot-separated
|
||||
components composed of ASCII letters, digits, the hypen or the underscore ("_") character.
|
||||
*/
|
||||
bool isValidUniqueConnectionName(const QString &connName)
|
||||
{
|
||||
if (connName.isEmpty() || connName.length() > DBUS_MAXIMUM_NAME_LENGTH ||
|
||||
!connName.startsWith(':'))
|
||||
!connName.startsWith(QLatin1Char(':')))
|
||||
return false;
|
||||
|
||||
QStringList parts = connName.mid(1).split('.');
|
||||
QStringList parts = connName.mid(1).split(QLatin1Char('.'));
|
||||
if (parts.count() < 1)
|
||||
return false;
|
||||
|
||||
QRegExp regex("[a-zA-Z0-9_-]+");
|
||||
QRegExp regex(QLatin1String("[a-zA-Z0-9_-]+"));
|
||||
foreach (QString part, parts)
|
||||
if (!regex.exactMatch(part))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Returns true if \p busName is a valid bus name.
|
||||
|
||||
A valid bus name is either a valid unique connection name or follows the rules:
|
||||
- is not empty
|
||||
- does not exceed 255 characters in length
|
||||
- be composed of dot-separated string components that contain only ASCII letters, digits,
|
||||
hyphens or underscores ("_"), but don't start with a digit
|
||||
- contains at least two such elements
|
||||
|
||||
\see isValidUniqueConnectionName
|
||||
*/
|
||||
bool isValidBusName(const QString &busName)
|
||||
{
|
||||
if (busName.isEmpty() || busName.length() > DBUS_MAXIMUM_NAME_LENGTH)
|
||||
return false;
|
||||
|
||||
if (busName.startsWith(':'))
|
||||
if (busName.startsWith(QLatin1Char(':')))
|
||||
return isValidUniqueConnectionName(busName);
|
||||
|
||||
QStringList parts = busName.split('.');
|
||||
QStringList parts = busName.split(QLatin1Char('.'));
|
||||
if (parts.count() < 1)
|
||||
return false;
|
||||
|
||||
QRegExp regex("[a-zA-Z_-][a-zA-Z0-9_-]*");
|
||||
QRegExp regex(QLatin1String("[a-zA-Z_-][a-zA-Z0-9_-]*"));
|
||||
foreach (QString part, parts)
|
||||
if (!regex.exactMatch(part))
|
||||
return false;
|
||||
|
|
@ -85,34 +112,53 @@ namespace QDBusUtil
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if \p memberName is a valid member name. A valid member name does not exceed
|
||||
255 characters in length, is not empty, is composed only of ASCII letters, digits and
|
||||
underscores, but does not start with a digit.
|
||||
*/
|
||||
bool isValidMemberName(const QString &memberName)
|
||||
{
|
||||
if (memberName.isEmpty() || memberName.length() > DBUS_MAXIMUM_NAME_LENGTH)
|
||||
return false;
|
||||
|
||||
QRegExp regex("[a-zA-Z0-9_]+");
|
||||
QRegExp regex(QLatin1String("[a-zA-Z_][a-zA-Z0-9_]+"));
|
||||
return regex.exactMatch(memberName);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if \p errorName is a valid error name. Valid error names are valid interface
|
||||
names and vice-versa, so this function is actually an alias for isValidInterfaceName.
|
||||
*/
|
||||
bool isValidErrorName(const QString &errorName)
|
||||
{
|
||||
return isValidInterfaceName(errorName);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if \p path is valid object path.
|
||||
|
||||
Valid object paths follow the rules:
|
||||
- start with the slash character ("/")
|
||||
- do not end in a slash, unless the path is just the initial slash
|
||||
- do not contain any two slashes in sequence
|
||||
- contain slash-separated parts, each of which is composed of ASCII letters, digits and
|
||||
underscores ("_")
|
||||
*/
|
||||
bool isValidObjectPath(const QString &path)
|
||||
{
|
||||
if (path == QLatin1String("/"))
|
||||
return true;
|
||||
|
||||
if (!path.startsWith('/') || path.indexOf(QLatin1String("//")) != -1 ||
|
||||
path.endsWith('/'))
|
||||
if (!path.startsWith(QLatin1Char('/')) || path.indexOf(QLatin1String("//")) != -1 ||
|
||||
path.endsWith(QLatin1Char('/')))
|
||||
return false;
|
||||
|
||||
QStringList parts = path.split('/');
|
||||
QStringList parts = path.split(QLatin1Char('/'));
|
||||
Q_ASSERT(parts.count() >= 1);
|
||||
parts.removeFirst(); // it starts with /, so we get an empty first part
|
||||
|
||||
QRegExp regex("[a-zA-Z0-9_]+");
|
||||
|
||||
QRegExp regex(QLatin1String("[a-zA-Z0-9_]+"));
|
||||
foreach (QString part, parts)
|
||||
if (!regex.exactMatch(part))
|
||||
return false;
|
||||
|
|
@ -120,14 +166,26 @@ namespace QDBusUtil
|
|||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if \p signature is a valid D-Bus type signature for one or more types.
|
||||
This function returns true if it can all of \p signature into valid, individual types and no
|
||||
characters remain in \p signature.
|
||||
|
||||
\see isValidSingleSignature
|
||||
*/
|
||||
bool isValidSignature(const QString &signature)
|
||||
{
|
||||
return dbus_signature_validate(signature.toUtf8(), 0);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if \p signature is a valid D-Bus type signature for exactly one full type. This
|
||||
function tries to convert the type signature into a D-Bus type and, if it succeeds and no
|
||||
characters remain in the signature, it returns true.
|
||||
*/
|
||||
bool isValidSingleSignature(const QString &signature)
|
||||
{
|
||||
return dbus_signature_validate_single(signature.toUtf8(), 0);
|
||||
}
|
||||
|
||||
|
||||
} // namespace QDBusUtil
|
||||
|
|
|
|||
|
|
@ -33,6 +33,17 @@ struct QDBUS_EXPORT QDBusVariant
|
|||
{
|
||||
QDBusType type;
|
||||
QVariant value;
|
||||
|
||||
inline QDBusVariant()
|
||||
{ }
|
||||
inline QDBusVariant(const QVariant &variant) : value(variant)
|
||||
{ }
|
||||
inline QDBusVariant(const QVariant &variant, const QDBusType &forcetype)
|
||||
: type(forcetype), value(variant)
|
||||
{ }
|
||||
|
||||
inline operator const QVariant &() const
|
||||
{ return value; }
|
||||
};
|
||||
Q_DECLARE_METATYPE(QDBusVariant)
|
||||
|
||||
|
|
|
|||
|
|
@ -37,22 +37,22 @@ static QDBusIntrospection::Annotations
|
|||
parseAnnotations(const QDomElement& elem)
|
||||
{
|
||||
QDBusIntrospection::Annotations retval;
|
||||
QDomNodeList list = elem.elementsByTagName("annotation");
|
||||
QDomNodeList list = elem.elementsByTagName(QLatin1String("annotation"));
|
||||
for (int i = 0; i < list.count(); ++i)
|
||||
{
|
||||
QDomElement ann = list.item(i).toElement();
|
||||
if (ann.isNull())
|
||||
continue;
|
||||
|
||||
QString name = ann.attribute("name"),
|
||||
value = ann.attribute("value");
|
||||
|
||||
QString name = ann.attribute(QLatin1String("name")),
|
||||
value = ann.attribute(QLatin1String("value"));
|
||||
|
||||
if (name.isEmpty())
|
||||
continue;
|
||||
|
||||
retval.insert(name, value);
|
||||
}
|
||||
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -68,24 +68,24 @@ static QDBusIntrospection::Arguments
|
|||
parseArgs(const QDomElement& elem, const QLatin1String& direction, bool acceptEmpty = false)
|
||||
{
|
||||
QDBusIntrospection::Arguments retval;
|
||||
QDomNodeList list = elem.elementsByTagName("arg");
|
||||
QDomNodeList list = elem.elementsByTagName(QLatin1String("arg"));
|
||||
for (int i = 0; i < list.count(); ++i)
|
||||
{
|
||||
QDomElement arg = list.item(i).toElement();
|
||||
if (arg.isNull())
|
||||
continue;
|
||||
|
||||
if ((acceptEmpty && !arg.hasAttribute("direction")) ||
|
||||
arg.attribute("direction") == direction) {
|
||||
|
||||
if ((acceptEmpty && !arg.hasAttribute(QLatin1String("direction"))) ||
|
||||
arg.attribute(QLatin1String("direction")) == direction) {
|
||||
|
||||
QDBusIntrospection::Argument argData;
|
||||
if (arg.hasAttribute("name"))
|
||||
argData.name = arg.attribute("name"); // can be empty
|
||||
argData.type = parseType(arg.attribute("type"));
|
||||
|
||||
if (arg.hasAttribute(QLatin1String("name")))
|
||||
argData.name = arg.attribute(QLatin1String("name")); // can be empty
|
||||
argData.type = parseType(arg.attribute(QLatin1String("type")));
|
||||
|
||||
if (!argData.type.isValid())
|
||||
continue;
|
||||
|
||||
|
||||
retval << argData;
|
||||
}
|
||||
}
|
||||
|
|
@ -98,7 +98,7 @@ QDBusXmlParser::QDBusXmlParser(const QString& service, const QString& path,
|
|||
{
|
||||
QDomDocument doc;
|
||||
doc.setContent(xmlData);
|
||||
m_node = doc.firstChildElement("node");
|
||||
m_node = doc.firstChildElement(QLatin1String("node"));
|
||||
}
|
||||
|
||||
QDBusXmlParser::QDBusXmlParser(const QString& service, const QString& path,
|
||||
|
|
@ -121,16 +121,16 @@ QDBusXmlParser::interfaces() const
|
|||
|
||||
if (m_node.isNull())
|
||||
return retval;
|
||||
|
||||
QDomNodeList interfaces = m_node.elementsByTagName("interface");
|
||||
|
||||
QDomNodeList interfaces = m_node.elementsByTagName(QLatin1String("interface"));
|
||||
for (int i = 0; i < interfaces.count(); ++i)
|
||||
{
|
||||
QDomElement iface = interfaces.item(i).toElement();
|
||||
QString ifaceName = iface.attribute("name");
|
||||
QString ifaceName = iface.attribute(QLatin1String("name"));
|
||||
if (iface.isNull() || ifaceName.isEmpty())
|
||||
continue; // for whatever reason
|
||||
|
||||
QDBusIntrospection::Interface *ifaceData;
|
||||
QDBusIntrospection::Interface *ifaceData = 0; // make gcc shut up
|
||||
if (m_store) {
|
||||
QSharedDataPointer<QDBusIntrospection::Interface> knownData =
|
||||
m_store->findInterface(ifaceName);
|
||||
|
|
@ -161,11 +161,11 @@ QDBusXmlParser::interfaces() const
|
|||
ifaceData->annotations = parseAnnotations(iface);
|
||||
|
||||
// parse methods
|
||||
QDomNodeList list = iface.elementsByTagName("method");
|
||||
QDomNodeList list = iface.elementsByTagName(QLatin1String("method"));
|
||||
for (int j = 0; j < list.count(); ++j)
|
||||
{
|
||||
QDomElement method = list.item(j).toElement();
|
||||
QString methodName = method.attribute("name");
|
||||
QString methodName = method.attribute(QLatin1String("name"));
|
||||
if (method.isNull() || methodName.isEmpty())
|
||||
continue;
|
||||
|
||||
|
|
@ -178,15 +178,15 @@ QDBusXmlParser::interfaces() const
|
|||
methodData.annotations = parseAnnotations(method);
|
||||
|
||||
// add it
|
||||
ifaceData->methods.insert(methodName, methodData);
|
||||
ifaceData->methods.insert(methodName, methodData);
|
||||
}
|
||||
|
||||
// parse signals
|
||||
list = iface.elementsByTagName("signal");
|
||||
list = iface.elementsByTagName(QLatin1String("signal"));
|
||||
for (int j = 0; j < list.count(); ++j)
|
||||
{
|
||||
QDomElement signal = list.item(j).toElement();
|
||||
QString signalName = signal.attribute("name");
|
||||
QString signalName = signal.attribute(QLatin1String("name"));
|
||||
if (signal.isNull() || signalName.isEmpty())
|
||||
continue;
|
||||
|
||||
|
|
@ -202,11 +202,11 @@ QDBusXmlParser::interfaces() const
|
|||
}
|
||||
|
||||
// parse properties
|
||||
list = iface.elementsByTagName("property");
|
||||
list = iface.elementsByTagName(QLatin1String("property"));
|
||||
for (int j = 0; j < list.count(); ++j)
|
||||
{
|
||||
QDomElement property = list.item(j).toElement();
|
||||
QString propertyName = property.attribute("name");
|
||||
QString propertyName = property.attribute(QLatin1String("name"));
|
||||
if (property.isNull() || propertyName.isEmpty())
|
||||
continue;
|
||||
|
||||
|
|
@ -214,14 +214,14 @@ QDBusXmlParser::interfaces() const
|
|||
|
||||
// parse data
|
||||
propertyData.name = propertyName;
|
||||
propertyData.type = parseType(property.attribute("type"));
|
||||
propertyData.type = parseType(property.attribute(QLatin1String("type")));
|
||||
propertyData.annotations = parseAnnotations(property);
|
||||
|
||||
if (!propertyData.type.isValid())
|
||||
// cannot be!
|
||||
continue;
|
||||
|
||||
QString access = property.attribute("access");
|
||||
QString access = property.attribute(QLatin1String("access"));
|
||||
if (access.isEmpty())
|
||||
// can't be empty either!
|
||||
continue;
|
||||
|
|
@ -248,49 +248,51 @@ QDBusXmlParser::interfaces() const
|
|||
QSharedDataPointer<QDBusIntrospection::Object>
|
||||
QDBusXmlParser::object() const
|
||||
{
|
||||
QSharedDataPointer<QDBusIntrospection::Object> retval;
|
||||
|
||||
if (m_node.isNull())
|
||||
return retval;
|
||||
return QSharedDataPointer<QDBusIntrospection::Object>();
|
||||
|
||||
// check if the store knows about this one
|
||||
QDBusIntrospection::Object* objData;
|
||||
if (m_store) {
|
||||
retval = objData = m_store->findObject(m_service, m_path);
|
||||
objData = m_store->findObject(m_service, m_path);
|
||||
}
|
||||
else {
|
||||
objData = new QDBusIntrospection::Object;
|
||||
objData->service = m_service;
|
||||
objData->path = m_path;
|
||||
}
|
||||
|
||||
|
||||
// check if we have anything to process
|
||||
if (objData->introspection.isNull() && !m_node.firstChild().isNull()) {
|
||||
// yes, introspect this object
|
||||
QTextStream ts(&objData->introspection);
|
||||
m_node.save(ts,2);
|
||||
|
||||
QDomNodeList objects = m_node.elementsByTagName("node");
|
||||
|
||||
QDomNodeList objects = m_node.elementsByTagName(QLatin1String("node"));
|
||||
for (int i = 0; i < objects.count(); ++i) {
|
||||
QDomElement obj = objects.item(i).toElement();
|
||||
QString objName = obj.attribute("name");
|
||||
QString objName = obj.attribute(QLatin1String("name"));
|
||||
if (obj.isNull() || objName.isEmpty())
|
||||
continue; // for whatever reason
|
||||
|
||||
objData->childObjects.append(objName);
|
||||
}
|
||||
|
||||
QDomNodeList interfaces = m_node.elementsByTagName("interface");
|
||||
QDomNodeList interfaces = m_node.elementsByTagName(QLatin1String("interface"));
|
||||
for (int i = 0; i < interfaces.count(); ++i) {
|
||||
QDomElement iface = interfaces.item(i).toElement();
|
||||
QString ifaceName = iface.attribute("name");
|
||||
QString ifaceName = iface.attribute(QLatin1String("name"));
|
||||
if (iface.isNull() || ifaceName.isEmpty())
|
||||
continue;
|
||||
|
||||
objData->interfaces.append(ifaceName);
|
||||
}
|
||||
} else {
|
||||
objData->introspection = QLatin1String("<node/>\n");
|
||||
}
|
||||
|
||||
QSharedDataPointer<QDBusIntrospection::Object> retval;
|
||||
retval = objData;
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -308,17 +310,17 @@ QDBusXmlParser::objectTree() const
|
|||
retval->path = m_path;
|
||||
|
||||
QTextStream ts(&retval->introspection);
|
||||
m_node.save(ts,2);
|
||||
|
||||
m_node.save(ts,2);
|
||||
|
||||
// interfaces are easy:
|
||||
retval->interfaceData = interfaces();
|
||||
retval->interfaces = retval->interfaceData.keys();
|
||||
|
||||
// sub-objects are slightly more difficult:
|
||||
QDomNodeList objects = m_node.elementsByTagName("node");
|
||||
QDomNodeList objects = m_node.elementsByTagName(QLatin1String("node"));
|
||||
for (int i = 0; i < objects.count(); ++i) {
|
||||
QDomElement obj = objects.item(i).toElement();
|
||||
QString objName = obj.attribute("name");
|
||||
QString objName = obj.attribute(QLatin1String("name"));
|
||||
if (obj.isNull() || objName.isEmpty())
|
||||
continue; // for whatever reason
|
||||
|
||||
|
|
@ -331,10 +333,10 @@ QDBusXmlParser::objectTree() const
|
|||
|
||||
// parse it
|
||||
QString objAbsName = m_path;
|
||||
if (!objAbsName.endsWith('/'))
|
||||
objAbsName.append('/');
|
||||
if (!objAbsName.endsWith(QLatin1Char('/')))
|
||||
objAbsName.append(QLatin1Char('/'));
|
||||
objAbsName += objName;
|
||||
|
||||
|
||||
QDBusXmlParser parser(m_service, objAbsName, obj, m_store);
|
||||
retval->childObjectData.insert(objName, parser.objectTree());
|
||||
}
|
||||
|
|
@ -344,4 +346,4 @@ QDBusXmlParser::objectTree() const
|
|||
|
||||
return QSharedDataPointer<QDBusIntrospection::ObjectTree>( retval );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue