2018-07-31 17:01:58 +08:00
# 框架设计
`dde-dock` 主要分为两部分,即主界面 `frame` 部分与插件 `plugins` 部分。
## 主界面
主界面是指 dock 栏的主窗口。主窗口负责 dock 显示的位置、形状及相关的动画与特效处理。
主面板(MainPanel)是主窗口(MainWindow)的唯一子控件,它是一个 BoxLayout, 负责容纳 dock 上存放的所有项目。根据设置的不同,它的排版方向有水平和竖直两种。
### Item
dock 上所存放的所有条目都继承自 `Item` 类。这样设计的原因是简化 dock 布局,使得 dock 主面板的布局上所有条目的管理都能统一起来。
目前 dock 上的 Items 有以下几类:
- DockItem: 所有 Item 的基类,抽象类。
- LauncherItem: 启动器类型的 Item。
- AppItem: 关联所有应用程序的 Item。
- PlaceholderItem: 占位空间,用于在交换、拖拽 Item 时,显示一个临时的、空白的 Item。
- StretchItem: 在时尚模式下,充当中间的可伸缩空白区域。
- ContainerItem: 容器空间,用于存放被收纳隐藏的插件 Item。
- PluginsItem: 插件条目,每个插件可以注册 0 个或多个 PluginsItem 用于显示数据。
Dock 上从左至右(或从上至下)有不同的 Items 区域,在不同的显示模式下,不同工作区的显示状态或者调整策略都不一样,将它们统一为 Items 进行管理,可以极大的减小在这方面的工作。
### Item Controller
`DockItemController` 类是控制与管理所有 Items 的地方。任何 Item 的创建、销毁操作,移动、交换、刷新等信号的起始点都从这里开始。
其中, AppItem 的相关数据是从后端获取的。这些与后端通信的操作被封装在了 AppItem 中。Item Controller 并不处理这些具体某个 Item 的事情。
### DockItem Controller
由于插件的复杂性与特殊性, 专门为插件管理加了一层包装。DockItem Controller 是 ItemController 的一部分,专门负责插件类型的 Items 的创建、排序等相关操作。同时,也是作为 dock 主程序到插件之间的一个 proxy 的作用。
### MainPanel
`MainPanel` 是主界面上的唯一控件,是容纳所有 Items 的地方。这个类接受来自 ItemController 的控制消息,来更新界面上的 Items 列表。
它主动进行的操作只有两种:
- d& d 操作的处理。它接受 drag & drop 事件,对事件进行处理并显示动画。中间过程全部是临时数据。当用户操作完毕后,它将最终的控制信号发送给 ItemsController, 并由接收它发送的信号来更新界面顺序。
- 布局调整处理。在 dock 位置、大小、Items 数量等发生变化后, MainPanel 负责调整每个 Item 的大小并刷新布局。
需要注意的是,主面板类并不直接去控制 Items 列表的顺序,更不会去添加与销毁某个 Item。为了保证解耦, 功能上不能与 Controller 混淆,所以对 Item 的控制操作应该 __全部__ 来自于 ItemController 的控制信号。
2018-07-31 17:24:04 +08:00
### Popup Window
`Popup Window` 是一个特殊的控件。它是所有 Item 中用来显示提示信息,或是显示弹出式控件、列表的一个容器。但是考虑到这种控件使用频率非常高,如果在每个 Item 中创建多个的话很浪费内存,所以将 `PopupWindow` 设计为一个全局的控件,所有的 Item 共用这个控件。
2018-07-31 17:01:58 +08:00
## 插件
插件是符合标准的 Qt Plugins。插件的开发不必熟悉 dock 的所有代码,只需要熟悉一般的 Qt 插件开发过程,并了解 dock 所提供的接口。dock 的接口安装 `dde-dock-dev` 包即可。这也是方便插件开发者在无需配置完整的 dock 开发环境的情况下,更方便的进行 dock 插件的开发。
### 插件开发中的调试方法
在加载插件失败时,主程序会打印相关信息,仔细参考相关日志即可发现大部分问题。一般就是对应插件的 so 中有某些符号没有解析成功,或是插件版本与主程序的版本不相同。
如果插件可以成功加载,即可使用 gdb 等程序进行调试。
# 接口设计
## 插件接口
插件接口定义在 `interfaces/*.h` 中,参考具体类或函数的注释。
2018-07-31 17:24:04 +08:00
## DBus 接口
dock 主程序提供了一个 DBus 服务,可供外部访问到 dock 的 geometryRect 信息。这个信息也可以从后端的接口中读取,创建这个接口的最初目的是用作调试。当 dock 位置不正确时,可以比对此接口的信息与后端的信息。
其中后端的信息代表了 dock 主程序计算的结果,如果这个数据错误,就说明 dock 在位置计算的部分有 bug。
如果后端信息正确,而本接口中的数据错误,那就是计算正确,但是在向 X Server 发送对应的控制请求时出错。
通过检查两个接口的数据是否相同,也是一个进行自我检查的方法。目前在 `MainWindow::positionCheck` 中就进行了这样的操作,当发现两个数据不相同时,就重新向 X Server 发送请求,以此来 workaround 某些情况下 dock 位置不正确的问题。
# 优化
## MainWindow
目前所有的动画都被放在了 `MainWindow` 中进行处理。经过多次的改动,现在 `MainWindow` 中已经有很多动画相关的代码,这使得在进行窗口管理时不得不考虑动画的很多事情。
以后可以尝试将动画部分剔除出来,`MainWindow` 只进行窗口位置、大小等操作,尤其是应该把涉及到 `MainPanel` 动画的部分移动到 `MainPanel` 类中去,以此来减少在 `MainWindow` 中控制其它控件所带来的混乱。
## Popup Window
2018-07-31 17:01:58 +08:00
2018-07-31 17:24:04 +08:00
共用 `PopupWindow` 带来了很多好处,但是如果在使用时没有好好处理 data race、或是在 Tips Window 与 Model Window 切换中没有处理好顺序,就会造成很难调试,也很难处理的问题。可以尝试在这方面做一些优化。