当前位置:网站首页>Summary of QT plug-in development -- add plug-in menu in the main interface

Summary of QT plug-in development -- add plug-in menu in the main interface

2022-07-26 15:41:00 Bellerian


One 、 Preface

Through previous posts , We already know that :

The purpose of adding plug-ins is to expand the system , So when the system loads plug-ins , The system should have a plug-in function interface :

  • After the plug-in is loaded successfully , Automatically appear in the main interface ;
  • After the plug-in is uninstalled successfully , Automatically fade from the main interface ;

The purpose of this post : Add plug-ins , Plug in == A menu item (QAction)== Automatically add to the main interface , Click the menu item in the main interface , Call the slot function in the plug-in ;


Two 、 Effect display

 Please add a picture description


3、 ... and 、 flow chart

 Insert picture description here


Four 、 The principle,

1、 Define plug-in menu items in plug-in information

Each plug-in has its own plug-in information , for example :pluginA.jsom

{
    
    "author" : "Wang_JC",
    "date" : "2022/02/16",
    "name" : "pluginA",
    "version" : "1.0.0",
    "des" : " This is a plug-in A",
    "dependencies" : [],
    "action" : ["action_A1","action_A2","action_A3"]
}

 Insert picture description here
We define the plug-in menu item to the... Of the plug-in information action Item in , Above , plug-in unit A There are three menu items , Namely :action_A1、action_A2、action_A3


2、 The plug-in menu item function mapping linked list is defined in the plug-in interface

#include <functional>
using namespace std;

QList<QString> _actionName; // General components Action name 
QList<function<void(bool)> > _actionFunction;   // General components Action The function set 

3、 Initialize the plug-in menu item function mapping linked list in the plug-in

PluginA::PluginA(QObject *parent)
{
    
    _Plugin_Name = "PluginA";

    _actionName.push_back("action_A1");
    _actionName.push_back("action_A2");
    _actionName.push_back("action_A3");

    _actionFunction.push_back(slot_action_A1);
    _actionFunction.push_back(slot_action_A2);
    _actionFunction.push_back(slot_action_A3);
}

4、 When the plug-in manager loads the plug-in, it reads the plug-in information and distributes it to the main interface to create menu items

Plug in loading function : Scan the plug-in information when loading the plug-in , And check the plug-in menu item

void PluginManager::loadPlugin(const QString &filepath)
{
    
    if(!QLibrary::isLibrary(filepath))
        return;

    // Detect dependency 
    if(!managerPrivate->check(filepath))
        return;

    if(managerPrivate->m_loaders.keys().contains(filepath)) {
    
        return;
    }

    // Add plug-ins 
    QPluginLoader *loader = new QPluginLoader(filepath);
    if(loader->load()) {
    
        PluginInterface *plugin = qobject_cast<PluginInterface *>(loader->instance());
        if(plugin) {
    
            // Scan meta information 
            QJsonObject json;
            scanMetaData(filepath,json);	
            deal_metaData_action(loader,json);  // Check whether there is action

            plugin->Info(QString(" %1  Loading successful !").arg(plugin->_Plugin_Name));
            managerPrivate->m_loaders.insert(filepath, loader);
            connect(loader->instance(),SIGNAL(sendMsgToManager(PluginMetaData)),
                    this,SLOT(recMsgFromPlugin(PluginMetaData)));
        }else {
    
            delete loader;
            loader = nullptr;
        }
    }else{
    
        qDebug()<<"loadPlugin:"<<filepath<<loader->errorString();
    }
}

Plug in loading function , This function and Qt Plug in development summary – Plug in Manager This article compares , Slightly adjusted ;


scanning JSON Plug in data in the file

void PluginManager::scanMetaData(const QString &filepath,QJsonObject& json)
{
    
    // Judge whether it is a library ( Suffix validity )
    if(!QLibrary::isLibrary(filepath))
        return;

    // Fetch metadata 
    QPluginLoader *loader = new QPluginLoader(filepath);
    
    json = loader->metaData().value("MetaData").toObject();

    managerPrivate->m_names.insert(filepath, json.value("name").toVariant());
    managerPrivate->m_versions.insert(filepath, json.value("version").toVariant());
    managerPrivate->m_dependencies.insert(filepath, json.value("dependencies").toArray().toVariantList());

    delete loader;
    loader = nullptr;
}

