控制中心插件
本文档将会指导大家一步一步的构建出控制中心的插件。本项目使用CMake进行项目管理,Qt/C++进行项目开发,如不会CMake或者Qt,需要先进行学习准备。
CMake文件
首先需要新建出CMakeLists.txt,并设置好项目名称和插件名称。
set(PLUGIN_NAME "helloworld")
project(${PLUGIN_NAME})
创建src目录,并新建helloworldplugin.cpp文件,向cmake中添加该文件。
set(SRCS src/helloworldplugin.cpp)
现在添加基础的依赖。
# 载入Qt基础库
find_package(Qt5 REQUIRE COMPONENT Core Widgets)
#载入控制中心开发库
find_package(DdeControlCenter REQUIRED)
为项目添加生成的动态库,需要设置名称、库的类型和所需的依赖。
# 设置动态库的名称、类型,shared是动态库。
add_library(${PLUGIN_NAME} SHARED ${SRCS})
# 设置项目需要的访问的头文件,这里是控制中心的插件头文件
target_include_directories(${PLUGIN_NAME} PUBLIC ${DdeControlCenter_INCLUDE_DIR})
# 设置项目链接的依赖,这里是Qt和控制中心的控件动态库
target_link_libraries(${PLUGIN_NAME} PRIVATE
${DdeControlCenter_LIBRARIES})
插件代码开发
当所有的准备工作都完成以后,我们可以进行插件的代码开发工作了。
在src/helloworldplugin.cpp文件中,导入控制中心插件接口的头文件。
#include "interface/namespace.h"
#include "interface/moduleinterface.h"
#include "interface/frameproxyinterface.h"
首先先说明一下控制中心插件的接口:
// preInitialize会在模块初始化时被调用,用于模块在准备阶段进行资源的初始化;
// preInitialize不允许进行高资源的操作;
virtual void preInitialize(bool sync = false,FrameProxyInterface::PushType = FrameProxyInterface::PushType::Normal) {Q_UNUSED(sync)}
// initialize初始化相应的模块,参数proxy用于Moudle向Frame信息查询和主动调用;
// 返回Module的id;
// initialize的时候不能做资源占用较高的操作;
virtual void initialize() = 0;
// 保留,该接口用于重设插件的所有设置。
virtual void reset() {}
///
/// \brief name
/// 插件提供的模块名称,用于内部标识。
/// \return
///
virtual const QString name() const = 0;
///
/// \brief name
/// 模块名,用于显示
/// \return
///
virtual const QString displayName() const = 0;
///
/// \brief icon
/// 获取模块的图标路径。
/// \return
///
virtual QIcon icon() const {
return QIcon::fromTheme(QString("dcc_nav_%1").arg(name()));
}
///
/// \brief translationPath
/// 获取多语言文件的路径,用以搜索
/// \return QString
///
virtual QString translationPath() const {
return QStringLiteral(":/translations/dde-control-center_%1.ts");
}
// 应该暂时不需要finalize;
// virtual void finalize();
// 获取Module的Metadata;
// virtual ModuleMetadata getMetadata();
///
/// \brief showPage
/// 显示指定的某个页面
/// \param pageName
/// the page name
///
virtual void showPage(const QString &pageName) { Q_UNUSED(pageName); }
// 返回模块主Widget;
virtual QWidget *moduleWidget() { return nullptr;}
///
/// \brief contentPopped
/// 弹出指定的页面
/// \param w
///
virtual void contentPopped(QWidget *const w) { Q_UNUSED(w);}
///
/// \brief active
/// 当模块第一次被点击进入时,active会被调用,如果是插件,重载的时候必须声明为slots,否则加载不了
virtual void active() {}
///
/// \brief active
/// 当模块被销毁时,deactive会被调用
virtual void deactive() {}
///
/// \brief load
/// 当搜索到相关字段后,lead会被调用
/// 如果可以正常显示则返回 0, 否则返回非0
virtual int load(const QString &path) {
Q_UNUSED(path);
return 0;
}
virtual QStringList availPage() const { return QStringList(); }
/**
* @brief path
* @return 插件级别及二级菜单插件所属模块
*/
virtual QString path() const {
return QString();
}
/**
* @brief follow
* @return 插件插入位置,可以字符串或者数字
*/
virtual QString follow() const {
return QString();
}
/**
* @brief enabled
* @return 插件是否处于可用状态
*/
virtual bool enabled() const {
return true;
}
我们的helloworld模块只需要重写必要的纯虚函数,还需要重写moduleWidget方法,返回我们提供的页面。 新建一个HelloWorldPlugin类,并继承自QObject和DCC_NAMESPACE::ModuleInterface。不要担心C++的交叉继承,它只在部分特殊场景需要注意,特别是访问基类之间同名的方法。
class HelloWorldPlugin : public QObject, public DCC_NAMESPACE::ModuleInterface {
Q_OBJECT
Q_PLUGIN_METADATA(IID ModuleInterface_iid)
Q_INTERFACES(DCC_NAMESPACE::ModuleInterface)
public:
HelloWorldPlugin(QObject *parent = nullptr)
: QObject(parent)
, DCC_NAMESPACE::ModuleInterface()
{}
// 重写纯虚函数
virtual void initialize() override {
// 进行初始化操作,对于我们的插件来说,不需要做任何事情。
}
virtual const QString name() const override {
return "helloworldplugin";
}
virtual const QString displayName() const override {
return tr("HelloWorld Plugin");
}
// 重写虚函数
virtual QWidget* moduleWidget() const override {
if (!m_mainPage) {
m_mainPage = new QWidget(this);
}
return m_mainPage;
}
private:
QPointer<QWidget> m_mainPage;
};
#define ModuleInterface_iid "com.deepin.dde.ControlCenter.module/1.0"
Q_DECLARE_INTERFACE(DCC_NAMESPACE::ModuleInterface, ModuleInterface_iid)
此时如果进行构建,我们会看到Build目录出现了libhelloworldplugin.so了。但是我们还没实现安装,我们并不能执行make install将插件安装到系统里面。 返回CMakeLists.txt文件,追加上安装的配置。
install(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/dde-control-center/plugins/)
还未说我们如何执行构建和安装呢,新建一个build目录,然后执行cmake的命令生成makefile,再通过make命令执行编译和安装。
mkdir build
cd build
cmake ../
make
sudo make install
然后运行控制中心,就可以看到我们的插件被加载了。 项目自带的例子:https://github.com/linuxdeepin/dde-control-center/tree/master/src/frame/plugins/privacy