五、接口
QCPFrame的接口文件在QCPFrame\interface文件夹下,包含CoreInterface和PluginInterface。其中CoreInterface用于定义QCPF_Model要实现的功能,而PluginInterface用于定义所有Plugin要实现的功能。这意味着Core与Plugin之间可以通过这些接口互相访问。
1.1 CoreInterface
CoreInterface接口主要代码如下:
class QCPF_Interface : public QObject
{
Q_OBJECT
public:
/**********************************************************************************
* 系统组件:
* 1. 用以扩展系统功能,在加载时,首先被加载,其余Plugins为非系统组件。
* 2. 系统组件可以选择哪些可用哪些不可用,这可以用于用户权限管理等功能
* 3. 系统为单例组件,可排序,但是不容许被克隆。
**********************************************************************************/
RunMode I_RunMode;
//所有系统组件集合
QList<Plugin_Interface*> I_SysPlugins;
//所有被选中的系统组件集合
QList<Plugin_Interface*> I_SysPlugins_Sel;
/**********************************************************************************
* 非系统组件:
* 1. 用以实现业务层功能,在系统组件加载完成过后被加载。
* 2. 非系统组件可以选择哪些可用哪些不可用,这可以用于用户权限管理等功能
* 3. 非系统组件可排序,可以被克隆。
**********************************************************************************/
//非系统原始组件集合
QList<Plugin_Interface*> I_NSysOrigPlugins;
//被选中的非系统原始组件集合
QList<Plugin_Interface*> I_NSysOrigPlugins_Sel;
//克隆组件集合,克隆组件必须是从I_NSysOrigPlugins_Sel中生成的副本
QList<Plugin_Interface*> I_NSysClonePlugins;
//包括已选择的原始组件和克隆组件在内的所有非系统组件的集合
QList<Plugin_Interface*> I_NSysAllValidPlugins;
//=====================当前配置文件目录和组件目录
QString I_SystemID;
QString I_SystemName;
QString I_SystemVersion;
QString I_OrganizationName;
QString I_ApplicationDirPath;
QString I_SystemPluginDirPath;
QString I_NonSysPluginDirPath;
QString I_ConfigDirPath;
QString I_ConfigFileName;
QString I_ConfigFullFilePath;
//================================================Users
//用户信息
QList<UserInfo*> I_UserInfoLst;
UserInfo I_CurrentUserInfo;
//================================================SharedMemory
//组件间共享内存
bool I_SMBoolVar1;
bool I_SMBoolVar2;
int I_SMIntVar1;
int I_SMIntVar2;
double I_SMDoubleVar1;
double I_SMDoubleVar2;
QString I_SMStrVar1;
QString I_SMStrVar2;
QObject I_SMObject1;
QObject I_SMObject2;
QList<QObject*> I_SMObjectLst;
QVector<QObject*> I_SMObjectVec;
QQueue<QObject*> I_SMObjectQue;
//Thead
QThreadPool I_SMThreadPool;
QThread I_SMThread;
QMutex I_SMMutex;
QReadWriteLock I_SMReadWriteLock;
QSemaphore I_SMSemaphore;
QWaitCondition I_SMWaitCondition;
signals:
int sig_OutputInfo(tagOutputInfo& info);
int sig_Core(QVariant arg_in, QVariant &arg_out);
public slots:
virtual int slot_InputInfo(tagOutputInfo& info) { return 0; }
virtual int slot_Core(QVariant arg_in, QVariant &arg_out) { return 0; }
virtual int Invoke_PluginFunction(PluginType pType, QString pluginID, QString pluginFunctionName, QVariant arg_in, QVariant& arg_out) { return 0; }
virtual int Invoke_PluginFunction(PluginType pType, QString pluginID, QString copyID, QString pluginFunctionName, QVariant arg_in, QVariant& arg_out) { return 0; }
};
如上所示,CoreInterface定义了内核要实现的成员变量,信号及槽。
- 组件间共享内存 用于实现组件间变量的互相访问,这包括各种常用数据类型,以及用于线程间同步的成员变量。
- sig_OutputInfo 用于给外界暴露内核消息通道,即任何组件都可以通过这个信号向内核发送消息信号。
- sig_Core 用于给外界暴露内核通用信号,即任何组件都可以通过这个信号向内核发送通用信号,说它是通用信号,是因为它提供了QVariant类型的输入和输出,你可以通过它与Core进行双向数据传输。
- slot_InputInfo 用于定义内核接到输入信号后的处理函数,组件间通讯正是依赖Core的Switch/Case来实现消息路由。
- slot_Core 用于定义内核接到sig_Core信号后的处理函数。
- Invoke_PluginFunction 用于定义组件功能调用,它有两个重载的形式,用于组件通过Core来调用任意组件的任意Function。
enum InfoType
{
INFT_INITIALIZE_FINISHED,
INFT_MSG_INFO,
INFT_MSG_WARN,
INFT_MSG_ERROR,
INFT_MSG_QUESTION,
INFT_STATUS_INFO,
INFT_APPLICATION_CLOSE,
INFT_WRITE_LOG,
INFT_PLUGIN_COLLECT,
INFT_PLUGIN_COLLECT_FINISHED,
INFT_CORE_CONFIG_CHANGED,
INFT_VIEW_CONFIG_CHANGED,
INFT_PLUGIN_BROADCAST,//表示组件发起了事件广播,广播内容见参数
INFT_PLUGIN_SPECIAL,//表示组件向另一个指定组件发送消息,消息内容见参数
INFT_STATUSBAR_TEMP,
INFT_LOG_ACTION,
INFT_LOG_ERROR,
};
struct tagOutputInfo
{
public:
InfoType _type;
QString _title;
QString _content;
int _timeout;
tagOutputInfo(){}
tagOutputInfo(InfoType type, QString title, QString content){ _type=type;_title=title;_content=content;}
tagOutputInfo(InfoType type, QString title, QString content, int timeout){ _type=type;_title=title;_content=content; _timeout=timeout;}
};
tagOutputInfo消息结构如上所示,可以看到,我们可以通过该结构体承载任意消息类型,当Core的slot_InputInfo槽与组件的sig_OutputInfo信号绑定后,一旦检测到信号,Core会根据消息类型进行不同的处理,这是QCPFrame消息传输的主要思路,这种形式也便于后期消息类型扩展。至于不同的类型消息在内核里如果被处理,请关注后续QCPF_Model的相关介绍。
1.2 PluginInterface
PluginInterface接口主要代码如下:
class Plugin_Interface:public QObject
{
Q_OBJECT
public:
QString I_PluginID;//组件ID,该属性是组件间唯一的
PluginType I_PluginType;//组件类型,系统组件或非系统组件
QString I_PluginAliasName;//组件别名
QString I_PluginVersion;//组件版本
QString I_PluginAuther;//组件开发者
QString I_PluginComment;//组件功能说明
QString I_PluginFilePath;//组件路径
QVariant I_PluginTag;//组件类型,用于区别业务类型或者结构类型
AuthorityType I_PluginAuthority;//组件的访问权限
bool I_IsEnable;//是否被选中
bool I_IsCopy;//我是谁?我是不是一个克隆体?
QString I_CopyID;//副本ID,该属性是副本间唯一的
QString I_CopyAliasName;//副本别名
QString I_CopyComment;//副本功能说明
QVariant I_PluginVar;//通用组件变量
QList<QVariant> I_PluginVarList;//通用组件变量集合
QList<PluginActionInfo*> I_ActionList;//通用组件Action集合
QList<PluginFunctionInfo*> I_FunctionList;//通用组件Function集合
QVector<PluginWidgetInfo*> I_WidgetList;//通用组件部件集合
public:
virtual Plugin_Interface* Clone(QString copyID, QString copyAliasName, QString copyComment) {return nullptr;}
virtual bool ConnectCore(QObject* core) { return true; }
virtual int PluginFunction(QVariant arg_in, QVariant &arg_out) { return 0; }
virtual void InitActionList(Plugin_Interface* plugin){};
virtual void InitFunctionList(Plugin_Interface* plugin){};
virtual void InitWidgetList(Plugin_Interface* plugin){};
signals:
int sig_OutputInfo(tagOutputInfo& info);
int sig_Plugin(QVariant arg_in, QVariant &arg_out);
public slots:
virtual int slot_InputInfo(tagOutputInfo& info) { return 0; }
virtual int slot_Plugin(QVariant arg_in, QVariant &arg_out) { return 0; }
virtual void slot_Action(bool checkState) { }
//当core初始化时要执行的过程
virtual int OnCoreInitialize() { return 0; }
//当view视图构造完成后,Load前要执行的过程
virtual int OnViewCreated() { return 0; }
//当view视图Load时要执行的过程
virtual int OnViewLoaded() { return 0; }
//当view视图Closeing时要执行的过程
virtual int OnViewClosing() { return 0; }
};
以上定义了作为一个QCPFrame的组件必须要实现的功能。成员变量后面有明确的注释,其中I_ActionList,I_FunctionList,I_WidgetList是后期UI配置的主要数据来源。
- ConnectCore 用于实现组件连接Core时需要执行的操作。
- Clone 用于实现组件被克隆时需要执行的操作,它和ConnectCore都已经被后续要介绍的Plugin_Model实现了,因此当你的组件从Plugin_Model继承而来时,创建一个组件将会相当简单,它已经帮你实现了与宿主连接和对象数据深拷贝的功能。
- PluginFunction 用于实现一个通用的函数,便于内核及其他组件来调用(组件可以通过上述Core接口定义中的Invoke_PluginFunction来调用),以实现组件间直接函数调用。
- InitActionList 用于实现组件Action成员的收集。
- InitFunctionList 用于实现组件Function成员的收集。
- InitWidgetList 用于实现组件Widget成员的收集,对于开发人员来说,最主要的开发任务就是填充I_ActionList,I_FunctionList,I_WidgetList,宿主QCPF_Model并不关心他们的功能,他们之间是松耦合的。
具体来说,InitActionList,InitFunctionList,InitWidgetList分别用于组件I_ActionList,I_FunctionList,I_WidgetList的初始化,典型的应用是当QCPF_Model完成组件收集以后,ViewEditor(一个特殊用途的系统组件)通过接口获取目标组件的这些资源,并将他们展示给用户,用户可以通过ViewEditor的功能对主框架UI进行编辑,保存,用以实现主界面UI可配。
- sig_OutputInfo 用于实现与Core之间的消息通道,组件可以通过这个信号将消息传递到Core
- sig_Plugin 用于定义一个通用的组件信号,它用于实现除了tagOutputInfo消息以外的,其他用途的通用信号。
- slot_InputInfo 用于接收输入消息信号,这个信号可能来自Core,但更多时候是Plugin通过Core的sig_OutputInfo发来的信号。
- slot_Plugin 用于接收通用组件信号,
- slot_Action 用于接收Core发来的Action信号,该信号通常是被ViewEditer所编辑出的动态Action,经由用户操作而发出的。
- OnCoreInitialize core初始化时要执行的过程
- OnViewCreated view视图构造完成后,Load前要执行的过程
- OnViewLoaded view视图Load时要执行的过程
- OnViewClosing view视图Closeing时要执行的过程
接口提供了QCPFrame完整生命周期内,不同阶段的槽,用于组件初始化,响应,及内存回收。
【小结】:本节主要讲了QCPFrame的内核及组件接口设计,这些接口尽量以通用,可扩展,可裁剪为主要设计思路,后续会讲一讲组件的开发流程,谢谢关注。