From 184445992d0fad2a86973e3e8f8ed60cf578d73e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=9F=B3=E5=8D=9A=E6=96=87?= Date: Sat, 24 Feb 2018 11:27:56 +0800 Subject: [PATCH] add plugins develop guide Change-Id: I448c791af97d6ce50a39dff542f843763883a3e1 --- .../home_monitor/home_monitor.json | 3 + .../home_monitor/home_monitor.pro | 24 +++ .../home_monitor/homemonitorplugin.cpp | 28 +++ .../home_monitor/homemonitorplugin.h | 28 +++ .../home_monitor/informationwidget.cpp | 33 ++++ .../home_monitor/informationwidget.h | 21 ++ .../plugin-guide/plugins-developer-guide.md | 180 ++++++++++++++++++ 7 files changed, 317 insertions(+) create mode 100644 plugins/plugin-guide/home_monitor/home_monitor.json create mode 100644 plugins/plugin-guide/home_monitor/home_monitor.pro create mode 100644 plugins/plugin-guide/home_monitor/homemonitorplugin.cpp create mode 100644 plugins/plugin-guide/home_monitor/homemonitorplugin.h create mode 100644 plugins/plugin-guide/home_monitor/informationwidget.cpp create mode 100644 plugins/plugin-guide/home_monitor/informationwidget.h create mode 100644 plugins/plugin-guide/plugins-developer-guide.md diff --git a/plugins/plugin-guide/home_monitor/home_monitor.json b/plugins/plugin-guide/home_monitor/home_monitor.json new file mode 100644 index 000000000..3dfdb06db --- /dev/null +++ b/plugins/plugin-guide/home_monitor/home_monitor.json @@ -0,0 +1,3 @@ +{ + "api": "1.0" +} diff --git a/plugins/plugin-guide/home_monitor/home_monitor.pro b/plugins/plugin-guide/home_monitor/home_monitor.pro new file mode 100644 index 000000000..2ffdcd35a --- /dev/null +++ b/plugins/plugin-guide/home_monitor/home_monitor.pro @@ -0,0 +1,24 @@ + +QT += widgets +TEMPLATE = lib +CONFIG += plugin c++11 + +TARGET = $$qtLibraryTarget(home_monitor) +DESTDIR = $$_PRO_FILE_PWD_ +DISTFILES += home_monitor.json + +HEADERS += \ + homemonitorplugin.h \ + informationwidget.h + +SOURCES += \ + homemonitorplugin.cpp \ + informationwidget.cpp + +isEmpty(PREFIX) { + PREFIX = /usr +} + +target.path = $${PREFIX}/lib/dde-dock/plugins/ +INSTALLS += target + diff --git a/plugins/plugin-guide/home_monitor/homemonitorplugin.cpp b/plugins/plugin-guide/home_monitor/homemonitorplugin.cpp new file mode 100644 index 000000000..252709eea --- /dev/null +++ b/plugins/plugin-guide/home_monitor/homemonitorplugin.cpp @@ -0,0 +1,28 @@ +#include "homemonitorplugin.h" + +HomeMonitorPlugin::HomeMonitorPlugin(QObject *parent) + : QObject(parent) +{ + +} + +const QString HomeMonitorPlugin::pluginName() const +{ + return QStringLiteral("home_monitor"); +} + +void HomeMonitorPlugin::init(PluginProxyInterface *proxyInter) +{ + m_proxyInter = proxyInter; + + m_pluginWidget = new InformationWidget; + + m_proxyInter->itemAdded(this, QString()); +} + +QWidget *HomeMonitorPlugin::itemWidget(const QString &itemKey) +{ + Q_UNUSED(itemKey); + + return m_pluginWidget; +} diff --git a/plugins/plugin-guide/home_monitor/homemonitorplugin.h b/plugins/plugin-guide/home_monitor/homemonitorplugin.h new file mode 100644 index 000000000..bc35078fe --- /dev/null +++ b/plugins/plugin-guide/home_monitor/homemonitorplugin.h @@ -0,0 +1,28 @@ +#ifndef HOMEMONITORPLUGIN_H +#define HOMEMONITORPLUGIN_H + +#include "informationwidget.h" + +#include + +#include + +class HomeMonitorPlugin : public QObject, PluginsItemInterface +{ + Q_OBJECT + Q_INTERFACES(PluginsItemInterface) + Q_PLUGIN_METADATA(IID "com.deepin.dock.PluginsItemInterface" FILE "home_monitor.json") + +public: + explicit HomeMonitorPlugin(QObject *parent = nullptr); + + const QString pluginName() const override; + void init(PluginProxyInterface *proxyInter) override; + + QWidget *itemWidget(const QString &itemKey) override; + +private: + InformationWidget *m_pluginWidget; +}; + +#endif // HOMEMONITORPLUGIN_H diff --git a/plugins/plugin-guide/home_monitor/informationwidget.cpp b/plugins/plugin-guide/home_monitor/informationwidget.cpp new file mode 100644 index 000000000..d9c0ac2bd --- /dev/null +++ b/plugins/plugin-guide/home_monitor/informationwidget.cpp @@ -0,0 +1,33 @@ +#include "informationwidget.h" + +#include +#include + +InformationWidget::InformationWidget(QWidget *parent) + : QWidget(parent) + + , m_infoLabel(new QLabel) +{ + m_infoLabel->setStyleSheet("QLabel {" + "color: white;" + "}"); + + QVBoxLayout *centralLayout = new QVBoxLayout; + centralLayout->addWidget(m_infoLabel); + centralLayout->setSpacing(0); + centralLayout->setMargin(0); + + setLayout(centralLayout); + + QTimer::singleShot(1, this, &InformationWidget::refreshInfo); +} + +void InformationWidget::refreshInfo() +{ + // TODO: fetch info + const int remain = 50; + const int total = 100; + + // update display + m_infoLabel->setText(tr("Home:\n%1G/%2G").arg(remain).arg(total)); +} diff --git a/plugins/plugin-guide/home_monitor/informationwidget.h b/plugins/plugin-guide/home_monitor/informationwidget.h new file mode 100644 index 000000000..e3990e600 --- /dev/null +++ b/plugins/plugin-guide/home_monitor/informationwidget.h @@ -0,0 +1,21 @@ +#ifndef INFORMATIONWIDGET_H +#define INFORMATIONWIDGET_H + +#include +#include + +class InformationWidget : public QWidget +{ + Q_OBJECT + +public: + explicit InformationWidget(QWidget *parent = nullptr); + +private slots: + void refreshInfo(); + +private: + QLabel *m_infoLabel; +}; + +#endif // INFORMATIONWIDGET_H diff --git a/plugins/plugin-guide/plugins-developer-guide.md b/plugins/plugin-guide/plugins-developer-guide.md new file mode 100644 index 000000000..9820a4061 --- /dev/null +++ b/plugins/plugin-guide/plugins-developer-guide.md @@ -0,0 +1,180 @@ +# 从零构建 dde-dock 的插件 +本教程将展示一个简单的 dde-dock 插件的开发过程,插件开发者可跟随此步骤为 dde-dock 创造出更多具有丰富功能的插件。 + +在本教程中,将创建一个可以实时显示用户家目录(`~/`)使用情况的小工具。 + +### 插件的工作原理 +dde-dock 插件本质是一个按 Qt 插件标准所开发的共享库文件(`so`)。通过 dde-dock 预定的规范与提供的接口,共同完成 dde-dock 的功能扩展。 + +## 准备环境 +插件的开发环境可以是任意的,只要是符合 Qt 插件规范及 dde-dock 插件规范的共享库文件,都可以被当作 dde-dock 插件载入。下面以 Qt + qmake 为例进行说明: + +### 安装依赖 +以 Deepin 15.5 环境为基础,至少先安装如下的包: + +- dde-dock-dev +- qt5-qmake +- qtbase5-dev-tools +- libqt5core5a +- libqt5widgets5 +- pkg-config + +## 基本的项目结构 + +### 创建必需的项目目录与文件 +插件名称叫做`home_monitor`,所以创建以下的目录结构: +``` +home_monitor +├── home_monitor.json +├── homemonitorplugin.cpp +├── homemonitorplugin.h +└── home_monitor.pro +``` + +`home_monitor.pro`文件内容如下: +``` qmake +# 添加所需的 Qt 模块 +QT += widgets +# 指定生成目标为共享库 +TEMPLATE = lib +# 指定生成目标为 Qt 插件 +CONFIG += plugin c++11 + +# 指定生成目标的名称 +TARGET = $$qtLibraryTarget(home_monitor) +# 指定生成目标的目录 +DESTDIR = $$_PRO_FILE_PWD_ +# 添加必要的文件到插件中 +DISTFILES += home_monitor.json + +HEADERS += \ + homemonitorplugin.h + +SOURCES += \ + homemonitorplugin.cpp + +# 以下是安装相关的设定 +isEmpty(PREFIX) { + PREFIX = /usr +} + +target.path = $${PREFIX}/lib/dde-dock/plugins/ +INSTALLS += target +``` + +`home_monitor.json`文件指明了当前插件所使用的 dde-dock 的接口版本,dde-dock 在加载此插件时,会检测自己的接口版本是否与插件的接口版本一致,当双方的接口版本不一致时,dde-dock 为了安全将阻止加载对应的插件。 + +在 dde-dock 内建的插件代码中,可以找到当前具体的接口版本,目前只有 1.0 版本。 +``` json +{ + "api": "1.0" +} +``` + +`homemonitorplugin.h`包含了类`HomeMonitorPlugin`,它继承自`PluginItemInterface`,这代表了它是一个实现了 dde-dock 接口的插件。 + +`PluginItemInterface`中包含众多的功能接口以丰富插件的功能,具体的接口功能与用法可以查看对应文件中的文档。大多数接口在没有特定需求的时候都是无需处理的,需要所有插件显式处理的接口只有`pluginName`、`init`、`itemWidget`三个接口。 +``` c++ +#ifndef HOMEMONITORPLUGIN_H +#define HOMEMONITORPLUGIN_H + +#include + +#include + +class HomeMonitorPlugin : public QObject, PluginsItemInterface +{ + Q_OBJECT + Q_INTERFACES(PluginsItemInterface) + Q_PLUGIN_METADATA(IID "com.deepin.dock.PluginsItemInterface" FILE "home_monitor.json") + +public: + explicit HomeMonitorPlugin(QObject *parent = nullptr); + + // 返回插件的名称,必须是唯一值,不可以和其它插件冲突 + const QString pluginName() const override; + // 插件初始化函数 + void init(PluginProxyInterface *proxyInter) override; + + // 返回插件的 widget + QWidget *itemWidget(const QString &itemKey) override; +}; + +#endif // HOMEMONITORPLUGIN_H +``` + +`homemonitorplugin.cpp`中包含对应接口的实现 +``` c++ +#include "homemonitorplugin.h" + +HomeMonitorPlugin::HomeMonitorPlugin(QObject *parent) + : QObject(parent) +{ + +} + +const QString HomeMonitorPlugin::pluginName() const +{ + return QStringLiteral("home_monitor"); +} + +void HomeMonitorPlugin::init(PluginProxyInterface *proxyInter) +{ + m_proxyInter = proxyInter; +} + +QWidget *HomeMonitorPlugin::itemWidget(const QString &itemKey) +{ + Q_UNUSED(itemKey); + + return nullptr; +} +``` + +## 测试插件加载 +### 从源码构建 +为了不污染源码目录,推荐在源码目录中创建`build`进行构建: +``` sh +cd home_monitor +mkdir build +cd build +qmake .. +make -j4 +``` +### 安装 +``` +sudo make install +``` + +可以看到有`home_monitor.so`文件被安装在了 dde-dock 的插件目录。 + +``` sh +install -m 755 -p ../../home_monitor/libhome_monitor.so /usr/lib/dde-dock/plugins/libhome_monitor.so +``` + +### 测试加载 +执行`pkill dde-dock; dde-dock`来重新运行 dde-dock,在终端输出中如果出现以下的输出,说明插件的加载已经正常。 +``` +init plugin: "home_monitor" +init plugin finished: "home_monitor" +``` + +## 创建自己的 widget +按照一般的业务逻辑处理,这部分不是本教程的重点,可以参考完整代码及其它插件进行实现。 + +## 添加 widget 到 dde-dock 面板上 +在`init`方法中获取到了`PluginProxyInterface`对象,调用此对象的`itemAdded`即可实现向 dde-dock 面板上添加项目。 +第二个`QString`类型的参数代表了本插件所提供的 item 的 id,当一个插件提供多个 item 时,不同 item 之间的 id 要保证唯一。 +``` c++ +proxyInter->itemAdded(this, QString()); +``` + +在调用`itemAdded`之后,dde-dock 会在合适的时机调用插件的`itemWidget`接口以获取需要显示的 widget。在 itemWidget 接口中分析 itemKey,返回与之对应的 widget 对象,当插件只有一个可显示项目时,itemKey 可以忽略。 +``` c++ +QWidget *HomeMonitorPlugin::itemWidget(const QString &itemKey) +{ + Q_UNUSED(itemKey); + + return m_pluginWidget; +} +``` \ No newline at end of file