Scan plug-in information function , This function and Qt Plug in development summary – Plug in Manager This article compares , Slightly adjusted ;


Check whether the plug-in information contains action( Plug in menu ), If so, save the plug-in menu and plug-in instance into the plug-in instance of the plug-in manager - Menu item pool

void PluginManager::deal_metaData_action(QPluginLoader* loader,QJsonObject& json)
{
    
    QStringList list;
    if(json.keys().contains("action")) {
    
       QJsonArray JArray = json.value("action").toArray();
       for(int i=0;i<JArray.size();++i) {
    
           list << JArray.at(i).toString();

           MANAGER_ACTION_MAP manager_action_map;
           manager_action_map.action = JArray.at(i).toString();
           manager_action_map.plugin = loader;
           _actionMap.push_back(manager_action_map);
       }
    }

    if(!list.empty()) {
    
        emit sig_actions(list);	// If the plug-in menu item is detected , Send to the main interface 
    }
}

The main interface loads plug-ins , And bind the plug-in menu item signal sent in the plug-in manager

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    
    ui->setupUi(this);
    Init_UI();

    // All the plug-ins detected 
    qDebug()<<"CK_allPluginsName: "<<PluginManager::instance()->CK_allPluginsName();

    // Load one of the plug-ins 
    PluginManager::instance()->loadPlugin(PluginManager::instance()->CK_allPluginsName().value("pluginA"));
    PluginManager::instance()->loadPlugin(PluginManager::instance()->CK_allPluginsName().value("pluginB"));
}

void MainWindow::Init_UI()
{
    
	// The plug-in menu bar is reserved in the main interface Plugins
    menuBar = new QMenuBar(this);
    menuPlugin = new QMenu("Plugins", this);
    menuBar->addMenu(menuPlugin);
    this->setMenuBar(menuBar);

    connect(PluginManager::instance(),&PluginManager::sig_actions,this,&MainWindow::slot_PluginAction);	// The plug-in manager will send the plug-in menu items to the main interface 
}

The main interface is based on the plug-in menu item signal sent by the plug-in manager , Create a menu

void MainWindow::slot_PluginAction(QStringList list)
{
    
    QAction * action = nullptr;
    for(int i=0; i<list.size(); ++i) {
    
        action = new QAction(QIcon(), list.at(i), this);
        menuPlugin->addAction(action);
        connect(action,&QAction::triggered,this,&MainWindow::slot_PluginsAction_trigger);
    }
}

5、 Main interface menu item slot function

  • Get the clicked on the main interface Action The name of ;
  • Go to the plug-in manager menu item pool to match , Find the plug-in instance corresponding to the change menu item ;
  • Convert the instance to an interface pointer , Matching plug-in menu item function mapping linked list ;
  • Find the main interface and click Action Corresponding to the function pointer in the plug-in , And call ;
void MainWindow::slot_PluginsAction_trigger(bool isChecked)
{
    
    QAction* action = qobject_cast<QAction*>(sender());
    for(int i=0; i<PluginManager::instance()->_actionMap.size(); ++i) {
     // Traverse the plug-in manager action The mapping table 
        if(PluginManager::instance()->_actionMap.at(i).action == action->text()) {
      // The mapping table matches Action Corresponding method 
            PluginInterface* plugin = qobject_cast<PluginInterface *>(PluginManager::instance()->_actionMap.at(i).plugin->instance());  // Get the action Corresponding interface pointer 
            if(plugin) {
    
                for(int j=0; j<plugin->_actionName.size(); ++j) {
       // Traverse the action name 
                    if(plugin->_actionName[j] == action->text()) {
    
                        plugin->_actionFunction[j](true);
                        break;
                    }
                }
            }
            break;
        }
    }
}


5、 ... and 、 Complete code

1、 Engineering structure

 Insert picture description here


 Insert picture description here


2、PluginApp

file :PluginApp.pro

TEMPLATE = subdirs

