IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【开源】基于Qt的跨平台插件开发框架QCPFrame(三) -> 正文阅读

[C++知识库]【开源】基于Qt的跨平台插件开发框架QCPFrame(三)

【开源】基于Qt的跨平台插件开发框架QCPFrame(二)

六、组件

?????? 对于QCPFrame而言,一切皆插件的思想决定了其主要业务和功能都将以组件的形式存在,因此本章内容我们来讲讲QCPFrame组件的开发。

1. 创建一个插件工程

?????? 如果我告诉你拷贝一个工程,然后修改*.pro和PluginIO类。你一定会觉得很Low,可是这也确实是最为快捷的一种创建插件工程的方式。好了,下面我们来看怎么老老实实创建一个QCPFrame插件工程。

1.1 新建动态链接库工程

你可以通过Qt创建一个动态库工程,如下图:

1.2. 添加接口文件

在工程中添加interface文件夹下面的两个接口文件“coreinterface.h”和“plugininterface.h”。

1.3. 添加组件基类库文件

??? 在工程右键菜单选择“添加库...”,找到QCPF_PluginModel.h及QCPF_PluginModel.lib,典型的路径如下:

unix|win32: LIBS += -L$$PWD/../../../bin/ -lQCPF_PluginModel

INCLUDEPATH += $$PWD/../../QCPF_PluginModel

DEPENDPATH += $$PWD/../../QCPF_PluginModel

1.4. 新建组件实现类

在工程右键菜单选择“Add New”,创建“PluginIO.h/PluginIO.cpp”。其头文件如下所示:

? PluginIO.h

#ifndef QCPF_PLUGINIO_H
#define QCPF_PLUGINIO_H

#include "../../QCPF_PluginModel/qcpf_nonsystempluginmodel.h"

class PluginIO : public QCPF_NonSystemPluginModel
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID Plugin_Interface_iid FILE "QPlugin.json")
    Q_INTERFACES(Plugin_Interface)
public:
    PluginIO();
    ~PluginIO();

public:
    static PluginIO* getInstance();//静态获取实例
};

#endif

?PluginIO.cpp

#include "PluginIO.h"

#include <QVariant>
#include <QStringLiteral>
#include <QAction>


PluginIO* instance;

PluginIO::PluginIO()
{
    instance = this;

    I_PluginID = QStringLiteral("QPlugin1");
    I_PluginAliasName = QStringLiteral("QPlugin1");
    I_PluginAuther = QStringLiteral("xxxx");
    I_PluginVersion = QStringLiteral("1.0.0.1");
    I_PluginComment = QStringLiteral("QPlugin1 comment");
    I_PluginAuthority = AT_USER1;
    I_PluginTag = QStringLiteral("NON_SYSTEM\\DataSave");
}

PluginIO::~PluginIO(){}

PluginIO* PluginIO::getInstance()
{
    return instance;
}

??????? PluginIO.h中的代码#include "../../QCPF_PluginModel/qcpf_nonsystempluginmodel.h"表示包含非系统组件类的头文件,如果你要创建的是一个系统组件,那么就包含qcpf_systempluginmodel.h。同样的,继承的类也要与之对应。

?????? 至此一个典型的插件工程就建好了。你可以根据你的业务需求在“PluginIO.h/PluginIO.cpp”中添加代码,或者在工程中添加文件。但请记住“PluginIO.h/PluginIO.cpp”始终是你与系统之间通讯生命周期中的接口文件。

2. PluginIO文件功能及代码风格建议

??? PluginIO文件是组件与内核连接的主要渠道,我们以系统组件“QCPF_UserManager”为例来讲讲如何在该文件中添加功能代码。QCPF_UserManager.h代码如下:

/*
Author : Jamie.Tong
QQ      : 260271262
Data    : 2020-09-07
License: GPL v3.0
*/

#ifndef QCPF_PLUGINIO_H
#define QCPF_PLUGINIO_H

#include "../../QCPF_PluginModel/qcpf_systempluginmodel.h"

class PluginIO : public QCPF_SystemPluginModel
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID Plugin_Interface_iid FILE "QPlugin.json")
    Q_INTERFACES(Plugin_Interface)
public:
    PluginIO();
    ~PluginIO();

    void InitActionList(Plugin_Interface* plugin) Q_DECL_OVERRIDE;
    void InitFunctionList(Plugin_Interface* plugin) Q_DECL_OVERRIDE;
    void InitWidgetList(Plugin_Interface* plugin) Q_DECL_OVERRIDE;

public:
    tagOutputInfo tinfo;
    static PluginIO* getInstance();
     int GetUsersInfoFromJson();
