summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago@kde.org>2006-04-29 12:44:31 +0000
committerThiago Macieira <thiago@kde.org>2006-04-29 12:44:31 +0000
commit7cabddaa4237b7e0ce1c6b9781d115b9831e77f2 (patch)
tree982dc3f62b4356ee5d78d94767cb44d8f0d98973
parent47999a1c43302e9e80884b4018c416327fe675d2 (diff)
* qt/qdbusinterface.h: Rename QDBusRef to QDBusInterfacePtr
and disable the copy operators. (r533772, r534746) * qt/qdbuserror.h: Remove the automatic cast to bool. (r533929) * qt/qdbusabstractinterface.cpp: * qt/qdbusabstractinterface.h: Change the default call mode to not use the event loop. Add convenience call() methods that take a CallMode parameter. (r534042) * qt/qdbusconnection.h: Change the default call mode to not use the event loop. (r534042) * qt/qdbusinterface.cpp: * qt/qdbusinterface.h: Add a method to tell us if the interface is valid (since we don't return a null pointer anymore) (r534099) * qt/qdbusinterface_p.h: Don't crash if metaObject is 0 (r534101) * qt/qdbusinternalfilters.cpp: Decouple the introspection function in two so taht we get the chance to introspect without having a QDBusMessage (r534102) * qt/qdbusbus.h: * qt/qdbusconnection.cpp: * qt/qdbusconnection_p.h: * qt/qdbusintegrator.cpp: Keep a list of our own names to avoid a round-trip to the server when attempting to introspect one of our own objects. Also make sure the filter functions match the empty interface as well. (r534108) Don't keep the connection names. Instead, trust the unique connection name (r534111) Remove event loop usage (r534112)
-rw-r--r--ChangeLog38
-rw-r--r--qt/qdbusabstractinterface.cpp2
-rw-r--r--qt/qdbusabstractinterface.h84
-rw-r--r--qt/qdbusbus.h2
-rw-r--r--qt/qdbusconnection.h2
-rw-r--r--qt/qdbusconnection_p.h1
-rw-r--r--qt/qdbusintegrator.cpp85
-rw-r--r--qt/qdbusinterface.cpp17
-rw-r--r--qt/qdbusinterface.h15
-rw-r--r--qt/qdbusinterface_p.h2
-rw-r--r--qt/qdbusinternalfilters.cpp10
11 files changed, 230 insertions, 28 deletions
diff --git a/ChangeLog b/ChangeLog
index 7a07e132..c29fb746 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,43 @@
2006-04-29 Thiago Macieira <thiago.macieira@trolltech.com>
+ * qt/qdbusinterface.h: Rename QDBusRef to QDBusInterfacePtr
+ and disable the copy operators. (r533772, r534746)
+
+ * qt/qdbuserror.h: Remove the automatic cast to bool. (r533929)
+
+ * qt/qdbusabstractinterface.cpp:
+ * qt/qdbusabstractinterface.h: Change the default call mode to
+ not use the event loop. Add convenience call() methods that
+ take a CallMode parameter. (r534042)
+
+ * qt/qdbusconnection.h: Change the default call mode to not
+ use the event loop. (r534042)
+
+ * qt/qdbusinterface.cpp:
+ * qt/qdbusinterface.h: Add a method to tell us if the
+ interface is valid (since we don't return a null pointer
+ anymore) (r534099)
+
+ * qt/qdbusinterface_p.h: Don't crash if metaObject is 0
+ (r534101)
+
+ * qt/qdbusinternalfilters.cpp: Decouple the introspection
+ function in two so taht we get the chance to introspect
+ without having a QDBusMessage (r534102)
+
+ * qt/qdbusbus.h:
+ * qt/qdbusconnection.cpp:
+ * qt/qdbusconnection_p.h:
+ * qt/qdbusintegrator.cpp: Keep a list of our own names to
+ avoid a round-trip to the server when attempting to introspect
+ one of our own objects. Also make sure the filter functions
+ match the empty interface as well. (r534108)
+ Don't keep the connection names. Instead, trust the unique
+ connection name (r534111)
+ Remove event loop usage (r534112)
+
+2006-04-29 Thiago Macieira <thiago.macieira@trolltech.com>
+
* qt/qdbusintegrator.cpp: Fix assertion failure spotted by
Brad Hards.
diff --git a/qt/qdbusabstractinterface.cpp b/qt/qdbusabstractinterface.cpp
index 291888fe..eec373a3 100644
--- a/qt/qdbusabstractinterface.cpp
+++ b/qt/qdbusabstractinterface.cpp
@@ -148,7 +148,7 @@ QDBusMessage QDBusAbstractInterface::callWithArgs(const QString& method, const Q
if (mode == AutoDetect) {
// determine if this a sync or async call
- mode = UseEventLoop;
+ mode = NoUseEventLoop;
const QMetaObject *mo = metaObject();
QByteArray match = method.toLatin1() + '(';
diff --git a/qt/qdbusabstractinterface.h b/qt/qdbusabstractinterface.h
index ae80b0a3..23f928a2 100644
--- a/qt/qdbusabstractinterface.h
+++ b/qt/qdbusabstractinterface.h
@@ -69,6 +69,11 @@ public:
{
return callWithArgs(m);
}
+
+ inline QDBusMessage call(CallMode mode, const QString &m)
+ {
+ return callWithArgs(m, QList<QVariant>(), mode);
+ }
#ifndef Q_QDOC
private:
@@ -152,6 +157,85 @@ public:
<< qvfv(t7) << qvfv(t8);
return callWithArgs(m, args);
}
+
+ template<typename T1>
+ inline QDBusMessage call(CallMode mode, const QString &m, const T1 &t1)
+ {
+ QList<QVariant> args;
+ args << qvfv(t1);
+ return callWithArgs(m, args, mode);
+ }
+
+ template<typename T1, typename T2>
+ inline QDBusMessage call(CallMode mode, const QString &m, const T1 &t1, const T2 &t2)
+ {
+ QList<QVariant> args;
+ args << qvfv(t1) << qvfv(t2);
+ return callWithArgs(m, args, mode);
+ }
+
+ template<typename T1, typename T2, typename T3>
+ inline QDBusMessage call(CallMode mode, const QString &m, const T1 &t1, const T2 &t2,
+ const T3 &t3)
+ {
+ QList<QVariant> args;
+ args << qvfv(t1) << qvfv(t2) << qvfv(t3);
+ return callWithArgs(m, args, mode);
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4>
+ inline QDBusMessage call(CallMode mode, const QString &m, const T1 &t1, const T2 &t2,
+ const T3 &t3, const T4 &t4)
+ {
+ QList<QVariant> args;
+ args << qvfv(t1) << qvfv(t2) << qvfv(t3)
+ << qvfv(t4);
+ return callWithArgs(m, args, mode);
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5>
+ inline QDBusMessage call(CallMode mode, const QString &m, const T1 &t1, const T2 &t2,
+ const T3 &t3, const T4 &t4, const T5 &t5)
+ {
+ QList<QVariant> args;
+ args << qvfv(t1) << qvfv(t2) << qvfv(t3)
+ << qvfv(t4) << qvfv(t5);
+ return callWithArgs(m, args, mode);
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
+ inline QDBusMessage call(CallMode mode, const QString &m, const T1 &t1, const T2 &t2,
+ const T3 &t3, const T4 &t4, const T5 &t5, const T6 &t6)
+ {
+ QList<QVariant> args;
+ args << qvfv(t1) << qvfv(t2) << qvfv(t3)
+ << qvfv(t4) << qvfv(t5) << qvfv(t6);
+ return callWithArgs(m, args, mode);
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
+ inline QDBusMessage call(CallMode mode, const QString &m, const T1 &t1, const T2 &t2,
+ const T3 &t3, const T4 &t4, const T5 &t5, const T6 &t6, const T7 &t7)
+ {
+ QList<QVariant> args;
+ args << qvfv(t1) << qvfv(t2) << qvfv(t3)
+ << qvfv(t4) << qvfv(t5) << qvfv(t6)
+ << qvfv(t7);
+ return callWithArgs(m, args, mode);
+ }
+
+ template<typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8>
+ inline QDBusMessage call(CallMode mode, const QString &m, const T1 &t1, const T2 &t2,
+ const T3 &t3, const T4 &t4, const T5 &t5, const T6 &t6, const T7 &t7,
+ const T8 &t8)
+ {
+ QList<QVariant> args;
+ args << qvfv(t1) << qvfv(t2) << qvfv(t3)
+ << qvfv(t4) << qvfv(t5) << qvfv(t6)
+ << qvfv(t7) << qvfv(t8);
+ return callWithArgs(m, args, mode);
+ }
#endif
protected:
diff --git a/qt/qdbusbus.h b/qt/qdbusbus.h
index ae2720e2..6f0bbb1c 100644
--- a/qt/qdbusbus.h
+++ b/qt/qdbusbus.h
@@ -150,7 +150,7 @@ public slots:
signals:
void nameAcquired(const QString &service);
void nameLost(const QString &service);
- void nameOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner);
+ void nameOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner);
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QDBusBusService::RequestNameOptions);
diff --git a/qt/qdbusconnection.h b/qt/qdbusconnection.h
index 60116e10..e107242b 100644
--- a/qt/qdbusconnection.h
+++ b/qt/qdbusconnection.h
@@ -74,7 +74,7 @@ public:
QDBusError lastError() const;
bool send(const QDBusMessage &message) const;
- QDBusMessage sendWithReply(const QDBusMessage &message, WaitMode mode = UseEventLoop) const;
+ QDBusMessage sendWithReply(const QDBusMessage &message, WaitMode mode = NoUseEventLoop) const;
int sendWithReplyAsync(const QDBusMessage &message, QObject *receiver,
const char *slot) const;
diff --git a/qt/qdbusconnection_p.h b/qt/qdbusconnection_p.h
index 36f21db7..af572084 100644
--- a/qt/qdbusconnection_p.h
+++ b/qt/qdbusconnection_p.h
@@ -230,6 +230,7 @@ extern int qDBusNameToTypeId(const char *name);
extern bool qDBusCheckAsyncTag(const char *tag);
// in qdbusinternalfilters.cpp
+extern QString qDBusIntrospectObject(const QDBusConnectionPrivate::ObjectTreeNode *node);
extern void qDBusIntrospectObject(const QDBusConnectionPrivate::ObjectTreeNode *node,
const QDBusMessage &msg);
extern void qDBusPropertyGet(const QDBusConnectionPrivate::ObjectTreeNode *node,
diff --git a/qt/qdbusintegrator.cpp b/qt/qdbusintegrator.cpp
index bef8268d..3f907256 100644
--- a/qt/qdbusintegrator.cpp
+++ b/qt/qdbusintegrator.cpp
@@ -984,13 +984,14 @@ bool QDBusConnectionPrivate::activateInternalFilters(const ObjectTreeNode *node,
{
// object may be null
- if (msg.interface() == QLatin1String(DBUS_INTERFACE_INTROSPECTABLE)) {
+ if (msg.interface().isEmpty() || 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 (node->obj && (msg.interface().isEmpty() ||
+ 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"))
@@ -1053,25 +1054,26 @@ bool QDBusConnectionPrivate::activateObject(const ObjectTreeNode *node, const QD
return false;
}
-bool QDBusConnectionPrivate::handleObjectCall(const QDBusMessage &msg)
+template<typename Func>
+static bool applyForObject(QDBusConnectionPrivate::ObjectTreeNode *root, const QString &fullpath,
+ Func& functor)
{
- QReadLocker locker(&lock);
-
// walk the object tree
- QStringList path = msg.path().split(QLatin1Char('/'));
+ QStringList path = fullpath.split(QLatin1Char('/'));
if (path.last().isEmpty())
path.removeLast(); // happens if path is "/"
int i = 1;
- ObjectTreeNode *node = &rootNode;
+ QDBusConnectionPrivate::ObjectTreeNode *node = root;
// try our own tree first
while (node && !(node->flags & QDBusConnection::ExportChildObjects) ) {
if (i == path.count()) {
// found our object
- return activateObject(node, msg);
+ functor(node);
+ return true;
}
- QVector<ObjectTreeNode::Data>::ConstIterator it =
+ QVector<QDBusConnectionPrivate::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
@@ -1089,9 +1091,10 @@ bool QDBusConnectionPrivate::handleObjectCall(const QDBusMessage &msg)
while (obj) {
if (i == path.count()) {
// we're at the correct level
- ObjectTreeNode fakenode(*node);
+ QDBusConnectionPrivate::ObjectTreeNode fakenode(*node);
fakenode.obj = obj;
- return activateObject(&fakenode, msg);
+ functor(&fakenode);
+ return true;
}
const QObjectList &children = obj->children();
@@ -1112,6 +1115,31 @@ bool QDBusConnectionPrivate::handleObjectCall(const QDBusMessage &msg)
}
}
+ // object not found
+ return false;
+}
+
+struct qdbus_activateObject
+{
+ QDBusConnectionPrivate *self;
+ const QDBusMessage &msg;
+ bool returnVal;
+ inline qdbus_activateObject(QDBusConnectionPrivate *s, const QDBusMessage &m)
+ : self(s), msg(m)
+ { }
+
+ inline void operator()(QDBusConnectionPrivate::ObjectTreeNode *node)
+ { returnVal = self->activateObject(node, msg); }
+};
+
+bool QDBusConnectionPrivate::handleObjectCall(const QDBusMessage &msg)
+{
+ QReadLocker locker(&lock);
+
+ qdbus_activateObject apply(this, msg);
+ if (applyForObject(&rootNode, msg.path(), apply))
+ return apply.returnVal;
+
qDebug("Call failed: no object found at %s", qPrintable(msg.path()));
return false;
}
@@ -1479,6 +1507,7 @@ QDBusConnectionPrivate::findInterface(const QString &service,
QString owner = getNameOwner(service);
if (connection && !owner.isEmpty() && QDBusUtil::isValidObjectPath(path) &&
(interface.isEmpty() || QDBusUtil::isValidInterfaceName(interface)))
+ // always call here with the unique connection name
mo = findMetaObject(owner, path, interface);
QDBusInterfacePrivate *p = new QDBusInterfacePrivate(QDBusConnection(name), this, owner, path, interface, mo);
@@ -1509,24 +1538,52 @@ QDBusConnectionPrivate::findInterface(const QString &service,
return p;
}
+struct qdbus_Introspect
+{
+ QString xml;
+ inline void operator()(QDBusConnectionPrivate::ObjectTreeNode *node)
+ { xml = qDBusIntrospectObject(node); }
+};
+
QDBusMetaObject *
QDBusConnectionPrivate::findMetaObject(const QString &service, const QString &path,
const QString &interface)
{
+ // service must be a unique connection name
if (!interface.isEmpty()) {
QReadLocker locker(&lock);
QDBusMetaObject *mo = cachedMetaObjects.value(interface, 0);
if (mo)
return mo;
}
+ if (service == QString::fromUtf8(dbus_bus_get_unique_name(connection))) {
+ // it's one of our own
+ QWriteLocker locker(&lock);
+ QDBusMetaObject *mo = 0;
+ if (!interface.isEmpty())
+ mo = cachedMetaObjects.value(interface, 0);
+ if (mo)
+ // maybe it got created when we switched from read to write lock
+ return mo;
+
+ qdbus_Introspect apply;
+ if (!applyForObject(&rootNode, path, apply)) {
+ lastError = QDBusError(QDBusError::InvalidArgs,
+ QString(QLatin1String("No object at %1")).arg(path));
+ return 0; // no object at path
+ }
+
+ // release the lock and return
+ return QDBusMetaObject::createMetaObject(interface, apply.xml, cachedMetaObjects, lastError);
+ }
- // introspect the target object:
+ // not local: introspect the target object:
QDBusMessage msg = QDBusMessage::methodCall(service, path,
QLatin1String(DBUS_INTERFACE_INTROSPECTABLE),
QLatin1String("Introspect"));
- // we have to spin the event loop because the call could be targetting ourselves
- QDBusMessage reply = sendWithReply(msg, QDBusConnection::UseEventLoop);
+
+ QDBusMessage reply = sendWithReply(msg, QDBusConnection::NoUseEventLoop);
// it doesn't exist yet, we have to create it
QWriteLocker locker(&lock);
diff --git a/qt/qdbusinterface.cpp b/qt/qdbusinterface.cpp
index ff8fdc95..48b1011c 100644
--- a/qt/qdbusinterface.cpp
+++ b/qt/qdbusinterface.cpp
@@ -58,6 +58,19 @@ QDBusInterface::~QDBusInterface()
}
/*!
+ Returns true if this is a valid reference to a remote object. It returns false if
+ there was an error during the creation of this interface (for instance, if the remote
+ application does not exist).
+
+ Note: when dealing with remote objects, it is not always possible to determine if it
+ exists when creating a QDBusInterface or QDBusInterfacePtr object.
+*/
+bool QDBusInterface::isValid() const
+{
+ return d_func()->isValid;
+}
+
+/*!
\internal
Overrides QObject::metaObject to return our own copy.
*/
@@ -238,13 +251,13 @@ int QDBusInterfacePrivate::metacall(QMetaObject::Call c, int id, void **argv)
return id;
}
-QDBusRef::QDBusRef(QDBusConnection &conn, const QString &service, const QString &path,
+QDBusInterfacePtr::QDBusInterfacePtr(QDBusConnection &conn, const QString &service, const QString &path,
const QString &interface)
: d(conn.findInterface(service, path, interface))
{
}
-QDBusRef::QDBusRef(const QString &service, const QString &path, const QString &interface)
+QDBusInterfacePtr::QDBusInterfacePtr(const QString &service, const QString &path, const QString &interface)
: d(QDBus::sessionBus().findInterface(service, path, interface))
{
}
diff --git a/qt/qdbusinterface.h b/qt/qdbusinterface.h
index f667698b..2e16e5ce 100644
--- a/qt/qdbusinterface.h
+++ b/qt/qdbusinterface.h
@@ -35,6 +35,8 @@ private:
public:
~QDBusInterface();
+ bool isValid() const;
+
virtual const QMetaObject *metaObject() const;
virtual void *qt_metacast(const char *);
virtual int qt_metacall(QMetaObject::Call, int, void **);
@@ -43,16 +45,19 @@ private:
Q_DECLARE_PRIVATE(QDBusInterface);
};
-struct QDBUS_EXPORT QDBusRef
+struct QDBUS_EXPORT QDBusInterfacePtr
{
- QDBusRef(QDBusConnection &conn, const QString &service, const QString &path,
+ QDBusInterfacePtr(QDBusInterface *iface) : d(iface) { }
+ QDBusInterfacePtr(QDBusConnection &conn, const QString &service, const QString &path,
const QString &interface = QString());
- QDBusRef(const QString &service, const QString &path, const QString &interface = QString());
- ~QDBusRef() { delete d; }
+ QDBusInterfacePtr(const QString &service, const QString &path, const QString &interface = QString());
+ ~QDBusInterfacePtr() { delete d; }
- QDBusInterface* operator->() const { return d; }
+ QDBusInterface *interface() { return d; }
+ QDBusInterface *operator->() { return d; }
private:
QDBusInterface *const d;
+ Q_DISABLE_COPY(QDBusInterfacePtr)
};
#endif
diff --git a/qt/qdbusinterface_p.h b/qt/qdbusinterface_p.h
index 70b732c2..25cb9ffa 100644
--- a/qt/qdbusinterface_p.h
+++ b/qt/qdbusinterface_p.h
@@ -55,7 +55,7 @@ public:
}
~QDBusInterfacePrivate()
{
- if (!metaObject->cached)
+ if (metaObject && !metaObject->cached)
delete metaObject;
}
diff --git a/qt/qdbusinternalfilters.cpp b/qt/qdbusinternalfilters.cpp
index fe57a875..3d454277 100644
--- a/qt/qdbusinternalfilters.cpp
+++ b/qt/qdbusinternalfilters.cpp
@@ -225,8 +225,7 @@ static QString generateSubObjectXml(QObject *object)
return retval;
}
-void qDBusIntrospectObject(const QDBusConnectionPrivate::ObjectTreeNode *node,
- const QDBusMessage &msg)
+QString qDBusIntrospectObject(const QDBusConnectionPrivate::ObjectTreeNode *node)
{
// object may be null
@@ -281,10 +280,15 @@ void qDBusIntrospectObject(const QDBusConnectionPrivate::ObjectTreeNode *node,
}
xml_data += QLatin1String("</node>\n");
+ return xml_data;
+}
+void qDBusIntrospectObject(const QDBusConnectionPrivate::ObjectTreeNode *node,
+ const QDBusMessage &msg)
+{
// now send it
QDBusMessage reply = QDBusMessage::methodReply(msg);
- reply << xml_data;
+ reply << qDBusIntrospectObject(node);
msg.connection().send(reply);
}