SUBDIRS += \
    MainWin \
    pluginA \
    pluginB

3、PluginInterface.h( Plug-in interface )

#ifndef PLUGININTERFACE_H
#define PLUGININTERFACE_H

#include <QObject>
#include <QJsonObject>
#include <functional>
using namespace std;

struct PluginMetaData
{
    
    QString from;   // Source 
    QString dest;   // Where does the message go 
    QString msg;    // news 

    QObject* object = nullptr;
    QJsonObject info = QJsonObject();
};
Q_DECLARE_METATYPE(PluginMetaData); // Ensure that the type can be transmitted through the signal slot 

// Defining interfaces 
class PluginInterface : public QObject
{
    
    Q_OBJECT
public:
    virtual ~PluginInterface(){
    }
    virtual void Info(QString) = 0;

    virtual void recMsgFromManager(PluginMetaData) = 0; // Receive messages from the plug-in manager 
    virtual void sendMsgToManager(PluginMetaData) = 0;  // Send a message to the plug-in manager 

public:
    QString _Plugin_Name;

public:
    QList<QString> _actionName; // General components Action name 
    QList<function<void(bool)> > _actionFunction;   // General components Action The function set 

};

// Must be a unique identifier 
#define PluginInterface_iid "Examples.Plugin.PluginInterface"

QT_BEGIN_NAMESPACE
Q_DECLARE_INTERFACE(PluginInterface,PluginInterface_iid)
QT_END_NAMESPACE

#endif // PLUGININTERFACE_H


4、MainWin

file :MainWin.pro

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    PluginManager.cpp \
    main.cpp \
    mainwindow.cpp

HEADERS += \
    ../Plugin_Interface/PluginInterface.h \
    PluginManager.h \
    mainwindow.h

FORMS += \
    mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${
    TARGET}/bin
else: unix:!android: target.path = /opt/$${
    TARGET}/bin
!isEmpty(target.path): INSTALLS += target

file :mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDebug>
#include "PluginManager.h"
#include <QDir>
#include <QMenuBar>

QT_BEGIN_NAMESPACE
namespace Ui {
     class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    void Init_UI();

    QMenuBar* menuBar;
    QMenu * menuPlugin;

private slots:
    void slot_PluginAction(QStringList);    // Add the plug-in Action
    void slot_PluginsAction_trigger(bool isChecked);    // Response plug-in Action

private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

file :mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    
    ui->setupUi(this);
    Init_UI();

    // All the plug-ins detected 
    qDebug()<<"CK_allPluginsName: "<<PluginManager::instance()->CK_allPluginsName();

    // Load one of the plug-ins 
    PluginManager::instance()->loadPlugin(PluginManager::instance()->CK_allPluginsName().value("pluginA"));
    PluginManager::instance()->loadPlugin(PluginManager::instance()->CK_allPluginsName().value("pluginB"));
}

MainWindow::~MainWindow()
{
    
    delete ui;
}

void MainWindow::Init_UI()
{
    
    menuBar = new QMenuBar(this);
    menuPlugin = new QMenu("Plugins", this);
    menuBar->addMenu(menuPlugin);
    this->setMenuBar(menuBar);

    connect(PluginManager::instance(),&PluginManager::sig_actions,this,&MainWindow::slot_PluginAction);
}

void MainWindow::slot_PluginAction(QStringList list)
{
    
    QAction * action = nullptr;
    for(int i=0; i<list.size(); ++i) {
    
        action = new QAction(QIcon(), list.at(i), this);
        menuPlugin->addAction(action);
        connect(action,&QAction::triggered,this,&MainWindow::slot_PluginsAction_trigger);
    }
}
void MainWindow::slot_PluginsAction_trigger(bool isChecked)
{
    
    QAction* action = qobject_cast<QAction*>(sender());
    for(int i=0; i<PluginManager::instance()->_actionMap.size(); ++i) {
     // Traverse the plug-in manager action The mapping table 
        if(PluginManager::instance()->_actionMap.at(i).action == action->text()) {
      // The mapping table matches Action Corresponding method 
            PluginInterface* plugin = qobject_cast<PluginInterface *>(PluginManager::instance()->_actionMap.at(i).plugin->instance());  // Get the action Corresponding interface pointer 
            if(plugin) {
    
                for(int j=0; j<plugin->_actionName.size(); ++j) {
       // Traverse the action name 
                    if(plugin->_actionName[j] == action->text()) {
    
                        plugin->_actionFunction[j](true);
                        break;
                    }
                }
            }
            break;
        }
    }
}

