Search code examples
qtc++11pluginsqt4qt5

Qt piping data between plugins


I'm developing an app based on plugins, following the Echo Plugin Example.

So far so good. Now I'm at a point where I would like to pipe data between plugins. I have one plugin which establishes a network connection using QTcpSocket and I have another plugin in which I would like to display the data in a QTextEdit. How do I pipe the data between plugins?

If both where simple objects I will do simple signal slot connection, but since the interface of plugins doesn't derive from QObject it's not possible to have signal slots. Or, at least I don't know how.


Solution

  • Actually, signal-slots is possible. All you have to do is to cast your plugin to a QObject. Example:

    Your plugin interface:

    class MyPluginInterface1
    {
    public:
        virtual ~MyPluginInterface1() {}
    
    signals:
        virtual void mySignal() = 0;
    }
    
    class MyPluginInterface2
    {
    public:
        virtual ~MyPluginInterface2() {}
    
    public slots:
        virtual void mySlot() = 0;
    }
    
    Q_DECLARE_INTERFACE(MyPluginInterface1, ...)
    Q_DECLARE_INTERFACE(MyPluginInterface2, ...)
    

    Now, in your implementation, you do:

    class MyPlugin1 : public QObject, public MyPluginInterface1
    {
        Q_OBJECT
        Q_PLUGIN_METADATA(...)
        Q_INTERFACES(MyPluginInterface1)
    
    signals:
        void mySignal() Q_DECL_FINAL;//make it final because signals cannot be overridden
    }
    
    class MyPlugin2 : public QObject, public MyPluginInterface2
    {
        Q_OBJECT
        Q_PLUGIN_METADATA(...)
        Q_INTERFACES(MyPluginInterface2)
    
    public slots:
        void mySlot() Q_DECL_OVERRIDE;
    }
    

    And finally, when doing the connection

    //...
    MyPluginInterface1 *p1 = this->plugin1;//Just an example
    MyPluginInterface2 *p1 = this->plugin2;
    
    //since you know both inherit QObject, you can do:
    QObject::connect(dynamic_cast<QObject*>(p1), SIGNAL(mySignal()),
                     dynamic_cast<QObject*>(p2), SLOT(mySlot()));
    
    //...
    

    Please note that Qt will not provide auto-completion for those signals/slots and you have to connect them using this (old) syntax.

    Hint: If you want to have signals in your interfaces, please understand that signals are not virtual, they cannot be overriden. However, to add the signal to your interface, it has to be pure virtual. To avoid errors, always implement the signals using the Q_DECL_FINAL macro - this prevents you from overriden them.