CTK框架 - 插件依赖关系 - 给插件加上界面

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 在第一篇文章中吗,我们提到了MANIFEST.MF中有个字段是依赖关系,这次我们来测试一下这个依赖关系:

CTK框架 - 插件依赖关系 - 给插件加上界面


插件依赖关系

在第一篇文章中吗,我们提到了MANIFEST.MF中有个字段是依赖关系,这次我们来测试一下这个依赖关系:


MANIFEST.MF

之前对资源文件没有做过多介绍,这次来说一下里面的内容

名称 作用
Plugin-SymbolicName 插件的符号名,插件的唯一标识
Plugin-Copyright 插件的版权信息
Plugin-Description 插件的简要描述
Plugin-Name 插件的名称,对插件起说明作用,不影响插件功能
Plugin-Vendor 插件的供应商
Plugin-Localization 标识插件的Qt .qm 文件的基本名称:如中文qt_zh.qm,此处写zh
Require-Plugin 插件所需的其他插件的符号名称
Plugin-Version 插件的版本号
Plugin-ActivationPolicy 插件的激活策略
Plugin-UpdateLocation 在插件更新操作期间,获取新插件版本的位置

插件的激活策略由 Plugin-ActivationPolicy指定,默认值是 lazy


   ●  eager:插件使用 ctkPlugin::START_ACTIVATION_POLICY 选项启动,当框架启动时会立即激活。

   ●  lazy:插件使用 ctkPlugin::START_ACTIVATION_POLICY 选项启动,并在 ctkPlugin::STARTING 状态等待,直到插件的第一类实例化发生。插件将在实例返回给请求者之前被激活


插件依赖的插件由Require-Plugin指定,


resolution用来标识Require-Plugin中的解析类型,默认值是mandatory。包括:


   ●  optional(可选的):表示所需的插件是可选的,并且即使所需的插件没有被解析,该插件也可以被解析。

   ●  mandatory(强制的):表示在解析插件时,所需的插件也必须被解析。如果所需的插件不能被解析,则模块解析失败。


首先将About依赖于Core插件

Plugin-SymbolicName:About
Plugin-Version:1.0.0
Require-Plugin:Core; plugin-version="[2.0,5.0)"; resolution:="mandatory"

这个时候加载About插件会打印Failed to resolve required plugin: Core

如果版本号正常或者是resolution:="optional"则可以正常加载


给插件加上界面


Core插件

我们之前都是使用控制台打印的插件的通信信息或者是其他的信息,这次我们来给我们的插件加上界面。


界面的创建:

1.首先是我们的Core插件,我们给Core加一个mainwindow,并且加一个sendEvent的菜单,并且在mainwindowplugin中使用pop接口将界面弹出来


mainwindow

#ifndef CTKTEST_MAINWINDOW_H
#define CTKTEST_MAINWINDOW_H
#include <QMainWindow>
#include "ctkPluginContext.h"
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(ctkPluginContext *context, QWidget *parent = 0);
    ~MainWindow() override;
protected slots:
    void actionSendEvent();
private:
    ctkPluginContext *context_;
};
#endif //CTKTEST_MAINWINDOW_H
#include "mainwindow.h"
#include "service/event/ctkEventAdmin.h"
#include <QMenuBar>
MainWindow::MainWindow(ctkPluginContext *context, QWidget *parent)
    : QMainWindow(parent)
    , context_(context)
{
    QMenuBar *menubar  = new QMenuBar(this);
    setMenuBar(menubar);
    QAction *action = new QAction("发送事件", this);
    menubar->addAction(action);
    connect(action, &QAction::triggered, this, &MainWindow::actionSendEvent);
}
MainWindow::~MainWindow()
{
}
void MainWindow::actionSendEvent()
{
    //获取事件服务接口
    ctkServiceReference ref = context_->getServiceReference<ctkEventAdmin>();
    ctkEventAdmin* eventAdmin{nullptr};
    if(ref)
    {
        eventAdmin = context_->getService<ctkEventAdmin>(ref);
        context_->ungetService(ref);
    }
    //发送事件
    ctkDictionary message;
    ctkDictionary message2;
    ctkDictionary message3;
    message.insert("About", "im a message to about plugin");
    message2.insert("About", "im AAA message to about plugin");
    message3.insert("MMM", "im MMM message to about plugin");
    if(eventAdmin)
        eventAdmin->postEvent(ctkEvent("About", message));
    if(eventAdmin)
        eventAdmin->postEvent(ctkEvent("AAA", message2));
    if(eventAdmin)
        eventAdmin->postEvent(ctkEvent("About", message3));
}

mainwindowplugin

#ifndef CTKTEST_MAINWINDOWPLUGIN_H
#define CTKTEST_MAINWINDOWPLUGIN_H
#include <QObject>
#include "../src/imainwindow.h"
#include "ctkPluginContext.h"
#include "service/event/ctkEventHandler.h"
class MainWindow;
class MainWindowPlugin : public QObject, public iMainWindow
{
    Q_OBJECT
    /*
    此宏与Q_DECLARE_INTERFACE宏配合使用。
    Q_DECLARE_INTERFACE:声明一个接口类
    Q_INTERFACES:当一个类继承这个接口类,表明需要实现这个接口类
    */
    Q_INTERFACES(iMainWindow)
public:
    explicit MainWindowPlugin(ctkPluginContext *context);
    void popWindow() override;
signals:
    void sig_send();
private:
    ctkPluginContext *context_;
    MainWindow *main_window_;
};
#endif //CTKTEST_MAINWINDOWPLUGIN_H
#include "mainwindowplugin.h"
#include "service/event/ctkEventAdmin.h"
#include <iostream>
#include "mainwindow.h"
MainWindowPlugin::MainWindowPlugin(ctkPluginContext *context)
        : context_(context)
{
    main_window_ = new MainWindow(context);
}
void MainWindowPlugin::popWindow()
{
    main_window_->show();
}

