第13章 Xournal++ 插件开发指南
Building Plugins¶ Xournal++ 提供基础 Lua 插件接口。插件无需从源码构建 Xournal++ 即可添加。其主要用途包括添加用户特定功能、快捷键、调用外部程序、定义用户特定导出功能等。 总体而言,Lua 插件接口仍处于早期阶段,未来将会扩展。 若使用 Lua 插件,请确保设备上已安装 Lua(版本 >=5.3)。
Plugin manager¶ 插件需在插件管理器(通过菜单“Plugin > Plugin manager”)中激活或停用。插件管理器列出每个插件的安装文件夹、描述、作者和版本。仅激活的插件会显示在菜单栏中,且仅那些可运行。其他插件被安全排除。注意,更改插件激活状态需重启 Xournal++。
Installation folder¶ 随 Xournal++ 发布的插件位于同一文件夹,即 shared resources 文件夹的 plugins 子文件夹中。 在最新开发版本中,自定义插件可存储在 config 文件夹的 plugins 子文件夹中。若该文件夹不存在,请手动创建。 每个插件的文件存储在插件文件夹的子文件夹中,至少包含一个 plugin.ini 文件和一个 Lua 代码文件。
Plugin structure¶ plugin.ini 文件包含作者姓名、版本号、是否默认启用的信息,以及主 Lua 代码文件的引用。示例文件(引用 main.lua)如下:
plugin.ini¶ [about] ## Author / Copyright notice author=作者姓名
description=插件描述
## 若插件随 Xournal++ 打包,使用
##
[default] enabled=false
[plugin] mainfile=main.lua
plugin.ini 中引用的 Lua 代码文件必须定义 initUi 函数,该函数注册工具栏操作并初始化所有 UI 内容。它应调用 app.registerUi 函数,其参数是一个 Lua 表,包含
Xournal++ 菜单栏中显示的菜单名称,
当通过菜单或键盘快捷键调用插件时使用的回调函数,
执行插件回调函数所用的快捷键。格式如
可通过多次调用 app.registerUi,在同一插件中注册多个菜单条目/快捷键。 主 Lua 代码文件示例:
main.lua¶
-- Register all Toolbar actions and intialize all UI stuff
function initUi()
app.registerUi({["menu"] = "NAME", ["callback"] = "run", ["accelerator"] = "
-- 菜单项执行时的回调 function run() -- 添加类似如下代码 -- app.uiAction({["action"]="ACTION_TOOL_PEN"}) -- 切换到钢笔工具,或 -- app.changeToolColor({["color"] = 0xff0000, ["selection"] = true}) -- 将当前工具颜色改为红色 end
更多详细插件示例,可查看 Xournal++ 仓库中随附插件的代码。
Plugin API¶ Error-handling¶ xournalpp Lua-API 函数会返回 Lua 错误,当发生意外(如参数错误)时,可通过 pcall 调用函数来处理。在罕见情况下,可能静默抛出 nil, errorMessage 错误。这预留给预期内的情形(如资源不可用)。可通过 assert 包裹将此类错误转为 Lua 错误。
Functions¶ 任何 Lua 插件均可执行一系列 Xournal++ 函数以与 Xournal++ 交互。这些函数在插件 API 的定义文件中定义。该文件列出所有 Xournal++ 函数、其参数、返回值和使用示例。此外,可结合 Lua 语言服务器使用,实现代码补全、悬停提示、跳转定义、查找引用等。使用支持 Lua 语言服务器的众多代码编辑器之一编写插件较为合理。若需了解这些 Xournal++ 函数如何定义,请参阅适用于你 xournalpp 版本的 luapi_application.h 文件:
1.1.x 系列 1.2.x 系列 nightly 构建
使用插件为 ui 操作定义快捷键¶ 目前 Xournal++ 偏好设置中无可配置的快捷键/键绑定。但你可编写自定义插件实现此功能。 用于模拟工具栏/菜单栏点击的 app.uiAction 函数可用于许多不同操作。 该命令接受一个 Lua 表作为参数,键为 "action" 和 "enabled"。"enabled" 键默认为 true,故常可省略。"action" 键接受 ActionBackwardCompatibilityLayer.cpp 源文件中列出的操作字符串之一。注意,当 Xournal++ 添加新功能时,操作列表会变化。 例如使用: app.uiAction({ action = "ACTION_RULER" })
激活标尺(用于绘制线段),或 app.uiAction({ action = "ACTION_TOOL_FILL", enabled = false })
关闭形状填充。
获取文档信息并遍历页面和图层¶ app.getDocumentStructure 函数生成如下形状的 Lua 表: { pages = { { pageWidth = number, pageHeight = number, isAnnoated = bool, pageTypeFormat = string, pdfBackgroundPageNo = integer (若无非背景 PDF 页则为 0), layers = { [0] = { isVisible = bool }, [1] = { isVisible = bool, isAnnotated = bool }, ... }, currentLayer = integer }, ... } currentPage = integer, pdfBackgroundFilename = string (若无则空) }
例如,获取所有页面数、当前页码和当前图层 ID,使用代码: local docStructure = app.getDocumentStructure() local numPages = #docStructure.pages local currPage = docStructure.currentPage local currLayer = docStructure.pages[currPage].currentLayer
可通过以下行遍历所有页面: local docStructure = app.getDocumentStructure() local numPages = #docStructure.pages for i=1, numPages do -- 添加对第 i 页执行的代码 end
类似地,可遍历页面的所有图层。对当前页则如: local docStructure = app.getDocumentStructure() local page = docStructure.currentPage local numLayers = #docStructure.pages[page].layers for i=1, numLayers do -- 添加对第 i 图层执行的代码 end
使用 Lua 模块¶ 更复杂的插件需要 Lua 模块执行特定操作。例如,若插件需要更复杂的 GUI 或想在预定时间间隔重复任务,可使用 require("lgi") 的 lgi 模块。 Lua 包路径默认包含插件根文件夹和系统 Lua 包路径。 若包路径需其他文件夹,使用 package.path 键添加。