Declare abstract signal in interface class

Beachwalker picture Beachwalker · Jul 30, 2013 · Viewed 23.5k times · Source

How to declare a Qt signal in an abstract class / interface when the implementing class is already derrived from QObject/QWidget?

class IEmitSomething
{
   public:
     // this should be the signal known to others
     virtual void someThingHappened() = 0;
}

class ImplementEmitterOfSomething : public QWidget, public IEmitSomething
{
     // signal implementation should be generated here
     signals: void someThingHappended();
}

Answer

Beachwalker picture Beachwalker · Aug 7, 2013

As I found out in the last days... the Qt way of doing this is like this:

class IEmitSomething
{
   public:
     virtual ~IEmitSomething(){} // do not forget this

   signals: // <- ignored by moc and only serves as documentation aid
            // The code will work exactly the same if signals: is absent.
     virtual void someThingHappened() = 0;
}

Q_DECLARE_INTERFACE(IEmitSomething, "IEmitSomething") // define this out of namespace scope

class ImplementEmitterOfSomething : public QWidget, public IEmitSomething
{
   Q_OBJECT
   Q_INTERFACES(IEmitSomething)

   signals:
      void someThingHappended();
}

Now you can connect to those interface signals.

If you don't have access to the implementation when connecting to the signal your connect statement will require a dynamic cast to QObject:

IEmitSomething* es = ... // your implementation class

connect(dynamic_cast<QObject*>(es), SIGNAL(someThingHappended()), ...);

... and this way you're not forced to expose the implementation class to subscribers and clients. Yeah!!!