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
Forum Updated to NodeBB v4.3 + New Features

Send QJsonObject from plugin to main app

Scheduled Pinned Locked Moved Solved General and Desktop
10 Posts 3 Posters 351 Views 1 Watching
  • 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 10 Dec 2019, 14:04 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
      11 Dec 2019, 13:50

      @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 11 Dec 2019, 15:00 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
      • S Offline
        S Offline
        SGaist
        Lifetime Qt Champion
        wrote on 10 Dec 2019, 21:01 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 11 Dec 2019, 13:04
        1
        • S SGaist
          10 Dec 2019, 21:01

          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 11 Dec 2019, 13:04 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?

          J 1 Reply Last reply 11 Dec 2019, 13:06
          0
          • F fem_dev
            11 Dec 2019, 13:04

            @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?

            J Offline
            J Offline
            jsulm
            Lifetime Qt Champion
            wrote on 11 Dec 2019, 13:06 last edited by jsulm 12 Nov 2019, 13:09
            #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 11 Dec 2019, 13:23
            0
            • J jsulm
              11 Dec 2019, 13:06

              @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 11 Dec 2019, 13:23 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?

              J 1 Reply Last reply 11 Dec 2019, 13:25
              0
              • F fem_dev
                11 Dec 2019, 13:23

                @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?

                J Offline
                J Offline
                jsulm
                Lifetime Qt Champion
                wrote on 11 Dec 2019, 13:25 last edited by jsulm 12 Nov 2019, 13:25
                #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 11 Dec 2019, 13:38
                0
                • J jsulm
                  11 Dec 2019, 13:25

                  @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 11 Dec 2019, 13:38 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'
                  
                  J 1 Reply Last reply 11 Dec 2019, 13:43
                  0
                  • F fem_dev
                    11 Dec 2019, 13:38

                    @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'
                    
                    J Offline
                    J Offline
                    jsulm
                    Lifetime Qt Champion
                    wrote on 11 Dec 2019, 13:43 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 11 Dec 2019, 13:50
                    0
                    • J jsulm
                      11 Dec 2019, 13:43

                      @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 11 Dec 2019, 13:50 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 11 Dec 2019, 15:00
                      0
                      • F fem_dev
                        11 Dec 2019, 13:50

                        @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 11 Dec 2019, 15:00 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

                        5/10

                        11 Dec 2019, 13:23

                        • Login

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