Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Send QJsonObject from plugin to main app
QtWS25 Last Chance

Send QJsonObject from plugin to main app

Scheduled Pinned Locked Moved Solved General and Desktop
10 Posts 3 Posters 331 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • F Offline
    F Offline
    fem_dev
    wrote on last edited by
    #1

    Hi, I have a main application that will load many future developed plugins with the same interface:

    #ifndef PLUGIN_API_H
    #define PLUGIN_API_H
    
    #include <QString>
    #include <QDebug>
    
    class Plugin_API
    {
    public:
        virtual ~Plugin_API() = default;
    
        virtual QJsonObject data_from_plugin2app(void) = 0;
        virtual void open_ui(const int id) = 0;
        virtual void run(const int id) = 0;
    };
    
    // Declare our interface:
    Q_DECLARE_INTERFACE(Plugin_API, "com.lamar.plugin")
    
    #endif // PLUGIN_H
    

    The loaded plugins will be placed by the user in a custom serial sequence of execution.

    Now I can call the plugin->open_ui() and I get the plugin GUI on my screen. So I can fill the plugin input text with some data.

    My problem is:
    I have to save this plugin data (QJsonObject) in a main QJsonArray plugins_data that is a variable located in the main application.

    How can I send the data from my plugin (*.dll) to my main application?

    1 Reply Last reply
    0
    • F fem_dev

      @jsulm it's not possible because I have many different plugins that share the same Plugin_API...

      As you can see in the top, the Plugin_API have all methods that I use in all different plugins.

      So, when I load all plugins inside a foreach() loop, I have to cast they using the Plugin_API.

      Each individual plugin inherit the Plugin_API class.
      And inside each individual plugin I have declared:

      class PLUGIN_SHARED_EXPORT Plugin: public QObject, public Plugin_API
      {
          Q_OBJECT
          Q_PLUGIN_METADATA(IID "com.lamar.plugin")
          Q_INTERFACES(Plugin_API)
      

      What I'm doing wrong?

      F Offline
      F Offline
      fem_dev
      wrote on last edited by
      #10

      Thank you @SGaist and @jsulm
      With your help I think that I found a solution! Here is the code:

      My plugin interface is called Plugin_API. So the plugin_api.h is:

      #ifndef PLUGIN_API_H
      #define PLUGIN_API_H
      
      #include <QString>
      #include <QDebug>
      #include <QJsonObject>
      #include <QObject>
      
      // You have to import and inherit QOBject in the plugin interface
      class Plugin_API : public QObject
      {
          // USE Q_OBJECT MACRO inside the interface
          Q_OBJECT
      public:
          virtual ~Plugin_API() = default;
      
          virtual QJsonObject get_data(void) = 0;
          virtual void set_project_path(const QString project_path) = 0;
          virtual void open_ui(const QJsonObject ui_data) = 0;
          virtual void run(const int job_id) = 0;
      
          // ===== SIGNALS ===== //
          // You have to declare the signals in the interface too:
          virtual void send_msg(const QString msg) = 0;
      };
      
      // Declare our interface:
      Q_DECLARE_INTERFACE(Plugin_API, "com.lamar.plugin")
      
      #endif // PLUGIN_API_H
      

      After that, in the plugin.h I have:

      // Do NOT inherit plublic QObject here:
      class PLUGINSHARED_EXPORT Plugin: public Plugin_API
      {
          // ADD Q_OBJECT MACRO HERE TOO:
          Q_OBJECT
          Q_PLUGIN_METADATA(IID "com.lamar.plugin")
          Q_INTERFACES(Plugin_API)
      
         ...
         // Overide the signal method:
         signals:
          void send_msg(const QString msg) override;
      

      In my Main Application header main.h I have:

      public slots:
          void receive_msg(const QString msg);
      

      And finally, the implementaion of the main application slot is:

      void main_app::receive_msg(const QString msg)
      {
          qDebug() << "I RECEIVE THIS MSG: " << msg;
      }
      

      Thank you @SGaist and @jsulm for your help and patience!

      1 Reply Last reply
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #2

        Hi,

        Well, you load your plugin and then call the corresponding method from its interface.

        What have you tried ?

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        F 1 Reply Last reply
        1
        • SGaistS SGaist

          Hi,

          Well, you load your plugin and then call the corresponding method from its interface.

          What have you tried ?

          F Offline
          F Offline
          fem_dev
          wrote on last edited by
          #3

          @SGaist Sorry, but I'm not seeing how can I do it. Could you help me?

          How the main application will know when the button save was clicked in the plugin UI window?
          Is possible to inform that only using interfaces? Or I need to use signals and slots.

          Today I tried to connect the plugin and the main app using signals and slots.
          So, inside the plugin.cpp in the constructor(), I type:

          connect(this, SIGNAL(send_msg(QString)), ???, SLOT(receive_msg(QString)));
          

          But, what I have to write in ????

          Obs.: I'm loading the plugins using QPluginLoader:

          QPluginLoader loader(file);
          loader.load()
          Plugin_API* plugin = qobject_cast<Plugin_API*>(loader.instance());
          

          I'm confused about this topic...
          Could you please help me a little more?

          jsulmJ 1 Reply Last reply
          0
          • F fem_dev

            @SGaist Sorry, but I'm not seeing how can I do it. Could you help me?

            How the main application will know when the button save was clicked in the plugin UI window?
            Is possible to inform that only using interfaces? Or I need to use signals and slots.

            Today I tried to connect the plugin and the main app using signals and slots.
            So, inside the plugin.cpp in the constructor(), I type:

            connect(this, SIGNAL(send_msg(QString)), ???, SLOT(receive_msg(QString)));
            

            But, what I have to write in ????

            Obs.: I'm loading the plugins using QPluginLoader:

            QPluginLoader loader(file);
            loader.load()
            Plugin_API* plugin = qobject_cast<Plugin_API*>(loader.instance());
            

            I'm confused about this topic...
            Could you please help me a little more?

            jsulmJ Offline
            jsulmJ Offline
            jsulm
            Lifetime Qt Champion
            wrote on last edited by jsulm
            #4

            @fem_dev Do not connect inside plug-in as it does not know anything about receiver of its signals (and it should not!).
            Do the connect in main window (or where-ever you use the plug-in).
            So, like

            MainWindow::MainWindow(...)
            {
                connect(plugin, SIGNAL(send_msg(QString)), this, SLOT(receive_msg(QString)));
            }
            
            plugin->data_from_plugin2app();
            

            https://forum.qt.io/topic/113070/qt-code-of-conduct

            F 1 Reply Last reply
            0
            • jsulmJ jsulm

              @fem_dev Do not connect inside plug-in as it does not know anything about receiver of its signals (and it should not!).
              Do the connect in main window (or where-ever you use the plug-in).
              So, like

              MainWindow::MainWindow(...)
              {
                  connect(plugin, SIGNAL(send_msg(QString)), this, SLOT(receive_msg(QString)));
              }
              
              plugin->data_from_plugin2app();
              
              F Offline
              F Offline
              fem_dev
              wrote on last edited by
              #5

              @jsulm thank you....I think that this is the half of solution...

              foreach(QString file, plugins) {
                      QPluginLoader loader(file);
                      if(loader.load())
                      {
                          Plugin_API* plugin = qobject_cast<Plugin_API*>(loader.instance());
              
                          if(plugin) {
                              // HERE I GOT A COMPILATION ERROR:
                              // Cannot convert argument 1 from 'Plugin_API *' to 'const QObject *'
                              connect(plugin, SIGNAL(send_msg(QString)), this, SLOT(receive_msg(QString)));   
                          } else {
                              qCritical() << "Wrong Plugin API! Could not cast: " << loader.fileName();
                          }
                      } else {
                          qCritical() << "ERROR: " << loader.fileName() << " - Msg: " << loader.errorString();
                      }
                  }
              

              Buy my plugin.h have Q_OBJECT macro:

              #ifndef PLUGIN_H
              #define PLUGIN_H
              
              #include <QObject>
              #include <QtPlugin>
              
              #include <QJsonDocument>
              #include <QJsonArray>
              #include <QJsonObject>
              #include <QFile>
              #include <QByteArray>
              
              #include "analysis_x_global.h"
              #include "../plugin_api.h"
              #include "dialog.h"
              
              class PLUGIN_SHARED_EXPORT Plugin: public QObject, public Plugin_API
              {
                  Q_OBJECT
                  Q_PLUGIN_METADATA(IID "com.lamar.plugin")
                  Q_INTERFACES(Plugin_API)
              
              public:
                  explicit Plugin(QObject* parent = nullptr);
                  ~Plugin() override;
              
                  QJsonObject get_data(void) override;
                  void open_ui(const QJsonObject ui_data) override;
                  void run(const int job_id) override;
              
              signals:
                  void send_msg(const QString msg);
              
              public slots:
                  void onMessage(QJsonObject updated_ui_data);
              };
              
              #endif // PLUGIN_H
              

              Second: to call a plugin method from the main app, I know that can be done using:

              plugin->method()
              

              But my plugin have a Window (UI) and some buttons, like save.
              How can I send a plugin data to my main app when the user hits the save button in the plugin Window UI?

              jsulmJ 1 Reply Last reply
              0
              • F fem_dev

                @jsulm thank you....I think that this is the half of solution...

                foreach(QString file, plugins) {
                        QPluginLoader loader(file);
                        if(loader.load())
                        {
                            Plugin_API* plugin = qobject_cast<Plugin_API*>(loader.instance());
                
                            if(plugin) {
                                // HERE I GOT A COMPILATION ERROR:
                                // Cannot convert argument 1 from 'Plugin_API *' to 'const QObject *'
                                connect(plugin, SIGNAL(send_msg(QString)), this, SLOT(receive_msg(QString)));   
                            } else {
                                qCritical() << "Wrong Plugin API! Could not cast: " << loader.fileName();
                            }
                        } else {
                            qCritical() << "ERROR: " << loader.fileName() << " - Msg: " << loader.errorString();
                        }
                    }
                

                Buy my plugin.h have Q_OBJECT macro:

                #ifndef PLUGIN_H
                #define PLUGIN_H
                
                #include <QObject>
                #include <QtPlugin>
                
                #include <QJsonDocument>
                #include <QJsonArray>
                #include <QJsonObject>
                #include <QFile>
                #include <QByteArray>
                
                #include "analysis_x_global.h"
                #include "../plugin_api.h"
                #include "dialog.h"
                
                class PLUGIN_SHARED_EXPORT Plugin: public QObject, public Plugin_API
                {
                    Q_OBJECT
                    Q_PLUGIN_METADATA(IID "com.lamar.plugin")
                    Q_INTERFACES(Plugin_API)
                
                public:
                    explicit Plugin(QObject* parent = nullptr);
                    ~Plugin() override;
                
                    QJsonObject get_data(void) override;
                    void open_ui(const QJsonObject ui_data) override;
                    void run(const int job_id) override;
                
                signals:
                    void send_msg(const QString msg);
                
                public slots:
                    void onMessage(QJsonObject updated_ui_data);
                };
                
                #endif // PLUGIN_H
                

                Second: to call a plugin method from the main app, I know that can be done using:

                plugin->method()
                

                But my plugin have a Window (UI) and some buttons, like save.
                How can I send a plugin data to my main app when the user hits the save button in the plugin Window UI?

                jsulmJ Offline
                jsulmJ Offline
                jsulm
                Lifetime Qt Champion
                wrote on last edited by jsulm
                #6

                @fem_dev said in Send QJsonObject from plugin to main app:

                How can I send a plugin data to my main app when the user hits the save button in the plugin Window UI?

                Via signals/slots.

                "Cannot convert argument 1 from 'Plugin_API *' to 'const QObject *'" - this is because your plug-in class is not derived from QObject and does not contain Q_OBJECT macro.

                https://forum.qt.io/topic/113070/qt-code-of-conduct

                F 1 Reply Last reply
                0
                • jsulmJ jsulm

                  @fem_dev said in Send QJsonObject from plugin to main app:

                  How can I send a plugin data to my main app when the user hits the save button in the plugin Window UI?

                  Via signals/slots.

                  "Cannot convert argument 1 from 'Plugin_API *' to 'const QObject *'" - this is because your plug-in class is not derived from QObject and does not contain Q_OBJECT macro.

                  F Offline
                  F Offline
                  fem_dev
                  wrote on last edited by
                  #7

                  @jsulm please, look my plugin.h header above. It have the Q_OBJECT macro.
                  And the class declaration is:

                  class PLUGIN_SHARED_EXPORT Plugin: public QObject, public Plugin_API
                  

                  What is wrong?

                  I tried to add the public QObject and Q_OBJECT macro inside the plugin_API class, but I got these compilation warnings/errors:

                  'Plugin': base-class 'QObject' is already a base-class of 'Plugin_API'
                  
                  jsulmJ 1 Reply Last reply
                  0
                  • F fem_dev

                    @jsulm please, look my plugin.h header above. It have the Q_OBJECT macro.
                    And the class declaration is:

                    class PLUGIN_SHARED_EXPORT Plugin: public QObject, public Plugin_API
                    

                    What is wrong?

                    I tried to add the public QObject and Q_OBJECT macro inside the plugin_API class, but I got these compilation warnings/errors:

                    'Plugin': base-class 'QObject' is already a base-class of 'Plugin_API'
                    
                    jsulmJ Offline
                    jsulmJ Offline
                    jsulm
                    Lifetime Qt Champion
                    wrote on last edited by
                    #8

                    @fem_dev said in Send QJsonObject from plugin to main app:

                    What is wrong?

                    Problem is that plugin bellow is Plugin_API* and not Plugin*:

                    connect(plugin, SIGNAL(send_msg(QString)), this, SLOT(receive_msg(QString))); 
                    

                    Cast to Plugin* instead of Plugin_API*.

                    https://forum.qt.io/topic/113070/qt-code-of-conduct

                    F 1 Reply Last reply
                    0
                    • jsulmJ jsulm

                      @fem_dev said in Send QJsonObject from plugin to main app:

                      What is wrong?

                      Problem is that plugin bellow is Plugin_API* and not Plugin*:

                      connect(plugin, SIGNAL(send_msg(QString)), this, SLOT(receive_msg(QString))); 
                      

                      Cast to Plugin* instead of Plugin_API*.

                      F Offline
                      F Offline
                      fem_dev
                      wrote on last edited by
                      #9

                      @jsulm it's not possible because I have many different plugins that share the same Plugin_API...

                      As you can see in the top, the Plugin_API have all methods that I use in all different plugins.

                      So, when I load all plugins inside a foreach() loop, I have to cast they using the Plugin_API.

                      Each individual plugin inherit the Plugin_API class.
                      And inside each individual plugin I have declared:

                      class PLUGIN_SHARED_EXPORT Plugin: public QObject, public Plugin_API
                      {
                          Q_OBJECT
                          Q_PLUGIN_METADATA(IID "com.lamar.plugin")
                          Q_INTERFACES(Plugin_API)
                      

                      What I'm doing wrong?

                      F 1 Reply Last reply
                      0
                      • F fem_dev

                        @jsulm it's not possible because I have many different plugins that share the same Plugin_API...

                        As you can see in the top, the Plugin_API have all methods that I use in all different plugins.

                        So, when I load all plugins inside a foreach() loop, I have to cast they using the Plugin_API.

                        Each individual plugin inherit the Plugin_API class.
                        And inside each individual plugin I have declared:

                        class PLUGIN_SHARED_EXPORT Plugin: public QObject, public Plugin_API
                        {
                            Q_OBJECT
                            Q_PLUGIN_METADATA(IID "com.lamar.plugin")
                            Q_INTERFACES(Plugin_API)
                        

                        What I'm doing wrong?

                        F Offline
                        F Offline
                        fem_dev
                        wrote on last edited by
                        #10

                        Thank you @SGaist and @jsulm
                        With your help I think that I found a solution! Here is the code:

                        My plugin interface is called Plugin_API. So the plugin_api.h is:

                        #ifndef PLUGIN_API_H
                        #define PLUGIN_API_H
                        
                        #include <QString>
                        #include <QDebug>
                        #include <QJsonObject>
                        #include <QObject>
                        
                        // You have to import and inherit QOBject in the plugin interface
                        class Plugin_API : public QObject
                        {
                            // USE Q_OBJECT MACRO inside the interface
                            Q_OBJECT
                        public:
                            virtual ~Plugin_API() = default;
                        
                            virtual QJsonObject get_data(void) = 0;
                            virtual void set_project_path(const QString project_path) = 0;
                            virtual void open_ui(const QJsonObject ui_data) = 0;
                            virtual void run(const int job_id) = 0;
                        
                            // ===== SIGNALS ===== //
                            // You have to declare the signals in the interface too:
                            virtual void send_msg(const QString msg) = 0;
                        };
                        
                        // Declare our interface:
                        Q_DECLARE_INTERFACE(Plugin_API, "com.lamar.plugin")
                        
                        #endif // PLUGIN_API_H
                        

                        After that, in the plugin.h I have:

                        // Do NOT inherit plublic QObject here:
                        class PLUGINSHARED_EXPORT Plugin: public Plugin_API
                        {
                            // ADD Q_OBJECT MACRO HERE TOO:
                            Q_OBJECT
                            Q_PLUGIN_METADATA(IID "com.lamar.plugin")
                            Q_INTERFACES(Plugin_API)
                        
                           ...
                           // Overide the signal method:
                           signals:
                            void send_msg(const QString msg) override;
                        

                        In my Main Application header main.h I have:

                        public slots:
                            void receive_msg(const QString msg);
                        

                        And finally, the implementaion of the main application slot is:

                        void main_app::receive_msg(const QString msg)
                        {
                            qDebug() << "I RECEIVE THIS MSG: " << msg;
                        }
                        

                        Thank you @SGaist and @jsulm for your help and patience!

                        1 Reply Last reply
                        0

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved