CTK框架(十):PluginAdmin插件

目录

1.引言

2.实现原理

3.实际应用

3.1.界面控制

3.2.访问服务管理插件

4.总结


1.引言

        在CTK框架(三): 插件的安装讲解了插件的安装、启动、停止和卸载方法,对于一个插件可以这样写;但是如果是在一个大型的应用程序中,里面有很多插件,就需要一个管理这些插件的服务,CTK官方就提供给了一个:PluginAdmin。

        PluginAdmin它本身也是一个插件,它提供服务的接口有:

struct PluginAdmin
{virtual ~PluginAdmin() {}virtual void installAllPlugin() = 0;virtual void startAllPlugin() = 0;virtual void stopAllPlugin() = 0;virtual void uninstallAllPlugin() = 0;
};
  • installAllPlugin:安装系统所有插件
  • startAllPlugin:启动系统所有插件
  • stopAllPlugin:停止系统所有插件
  • uninstallAllPlugin: 卸载系统所有插件

2.实现原理

        跟其它CTK插件服务的一样,在PluginAdmin插件里面实现了接口PluginAdmin,代码如下:
pluginadminservice.h

#ifndef PLUGINADMINSERVICE_H
#define PLUGINADMINSERVICE_H#include <QObject>
#include <service/pluginadmin/pluginAdmin.h>
#include <ctkPluginContext.h>
#include <service/event/ctkEventAdmin.h>class PluginAdminService :public QObject,public PluginAdmin
{Q_OBJECTQ_INTERFACES(PluginAdmin)public:explicit PluginAdminService(ctkPluginContext* context,QObject *parent = nullptr);~PluginAdminService();public:void installAllPlugin() Q_DECL_OVERRIDE;void startAllPlugin() Q_DECL_OVERRIDE;void stopAllPlugin() Q_DECL_OVERRIDE;void uninstallAllPlugin() Q_DECL_OVERRIDE;signals:private slots:private:ctkPluginContext *m_context;ctkDictionary m_dictionary;ctkProperties m_properties;//事件管理服务插件ctkEventAdmin *m_eventAdmin;QSharedPointer<ctkPluginFramework> m_framework;QStringList m_libFilter;QString m_path;
};#endif // PLUGINADMINSERVICE_H

pluginadminservice.cpp

#include "pluginadminservice.h"
#include <service/event/ctkEventConstants.h>
#include <QCoreApplication>
#include <QDirIterator>
#include <QJsonArray>
#include <QThread>
#include <ctkPluginException.h>
#include <ctkPluginFrameworkFactory.h>
#include <ctkPluginFrameworkLauncher.h>PluginAdminService::PluginAdminService(ctkPluginContext* context, QObject* parent) :QObject(parent),m_context(context),m_eventAdmin(nullptr),m_framework(nullptr)
{//注册插件管理服务context->registerService<PluginAdmin>(this);ctkServiceReference eventRef = context->getServiceReference<ctkEventAdmin>();m_eventAdmin = qobject_cast<ctkEventAdmin*>(context->getService(eventRef));if (eventRef) {context->ungetService(eventRef);}m_path = QCoreApplication::applicationDirPath() + "/plugins";ctkPluginFrameworkLauncher::addSearchPath(m_path, true);
#if defined(Q_OS_WIN)m_libFilter << "*.dll";
#elif defined(Q_OS_LINUX)m_libFilter << "*.so";
#elif defined(Q_OS_MAC)m_libFilter << "*.dylib";
#endif
}PluginAdminService::~PluginAdminService()
{
}void PluginAdminService::installAllPlugin()
{QDirIterator dirIter(m_path, m_libFilter, QDir::Files);QString fileLocation;while (dirIter.hasNext()) {try {fileLocation = dirIter.next();if (!fileLocation.contains(QString("pluginadmin"))) {m_context->installPlugin(QUrl::fromLocalFile(fileLocation));qDebug() << QString::fromLocal8Bit("1.1 安装插件:") << fileLocation;}else {qDebug() << QString::fromLocal8Bit("1.2 未重复安装插件:") << fileLocation;}}catch (const ctkPluginException& exc) {qCritical() << fileLocation << exc.what();}}
}void PluginAdminService::startAllPlugin()
{foreach(const QSharedPointer<ctkPlugin> &plugin, m_context->getPlugins()) {try {if (QString("system.plugin") != plugin->getSymbolicName()&& QString("pluginadmin") != plugin->getSymbolicName()) {plugin->start();qDebug() << QString::fromLocal8Bit("2.1 启动插件:") << plugin->getSymbolicName();}else {qDebug() << QString::fromLocal8Bit("2.2 未重复启动插件:") << plugin->getSymbolicName();}}catch (const ctkPluginException& exc) {qCritical() << exc.what();}}
}void PluginAdminService::stopAllPlugin()
{foreach(const QSharedPointer<ctkPlugin> &plugin, m_context->getPlugins()) {try {if (QString("system.plugin") != plugin->getSymbolicName()&& QString("pluginadmin") != plugin->getSymbolicName()) {qDebug() << QString::fromLocal8Bit("3.1 停止插件:") << plugin->getSymbolicName();plugin->stop();}else {qDebug() << QString::fromLocal8Bit("3.2 未停止运行插件:") << plugin->getSymbolicName();}}catch (const ctkPluginException& exc) {qCritical() << exc.what();}}
}void PluginAdminService::uninstallAllPlugin()
{foreach(const QSharedPointer<ctkPlugin> &plugin, m_context->getPlugins()) {try {if (QString("system.plugin") != plugin->getSymbolicName()&& QString("pluginadmin") != plugin->getSymbolicName()) {qDebug() << QString::fromLocal8Bit("4.1 卸载插件:") << plugin->getSymbolicName();plugin->uninstall();}}catch (const ctkPluginException& exc) {qCritical() << exc.what();}}foreach(const QSharedPointer<ctkPlugin> &plugin, m_context->getPlugins()) {qDebug() << QString::fromLocal8Bit("4.2 未卸载插件:") << plugin->getSymbolicName();}
}

其实实现也不难,以安装插件的installAllPlugin函数实现为例,如果是windows,就是在应用程序的插件目录下面循环查找.dll文件,依次调用ctkPluginContext的installPlugin函数,安装插件,所以这个插件目录不能存放不是插件的.dll文件,否则就会出现安装异常。

启动器

pluginadminactivator.h

#ifndef PLUGINADMINACTIVATOR_H
#define PLUGINADMINACTIVATOR_H#include "pluginadminthread.h"
#include "pluginadmindialog.h"#include <ctkPluginActivator.h>#include <QObject>class PluginAdminActivator : public QObject, public ctkPluginActivator
{Q_OBJECTQ_INTERFACES(ctkPluginActivator)Q_PLUGIN_METADATA(IID "pluginadmin")public:PluginAdminActivator();void start(ctkPluginContext* context) Q_DECL_OVERRIDE;void stop(ctkPluginContext* context) Q_DECL_OVERRIDE;private:QThread *m_pluginAdminThread;PluginAdminDialog* m_pluginAdminDialog;
};#endif // PLUGINADMINACTIVATOR_H

pluginadminactivator.cpp

#include "pluginadminactivator.h"
#include <QDebug>PluginAdminActivator::PluginAdminActivator() :m_pluginAdminThread(nullptr)
{}void PluginAdminActivator::start(ctkPluginContext* context)
{qDebug() << "插件启动";m_pluginAdminThread = new PluginAdminThread(context);m_pluginAdminThread->start();m_pluginAdminDialog = new PluginAdminDialog(context);m_pluginAdminDialog->setWindowTitle(QString::fromLocal8Bit("插件管理器"));m_pluginAdminDialog->show();
}void PluginAdminActivator::stop(ctkPluginContext* context)
{Q_UNUSED(context)if (m_pluginAdminThread){m_pluginAdminThread->exit();m_pluginAdminThread->wait();m_pluginAdminThread->deleteLater();m_pluginAdminThread = nullptr;}
}#if (QT_VERSION < QT_VERSION_CHECK(5,0,0))
Q_EXPORT_PLUGIN2(PluginAdmin, PluginAdminActivator)
#endif