file :PluginManager.h

#ifndef PLUGINMANAGER_H
#define PLUGINMANAGER_H

#include "../Plugin_Interface/PluginInterface.h"
#include <QObject>
#include <QPluginLoader>
#include <QVariant>
#include <QAction>

typedef struct manager_action_map
{
    
    QString action;
    QPluginLoader* plugin;
}MANAGER_ACTION_MAP;

class PluginManager : public QObject
{
    
    Q_OBJECT
public:
    explicit PluginManager(QObject *parent = nullptr);
    ~PluginManager();

    static PluginManager *instance(){
    
         if(m_instance==nullptr)
             m_instance=new PluginManager();
         return m_instance;
     }

public:
    QList<MANAGER_ACTION_MAP> _actionMap;
    void deal_metaData_action(QPluginLoader* loader,QJsonObject& json);


public:
    // scanning JSON Plug in metadata in the file 
    void scanMetaData(const QString &filepath,QJsonObject& json);

     // Load all plug-ins 
     void loadAllPlugins();

     // Load one of the plug-ins 
     void loadPlugin(const QString &filepath);

     // Uninstall all plug-ins 
     void unloadAllPlugins();

     // Uninstall a plug-in 
     void unloadPlugin(const QString &filepath);

     // Get all plug-in names 
     QList<QVariant> allPluginsName();

     // Get all plug-ins 
     QList<QPluginLoader *> allPlugins();

     // Get a plug-in name 
     QVariant getPluginName(QPluginLoader *loader);

     // Get the plug-in by name 
     QPluginLoader* getPlugin(const QString &name);

     // Get the names of all plug-ins in the Library 
     QHash<QString,QString> CK_allPluginsName();

signals:
     void sig_actions(QStringList);

public slots:
     void recMsgFromPlugin(PluginMetaData);

private:
     static PluginManager *m_instance;

     class PluginsManagerPrivate;
     PluginsManagerPrivate *managerPrivate;
};

#endif // PLUGINMANAGER_H

file :PluginManager.cpp

#include "PluginManager.h"
#include <QDir>
#include <QCoreApplication>
#include <QJsonArray>
#include <QDebug>

PluginManager* PluginManager::m_instance=nullptr;

class PluginManager::PluginsManagerPrivate
{
    
public:
    PluginsManagerPrivate()
    {
    
        m_names.clear();
        m_versions.clear();
        m_dependencies.clear();
        m_loaders.clear();
    }
    ~PluginsManagerPrivate(){
    }

    QHash<QString, QVariant> m_names;               // The plugin path -- The plug-in name 
    QHash<QString, QVariant> m_versions;            // The plugin path -- The plug-in version 
    QHash<QString, QVariantList> m_dependencies;    // The plugin path -- Other plug-ins on which the plug-in depends 
    QHash<QString, QPluginLoader *> m_loaders;      // The plugin path --QPluginLoader example 

    bool check(const QString &filepath)             // Plug in dependency detection 
    {
    
        bool status = true;

        foreach (QVariant item, m_dependencies.value(filepath)) {
    
            QVariantMap map = item.toMap();
            //  Dependent plug-in name 、 edition 、 route 
            QVariant name = map.value("name");
            QVariant version = map.value("version");
            QString path = m_names.key(name);

            /**********  Check whether the plug-in depends on other plug-ins  **********/
            //  Check the plug-in name first 
            if (!m_names.values().contains(name)) {
    
                qDebug() << Q_FUNC_INFO << " Missing dependency:" << name.toString() << "for plugin" << path;
                status = false;
                continue;
            }

            //  Then check the plug-in version 
            if (m_versions.value(path) != version) {
    
                qDebug() << Q_FUNC_INFO << " Version mismatch:" << name.toString() << "version"
                         << m_versions.value(m_names.key(name)).toString() << "but" << version.toString() << "required for plugin" << path;
                status = false;
                continue;
            }

            //  then , Check whether the dependent plug-in depends on another plug-in 
            if (!check(path)) {
    
                qDebug() << Q_FUNC_INFO << "Corrupted dependency:" << name.toString() << "for plugin" << path;
                status = false;
                continue;
            }
        }

        return status;
    }

};

