QtDbus peer-to-peer support and other good news

I’ve been really busy, so I was unable to blog for a while… And I’m still really busy, so this is just a quick update about what happened in the last few days.

  • My merge request [1] was finally merged in Qt master [2] and finally QTBUG-186 [3] is resolved. It took more than one year to get it in (the first version was submitted on March 26th, 2010), but it was definitely worth.
    This means that since Qt 4.8, QDBusServer won’t be just stub and QDBusConnection will have two new methods QDBusConnection::connectToPeer and QDBusConnection::disconnectFromPeer. You will be able to connect two applications directly and use DBus protocol for communication using Qt API, but without using the DBus daemon. (The only limitation is that you won’t be able to have both server and client in the same process and use blocking calls)
    This also means that DBusTubes using Telepathy-Qt4 (and therefore in KDE [4, 5]) will be soon possible (KDE 4.8 maybe?)
  • I succesfully defended my PhD Thesis (“Design and Development of a Framework for Tool Integration and Collaboration in Neuroinformatics and Computer-Aided Neurosurgery”), I’ll release the source code I wrote as soon as I find some time to do it (I need to clean the source code, translate comments, remove swears and other tasks like that before a serious release 😉 ), then I’ll probably write some blog posts about it.
  • Last but not least I am now engaged. 😀

[1]Merge Request 2342 – QtDbus peer-to-peer support
[2]Qt commit 685df07ff7e357f6848c50cffa311641afdca307
[3]QTBUG-186
[4]GSoC Update: DBusTubes work!
[5]Hello Planet KDE && GSoC: Telepathy Tubes and File Transfer in KDE

Qdbusxml2cpp and QDBusAbstractAdaptor Limitations

Issue #1:

Object implementing two different interfaces, both having a method named "Bar"

<interface name="org.drdanz.foo">
  <method name="Bar">
</interface>
<interface name="org.drdanz.boo">
  <method name="Bar">
</interface>

The adaptor code generated by qdbusxml2cpp is something like

[...]

QString fooAdaptor::Bar() const
{
    // handle method call home.drdanz.foo.Bar
    parent()->Bar();
}

[...]

QString booAdaptor::Bar() const
{
    // handle method call home.drdanz.boo.Bar
    parent()->Bar();
}

[...]

This means that the called method is the same, therefore it is not possible to have two different behaviours of the methods.

I don’t think that there is a way to know which of the methods called the parent()->Bar(); method and implement a simple switch (the QObject::sender() works only if called in a slot activated by a signal and I’m not aware of any other method to do that.

Solutions:

  1. Modify the auto-generated adaptor classes or to call a different method. (boring)
  2. Do not use qdbusxml2cpp and write the adaptor classes by hand, or don’t use adaptors at all (even more boring)

Issue #2

Objects implementing the same interface

class Base : public QObject {
  virtual <interface org.drdanz.foo> = 0
}
class Derived1 : public Base {
  <interface org.drdanz.foo>
  <interface org.drdanz.foo.bar1>
  <interface org.drdanz.foo.bar2>
}
class Derived2 : public Base {
  <interface org.drdanz.foo>
  <interface org.drdanz.foo.bar1>
  <interface org.drdanz.foo.bar3>
}
class Derived3 : public Base {
  <interface org.drdanz.foo>
  <interface org.drdanz.foo.bar2>
  <interface org.drdanz.foo.bar3>
}

Implementation of org.drdanz.foo.bar1 should available to all the classes that implement that interface.

Adaptors for interfaces org.drdanz.foo.barX cannot be created using Base as the parent class because Base should have virtual methods for every possible barX

(Just to demonstrate that a similar architecture make sense and is legal in D-Bus, an existing example is the Connection object in Telepathy, that must always implement the interface org.freedesktop.Telepathy.Connection, but can implement any number of additional org.freedesktop.Telepathy.Connection.Interface.XXXX interface.)

It is impossible to create a class Bar1 and declare

class Base : public virtual QObject {
  virtual <interface org.drdanz.foo> = 0
}
class Bar1 : public virtual QObject {
  <interface org.drdanz.foo.bar1>
}
class Derived1 : public Base, public Bar1;

because both Base and Bar1 needs to be QObject to be a parent for the adaptor and multiple inheritance is not supported for QObjects:

Warning: Class Derived1 inherits from two QObject subclasses Base and Bar1. This is not supported!

Solutions:

  1. Write/modify adaptors by hand (boring)
  2. Auto generate adaptors for every derived class and implement the methods multiple times (redundant and stupid)

A better possible solution to both issues:

Allow auto generated adaptors to use the methods on a QObject (adaptee) that is not the parent.

This is what qdbusxml2cpp produces in Qt 4.7:

qdbusxml2cpp produced adaptors in Qt 4.7

qdbusxml2cpp produced adaptors in Qt 4.7

The Object that "owns" the adaptor is the same that implements the real methods.

This is in my opinion what should be produced by qdbusxml2cpp:

What qdbusxml2cpp should produce

What qdbusxml2cpp should produce

The object that is registered on D-Bus exports all the adaptors, but the implementation of the interface can be in a different object

This requires just a few changes in the class QDBusAbstractAdaptor:

  1. Add a public (or protected) method to retrieve the adaptee QObject* adaptee() const;
  2. Add a method to set the adaptee void setAdaptee(QObject *adaptee);
  3. Add a constructor QBBusAbstractAdaptor(QObject *adaptee, QObject *parent).
    This doesn’t mean that adaptee must not be the parent, it just means that it can be a different object.
    Therefore to be backwards compatible the QBBusAbstractAdaptor(QObject *parent) must be modified to setAdaptee(parent)

Then a few changes are required in qdbusxml2cpp, to produce adaptors that use methods of the adaptee class instead methods of parent class.

An even easier implementation requires just to implement the adaptee logic in classes generated by qdbusxml2cpp

It could be enough to modify only qdbusxml2cpp

It could be enough to modify only qdbusxml2cpp