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:
- Modify the auto-generated adaptor classes or to call a different method. (boring)
- 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:
- Write/modify adaptors by hand (boring)
- 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:
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:
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
:
- Add a public (or protected) method to retrieve the adaptee
QObject* adaptee() const;
- Add a method to set the adaptee
void setAdaptee(QObject *adaptee);
- 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 tosetAdaptee(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