3.实际应用

3.1.界面控制

PluginAdmin提供了一个简单的插件管理界面,加载PluginAdmin插件会弹出如图所示界面:

直接在界面就可以管理系统的所有插件了。

3.2.访问服务管理插件

跟CTK插件访问服务的方式一样,访问PluginAdmin提供的服务,一般在系统退出的时候调用,代码如下:

//系统退出函数
void MainWindow::closeEvent(QCloseEvent* e)
{ctkServiceReference reference = context->getServiceReference<PluginAdmin>();if (reference ) {PluginAdmin* pPluginManager = context->getService<PluginAdmin>(reference);assert(pPluginManager );pPluginManager->stopAllPlugin();}
}

4.总结

        PluginAdmin是CTK插件框架中的一个重要组件,它负责管理插件的生命周期和插件之间的交互。通过PluginAdmin,可以很方便的管理插件。这使得CTK插件框架能够支持高度模块化和可扩展的应用程序开发。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/422444.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从100G到400G:利用多模光纤升级数据中心网络

数据中心网络的持续发展 数据中心网络的持续发展涵盖了两个关键方面。首先&#xff0c;必须应对由机器学习和物联网等数据密集型应用所带来的带宽和流量需求的增长挑战&#xff0c;这些应用正在推动现有10G和40G链路的升级&#xff1b;其次&#xff0c;为了满足日益提升的可持…

好用的视频压缩工具有哪些?这4款千万不要错过

视频压缩的方法有很多种&#xff0c;像我们手机里的视频剪辑工具&#xff0c;手机和电脑自带的压缩功能&#xff0c;在线压缩网站&#xff0c;专业压缩软件压缩等等。不同的场景和需求下大家可以选择不同的工具&#xff0c;但是如果碰到需要大量和经常压缩视频的话&#xff0c;…

JS_阿里云oss视频上传后,如何获取视频封面

当您需要获取视频封面、提取视频关键帧图像进行视频编辑&#xff0c;或者提取视频中特定场景帧图像用于视频监控等时&#xff0c;可以将视频上传至OSS存储空间&#xff0c;然后通过本文所示方法进行视频截帧。 使用示例 本文示例使用的Bucket为杭州地域名为oss-console-img-de…

python绘制3D瀑布图

成品&#xff1a; 代码&#xff1a; import matplotlib.pyplot as plt import matplotlib.ticker as ticker from mpl_toolkits.mplot3d.art3d import Poly3DCollection import numpy as npdef line_3d(x, y, z, x_label_indexs):"""在y轴的每个点&#xff0c;…

Android Framework(五)WMS-窗口显示流程——窗口布局与绘制显示

文章目录 relayoutWindow流程概览应用端处理——ViewRootImpl::setView -> relayoutWindowViewRootImpl::setViewViewRootImpl::performTraversalsViewRootImpl::relayoutWindow Surface的创建WindowManagerService::relayoutWindow了解容器类型和Buff类型的SurfaceBuff类型…

【机器学习】高斯网络的基本概念和应用领域以及在python中的实例

引言 高斯网络&#xff08;Gaussian Network&#xff09;通常指的是一个概率图模型&#xff0c;其中所有的随机变量&#xff08;或节点&#xff09;都遵循高斯分布 文章目录 引言一、高斯网络&#xff08;Gaussian Network&#xff09;1.1 高斯过程&#xff08;Gaussian Proces…

【JSP `page` 指令详解:构建高效的动态网页】

JSP page 指令详解&#xff1a;构建高效的动态网页 在 JavaServer Pages (JSP) 中&#xff0c;<% page %> 指令用于配置 JSP 页面的一些关键属性。这些属性控制着页面的行为和生成的 Servlet 的特性&#xff0c;例如字符编码、是否启用会话、缓冲区大小等。合理使用 page…

鸿蒙OpenHarmony【轻量系统芯片移植】内核移植

移植芯片架构 芯片架构的移植是内核移植的基础&#xff0c;在OpenHarmony中芯片架构移植是可选过程&#xff0c;如果当前OpenHarmony已经支持对应芯片架构则不需要移植操作&#xff0c;在“liteos_m/arch”目录下可看到当前已经支持的架构&#xff0c;如表1&#xff1a; 表1 …

