当前位置:网站首页>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】
List of articles
- One 、 Preface
- Two 、 Effect display
- 3、 ... and 、 flow chart
- Four 、 The principle,
- 1、 Define plug-in menu items in plug-in information
- 2、 The plug-in menu item function mapping linked list is defined in the plug-in interface
- 3、 Initialize the plug-in menu item function mapping linked list in the plug-in
- 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
- 5、 Main interface menu item slot function
- 5、 ... and 、 Complete code
One 、 Preface
Through previous posts , We already know that :
- How to create plug-ins ;Qt Plug in development summary – Creation and use of plug-ins
- How to manage plug-ins ;Qt Plug in development summary – Plug in Manager
- How to realize the communication between plug-ins ;Qt Plug in development summary – Communication between plug-ins
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

3、 ... and 、 flow chart

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"]
}

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


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"]
}
边栏推荐
- sklearn clustering聚类
- 持续集成(二)Jenkins基本使用介绍
- Practical task scheduling platform (scheduled task)
- Familiarize you with the "phone book" of cloud network: DNS
- 谷歌尝试为ChromeOS引入密码强度指示器以提升线上安全性
- 撤回就看不到了?三步让你微信防撤回。
- NAT/NAPT地址转换(内外网通信)技术详解【华为eNSP】
- 第七章 在 REST 服务中支持 CORS
- pytorch安装 CUDA对应
- How to convert planning map into vector data with longitude and latitude geojson
猜你喜欢

TI C6000 TMS320C6678 DSP+ Zynq-7045的PS + PL异构多核案例开发手册(3)

FOC电机控制基础

采购实用技巧,5个瓶颈物料的采购方法

How much help does solid state disk have for game operation

gcc/g++与动静库以及gdb

If you want to be good at work, you must first use its tools -c language expansion -- embedded C language (11)

Digital warehouse: iqiyi digital warehouse platform construction practice
原来卡布奇诺信息安全协会是干这个的呀,一起来看看吧。

阿里巴巴一面 :十道经典面试题解析

VS添加作者信息和时间信息的设置
随机推荐
R language ggplot2 visualization: visual line graph, visual line graph for different groups using the group parameter in AES function
[expdp export data] expdp exports a table with 23 rows of records and no lob field. It takes 48 minutes. Please help us have a look
软测(七)性能测试(1)简要介绍
gcc/g++与动静库以及gdb
QCF for deep packet inspection paper summary
Vs add settings for author information and time information
数仓:爱奇艺数仓平台建设实践
81. (cesium home) cesium modifies the gray background (default blue)
The civil construction of the whole line of Guangzhou Metro Line 13 phase II has been completed by 53%, and it is expected to open next year
Super simple! It only takes a few steps to customize the weather assistant for TA!!
No module named ‘win32gui‘
企业数字化转型需要深入研究,不能为了转型而转型
In the changing era of equipment manufacturing industry, how can SCM supply chain management system enable equipment manufacturing enterprises to transform and upgrade
Google tries to introduce password strength indicator for chromeos to improve online security
2023 catering industry exhibition, China catering supply chain exhibition and Jiangxi catering Ingredients Exhibition were held in February
R语言ggplot2可视化:使用ggpubr包的ggdotplot函数可视化点阵图(dot plot)、设置add参数添加均值和标准差竖线、设置error.plot参数实际显示箱体
持续集成(一)基本概念简要介绍
Pytorch installation CUDA corresponding
Basic specification of component development, localstorage and sessionstorage, object data to basic value, prototype chain use
Practical purchasing skills, purchasing methods of five bottleneck materials