PluginManager::PluginManager(QObject *parent) : QObject(parent)
{
    
    managerPrivate = new PluginsManagerPrivate;
}
PluginManager::~PluginManager()
{
    
    delete managerPrivate;
}

void PluginManager::loadAllPlugins()
{
    
    QDir pluginsDir(qApp->applicationDirPath());    //pluginsDir: "../build-xxx-debug/debug"
    if(pluginsDir.dirName().toLower() == "debug" ||
            pluginsDir.dirName().toLower() == "release") {
    
        pluginsDir.cdUp();  //pluginsDir: "../build-xxx-debug"
        pluginsDir.cdUp();  //pluginsDir: "../"
    }
    pluginsDir.cd("plugins");

    QFileInfoList pluginsInfo = pluginsDir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot);

    // Add plug-ins 
    for(QFileInfo fileinfo : pluginsInfo)
        loadPlugin(fileinfo.absoluteFilePath());
}

void PluginManager::scanMetaData(const QString &filepath,QJsonObject& json)
{
    
    // Judge whether it is a library ( Suffix validity )
    if(!QLibrary::isLibrary(filepath))
        return;

    // Fetch metadata 
    QPluginLoader *loader = new QPluginLoader(filepath);

    //qDebug()<<loader->metaData().keys();
    json = loader->metaData().value("MetaData").toObject();
// for(int i=0; i<json.keys().size(); ++i) {
    
// qDebug()<<json.keys().at(i)<< " : "<<json.value(json.keys().at(i));
// }

    managerPrivate->m_names.insert(filepath, json.value("name").toVariant());
    managerPrivate->m_versions.insert(filepath, json.value("version").toVariant());
    managerPrivate->m_dependencies.insert(filepath, json.value("dependencies").toArray().toVariantList());

    delete loader;
    loader = nullptr;
}

void PluginManager::loadPlugin(const QString &filepath)
{
    
    if(!QLibrary::isLibrary(filepath))
        return;

    // Detect dependency 
    if(!managerPrivate->check(filepath))
        return;

    if(managerPrivate->m_loaders.keys().contains(filepath)) {
    
        return;
    }

    // Add plug-ins 
    QPluginLoader *loader = new QPluginLoader(filepath);
    if(loader->load()) {
    
        PluginInterface *plugin = qobject_cast<PluginInterface *>(loader->instance());
        if(plugin) {
    
            // Scan meta information 
            QJsonObject json;
            scanMetaData(filepath,json);
            deal_metaData_action(loader,json);  // Check whether there is action

            plugin->Info(QString(" %1  Loading successful !").arg(plugin->_Plugin_Name));
            managerPrivate->m_loaders.insert(filepath, loader);
            connect(loader->instance(),SIGNAL(sendMsgToManager(PluginMetaData)),
                    this,SLOT(recMsgFromPlugin(PluginMetaData)));
        }else {
    
            delete loader;
            loader = nullptr;
        }
    }else{
    
        qDebug()<<"loadPlugin:"<<filepath<<loader->errorString();
    }
}

void PluginManager::unloadAllPlugins()
{
    
    for(QString filepath : managerPrivate->m_loaders.keys())
        unloadPlugin(filepath);
}

void PluginManager::unloadPlugin(const QString &filepath)
{
    
    if(!managerPrivate->m_loaders.keys().contains(filepath)) {
    
        return;
    }

    QPluginLoader *loader = managerPrivate->m_loaders.value(filepath);
    // Uninstall plugins , And remove from the internal data structure 
    if(loader->unload()) {
    
        PluginInterface *plugin = qobject_cast<PluginInterface *>(loader->instance());
        if(plugin) {
    
            plugin->Info(" The plug-in uninstalled successfully !");
            managerPrivate->m_loaders.remove(filepath);
            delete loader;
            loader = nullptr;
        }
    }
}