这样我们在调用popWindow的时候我们就得到了一个界面,并且点击发送事件的时候也会打印我们之前事件打印的那句话


注意:  不要忘记删除掉imainwindow中的sendEvent接口,因为这个时候它已经没有任何作用了


About插件

接下来我们给About也做一个界面弹出:


aboutdlg

#ifndef CTKTEST_ABOUTDLG_H
#define CTKTEST_ABOUTDLG_H
#include <QDialog>
class AboutDlg : public QDialog
{
    Q_OBJECT
public:
    explicit AboutDlg(QWidget *parent = 0);
    ~AboutDlg() override;
};
#endif //CTKTEST_ABOUTDLG_H
#include <iostream>
#include "aboutdlg.h"
AboutDlg::AboutDlg(QWidget *parent)
    : QDialog(parent)
{
}
AboutDlg::~AboutDlg()
{
    std::cout << "~AboutDlg" << std::endl;
}

aboutplugin

#ifndef CTKTEST_ABOUTPLUGIN_H
#define CTKTEST_ABOUTPLUGIN_H
#include <QObject>
#include "ctkPluginContext.h"
#include "service/event/ctkEventAdmin.h"
#include "service/event/ctkEventHandler.h"
class AboutDlg;
class AboutPlugin : public QObject, public ctkEventHandler
{
    Q_OBJECT
    Q_INTERFACES(ctkEventHandler)
public:
    explicit AboutPlugin(ctkPluginContext *context);
signals:
    void sig_open();
protected slots:
    void pageOpen();
protected:
    void handleEvent(const ctkEvent& event) override;
private:
    ctkPluginContext *m_context;
    QSharedPointer<AboutDlg> about_page_;
};
#endif //CTKTEST_ABOUTPLUGIN_H
#include "aboutplugin.h"
#include "aboutdlg.h"
#include <service/event/ctkEventConstants.h>
#include <iostream>
AboutPlugin::AboutPlugin(ctkPluginContext *context)
    : m_context( context )
{
    //注册监听信号"About"
    ctkDictionary dic;
    dic.insert(ctkEventConstants::EVENT_TOPIC, "About");
    m_context->registerService<ctkEventHandler>(this, dic);
    connect(this, &AboutPlugin::sig_open, this, &AboutPlugin::pageOpen);
    about_page_.reset(new AboutDlg());
}
void AboutPlugin::handleEvent(const ctkEvent &event)
{
//接收监听事件接口
    if(event.getTopic() == "About")
    {
        emit sig_open();
    }
}
void AboutPlugin::pageOpen()
{
    about_page_->exec();
}

这里使用信号打开界面的原因是因为postEvent不在界面线程,所以需要使用信号槽来打开界面。


界面的析构:

1.界面是非智能指针对象: 非智能指针对象记得在stop删除插件的时候把new出的界面对象删除;

2.界面是智能指针对象:如果我们使用QSharedPointer<MainWindow> main_window_;我们则不用关心这个界面的析构,当我们关闭界面的时候会自动调用界面的析构函数。


我这里为了省事也是都给界面换成了智能指针,并且我再析构函数中加了打印,可以看到系统关闭的时候界面的析构函数都被调用了。

目录
相关文章
|
XML 数据格式
Camunda常用功能
Camunda常用接口简介
3953 1
Camunda常用功能
|
3月前
|
jenkins 持续交付
jenkins学习笔记之六:共享库方式集成构建工具
jenkins学习笔记之六:共享库方式集成构建工具
|
5月前
|
存储 数据库 数据安全/隐私保护
Duplicator插件的主要功能是什么?
【6月更文挑战第4天】Duplicator插件的主要功能是什么?
57 1
CTK框架 - 第一个插件
前面我们已经介绍了CTK框架的基本信息,接下来我们来一步一步搭建CTK的第一个插件。
125 0
|
数据库
插件配置设计
插件配置设计
108 0
|
资源调度 JavaScript 测试技术
day-ui 组件库打包环境配置
本小节我们把写好的库打包发布到 npm 上。之后我们建个小 vue3 的项目,安装我们自己的包。实现全加载和按需加载
435 0
day-ui 组件库打包环境配置
版本依赖和插件管理
版本依赖和插件管理
100 0
|
ARouter 测试技术 Android开发
通过Gradle自动实现Android组件化模块构建
为什么我们要用Gradle管理组件呢? 先来看看Android组件化需要实现的目标 按照业务逻辑划分模块 项目模块能够单独启动测试 能够根据需求引入或删除某些业务模块 通过不同模块的组合,组成不同的App 对于第一点:需要根据技术架构和业务架构来划分模块,这里需要根据实际情况来考虑。
1719 0
下一篇
无影云桌面