private:
    void Action_ShowUserManager(bool checkState);
    int Function_VerifyLoginInfo(QVariant arg_in, QVariant& arg_out);
public slots:
    //当core初始化时要执行的过程
    int OnCoreInitialize() Q_DECL_OVERRIDE;
    int slot_InputInfo(tagOutputInfo& info) Q_DECL_OVERRIDE;
};

#endif

? ? ? ? 其中 InitActionList用于初始化和收集本组件中的所有Action,InitFunctionList用于初始化和收集本组件中的所有Function,InitWidgetList用于初始化和收集本组件中的所有Widget。

??????? getInstance() 用于获取this实例,在有些时候非常有用。

??????? OnCoreInitialize()是组件被内核连接时会被调用的过程,在本组件中,我们在OnCoreInitialize过程中调用GetUserInfoFromJson()函数,目的是组件被连接时就获取到用户登录信息。

??????? slot_InputInfo槽是用于接收输入信息而声名的,用于对输入的消息做出不同的响应。

??????? 建议用于Action的函数以“Action_”开头,用于Function的函数以“Function_”开头,这能便于我们快速归类和查找我们要编辑的功能模块。

/*
Author : Jamie.Tong
QQ      : 260271262
Data    : 2020-09-07
License: GPL v3.0
*/

#include "PluginIO.h"

#include <QWidget>
#include <QVariant>
#include <qobject.h>

#include <QStringLiteral>
#include <QAction>

#include "usermanager.h"
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
#include <QJsonValue>
#include <QCryptographicHash>//用于md5加密

PluginIO* instance;
PluginIO::PluginIO()
{
    instance = this;

    I_PluginID = tr("QCPF_UserManager");
    I_PluginAliasName = tr("User Manager");
    I_PluginAuther = tr("Jamie.T");
    I_PluginVersion = tr("1.0.0.4");
    I_PluginComment = tr("Manage users.");
    I_PluginTag = tr("SINGLETON\\SYSTEM\\USER_MANAGER");
    I_PluginAuthority = AT_MANAGER1;

    //GetUsersInfoFromJson();不能放在这里,基类的_core还没构造完
}

PluginIO::~PluginIO(){}

PluginIO* PluginIO::getInstance()
{
    return instance;
}

//接口方法实现
/***************************************************
*                       方法接口                                       *
***************************************************/
int PluginIO::OnCoreInitialize()
{
    return GetUsersInfoFromJson();
}

void PluginIO::InitActionList(Plugin_Interface* plugin)
{
    PluginActionInfo* pai = new PluginActionInfo();
    pai->_actionName = tr("Show User Manager");
    pai->_actionDetail = tr("User Manager.");
    pai->_pAction = (FPTR_ACTION)(&PluginIO::Action_ShowUserManager);

    plugin->I_ActionList.append(pai);

}

void PluginIO::InitFunctionList(Plugin_Interface* plugin)
{
    //--------------------------------------------
    PluginFunctionInfo* pfi_verifyLoginInfo = new PluginFunctionInfo();
    pfi_verifyLoginInfo->_functionName = tr("VerifyLoginInfo");
    pfi_verifyLoginInfo->_functionDetail = tr("Verify login info.");
    pfi_verifyLoginInfo->_pFunction = (FPTR_FUNC_CLS)(&PluginIO::Function_VerifyLoginInfo);

    plugin->I_FunctionList.append(pfi_verifyLoginInfo);
}

void PluginIO::InitWidgetList(Plugin_Interface* plugin)
{
    QCPF_Model* core = (QCPF_Model*)_core;
    PluginWidgetInfo *nFormInfo = new PluginWidgetInfo();

    nFormInfo->_showType = ST_POPUP;
    nFormInfo->_widget = new UserManager(core);
    nFormInfo->_origWidth = nFormInfo->_widget->width();
    nFormInfo->_origHeight = nFormInfo->_widget->height();
    nFormInfo->_widgetDetail = tr("It's used for managing the Non-System plugins");

    plugin->I_WidgetList.append(nFormInfo);
}

int PluginIO::slot_InputInfo(tagOutputInfo& info)
{
    if(info._type == INFT_PLUGIN_COLLECT_FINISHED)


    return 0;
}