QList<QPluginLoader *> PluginManager::allPlugins()
{
    
    return managerPrivate->m_loaders.values();
}

QList<QVariant> PluginManager::allPluginsName()
{
    
    return managerPrivate->m_names.values();
}

QVariant PluginManager::getPluginName(QPluginLoader *loader)
{
    
    if(loader)
        return managerPrivate->m_names.value(managerPrivate->m_loaders.key(loader));
    else
        return "";
}

QPluginLoader *PluginManager::getPlugin(const QString &name)
{
    
    return managerPrivate->m_loaders.value(managerPrivate->m_names.key(name));
}

void PluginManager::recMsgFromPlugin(PluginMetaData metaData)
{
    
    auto loader = getPlugin(metaData.dest); // Target plug-in 
    if(loader) {
    
        auto interface = qobject_cast<PluginInterface*>(loader->instance());
        if(interface) {
    
            interface->recMsgFromManager(metaData); // Forward to the corresponding plug-in 
        }
    }
}

QHash<QString,QString> PluginManager::CK_allPluginsName()
{
    
    QDir pluginsDir(qApp->applicationDirPath());    //pluginsDir: "../build-xxx-debug/debug"
    if(pluginsDir.dirName().toLower() == "debug" ||
            pluginsDir.dirName().toLower() == "release") {
    
        pluginsDir.cdUp();  //pluginsDir: "../build-xxx-debug"
        pluginsDir.cdUp();  //pluginsDir: "../"
    }
    pluginsDir.cd("plugins");

    QFileInfoList pluginsInfo = pluginsDir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot);

    // Plug ins in the Library 
    QHash<QString,QString> pluginNames;
    for(QFileInfo fileinfo : pluginsInfo){
    
        if(fileinfo.fileName().contains(".dll")) {
    
            QString pluginName = fileinfo.fileName().mid(0,fileinfo.fileName().size()-4);
            QString pluginPath = fileinfo.filePath();
            pluginNames.insert(pluginName,pluginPath);
        }
    }

    return pluginNames;
}

void PluginManager::deal_metaData_action(QPluginLoader* loader,QJsonObject& json)
{
    
    QStringList list;
    if(json.keys().contains("action")) {
    
       QJsonArray JArray = json.value("action").toArray();
       for(int i=0;i<JArray.size();++i) {
    
           list << JArray.at(i).toString();

           MANAGER_ACTION_MAP manager_action_map;
           manager_action_map.action = JArray.at(i).toString();
           manager_action_map.plugin = loader;
           _actionMap.push_back(manager_action_map);
       }
    }

    if(!list.empty()) {
    
        emit sig_actions(list);
    }
}


5、pluginA

file :pluginA.pro

QT += widgets

TEMPLATE = lib          # Indicates that the makefile It's a lib Of makefile
CONFIG += plugin        # An application is a plug-in 

TARGET = pluginA        # The plug-in name 
DESTDIR = ../plugins    #  The output directory 

HEADERS += \
    ../Plugin_Interface/PluginInterface.h \
    pluginA.h

SOURCES += \
    pluginA.cpp

DISTFILES += \
    pluginA.json

file :pluginA.h

#ifndef PLUGINA_H
#define PLUGINA_H

#include <QObject>
#include <QtPlugin>
#include <QDebug>
#include "../Plugin_Interface/PluginInterface.h"

class PluginA : public PluginInterface
{
    
    Q_OBJECT
    Q_INTERFACES(PluginInterface)
    Q_PLUGIN_METADATA(IID PluginInterface_iid FILE "pluginA.json")
public:
    explicit  PluginA(QObject *parent = nullptr);
    void Info(QString info);

    void recMsgFromManager(PluginMetaData metaData);

signals:
    void sendMsgToManager(PluginMetaData);

public slots:
    static void slot_action_A1(bool isChecked);
    static void slot_action_A2(bool isChecked);
    static void slot_action_A3(bool isChecked);

};

#endif // PLUGINA_H

file :pluginA.cpp

