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

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_;我们则不用关心这个界面的析构,当我们关闭界面的时候会自动调用界面的析构函数。

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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

turbolove

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值