羽毛球关键点检测系统源码分享

羽毛球关键点检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer…

openSSL 如何降版本

文章目录 前言openSSL 如何降版本1. 卸载2. 安装新的openssl版本3. 验证 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差&#xff0c;实在白嫖的话&…

Linux IO模型(多路复用)

【1】Linux IO模型&#xff1a;IO多路复用 场景假设二 假设妈妈有三个孩子&#xff0c;分别不同的房间里睡觉&#xff0c;需要及时获知每个孩子是否醒了&#xff0c;如何做&#xff1f; 1.一直在一个房间呆着&#xff1a;看不到其他两个孩子 2.每个房间不停的看&#xff1a;可以…

WebGL系列教程五(使用索引绘制彩色立方体)

目录 1 前言2 立方体3 开始绘制3.1 声明顶点和颜色3.2 使用索引绘制3.3 效果3.4 完整代码 4 总结 1 前言 上一讲我们讲了如何绘制彩色的三角形&#xff0c;这一讲我们来说如何绘制立方体。为什么几乎所有的WebGL教程总是从开始绘制三角形开始&#xff0c;因为三角形是最小的面&…

服务器模型 Reactor 和 Proactor

Proactor 具体流程如下&#xff1a; 处理器发起异步操作&#xff0c;并关注 IO 完成事件&#xff1b;事件分离器等待操作完成事件&#xff1b;分离器等待过程中&#xff0c;内核并行执行实际的 IO 操作&#xff0c;并将结果存储入用户自定义的缓冲区&#xff0c;最后通知事件分…

【C++】C++ STL 探索:List使用与背后底层逻辑

C语法相关知识点可以通过点击以下链接进行学习一起加油&#xff01;命名空间缺省参数与函数重载C相关特性类和对象-上篇类和对象-中篇类和对象-下篇日期类C/C内存管理模板初阶String使用String模拟实现Vector使用及其模拟实现 本文将通过模拟实现List&#xff0c;从多个角度深入…

60 道 MySQL 精选面试题

基础 #1、关系型和非关系型数据库的区别&#xff1f; 关系型数据库的优点 容易理解&#xff0c;因为它采用了关系模型来组织数据。可以保持数据的一致性。数据更新的开销比较小。支持复杂查询&#xff08;带 where 子句的查询&#xff09; 非关系型数据库&#xff08;NOSQL…

微服务-nacos

nacos-注册中心 启动 服务注册到nacos

【Unity踩坑】创建新项目后提示编译错误要进入安全模式

在创建了新项目后&#xff08;比如URP&#xff0c;AR&#xff0c;VR&#xff09;&#xff0c;首次打开时提示有编译错误&#xff0c;要进入安全模式。 脚本是项目模板自带的&#xff0c;不会有问题。这时需要先选择进入安全模式&#xff0c;然后关闭项目&#xff0c;重新打开就…

9月12号作业

主要更改的代码 void Widget::read_solt() { QByteArray msg socket->readAll();//接受信息 if(QString::fromLocal8Bit(msg)msg2||msg3QString::fromLocal8Bit(msg)||msg6QString::fromLocal8Bit(msg)) { QListWidgetItem *listItem new QListWidgetItem(QString::fromL…

网络视频流解码显示后花屏问题的分析

问题描述 rtp打包的ps视频流发送到客户端后显示花屏。 数据分析过程 1、用tcpdump抓包 tcpdump -i eth0 -vnn -w rtp.pcap 2、用wireshark提取rtp的payload 保存为record.h264文件 3、用vlc播放器播放 显示花屏 4、提取关键帧 用xxd命令将h264文件转为txt文件 xxd -p…

2 创建会计科目表

定义解释 在SAP系统中&#xff0c;会计科目表是财务系统的基础数据之一&#xff0c;对于企业的财务核算和财务管理至关重要 定义&#xff1a;会计科目表是SAP系统中用于定义和分类总账科目的集合&#xff0c;它包含了所有需要在财务系统中记录和管理的会计科目。这些科目按照…