#include "pluginA.h"

PluginA::PluginA(QObject *parent)
{
    
    _Plugin_Name = "PluginA";

    _actionName.push_back("action_A1");
    _actionName.push_back("action_A2");
    _actionName.push_back("action_A3");

    _actionFunction.push_back(slot_action_A1);
    _actionFunction.push_back(slot_action_A2);
    _actionFunction.push_back(slot_action_A3);
}

void PluginA::Info(QString info)
{
    
    qDebug()<<info;
}

void PluginA::recMsgFromManager(PluginMetaData metaData)
{
    
    qDebug()<<" plug-in unit A Message received :"<<metaData.msg;
}

void PluginA::slot_action_A1(bool isChecked)
{
    
    qDebug()<<"PluginA::slot_action_A1()";
}
void PluginA::slot_action_A2(bool isChecked)
{
    
    qDebug()<<"PluginA::slot_action_A2()";
}
void PluginA::slot_action_A3(bool isChecked)
{
    
    qDebug()<<"PluginA::slot_action_A3()";
}

file :pluginA.json

{
    
    "author" : "Wang_JC",
    "date" : "2022/02/16",
    "name" : "pluginA",
    "version" : "1.0.0",
    "des" : " This is a plug-in A",
    "dependencies" : [],
    "action" : ["action_A1","action_A2","action_A3"]
}


6、pluginB

file :pluginB.pro

QT += widgets

TEMPLATE = lib          # Indicates that the makefile It's a lib Of makefile
CONFIG += plugin        # An application is a plug-in 

TARGET = pluginB        # The plug-in name 
DESTDIR = ../plugins    #  The output directory 

HEADERS += \
    ../Plugin_Interface/PluginInterface.h \
    pluginB.h

SOURCES += \
    pluginB.cpp

DISTFILES += \
    pluginB.json

file :pluginB.h

#ifndef PLUGINB_H
#define PLUGINB_H

#include <QObject>
#include <QtPlugin>
#include <QDebug>
#include "../Plugin_Interface/PluginInterface.h"

class PluginB : public PluginInterface
{
    
    Q_OBJECT
    Q_INTERFACES(PluginInterface)
    Q_PLUGIN_METADATA(IID PluginInterface_iid FILE "pluginB.json")
public:
    explicit  PluginB(QObject *parent = nullptr);
    void Info(QString info);

public:
    void recMsgFromManager(PluginMetaData metaData);

signals:
    void sendMsgToManager(PluginMetaData);

public slots:
    static void slot_action_B1(bool isChecked);
    static void slot_action_B2(bool isChecked);
    static void slot_action_B3(bool isChecked);

};

#endif // PLUGINB_H

file :pluginB.cpp

#include "pluginB.h"

PluginB::PluginB(QObject *parent)
{
    
    _Plugin_Name = "PluginB";

    _actionName.push_back("action_B1");
    _actionName.push_back("action_B2");
    _actionName.push_back("action_B3");

    _actionFunction.push_back(slot_action_B1);
    _actionFunction.push_back(slot_action_B2);
    _actionFunction.push_back(slot_action_B3);
}

void PluginB::Info(QString info)
{
    
    qDebug()<<info;
}

void PluginB::recMsgFromManager(PluginMetaData metaData)
{
    
    qDebug()<<" plug-in unit B Message received :"<<metaData.msg;
}

void PluginB::slot_action_B1(bool isChecked)
{
    
    qDebug()<<"PluginB::slot_action_B1()";
}
void PluginB::slot_action_B2(bool isChecked)
{
    
    qDebug()<<"PluginB::slot_action_B2()";
}
void PluginB::slot_action_B3(bool isChecked)
{
    
    qDebug()<<"PluginB::slot_action_B3()";
}

file :pluginB.json

{
    
    "author" : "Wang_JC",
    "date" : "2022/02/16",
    "name" : "pluginB",
    "version" : "1.0.0",
    "des" : " This is a plug-in B",
    "dependencies" : [],
    "action" : ["action_B1","action_B2","action_B3"]
}


原网站

版权声明
本文为[Bellerian]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/201/202207181633330004.html

随机推荐