int PluginIO::GetUsersInfoFromJson()
{
    QFile file(_core->I_ApplicationDirPath + "/Data/User/Users.dat");
    if(!file.open(QIODevice::ReadOnly))
        return -1;

    QByteArray allData = QByteArray::fromBase64(file.readAll());
    file.close();

    //进行JSON相关的处理
    QJsonParseError json_error;
    QJsonDocument jsonDoc(QJsonDocument::fromJson(allData, &json_error));
    if(json_error.error != QJsonParseError::NoError)
        return -2;

    QJsonObject rootObj = jsonDoc.object();
    //数据存入QJsonObject格式的rootObj中
    if (rootObj.contains("Users"))
    {
        QJsonValue value = rootObj.value("Users");
        if (value.isArray())
        {
            QJsonArray array = value.toArray();
            int nSize = array.size();

            _core->I_UserInfoLst.clear();
            for (int i = 0; i < nSize; ++i)
            {
                UserInfo* tUser = new UserInfo();
                tUser->_userName = array.at(i).toObject().value("UserName").toString();
                tUser->_password = array.at(i).toObject().value("Password").toString();
                QString authStr = array.at(i).toObject().value("Authority").toString();
                int auth = authStr.toInt();
                tUser->_authority = (AuthorityType)auth;
                tUser->_createDatetime = array.at(i).toObject().value("Datetime").toString();
                _core->I_UserInfoLst.append(tUser);
            }
        }
    }

    return 0;
}

/***********************************************************************
 *  action 函数指针所对应的回调函数
 * *********************************************************************/
void PluginIO::Action_ShowUserManager(bool checkState)
{
    QAction* actSender = (QAction*)sender();
    if(I_WidgetList.count()>0)
    {
        foreach (PluginWidgetInfo* pwi, instance->I_WidgetList) {
            if(pwi->_widget->objectName() == QStringLiteral("UserManager"))
            {
                pwi->_widget->setWindowIcon(actSender->icon());
                ((QDialog*)pwi->_widget)->exec();
            }
        }
    }
}

struct tagUserInfo{
    QString userName;
    QString password;
};
Q_DECLARE_METATYPE(tagUserInfo)

int PluginIO::Function_VerifyLoginInfo(QVariant arg_in, QVariant& arg_out)
{
    arg_out = false;

    if(arg_in.canConvert<tagUserInfo>())
    {
        tagUserInfo userInfo =arg_in.value<tagUserInfo>();

        //2021.07.26 将该部分代码挪到HostView中,因为一旦扫描不到插件,就无法进入维护模式。
        /*if(userInfo.userName.toUpper() == "JAMIE" || userInfo.password == "19820901")
        {
            _core->I_CurrentUserInfo._userName = userInfo.userName;
            _core->I_CurrentUserInfo._password = userInfo.password;
            _core->I_CurrentUserInfo._authority = AT_ORIGINATOR;
            _core->I_CurrentUserInfo._createDatetime = "long long ago.";
            _core->I_CurrentUserInfo._detail = "";
            arg_out = true;
            return 0;
        }*/

        foreach (UserInfo* uInfo, _core->I_UserInfoLst) {
            if(uInfo->_userName == userInfo.userName)
            {
                //QString md5PwdStr = QCryptographicHash::hash(userInfo.password.toLatin1(),QCryptographicHash::Md5).toHex();
                 if(uInfo->_password == userInfo.password)
                 {
                    _core->I_CurrentUserInfo._userName = uInfo->_userName;
                    _core->I_CurrentUserInfo._password = uInfo->_password;
                    _core->I_CurrentUserInfo._authority = uInfo->_authority;
                    _core->I_CurrentUserInfo._createDatetime = uInfo->_createDatetime;
                    _core->I_CurrentUserInfo._detail = uInfo->_detail;
                    arg_out = true;
                 }
                break;
            }
        }
    }

    return 0;
}

??????? 我们看到PluginIO.cpp除了实现PluginIO.h所定义的函数,代码开始部分的以“I_”开头的系列接口的填充将用于本组件信息的暴露。

??????? 总结,QCPFrame插件开发的流程其实很简单,但是要实现复杂的功能还是有很多事情要做。仔细研究源码,你会发现QCPFrame的主要的功能如系统管理器,插件管理器,用户管理器等都是由插件来实现的,你完全可以从这些插件源码中看到一些插件设计及通讯的思路。为其嫁接新的业务时,需要考虑单独设计一个业务Model,并在一个插件的PluginIO中将该Model引入插件系统中。不要把业务与QCPFrame_Model进行耦合,那样就失去了框架最初设计的意义,我们只需要将其他业务的Model引入一个插件的PluginIO类中,使QCPF_Model/QCPF_ViewModel与你的业务Model在这一个插件中进行相互访问,即可解耦。即新的业务只跟该插件相关,而与QCPFrame插件系统无关。最终希望达到的目标是QCPF_Model.dll/QCPF_ViewModel.dll及QCPF_HostView.exe不再更新,更新的只是插件。

????? 最后,祝你开发愉快,如果您对此有什么疑问,可以留言或者加入QQ群852374570进行讨论。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-13 21:33:09  更:2022-03-13 21:35:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:56:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码