Compare commits
102 Commits
51ee526268
...
0a1b176032
Author | SHA1 | Date |
---|---|---|
zinface | 0a1b176032 | |
zinface | 69791ec3d4 | |
zinface | 17de64d288 | |
zinface | 7c3ab6b3e0 | |
zinface | a4c4c2bb38 | |
爬山虎 | ee35169ac4 | |
爬山虎 | a25c215bec | |
zinface | 1807b73840 | |
爬山虎 | 8d115ee553 | |
zinface | 03080aceff | |
zinface | 0ba627d75b | |
爬山虎 | 3703787975 | |
高乐喆 | 541dbd8b39 | |
zinface | 1346c6ad6a | |
zinface | 5a78b0b7d5 | |
zinface | 0f1fdf51d7 | |
zinface | 0292adb402 | |
zinface | f1b56e2438 | |
zinface | bc411b200d | |
zinface | bac93a1b2b | |
zinface | bcfc8494b0 | |
zinface | fc3986fd3f | |
zinface | 62ae5ab332 | |
zinface | 395336704a | |
zinface | 169d327485 | |
zinface | c1fdfbfcb7 | |
zinface | 8310215faa | |
zinface | f232da29c7 | |
zinface | 199f57b975 | |
zinface | eca90aacbd | |
zinface | 93b66b1651 | |
zinface | 1770af797d | |
zinface | 8c68f8b8dc | |
zinface | f2862392ee | |
zinface | b6c27ca8b7 | |
zinface | df033e899e | |
zinface | bd756a8e9e | |
zinface | e4ab5422e5 | |
zinface | 880ba6c0bb | |
zinface | 13dad44cbc | |
zinface | 1acc604635 | |
zinface | 2ba318b34e | |
zinface | d25422e65b | |
zinface | 7936831b6e | |
zinface | 1f3408c621 | |
zinface | ecfc9273a4 | |
zinface | 4c63813eeb | |
zinface | cd91e69268 | |
zinface | f9f82c66ca | |
zinface | 4fedd93d1a | |
zinface | 06b4549140 | |
zinface | f7277e6660 | |
zinface | 4792607f9d | |
zinface | 696471371e | |
zinface | d8aad108f1 | |
zinface | dffdfe82c9 | |
zinface | aba6da24dd | |
zinface | 474aa840ec | |
zinface | 6597452033 | |
zinface | 824d367191 | |
zinface | a5fab253e3 | |
zinface | d0506e058d | |
zinface | 248e3c1f04 | |
zinface | 0c96e64c97 | |
zinface | e50b7d3ef0 | |
zinface | 721bfdb056 | |
zinface | 40f81950ee | |
zinface | cb80ce5b2b | |
zinface | 496437bd49 | |
zinface | 794f6ad7bf | |
zinface | 9459ad6e6e | |
zinface | 87d21a0279 | |
zinface | a5a270944c | |
zinface | c9d84a4749 | |
zinface | 24024c5997 | |
zinface | 607ca11d92 | |
zinface | 9130083e8f | |
zinface | 43fd6b0743 | |
zinface | 025e0e8f65 | |
zinface | 3ed8f418ee | |
zinface | cd8364c16f | |
zinface | 6249c13434 | |
zinface | 34b7f57739 | |
zinface | 6cd5a564b4 | |
zinface | b929bca982 | |
zinface | a55f53bfd3 | |
zinface | 93a6b86cd0 | |
zinface | d7d44985a6 | |
zinface | a5bc93c44a | |
zinface | 04d866ea89 | |
zinface | a2f9673737 | |
zinface | 0415bf2506 | |
zinface | 99e3db95ab | |
zinface | e600007e75 | |
zinface | d65d9b970c | |
zinface | 2d4252697c | |
zinface | d3e24e173b | |
zinface | 04de7202b1 | |
zinface | dbfbce1c80 | |
zinface | 765eba148f | |
zinface | 1b28afacc0 | |
zinface | 2186c013d6 |
|
@ -526,4 +526,5 @@ _deps
|
|||
# If you copy here and customize the build form, its changes will be ignored.
|
||||
|
||||
# Windows cmd or powershell supported files..
|
||||
/windows-msvc-ninja.bat
|
||||
/windows-msvc-ninja.bat
|
||||
/3rd_plugins_cache
|
|
@ -0,0 +1,8 @@
|
|||
# 3rd_plugins_cache
|
||||
|
||||
> 此处存储由框架构建自动缓存引用的项目,为了提供更好的引用间维护
|
||||
|
||||
如插件间开发,引用间调试,资源引用构建,插件代码调整等操作可在此处集中配置。
|
||||
|
||||
|
||||
开发者请在:src/plugin/dev.cmake 中编写插件
|
|
@ -1,24 +1,37 @@
|
|||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
include(cmake/SparkWithGit.cmake)
|
||||
|
||||
spark_include(SparkCMakeInfoBeforeConfig.cmake)
|
||||
project(Notepad-- VERSION 2.0.0)
|
||||
spark_include(SparkCMakeInfoAfterConfig.cmake)
|
||||
|
||||
# -------------- Notepad -- 全局构建配置 ------------- #
|
||||
option(USE_QT6 "使用 Qt6 进行编译本项目与随带所有内容" OFF)
|
||||
|
||||
include(cmake/SparkEnvConfig.cmake)
|
||||
include(cmake/SparkMacrosConfig.cmake)
|
||||
spark_include(cmake/SparkEnvConfig.cmake)
|
||||
spark_include(cmake/SparkMacrosConfig.cmake)
|
||||
if(USE_QT6)
|
||||
include(cmake/SparkFindQt6Config.cmake)
|
||||
else()
|
||||
include(cmake/SparkFindQt5Config.cmake)
|
||||
endif(USE_QT6)
|
||||
include(cmake/SparkMacrosExtendConfig.cmake)
|
||||
spark_include(SparkMacrosExtendConfig.cmake)
|
||||
include(cmake/SparkCMakeDebugConfig.cmake)
|
||||
|
||||
# 引用构建起始
|
||||
set(SPARK_FRAMEWORK_STORE "${CMAKE_SOURCE_DIR}/3rd_plugins_cache")
|
||||
spark_include(SparkFramework.cmake)
|
||||
|
||||
# ----------------- 构建之前 全局定义 ----------------- #
|
||||
# 在 Windows 中开启 UNICODE 以支持 TCHAR 功能
|
||||
if(WIN32)
|
||||
add_compile_definitions(_UNICODE= UNICODE=)
|
||||
# TODO: move to cmake/platforms/windows-msvc.cmake
|
||||
if(MSVC)
|
||||
# MSVC 编译器处理方案,支持 utf-8 编码的项目,同时为扩展的插件提供能力
|
||||
add_compile_options(/utf-8)
|
||||
endif(MSVC)
|
||||
endif()
|
||||
# 符合 2.0.0 代码预期的版本处理, 核心编辑器组件 2.11
|
||||
add_compile_definitions(TEST_PRE)
|
||||
|
@ -34,6 +47,9 @@ if(TRUE)
|
|||
include(cmake/modules/Notepad--.cmake)
|
||||
endif(TRUE)
|
||||
|
||||
# ----------------- 构建 Notepad-- 插件 ----------------- #
|
||||
add_subdirectory(src/plugin)
|
||||
|
||||
# ----------------- Notepad-- 其它主线构建相关 ----------------- #
|
||||
option(USE_WINDOWS_UNIVERSAL "通用 Windows 平台构建" OFF)
|
||||
option(USE_WINDOWS_MINGW "通用 Windows 平台 MinGW 构建" OFF)
|
||||
|
@ -126,3 +142,7 @@ if(USE_QT6)
|
|||
message(NOTICE "[${QT56_PASS}] Qt5/Qt6 兼容性检查文件当前检查通过。")
|
||||
endif(NOT QT56_PASS)
|
||||
endif(USE_QT6)
|
||||
|
||||
|
||||
# 在全局结束位置使用 cmake-debug 目标来驱动内部调试信息打印
|
||||
spark_generator_cmake_debug(cmake-debug)
|
23
README.md
|
@ -12,22 +12,21 @@ Notepad-- 是使用C++编写的轻量级文本编辑器, 简称ndd, 可以支持
|
|||
|
||||
**鉴于某些Notepad竞品作者的不当言论,Notepad--的意义在于:减少一点错误言论,减少一点自以为是。**
|
||||
|
||||
**Notepad--的目标,致力于国产软件的可替代,专心做软件。**
|
||||
**Notepad--的目标:致力于国产软件的可替代,专心做软件。**
|
||||
|
||||
您可以在这个项目提交bug或反馈问题。
|
||||
|
||||
最新版本下载地址:https://gitee.com/cxasm/notepad--/releases/latest
|
||||
|
||||
NDD 具备插件编写功能,如果您愿意开发插件,还请提交给我们。
|
||||
|
||||
做国人自己的免费编辑器,离不开您的支持,请通过微信众筹支持我们。(留言处留下邮件,会发送您正版激活码)
|
||||
|
||||
众筹捐赠支持本项目的热心用户,也请留言处留下邮箱,会发送正版激活码,后续也可以发邮件给作者索要激活码。
|
||||
|
||||
![输入图片说明](6688.png)
|
||||
|
||||
## 编译
|
||||
|
||||
**分支说明:cmake-dev 与 cmake-plugins-dev(已合并)**
|
||||
|
||||
cmake-plugins-dev 已合并到 cmake-dev,所有插件构建相关问题基本修复完成。
|
||||
基于引用构建,扩展代码将会以引用形式依赖或提供构建能力。
|
||||
|
||||
**CMake工具链编译说明:**
|
||||
|
||||
- Windows 系统通用构建 - 基于 Batch 脚本进行构建
|
||||
|
@ -39,6 +38,14 @@ NDD 具备插件编写功能,如果您愿意开发插件,还请提交给我
|
|||
;; 使用脚本进行构建,它将会询问如何进行构建
|
||||
windows-msvc-ninja.bat
|
||||
```
|
||||
- Windows 系统 QtCreator 构建 - MSVC/MinGW
|
||||
|
||||
```batch
|
||||
;; 支持 MSVC 与 MinGW 两种编译器与依赖库方案
|
||||
;; 1. 将 CMakeLists.txt 拖入 QtCreator 并选择编译方案
|
||||
;; MSVC 编译速度快,MinGW 编译较慢
|
||||
;; 2. 扩展开发需要与当前主程序使用的编译器相同
|
||||
```
|
||||
|
||||
- Windows 系统 VSCode 构建 - 基于 VSCode 配置模板进行调整构建
|
||||
|
||||
|
@ -186,7 +193,7 @@ yay -S notepad---git
|
|||
```
|
||||
## 联络方式
|
||||
|
||||
QQ群:213027225(新开) 372613546(已满) 959439826(已满)728578708(已满) 用户群,做NDD的问题反馈、功能建议等。
|
||||
QQ群:234879615(新开) 用户群,做NDD的问题反馈、功能建议等。
|
||||
|
||||
QQ群 616606091 开发群,建议懂CPP/QT、愿意参与NDD项目代码贡献的开发人士加入。
|
||||
|
||||
|
|
|
@ -1,192 +0,0 @@
|
|||
# SparkAppimageConfig.cmake
|
||||
|
||||
# 1. 在使用时通过准备默认的 icon 与 SparkDesktopConfig.cmake 在生成 desktop 文件
|
||||
# 时进行借用 desktop 文件中的基本描述完成 spark-appimage.dekstop 文件的生成,
|
||||
# 并在使用 add_appimage 时完成所有逻辑判断与目标的定义
|
||||
# add_appimage_icon
|
||||
# add_appimage_desktop
|
||||
# add_appimage
|
||||
|
||||
# 2. 在 add_appimage 中,我们判断了是否为 cmake 提供了 LINUXDEPLOYQT 宏,
|
||||
# 并获取此工具的真实路径。并继续判断了 APPIMAGETOOL 宏与该工具的真实路径。
|
||||
# 然后,创建一个目录,用于即将进行的 Appimage 打包。
|
||||
|
||||
# 通过调用 target_linuxdeploy() 来完成 linuxdeploy 的目标创建
|
||||
# 通过调用 target_appimage() 来完成 appimage 的目标创建
|
||||
|
||||
# 3. 对于 linuxdeploy 目标,大致上就是通过执行 linuxdeployqt 命令与 -appimage
|
||||
# 参数来创建可用于 Appimage 打包的内容结构,并且使用一些参数来处理相关库的依赖。
|
||||
# 其次就是,将 spark-appimage.desktop 复制为 default.desktop
|
||||
# 另一个就是 spark-appimage.png 复制为 default.png
|
||||
|
||||
# 4. 对于 appimage 目标,大致上就是通过执行 appimagetool 命令将准备好打包的目录
|
||||
# 结构进行打包为 Appimage 可执行文件,其中为了避免可能缺失的文件,重复了对
|
||||
# default.desktop 文件与 default.png 文件的生成。
|
||||
# 这是一个依赖的 copy-desktop-appimage 目标,并先行执行
|
||||
|
||||
# 要求:
|
||||
# LINUXDEPLOYQT 提供的外部参数,一般指 linuxdeployqt 程序路径
|
||||
# APPIMAGETOOL 提供的外部参数,一般指 appimagetool 程序路径
|
||||
|
||||
option(USE_APPIMAGE_NEW_GLIBC "允许在打包过程中使用较新版本的 glibc 库" ON)
|
||||
|
||||
set(APPIMAGE_OUTPUT "${CMAKE_BINARY_DIR}/appimage")
|
||||
set(APPIMAGE_OUTPUT_ICON "${APPIMAGE_OUTPUT}/default.png")
|
||||
set(APPIMAGE_OUTPUT_DESTKOP "${APPIMAGE_OUTPUT}/default.desktop")
|
||||
|
||||
# 1. 添加一个可以用于 Appimage 使用的图标文件
|
||||
function(add_appimage_icon _icon)
|
||||
if(CMAKE_VERSION VERSION_LESS 3.21)
|
||||
message("> cmake version is less than 3.21")
|
||||
configure_file(${_icon} ${APPIMAGE_OUTPUT_ICON} COPYONLY)
|
||||
else()
|
||||
file(MAKE_DIRECTORY ${APPIMAGE_OUTPUT})
|
||||
file(COPY_FILE ${_icon} ${APPIMAGE_OUTPUT_ICON})
|
||||
endif(CMAKE_VERSION VERSION_LESS 3.21)
|
||||
endfunction(add_appimage_icon _icon)
|
||||
|
||||
# 2. 基于 SparkDesktopMacros.cmake 提供的宏来定义 desktop 内容说明
|
||||
# 使用与自身的 desktop.in 模板进行生成
|
||||
function(add_appimage_desktop)
|
||||
configure_file(cmake/spark-appimage.desktop.in.txt
|
||||
${APPIMAGE_OUTPUT_DESTKOP} @ONLY)
|
||||
endfunction(add_appimage_desktop)
|
||||
|
||||
function(target_linuxdeploy _target)
|
||||
|
||||
if(USE_APPIMAGE_NEW_GLIBC)
|
||||
message("Use New glibc")
|
||||
add_custom_target(linuxdeploy pwd
|
||||
BYPRODUCTS appimage
|
||||
COMMAND "${LINUXDEPLOYQT}" $<TARGET_FILE:${_target}> -appimage -unsupported-allow-new-glibc -verbose=3 -no-strip || true
|
||||
WORKING_DIRECTORY "${APPIMAGE_OUTPUT}")
|
||||
else()
|
||||
message("Un Use New glibc")
|
||||
add_custom_target(linuxdeploy pwd
|
||||
BYPRODUCTS appimage
|
||||
COMMAND "${LINUXDEPLOYQT}" $<TARGET_FILE:${_target}> -appimage -verbose=3 -no-strip || true
|
||||
WORKING_DIRECTORY "${APPIMAGE_OUTPUT}")
|
||||
endif(USE_APPIMAGE_NEW_GLIBC)
|
||||
|
||||
endfunction(target_linuxdeploy _target)
|
||||
|
||||
function(target_appimage)
|
||||
add_custom_target(appimage pwd
|
||||
COMMAND ${APPIMAGETOOL} ${APPIMAGE_OUTPUT}
|
||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}")
|
||||
endfunction(target_appimage)
|
||||
|
||||
# 3. 添加对目标的 Appimage 构建,Appimage 在一个项目中只能构建一个目标
|
||||
function(add_appimage_target _target)
|
||||
# check linuxdeploy
|
||||
if(NOT DEFINED LINUXDEPLOYQT)
|
||||
message("AppImage> Not Found LINUXDEPLOYQT Variable!")
|
||||
return()
|
||||
endif(NOT DEFINED LINUXDEPLOYQT)
|
||||
if(CMAKE_VERSION VERSION_LESS 3.19)
|
||||
message("> cmake version is less than 3.19")
|
||||
if(CMAKE_VERSION VERSION_GREATER 3.4)
|
||||
get_filename_component(LINUXDEPLOYQT_REAL_PATH ${LINUXDEPLOYQT} REALPATH)
|
||||
else()
|
||||
message("> cmake version is less than 3.4")
|
||||
message(WARNING "!Relative paths are not supported!")
|
||||
endif(CMAKE_VERSION VERSION_GREATER 3.4)
|
||||
else()
|
||||
file(REAL_PATH ${LINUXDEPLOYQT} LINUXDEPLOYQT_REAL_PATH)
|
||||
endif(CMAKE_VERSION VERSION_LESS 3.19)
|
||||
message("AppImage> Found LINUXDEPLOYQT Variable: ${LINUXDEPLOYQT_REAL_PATH}")
|
||||
|
||||
# check appimagetool
|
||||
if(NOT DEFINED APPIMAGETOOL)
|
||||
message("AppImage> Not Found APPIMAGETOOL Variable!")
|
||||
return()
|
||||
endif(NOT DEFINED APPIMAGETOOL)
|
||||
if(CMAKE_VERSION VERSION_LESS 3.19)
|
||||
# execute_process(COMMAND realpath ${APPIMAGETOOL} OUTPUT_VARIABLE APPIMAGETOOL_REAL_PATH)
|
||||
message("> cmake version is less than 3.19")
|
||||
if(CMAKE_VERSION VERSION_GREATER 3.4)
|
||||
get_filename_component(APPIMAGETOOL_REAL_PATH ${APPIMAGETOOL} REALPATH)
|
||||
else()
|
||||
message("> cmake version is less than 3.4")
|
||||
message(WARNING "!Relative paths are not supported!")
|
||||
endif(CMAKE_VERSION VERSION_GREATER 3.4)
|
||||
else()
|
||||
file(REAL_PATH ${APPIMAGETOOL} APPIMAGETOOL_REAL_PATH)
|
||||
endif(CMAKE_VERSION VERSION_LESS 3.19)
|
||||
message("AppImage> Found APPIMAGETOOL Variable: ${APPIMAGETOOL}")
|
||||
|
||||
# do add_custome_target
|
||||
make_directory(${APPIMAGE_OUTPUT})
|
||||
target_linuxdeploy(${_target})
|
||||
target_appimage()
|
||||
|
||||
# 重设目标输出的目录
|
||||
set_target_properties(${_target}
|
||||
PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY "${APPIMAGE_OUTPUT}")
|
||||
|
||||
# 为解决在不使用 -unsupported-allow-new-glibc 参数时,
|
||||
# 可能不会生成 AppRun 软链接的问题
|
||||
if(NOT USE_APPIMAGE_NEW_GLIBC)
|
||||
set_target_properties(${_target}
|
||||
PROPERTIES
|
||||
RUNTIME_OUTPUT_NAME "AppRun")
|
||||
endif(NOT USE_APPIMAGE_NEW_GLIBC)
|
||||
|
||||
endfunction(add_appimage_target _target)
|
||||
|
||||
|
||||
# 如果 glic>=2.27, 你就需要加上参数 -unsupported-allow-new-glibc 意思就是不再低版本发行版使用了
|
||||
# 或 -unsupported-bundle-everything
|
||||
# 大概的意思是尝试兼容,实际测试,到其他发行版直接用不了了,有可能是发行版的原因,还是建议用前者,虽然放弃了低版本
|
||||
|
||||
# -unsupported-bundle-everything
|
||||
# 捆绑所有依赖库,包括 ld-linux.so 加载器和 glibc。
|
||||
# 这将允许构建在较新系统上的应用程序在较旧的目标系统上运行,
|
||||
# 但不建议这样做,因为它会导致捆绑包超出所需的大小(并且可能到其他发行版无法使用)
|
||||
# -unsupported-allow-new-glibc
|
||||
# 允许 linuxdeployqt 在比仍受支持的最旧 Ubuntu LTS 版本更新的发行版上运行。
|
||||
# 这将导致 AppImage无法在所有仍受支持的发行版上运行,既不推荐也不测试或支持
|
||||
|
||||
# 对 linuxdeployqt 的使用
|
||||
# ./linuxdeployqt-7-x86_64.AppImage
|
||||
# 程序目录/程序 -appimage -unsupported-allow-new-glibc
|
||||
# ./linuxdeployqt-7-x86_64.AppImage
|
||||
# 程序目录/程序 -appimage -unsupported-bundle-everything
|
||||
|
||||
|
||||
|
||||
|
||||
# 1. 在顶层构建中导入 Appimage 的构建
|
||||
# include(cmake/SparkAppimageConfig.cmake) # 导入来自 Spark 构建的 Appimage 构建
|
||||
# add_appimage_icon(assets/spark.png) # 添加到 Appimage 中的默认的图标
|
||||
# add_appimage_desktop() # 添加到 Appimage 中的默认desktop(使用来自 Spark 构建的 Desktop 构建中配置的信息(必须要求 spark-desktop))
|
||||
# add_appimage_target(${PROJECT_NAME}) # 添加到 Appimage 中的默认目标,应用对 Appimage 的构建
|
||||
|
||||
# 2. 在 Makefile 进行构建目标构建 Appimage 的构建流 --
|
||||
# 在 Makefile 进行构建目标构建 Appimage (要求提供工具的绝对路径,然后可依次进行linuxdeployqt, genrate-appimage)
|
||||
# 来自于 https://github.com/probonopd/linuxdeployqt 的 linuxdeployqt
|
||||
# 来自于 https://github.com/AppImage/AppImageKit 的 appimagetool
|
||||
# 来自于 https://gitlink.org.cn/zinface/bundle-linuxdeployqt.git 托管存储的工具
|
||||
|
||||
# 或指定你所想存放克隆项目的位置
|
||||
# BUNDLE_LINUXDEPLOYQT := $(shell pwd)/build/bundle-linuxdeployqt
|
||||
|
||||
# download-bundle-linuxdeploytools:
|
||||
# -git clone https://gitlink.org.cn/zinface/bundle-linuxdeployqt.git $(BUNDLE_LINUXDEPLOYQT)
|
||||
|
||||
# LINUXDEPLOYQT := "$(BUNDLE_LINUXDEPLOYQT)/linuxdeployqt-continuous-x86_64.AppImage"
|
||||
# APPIMAGETOOL := "$(BUNDLE_LINUXDEPLOYQT)/appimagetool-x86_64.AppImage"
|
||||
|
||||
# linuxdeploy: release download-bundle-linuxdeploytools
|
||||
# cd build && cmake .. -DLINUXDEPLOYQT=$(LINUXDEPLOYQT) -DAPPIMAGETOOL=$(APPIMAGETOOL)
|
||||
# cd build && make linuxdeploy
|
||||
|
||||
# genrate-appimage:
|
||||
# cd build && cmake .. -DLINUXDEPLOYQT=$(LINUXDEPLOYQT) -DAPPIMAGETOOL=$(APPIMAGETOOL)
|
||||
# cd build && make appimage
|
||||
|
||||
|
||||
|
||||
# NOTE:
|
||||
# 如果使用的库不存在于系统路径,则需要配置 export LD_LIBRARY_PATH=<路径> 以便 linuxdeployqt 可搜索到库的位置
|
|
@ -1,8 +0,0 @@
|
|||
cmake_minimum_required(VERSION 3.5.1)
|
||||
|
||||
# 添加构建项目依赖图目标: make builddeps
|
||||
add_custom_target(builddeps
|
||||
COMMAND "${CMAKE_COMMAND}" "--graphviz=graphviz/builddeps.dot" .
|
||||
COMMAND dot -Tpng graphviz/builddeps.dot -o builddeps.png
|
||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
|
||||
)
|
|
@ -0,0 +1,41 @@
|
|||
# SparkCMakeDebugConfig.cmake
|
||||
|
||||
option(SPARK_CMAKE_DEBUG "CMake内部信息调试能力" ON)
|
||||
|
||||
set(SPARK_CMAKE_DEBUG_FILE "${CMAKE_BINARY_DIR}/spark_debug.txt")
|
||||
set(SPARK_CMAKE_CONTENT_FILE "${CMAKE_BINARY_DIR}/spark_debug_content.txt")
|
||||
|
||||
# 模块内部初始化空信息文件
|
||||
file(WRITE ${SPARK_CMAKE_CONTENT_FILE} "")
|
||||
|
||||
# spark_cmake_debug <message> ...
|
||||
# 添加、增量需要准备生成的的调试内容。
|
||||
function(spark_cmake_debug)
|
||||
list(JOIN ARGN "\n" _content)
|
||||
file(APPEND ${SPARK_CMAKE_CONTENT_FILE} "${_content}\n")
|
||||
endfunction()
|
||||
|
||||
# spark_generator_cmake_debug <target>
|
||||
# 生成 <target> 目标来驱动打印调试内容
|
||||
function(spark_generator_cmake_debug _target)
|
||||
add_custom_target(${_target}
|
||||
COMMAND ${CMAKE_COMMAND} -E cat
|
||||
${SPARK_CMAKE_DEBUG_FILE}
|
||||
)
|
||||
file(GENERATE
|
||||
OUTPUT
|
||||
${SPARK_CMAKE_DEBUG_FILE}
|
||||
INPUT
|
||||
${SPARK_CMAKE_CONTENT_FILE})
|
||||
endfunction(spark_generator_cmake_debug _target)
|
||||
|
||||
|
||||
#
|
||||
# 1. 使用 spark_cmake_debug( <content> [...])
|
||||
# 添加、增量需要准备生成的的调试内容。
|
||||
# 支持普通文本、变量求值、生成器表达式求值。
|
||||
#
|
||||
# 2. 使用 spark_generator_cmake_debug( <target> )
|
||||
# 生成 <target> 目标来驱动打印调试内容
|
||||
# 仅建议在全局结束位置使用此 function
|
||||
#
|
|
@ -1,366 +0,0 @@
|
|||
cmake_minimum_required(VERSION 3.0.0)
|
||||
|
||||
# function(add_deb_package PACKAGE_NAME PACKAGE_VERSION PACKAGE_MAINTAINER PACKAGE_EMAIL PACKAGE_SHORT_DESCRIPTION PACKAGE_LONG_DESCRIPTION)
|
||||
|
||||
# endfunction(add_deb_package PACKAGE_NAME PACKAGE_VERSION PACKAGE_MAINTAINER PACKAGE_EMAIL PACKAGE_SHORT_DESCRIPTION PACKAGE_LONG_DESCRIPTION)
|
||||
|
||||
# if(add_deb_package VALUE) set(Package ${VALUE} PARENT_SCOPE) endif(add_deb_package VALUE)
|
||||
# if(add_deb_version VALUE) set(Version ${VALUE} PARENT_SCOPE) endif(add_deb_version VALUE)
|
||||
# if(add_deb_maintainer VALUE) set(Maintainer ${VALUE} PARENT_SCOPE) endif(add_deb_maintainer VALUE)
|
||||
# if(add_deb_email VALUE) set(Email ${VALUE} PARENT_SCOPE) endif(add_deb_email VALUE)
|
||||
# if(add_deb_descrition VALUE) set(Descrition ${VALUE} PARENT_SCOPE) endif(add_deb_descrition VALUE)
|
||||
# if(add_deb_detail VALUE) set(Detail ${VALUE} PARENT_SCOPE) endif(add_deb_detail VALUE)
|
||||
|
||||
|
||||
# set(Package "")
|
||||
# set(Version "")
|
||||
# set(Architecture "")
|
||||
# set(Maintainer "")
|
||||
# set(Email "")
|
||||
# set(Descrition "")
|
||||
|
||||
function(find_str _IN _SEP _OUT)
|
||||
string(FIND "${_IN}" "${_SEP}" _TMP)
|
||||
set(${_OUT} ${_TMP} PARENT_SCOPE)
|
||||
endfunction(find_str _IN _SEP _OUT)
|
||||
|
||||
|
||||
function(find_next _IN _OUT)
|
||||
find_str("${_IN}" "\n" _TMP)
|
||||
set(${_OUT} ${_TMP} PARENT_SCOPE)
|
||||
endfunction(find_next _IN _OUT)
|
||||
|
||||
function(sub_next _IN _INDEX _OUT __OUT)
|
||||
find_next(${_IN} _NEXTINDEX)
|
||||
string(SUBSTRING "${_IN}" ${_INDEX} ${_NEXTINDEX} _TMP)
|
||||
math(EXPR _NEXTINDEX ${_NEXTINDEX}+1)
|
||||
string(SUBSTRING "${_IN}" ${_NEXTINDEX} -1 __TMP)
|
||||
set(${_OUT} ${_TMP} PARENT_SCOPE)
|
||||
set(${__OUT} ${__TMP} PARENT_SCOPE)
|
||||
endfunction(sub_next _IN _INDEX _OUT)
|
||||
|
||||
function(trim_str _IN _OUT)
|
||||
string(STRIP "${_IN}" _TMP)
|
||||
set(${_OUT} ${_TMP} PARENT_SCOPE)
|
||||
endfunction(trim_str _IN _OUT)
|
||||
|
||||
function(split_str _IN _SEP _OUT)
|
||||
string(FIND "${_IN}" "${_SEP}" _TMP_INDEX)
|
||||
if(NOT _TMP_INDEX EQUAL -1)
|
||||
string(SUBSTRING "${_IN}" 0 ${_TMP_INDEX} _TMP)
|
||||
math(EXPR _TMP_INDEX ${_TMP_INDEX}+1)
|
||||
string(SUBSTRING "${_IN}" ${_TMP_INDEX} -1 __TMP)
|
||||
set(${_OUT} "${_TMP};${__TMP}" PARENT_SCOPE)
|
||||
else()
|
||||
set(${_OUT} ${_IN} PARENT_SCOPE)
|
||||
endif(NOT _TMP_INDEX EQUAL -1)
|
||||
endfunction(split_str _IN _SEP _OUT)
|
||||
|
||||
function(split_str_p _IN _SEP _OUT __OUT)
|
||||
split_str("${_IN}" "${_SEP}" _TMP)
|
||||
list(GET _TMP 0 __TMP)
|
||||
list(GET _TMP 1 ___TMP)
|
||||
set(${_OUT} ${__TMP} PARENT_SCOPE)
|
||||
set(${__OUT} ${___TMP} PARENT_SCOPE)
|
||||
endfunction(split_str_p _IN _SEP _OUT __OUT)
|
||||
|
||||
function(split_str_n _IN _SEP _OUT _N)
|
||||
if(_N GREATER 1)
|
||||
set(_C ${_N})
|
||||
set(_RET "")
|
||||
set(_NEXT ${_IN})
|
||||
while(NOT _C EQUAL 0)
|
||||
split_str("${_NEXT}" "${_SEP}" _TMP)
|
||||
list(LENGTH _TMP _TMP_LEN)
|
||||
if(_TMP_LEN EQUAL 2)
|
||||
list(GET _TMP 0 __TMP)
|
||||
list(GET _TMP 1 _NEXT)
|
||||
list(APPEND _RET ${__TMP})
|
||||
else()
|
||||
break()
|
||||
endif(_TMP_LEN EQUAL 2)
|
||||
math(EXPR _C "${_C}-1")
|
||||
endwhile(NOT _C EQUAL 0)
|
||||
list(APPEND _RET ${_NEXT})
|
||||
set(${_OUT} ${_RET} PARENT_SCOPE)
|
||||
else()
|
||||
split_str("${_IN}" "${_SEP}" _TMP)
|
||||
set(${_OUT} ${_TMP} PARENT_SCOPE)
|
||||
endif(_N GREATER 1)
|
||||
endfunction(split_str_n _IN _SEP _OUT _N)
|
||||
|
||||
|
||||
function(set_package_vars _IN_KEY _IN_VAL)
|
||||
|
||||
# trim_str("${_IN_KEY}" _IN_KEY)
|
||||
|
||||
find_str("${_IN_KEY}" "Type" _Type)
|
||||
if(_Type EQUAL "0")
|
||||
string(TOUPPER "${_IN_VAL}" _IN_VAL_UPPER)
|
||||
string(TOLOWER "${_IN_VAL}" _IN_VAL_LOWER)
|
||||
set(CPACK_GENERATOR "${_IN_VAL_UPPER}" PARENT_SCOPE)
|
||||
message("--> 软件包类型: ${_IN_VAL_LOWER}")
|
||||
endif(_Type EQUAL "0")
|
||||
|
||||
find_str("${_IN_KEY}" "Package" _Package)
|
||||
if(_Package EQUAL "0")
|
||||
if(_IN_VAL STREQUAL "auto")
|
||||
set(CPACK_DEBIAN_PACKAGE_NAME "${PROJECT_NAME}" PARENT_SCOPE)
|
||||
else()
|
||||
set(CPACK_DEBIAN_PACKAGE_NAME "${_IN_VAL}" PARENT_SCOPE)
|
||||
endif(_IN_VAL STREQUAL "auto")
|
||||
message("--> 软件包名: ${_IN_VAL}")
|
||||
endif(_Package EQUAL "0")
|
||||
|
||||
find_str("${_IN_KEY}" "Version" _Version)
|
||||
if(_Version EQUAL "0")
|
||||
if(_IN_VAL STREQUAL "auto")
|
||||
set(CPACK_DEBIAN_PACKAGE_VERSION "${PROJECT_VERSION}" PARENT_SCOPE)
|
||||
else()
|
||||
set(CPACK_DEBIAN_PACKAGE_VERSION "${_IN_VAL}" PARENT_SCOPE)
|
||||
endif(_IN_VAL STREQUAL "auto")
|
||||
|
||||
message("--> 软件版本: ${_IN_VAL}")
|
||||
endif(_Version EQUAL "0")
|
||||
|
||||
find_str("${_IN_KEY}" "CalVer" _CalVer)
|
||||
if(_CalVer EQUAL "0")
|
||||
set(CalVer "${_IN_VAL}" PARENT_SCOPE)
|
||||
message("--> 日历化版本: ${_IN_VAL}")
|
||||
endif(_CalVer EQUAL "0")
|
||||
|
||||
find_str("${_IN_KEY}" "OSD" _OSDVer)
|
||||
if(_OSDVer EQUAL "0")
|
||||
set(OSDVer "${_IN_VAL}" PARENT_SCOPE)
|
||||
message("--> 声明发行版号: ${_IN_VAL}")
|
||||
endif(_OSDVer EQUAL "0")
|
||||
|
||||
find_str("${_IN_KEY}" "Architecture" _Architecture)
|
||||
if(_Architecture EQUAL "0")
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "${_IN_VAL}" PARENT_SCOPE)
|
||||
if(_IN_VAL STREQUAL "auto")
|
||||
execute_process(
|
||||
COMMAND dpkg --print-architecture
|
||||
OUTPUT_VARIABLE _RETV
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "${_RETV}" PARENT_SCOPE)
|
||||
endif(_IN_VAL STREQUAL "auto")
|
||||
message("--> 软件架构: ${_IN_VAL}")
|
||||
endif(_Architecture EQUAL "0")
|
||||
|
||||
find_str("${_IN_KEY}" "Priority" _Priority)
|
||||
if(_Priority EQUAL "0")
|
||||
set(CPACK_DEBIAN_PACKAGE_PRIORITY "${_IN_VAL}" PARENT_SCOPE)
|
||||
message("--> 优先级: ${_IN_VAL}")
|
||||
endif(_Priority EQUAL "0")
|
||||
|
||||
find_str("${_IN_KEY}" "Depends" _Depends)
|
||||
if(_Depends EQUAL "0")
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "${_IN_VAL}" PARENT_SCOPE)
|
||||
message("--> 软件依赖: ${_IN_VAL}")
|
||||
endif(_Depends EQUAL "0")
|
||||
|
||||
find_str("${_IN_KEY}" "Maintainer" _Maintainer)
|
||||
if(_Maintainer EQUAL "0")
|
||||
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "${_IN_VAL}" PARENT_SCOPE)
|
||||
message("--> 软件维护者: ${_IN_VAL}")
|
||||
endif(_Maintainer EQUAL "0")
|
||||
|
||||
find_str("${_IN_KEY}" "Homepage" _Homepage)
|
||||
if(_Homepage EQUAL "0")
|
||||
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "${_IN_VAL}" PARENT_SCOPE)
|
||||
message("--> 软件主页: ${_IN_VAL}")
|
||||
endif(_Homepage EQUAL "0")
|
||||
|
||||
find_str("${_IN_KEY}" "Recommends" _Recommends)
|
||||
if(_Recommends EQUAL "0")
|
||||
set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "${_IN_VAL}" PARENT_SCOPE)
|
||||
message("--> 软件建议: ${_IN_VAL}")
|
||||
endif(_Recommends EQUAL "0")
|
||||
|
||||
find_str("${_IN_KEY}" "Conflicts" _Conflicts)
|
||||
if(_Conflicts EQUAL "0")
|
||||
set(CPACK_DEBIAN_PACKAGE_CONFLICTS "${_IN_VAL}" PARENT_SCOPE)
|
||||
message("--> 软件冲突: ${_IN_VAL}")
|
||||
endif(_Conflicts EQUAL "0")
|
||||
|
||||
endfunction(set_package_vars _IN_KEY _IN_VAL)
|
||||
|
||||
# 定义一个自定义(add_package_descript)函数
|
||||
# 用于按特定配置约定自动化构建软件包配置
|
||||
function(add_package_descript IN_DES)
|
||||
set(PACKAGE_DES_PATH "${IN_DES}")
|
||||
|
||||
if(EXISTS ${IN_DES})
|
||||
|
||||
elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${IN_DES}")
|
||||
set(PACKAGE_DES_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${IN_DES}")
|
||||
else()
|
||||
message(FATAL_ERROR "!! Not Found Path: ${PACKAGE_DES_PATH}")
|
||||
return()
|
||||
endif(EXISTS ${IN_DES})
|
||||
|
||||
file(READ ${PACKAGE_DES_PATH} DES_CONTENT)
|
||||
trim_str("${DES_CONTENT}" DES_CONTENT)
|
||||
|
||||
################## 解析 ##################
|
||||
|
||||
sub_next(${DES_CONTENT} NEXT_INDEX DES_LINE DES_CONTENT)
|
||||
set(PREV_DES "")
|
||||
while(NOT DES_LINE STREQUAL "${PREV_DES}")
|
||||
# 检查该描述行是否是 # 注释开头,是的话将跳过该行
|
||||
find_str("${DES_LINE}" "#" _COMMENT)
|
||||
if(_COMMENT EQUAL "0")
|
||||
message("--> !!!!!!! ${DES_LINE}")
|
||||
sub_next(${DES_CONTENT} NEXT_INDEX DES_LINE DES_CONTENT)
|
||||
continue()
|
||||
endif(_COMMENT EQUAL "0")
|
||||
|
||||
# 检查该描述行是否是 Descrition 开头,是的话说明描述结尾了
|
||||
find_str("${DES_LINE}" "Descrition" _DESCRIPTION)
|
||||
if(_DESCRIPTION EQUAL "0")
|
||||
break()
|
||||
endif(_DESCRIPTION EQUAL "0")
|
||||
|
||||
split_str_n("${DES_LINE}" ":" _TMP 1)
|
||||
list(LENGTH _TMP _TMP_LEN)
|
||||
|
||||
if(_TMP_LEN EQUAL 2)
|
||||
split_str_p("${DES_LINE}" ":" _TMP __TMP)
|
||||
trim_str("${__TMP}" __TMP)
|
||||
string(LENGTH "${__TMP}" __TMP_LENGTH)
|
||||
if(NOT __TMP_LENGTH EQUAL "0")
|
||||
set_package_vars("${_TMP}" "${__TMP}")
|
||||
endif(NOT __TMP_LENGTH EQUAL "0")
|
||||
endif(_TMP_LEN EQUAL 2)
|
||||
|
||||
# 记录当前行,获取下一行,可能是已经结尾了(将保持重复行)
|
||||
set(PREV_DES "${DES_LINE}")
|
||||
sub_next(${DES_CONTENT} NEXT_INDEX DES_LINE DES_CONTENT)
|
||||
endwhile(NOT DES_LINE STREQUAL "${PREV_DES}")
|
||||
|
||||
|
||||
# 再一次检查该描述行是否是 Descrition 开头,是的话将进行分析描述行
|
||||
find_str("${DES_LINE}" "Descrition" _DESCRIPTION)
|
||||
if(_DESCRIPTION EQUAL "0")
|
||||
split_str_p("${DES_LINE}" ":" _TMP __TMP)
|
||||
trim_str("${__TMP}" __TMP)
|
||||
set(Descrition ${__TMP})
|
||||
set(PREV_DES_LINE "")
|
||||
while(NOT PREV_DES_LINE STREQUAL DES_LINE)
|
||||
if(NOT PREV_DES_LINE STREQUAL "")
|
||||
if ("${CMAKE_VERSION}" VERSION_LESS "3.15")
|
||||
set(Descrition "${Descrition}\n${DES_LINE}")
|
||||
else()
|
||||
string(STRIP "${DES_LINE}" STRIP_DES_LINE)
|
||||
set(Descrition "${Descrition}\n${STRIP_DES_LINE}")
|
||||
endif("${CMAKE_VERSION}" VERSION_LESS "3.15")
|
||||
endif(NOT PREV_DES_LINE STREQUAL "")
|
||||
set(PREV_DES_LINE "${DES_LINE}")
|
||||
sub_next(${DES_CONTENT} NEXT_INDEX DES_LINE DES_CONTENT)
|
||||
endwhile(NOT PREV_DES_LINE STREQUAL DES_LINE)
|
||||
# set(Descrition "${Descrition}")
|
||||
message("--> 软件说明: ${Descrition}")
|
||||
|
||||
set(CPACK_DEBIAN_PACKAGE_DESCRIPTION ${Descrition})
|
||||
endif(_DESCRIPTION EQUAL "0")
|
||||
|
||||
##################### deb #####################
|
||||
# ARCHITECTURE
|
||||
if(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "x86_64")
|
||||
set(ARCHITECTURE "amd64")
|
||||
elseif(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "aarch64")
|
||||
set(ARCHITECTURE "arm64")
|
||||
endif()
|
||||
|
||||
#################### Calendar Version ###################
|
||||
if("${CalVer}" STREQUAL "true")
|
||||
string(TIMESTAMP BUILD_TIME "%Y%m%d")
|
||||
set(CPACK_DEBIAN_PACKAGE_VERSION "${CPACK_DEBIAN_PACKAGE_VERSION}-${BUILD_TIME}")
|
||||
endif("${CalVer}" STREQUAL "true")
|
||||
|
||||
|
||||
####################### OS Release ######################
|
||||
if("${OSDVer}" STREQUAL "true")
|
||||
exec_program(lsb_release ARGS -si
|
||||
OUTPUT_VARIABLE _OSI
|
||||
)
|
||||
exec_program(lsb_release ARGS -sr
|
||||
OUTPUT_VARIABLE _OSR
|
||||
)
|
||||
if(NOT "${_OSI}" STREQUAL "" AND NOT "${_OSR}" STREQUAL "")
|
||||
set(PACKAGE_SUFFIX "${PACKAGE_SUFFIX}_${_OSI}${_OSR}")
|
||||
endif(NOT "${_OSI}" STREQUAL "" AND NOT "${_OSR}" STREQUAL "")
|
||||
endif("${OSDVer}" STREQUAL "true")
|
||||
|
||||
|
||||
|
||||
##################### deb file name #####################
|
||||
set(_Package "${CPACK_DEBIAN_PACKAGE_NAME}")
|
||||
set(_Version "${CPACK_DEBIAN_PACKAGE_VERSION}")
|
||||
set(_Architecture "${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
|
||||
|
||||
set(_DebFileName
|
||||
"${_Package}_${_Version}_${_Architecture}${PACKAGE_SUFFIX}.deb"
|
||||
)
|
||||
set(CPACK_DEBIAN_FILE_NAME ${_DebFileName})
|
||||
|
||||
# 标识: spark-deb-package
|
||||
if(NOT "${PACKAGE_SUFFIX}" STREQUAL "")
|
||||
# eg: remove '_' of '_Debian'
|
||||
string(SUBSTRING "${PACKAGE_SUFFIX}" 1 -1 DISTRIBUTION)
|
||||
if ("${CMAKE_VERSION}" VERSION_LESS "3.15")
|
||||
set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "${Descrition}\n .\n Build for ${DISTRIBUTION} through spark-deb-build.")
|
||||
else()
|
||||
set(CPACK_DEBIAN_PACKAGE_DESCRIPTION ${Descrition} "\n.\nBuild for ${DISTRIBUTION} through spark-deb-build.")
|
||||
endif("${CMAKE_VERSION}" VERSION_LESS "3.15")
|
||||
|
||||
endif(NOT "${PACKAGE_SUFFIX}" STREQUAL "")
|
||||
|
||||
# set(CPACK_DEBIAN_PACKAGE_NAME "${Package}")
|
||||
# set(CPACK_DEBIAN_PACKAGE_VERSION "${Version}")
|
||||
# set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "${Architecture}")
|
||||
# set(CPACK_DEBIAN_PACKAGE_DEPENDS "${Depends}")
|
||||
# set(CPACK_DEBIAN_PACKAGE_PRIORITY "${Priority}")
|
||||
# set(CPACK_DEBIAN_PACKAGE_MAINTAINER "${Maintainer}")
|
||||
# set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "${Descrition}")
|
||||
|
||||
# 设置即将使用的标准脚本
|
||||
# set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA
|
||||
# "${CMAKE_SOURCE_DIR}/config/DEBIAN/preinst"
|
||||
# "${CMAKE_SOURCE_DIR}/config/DEBIAN/postinst"
|
||||
# "${CMAKE_SOURCE_DIR}/config/DEBIAN/prerm"
|
||||
# "${CMAKE_SOURCE_DIR}/config/DEBIAN/postrm"
|
||||
# )
|
||||
|
||||
# 设置为ON,以便使用 dpkg-shlibdeps 生成更好的包依赖列表。
|
||||
# set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
||||
# set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS ON)
|
||||
# set(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS_POLICY "=")
|
||||
|
||||
include(CPack)
|
||||
|
||||
endfunction(add_package_descript IN_DES)
|
||||
|
||||
|
||||
# TODO:
|
||||
# CPACK_GENERATOR
|
||||
# CPACK_DEBIAN_FILE_NAME - n
|
||||
# CPACK_DEBIAN_PACKAGE_NAME - y
|
||||
# CPACK_DEBIAN_PACKAGE_VERSION - y
|
||||
# CPACK_DEBIAN_PACKAGE_ARCHITECTURE - y(auto) -> dpkg --print-architecture
|
||||
# CPACK_DEBIAN_PACKAGE_DEPENDS - y
|
||||
# CPACK_DEBIAN_PACKAGE_PRIORITY - y
|
||||
# CPACK_DEBIAN_PACKAGE_MAINTAINER - y
|
||||
# CPACK_DEBIAN_PACKAGE_DESCRIPTION - y
|
||||
|
||||
# ARCHITECTURE
|
||||
# if(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "x86_64")
|
||||
# set(ARCHITECTURE "amd64")
|
||||
# elseif(${CMAKE_HOST_SYSTEM_PROCESSOR} STREQUAL "aarch64")
|
||||
# set(ARCHITECTURE "arm64")
|
||||
# endif()
|
||||
|
||||
|
||||
# string(TIMESTAMP BUILD_TIME "%Y%m%d")
|
|
@ -1,50 +0,0 @@
|
|||
# SparkDesktopMacros.cmake
|
||||
|
||||
macro(spark_desktop_macros)
|
||||
set(APP_NAME ${ARGV0})
|
||||
set(APP_NAME_ZH_CN ${ARGV1})
|
||||
set(APP_COMMENT ${ARGV2})
|
||||
set(APP_TYPE ${ARGV3})
|
||||
set(APP_EXECUTE_PATH ${ARGV4})
|
||||
set(APP_EXECUTE_ICON_PATH ${ARGV5})
|
||||
set(APP_CATEGORIES ${ARGV6})
|
||||
set(APP_MIME_TYPE ${ARGV7})
|
||||
configure_file(cmake/spark-desktop.desktop.in.txt
|
||||
${CMAKE_BINARY_DIR}/${ARGV0}.desktop
|
||||
)
|
||||
set(SPARK_DESKTOP_FILE ${CMAKE_BINARY_DIR}/${ARGV0}.desktop)
|
||||
endmacro(spark_desktop_macros)
|
||||
|
||||
# include(cmake/SparkDesktopMacros.cmake)
|
||||
# 内容默认应用名称: Name= 应与项目名称相同
|
||||
# spark_desktop_macros(
|
||||
# 应用名称: Name=
|
||||
# 应用名称: Name[zh_CN]=
|
||||
# 应用说明: Comment=
|
||||
# 应用类型: Type=
|
||||
# 执行程序: Exec=
|
||||
# 图标路径: Icon=
|
||||
# 应用分类: Categories=
|
||||
# MIME类型: MimeType=
|
||||
# )
|
||||
|
||||
# TODO 安装位置:INSTALL(将自动实现 install 文件,如 /usr/share/applications)
|
||||
|
||||
# install(FILES ${APP_NAME}.desktop
|
||||
# DESTINATION /usr/share/applications
|
||||
# )
|
||||
# 或者
|
||||
# install(FILES ${SPARK_DESKTOP_FILE}
|
||||
# DESTINATION /usr/share/applications
|
||||
# )
|
||||
|
||||
# 基于 configure_file 填充内容配置
|
||||
# configure_file(<input> <output>
|
||||
# [NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS |
|
||||
# FILE_PERMISSIONS <permissions>...]
|
||||
# [COPYONLY] [ESCAPE_QUOTES] [@ONLY]
|
||||
# [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
|
||||
|
||||
# install(FILES ${SPARK_DESKTOP_FILE}.desktop
|
||||
# DESTINATION /usr/share/applications
|
||||
# )
|
|
@ -1,22 +0,0 @@
|
|||
cmake_minimum_required(VERSION 3.5.1)
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
# set(CMAKE_BUILD_TYPE "Debug")
|
||||
|
||||
option(SPARK_DEBUG_MESSAGE "CMake Spark Module Debug Message." OFF)
|
||||
set(SPAKK_DEBUG_LOGFILE "${CMAKE_BINARY_DIR}/spark_debug.log" CACHE STRING "Spark Build Debug logfile." FORCE)
|
||||
file(WRITE ${SPAKK_DEBUG_LOGFILE})
|
||||
|
||||
macro(spark_debug_message)
|
||||
if(SPARK_DEBUG_MESSAGE)
|
||||
set(SPARK_ONECE_LOG ${ARGN})
|
||||
message("[SPARK_MESSAGE]: " ${SPARK_ONECE_LOG})
|
||||
file(APPEND ${SPAKK_DEBUG_LOGFILE} ${SPARK_ONECE_LOG} "\n")
|
||||
unset(SPARK_ONECE_LOG)
|
||||
endif(SPARK_DEBUG_MESSAGE)
|
||||
endmacro(spark_debug_message)
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
cmake_minimum_required(VERSION 3.5.1)
|
||||
|
||||
# include(SparkFindQt5Config.cmake)
|
||||
find_package(Dtk COMPONENTS Core Widget Gui)
|
||||
|
||||
function(target_link_dtk NAME)
|
||||
target_link_libraries(${NAME}
|
||||
${DtkCore_LIBRARIES}
|
||||
${DtkWidget_LIBRARIES}
|
||||
${DtkGui_LIBRARIES})
|
||||
endfunction(target_link_dtk NAME)
|
|
@ -1,7 +0,0 @@
|
|||
cmake_minimum_required(VERSION 3.5.1)
|
||||
|
||||
# spark_find_library(notify libnotify)
|
||||
|
||||
# function(target_link_${_prefix} TARGET)
|
||||
# target_link_libraries(${TARGET} ${_prefix})
|
||||
# endfunction(target_link_${_prefix} TARGET)
|
|
@ -1,6 +1,9 @@
|
|||
cmake_minimum_required(VERSION 3.5.1)
|
||||
|
||||
set(SPARK_FIND_QT5 TRUE)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
find_package(Qt5 COMPONENTS Core Widgets Network REQUIRED)
|
||||
|
||||
|
@ -21,6 +24,7 @@ spark_add_link(qt5 Qt5::Core Qt5::Widgets Qt5::Network)
|
|||
# 同等于 spark_add_link(qt_<name> ${ARGN})
|
||||
macro(spark_add_link_qt5 _IN_NAME)
|
||||
spark_add_link(qt5_${_IN_NAME} ${ARGN})
|
||||
spark_add_link(qt_${_IN_NAME} ${ARGN})
|
||||
endmacro(spark_add_link_qt5 _IN_NAME)
|
||||
|
||||
# 使用 spark_add_link_qt5 生成 target_link_qt5_<name> 的宏
|
||||
|
@ -150,4 +154,4 @@ spark_add_links_qt5(
|
|||
# XkbCommonSupport
|
||||
# Xml
|
||||
XmlPatterns
|
||||
)
|
||||
)
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
cmake_minimum_required(VERSION 3.5.1)
|
||||
|
||||
set(SPARK_FIND_QT6 TRUE)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
find_package(Qt6 COMPONENTS Core Widgets Network REQUIRED)
|
||||
|
||||
|
@ -21,6 +24,7 @@ spark_add_link(qt6 Qt6::Core Qt6::Widgets Qt6::Network)
|
|||
# 同等于 spark_add_link(qt_<name> ${ARGN})
|
||||
macro(spark_add_link_qt6 _IN_NAME)
|
||||
spark_add_link(qt6_${_IN_NAME} ${ARGN})
|
||||
spark_add_link(qt_${_IN_NAME} ${ARGN})
|
||||
endmacro(spark_add_link_qt6 _IN_NAME)
|
||||
|
||||
# 使用 spark_add_link_qt6 生成 target_link_qt6_<name> 的宏
|
||||
|
@ -127,4 +131,4 @@ spark_add_links_qt6(
|
|||
# WidgetsTools
|
||||
# XcbQpaPrivate
|
||||
# Xml
|
||||
)
|
||||
)
|
||||
|
|
|
@ -1,132 +0,0 @@
|
|||
|
||||
# spark_install_target
|
||||
# 基于传入的路径/目标进行安装
|
||||
# 可接受的值为: 安装路径 目标A
|
||||
# 可接受的值为: 安装路径 目标A 目标B 目标C...
|
||||
macro(spark_install_target INSTALL_TARGET_DIR INSTALL_TARGETS)
|
||||
install(TARGETS
|
||||
${INSTALL_TARGETS} ${ARGN}
|
||||
DESTINATION ${INSTALL_TARGET_DIR})
|
||||
endmacro(spark_install_target INSTALL_TARGET_DIR INSTALL_TARGETS)
|
||||
|
||||
# spark_install_file
|
||||
# 基于传入的路径/文件进行安装
|
||||
# 可接受的值为: 安装路径 文件A
|
||||
# 可接受的值为: 安装路径 文件A 文件B 文件C...
|
||||
macro(spark_install_file INSTALL_FILE_DIR INSTALL_FILE)
|
||||
install(FILES
|
||||
${INSTALL_FILE} ${ARGN}
|
||||
DESTINATION ${INSTALL_FILE_DIR})
|
||||
endmacro(spark_install_file INSTALL_FILE_DIR INSTALL_FILE)
|
||||
|
||||
# spark_install_program
|
||||
# 基于传入的路径/文件进行安装,并自动为其添加可执行权限
|
||||
# 可接受的值为: 安装路径 文件A
|
||||
# 可接受的值为: 安装路径 文件A 文件B 文件C...
|
||||
macro(spark_install_program INSTALL_PROGRAM_DIR INSTALL_PROGRAM)
|
||||
install(PROGRAMS
|
||||
${INSTALL_PROGRAM} ${ARGN}
|
||||
DESTINATION ${INSTALL_PROGRAM_DIR})
|
||||
endmacro(spark_install_program INSTALL_PROGRAM_DIR INSTALL_PROGRAM)
|
||||
|
||||
|
||||
# spark_install_directory
|
||||
# 基于传入的路径/目录进行安装
|
||||
# 可接受的值为: 安装路径 路径A
|
||||
# 可接受的值为: 安装路径 路径A/* 为安装路径A下所有内容
|
||||
macro(spark_install_directory INSTALL_DIRECTORY_DIR INSTALL_DIRECOTRY)
|
||||
# INSTALL_DIRECOTRY 可能包含 * ?
|
||||
# 1. 找到 '*', 截取,列出目录下所有文件,安装
|
||||
# 2. 是文件的直接使用 spark_install_file 安装
|
||||
# 2. 是目录的直接使用 spark_install_directory 安装
|
||||
# message(FATAL_ERROR "${INSTALL_DIRECTORY_DIR}")
|
||||
# string(FIND <string> <substring> <output_variable> [REVERSE])
|
||||
string(FIND "${INSTALL_DIRECOTRY}" "*" INSTALL_DIRECTORY_FIND_INDEX)
|
||||
# message(FATAL_ERROR "${INSTALL_DIRECTORY_FIND_INDEX}: ${INSTALL_DIRECTORY_DIR}")
|
||||
|
||||
# file(GLOB <variable>
|
||||
# [LIST_DIRECTORIES true|false] [RELATIVE <path>] [CONFIGURE_DEPENDS]
|
||||
# [<globbing-expressions>...])
|
||||
|
||||
if (NOT INSTALL_DIRECTORY_FIND_INDEX EQUAL -1)
|
||||
# string(SUBSTRING <string> <begin> <length> <output_variable>)
|
||||
string(SUBSTRING "${INSTALL_DIRECOTRY}" 0 ${INSTALL_DIRECTORY_FIND_INDEX} INSTALL_DIRECTORY_FIND_INDEX_SUBSTRING)
|
||||
# message(FATAL_ERROR "directory: ${INSTALL_DIRECTORY_FIND_INDEX_SUBSTRING}")
|
||||
|
||||
# file(GLOB <variable>
|
||||
# [LIST_DIRECTORIES true|false] [RELATIVE <path>] [CONFIGURE_DEPENDS]
|
||||
# [<globbing-expressions>...])
|
||||
|
||||
file(GLOB INSTALL_DIRECTORY_FIND_INDEX_SUBSTRING_FILE_GLOB_LIST ${INSTALL_DIRECTORY_FIND_INDEX_SUBSTRING}/*)
|
||||
list(LENGTH INSTALL_DIRECTORY_FIND_INDEX_SUBSTRING_FILE_GLOB_LIST INSTALL_DIRECTORY_FIND_INDEX_SUBSTRING_FILE_GLOB_LIST_LENGTH)
|
||||
foreach(item IN LISTS INSTALL_DIRECTORY_FIND_INDEX_SUBSTRING_FILE_GLOB_LIST)
|
||||
# message("-> ${item}")
|
||||
if(IS_DIRECTORY ${item})
|
||||
message("-> ${item} IS_DIRECTORY")
|
||||
# spark_install_directory(${INSTALL_DIRECTORY_DIR} ${item})
|
||||
install(DIRECTORY
|
||||
${item}
|
||||
DESTINATION ${INSTALL_DIRECTORY_DIR}
|
||||
USE_SOURCE_PERMISSIONS)
|
||||
else()
|
||||
message("-> ${item} NOT IS_DIRECTORY")
|
||||
spark_install_program(${INSTALL_DIRECTORY_DIR} ${item})
|
||||
# spark_install_file(${INSTALL_DIRECTORY_DIR} ${item})
|
||||
endif(IS_DIRECTORY ${item})
|
||||
endforeach(item IN LISTS INSTALL_DIRECTORY_FIND_INDEX_SUBSTRING_FILE_GLOB_LIST)
|
||||
|
||||
# message(FATAL_ERROR " directory: ${INSTALL_DIRECTORY_FIND_INDEX_SUBSTRING_FILE_GLOB_LIST}")
|
||||
# message(FATAL_ERROR " directory: ${INSTALL_DIRECTORY_FIND_INDEX_SUBSTRING_FILE_GLOB_LIST_LENGTH}")
|
||||
|
||||
else()
|
||||
# ISSUES: You Must check here
|
||||
# message(FATAL_ERROR "install: ${INSTALL_DIRECTORY_DIR}")
|
||||
|
||||
install(DIRECTORY
|
||||
${INSTALL_DIRECOTRY} ${ARGN}
|
||||
DESTINATION ${INSTALL_DIRECTORY_DIR})
|
||||
endif(NOT INSTALL_DIRECTORY_FIND_INDEX EQUAL -1)
|
||||
|
||||
endmacro(spark_install_directory INSTALL_DIRECTORY_DIR INSTALL_DIRECOTRY)
|
||||
|
||||
|
||||
|
||||
macro(spark_install_changelog CHANGE_LOG_FILE)
|
||||
set(SOURCE_CHANGE_LOG_FILE ${CHANGE_LOG_FILE})
|
||||
if (EXISTS ${SOURCE_CHANGE_LOG_FILE})
|
||||
|
||||
execute_process(COMMAND test -f ${SOURCE_CHANGE_LOG_FILE}
|
||||
RESULT_VARIABLE changelog_test
|
||||
)
|
||||
execute_process(COMMAND which gzip
|
||||
RESULT_VARIABLE gzip_test
|
||||
)
|
||||
if (NOT changelog_test EQUAL 0)
|
||||
message(FATAL_ERROR "NOTE: 不是常规文件: ${SOURCE_CHANGE_LOG_FILE}")
|
||||
endif(NOT changelog_test EQUAL 0)
|
||||
|
||||
if (NOT gzip_test EQUAL 0)
|
||||
message(FATAL_ERROR "NOTE: 未安装 gzip, 无法压缩 changelog")
|
||||
endif(NOT gzip_test EQUAL 0)
|
||||
|
||||
# 压缩与安装日志文件
|
||||
add_custom_command(
|
||||
OUTPUT "${CMAKE_BINARY_DIR}/changelog.gz"
|
||||
COMMAND gzip -cn9 "${SOURCE_CHANGE_LOG_FILE}" > "${CMAKE_BINARY_DIR}/changelog.gz"
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
COMMENT "Compressing changelog"
|
||||
)
|
||||
add_custom_target(changelog ALL DEPENDS "${CMAKE_BINARY_DIR}/changelog.gz")
|
||||
|
||||
# include(GNUInstallDirs)
|
||||
set(SPARK_INSTALL_CHANGE_LOG_DIR "/usr/share/doc/${PROJECT_NAME}/")
|
||||
install(FILES
|
||||
${CMAKE_BINARY_DIR}/changelog.gz
|
||||
debian/copyright
|
||||
|
||||
DESTINATION ${SPARK_INSTALL_CHANGE_LOG_DIR}
|
||||
)
|
||||
else()
|
||||
message(FATAL_ERROR "未找到: ${SOURCE_CHANGE_LOG_FILE}")
|
||||
endif(EXISTS ${SOURCE_CHANGE_LOG_FILE})
|
||||
endmacro(spark_install_changelog CHANGE_LOG_FILE)
|
|
@ -1,360 +0,0 @@
|
|||
cmake_minimum_required(VERSION 3.5.1)
|
||||
|
||||
# 定义一些 macro 用于自动生成构建结构
|
||||
|
||||
# spark_aux_source_directory outvar invar [skip]
|
||||
# 获取目录下的所有源代码
|
||||
macro(spark_aux_source_directory OUTVAR INVAR)
|
||||
# iv: internal_variable
|
||||
set(iv_args ${ARGN})
|
||||
list(LENGTH iv_args iv_arglen)
|
||||
|
||||
file(GLOB iv_SOURCE_LIST RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${INVAR}/*.c ${INVAR}/*.cpp)
|
||||
file(GLOB iv_HEADER_LIST RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${INVAR}/*.h ${INVAR}/*.hpp)
|
||||
file(GLOB iv_QT_UI_LIST RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${INVAR}/*.ui ${INVAR}/*.qrc)
|
||||
|
||||
if(iv_arglen EQUAL 1)
|
||||
list(APPEND ${OUTVAR} ${iv_SOURCE_LIST} ${iv_HEADER_LIST} ${iv_QT_UI_LIST})
|
||||
else()
|
||||
set(${OUTVAR} ${iv_SOURCE_LIST} ${iv_HEADER_LIST} ${iv_QT_UI_LIST})
|
||||
endif(iv_arglen EQUAL 1)
|
||||
|
||||
unset(iv_args)
|
||||
unset(iv_arglen)
|
||||
unset(iv_SOURCE_LIST)
|
||||
unset(iv_HEADER_LIST)
|
||||
unset(iv_QT_UI_LIST)
|
||||
|
||||
endmacro(spark_aux_source_directory OUTVAR INVAR)
|
||||
|
||||
# spark_aux_source_directories outvar invar [...]
|
||||
# 获取目录列表下的所有源代码
|
||||
# spark_aux_source_directory 的扩展,支持多个 invar 与追加参数
|
||||
macro(spark_aux_source_directories OUTVAR INVAR)
|
||||
set(iv_aux_directories ${ARGN})
|
||||
|
||||
spark_aux_source_directory(${OUTVAR} ${INVAR})
|
||||
|
||||
foreach(iv_directory IN LISTS iv_aux_directories)
|
||||
spark_aux_source_directory(${OUTVAR} ${iv_directory} SKIP)
|
||||
endforeach(iv_directory IN LISTS iv_aux_directories)
|
||||
|
||||
unset(iv_aux_directories)
|
||||
|
||||
endmacro(spark_aux_source_directories OUTVAR INVAR)
|
||||
|
||||
|
||||
# spark_add_library <lib_name> [files]...
|
||||
# 构建一个库,基于指定的源文件
|
||||
# 并根据库名生成 target_link_<lib_name> 函数
|
||||
macro(spark_add_library _lib_name)
|
||||
spark_debug_message("================ ${_lib_name} Library ================")
|
||||
add_library(${_lib_name} ${ARGN})
|
||||
|
||||
set(SRCS ${ARGN})
|
||||
foreach(item IN LISTS SRCS)
|
||||
spark_debug_message(" -> ${item}")
|
||||
endforeach(item IN LISTS SRCS)
|
||||
|
||||
function(target_link_${_lib_name} TARGET)
|
||||
spark_debug_message("${_lib_name}")
|
||||
target_link_libraries(${TARGET} ${_lib_name})
|
||||
endfunction(target_link_${_lib_name} TARGET)
|
||||
|
||||
endmacro(spark_add_library _lib_name)
|
||||
|
||||
# spark_add_library_path <lib_name> <lib_path>
|
||||
# 构建一个库,基于指定的路径
|
||||
# 并根据库名生成 target_link_<lib_name> 函数
|
||||
# 函数内增加以 <lib_path> 头文件搜索路径
|
||||
macro(spark_add_library_path _lib_name _lib_path)
|
||||
|
||||
# 0. 建立初始变量体系
|
||||
set(${_lib_name}_TYPE)
|
||||
set(${_lib_name}_TYPE_MESSAGE "STATIC(Default)")
|
||||
set(${_lib_name}_ARGN ${ARGN})
|
||||
|
||||
# 1. 判断 _lib_path 是否是 SHARED 或 STATIC
|
||||
if(${_lib_path} STREQUAL SHARED OR ${_lib_path} STREQUAL STATIC)
|
||||
set(${_lib_name}_TYPE ${_lib_path})
|
||||
set(${_lib_name}_TYPE_MESSAGE ${${_lib_name}_TYPE})
|
||||
|
||||
if(${ARGC} LESS 3)
|
||||
message(FATAL_ERROR "Missing parameter, library path not specified.")
|
||||
endif(${ARGC} LESS 3)
|
||||
else()
|
||||
# 如没有则将 _lib_path 加入到 ARGN
|
||||
list(APPEND ${_lib_name}_ARGN ${_lib_path})
|
||||
endif(${_lib_path} STREQUAL SHARED OR ${_lib_path} STREQUAL STATIC)
|
||||
|
||||
# 1. 处理由 spark_add_library_realpaths 构建转本构建时的清洗机制
|
||||
spark_debug_message("> Building: ${_lib_name}, type: ${${_lib_name}_TYPE_MESSAGE}")
|
||||
set(${_lib_name}_ARGN_REF ${${_lib_name}_ARGN})
|
||||
unset(${_lib_name}_ARGN)
|
||||
foreach(_old IN LISTS ${_lib_name}_ARGN_REF)
|
||||
set(_new ${_old})
|
||||
string(FIND "${_old}" "+" _plus_index)
|
||||
if(${_plus_index} GREATER 0)
|
||||
string(SUBSTRING "${_old}" 0 ${_plus_index} _new)
|
||||
spark_debug_message(" [CONVERT] ${_new} <- ${_old}")
|
||||
endif(${_plus_index} GREATER 0)
|
||||
list(APPEND ${_lib_name}_ARGN ${_new})
|
||||
endforeach(_old IN LISTS ${_lib_name}_ARGN_REF)
|
||||
|
||||
|
||||
# 2.目标参数项分析出子项
|
||||
# 拆分出源代码、路径、未知项等
|
||||
set(${_lib_name}_ARGN_SOURCES)
|
||||
set(${_lib_name}_ARGN_APPEND_PATHS)
|
||||
set(${_lib_name}_ARGN_UNKNOW)
|
||||
foreach(item IN LISTS ${_lib_name}_ARGN)
|
||||
spark_debug_message(" [ARGN] check:" ${item})
|
||||
if(NOT EXISTS ${item})
|
||||
set(item ${CMAKE_CURRENT_LIST_DIR}/${item})
|
||||
endif()
|
||||
if(EXISTS ${item})
|
||||
# spark_debug_message(" exists: true")
|
||||
file(REAL_PATH ${item} ${_lib_name}_ARGN_item)
|
||||
if(IS_DIRECTORY ${${_lib_name}_ARGN_item})
|
||||
list(APPEND ${_lib_name}_ARGN_APPEND_PATHS ${item})
|
||||
else()
|
||||
list(APPEND ${_lib_name}_ARGN_SOURCES ${item})
|
||||
endif(IS_DIRECTORY ${${_lib_name}_ARGN_item})
|
||||
else()
|
||||
list(APPEND ${_lib_name}_ARGN_UNKNOW ${item})
|
||||
spark_debug_message(" exists: false")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
list(LENGTH ${_lib_name}_ARGN_SOURCES ${_lib_name}_ARGN_SOURCES_LENGTH)
|
||||
list(LENGTH ${_lib_name}_ARGN_APPEND_PATHS ${_lib_name}_ARGN_APPEND_PATHS_LENGTH)
|
||||
list(LENGTH ${_lib_name}_ARGN_UNKNOW ${_lib_name}_ARGN_UNKNOW_LENGTH)
|
||||
spark_debug_message(" result: files(${${_lib_name}_ARGN_SOURCES_LENGTH}), paths(${${_lib_name}_ARGN_APPEND_PATHS_LENGTH}), unknow(${${_lib_name}_ARGN_UNKNOW_LENGTH})" ${item})
|
||||
|
||||
# 3. 获取所以源代码为 any_files
|
||||
spark_debug_message(" files:")
|
||||
set(any_files ${${_lib_name}_ARGN_SOURCES})
|
||||
foreach(item IN LISTS ${_lib_name}_ARGN_APPEND_PATHS)
|
||||
spark_aux_source_directory(item_files ${item})
|
||||
list(APPEND any_files ${item_files})
|
||||
foreach(item_file IN LISTS item_files)
|
||||
spark_debug_message(" ${item_file}")
|
||||
endforeach(item_file IN LISTS item_files)
|
||||
endforeach(item IN LISTS ${_lib_name}_ARGN_APPEND_PATHS)
|
||||
|
||||
# 4. 构建目标库
|
||||
add_library(${_lib_name} ${${_lib_name}_TYPE}
|
||||
${${_lib_name}_ARGN_SOURCES}
|
||||
${any_files})
|
||||
|
||||
# 5. 建立引用点
|
||||
# target_link_<_lib_name> 函数
|
||||
# target_include_<_lib_name> 函数
|
||||
|
||||
# target_<_lib_name>_include 函数
|
||||
# target_<_lib_name>_link 函数
|
||||
|
||||
function(target_${_lib_name}_include _include)
|
||||
spark_debug_message("添加引用: ${_lib_name} <- ${_include} ${${_lib_name}_INCLUDE_ARGN}")
|
||||
target_include_directories(${_lib_name} PRIVATE ${_include})
|
||||
endfunction(target_${_lib_name}_include _include)
|
||||
|
||||
function(target_${_lib_name}_link _library)
|
||||
spark_debug_message("添加链接: ${_lib_name} <- ${_library} ${${_lib_name}_LINK_ARGN}")
|
||||
target_link_libraries(${_lib_name} ${_library})
|
||||
endfunction(target_${_lib_name}_link _library)
|
||||
|
||||
function(target_link_${_lib_name} TARGET)
|
||||
spark_debug_message("链接引用: ${TARGET} <- ${_lib_name}")
|
||||
target_include_directories(${TARGET} PRIVATE
|
||||
"${${_lib_name}_SOURCE_PATH}" ${${_lib_name}_ARGN_APPEND_PATHS})
|
||||
target_link_libraries(${TARGET} ${_lib_name})
|
||||
endfunction(target_link_${_lib_name} TARGET)
|
||||
|
||||
function(target_include_${_lib_name} TARGET)
|
||||
spark_debug_message("引入引用: ${TARGET} <- ${_lib_name}")
|
||||
target_include_directories(${TARGET} PUBLIC
|
||||
"${${_lib_name}_SOURCE_PATH}" ${${_lib_name}_ARGN_APPEND_PATHS})
|
||||
endfunction(target_include_${_lib_name} TARGET)
|
||||
|
||||
|
||||
target_include_directories(${_lib_name} PRIVATE
|
||||
"${${_lib_name}_ARGN_APPEND_PATHS}")
|
||||
|
||||
# 输出 includes
|
||||
spark_debug_message(" ${_lib_name}_ARGN_APPEND_PATHS: ")
|
||||
foreach(item IN LISTS ${_lib_name}_ARGN_APPEND_PATHS)
|
||||
string(REPLACE "${CMAKE_SOURCE_DIR}/" "" item_var "${item}")
|
||||
spark_debug_message(" ${item_var}")
|
||||
endforeach(item IN LISTS ${_lib_name}_ARGN_APPEND_PATHS)
|
||||
|
||||
# 如果想用以下操作手动实现 target_link_include_directories
|
||||
# 请注意对 LIST 类型使用 "" 进行包围
|
||||
# target_link_include_directories 的 PUBLIC 将会填充(追加)目标的 INCLUDE_DIRECTORIES 属性
|
||||
# target_link_include_directories 支持 cmake 生成大表达式,更容易操作,手动将无法实现此类能力
|
||||
# target_link_include_directories 支持相对路径和绝对路径参数
|
||||
# 手动操作将必须使用绝对路径,这是不好的地方
|
||||
# get_target_property(_lib_include_directories ${_lib_name} INCLUDE_DIRECTORIES)
|
||||
# list(APPEND _lib_include_directories "${CMAKE_CURRENT_LIST_DIR}/${${_lib_name}_SOURCE_PATH}")
|
||||
# spark_debug_message("----> ${CMAKE_CURRENT_LIST_DIR}/${${_lib_name}_SOURCE_PATH}")
|
||||
# spark_debug_message("----> ${_lib_include_directories}")
|
||||
# set_target_properties(${_lib_name} PROPERTIES
|
||||
# INCLUDE_DIRECTORIES "${_lib_include_directories}"
|
||||
# INTERFACE_INCLUDE_DIRECTORIES "${_lib_include_directories}"
|
||||
# )
|
||||
|
||||
endmacro(spark_add_library_path _lib_name _lib_path)
|
||||
|
||||
# spark_add_executable <exec_name> [files]...
|
||||
# 构建一个可执行文件,基于指定的源文件
|
||||
# Qt编译时源文件包括很多类型,需要指定 *.h/*.cpp/*.qrc/*.qm/... 等
|
||||
macro(spark_add_executable _exec_name)
|
||||
|
||||
set(${_exec_name}_TYPE_MESSAGE "可执行程序")
|
||||
spark_debug_message("> Building: ${_exec_name}, type: ${${_exec_name}_TYPE_MESSAGE}")
|
||||
|
||||
add_executable(${_exec_name} ${ARGN})
|
||||
|
||||
endmacro(spark_add_executable _exec_name)
|
||||
|
||||
# spark_add_executable_path <target> <path> [files ... paths]
|
||||
# 构建一个可执行程序,基于指定的路径
|
||||
macro(spark_add_executable_path _exec_name _exec_path)
|
||||
spark_add_executable(${_exec_name})
|
||||
|
||||
# 0. 建立初始变量体系
|
||||
# set(${_exec_name}_TYPE)
|
||||
# set(${_exec_name}_TYPE_MESSAGE "可执行程序")
|
||||
set(${_exec_name}_ARGN ${ARGN})
|
||||
|
||||
# 1. 处理由 spark_add_executable_realpaths 构建转本构建时的清洗机制
|
||||
# spark_debug_message("> Building: ${_exec_name}, type: ${${_exec_name}_TYPE_MESSAGE}")
|
||||
set(${_exec_name}_ARGN_REF ${${_exec_name}_ARGN})
|
||||
unset(${_exec_name}_ARGN)
|
||||
foreach(_old IN LISTS ${_exec_name}_ARGN_REF)
|
||||
set(_new ${_old})
|
||||
string(FIND "${_old}" "+" _plus_index)
|
||||
if(${_plus_index} GREATER 0)
|
||||
string(SUBSTRING "${_old}" 0 ${_plus_index} _new)
|
||||
spark_debug_message(" [CONVERT] ${_new} <- ${_old}")
|
||||
endif(${_plus_index} GREATER 0)
|
||||
list(APPEND ${_exec_name}_ARGN ${_new})
|
||||
endforeach(_old IN LISTS ${_exec_name}_ARGN_REF)
|
||||
|
||||
# 1.目标参数项分析出子项
|
||||
# 拆分出源代码、路径、未知项等
|
||||
# spark_debug_message("> Building: ${_exec_name}, type: ${${_exec_name}_TYPE_MESSAGE}")
|
||||
set(${_exec_name}_ARGN_SOURCES)
|
||||
set(${_exec_name}_ARGN_APPEND_PATHS ${_exec_path})
|
||||
set(${_exec_name}_ARGN_UNKNOW)
|
||||
foreach(item IN LISTS ${_exec_name}_ARGN)
|
||||
spark_debug_message(" [ARGN] check:" ${item})
|
||||
if(NOT EXISTS ${item})
|
||||
set(item ${CMAKE_CURRENT_LIST_DIR}/${item})
|
||||
endif()
|
||||
if(EXISTS ${item})
|
||||
# spark_debug_message(" exists: true")
|
||||
file(REAL_PATH ${item} ${_exec_name}_ARGN_item)
|
||||
if(IS_DIRECTORY ${${_exec_name}_ARGN_item})
|
||||
list(APPEND ${_exec_name}_ARGN_APPEND_PATHS ${item})
|
||||
else()
|
||||
list(APPEND ${_exec_name}_ARGN_SOURCES ${item})
|
||||
endif(IS_DIRECTORY ${${_exec_name}_ARGN_item})
|
||||
else()
|
||||
list(APPEND ${_exec_name}_ARGN_UNKNOW ${item})
|
||||
spark_debug_message(" exists: false")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
list(LENGTH ${_exec_name}_ARGN_SOURCES ${_exec_name}_ARGN_SOURCES_LENGTH)
|
||||
list(LENGTH ${_exec_name}_ARGN_APPEND_PATHS ${_exec_name}_ARGN_APPEND_PATHS_LENGTH)
|
||||
list(LENGTH ${_exec_name}_ARGN_UNKNOW ${_exec_name}_ARGN_UNKNOW_LENGTH)
|
||||
spark_debug_message(" result: files(${${_exec_name}_ARGN_SOURCES_LENGTH}), paths(${${_exec_name}_ARGN_APPEND_PATHS_LENGTH}), unknow(${${_exec_name}_ARGN_UNKNOW_LENGTH})" ${item})
|
||||
|
||||
|
||||
# 2. 获取所以源代码为 any_files
|
||||
spark_debug_message(" files:")
|
||||
set(any_files ${${_exec_name}_ARGN_SOURCES})
|
||||
foreach(item IN LISTS ${_exec_name}_ARGN_APPEND_PATHS)
|
||||
spark_aux_source_directory(item_files ${item})
|
||||
list(APPEND any_files ${item_files})
|
||||
foreach(item_file IN LISTS item_files)
|
||||
spark_debug_message(" ${item_file}")
|
||||
endforeach(item_file IN LISTS item_files)
|
||||
endforeach(item IN LISTS ${_exec_name}_ARGN_APPEND_PATHS)
|
||||
|
||||
# 3. 构建可执行目标所需要的文件
|
||||
# add_executable(${_exec_name}
|
||||
# ${${_exec_name}_ARGN_SOURCES}
|
||||
# ${any_files})
|
||||
|
||||
target_sources(${_exec_name} PRIVATE
|
||||
${${_exec_name}_ARGN_SOURCES}
|
||||
${any_files})
|
||||
|
||||
# 4. 建立引用点
|
||||
# target_<_exec_name>_include 函数
|
||||
# target_<_exec_name>_link 函数
|
||||
function(target_${_exec_name}_include _include)
|
||||
spark_debug_message("添加引用: ${_exec_name} <- ${_include} ${${_exec_name}_INCLUDE_ARGN}")
|
||||
target_include_directories(${_exec_name} PRIVATE ${_include})
|
||||
endfunction(target_${_exec_name}_include _include)
|
||||
|
||||
function(target_${_exec_name}_link _library)
|
||||
spark_debug_message("添加链接: ${_exec_name} <- ${_library} ${${_exec_name}_LINK_ARGN}")
|
||||
target_link_libraries(${_exec_name} ${_library})
|
||||
endfunction(target_${_exec_name}_link _library)
|
||||
|
||||
target_include_directories(${_exec_name} PRIVATE
|
||||
${_exec_path})
|
||||
spark_debug_message(" include: ${_exec_path}\n")
|
||||
|
||||
endmacro(spark_add_executable_path _exec_name _exec_path)
|
||||
|
||||
# spark_find_library
|
||||
# 搜索一个库,基于指定的库名,调用 pkg-config 搜索库
|
||||
# 并根据库名生成一个 target_link_<prefix> 函数
|
||||
macro(spark_find_library _prefix)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
# libnotify
|
||||
pkg_check_modules(${_prefix} ${ARGN})
|
||||
function(target_link_${_prefix} TARGET)
|
||||
target_include_directories(${TARGET} PUBLIC
|
||||
${${_prefix}_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET}
|
||||
${${_prefix}_LIBRARIES})
|
||||
endfunction(target_link_${_prefix} TARGET)
|
||||
|
||||
endmacro(spark_find_library _prefix)
|
||||
|
||||
|
||||
# spark_add_executable_paths
|
||||
# 自定义构建宏,基于指定的前缀名称,处理后续参数为子目录
|
||||
# item: 为进行遍历后的单项,类似于 python3 中的 (for item in items:)
|
||||
# file: 为在目录中不以递归(GLOB_RECURSE)方式寻找 qrc 文件,需要将其参与编译才能被 rcc
|
||||
# 并根据 prefix-<item> 生成构建目标,
|
||||
macro(spark_add_executable_paths _prefix_path)
|
||||
set(PATHS ${ARGN})
|
||||
foreach(item IN LISTS PATHS)
|
||||
file(GLOB QRCS "${item}/*.qrc")
|
||||
spark_debug_message(">>> add_executable: " "${_prefix_path}-${item} ${item} + ${QRCS}")
|
||||
spark_add_executable_path(${_prefix_path}-${item} ${item} ${QRCS})
|
||||
target_link_qt5(${_prefix_path}-${item})
|
||||
endforeach(item IN LISTS PATHS)
|
||||
endmacro(spark_add_executable_paths _prefix_path)
|
||||
|
||||
# spark_add_link
|
||||
# 自定义宏以代替当前使用 fucntion 定义 target_link_<name> 结构
|
||||
# _IN_NAME: 此宏生成 target_link_<name> 的要求参数
|
||||
# ARGN: 此宏剩余的参数列表
|
||||
# 在使用 target_link_<name> 时
|
||||
# _NAME: 用于此 fucntion 中的要求参数: <_NAME>目标将要连接此库
|
||||
macro(spark_add_link _name)
|
||||
function(target_link_${_name} _link)
|
||||
spark_debug_message("> Linking: ${_link}")
|
||||
spark_debug_message(" <- ${ARGN}\n")
|
||||
target_link_libraries(${_link}
|
||||
${ARGN})
|
||||
endfunction(target_link_${_name} _link)
|
||||
endmacro(spark_add_link _name)
|
|
@ -1,335 +0,0 @@
|
|||
|
||||
# find_plus
|
||||
# 寻找 INVAl 传入的字符串,如果存在 + 字符将写入位置到 OUTVAL
|
||||
function(find_plus INVAL OUTVAL)
|
||||
string(FIND "${INVAL}" "+" plus_index)
|
||||
set(${OUTVAL} ${plus_index} PARENT_SCOPE)
|
||||
endfunction(find_plus INVAL OUTVAL)
|
||||
|
||||
function(find_plus_v INVAL OUTVAL)
|
||||
string(FIND "${${INVAL}}" "+" plus_index)
|
||||
set(${OUTVAL} ${plus_index} PARENT_SCOPE)
|
||||
endfunction(find_plus_v INVAL OUTVAL)
|
||||
|
||||
function(find_colon INVAL OUTVAL)
|
||||
string(FIND "${INVAL}" ":" colon_index)
|
||||
set(${OUTVAL} ${colon_index} PARENT_SCOPE)
|
||||
endfunction(find_colon INVAL OUTVAL)
|
||||
|
||||
function(find_colon_v INVAL OUTVAL)
|
||||
string(FIND "${${INVAL}}" ":" colon_index)
|
||||
set(${OUTVAL} ${colon_index} PARENT_SCOPE)
|
||||
endfunction(find_colon_v INVAL OUTVAL)
|
||||
|
||||
function(find_dir INVAL OUTVAL)
|
||||
string(FIND "${INVAL}" "/" _STR ${ARGN})
|
||||
set(${OUTVAL} ${_STR} PARENT_SCOPE)
|
||||
endfunction(find_dir INVAL OUTVAL)
|
||||
|
||||
function(find_dir_v INVAL OUTVAL)
|
||||
string(FIND "${${INVAL}}" "/" _STR ${ARGN})
|
||||
set(${OUTVAL} ${_STR} PARENT_SCOPE)
|
||||
endfunction(find_dir_v INVAL OUTVAL)
|
||||
|
||||
#
|
||||
function(str_left INVAL INDEX OUTVAL)
|
||||
set(LEFT_INDEX ${INDEX})
|
||||
string(SUBSTRING "${INVAL}" 0 ${LEFT_INDEX} _LEFT_V)
|
||||
set(${OUTVAL} ${_LEFT_V} PARENT_SCOPE)
|
||||
endfunction(str_left INVAL INDEX OUTVAL)
|
||||
|
||||
function(str_right INVAL INDEX OUTVAL)
|
||||
math(EXPR RIGHT_INDEX ${INDEX}+1)
|
||||
string(SUBSTRING "${INVAL}" ${RIGHT_INDEX} -1 _RIGHT_V)
|
||||
set(${OUTVAL} ${_RIGHT_V} PARENT_SCOPE)
|
||||
endfunction(str_right INVAL INDEX OUTVAL)
|
||||
|
||||
function(str_left_v INVAL INDEX OUTVAL)
|
||||
set(LEFT_INDEX ${${INDEX}})
|
||||
string(SUBSTRING "${${INVAL}}" 0 ${LEFT_INDEX} _LEFT_V)
|
||||
set(${OUTVAL} ${_LEFT_V} PARENT_SCOPE)
|
||||
endfunction(str_left_v INVAL INDEX OUTVAL)
|
||||
|
||||
function(str_right_v INVAL INDEX OUTVAL)
|
||||
math(EXPR RIGHT_INDEX ${${INDEX}}+1)
|
||||
string(SUBSTRING "${${INVAL}}" ${RIGHT_INDEX} -1 _RIGHT_V)
|
||||
set(${OUTVAL} ${_RIGHT_V} PARENT_SCOPE)
|
||||
endfunction(str_right_v INVAL INDEX OUTVAL)
|
||||
|
||||
#
|
||||
function(find_colon_plus INVAL OUTVAL)
|
||||
find_colon(${INVAL} COLON_INDEX)
|
||||
str_right(${INVAL} ${COLON_INDEX} COLON_RIGHT)
|
||||
find_plus_v(COLON_RIGHT PLUS_INDEX)
|
||||
str_left_v(COLON_RIGHT PLUS_INDEX COLON_RIGHT_LEFT_PLUS)
|
||||
|
||||
set(${OUTVAL} ${COLON_RIGHT_LEFT_PLUS} PARENT_SCOPE)
|
||||
endfunction(find_colon_plus INVAL OUTVAL)
|
||||
|
||||
function(find_colon_plus_v INVAL OUTVAL)
|
||||
find_colon_v(${INVAL} COLON_INDEX)
|
||||
str_right_v(${INVAL} COLON_INDEX COLON_RIGHT)
|
||||
find_plus_v(COLON_RIGHT PLUS_INDEX)
|
||||
str_left_v(COLON_RIGHT PLUS_INDEX COLON_RIGHT_LEFT_PLUS)
|
||||
|
||||
set(${OUTVAL} ${COLON_RIGHT_LEFT_PLUS} PARENT_SCOPE)
|
||||
endfunction(find_colon_plus_v INVAL OUTVAL)
|
||||
|
||||
function(find_dir_plus INVAL OUTVAL)
|
||||
# t:*/*+d
|
||||
# ^
|
||||
find_dir("${INVAL}" SLASH_INDEX REVERSE)
|
||||
str_right("${INVAL}" ${SLASH_INDEX} SLASH_RIGHT)
|
||||
find_plus_v(SLASH_RIGHT PLUS_INDEX)
|
||||
str_left_v(SLASH_RIGHT PLUS_INDEX SLASH_RIGHT_LEFT_PLUS)
|
||||
|
||||
set(${OUTVAL} ${SLASH_RIGHT_LEFT_PLUS} PARENT_SCOPE)
|
||||
endfunction(find_dir_plus INVAL OUTVAL)
|
||||
|
||||
function(find_dir_plus_v INVAL OUTVAL)
|
||||
# t:*/*+d
|
||||
# ^
|
||||
find_dir("${${INVAL}}" SLASH_INDEX REVERSE)
|
||||
str_right("${${INVAL}}" ${SLASH_INDEX} SLASH_RIGHT)
|
||||
find_plus_v(SLASH_RIGHT PLUS_INDEX)
|
||||
str_left_v(SLASH_RIGHT PLUS_INDEX SLASH_RIGHT_LEFT_PLUS)
|
||||
|
||||
set(${OUTVAL} ${SLASH_RIGHT_LEFT_PLUS} PARENT_SCOPE)
|
||||
endfunction(find_dir_plus_v INVAL OUTVAL)
|
||||
|
||||
|
||||
# spark_add_library_source <target> ...
|
||||
# 扩展 一行一可执行目标 的构建的扩展宏
|
||||
# 在构建时将会另外加入这些资源
|
||||
macro(spark_add_library_source target)
|
||||
set(${target}_ADD_SOURCE ${ARGN})
|
||||
endmacro(spark_add_library_source target)
|
||||
|
||||
# 冗余的 target_link_qt5 或 qt6 的处理逻辑
|
||||
macro(_handle_spark_target_link_qt_macro _target)
|
||||
if(SPARK_FIND_QT5)
|
||||
target_link_qt5(${_target})
|
||||
endif(SPARK_FIND_QT5)
|
||||
|
||||
if(SPARK_FIND_QT6)
|
||||
target_link_qt6(${_target})
|
||||
endif(SPARK_FIND_QT6)
|
||||
endmacro(_handle_spark_target_link_qt_macro _target)
|
||||
|
||||
# spark_add_library_realpaths
|
||||
# 基于传入的项进行构建
|
||||
# 可接受的值为: 路径列表
|
||||
# 可接受的值为: 路径列表+依赖库A+依赖库B
|
||||
macro(spark_add_library_realpaths)
|
||||
|
||||
set(REALPATHS ${ARGN})
|
||||
foreach(REALPATH IN LISTS REALPATHS)
|
||||
|
||||
# # 找 : 号下标,这是找:号的函数
|
||||
# find_colon(${REALPATH} COLON_INDEX)
|
||||
# 找 / 号下标,这是找/号的函数
|
||||
find_dir_v(REALPATH SLASH_INDEX REVERSE)
|
||||
# 找 + 号下标,这是找+号的函数
|
||||
find_plus_v(REALPATH PLUS_INDEX)
|
||||
|
||||
# +
|
||||
if(PLUS_INDEX LESS 0)
|
||||
# 完全没有 + 的情况下,它就是一个基于目录的构建
|
||||
set(dir ${REALPATH})
|
||||
str_right_v(REALPATH SLASH_INDEX target)
|
||||
|
||||
spark_add_library_path(${target}
|
||||
${dir}
|
||||
${${target}_ADD_SOURCE}
|
||||
)
|
||||
# 使用 spark_add_library_realpaths 构建的依赖将允许直接引用库头文件
|
||||
target_include_directories(${target} PUBLIC ${dir})
|
||||
_handle_spark_target_link_qt_macro(${target})
|
||||
else()
|
||||
# 有 + 的情况下,获取 + 号下标右侧所有内容为 target_depends_str 并转为列表
|
||||
str_right_v(REALPATH PLUS_INDEX target_depends_str)
|
||||
string(REPLACE "+" ";" target_depends "${target_depends_str}")
|
||||
|
||||
find_dir_plus_v(REALPATH target)
|
||||
str_left_v(REALPATH PLUS_INDEX dir)
|
||||
|
||||
spark_add_library_path(${target}
|
||||
${dir}
|
||||
${${target}_ADD_SOURCE}
|
||||
)
|
||||
spark_debug_message(" [INCLUDE_DIRS]: ${dir} ${dir}/.. \n")
|
||||
target_include_directories(${target} PUBLIC ${dir} ${dir}/..)
|
||||
target_link_libraries(${target} ${target_depends})
|
||||
endif(PLUS_INDEX LESS 0)
|
||||
|
||||
endforeach(REALPATH IN LISTS REALPATHS)
|
||||
|
||||
endmacro(spark_add_library_realpaths)
|
||||
|
||||
|
||||
# spark_aux_source_paths
|
||||
# 将指定路径中的文件变成可用的AUX源文件列表
|
||||
macro(spark_aux_source_paths AUX_VAR)
|
||||
set(${AUX_VAR} "")
|
||||
set(${AUX_VAR}_PATHS ${ARGN})
|
||||
|
||||
foreach(aux_path IN LISTS ${AUX_VAR}_PATHS)
|
||||
# spark_debug_message("aux_path: ${aux_path}")
|
||||
aux_source_directory(${aux_path} ${AUX_VAR})
|
||||
endforeach(aux_path IN LISTS ${AUX_VAR}_PATHS)
|
||||
|
||||
endmacro(spark_aux_source_paths AUX_VAR)
|
||||
|
||||
# spark_file_glob
|
||||
# 使用用 file(GLOB) 的匹配规则,并一次可匹配多个规则
|
||||
#
|
||||
macro(spark_file_glob FGLOB_VAR)
|
||||
set(${FGLOB_VAR} "")
|
||||
set(${FGLOB_VAR}_PATHS ${ARGN})
|
||||
|
||||
foreach(fglob_path IN LISTS ${FGLOB_VAR}_PATHS)
|
||||
|
||||
file(GLOB FGLOB_PATH_SRCS ${fglob_path})
|
||||
foreach(fglob_path_src IN LISTS FGLOB_PATH_SRCS)
|
||||
# spark_debug_message(" -> ${item}")
|
||||
list(APPEND ${FGLOB_VAR} ${fglob_path_src})
|
||||
endforeach(fglob_path_src IN LISTS FGLOB_PATH_SRCS)
|
||||
|
||||
endforeach(fglob_path IN LISTS ${FGLOB_VAR}_PATHS)
|
||||
|
||||
endmacro(spark_file_glob FGLOB_VAR)
|
||||
|
||||
|
||||
# spark_add_source_paths
|
||||
# 将指定路径中的文件变成可用的源文件列表
|
||||
#
|
||||
macro(spark_add_source_paths SOURCE_VAR)
|
||||
set(${SOURCE_VAR} "")
|
||||
set(${SOURCE_VAR}_PATHS ${ARGN})
|
||||
|
||||
spark_aux_source_paths(${SOURCE_VAR} ${ARGN})
|
||||
foreach(source_path IN LISTS ${SOURCE_VAR}_PATHS)
|
||||
# list(APPEND ${SOURCE_VAR}_PATHS ${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE_PATH})
|
||||
# aux_source_directory(${SOURCE_PATH} _SOURCES)
|
||||
# foreach(item IN LISTS _SOURCES)
|
||||
# # spark_debug_message(" -> ${item}")
|
||||
# list(APPEND ${SOURCE_VAR} ${item})
|
||||
# endforeach(item IN LISTS _SOURCES)
|
||||
|
||||
# file(GLOB HEADER_LIST RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${SOURCE_PATH}/*.h)
|
||||
# foreach(item IN LISTS HEADER_LIST)
|
||||
# # spark_debug_message(" -> ${item}")
|
||||
# list(APPEND ${SOURCE_VAR} ${item})
|
||||
# endforeach(item IN LISTS HEADER_LIST)
|
||||
|
||||
file(GLOB UI_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${source_path}/*.ui)
|
||||
foreach(ui_src IN LISTS UI_SRCS)
|
||||
# spark_debug_message(" -> ${item}")
|
||||
list(APPEND ${SOURCE_VAR} ${ui_src})
|
||||
endforeach(ui_src IN LISTS UI_SRCS)
|
||||
endforeach(source_path IN LISTS ${SOURCE_VAR}_PATHS)
|
||||
endmacro(spark_add_source_paths SOURCE_VAR)
|
||||
|
||||
|
||||
# spark_add_library_file_glob
|
||||
#
|
||||
macro(spark_add_library_file_glob _lib_name)
|
||||
spark_file_glob(${_lib_name}_SOURCES ${ARGN})
|
||||
spark_add_library(${_lib_name} ${${_lib_name}_SOURCES})
|
||||
endmacro(spark_add_library_file_glob _lib_name)
|
||||
|
||||
|
||||
|
||||
# spark_add_executable_source <target> ...
|
||||
# 扩展 一行一可执行目标 的构建的扩展宏
|
||||
# 在构建时将会另外加入这些资源
|
||||
macro(spark_add_executable_source target)
|
||||
set(${target}_ADD_SOURCE ${ARGN})
|
||||
endmacro(spark_add_executable_source target)
|
||||
|
||||
# 冗余的 spark_add_executable_realpaths 的 dir 处理逻辑
|
||||
macro(_handle_spark_add_executable_realpaths_if_dir_empty_macro)
|
||||
if("${dir}" STREQUAL "")
|
||||
spark_add_executable(${target}
|
||||
${${target}_ADD_SOURCE}
|
||||
)
|
||||
else()
|
||||
spark_add_executable_path(${target}
|
||||
${dir}
|
||||
${${target}_ADD_SOURCE}
|
||||
)
|
||||
endif("${dir}" STREQUAL "")
|
||||
endmacro(_handle_spark_add_executable_realpaths_if_dir_empty_macro)
|
||||
|
||||
# spark_add_executable_realpaths
|
||||
# 基于传入的项进行构建
|
||||
# 可接受的值为: 可执行目标:路径列表
|
||||
# 可接受的值为: 可执行目标:路径列表+依赖库A+依赖库B
|
||||
macro(spark_add_executable_realpaths)
|
||||
|
||||
set(REALPATHS ${ARGN})
|
||||
foreach(REALPATH IN LISTS REALPATHS)
|
||||
|
||||
# 找 : 号下标,这是找:号的函数
|
||||
find_colon(${REALPATH} COLON_INDEX)
|
||||
|
||||
if(COLON_INDEX LESS 0)
|
||||
# do not anything
|
||||
else()
|
||||
# 找到 : 号,将截取 target 名称
|
||||
# string(SUBSTRING "${REALPATH}" 0 ${COLON_INDEX} REALTARGET)
|
||||
find_colon_v(REALPATH COLON_INDEX)
|
||||
str_left_v(REALPATH COLON_INDEX target)
|
||||
str_right_v(REALPATH COLON_INDEX COLON_REMAIN)
|
||||
# message(FATAL_ERROR "构建一个: ${target}") # 已验证
|
||||
|
||||
endif(COLON_INDEX LESS 0)
|
||||
|
||||
# 找 + 号下标,这是找+号的函数
|
||||
find_plus_v(REALPATH PLUS_INDEX)
|
||||
|
||||
if(PLUS_INDEX LESS 0)
|
||||
# 完全没有 + 的情况下,它就是一个基于目录的构建
|
||||
set(dir ${COLON_REMAIN})
|
||||
# spark_add_executable_path(${target}
|
||||
# ${dir}
|
||||
# ${${target}_ADD_SOURCE}
|
||||
# )
|
||||
_handle_spark_add_executable_realpaths_if_dir_empty_macro()
|
||||
_handle_spark_target_link_qt_macro(${target})
|
||||
else()
|
||||
# 有 + 的情况下,获取 + 号下标右侧所有内容为 target_depends_str 并转为列表
|
||||
str_right_v(REALPATH PLUS_INDEX target_depends_str)
|
||||
string(REPLACE "+" ";" target_depends "${target_depends_str}")
|
||||
|
||||
# 再从主要内容中获取 dir ,以及
|
||||
find_colon_plus_v(REALPATH dir)
|
||||
# spark_add_executable_path(${target}
|
||||
# ${dir}
|
||||
# ${${target}_ADD_SOURCE}
|
||||
# )
|
||||
_handle_spark_add_executable_realpaths_if_dir_empty_macro()
|
||||
target_include_directories(${target} PUBLIC ${dir} ${dir}/..)
|
||||
target_link_libraries(${target} ${target_depends})
|
||||
endif(PLUS_INDEX LESS 0)
|
||||
endforeach(REALPATH IN LISTS REALPATHS)
|
||||
|
||||
endmacro(spark_add_executable_realpaths)
|
||||
|
||||
|
||||
# 一行一库概念构建
|
||||
# 1.构建一个库,基于指定的目录路径进行构建
|
||||
# src/widgets/DocTypeListView
|
||||
# ^目录将被用于制作的目标名称
|
||||
# 目录下的所有文件将被用于制作此库的源代码文件
|
||||
#
|
||||
# 2.构建一个库,基于指定的目录路径进行构建,并依赖其后面所列出的依赖项
|
||||
# src/widgets/MaintainerInfoView+DocTypeListView+...
|
||||
# ^此库将被用于 MaintainerInfoView 库的依赖
|
||||
# ^此符号'+'将被视为依赖项列表的分隔符
|
||||
|
||||
# 一行一可执行目标概念
|
||||
# 1.构建一个可执行目标,基于指定的目录路径进行构建(行不通,可执行目标很少为一个目录)
|
||||
# 2.构建一个可执行目标,基于指定的文件路径进行构建(也许可以)
|
||||
# 3.构建一个可执行目标,基于指定的文件名称进行构建()
|
||||
# 4.构建一个可执行目标,基于指定命名规则(target:dir:dir+depend+depend...)
|
|
@ -1,48 +0,0 @@
|
|||
cmake_minimum_required(VERSION 3.5.1)
|
||||
|
||||
# translator_qt5 _qmvar [... *.ts]
|
||||
macro(translator_qt5 _qmvar)
|
||||
# set(SPARK_TRANSLATIONS_ARGN ${ARGN})
|
||||
# file(GLOB SPARK_TRANSLATIONS ${SPARK_TRANSLATIONS_ARGN})
|
||||
# qt5_add_translation(SPARK_QM_TRANSLATIONS
|
||||
# ${SPARK_TRANSLATIONS})
|
||||
|
||||
set(${_qmvar}_ARNG ${ARGN})
|
||||
file(GLOB ${_qmvar}_TS_FILES ${${_qmvar}_ARNG})
|
||||
find_package(Qt5LinguistTools)
|
||||
|
||||
qt5_add_translation(${_qmvar}
|
||||
${${_qmvar}_TS_FILES})
|
||||
|
||||
set(SPARK_QM_TRANSLATIONS ${_qmvar})
|
||||
|
||||
# 注意,必须将 SPARK_QM_TRANSLATIONS 或 ${_qmvar} 加入到 add_executable 参数中才能在编译时生成只有原文的ts文件
|
||||
|
||||
# qt5_create_translation
|
||||
# ts文件会在 make clean 或重新编译的时候一并被删除,再编译的时候生成全新的ts(原有的翻译会丢失,万分注意!!)
|
||||
|
||||
# qt5_add_translation
|
||||
# 此宏比较稳定
|
||||
endmacro(translator_qt5 _qmvar)
|
||||
|
||||
|
||||
# translator_qt6 _qmvar [... *.ts]
|
||||
macro(translator_qt6 _qmvar)
|
||||
# todo
|
||||
endmacro(translator_qt6 _qmvar)
|
||||
|
||||
# 冗余的 translator_qt5 或 qt6 的处理逻辑
|
||||
macro(_handle_spark_translator_qt_macro _outvar)
|
||||
if(SPARK_FIND_QT5)
|
||||
translator_qt5(${_outvar} ${ARGN})
|
||||
endif(SPARK_FIND_QT5)
|
||||
|
||||
if(SPARK_FIND_QT6)
|
||||
translator_qt6(${_outvar} ${ARGN})
|
||||
endif(SPARK_FIND_QT6)
|
||||
endmacro(_handle_spark_translator_qt_macro _outvar)
|
||||
|
||||
# translator_qt _qmvar [... *.ts | match]
|
||||
macro(translator_qt)
|
||||
_handle_spark_translator_qt_macro(${ARGN})
|
||||
endmacro(translator_qt)
|
|
@ -0,0 +1,113 @@
|
|||
# Spark WithGit
|
||||
|
||||
set(SPARK_FRAMEWORK_TO "${CMAKE_SOURCE_DIR}/cmake/_spark")
|
||||
|
||||
function(spark_framework_from_git)
|
||||
|
||||
# 1. 解析参数,使用原生 cmake 提供的参数解析器
|
||||
# set(OPTIONS)
|
||||
set(ONEVARG PREFIX)
|
||||
set(MULVARG COMPONENTS)
|
||||
|
||||
cmake_parse_arguments(SPARK "" "${ONEVARG}" "${MULVARG}" ${ARGN})
|
||||
|
||||
# 2. 如果包含 PREFIX 则开始进行解析
|
||||
if(SPARK_PREFIX)
|
||||
if(NOT EXISTS "${SPARK_FRAMEWORK_TO}")
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory "${SPARK_FRAMEWORK_TO}")
|
||||
endif(NOT EXISTS "${SPARK_FRAMEWORK_TO}")
|
||||
|
||||
foreach(SPARK_COMPONENT IN LISTS SPARK_COMPONENTS)
|
||||
# execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory "${SPARK_PREFIX}.${SPARK_COMPONENT}'"
|
||||
# WORKING_DIRECTORY ${SPARK_FRAMEWORK_TO})
|
||||
if(NOT EXISTS "${SPARK_FRAMEWORK_TO}/${SPARK_COMPONENT}")
|
||||
execute_process(COMMAND git clone "${SPARK_PREFIX}/${SPARK_COMPONENT}"
|
||||
WORKING_DIRECTORY ${SPARK_FRAMEWORK_TO})
|
||||
else()
|
||||
message("[SparkWithGit] Exits: ${SPARK_COMPONENT}")
|
||||
endif(NOT EXISTS "${SPARK_FRAMEWORK_TO}/${SPARK_COMPONENT}")
|
||||
endforeach(SPARK_COMPONENT IN LISTS SPARK_COMPONENTS)
|
||||
endif(SPARK_PREFIX)
|
||||
|
||||
# 方案一:.gitignoe
|
||||
if(NOT EXISTS "${SPARK_FRAMEWORK_TO}/.gitignore")
|
||||
file(WRITE "${SPARK_FRAMEWORK_TO}/.gitignore" "spark.*/\n.gitignore")
|
||||
endif(NOT EXISTS "${SPARK_FRAMEWORK_TO}/.gitignore")
|
||||
|
||||
# 方案二: ../.gitignore
|
||||
# if(NOT EXISTS "${SPARK_FRAMEWORK_TO}/../.gitignore")
|
||||
# file(WRITE "${SPARK_FRAMEWORK_TO}/../.gitignore" "_spark/\n.gitignore")
|
||||
# endif(NOT EXISTS "${SPARK_FRAMEWORK_TO}/../.gitignore")
|
||||
|
||||
endfunction(spark_framework_from_git)
|
||||
|
||||
macro(spark_include)
|
||||
set(_spark_files ${ARGN})
|
||||
foreach(_spark_file IN LISTS _spark_files)
|
||||
if(EXISTS "${_spark_file}")
|
||||
include(${_spark_file})
|
||||
continue()
|
||||
endif(EXISTS "${_spark_file}")
|
||||
file(GLOB_RECURSE _file RELATIVE "${SPARK_FRAMEWORK_TO}" ${_spark_file})
|
||||
list(FILTER _file EXCLUDE REGEX "\\.\\.")
|
||||
|
||||
if(EXISTS "${SPARK_FRAMEWORK_TO}/${_file}")
|
||||
message("FOUND: ${SPARK_FRAMEWORK_TO}/${_file}")
|
||||
include("${SPARK_FRAMEWORK_TO}/${_file}")
|
||||
else()
|
||||
message(WARNING "NOT FOUND: ${SPARK_FRAMEWORK_TO}/${_file}")
|
||||
endif(EXISTS "${SPARK_FRAMEWORK_TO}/${_file}")
|
||||
endforeach(_spark_file IN LISTS _spark_files)
|
||||
endmacro(spark_include)
|
||||
|
||||
|
||||
# 引入的所有 Spark 构建模块
|
||||
spark_framework_from_git(
|
||||
PREFIX
|
||||
http://gitee.com/zinface/
|
||||
COMPONENTS
|
||||
spark.assets-icon
|
||||
spark.env
|
||||
spark.macros
|
||||
spark.find-qt5
|
||||
spark.find-qt6
|
||||
spark.find-dtk
|
||||
spark.find-library
|
||||
spark.macros-extend
|
||||
spark.build-graphviz
|
||||
|
||||
spark.framework
|
||||
spark.cmake-info
|
||||
spark.external-project
|
||||
|
||||
spark.translator-macro
|
||||
spark.install-macros
|
||||
spark.desktop-macro
|
||||
spark.deb-package
|
||||
spark.appimage-macros-online
|
||||
)
|
||||
|
||||
# include(cmake/SparkWithGit.cmake)
|
||||
|
||||
# 用于 spark_include 引入相关的列表项,每一项都是可引用的构建模块
|
||||
# spark_include(
|
||||
# SparkEnvConfig.cmake
|
||||
# SparkMacrosConfig.cmake
|
||||
# SparkFindQt5Config.cmake
|
||||
# SparkFindQt6Config.cmake
|
||||
# SparkFindDtkConfig.cmake
|
||||
# SparkFindLibraries.cmake
|
||||
# SparkMacrosExtendConfig.cmake
|
||||
|
||||
# SparkFramework.cmake
|
||||
# SparkCMakeInfoAfterConfig.cmake
|
||||
# SparkCMakeInfoBeforeConfig.cmake
|
||||
# SparkExternalProject.cmake
|
||||
|
||||
# SparkTranslatorConfig.cmake
|
||||
# SparkInstallMacrosConfig.cmake
|
||||
# SparkBuildGraphviz.cmake
|
||||
# SparkDesktopMacros.cmake
|
||||
# SparkDebPackageConfig.cmake
|
||||
# SparkAppimageConfig.cmake
|
||||
# )
|
|
@ -93,9 +93,10 @@ if not "%deployqt5%" == "6" (
|
|||
:: ------------------------------------------------------------------- ::
|
||||
@echo ----------------------- 构建前配置预览 ---------------------------
|
||||
@echo "cmake -B%builddir% %CMAKE_OPTIONS% ."
|
||||
@echo "cmake --build %builddir% --config %CMAKE_BUILD_TYPE%" --target opencc_git
|
||||
@echo "cmake --build %builddir% --config %CMAKE_BUILD_TYPE%"
|
||||
@echo "cmake --install %builddir% --prefix %installdir%"
|
||||
@echo "cmake --build %builddir% --target windows-deployqt"
|
||||
|
||||
:: ------------------------------------------------------------------- ::
|
||||
|
||||
|
||||
|
@ -103,7 +104,7 @@ if not "%deployqt5%" == "6" (
|
|||
@echo ---- 寻找硬盘中的 msvc 环境配置 ----
|
||||
|
||||
set vcvars=
|
||||
for %%d in (C: D: E: F: G: H:) do (
|
||||
for %%d in ( "C:\Program Files\Microsoft Visual Studio" C: D: E: F: G: H:) do (
|
||||
if exist %%d (
|
||||
@echo 正在查找硬盘 %%d 中的 VC 配置环境...
|
||||
pushd %%d\
|
||||
|
@ -130,6 +131,7 @@ if "%vcvars%" == "" (
|
|||
:: 正式对项目进行配置、构建、安装、部署
|
||||
@echo ------------ 准备构建 ------------
|
||||
cmake -B%builddir% %CMAKE_OPTIONS% .
|
||||
cmake --build %builddir% --config %CMAKE_BUILD_TYPE% --target opencc_git
|
||||
cmake --build %builddir% --config %CMAKE_BUILD_TYPE%
|
||||
cmake --install %builddir% --prefix %installdir%
|
||||
:: 不再使用的部分,由 install 自动配置的 windeployqt 已经配置
|
||||
|
|
|
@ -5,12 +5,17 @@
|
|||
# 1. 默认构建时产出的目标为 Notepad--
|
||||
# 2. 在此处可对 Notepad-- 目标进行详细的构建计划
|
||||
|
||||
# Notepad-- 版本配置
|
||||
configure_file(cmake/modules/config.h.in
|
||||
${CMAKE_BINARY_DIR}/config.h @ONLY)
|
||||
|
||||
if(TRUE)
|
||||
# 准备构建 Notepad-- 主程序
|
||||
set(QRC_SOURCES src/RealCompare.qrc)
|
||||
spark_add_executable_path(${PROJECT_NAME}
|
||||
${PROJECT_SOURCE_DIR}/src
|
||||
${PROJECT_SOURCE_DIR}/src/cceditor
|
||||
${PROJECT_SOURCE_DIR}/src/utils
|
||||
${QRC_SOURCES})
|
||||
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
|
@ -49,20 +54,19 @@ endif(TRUE)
|
|||
|
||||
# ----------------- Notepad-- 构建宏支持相关 ----------------- #
|
||||
|
||||
if(WIN32)
|
||||
# 在 Windows 中构建时,需要关注此库的构建形式,QScintilla 应该以何种方式编译
|
||||
target_compile_definitions(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
NO_PLUGIN # 开启插件支持
|
||||
QSCINTILLA_DLL # 目前在 Windows 中使用 QSci 库时应该采用 Q_DECL_IMPORT
|
||||
# 控制 QSCINTILLA_EXPORT 符号应为 Q_DECL_IMPORT
|
||||
)
|
||||
endif(WIN32)
|
||||
# 在 Windows 中构建时,需要关注此库的构建形式,QScintilla 应该以何种方式编译
|
||||
target_compile_definitions(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
NO_PLUGIN # 开启插件支持
|
||||
)
|
||||
|
||||
if(UNIX)
|
||||
# 在 Windows 中构建时,需要关注此库的构建形式,QScintilla 应该以何种方式编译
|
||||
target_compile_definitions(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
NO_PLUGIN # 开启插件支持
|
||||
)
|
||||
endif(UNIX)
|
||||
# 添加 Notepad-- 目标属性与生成器调试信息
|
||||
spark_cmake_debug(
|
||||
">>>>>>>>>>>>>>>>>>>>>>>>>>> Notepad-- CMake Debug <<<<<<<<<<<<<<<<<<<<<<<<<<<"
|
||||
"Notepad-- LINK_LIBRARIES: $<TARGET_PROPERTY:Notepad--,LINK_LIBRARIES>"
|
||||
"Notepad-- COMPILE_DEFINITIONS: $<TARGET_PROPERTY:Notepad--,COMPILE_DEFINITIONS>"
|
||||
"Notepad-- INTERFACE: $<TARGET_PROPERTY:Notepad--,INTERFACE>"
|
||||
"Notepad-- TARGET_FILE_BASE_NAME: $<TARGET_FILE_BASE_NAME:Notepad-->"
|
||||
"Notepad-- TARGET_FILE_NAME: $<TARGET_FILE_NAME:Notepad-->"
|
||||
">>>>>>>>>>>>>>>>>>>>>>>>>>> Notepad-- CMake Debug <<<<<<<<<<<<<<<<<<<<<<<<<<<"
|
||||
)
|
|
@ -60,16 +60,40 @@ endif(TRUE)
|
|||
|
||||
if(WIN32)
|
||||
# 在 Windows 中构建时,需要关注此库的构建形式,QScintilla 应该以何种方式编译
|
||||
target_compile_definitions(QSci
|
||||
PRIVATE
|
||||
SCINTILLA_QT #
|
||||
SCI_LEXER #
|
||||
INCLUDE_DEPRECATED_FEATURES #
|
||||
QSCINTILLA_MAKE_DLL # 在 Windows 中构建此库时应该采用 Q_DECL_EXPORT
|
||||
# 并且在 Windows 中使用此库时应该采用 Q_DECL_IMPORT
|
||||
# 控制 QSCINTILLA_EXPORT 符号应为:
|
||||
# 构建时(导出),由外部使用时(导入)
|
||||
)
|
||||
if(NOTEPAD_BUILD_BY_SHARED)
|
||||
# 在 Windows 中构建时动态化的 QSci 库时,对于不同的编译器进行处理
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
# 在 Windows 中使用 MSVC 构建时
|
||||
target_compile_definitions(QSci
|
||||
PRIVATE
|
||||
SCINTILLA_QT #
|
||||
SCI_LEXER #
|
||||
INCLUDE_DEPRECATED_FEATURES #
|
||||
|
||||
# 控制 QSCINTILLA_EXPORT 符号应为:
|
||||
# 构建时(导出),由外部使用时(导入)
|
||||
QSCINTILLA_MAKE_DLL # 在 Windows 中构建此库时应该采用 Q_DECL_EXPORT
|
||||
INTERFACE
|
||||
QSCINTILLA_DLL # 在 Windows 中使用此库时应该采用 Q_DECL_IMPORT
|
||||
)
|
||||
else()
|
||||
# 在 Windows 中使用 MinGW 构建时
|
||||
target_compile_definitions(QSci
|
||||
PRIVATE
|
||||
SCINTILLA_QT #
|
||||
SCI_LEXER #
|
||||
INCLUDE_DEPRECATED_FEATURES #
|
||||
)
|
||||
endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
else()
|
||||
# 在 Windows 中构建静态化的 QSci 库时,不同的编译器基本无区别
|
||||
target_compile_definitions(QSci
|
||||
PRIVATE
|
||||
SCINTILLA_QT #
|
||||
SCI_LEXER #
|
||||
INCLUDE_DEPRECATED_FEATURES #
|
||||
)
|
||||
endif(NOTEPAD_BUILD_BY_SHARED)
|
||||
endif(WIN32)
|
||||
|
||||
if(UNIX)
|
||||
|
@ -83,3 +107,14 @@ if(UNIX)
|
|||
# 控制 QSCINTILLA_EXPORT 符号应为留空
|
||||
)
|
||||
endif(UNIX)
|
||||
|
||||
# 添加 QSci 目标属性与生成器调试信息
|
||||
spark_cmake_debug(
|
||||
">>>>>>>>>>>>>>>>>>>>>>>>>>> QSci CMake Debug <<<<<<<<<<<<<<<<<<<<<<<<<<<"
|
||||
"QSci LINK_LIBRARIES: $<TARGET_PROPERTY:QSci,LINK_LIBRARIES>"
|
||||
"QSci COMPILE_DEFINITIONS: $<TARGET_PROPERTY:QSci,COMPILE_DEFINITIONS>"
|
||||
"QSci INTERFACE: $<TARGET_PROPERTY:QSci,INTERFACE>"
|
||||
"QSci TARGET_FILE_BASE_NAME: $<TARGET_FILE_BASE_NAME:QSci>"
|
||||
"QSci TARGET_FILE_NAME: $<TARGET_FILE_NAME:QSci>"
|
||||
">>>>>>>>>>>>>>>>>>>>>>>>>>> QSci CMake Debug <<<<<<<<<<<<<<<<<<<<<<<<<<<"
|
||||
)
|
|
@ -0,0 +1 @@
|
|||
#define NOTEPAD_VERSION "v@PROJECT_VERSION@"
|
|
@ -19,7 +19,7 @@ option(USE_LINUX_APPIMAGE "为 Linux 生成 Appimage 可执行程序" OFF)
|
|||
|
||||
if(USE_LINUX_APPIMAGE)
|
||||
|
||||
include(cmake/SparkDesktopMacros.cmake)
|
||||
spark_include(cmake/SparkDesktopMacros.cmake)
|
||||
# 内容默认应用名称: Name= 应与项目名称相同
|
||||
spark_desktop_macros(
|
||||
# 应用名称: Name=
|
||||
|
@ -40,9 +40,14 @@ if(USE_LINUX_APPIMAGE)
|
|||
)
|
||||
|
||||
# 1. 在顶层构建中导入 Appimage 的构建
|
||||
include(cmake/SparkAppimageConfig.cmake) # 导入来自 Spark 构建的 Appimage 构建
|
||||
spark_include(cmake/SparkAppimageConfig.cmake) # 导入来自 Spark 构建的 Appimage 构建
|
||||
add_appimage_icon(assets/spark.png) # 添加到 Appimage 中的默认的图标
|
||||
add_appimage_desktop() # 添加到 Appimage 中的默认desktop(使用来自 Spark 构建的 Desktop 构建中配置的信息(必须要求 spark-desktop))
|
||||
add_appimage_target(${PROJECT_NAME}) # 应用对 Appimage 的构建
|
||||
add_appimage_target(${PROJECT_NAME}) # 添加到 Appimage 中的默认目标,应用对 Appimage 的构建
|
||||
|
||||
# 处理 src/themes 目录的复制到
|
||||
add_custom_command(TARGET ${PROJECT_NAME}
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/src/themes $<TARGET_FILE_DIR:${PROJECT_NAME}>/themes)
|
||||
|
||||
endif(USE_LINUX_APPIMAGE)
|
||||
|
|
|
@ -9,7 +9,7 @@ option(USE_LINUX_DEBIAN "为 Linux 生成 deb 软件包" OFF)
|
|||
|
||||
if(USE_LINUX_DEBIAN)
|
||||
|
||||
find_package(SparkDebPackage PATHS ${CMAKE_SOURCE_DIR})
|
||||
spark_include(SparkDebPackageConfig.cmake)
|
||||
add_package_descript(cmake/spark-deb-package.descript)
|
||||
|
||||
endif(USE_LINUX_DEBIAN)
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
# 可能需要变更为 CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux" ??
|
||||
# 并使用 Linux.cmake 维护?
|
||||
if(CMAKE_HOST_UNIX)
|
||||
include(cmake/SparkInstallMacrosConfig.cmake)
|
||||
spark_include(cmake/SparkInstallMacrosConfig.cmake)
|
||||
|
||||
# 当使用 Linux 构建应用时,可执行程序的资源文件应该存放在此处
|
||||
set(LINUX_APPLICATION_DIR /usr/share/${PROJECT_NAME})
|
||||
|
|
|
@ -43,7 +43,7 @@ if(USE_LINUX_UOS)
|
|||
# 当使用 Linux 构建应用时,可执行程序的资源文件应该存放在此处
|
||||
set(LINUX_UOS_APP_HOME_DIR ${UOS_APP_HOME_DIR})
|
||||
|
||||
include(cmake/SparkInstallMacrosConfig.cmake)
|
||||
spark_include(cmake/SparkInstallMacrosConfig.cmake)
|
||||
|
||||
# ------------------ 部署应用目录结构 ------------------ #
|
||||
# 1. 将项目内准备的 Uos 应用目录安装到 /opt/apps/ 中
|
||||
|
@ -66,7 +66,7 @@ if(USE_LINUX_UOS)
|
|||
# set(PACKAGE_SUFFIX "_onlyUos")
|
||||
|
||||
# 2. 使用同样来自 debian 系列的 deb 构建能力
|
||||
find_package(SparkDebPackage PATHS ${CMAKE_SOURCE_DIR})
|
||||
spark_include(SparkDebPackageConfig.cmake)
|
||||
add_package_descript(cmake/spark-deb-package.descript)
|
||||
|
||||
endif(USE_LINUX_UOS)
|
||||
|
|
|
@ -124,7 +124,7 @@ if(WINDOWS_DEPLOY_QT)
|
|||
# 执行以下命令进行 windeployqt
|
||||
COMMAND ${WINDOWS_QT_DIR}/../../../bin/windeployqt
|
||||
#
|
||||
${WINDOWS_APPLICATION_DEPLOY_PATH}/QSci.dll
|
||||
${WINDOWS_APPLICATION_DEPLOY_PATH}/$<TARGET_FILE_NAME:QSci>
|
||||
|
||||
# 扫描QML-从目录开始导入。
|
||||
--qmlimport ${WINDOWS_QT_DIR}/../../../qml
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
|
||||
if(CMAKE_HOST_WIN32)
|
||||
include(cmake/SparkInstallMacrosConfig.cmake)
|
||||
spark_include(cmake/SparkInstallMacrosConfig.cmake)
|
||||
# ------------------ INSTALL PLUGIN CONFIG ------------------ #
|
||||
# ------------------ INSTALL PLUGIN CONFIG ------------------ #
|
||||
# ------------------ INSTALL PLUGIN CONFIG ------------------ #
|
||||
|
|
|
@ -30,16 +30,26 @@ APPIMAGETOOL := "$(BUNDLE_LINUXDEPLOYQT)/appimagetool-x86_64.AppImage"
|
|||
# 追加 Appimagetool、linuxdeployqt 构建配置
|
||||
CMAKE_OPTIONS := -DLINUXDEPLOYQT=$(LINUXDEPLOYQT) -DAPPIMAGETOOL=$(APPIMAGETOOL) $(CMAKE_OPTIONS)
|
||||
|
||||
# 执行 Linux DeployQt 并生成可制作 Appimage 的目录结构
|
||||
linuxdeploy: download-bundle-linuxdeploytools
|
||||
cmake -B$(builddir) $(CMAKE_OPTIONS) -DUSE_APPIMAGE_NEW_GLIBC=ON
|
||||
cmake --build $(builddir) --target linuxdeploy
|
||||
|
||||
# 执行 Linux DeployQt 并生成可制作 Appimage 的目录结构
|
||||
# 但生成的应用程序将只使用操作系统中已安装的标准glibc库版本。
|
||||
linuxdeploy-fast: download-bundle-linuxdeploytools
|
||||
cmake -B$(builddir) $(CMAKE_OPTIONS) -DUSE_APPIMAGE_NEW_GLIBC=OFF
|
||||
cmake --build $(builddir) --target linuxdeploy
|
||||
|
||||
# 执行 Appimage 目录结构的打包生成
|
||||
make-appimage:
|
||||
cmake -B$(builddir) $(CMAKE_OPTIONS)
|
||||
cmake --build $(builddir) -- linuxdeploy
|
||||
cmake --build $(builddir) --target appimage
|
||||
|
||||
genrate-appimage:
|
||||
cmake -B$(builddir) $(CMAKE_OPTIONS)
|
||||
cmake --build $(builddir) -- appimage
|
||||
package: linux-universal-release linuxdeploy make-appimage
|
||||
|
||||
|
||||
package: linux-universal-release linuxdeploy genrate-appimage
|
||||
# 不要一开始就使用 - 否则无法生成 AppRun
|
||||
package-fast: linux-universal-release linuxdeploy-fast make-appimage
|
||||
|
||||
linux-build-options:
|
||||
@echo $(CMAKE_OPTIONS)
|
||||
|
|
|
@ -56,8 +56,13 @@ typedef void (*NDD_PROC_FOUND_CALLBACK)(NDD_PROC_DATA* pProcData, void* pUserDat
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
// v1.x 版本的插件接口
|
||||
NDD_EXPORT bool NDD_PROC_IDENTIFY(NDD_PROC_DATA* pProcData);
|
||||
NDD_EXPORT int NDD_PROC_MAIN(QWidget* pNotepad, const QString& strFileName, std::function<QsciScintilla* ()>getCurEdit);
|
||||
NDD_EXPORT int NDD_PROC_MAIN(QWidget* pNotepad, const QString& strFileName, std::function<QsciScintilla* ()>getCurEdit, NDD_PROC_DATA* pProcData);
|
||||
|
||||
// v2.0 版本后的插件接口
|
||||
// NDD_EXPORT bool NDD_PROC_IDENTIFY(NDD_PROC_DATA* pProcData);
|
||||
// NDD_EXPORT int NDD_PROC_MAIN(QWidget* pNotepad, const QString& strFileName, std::function<QsciScintilla* (QWidget*)>getCurEdit, std::function<bool(QWidget*, int, void*)> pluginCallBack, NDD_PROC_DATA* procData);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -70,10 +75,62 @@ typedef void (*NDD_PROC_FOUND_CALLBACK)(NDD_PROC_DATA* pProcData, void* pUserDat
|
|||
pProcData->m_auther = QString(author); \
|
||||
pProcData->m_strFilePath = QString(filepath); \
|
||||
|
||||
#define NOTEPAD_PLUGIN_IMPLEMENT(imp_class) \
|
||||
#define NOTEPAD_PLUGIN_IMPLEMENT(imp_class) \
|
||||
imp_class *imp = new imp_class(pNotepad, getCurEdit()); \
|
||||
//imp->setWindowFlag(Qt::Window); \
|
||||
//imp->setWindowFlag(Qt::Window); \
|
||||
imp->show();
|
||||
|
||||
/*** Interface Implementation Assistant ***/
|
||||
|
||||
// 原始接口
|
||||
#define NOTEPAD_PLUGIN_METADATA_IDENTIFY(name, version, author, comment, filepath) \
|
||||
bool NDD_PROC_IDENTIFY(NDD_PROC_DATA* pProcData) { \
|
||||
NOTEPAD_PLUGIN_METADATA(name, version, author, comment, filepath) \
|
||||
return true;\
|
||||
}\
|
||||
|
||||
#define NOTEPAD_PLUGIN_METADATA_IMPLEMENT(imp_class, imp_show_window) \
|
||||
int NDD_PROC_MAIN(QWidget* pNotepad, const QString& strFileName, std::function<QsciScintilla* ()>getCurEdit, NDD_PROC_DATA* pProcData) {\
|
||||
NOTEPAD_PLUGIN_IMPLEMENT(imp_class); \
|
||||
if (imp_show_window) {\
|
||||
imp->show();\
|
||||
}\
|
||||
return 0;\
|
||||
}\
|
||||
|
||||
// v1 支持 Menu 的接口
|
||||
#define NOTEPAD_PLUGIN_METADATA_IDENTIFY_V1(name, version, author, comment, filepath) \
|
||||
bool NDD_PROC_IDENTIFY(NDD_PROC_DATA* pProcData) { \
|
||||
NOTEPAD_PLUGIN_METADATA(name, version, author, comment, filepath) \
|
||||
pProcData->m_menuType = 1;\
|
||||
return true;\
|
||||
}\
|
||||
|
||||
#define NOTEPAD_PLUGIN_METADATA_IMPLEMENT_V1(imp_class, imp_show_window) \
|
||||
static QWidget *s_pNotepad;\
|
||||
static NDD_PROC_DATA s_pProcData;\
|
||||
static std::function<QsciScintilla* ()> s_getCurEdit;\
|
||||
int NDD_PROC_MAIN(QWidget* pNotepad, const QString& strFileName, std::function<QsciScintilla* ()>getCurEdit, NDD_PROC_DATA* pProcData) {\
|
||||
if(pNotepad != nullptr) { \
|
||||
s_pNotepad = pNotepad; \
|
||||
} else return -1; \
|
||||
\
|
||||
if(pProcData != nullptr) { \
|
||||
s_pProcData = *pProcData; \
|
||||
} else return -1; \
|
||||
\
|
||||
if(getCurEdit != nullptr) { \
|
||||
s_getCurEdit = getCurEdit; \
|
||||
} else return -1; \
|
||||
\
|
||||
NOTEPAD_PLUGIN_IMPLEMENT(imp_class); \
|
||||
imp->setCurrentEditFunc(s_getCurEdit); \
|
||||
imp->setMenuActions(s_pProcData.m_rootMenu);\
|
||||
if (imp_show_window) {\
|
||||
imp->show();\
|
||||
}\
|
||||
return 0;\
|
||||
}\
|
||||
|
||||
#endif //NOTEPAD_PLUGIN_MANAGER
|
||||
/***********在编译插件时提供的内容**************/
|
||||
|
|
|
@ -153,6 +153,11 @@ int main(int argc, char *argv[])
|
|||
a.setApplicationDisplayName(c_strTitle);
|
||||
a.setApplicationName(c_strTitle);
|
||||
|
||||
#include <config.h>
|
||||
#ifdef NOTEPAD_VERSION
|
||||
a.setApplicationVersion(NOTEPAD_VERSION);
|
||||
#endif //NOTEPAD_VERSION
|
||||
|
||||
QStringList arguments = QCoreApplication::arguments();
|
||||
|
||||
//目前就三种
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
|
||||
option(USE_NOTEPAD_PLUGIN "构建 Notepad-- 内部插件" ON)
|
||||
option(USE_NOTEPAD_PLUGIN_BASE "构建 Notepad-- 内部的插件基础模板" OFF)
|
||||
|
||||
|
||||
if(USE_NOTEPAD_PLUGIN)
|
||||
|
||||
# [核心]:[引入插件框架核心模块]
|
||||
include(framework/framework.cmake)
|
||||
include(framework/framework-include.cmake)
|
||||
|
||||
if(USE_NOTEPAD_PLUGIN_BASE) # 早期构建,准备废弃
|
||||
# 默认的测试插件
|
||||
add_subdirectory(test)
|
||||
|
||||
# 被 cmake-plugins-dev 构建的
|
||||
# 基于源代码构建的系列插件模板
|
||||
set(base-plugin_ENABLE ON)
|
||||
add_framework_plugin(base-plugin
|
||||
template-plugins/base-plugin)
|
||||
set(base-secondary-plugin_ENABLE ON)
|
||||
add_framework_plugin(base-secondary-plugin
|
||||
template-plugins/base-secondary-plugin
|
||||
)
|
||||
set(base-secondary-widget-plugin_ENABLE ON)
|
||||
add_framework_plugin(base-secondary-widget-plugin
|
||||
template-plugins/base-secondary-widget-plugin
|
||||
)
|
||||
# add_subdirectory(template-plugins/base-widget-plugin)
|
||||
# add_subdirectory(template-plugins/base-widget-ui-plugin)
|
||||
# add_subdirectory(template-plugins/base-secondary-menu-plugin)
|
||||
# add_subdirectory(template-plugins/base-secondary-menu-plugin-v1)
|
||||
# add_subdirectory(template-plugins/base-secondary-menu-ui-plugin-v1)
|
||||
endif(USE_NOTEPAD_PLUGIN_BASE)
|
||||
|
||||
# [开发者计划]:不改变本 CMakeLists.txt 的情况下开发自己的插件
|
||||
# 非冲突化开发方式,在 dev.cmake 中建立自己的本地引用或在线引用来构建自己的插件。
|
||||
# 并将其作为开发者计划的关注位置点,以此保证本 CMakeLists.txt 可以直接随项目更新
|
||||
include(dev.cmake)
|
||||
|
||||
## [框架:插件目标直接构建]
|
||||
# add_framework_plugin <target> [<dir>...] [<file>...]
|
||||
# 1. 构建一个基于 framework 的插件
|
||||
# 基于提供的包含源代码文件的的路径,或指定的要构建的源代码
|
||||
add_framework_plugin(framework-helloworld
|
||||
framework-plugins/helloworld
|
||||
)
|
||||
|
||||
# 2. 简单的 framework-hello 插件
|
||||
# 基于提供的包含源代码文件的的路径,或指定的要构建的源代码
|
||||
add_framework_plugin(framework-hello-simple
|
||||
${PROJECT_SOURCE_DIR}/src/utils
|
||||
framework-plugins/hello-simple
|
||||
framework-plugins/hello-simple/view
|
||||
framework-plugins/hello-simple/template
|
||||
framework-plugins/hello-simple/buildin.qrc)
|
||||
|
||||
|
||||
## [框架:插件描述引用构建]
|
||||
# include(path/to/plugin.cmake)
|
||||
# 1. 使用本地 plugin.cmake 引用构建(示例)
|
||||
|
||||
|
||||
## [框架:插件 with_git 的引用构建 - 与在线]
|
||||
# add_framework_plugin_with_git <git> [args...]
|
||||
# [框架引用:插件扩展处的资源引用构建]
|
||||
# framework_plugin_include <target> <git>
|
||||
# framework_plugin_include_with_git <target> <git> [args...]
|
||||
|
||||
# 1. 基于 git 仓库在线构建 helloworld 插件
|
||||
# add_framework_plugin_with_git(
|
||||
# https://gitee.com/zinface/notepad--plugin.helloworld
|
||||
# --branch=cmake-plugins-dev)
|
||||
|
||||
# 2. 一个 plantuml 预览插件
|
||||
# (使用 with_git 引用的在线构建)
|
||||
# add_framework_plugin_with_git(
|
||||
# https://gitee.com/ndd-community/notepad--plugin.plantuml-preview
|
||||
# --branch=cmake-plugins-dev)
|
||||
|
||||
# 3. 一个简单的 svg 预览插件
|
||||
# (使用 with_git 引用的在线构建)
|
||||
# (使用了 plantuml 预览插件的共享的资源定义)
|
||||
# add_framework_plugin_with_git(
|
||||
# https://gitee.com/ndd-community/notepad--plugin.svg-preview
|
||||
# --branch=cmake-plugins-dev)
|
||||
|
||||
# 4. 一个使用引用构建的 plantumlexamples 插件
|
||||
# (使用 with_git 引用的在线构建)
|
||||
# (使用了 plantuml 预览插件的共享的资源定义)
|
||||
# (使用了 framework-plugin-component-library 提供的共享的资源定义)
|
||||
# add_framework_plugin_with_git(
|
||||
# https://gitee.com/zinface/notepad--plugin.plantuml-examples
|
||||
# --branch=cmake-plugins-dev)
|
||||
|
||||
|
||||
## 例外:早期的构建模式,即将准备废弃
|
||||
# 一个简单的插件示例,但依赖于外部的 opencc 项目(基于 git)
|
||||
# add_subdirectory(opencc-demo-plugin)
|
||||
# # 一个简单的版本更新检查的插件
|
||||
# add_subdirectory(versionUpdate)
|
||||
# # 一个简单的可二次扩展的插件
|
||||
# add_subdirectory(external-plugin)
|
||||
|
||||
# # Linux 可构建的插件
|
||||
# if(UNIX AND NOT APPLE)
|
||||
# # 一个简单的 Linux 终端插件,但依赖于外部的 lxqt-qterminal
|
||||
# add_subdirectory(linux-terminal-plugin)
|
||||
# endif(UNIX AND NOT APPLE)
|
||||
|
||||
# # TTS 语音合成
|
||||
# add_subdirectory(TTS-plugin)
|
||||
|
||||
endif(USE_NOTEPAD_PLUGIN)
|
|
@ -0,0 +1,181 @@
|
|||
# Notepad--Plugin - 基于基础插件生成器的插件开发说明
|
||||
|
||||
> 流程图示
|
||||
|
||||
- 插件基础生成器主体结构预览
|
||||
|
||||
```cpp
|
||||
/*
|
||||
1. 它本身作为 Notepad-- 的插件
|
||||
2. 它在构建时使用了 buildin.qrc 内置三个模板(h cpp cmake).
|
||||
3. 它通过对话框输入的信息来对模板内容进行替换来生成适用于插件开发结构的代码
|
||||
4. 它可以直接生成到目录,而且内置了一系列模板替换逻辑
|
||||
5. 最后,它为你直接准备好了基础插件结构,并生成最终说明到 Notepad-- 的新编辑器中。
|
||||
*/
|
||||
```
|
||||
|
||||
#### 新插件诞生流程
|
||||
|
||||
1. 使用源码树中的 hello-simple 插件提供的功能
|
||||
|
||||
![图片](doc/image.png)
|
||||
|
||||
2. 在对话框中填写你的插件名称与类名(纯英文不带空格可以直接使用插件名)
|
||||
|
||||
![图片](doc/image-1.png)
|
||||
|
||||
3. 保存(生成)到源码树目录的某个子目录下
|
||||
|
||||
![图片](doc/image-2.png)
|
||||
|
||||
4. 在编辑器中将出现一段cmake的构建说明,粘贴到 src/plugin/CMakeLists.txt 中
|
||||
|
||||
![图片](doc/image-3.png)
|
||||
|
||||
5. 在 Qt Creator 中准备构建这个插件 - 勾选
|
||||
|
||||
![图片](doc/image-4.png)
|
||||
|
||||
6. 在 Qt Creator 中选中这个目标单独构建它
|
||||
|
||||
![图片](doc/image-5.png)
|
||||
|
||||
7. 构建完成直接启动已编译过的 Notepad-- 程序
|
||||
|
||||
![图片](doc/image-6.png)
|
||||
|
||||
8. 在打开的 Notepad-- 中可以发现插件已经加载了
|
||||
|
||||
![图片](doc/image-7.png)
|
||||
|
||||
9. 在插件源码中可以发现一级菜单直接触发时执行的内容
|
||||
|
||||
![图片](doc/image-8.png)
|
||||
|
||||
10. 插件:一级菜单和二级菜单的区别
|
||||
|
||||
![图片](doc/image-9.png)
|
||||
|
||||
11. 插件二级菜单的入口与逻辑说明
|
||||
|
||||
![图片](doc/image-10.png)
|
||||
|
||||
|
||||
|
||||
- 来自 Notepad-- 新插件诞生流程缩略预览
|
||||
|
||||
```shell
|
||||
# 1. 使用源码树中的 hello-simple 插件提供的功能
|
||||
# 2. 在对话框中填写你的插件名称与类名(纯英文不带空格可以直接使用插件名)
|
||||
# 3. 保存(生成)到源码树目录的某个子目录下
|
||||
# 4. 在编辑器中将出现一段cmake的构建说明,粘贴到 src/plugin/CMakeLists.txt 中
|
||||
# 5. 在 Qt Creator 中准备构建这个插件 - 勾选
|
||||
# 6. 在 Qt Creator 中选中这个目标单独构建它
|
||||
# 7. 构建完成直接启动已编译过的 Notepad-- 程序
|
||||
# 8. 在打开的 Notepad-- 中可以发现插件已经加载了
|
||||
# 9. 在插件源码中可以发现一级菜单直接触发时执行的内容
|
||||
# 10. 插件:一级菜单和二级菜单的区别
|
||||
# 11. 插件二级菜单的入口与逻辑说明
|
||||
```
|
||||
|
||||
- 来自框架化构建插件的开发后记
|
||||
|
||||
```shell
|
||||
# 1. 一开始走了好多弯路,以前疯狂用宏来定义入口与触发实现,纯 C 风格的一层操作。
|
||||
# 2. 后来给它加了层 "标准Qt插件开发" 的壳,诞生出基于某种意义上的框架来实现插件。
|
||||
# 3. 开发过几个插件后,发现基于框架的东西基本上都是重复的。
|
||||
# 4.为了解决插件的诞生难题,为了不像用 vulkan 一样画个三角形都要写900行框架初始化代码
|
||||
# 所以用生成器的概念来创造插件的基础代码。
|
||||
```
|
||||
|
||||
### Deprecated: 被废弃的开发说明
|
||||
|
||||
|
||||
> 当前插件开发提供一系列模板
|
||||
|
||||
- 有关基于源代码的插件开发描述与 template-plugins 说明
|
||||
|
||||
```shell
|
||||
...
|
||||
template-plugins/
|
||||
├── base-plugin # 一个比较原始的插件结构,仅用于参考
|
||||
├── base-widget-plugin # 一个基于 QWidget 的插件模板
|
||||
├── base-widget-ui-plugin # 一个基于 QMainWindow 的插件模板
|
||||
│ ├── CMakeLists.txt
|
||||
│ ├── ndd_plugin_implement.cpp # 提供一组结构实现
|
||||
│ ├── ndd_plugin_implement.h #
|
||||
│ ├── ndd_plugin_implement.ui # 提供 ui 文件的插件
|
||||
│ └── plugin.cpp # 提供 插件信息描述文件
|
||||
├── ... # 添加更多的模板类型
|
||||
└── plugin.cpp # 插件宏变化文件,以记录插件宏与接口的历史性变化
|
||||
...
|
||||
```
|
||||
|
||||
- 如何开发一个基于源代码树的插件
|
||||
|
||||
```cmake
|
||||
# 复制一份你所想继承的模板,例如: base-widget-ui-plugin
|
||||
|
||||
# 基于 base-widget-ui-plugin 开发一个新的插件 version-update
|
||||
# 1. 将文件夹重命名为插件名称
|
||||
# 2. 替换内部 CMakeLists.txt 文件的 base-widget-ui-plugin 字符串
|
||||
# 3. 在 plugin/CMakeLists.txt 中添加
|
||||
add_subdirectory(version-update)
|
||||
|
||||
# 4. 在 version-update/plugin.cpp 中
|
||||
NOTEPAD_PLUGIN_METADATA_IDENTIFY("检查更新", "v0.1", "zinface",
|
||||
"Notepad-- 版本检查", "");
|
||||
|
||||
NOTEPAD_PLUGIN_METADATA_IMPLEMENT(NddPluginImplement, false);
|
||||
# NddPluginImplement 是来源于 ndd_plugin_implement.h 的类
|
||||
# false 表示这个窗口不需要显示
|
||||
```
|
||||
|
||||
- 如何开发一个基于源代码树的原生二级菜单显示插件
|
||||
|
||||
```cmake
|
||||
# 复制一份你所想继承的模板,例如: base-secondary-menu-plugin-v1
|
||||
|
||||
# 基于 base-secondary-menu-plugin-v1 开发一个新的插件 external-plugin
|
||||
# 1. 将文件夹重命名为插件名称
|
||||
# 2. 替换内部 CMakeLists.txt 文件的 base-widget-ui-plugin 字符串
|
||||
# 3. 在 plugin/CMakeLists.txt 中添加
|
||||
add_subdirectory(external-plugin)
|
||||
|
||||
# 4. 在 external-plugin/plugin.cpp 中
|
||||
NOTEPAD_PLUGIN_METADATA_IDENTIFY_V1("外部插件测试", "0.1", "zinface",
|
||||
u8"二级扩展的插件支持", "");
|
||||
|
||||
NOTEPAD_PLUGIN_METADATA_IMPLEMENT_V1(NddPluginImplement, false);
|
||||
# NddPluginImplement 是来源于 ndd_plugin_implement.h 的类
|
||||
# false 表示这个窗口不需要显示
|
||||
```
|
||||
|
||||
- 有关 plugin.cpp 宏变化文件
|
||||
|
||||
```shell
|
||||
# 1. 记录了在 cmake-dev 以前的插件宏实现方式
|
||||
# 2. 记录了在 cmake-dev 以来的插件宏实现方式
|
||||
# 3. 记录了在 cmake-plugins-dev 以来的插件宏实现方式
|
||||
# 4. 记录了在 原生支持二级菜单显示 以来的插件宏实现方式
|
||||
# ...
|
||||
```
|
||||
|
||||
|
||||
- 写在后面
|
||||
|
||||
```shell
|
||||
# 此系列插件继承原有的模式,暂不支持在源代码之外构建
|
||||
#
|
||||
# 注意:
|
||||
# 由于插件系列统一以 ndd_plugin_implement 为文件名
|
||||
# 在编写 ui 文件时,请提前打开此 ui 文件相关的 cpp 文件
|
||||
# 或关闭其它不相关的插件源文件,以避免生成槽函数时出现在其它位置
|
||||
|
||||
# 关于在 Windows 中编译插件出现的问题:
|
||||
# 1. error C2001: 常量中有换行符
|
||||
# 在中文与双引号处添加空格为分隔:"中文 "
|
||||
# 或在中文结束位置添加英文结束符:"中文."
|
||||
|
||||
# 此错误一般来源于 NOTEPAD_PLUGIN_METADATA_IDENTIFY 宏
|
||||
```
|
|
@ -0,0 +1,91 @@
|
|||
# TTS-plugin/CMakeLists.txt
|
||||
# 用于在源代码中构建一个插件的模板
|
||||
|
||||
# 如果不是在源代码中构建插件,请不要使用这个部分
|
||||
# 如果想在源代码中添加更多内置模板
|
||||
# 请替换 TTS-plugin 为你的插件名称
|
||||
# TTS-plugin -> your plugin name
|
||||
|
||||
set(LOCAL_PLUGIN_NAME "TTS-plugin")
|
||||
|
||||
# TTS-plugin 核心构建
|
||||
# 在模块化构建中,这个部分代表着构建 TTS-plugin 插件
|
||||
# 1. 默认构建时产出的目标为 TTS-plugin
|
||||
# 2. 在此处可对 TTS-plugin 目标进行详细的构建计划
|
||||
|
||||
if(TRUE)
|
||||
# 准备构建 TTS-plugin 主程序扩展
|
||||
spark_file_glob(LocalSources
|
||||
./*.h ./*.cpp ./*.ui
|
||||
)
|
||||
spark_add_library(${LOCAL_PLUGIN_NAME} SHARED ${LocalSources})
|
||||
target_include_directories(${LOCAL_PLUGIN_NAME} PRIVATE
|
||||
${PROJECT_SOURCE_DIR}/src
|
||||
${PROJECT_SOURCE_DIR}/src/cceditor
|
||||
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/src
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/src/Qsci
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/scintilla/src
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/scintilla/include
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/scintilla/lexlib
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/scintilla/boostregex
|
||||
)
|
||||
# target_link_libraries(${LOCAL_PLUGIN_NAME} QSci)
|
||||
target_link_QSci(${LOCAL_PLUGIN_NAME})
|
||||
if(USE_QT6)
|
||||
# target_link_qt6_Core5Compat(${LOCAL_PLUGIN_NAME}) # 兼容性: Qt6 可使用 Core5Compat 少量更改 Qt5 部分
|
||||
# target_link_qt6_PrintSupport(${LOCAL_PLUGIN_NAME})
|
||||
# target_link_qt6_XmlPatterns(${LOCAL_PLUGIN_NAME}) # Bug 初期配置时无此依赖要求
|
||||
else()
|
||||
# target_link_qt5_PrintSupport(${LOCAL_PLUGIN_NAME})
|
||||
# target_link_qt5_XmlPatterns(${LOCAL_PLUGIN_NAME})
|
||||
endif(USE_QT6)
|
||||
|
||||
# 确保生成到 Notepad-- 的相对 plugin 目录下
|
||||
set_target_properties(${LOCAL_PLUGIN_NAME}
|
||||
PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:${PROJECT_NAME}>/plugin
|
||||
LIBRARY_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:${PROJECT_NAME}>/plugin
|
||||
ARCHIVE_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:${PROJECT_NAME}>/plugin)
|
||||
|
||||
# 控制是否安装到 bin/plugin 而各种配方之下,每个位置或许都不一样(特别是 Linux)
|
||||
# install(TARGETS ${LOCAL_PLUGIN_NAME} DESTINATION bin/plugin)
|
||||
endif(TRUE)
|
||||
|
||||
|
||||
# ----------------- TTS-plugin 构建宏支持相关 ----------------- #
|
||||
|
||||
if(WIN32 AND NOTEPAD_BUILD_BY_SHARED)
|
||||
# 在 Windows 中构建时,需要关注此库的构建形式,QScintilla 应该以何种方式编译
|
||||
target_compile_definitions(${LOCAL_PLUGIN_NAME}
|
||||
PRIVATE
|
||||
NOTEPAD_PLUGIN_MANAGER
|
||||
QSCINTILLA_DLL # 目前在 Windows 中使用 QSci 库时应该采用 Q_DECL_IMPORT
|
||||
# 控制 QSCINTILLA_EXPORT 符号应为 Q_DECL_IMPORT
|
||||
)
|
||||
else()
|
||||
# 在 Windows 中构建时,需要关注此库的构建形式,QScintilla 应该以何种方式编译
|
||||
target_compile_definitions(${LOCAL_PLUGIN_NAME}
|
||||
PRIVATE
|
||||
NOTEPAD_PLUGIN_MANAGER
|
||||
# QSCINTILLA_DLL # 目前在 Windows 中使用 QSci 库时应该采用 Q_DECL_IMPORT
|
||||
# 控制 QSCINTILLA_EXPORT 符号应为 Q_DECL_IMPORT
|
||||
)
|
||||
endif(WIN32 AND NOTEPAD_BUILD_BY_SHARED)
|
||||
|
||||
if(UNIX)
|
||||
# 默认在 Unix/Linux 中仅需要定义一个内部插件宏管理器
|
||||
target_compile_definitions(${LOCAL_PLUGIN_NAME}
|
||||
PRIVATE
|
||||
NOTEPAD_PLUGIN_MANAGER
|
||||
)
|
||||
endif(UNIX)
|
||||
|
||||
# ----------------- TTS-plugin 构建的外部项目依赖 ----------------- #
|
||||
|
||||
# include(ExternalProject)
|
||||
|
||||
# ExternalProject_Add(
|
||||
# GIT_REPOSITORY
|
||||
# https://gitee.com/mirrors/ekho.git
|
||||
# )
|
|
@ -0,0 +1,41 @@
|
|||
# TTS 语音合成插件说明
|
||||
|
||||
这是一个使用 espeak 和 ekho 进行 TTS 语音合成的插件。
|
||||
|
||||
## 简介
|
||||
TTS (Text-to-Speech) 语音合成技术是一种将文本转换成音频的技术,可以让计算机像人一样“说话”。该项目使用 espeak 和 ekho 进行 TTS 语音合成,支持多种语言,包括英文、中文、日文、韩文等等。
|
||||
|
||||
### espeak
|
||||
espeak 是一款轻量级的 TTS 引擎,可以通过命令行进行调用,支持多种语言和音色。
|
||||
|
||||
### ekho
|
||||
ekho 是一个中文 TTS 引擎,支持多种中文方言,包括普通话、粤语、闽南语、客家语等等,也支持英文和其他语言。
|
||||
|
||||
## 安装
|
||||
|
||||
### 安装 espeak
|
||||
espeak 可以通过包管理器进行安装:
|
||||
|
||||
- Debian/Ubuntu 系统:sudo apt-get install espeak
|
||||
- Red Hat/Fedora/CentOS 系统:sudo yum install espeak
|
||||
- macOS:brew install espeak
|
||||
|
||||
也可以从官网下载编译安装,详情请见 [espeak](https://espeak.sourceforge.net/) 官网.
|
||||
|
||||
### 安装 ekho
|
||||
|
||||
ekho 也可以通过包管理器进行安装:
|
||||
|
||||
- Debian/Ubuntu 系统:sudo apt-get install ekho
|
||||
- Red Hat/Fedora/CentOS 系统:sudo yum install ekho
|
||||
- macOS:brew install ekho
|
||||
|
||||
|
||||
也可以从 GitHub 上下载源码编译安装,详情请见 [ekho GitHub](https://github.com/hgneng/ekho) 主页.
|
||||
|
||||
|
||||
## 一些扩展来源
|
||||
|
||||
- e-speak 语音合成器 https://www.oschina.net/p/espeak
|
||||
- Ekho 7.0 发布,中文语音合成:https://www.oschina.net/news/76933/ekho-7-0
|
||||
- Ekho(余音) - 中文语音合成软件:http://www.eguidedog.net/cn/index.php
|
|
@ -0,0 +1,258 @@
|
|||
#include "ndd_plugin_implement.h"
|
||||
#include "ui_ndd_plugin_implement.h"
|
||||
|
||||
#include <qsciscintilla.h>
|
||||
#include <QDebug>
|
||||
#include <QProcess>
|
||||
|
||||
#include <QDir>
|
||||
#include <QDockWidget>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QThread>
|
||||
NddPluginImplement::NddPluginImplement(QWidget *parent, QsciScintilla *pEdit) : QMainWindow(parent)
|
||||
, currentWidget(parent)
|
||||
, currentEdit(pEdit)
|
||||
, ttsSettingWidget(new Ui::NddPluginImplement)
|
||||
{
|
||||
ttsSettingWidget->setupUi(this);
|
||||
}
|
||||
|
||||
NddPluginImplement::~NddPluginImplement()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void NddPluginImplement::setMenuActions(QMenu *menu)
|
||||
{
|
||||
|
||||
connect(menu->addAction(u8"TTS Settings"), &QAction::triggered, this, [=](){
|
||||
this->setParent(nullptr);
|
||||
this->show();
|
||||
});
|
||||
|
||||
connect(menu->addAction(u8"TTS Settings(Dock)"), &QAction::triggered, this, [=](){
|
||||
auto mainWindow = dynamic_cast<QMainWindow*>(currentWidget);
|
||||
if(!mainWindow) {
|
||||
qDebug() << "None";
|
||||
return;
|
||||
}
|
||||
|
||||
QDockWidget *m_dockWidget = new QDockWidget(mainWindow);
|
||||
m_dockWidget->setMinimumSize(100, 200);
|
||||
mainWindow->addDockWidget(Qt::RightDockWidgetArea, m_dockWidget);
|
||||
|
||||
if (!m_dockWidget->isVisible())
|
||||
m_dockWidget->show();
|
||||
|
||||
m_dockWidget->setWidget(this);
|
||||
});
|
||||
|
||||
|
||||
//
|
||||
connect(menu->addAction(u8"TTS Start"), &QAction::triggered, this, [&](){
|
||||
// 获取当前编辑器,并直接打印编辑器内容
|
||||
QsciScintilla *edit = getCurrentEditFunc();
|
||||
|
||||
QStringList arguments = QStringList() << "-v" << "zh" << edit->selectedText();;
|
||||
speakeSpeck(arguments);
|
||||
});
|
||||
|
||||
connect(menu->addAction(u8"TTS Stop"), &QAction::triggered, this, [&](){
|
||||
if (process->state() != QProcess::NotRunning) {
|
||||
process->kill();
|
||||
}
|
||||
});
|
||||
|
||||
connect(menu->addAction(u8"阅读选中内容 eSpeak (未指定)"), &QAction::triggered, this, [&](){
|
||||
QStringList arguments = QStringList() << getCurrentEditFunc()->selectedText();
|
||||
|
||||
speakeSpeck(arguments);
|
||||
});
|
||||
|
||||
connect(menu->addAction(u8"阅读选中内容 eSpeak (普通话)"), &QAction::triggered, this, [&](){
|
||||
QStringList arguments = QStringList() << "-v" << "zh" << getCurrentEditFunc()->selectedText();
|
||||
|
||||
speakeSpeck(arguments);
|
||||
});
|
||||
|
||||
connect(menu->addAction(u8"阅读选中内容 Ekho (未指定)"), &QAction::triggered, this, [&](){
|
||||
QStringList arguments = QStringList() << getCurrentEditFunc()->selectedText();
|
||||
|
||||
speakeSpeck(arguments);
|
||||
});
|
||||
|
||||
connect(menu->addAction(u8"阅读选中内容 Ekho (普通话)"), &QAction::triggered, this, [&](){
|
||||
QStringList arguments = QStringList() << "-v" << "Mandarin" << getCurrentEditFunc()->selectedText();
|
||||
|
||||
speakEkho(arguments);
|
||||
});
|
||||
|
||||
connect(menu->addAction(u8"阅读选中内容 Ekho (广东话-粤语)"), &QAction::triggered, this, [&](){
|
||||
QStringList arguments = QStringList() << "-v" << "Cantonese" << getCurrentEditFunc()->selectedText();
|
||||
|
||||
speakEkho(arguments);
|
||||
});
|
||||
|
||||
connect(menu->addAction(u8"阅读选中内容 Ekho (台山话)"), &QAction::triggered, this, [&](){
|
||||
QStringList arguments = QStringList() << "-v" << "Toisanese" << getCurrentEditFunc()->selectedText();
|
||||
|
||||
speakEkho(arguments);
|
||||
});
|
||||
|
||||
connect(menu->addAction(u8"阅读选中内容 Ekho (客家话)"), &QAction::triggered, this, [&](){
|
||||
QStringList arguments = QStringList() << "-v" << "Hakka" << getCurrentEditFunc()->selectedText();
|
||||
|
||||
speakEkho(arguments);
|
||||
});
|
||||
|
||||
connect(menu->addAction(u8"阅读选中内容 Ekho (藏语)"), &QAction::triggered, this, [&](){
|
||||
QStringList arguments = QStringList() << "-v" << "Tibetan" << getCurrentEditFunc()->selectedText();
|
||||
|
||||
speakEkho(arguments);
|
||||
});
|
||||
|
||||
connect(menu->addAction(u8"阅读选中内容 Ekho (南京话)"), &QAction::triggered, this, [&](){
|
||||
QStringList arguments = QStringList() << "-v" << "Ngangien" << getCurrentEditFunc()->selectedText();
|
||||
|
||||
speakEkho(arguments);
|
||||
});
|
||||
|
||||
connect(menu->addAction(u8"阅读选中内容 Ekho (韩语)"), &QAction::triggered, this, [&](){
|
||||
QStringList arguments = QStringList() << "-v" << "Hangul" << getCurrentEditFunc()->selectedText();
|
||||
|
||||
speakEkho(arguments);
|
||||
});
|
||||
|
||||
connect(menu->addAction(u8"监听变化"), &QAction::triggered, this, [&](){
|
||||
// QThread *thread = new QThread;
|
||||
|
||||
currentEdit = getCurrentEditFunc();
|
||||
|
||||
// 光标移动声
|
||||
connect(currentEdit, &QsciScintilla::selectionChanged, this, [=](){
|
||||
speakeSpeckEditrMonitor("k", 450);
|
||||
});
|
||||
|
||||
// 输入声 - change event
|
||||
connect(currentEdit, &QsciScintilla::textChanged, this, [=](){
|
||||
QStringList arguments = QStringList() << "-v" << "zh";
|
||||
speakeSpeckEditrMonitor(u8"滴", arguments, 450);
|
||||
});
|
||||
});
|
||||
|
||||
// Cursor
|
||||
connect(menu->addAction(u8"光标行号变化监听"), &QAction::triggered, this, [&](){
|
||||
currentEdit = getCurrentEditFunc();
|
||||
connect(currentEdit, &QsciScintilla::cursorPosChange, this, [=](int x, int y){
|
||||
QStringList arguments = QStringList() << "-v" << "zh";
|
||||
speakEkhoEditrMonitor(QString(u8"现在是第 %1").arg(x+1), arguments, 175);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ...
|
||||
|
||||
void NddPluginImplement::speakeSpeckEditrMonitor(const QString &text) {
|
||||
|
||||
QStringList arguments = QStringList() << "-v" << "en" << "-s" << "450" << text;
|
||||
|
||||
speakeSpeck(arguments);
|
||||
}
|
||||
|
||||
void NddPluginImplement::speakeSpeckEditrMonitor(const QString &text, int speed) {
|
||||
QStringList arguments = QStringList() << "-v" << "en" << "-s" << QString::number(speed) << text;
|
||||
|
||||
speakeSpeck(arguments);
|
||||
}
|
||||
|
||||
void NddPluginImplement::speakeSpeckEditrMonitor(const QString &text, QStringList &arguments, int speed)
|
||||
{
|
||||
arguments << "-s" << QString::number(speed) << text;
|
||||
|
||||
speakeSpeck(arguments);
|
||||
}
|
||||
|
||||
void NddPluginImplement::speakEkhoEditrMonitor(const QString &text)
|
||||
{
|
||||
QStringList arguments = QStringList() << text;
|
||||
|
||||
speakEkho(arguments);
|
||||
}
|
||||
|
||||
void NddPluginImplement::speakEkhoEditrMonitor(const QString &text, int speed)
|
||||
{
|
||||
QStringList arguments = QStringList() << "-s" << QString::number(speed) << text;
|
||||
|
||||
speakeSpeck(arguments);
|
||||
}
|
||||
|
||||
void NddPluginImplement::speakEkhoEditrMonitor(const QString &text, QStringList &arguments, int speed)
|
||||
{
|
||||
arguments << "-s" << QString::number(speed) << text;
|
||||
|
||||
speakeSpeck(arguments);
|
||||
}
|
||||
|
||||
void NddPluginImplement::speakeSpeck(const QString &text) {
|
||||
QStringList arguments = QStringList() << "-v" << "zh" << "-s" << "600";
|
||||
|
||||
arguments << "滴";
|
||||
|
||||
speakeSpeck(arguments);
|
||||
}
|
||||
|
||||
void NddPluginImplement::speakeSpeck(const QStringList &arguments)
|
||||
{
|
||||
if (process->state() == QProcess::Running) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString eSpeakEngine = ttsSettingWidget->espeakEngine->text();
|
||||
if (!QFile::exists(eSpeakEngine)) {
|
||||
return;
|
||||
}
|
||||
QDir eSpeakEngineDir = QFileInfo(eSpeakEngine).absoluteDir();
|
||||
|
||||
if (process->state() == QProcess::NotRunning) {
|
||||
process->start(eSpeakEngine, arguments);
|
||||
if (!process->waitForStarted(1000)) {
|
||||
qDebug() << "Failed to start espeak process";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NddPluginImplement::speakEkho(const QString &text) {
|
||||
QStringList arguments = QStringList() << getCurrentEditFunc()->text();
|
||||
|
||||
speakEkho(arguments);
|
||||
}
|
||||
|
||||
void NddPluginImplement::speakEkho(const QStringList &arguments)
|
||||
{
|
||||
if (process->state() == QProcess::Running) {
|
||||
process->kill();
|
||||
}
|
||||
|
||||
QString ekhoEngine = ttsSettingWidget->ekhoEngine->text();
|
||||
if (!QFile::exists(ekhoEngine)) {
|
||||
return;
|
||||
}
|
||||
QDir ekhoEngineDir = QFileInfo(ekhoEngine).absoluteDir();
|
||||
|
||||
process->setWorkingDirectory(ekhoEngineDir.absolutePath());
|
||||
if (process->state() == QProcess::NotRunning) {
|
||||
process->start(ekhoEngine, arguments);
|
||||
if (!process->waitForStarted(1000)) {
|
||||
qDebug() << "Failed to start espeak process";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NddPluginImplement::on_pushButton_clicked()
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
#ifndef NDD_PLUGIN_IMPLEMENT_H
|
||||
#define NDD_PLUGIN_IMPLEMENT_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QMenu>
|
||||
#include <QProcess>
|
||||
|
||||
class QsciScintilla;
|
||||
namespace Ui {
|
||||
class NddPluginImplement;
|
||||
};
|
||||
|
||||
class NddPluginImplement : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NddPluginImplement(QWidget *parent = nullptr, QsciScintilla *pEdit = nullptr);
|
||||
~NddPluginImplement();
|
||||
|
||||
void setMenuActions(QMenu *menu);
|
||||
void setCurrentEditFunc(std::function<QsciScintilla* ()> func) {
|
||||
getCurrentEditFunc = func;
|
||||
}
|
||||
|
||||
private slots:
|
||||
void speakeSpeck(const QString &text);
|
||||
void speakeSpeck(const QStringList &arguments);
|
||||
void speakEkho(const QString &text);
|
||||
void speakEkho(const QStringList &arguments);
|
||||
|
||||
void speakeSpeckEditrMonitor(const QString &text);
|
||||
void speakeSpeckEditrMonitor(const QString &text, int speed);
|
||||
void speakeSpeckEditrMonitor(const QString &text, QStringList &arguments, int speed);
|
||||
|
||||
void speakEkhoEditrMonitor(const QString &text);
|
||||
void speakEkhoEditrMonitor(const QString &text, int speed);
|
||||
void speakEkhoEditrMonitor(const QString &text, QStringList &arguments, int speed);
|
||||
|
||||
void on_pushButton_clicked();
|
||||
|
||||
private:
|
||||
// 目前看来需要准备一个完整内部状态
|
||||
QWidget *currentWidget;
|
||||
QsciScintilla *currentEdit;
|
||||
std::function<QsciScintilla* ()> getCurrentEditFunc;
|
||||
|
||||
QProcess *process = new QProcess;
|
||||
|
||||
private:
|
||||
Ui::NddPluginImplement *ttsSettingWidget;
|
||||
|
||||
};
|
||||
|
||||
#endif // NDD_PLUGIN_IMPLEMENT_H
|
|
@ -0,0 +1,106 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>NddPluginImplement</class>
|
||||
<widget class="QMainWindow" name="NddPluginImplement">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>571</width>
|
||||
<height>370</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>TTS Settings Panel</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>TTS Settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>TTS Engine(eSpeak):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="espeakEngine">
|
||||
<property name="text">
|
||||
<string>/usr/bin/espeak</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_2">
|
||||
<property name="text">
|
||||
<string>Open</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>TTS Engine(Ekho):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="ekhoEngine">
|
||||
<property name="text">
|
||||
<string>/usr/bin/ekho</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="text">
|
||||
<string>Open</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>226</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>571</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -0,0 +1,11 @@
|
|||
#include <qobject.h>
|
||||
#include <qstring.h>
|
||||
#include <include/pluginGl.h>
|
||||
#include <functional>
|
||||
#include <qsciscintilla.h>
|
||||
#include "ndd_plugin_implement.h"
|
||||
|
||||
|
||||
NOTEPAD_PLUGIN_METADATA_IDENTIFY_V1(u8"TTS 语音合成", "0.1", "zinface", u8"二级菜单高级插件", "");
|
||||
|
||||
NOTEPAD_PLUGIN_METADATA_IMPLEMENT_V1(NddPluginImplement, false);
|
|
@ -0,0 +1,15 @@
|
|||
# DO NOT COMMIT THIS FILE!
|
||||
|
||||
# [开发者计划](Developer plan):
|
||||
# 不改变 CMakeLists.txt 的情况下开发自己的插件(Develop your own plugin without changing CMakeLists.txt)
|
||||
|
||||
# [I] : copy the provided examples. like this:
|
||||
# 1. 基于 git 仓库在线构建 helloworld 插件(Build the helloworld plug-in online based on the git repository.)
|
||||
# add_framework_plugin_with_git(
|
||||
# https://gitee.com/zinface/notepad--plugin.helloworld
|
||||
# --branch=cmake-plugins-dev)
|
||||
|
||||
# Now, develop your new plugin:
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 236 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 118 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 124 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 27 KiB |
|
@ -0,0 +1,103 @@
|
|||
# external-plugin/CMakeLists.txt
|
||||
# 用于在源代码中构建一个插件的模板
|
||||
|
||||
# 如果不是在源代码中构建插件,请不要使用这个部分
|
||||
# 如果想在源代码中添加更多内置模板
|
||||
# 请替换 external-plugin 为你的插件名称
|
||||
# external-plugin -> your plugin name
|
||||
|
||||
set(LOCAL_PLUGIN_NAME "external-plugin")
|
||||
|
||||
# external-plugin 核心构建
|
||||
# 在模块化构建中,这个部分代表着构建 external-plugin 插件
|
||||
# 1. 默认构建时产出的目标为 external-plugin
|
||||
# 2. 在此处可对 external-plugin 目标进行详细的构建计划
|
||||
|
||||
if(TRUE)
|
||||
# 准备构建 external-plugin 主程序扩展
|
||||
spark_file_glob(LocalSources
|
||||
./*.h ./*.cpp ./*.ui
|
||||
)
|
||||
spark_add_library(${LOCAL_PLUGIN_NAME} SHARED ${LocalSources})
|
||||
target_include_directories(${LOCAL_PLUGIN_NAME} PRIVATE
|
||||
${PROJECT_SOURCE_DIR}/src
|
||||
${PROJECT_SOURCE_DIR}/src/cceditor
|
||||
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/src
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/src/Qsci
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/scintilla/src
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/scintilla/include
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/scintilla/lexlib
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/scintilla/boostregex
|
||||
)
|
||||
# target_link_libraries(${LOCAL_PLUGIN_NAME} QSci)
|
||||
target_link_QSci(${LOCAL_PLUGIN_NAME})
|
||||
if(USE_QT6)
|
||||
# target_link_qt6_Core5Compat(${LOCAL_PLUGIN_NAME}) # 兼容性: Qt6 可使用 Core5Compat 少量更改 Qt5 部分
|
||||
# target_link_qt6_PrintSupport(${LOCAL_PLUGIN_NAME})
|
||||
# target_link_qt6_XmlPatterns(${LOCAL_PLUGIN_NAME}) # Bug 初期配置时无此依赖要求
|
||||
else()
|
||||
# target_link_qt5_PrintSupport(${LOCAL_PLUGIN_NAME})
|
||||
# target_link_qt5_XmlPatterns(${LOCAL_PLUGIN_NAME})
|
||||
endif(USE_QT6)
|
||||
|
||||
# 确保生成到 Notepad-- 的相对 plugin 目录下
|
||||
set_target_properties(${LOCAL_PLUGIN_NAME}
|
||||
PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:${PROJECT_NAME}>/plugin
|
||||
LIBRARY_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:${PROJECT_NAME}>/plugin
|
||||
ARCHIVE_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:${PROJECT_NAME}>/plugin)
|
||||
|
||||
# 控制是否安装到 bin/plugin 而各种配方之下,每个位置或许都不一样(特别是 Linux)
|
||||
# install(TARGETS ${LOCAL_PLUGIN_NAME} DESTINATION bin/plugin)
|
||||
endif(TRUE)
|
||||
|
||||
|
||||
# ----------------- external-plugin 构建宏支持相关 ----------------- #
|
||||
|
||||
if(WIN32 AND NOTEPAD_BUILD_BY_SHARED)
|
||||
# 在 Windows 中构建时,需要关注此库的构建形式,QScintilla 应该以何种方式编译
|
||||
target_compile_definitions(${LOCAL_PLUGIN_NAME}
|
||||
PRIVATE
|
||||
NOTEPAD_PLUGIN_MANAGER
|
||||
QSCINTILLA_DLL # 目前在 Windows 中使用 QSci 库时应该采用 Q_DECL_IMPORT
|
||||
# 控制 QSCINTILLA_EXPORT 符号应为 Q_DECL_IMPORT
|
||||
)
|
||||
else()
|
||||
# 在 Windows 中构建时,需要关注此库的构建形式,QScintilla 应该以何种方式编译
|
||||
target_compile_definitions(${LOCAL_PLUGIN_NAME}
|
||||
PRIVATE
|
||||
NOTEPAD_PLUGIN_MANAGER
|
||||
# QSCINTILLA_DLL # 目前在 Windows 中使用 QSci 库时应该采用 Q_DECL_IMPORT
|
||||
# 控制 QSCINTILLA_EXPORT 符号应为 Q_DECL_IMPORT
|
||||
)
|
||||
endif(WIN32 AND NOTEPAD_BUILD_BY_SHARED)
|
||||
|
||||
if(UNIX)
|
||||
# 默认在 Unix/Linux 中仅需要定义一个内部插件宏管理器
|
||||
target_compile_definitions(${LOCAL_PLUGIN_NAME}
|
||||
PRIVATE
|
||||
NOTEPAD_PLUGIN_MANAGER
|
||||
)
|
||||
endif(UNIX)
|
||||
|
||||
|
||||
# ----------------- external-plugin 构建的外部项目依赖 ----------------- #
|
||||
add_library(external-plugin-base SHARED
|
||||
external-plugin/base.cpp external-plugin/interface/external.h)
|
||||
|
||||
if(WIN32)
|
||||
target_compile_features(external-plugin-base PUBLIC cxx_std_20)
|
||||
set_target_properties(external-plugin-base
|
||||
PROPERTIES
|
||||
LIBRARY_OUTPUT_DIRECTORY "$<TARGET_FILE_DIR:${PROJECT_NAME}>/plugin/external-plugins"
|
||||
ARCHIVE_OUTPUT_DIRECTORY "$<TARGET_FILE_DIR:${PROJECT_NAME}>/plugin/external-plugins"
|
||||
RUNTIME_OUTPUT_DIRECTORY "$<TARGET_FILE_DIR:${PROJECT_NAME}>/plugin/external-plugins")
|
||||
endif(WIN32)
|
||||
|
||||
if(UNIX)
|
||||
set_target_properties(external-plugin-base
|
||||
PROPERTIES
|
||||
LIBRARY_OUTPUT_DIRECTORY "$<TARGET_FILE_DIR:${PROJECT_NAME}>/plugin/external-plugins")
|
||||
endif(UNIX)
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
#include "interface/external.h"
|
||||
|
||||
// #include <stdio.h>
|
||||
// #include <string.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
void sayHello(std::string &content) {
|
||||
std::cout << "Hello World!" << std::endl;
|
||||
}
|
||||
|
||||
void appendSome(std::string &content) {
|
||||
content = "!!!!!!!!!!";
|
||||
}
|
||||
|
||||
void writeSome(std::string &content) {
|
||||
content += "\n重写了编辑器内容!!!!!!!!!!";
|
||||
}
|
||||
|
||||
void openLinkNotepad(std::string &content) {
|
||||
content = "https://gitee.com/cxasm/notepad--";
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
#ifdef WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
struct externalplugin plugin = {
|
||||
.type = ActionBase,
|
||||
.meta = "打印 Hello",
|
||||
.func = sayHello,
|
||||
};
|
||||
|
||||
#ifdef WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
struct externalplugin plugins[] = {
|
||||
{
|
||||
.type = ActionBase,
|
||||
.meta = "打印 Hello",
|
||||
.func = sayHello
|
||||
},
|
||||
{
|
||||
.type = ActionAppend,
|
||||
.meta = "追加 !!!!!!!",
|
||||
.func = appendSome
|
||||
},
|
||||
{
|
||||
.type = ActionReplace,
|
||||
.meta = "重写编辑器内容",
|
||||
.func = writeSome
|
||||
},
|
||||
{
|
||||
.type = ActionOpenHomeDir,
|
||||
.meta = "打开主目录",
|
||||
},
|
||||
{
|
||||
.type = ActionOpenLink,
|
||||
.meta = "打开此项目页面",
|
||||
.func = openLinkNotepad,
|
||||
},
|
||||
{
|
||||
.type = ActionUnknow
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef __EXTERNAL__H__
|
||||
#define __EXTERNAL__H__
|
||||
|
||||
#include <string>
|
||||
|
||||
enum actionType {
|
||||
ActionUnknow = -1, // unknown action,用于标志定义的结束
|
||||
|
||||
ActionBase, // 基本,你可以获取编辑器的内容
|
||||
ActionAppend, // 追加,意味着你的内容被追加到尾部
|
||||
ActionReplace, // 替换,意味着你的内容将被替换到编辑器中
|
||||
|
||||
ActionOpenHomeDir, // 打开,主目录,也就是用户目录
|
||||
ActionOpenLink, // 打开,链接
|
||||
};
|
||||
typedef void (*externalfunction)(std::string &content);
|
||||
|
||||
struct externalplugin {
|
||||
enum actionType type;
|
||||
const char *meta;
|
||||
externalfunction func;
|
||||
};
|
||||
|
||||
#endif //!__EXTERNAL__H__
|
|
@ -0,0 +1,132 @@
|
|||
#include "ndd_plugin_implement.h"
|
||||
#include "ui_ndd_plugin_implement.h"
|
||||
|
||||
#include <qsciscintilla.h>
|
||||
#include <QDir>
|
||||
#include <QDebug>
|
||||
#include <QLibrary>
|
||||
#include <QFunctionPointer>
|
||||
|
||||
#include "external-plugin/interface/external.h"
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <QDesktopServices>
|
||||
#include <QUrl>
|
||||
|
||||
NddPluginImplement::NddPluginImplement(QWidget *parent, QsciScintilla *pEdit) : QMainWindow (parent)
|
||||
, ui(new Ui::NddPluginImplement)
|
||||
, currentEdit(pEdit)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
|
||||
qDebug() << qApp->applicationPid();
|
||||
qDebug() << qApp->applicationName();
|
||||
qDebug() << qApp->applicationVersion();
|
||||
qDebug() << qApp->applicationDirPath();
|
||||
qDebug() << qApp->applicationFilePath();
|
||||
QDir dir("plugin/external-plugins");
|
||||
|
||||
QStringList filters;
|
||||
|
||||
#if defined (Q_OS_WIN)
|
||||
filters << "*.dll";
|
||||
#elif defined(Q_OS_UNIX)
|
||||
filters << "*.so";
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
dir.setNameFilters(filters);
|
||||
QFileInfoList list = dir.entryInfoList(QDir::Files);
|
||||
foreach(QFileInfo info, list) {
|
||||
qDebug() << info.fileName(); // false
|
||||
qDebug() << info.filePath(); // true
|
||||
qDebug() << info.absoluteFilePath(); // true
|
||||
|
||||
QLibrary lib(info.filePath());
|
||||
lib.load();
|
||||
|
||||
qDebug() << lib.isLoaded();
|
||||
|
||||
externalplugin *external_plugin;
|
||||
externalfunction func;
|
||||
// externalmetadata metadata;
|
||||
|
||||
// func = (externalfunction)lib.resolve("process");
|
||||
// metadata = (externalfunction)lib.resolve("metadata");
|
||||
external_plugin = (externalplugin*)lib.resolve("plugin");
|
||||
if (external_plugin != nullptr) {
|
||||
qDebug() << "Process!";
|
||||
plugins.append(external_plugin);
|
||||
}
|
||||
|
||||
externalplugin *external_plugins;
|
||||
external_plugins = (externalplugin*)lib.resolve("plugins");
|
||||
if (external_plugins != nullptr) {
|
||||
external_plugin = external_plugins;
|
||||
|
||||
while (external_plugin->type != ActionUnknow) {
|
||||
qDebug() << "Action:" << QString::fromLocal8Bit(external_plugin->meta);
|
||||
plugins.append(external_plugin);
|
||||
external_plugin++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NddPluginImplement::~NddPluginImplement()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void NddPluginImplement::setMenuActions(QMenu *menu)
|
||||
{
|
||||
// 此处开始配置 Menu 内容
|
||||
for (int i = 0; i < plugins.size(); i++)
|
||||
{
|
||||
int length = strlen(plugins[i]->meta);
|
||||
|
||||
QString name = QString::fromLocal8Bit(plugins[i]->meta, length);
|
||||
QAction *action = menu->addAction(name);
|
||||
|
||||
action->connect(action, &QAction::triggered, [=](){
|
||||
qDebug() << "func!";
|
||||
|
||||
// 作为二级菜单引擎,以当前编辑器为主进行扩展可用的设计
|
||||
currentEdit = getCurrentEditFunc();
|
||||
if (currentEdit == nullptr) {
|
||||
qDebug() << "Error: no current edit";
|
||||
return;
|
||||
}
|
||||
|
||||
// 准备当前编辑器的内容,转为可用的标准 C++ 类型
|
||||
QString s = currentEdit->text();
|
||||
std::string data = s.toStdString();
|
||||
|
||||
// 准备对不同的目标动作进行响应
|
||||
switch(plugins[i]->type) {
|
||||
|
||||
case ActionAppend:
|
||||
plugins[i]->func(data);
|
||||
currentEdit->append(QString::fromStdString(data));
|
||||
break;
|
||||
|
||||
case ActionReplace:
|
||||
plugins[i]->func(data);
|
||||
currentEdit->setText(QString::fromStdString(data));
|
||||
break;
|
||||
|
||||
case ActionOpenHomeDir:
|
||||
QDesktopServices::openUrl(QUrl(QStandardPaths::locate(QStandardPaths::HomeLocation, "", QStandardPaths::LocateDirectory)));
|
||||
break;
|
||||
|
||||
case ActionOpenLink:
|
||||
plugins[i]->func(data);
|
||||
QDesktopServices::openUrl(QUrl(QString::fromStdString(data)));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
#ifndef NDD_PLUGIN_IMPLEMENT_H
|
||||
#define NDD_PLUGIN_IMPLEMENT_H
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
#include "external-plugin/interface/external.h"
|
||||
|
||||
class QsciScintilla;
|
||||
namespace Ui {
|
||||
class NddPluginImplement;
|
||||
}
|
||||
class NddPluginImplement : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NddPluginImplement(QWidget *parent = nullptr, QsciScintilla *pEdit = nullptr);
|
||||
~NddPluginImplement();
|
||||
|
||||
void setMenuActions(QMenu *menu);
|
||||
void setCurrentEditFunc(std::function<QsciScintilla* ()> func) {
|
||||
getCurrentEditFunc = func;
|
||||
}
|
||||
|
||||
private:
|
||||
Ui::NddPluginImplement *ui;
|
||||
QsciScintilla *currentEdit;
|
||||
std::function<QsciScintilla* ()> getCurrentEditFunc;
|
||||
|
||||
QList<externalplugin*> plugins;
|
||||
};
|
||||
|
||||
#endif // NDD_PLUGIN_IMPLEMENT_H
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>NddPluginImplement</class>
|
||||
<widget class="QMainWindow" name="NddPluginImplement">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>554</width>
|
||||
<height>379</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget"/>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>554</width>
|
||||
<height>27</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -0,0 +1,11 @@
|
|||
#include <qobject.h>
|
||||
#include <qstring.h>
|
||||
#include <include/pluginGl.h>
|
||||
#include <functional>
|
||||
#include <qsciscintilla.h>
|
||||
#include "ndd_plugin_implement.h"
|
||||
|
||||
|
||||
NOTEPAD_PLUGIN_METADATA_IDENTIFY_V1(u8"外部插件扩展测试", "0.1", "zinface", u8"基于 QMainWindow Ui 的插件", "");
|
||||
|
||||
NOTEPAD_PLUGIN_METADATA_IMPLEMENT_V1(NddPluginImplement, false);
|
|
@ -0,0 +1,7 @@
|
|||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>template/plugintemplate.cpp</file>
|
||||
<file>template/plugintemplate.h</file>
|
||||
<file>template/plugintemplate.txt</file>
|
||||
</qresource>
|
||||
</RCC>
|
|
@ -0,0 +1,242 @@
|
|||
#include "hello.h"
|
||||
#include "pluginframeworkhelper.h"
|
||||
#include "view/createnewplugincodedialog.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QTextCodec>
|
||||
|
||||
#include <utils/pathutil.h>
|
||||
|
||||
Hello::Hello(QObject *parent)
|
||||
: QObject{parent}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Hello &Hello::instance()
|
||||
{
|
||||
static Hello hello;
|
||||
return hello;
|
||||
}
|
||||
|
||||
QString Hello::PluginName()
|
||||
{
|
||||
return "Hello";
|
||||
}
|
||||
|
||||
QString Hello::PluginVersion()
|
||||
{
|
||||
return "0.1";
|
||||
}
|
||||
|
||||
QString Hello::PluginAuthor()
|
||||
{
|
||||
return "zinface";
|
||||
}
|
||||
|
||||
QString Hello::PluginComment()
|
||||
{
|
||||
return "hello 插件";
|
||||
}
|
||||
|
||||
IPluginFramework::MenuType Hello::PluginMenuType()
|
||||
{
|
||||
return IPluginFramework::MenuType::SecondaryMenu;
|
||||
}
|
||||
|
||||
void Hello::registerNotepad(QWidget *notepad)
|
||||
{
|
||||
s_notepad = notepad;
|
||||
}
|
||||
|
||||
void Hello::registerStrFileName(QString str_file_name)
|
||||
{
|
||||
s_str_file_name = str_file_name;
|
||||
}
|
||||
|
||||
void Hello::PluginTrigger()
|
||||
{
|
||||
QMessageBox::information(nullptr, "Tip", "This is Hello Plugin");
|
||||
}
|
||||
|
||||
void Hello::registerPluginActions(QMenu *rootMenu)
|
||||
{
|
||||
rootMenu->addAction("First Plugin Action", this, [](){
|
||||
QMessageBox::information(nullptr, "Tip", "This is Hello Plugin(First Action)");
|
||||
});
|
||||
rootMenu->addAction("Second Plugin Action", this, [](){
|
||||
QMessageBox::information(nullptr, "Tip", "This is Hello Plugin(Second Action)");
|
||||
});
|
||||
rootMenu->addAction("Three Plugin Action", this, [this](){
|
||||
|
||||
|
||||
// QsciScintilla *edit = s_get_cur_edit_callback(s_notepad);
|
||||
|
||||
// QMessageBox::information(nullptr, "Tip", edit->text());
|
||||
|
||||
QVariant editName = PluginFrameworkHelper::DoNewEdit(s_notepad, s_plugin_callback);
|
||||
QMessageBox::information(nullptr, "New Edit", editName.toString());
|
||||
});
|
||||
rootMenu->addAction("Monitor textChanged", this, [=](){
|
||||
connect(s_get_cur_edit_callback(s_notepad), &QsciScintilla::textChanged, this, [](){
|
||||
QMessageBox::information(nullptr, "Tip", "textChanged!");
|
||||
});
|
||||
});
|
||||
|
||||
rootMenu->addAction("Create New Plugin Code Template", this, [this](){
|
||||
// 1. Dialog to PluginName and ClassName
|
||||
CreateNewPluginCodeDialog dialog;
|
||||
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
|
||||
/** H **/
|
||||
QFile file_h("://template/plugintemplate.h");
|
||||
file_h.open(QIODevice::ReadOnly);
|
||||
QString h = file_h.readAll();
|
||||
file_h.close();
|
||||
|
||||
// ifdef/class
|
||||
h.replace("PLUGINTEMPLATE", dialog.getClassName().toUpper());
|
||||
h.replace("PluginTemplate", dialog.getClassName());
|
||||
|
||||
/** CPP **/
|
||||
QFile file_cpp("://template/plugintemplate.cpp");
|
||||
file_cpp.open(QIODevice::ReadOnly);
|
||||
QString cpp = file_cpp.readAll();
|
||||
file_cpp.close();
|
||||
|
||||
// include/class
|
||||
cpp.replace("plugintemplate", dialog.getClassName().toLower());
|
||||
cpp.replace("PluginTemplate", dialog.getClassName());
|
||||
|
||||
// 1. 处理插件名称、版本、作者、简介说明
|
||||
#if _MSC_VER
|
||||
QTextCodec *codec = QTextCodec::codecForName("GBK");
|
||||
#else
|
||||
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
|
||||
#endif
|
||||
// QTextCodec::setCodecForLocale(codec);
|
||||
|
||||
cpp.replace("//Name", dialog.getName());
|
||||
cpp.replace("//Version", dialog.getVersion());
|
||||
cpp.replace("//Author", dialog.getAuthor());
|
||||
cpp.replace("//Comment", dialog.getComment());
|
||||
|
||||
// 2. 处理插件预期触发操作
|
||||
if (dialog.getMenuType() == true) {
|
||||
cpp.replace("//Trigger", "QMessageBox::information(nullptr, \"tip\", \"This is default tip message.\");");
|
||||
cpp.replace("//Actions", "//Actions: Will never enter here.");
|
||||
} else {
|
||||
cpp.replace("MenuType::None", "MenuType::SecondaryMenu");
|
||||
cpp.replace("//Trigger", "//Trigger: Will never enter here.");
|
||||
|
||||
cpp.replace("//Actions","rootMenu->addAction(\"Default\", this, [this](){\n"
|
||||
" QMessageBox::information(nullptr, \"tip\", \"This is default tip message.\");\n"
|
||||
" });");
|
||||
}
|
||||
// 3. 解锁 NDD_DECLARE_PLUGIN 宏注释
|
||||
cpp.replace("//NDD_DECLARE_PLUGIN", "NDD_DECLARE_PLUGIN");
|
||||
|
||||
|
||||
/** CMake **/
|
||||
QFile file_txt("://template/plugintemplate.txt");
|
||||
file_txt.open(QIODevice::ReadOnly);
|
||||
QString txt = file_txt.readAll();
|
||||
file_txt.close();
|
||||
|
||||
// 1. 处理对 CMakeLists.txt 的构建解释, 目标名称
|
||||
txt.replace("plugintemplate", dialog.getClassName().toLower());
|
||||
// 2. 这是在模板中的一个路径占位,但原始内容被构建解释改变了
|
||||
QString txtPlacePath = QString("#framework-plugins/%1").arg(dialog.getClassName().toLower());
|
||||
// 3. 这是在模板中的一个路径占位,使用引用的方式才会替换
|
||||
QString txtIncludePath = QString("path/to/plugin.cmake");
|
||||
|
||||
/** -------------------------------- */
|
||||
|
||||
// 1. 创建编辑器
|
||||
QVariant editName = PluginFrameworkHelper::DoNewEdit(s_notepad, s_plugin_callback);
|
||||
// 2. 获取刚才创建的编辑器
|
||||
QsciScintilla *curEdit = s_get_cur_edit_callback(s_notepad);
|
||||
|
||||
// 3. 将代码设置到内部,或打开对话框保存到目录
|
||||
if (dialog.getSaveType() == true) {
|
||||
curEdit->setText(h + "\n\n\n" + cpp + "\n\n\n" + txt);
|
||||
} else {
|
||||
// 获取保存目录路径
|
||||
QString existDir = QFileDialog::getExistingDirectory(nullptr, "Open Save Dir", PathUtil::execDir());
|
||||
if (existDir.isEmpty() == false) {
|
||||
QMessageBox::information(nullptr, "Note", QString("已保存到目录:\n%1").arg(existDir));
|
||||
QString header = QString("%1/%2.h").arg(existDir);
|
||||
QString source = QString("%1/%2.cpp").arg(existDir);
|
||||
QString plugincmake = QString("%1/plugin.cmake").arg(existDir);
|
||||
|
||||
QFile fh(header.arg(dialog.getClassName().toLower()));
|
||||
QFile fcpp(source.arg(dialog.getClassName().toLower()));
|
||||
QFile fcmake(plugincmake);
|
||||
|
||||
fh.open(QIODevice::WriteOnly);
|
||||
// fh.write(h.toLocal8Bit()); // 存在乱码情况,使用 QTextStream
|
||||
QTextStream fhout(&fh);
|
||||
fhout.setCodec("utf-8");
|
||||
fhout.setGenerateByteOrderMark(true); // with Bom
|
||||
fhout << h;
|
||||
fh.close();
|
||||
|
||||
fcpp.open(QIODevice::WriteOnly);
|
||||
// fcpp.write(cpp.toLocal8Bit()); // 存在乱码情况,使用 QTextStream
|
||||
QTextStream fcppout(&fcpp);
|
||||
fcppout.setCodec("utf-8");
|
||||
fcppout.setGenerateByteOrderMark(true); // with Bom
|
||||
fcppout << cpp;
|
||||
fcpp.close();
|
||||
|
||||
|
||||
// 可能逻辑: 如果存放在源代码目录树中,则处理掉路径前缀部分(替换占位)/或直接使用存储目录(替换占位)
|
||||
QString posiblePath = QString("plugin/framework-plugins");
|
||||
if (existDir.contains(posiblePath) == true) {
|
||||
int posibleIndex = existDir.indexOf("framework-plugins");
|
||||
if (posibleIndex > 0) {
|
||||
txt.replace(txtPlacePath, existDir.mid(posibleIndex));
|
||||
txt.replace(txtIncludePath, existDir.mid(posibleIndex) + "/plugin.cmake");
|
||||
}
|
||||
} else {
|
||||
txt.replace(txtPlacePath, existDir);
|
||||
txt.replace(txtIncludePath, existDir + "/plugin.cmake");
|
||||
}
|
||||
curEdit->setText(txt);
|
||||
|
||||
// 引用逻辑: 如果使用引用 plugin.cmake 的方式,那么将自动从 txt 模板中取8-18行的内容
|
||||
if (dialog.getQuoteCmake()) {
|
||||
fcmake.open(QIODevice::WriteOnly);
|
||||
// fcpp.write(cpp.toLocal8Bit()); // 存在乱码情况,使用 QTextStream
|
||||
QTextStream fcmakeout(&fcmake);
|
||||
fcmakeout.setCodec("utf-8");
|
||||
fcmakeout.setGenerateByteOrderMark(true); // with Bom
|
||||
fcmakeout << txt.split("\n").mid(29,28).join("\n").replace(existDir, "${CMAKE_CURRENT_LIST_DIR}");
|
||||
fcmakeout << txt.split("\n").mid(8,10).join("\n").replace(existDir, "${CMAKE_CURRENT_LIST_DIR}");
|
||||
fcmake.close();
|
||||
}
|
||||
} else {
|
||||
QMessageBox::information(nullptr, "Note", "未选中存储目录,本次操作被忽略");
|
||||
QString content = QString("未选中存储目录,本次操作被忽略,但保留了本次内容\n\n\n") + h + "\n\n\n" + cpp;
|
||||
curEdit->setText(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Hello::registerCurrentEditCallback(std::function<QsciScintilla *(QWidget *)> get_cur_edit_callback)
|
||||
{
|
||||
s_get_cur_edit_callback = get_cur_edit_callback;
|
||||
}
|
||||
|
||||
void Hello::registerPluginCallBack(std::function<bool (QWidget *, int, void *)> plugin_callback)
|
||||
{
|
||||
s_plugin_callback = plugin_callback;
|
||||
}
|
||||
|
||||
|
||||
NDD_DECLARE_PLUGIN(Hello::instance())
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef HELLO_H
|
||||
#define HELLO_H
|
||||
|
||||
#include <IPluginFramework.h>
|
||||
#include <QObject>
|
||||
|
||||
class Hello : public QObject, IPluginFramework
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Hello(QObject *parent = nullptr);
|
||||
static Hello &instance();
|
||||
|
||||
signals:
|
||||
|
||||
|
||||
// IPluginFramework interface
|
||||
public:
|
||||
QString PluginName() override;
|
||||
QString PluginVersion() override;
|
||||
QString PluginAuthor() override;
|
||||
QString PluginComment() override;
|
||||
MenuType PluginMenuType() override;
|
||||
void registerNotepad(QWidget *notepad) override;
|
||||
void registerStrFileName(QString str_file_name) override;
|
||||
void PluginTrigger() override;
|
||||
void registerPluginActions(QMenu *rootMenu) override;
|
||||
void registerCurrentEditCallback(std::function<QsciScintilla *(QWidget *)> get_cur_edit_callback) override;
|
||||
void registerPluginCallBack(std::function<bool (QWidget *, int, void *)> plugin_callback) override;
|
||||
|
||||
|
||||
private:
|
||||
QWidget *s_notepad;
|
||||
QString s_str_file_name;
|
||||
std::function<QsciScintilla*(QWidget*)> s_get_cur_edit_callback;
|
||||
std::function<bool(QWidget*, int, void*)> s_plugin_callback;
|
||||
};
|
||||
|
||||
#endif // HELLO_H
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
#include "plugintemplate.h"
|
||||
#include "pluginframeworkhelper.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
|
||||
PluginTemplate::PluginTemplate(QObject *parent)
|
||||
: QObject{parent}
|
||||
{}
|
||||
|
||||
PluginTemplate &PluginTemplate::instance()
|
||||
{
|
||||
static PluginTemplate _plugin;
|
||||
return _plugin;
|
||||
}
|
||||
|
||||
QString PluginTemplate::PluginName()
|
||||
{
|
||||
return "//Name";
|
||||
}
|
||||
|
||||
QString PluginTemplate::PluginVersion()
|
||||
{
|
||||
return "//Version";
|
||||
}
|
||||
|
||||
QString PluginTemplate::PluginAuthor()
|
||||
{
|
||||
return "//Author";
|
||||
}
|
||||
|
||||
QString PluginTemplate::PluginComment()
|
||||
{
|
||||
return "//Comment";
|
||||
}
|
||||
|
||||
IPluginFramework::MenuType PluginTemplate::PluginMenuType()
|
||||
{
|
||||
return MenuType::None;
|
||||
}
|
||||
|
||||
void PluginTemplate::PluginTrigger()
|
||||
{
|
||||
//Trigger
|
||||
}
|
||||
|
||||
void PluginTemplate::registerPluginActions(QMenu *rootMenu)
|
||||
{
|
||||
//Actions
|
||||
}
|
||||
|
||||
// Plug-in implementation wrapper
|
||||
//NDD_DECLARE_PLUGIN(PluginTemplate::instance())
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef PLUGINTEMPLATE_H
|
||||
#define PLUGINTEMPLATE_H
|
||||
|
||||
#include <IPluginFramework.h>
|
||||
#include <QObject>
|
||||
|
||||
class PluginTemplate : public QObject, public IPluginFramework
|
||||
{
|
||||
Q_OBJECT
|
||||
explicit PluginTemplate(QObject *parent = nullptr);
|
||||
public:
|
||||
static PluginTemplate &instance();
|
||||
|
||||
|
||||
// IPluginFramework interface
|
||||
public:
|
||||
QString PluginName();
|
||||
QString PluginVersion();
|
||||
QString PluginAuthor();
|
||||
QString PluginComment();
|
||||
MenuType PluginMenuType();
|
||||
void PluginTrigger();
|
||||
void registerPluginActions(QMenu *rootMenu);
|
||||
|
||||
/** 当前版本 IPluginManager 中已经为此实现 - 如需加载时执行自定义代码请重写 registerNotepad 实现.
|
||||
并在其实现内首行调用 IPluginFramework::registerNotepad(notepad);
|
||||
*/
|
||||
// void registerNotepad(QWidget *notepad);
|
||||
// void registerStrFileName(QString str_file_name);
|
||||
// void registerCurrentEditCallback(std::function<QsciScintilla *(QWidget *)> get_cur_edit_callback);
|
||||
// void registerPluginCallBack(std::function<bool (QWidget *, int, void *)> plugin_callback);
|
||||
};
|
||||
|
||||
#endif // PLUGINTEMPLATE_H
|
|
@ -0,0 +1,51 @@
|
|||
现在:将以下内容复制到源代码目录的 plugin/CMakeLists.txt 中。
|
||||
并在项目配置中启用该构建:framework-plugintemplate_ENABLE
|
||||
或在命令行中启用该构建:-Dframework-plugintemplate_ENABLE:BOOL=ON
|
||||
|
||||
注意:在以下 if 中,是对此目标的扩展构建,使用 if 是在确保项目中启用该构建时才进行构建。
|
||||
可以注意的是,在没有明确构建何种插件时,任何由 add_framework_plugin 添加的插件构建均不会起效。
|
||||
这样可以最大程度在默认情况下确保主程序的可构建性。
|
||||
|
||||
# 一个简单的 plugintemplate 插件
|
||||
add_framework_plugin(framework-plugintemplate
|
||||
# 这里可以进行编写包含源代码的目录、文件路径、其它需要构建的资源路径
|
||||
#framework-plugins/plugintemplate
|
||||
)
|
||||
if(framework-plugintemplate_ENABLE)
|
||||
# 这里可以进行扩展构建,
|
||||
# find_package(Qt5Svg)
|
||||
# target_link_libraries(framework-plugintemplate Qt5::Svg)
|
||||
endif(framework-plugintemplate_ENABLE)
|
||||
|
||||
|
||||
引用:在对话框中如果使用引用的方式,引用型声明式构建,直接在存储位置开始部署你的插件构建
|
||||
那么它应该生成 plugin.cmake 直接提供外部引用并自动将以上内容自动填充
|
||||
另外,它的构建路径以 plugin.cmake 文件所在目录为起始点
|
||||
|
||||
# 一个使用引用构建的 plugintemplate 插件
|
||||
include(path/to/plugin.cmake)
|
||||
|
||||
|
||||
|
||||
# 提供给其它插件项目引用的共享资源(如果其它插件想通过框架构建引用的话)
|
||||
if(FRAMEWORK_WANT_INCLUDE)
|
||||
message("-- [PLUGIN EXPORT]: FRAMEWORK_WANT_INCLUDE?")
|
||||
set(FRAMEWORK_INCLUDE_EXPORTS # 共享的引用目录 - 用于 include
|
||||
# ${CMAKE_CURRENT_LIST_DIR}/src
|
||||
)
|
||||
set(FRAMEWORK_SOURCES_EXPORTS # 共享的资源文件 - 用于 构建
|
||||
# ${CMAKE_CURRENT_LIST_DIR}/src/*.cpp
|
||||
)
|
||||
set(FRAMEWORK_WITHGIT_EXPORTS # 共享的引用构建资源
|
||||
# 1. 引用了公共存储库
|
||||
# https://gitee.com/ndd-community/framework-plugin-component-library
|
||||
)
|
||||
|
||||
# 特殊构建 - 为引用资源的目标配置预期所需依赖的构建
|
||||
# FRAMEWORK_PLUGIN 引用本资源的框架目标变量
|
||||
# find_package(Qt5Svg)
|
||||
# target_link_libraries(${FRAMEWORK_PLUGIN} Qt5::Svg)
|
||||
|
||||
return()
|
||||
endif(FRAMEWORK_WANT_INCLUDE)
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
#include "createnewplugincodedialog.h"
|
||||
#include "ui_createnewplugincodedialog.h"
|
||||
|
||||
CreateNewPluginCodeDialog::CreateNewPluginCodeDialog(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui::CreateNewPluginCodeDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
CreateNewPluginCodeDialog::~CreateNewPluginCodeDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
QString CreateNewPluginCodeDialog::getName()
|
||||
{
|
||||
return ui->edit_name->text();
|
||||
}
|
||||
|
||||
QString CreateNewPluginCodeDialog::getClassName()
|
||||
{
|
||||
if (ui->edit_class_name->text().isEmpty()) {
|
||||
return ui->edit_name->text();
|
||||
}
|
||||
return ui->edit_class_name->text();;
|
||||
}
|
||||
|
||||
QString CreateNewPluginCodeDialog::getVersion()
|
||||
{
|
||||
return ui->edit_version->text();
|
||||
}
|
||||
|
||||
QString CreateNewPluginCodeDialog::getAuthor()
|
||||
{
|
||||
return ui->edit_author->text();
|
||||
}
|
||||
|
||||
QString CreateNewPluginCodeDialog::getComment()
|
||||
{
|
||||
QString d = ui->edit_descript->toPlainText();
|
||||
return d.replace("\\", "\\\\").replace("\"", "\\\"");
|
||||
}
|
||||
|
||||
bool CreateNewPluginCodeDialog::getMenuType()
|
||||
{
|
||||
return ui->r_none->isChecked();
|
||||
}
|
||||
|
||||
bool CreateNewPluginCodeDialog::getSaveType()
|
||||
{
|
||||
return ui->r_save_edit->isChecked();
|
||||
}
|
||||
|
||||
bool CreateNewPluginCodeDialog::getQuoteCmake()
|
||||
{
|
||||
return ui->r_cmake_quote->isChecked();
|
||||
}
|
||||
|
||||
void CreateNewPluginCodeDialog::on_r_save_edit_clicked()
|
||||
{
|
||||
return ui->groupBox_4->setEnabled(false);
|
||||
}
|
||||
|
||||
void CreateNewPluginCodeDialog::on_r_save_dir_clicked()
|
||||
{
|
||||
return ui->groupBox_4->setEnabled(true);
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef CREATENEWPLUGINCODEDIALOG_H
|
||||
#define CREATENEWPLUGINCODEDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui {
|
||||
class CreateNewPluginCodeDialog;
|
||||
}
|
||||
|
||||
class CreateNewPluginCodeDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CreateNewPluginCodeDialog(QWidget *parent = nullptr);
|
||||
~CreateNewPluginCodeDialog();
|
||||
|
||||
QString getName();
|
||||
QString getClassName();
|
||||
QString getVersion();
|
||||
QString getAuthor();
|
||||
QString getComment();
|
||||
|
||||
bool getMenuType();
|
||||
|
||||
bool getSaveType();
|
||||
bool getQuoteCmake();
|
||||
|
||||
private slots:
|
||||
void on_r_save_edit_clicked();
|
||||
void on_r_save_dir_clicked();
|
||||
|
||||
private:
|
||||
Ui::CreateNewPluginCodeDialog *ui;
|
||||
};
|
||||
|
||||
#endif // CREATENEWPLUGINCODEDIALOG_H
|
|
@ -0,0 +1,279 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CreateNewPluginCodeDialog</class>
|
||||
<widget class="QDialog" name="CreateNewPluginCodeDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>326</width>
|
||||
<height>330</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>插件生成对话框</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="edit_version">
|
||||
<property name="text">
|
||||
<string>v0.1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="r_none">
|
||||
<property name="text">
|
||||
<string>None</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="r_second">
|
||||
<property name="text">
|
||||
<string>Second</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>插件版本:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="edit_name">
|
||||
<property name="text">
|
||||
<string>NextNddPlugin</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>插件说明:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QPlainTextEdit" name="edit_descript">
|
||||
<property name="plainText">
|
||||
<string>You can change the plug-in name to the appropriate name, and adjust any part that can be adjusted to make the code generation more accurate.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="edit_author">
|
||||
<property name="text">
|
||||
<string>unknow</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>插件名称:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>插件作者:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>菜单类型:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="edit_class_name">
|
||||
<property name="placeholderText">
|
||||
<string>类名:留空同名</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>生成类型:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="r_save_edit">
|
||||
<property name="text">
|
||||
<string>显示到编辑器</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="r_save_dir">
|
||||
<property name="text">
|
||||
<string>存储到目录</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_4">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>引用方式:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QRadioButton" name="r_cmake_quote">
|
||||
<property name="text">
|
||||
<string>引用(plugin.cmake)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QRadioButton" name="r_cmake_default">
|
||||
<property name="text">
|
||||
<string>默认</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>edit_name</tabstop>
|
||||
<tabstop>edit_class_name</tabstop>
|
||||
<tabstop>edit_version</tabstop>
|
||||
<tabstop>edit_author</tabstop>
|
||||
<tabstop>r_none</tabstop>
|
||||
<tabstop>r_second</tabstop>
|
||||
<tabstop>edit_descript</tabstop>
|
||||
<tabstop>r_save_edit</tabstop>
|
||||
<tabstop>r_save_dir</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>CreateNewPluginCodeDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>CreateNewPluginCodeDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
|
@ -0,0 +1,106 @@
|
|||
#include "helloworld.h"
|
||||
#include "pluginframeworkhelper.h"
|
||||
#include "qdebug.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QMessageBox>
|
||||
|
||||
HelloWorld::HelloWorld(QObject *parent)
|
||||
: QObject{parent}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
HelloWorld::~HelloWorld()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
HelloWorld &HelloWorld::instance()
|
||||
{
|
||||
static HelloWorld helloworld;
|
||||
return helloworld;
|
||||
}
|
||||
|
||||
QString HelloWorld::PluginName()
|
||||
{
|
||||
return "Framework HelloWorld";
|
||||
}
|
||||
|
||||
QString HelloWorld::PluginVersion()
|
||||
{
|
||||
return "v0.1";
|
||||
}
|
||||
|
||||
QString HelloWorld::PluginAuthor()
|
||||
{
|
||||
return "zinface";
|
||||
}
|
||||
|
||||
QString HelloWorld::PluginComment()
|
||||
{
|
||||
return "这一个基于IPluginFramework 实现的插件";
|
||||
}
|
||||
|
||||
IPluginFramework::MenuType HelloWorld::PluginMenuType()
|
||||
{
|
||||
// return None;
|
||||
return SecondaryMenu;
|
||||
}
|
||||
|
||||
void HelloWorld::PluginTrigger()
|
||||
{
|
||||
qDebug() << "Triggered";
|
||||
QMessageBox::information(nullptr, "提示信息", "您已 trigger 触发此插件");
|
||||
|
||||
int length = s_get_cur_edit_callback(s_notepad)->text().count();
|
||||
|
||||
QMessageBox::information(nullptr, "提示信息", QString("您当前编辑器有 %1 个字符").arg(length));
|
||||
}
|
||||
|
||||
|
||||
void HelloWorld::registerNotepad(QWidget *notepad)
|
||||
{
|
||||
s_notepad = notepad;
|
||||
}
|
||||
|
||||
void HelloWorld::registerStrFileName(QString str_file_name)
|
||||
{
|
||||
s_str_file_name = str_file_name;
|
||||
}
|
||||
|
||||
void HelloWorld::registerCurrentEditCallback(std::function<QsciScintilla *(QWidget *)> get_cur_edit_callback)
|
||||
{
|
||||
s_get_cur_edit_callback = get_cur_edit_callback;
|
||||
}
|
||||
|
||||
void HelloWorld::registerPluginCallBack(std::function<bool (QWidget *, int, void *)> plugin_callback)
|
||||
{
|
||||
s_plugin_callback = plugin_callback;
|
||||
}
|
||||
|
||||
void HelloWorld::registerPluginActions(QMenu *rootMenu)
|
||||
{
|
||||
// QMessageBox::information(nullptr, "提示信息", "您的 MenuType 类型为 1 需要注册 QAction 集合");
|
||||
rootMenu->addAction("第一个 QAction", [](){
|
||||
QMessageBox::information(nullptr, "提示信息", "您已 trigger 触发插件的第一个 QAction");
|
||||
});
|
||||
|
||||
rootMenu->addAction("创建一个编辑器", [this](){
|
||||
QVariant editName = PluginFrameworkHelper::DoNewEdit(s_notepad, s_plugin_callback);
|
||||
QMessageBox::information(nullptr, "提示信息", QString("您已 创建了一个编辑器: %1").arg(editName.toString()));
|
||||
});
|
||||
|
||||
rootMenu->addAction("改变当前编辑器语法为 Json", [this](){
|
||||
bool ret = PluginFrameworkHelper::DoChangeSyntax(s_notepad, s_plugin_callback, IPluginFramework::Json);
|
||||
if (ret) {
|
||||
QMessageBox::information(nullptr, "提示信息", QString("您已 改变了当前编辑器语法为 Json"));
|
||||
} else {
|
||||
QMessageBox::information(nullptr, "提示信息", QString("您未能成功改变当前编辑器语法为 Json"));
|
||||
}
|
||||
});
|
||||
|
||||
rootMenu->addAction("显示当前插件文件路径", [this](){
|
||||
QMessageBox::information(nullptr, "提示信息", QString("您当前插件的路径为:\n%1").arg(s_str_file_name));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef HELLOWORLD_H
|
||||
#define HELLOWORLD_H
|
||||
|
||||
#include <QObject>
|
||||
#include "framework/IPluginFramework.h"
|
||||
|
||||
class HelloWorld : public QObject, IPluginFramework
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID IPluginFramework_IID)
|
||||
Q_INTERFACES(IPluginFramework)
|
||||
public:
|
||||
explicit HelloWorld(QObject *parent = nullptr);
|
||||
~HelloWorld();
|
||||
|
||||
static HelloWorld &instance();
|
||||
|
||||
// IPluginFramework interface
|
||||
public:
|
||||
QString PluginName();
|
||||
QString PluginVersion();
|
||||
QString PluginAuthor();
|
||||
QString PluginComment();
|
||||
MenuType PluginMenuType();
|
||||
|
||||
void PluginTrigger();
|
||||
void registerNotepad(QWidget *notepad);
|
||||
void registerStrFileName(QString str_file_name) override;
|
||||
void registerCurrentEditCallback(std::function<QsciScintilla *(QWidget *)> get_cur_edit_callback);
|
||||
void registerPluginCallBack(std::function<bool (QWidget *, int, void *)> plugin_callback) override;
|
||||
void registerPluginActions(QMenu *rootMenu);
|
||||
|
||||
private:
|
||||
QWidget *s_notepad;
|
||||
QString s_str_file_name;
|
||||
std::function<QsciScintilla *(QWidget *)> s_get_cur_edit_callback;
|
||||
std::function<bool(QWidget*, int, void*)> s_plugin_callback;
|
||||
};
|
||||
|
||||
#endif // HELLOWORLD_H
|
|
@ -0,0 +1,72 @@
|
|||
|
||||
|
||||
// #include "../include/pluginGl.h"
|
||||
|
||||
#include "qdebug.h"
|
||||
#include <pluginGl.h>
|
||||
#include <functional>
|
||||
#include <qsciscintilla.h>
|
||||
|
||||
//#ifdef NOTEPAD_PLUGIN_MANAGER
|
||||
|
||||
|
||||
#define NDD_EXPORTDLL
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#if defined(NDD_EXPORTDLL)
|
||||
#define NDD_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define NDD_EXPORT __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define NDD_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
#include "helloworld.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define plugin HelloWorld::instance()
|
||||
|
||||
NDD_EXPORT bool NDD_PROC_IDENTIFY(NDD_PROC_DATA* pProcData) {
|
||||
|
||||
qDebug() << (pProcData == NULL);
|
||||
if(pProcData == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
pProcData->m_strPlugName = plugin.PluginName();
|
||||
pProcData->m_strComment = plugin.PluginComment();
|
||||
pProcData->m_version = plugin.PluginVersion();
|
||||
pProcData->m_auther = plugin.PluginAuthor();
|
||||
pProcData->m_menuType = plugin.PluginMenuType();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
NDD_EXPORT int NDD_PROC_MAIN(QWidget* pNotepad, const QString& strFileName, std::function<QsciScintilla* (QWidget*)>getCurEdit, std::function<bool(QWidget*, int, void*)> pluginCallBack, NDD_PROC_DATA* procData){
|
||||
|
||||
plugin.registerNotepad(pNotepad);
|
||||
plugin.registerStrFileName(strFileName);
|
||||
plugin.registerCurrentEditCallback(getCurEdit);
|
||||
plugin.registerPluginCallBack(pluginCallBack);
|
||||
|
||||
if (plugin.PluginMenuType() == IPluginFramework::None) {
|
||||
procData->m_pAction->connect(procData->m_pAction, &QAction::triggered, [](){
|
||||
plugin.PluginTrigger();
|
||||
});
|
||||
} else {
|
||||
plugin.registerPluginActions(procData->m_rootMenu);
|
||||
}
|
||||
|
||||
qDebug() << strFileName;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
//#endif //NOTEPAD_PLUGIN_MANAGER
|
|
@ -0,0 +1,235 @@
|
|||
#ifndef __IPLUGINFRAMEWORK__H__
|
||||
#define __IPLUGINFRAMEWORK__H__
|
||||
|
||||
#include <QAction>
|
||||
#include <cstddef>
|
||||
#include <qmenu.h>
|
||||
#include <qobject.h>
|
||||
#include <qobjectdefs.h>
|
||||
#include <qsciscintilla.h>
|
||||
|
||||
#define IPluginFramework_IID "com.gitee.ndd.pluginframework"
|
||||
|
||||
typedef std::function<QsciScintilla*(QWidget*)> PluginWantEditor;
|
||||
typedef std::function<bool(QWidget*, int, void*)> PluginWantDo;
|
||||
|
||||
/**
|
||||
在使用 IPluginFramework 时,请使用 : public IPluginFramework 并实现必要的代码
|
||||
另外:使用生成器生成适用于基于 IPluginFramework 的代码
|
||||
|
||||
基于 IPluginFramework 开发的ndd插件,主要为了更标准化生产一个插件
|
||||
*/
|
||||
class IPluginFramework
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief 提供给编辑器的菜单类型
|
||||
* @note None 为单功能菜单,SecondaryMenu 为二级菜单
|
||||
* @since v1.0
|
||||
*/
|
||||
enum MenuType {
|
||||
None = 0,
|
||||
SecondaryMenu = 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 让编辑器做指定的事
|
||||
* @note 目前编辑器支持由插件发出两种指令
|
||||
* @since v2.0
|
||||
*/
|
||||
enum Do {
|
||||
NewEdit = 1,
|
||||
ChangeSyntax = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 当指定编辑器做改变语法的时候提供以下实现
|
||||
* @since v2.0
|
||||
*/
|
||||
enum SyntaxType {
|
||||
Js = 0,
|
||||
Json,
|
||||
Html,
|
||||
};
|
||||
|
||||
/********************************************* 插件基本信息/
|
||||
/**
|
||||
* @brief 插件名称
|
||||
* @return
|
||||
*/
|
||||
virtual QString PluginName() = 0;
|
||||
/**
|
||||
* @brief 插件版本
|
||||
* @return
|
||||
*/
|
||||
virtual QString PluginVersion() = 0;
|
||||
/**
|
||||
* @brief 插件作者
|
||||
* @return
|
||||
*/
|
||||
virtual QString PluginAuthor() = 0;
|
||||
/**
|
||||
* @brief 插件说明
|
||||
* @return
|
||||
*/
|
||||
virtual QString PluginComment() = 0;
|
||||
/**
|
||||
* @brief 插件菜单类型
|
||||
* @note 如仅提供插件,而不实现任何其它菜单功能则建议为 None,否则
|
||||
* @return
|
||||
*/
|
||||
virtual MenuType PluginMenuType() = 0;
|
||||
|
||||
|
||||
/********************************************* 插件的主程序 Notepad 注册*/
|
||||
|
||||
/**
|
||||
* @brief registerNotepad
|
||||
* @param notepad
|
||||
*/
|
||||
virtual void registerNotepad(QWidget *notepad)
|
||||
{
|
||||
s_notepad = notepad;
|
||||
}
|
||||
|
||||
/********************************************* 插件路径注册*/
|
||||
/**
|
||||
* @brief registerStrFileName
|
||||
* @param str_file_name 主程序加载插件时提供 .dll/so 路径(也就是最终本插件被加载时的 .dll/so 文件位置)
|
||||
*/
|
||||
virtual void registerStrFileName(QString str_file_name)
|
||||
{
|
||||
s_str_file_name = str_file_name;
|
||||
}
|
||||
|
||||
/********************************************* 插件的一级(MenuType=None)或二级(MenuType=SecondaryMenu)菜单触发与注册接口/
|
||||
|
||||
/**
|
||||
* @brief 由插件实现的一级菜单触发动作(默认提供的动作)
|
||||
* @note 由于框架无法在 C 风格函数入口处完成事件注册,则由插件提供者自行在 registerTirgger 中连接信号到此处
|
||||
*/
|
||||
virtual void PluginTrigger() = 0;
|
||||
|
||||
/**
|
||||
* @brief 由插件实现的二级菜单触发动作集合(默认提供的动作)
|
||||
* @param menu
|
||||
* @note 由框架在 C 风格函数入口处代为转交,则由插件提供者自行实现来完成提供内部的 QAction 集合
|
||||
* @since v1.0
|
||||
*/
|
||||
virtual void registerPluginActions(QMenu *rootMenu) = 0;
|
||||
|
||||
/********************************************* 当前编辑器函数回调注册*/
|
||||
|
||||
/**
|
||||
* @brief 由框架提供的获取当前编辑器的回调函数注册
|
||||
* @param curEdit
|
||||
* @note 由于框架无法在 C 风格函数入口处完成回调函数注册,则由插件提供者自行在 registerCurrentEditCallback 中连接信号到此处
|
||||
* @since v2.0
|
||||
*/
|
||||
virtual void registerCurrentEditCallback(std::function<QsciScintilla*(QWidget*)> get_cur_edit_callback)
|
||||
{
|
||||
s_get_cur_edit_callback = get_cur_edit_callback;
|
||||
}
|
||||
|
||||
/********************************************* 编辑器功能函数回调注册*/
|
||||
/**
|
||||
* @brief 由框架提供的对 Notepad 进行的执行动作
|
||||
* @param plugin_callBack
|
||||
* @note 让编辑器做指定的事,目前编辑器支持由插件发出两种指令(Do::NewEdit, Do::)
|
||||
* @since v2.0
|
||||
*/
|
||||
virtual void registerPluginCallBack(std::function<bool(QWidget*, int, void*)> plugin_callback)
|
||||
{
|
||||
s_plugin_callback = plugin_callback;
|
||||
}
|
||||
|
||||
|
||||
/********************************************* 为插件拷贝以下信息 */
|
||||
/** s_notepad 为 CCNotepad,当前主程序 */
|
||||
/** s_strFileName 为当前路径 */
|
||||
/** s_get_cur_edit_callback 为回调函数,用于获取当前编辑器 */
|
||||
/** s_plugin_callBack 为回调函数,用于使当前主程序做某些事 */
|
||||
protected:
|
||||
QWidget *s_notepad;
|
||||
QString s_str_file_name;
|
||||
std::function<QsciScintilla*(QWidget*)> s_get_cur_edit_callback;
|
||||
std::function<bool(QWidget*, int, void*)> s_plugin_callback;
|
||||
};
|
||||
|
||||
Q_DECLARE_INTERFACE(IPluginFramework, IPluginFramework_IID)
|
||||
|
||||
#endif //!__IPLUGINFRAMEWORK__H__
|
||||
|
||||
#ifdef NOTEPAD_PLUGIN_MANAGER
|
||||
|
||||
#include "qdebug.h"
|
||||
#include <pluginGl.h>
|
||||
#include <functional>
|
||||
#include <qsciscintilla.h>
|
||||
|
||||
#define NDD_EXPORTDLL
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#if defined(NDD_EXPORTDLL)
|
||||
#define NDD_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define NDD_EXPORT __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define NDD_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
NDD_EXPORT bool NDD_PROC_IDENTIFY(NDD_PROC_DATA* pProcData);
|
||||
NDD_EXPORT int NDD_PROC_MAIN(QWidget* pNotepad, const QString& strFileName, std::function<QsciScintilla* (QWidget*)>getCurEdit, std::function<bool(QWidget*, int, void*)> pluginCallBack, NDD_PROC_DATA* procData);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define NDD_DECLARE_PLUGIN(plugin) \
|
||||
NDD_EXPORT bool NDD_PROC_IDENTIFY(NDD_PROC_DATA* pProcData) { \
|
||||
qDebug() << (pProcData == NULL); \
|
||||
if(pProcData == NULL) \
|
||||
{ \
|
||||
return false; \
|
||||
} \
|
||||
pProcData->m_strPlugName = plugin.PluginName(); \
|
||||
pProcData->m_strComment = plugin.PluginComment(); \
|
||||
pProcData->m_version = plugin.PluginVersion(); \
|
||||
pProcData->m_auther = plugin.PluginAuthor(); \
|
||||
pProcData->m_menuType = plugin.PluginMenuType(); \
|
||||
\
|
||||
return true; \
|
||||
} \
|
||||
NDD_EXPORT int NDD_PROC_MAIN(QWidget* pNotepad, \
|
||||
const QString& strFileName, \
|
||||
std::function<QsciScintilla* (QWidget*)>getCurEdit, \
|
||||
std::function<bool(QWidget*, int, void*)> pluginCallBack, \
|
||||
NDD_PROC_DATA* procData){ \
|
||||
\
|
||||
plugin.registerNotepad(pNotepad); \
|
||||
plugin.registerStrFileName(strFileName); \
|
||||
plugin.registerCurrentEditCallback(getCurEdit); \
|
||||
plugin.registerPluginCallBack(pluginCallBack); \
|
||||
\
|
||||
if (plugin.PluginMenuType() == IPluginFramework::None) { \
|
||||
procData->m_pAction->connect(procData->m_pAction, &QAction::triggered, [](){ \
|
||||
plugin.PluginTrigger(); \
|
||||
}); \
|
||||
} else { \
|
||||
plugin.registerPluginActions(procData->m_rootMenu); \
|
||||
} \
|
||||
\
|
||||
qDebug() << strFileName; \
|
||||
return 0; \
|
||||
} \
|
||||
|
||||
#else
|
||||
|
||||
#error Missing definition NOTEPAD_PLUGIN_MANAGER
|
||||
|
||||
#endif //NOTEPAD_PLUGIN_MANAGER
|
|
@ -0,0 +1,76 @@
|
|||
# Qt 插件开发
|
||||
|
||||
> https://gitee.com/zinface/qt.plugin-dev
|
||||
|
||||
- 定义一个插件的接口
|
||||
|
||||
```cpp
|
||||
// 定义一个插件所使用的 IID 名称,被实现的插件也可以使用此宏
|
||||
#define IPlugin_IID "com.test.plugin"
|
||||
|
||||
class IPlugin
|
||||
{
|
||||
public:
|
||||
// 定义一个插件时所用的名称
|
||||
virtual QString PluginName() = 0; // 插件声明函数必须 = 0
|
||||
};
|
||||
|
||||
Q_DECLARE_INTERFACE(IPlugin, IPlugin_IID)
|
||||
```
|
||||
|
||||
- 实现一个插件
|
||||
|
||||
```cpp
|
||||
#include "iplugin.h"
|
||||
|
||||
class PluginDemo : public QObject, IPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID IPlugin_IID)
|
||||
Q_INTERFACES(IPlugin)
|
||||
public:
|
||||
QString PluginName() override;
|
||||
};
|
||||
```
|
||||
|
||||
```cpp
|
||||
#include "plugindemo.h"
|
||||
|
||||
QString PluginDemo::PluginName()
|
||||
{
|
||||
return QString("插件demo");
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
# 不过设定好像也没啥问题
|
||||
add_definitions("${QT_DEFINITIONS} -DQT_PLUGIN")
|
||||
# 该库编译将产生一个 `libplugindemo.so`,在 cmake 中应当被指定为 SHARED 共享库目标
|
||||
```
|
||||
|
||||
- 使用插件
|
||||
|
||||
```cpp
|
||||
IPlugin *plugin;
|
||||
|
||||
// 使用 QPluginLoader,参数 argv[1] 表示为插件路径
|
||||
QPluginLoader pluginLoader(argv[1]);
|
||||
// 使用插件加载器加载扩展并尝试创建实例
|
||||
QObject *instance = pluginLoader.instance();
|
||||
if (instance) {
|
||||
// 如果实例创建成功,尝试转换对象
|
||||
plugin = qobject_cast<IPlugin *>(instance);
|
||||
if (plugin) {
|
||||
QTextStream(stdout) << QString("> 加载插件并调用函数:\n")
|
||||
<< "> plugin->PluginName(): "
|
||||
<< plugin->PluginName() << "\n";
|
||||
}
|
||||
pluginLoader.unload();
|
||||
}
|
||||
```
|
||||
|
||||
```shell
|
||||
# 将会在 build 目录中,执行以下命令加载插件(因Qt插件机制必须为'绝对路径')
|
||||
$ ./plugin-loader `realpath libplugindemo.so`
|
||||
plugin->PluginName: 插件demo
|
||||
```
|
|
@ -0,0 +1,24 @@
|
|||
# framework-extension.cmake
|
||||
# framework_plugin_include <target> <plugin.cmake>
|
||||
# 声明本地资源引用构建
|
||||
# framework_plugin_include_with_git <target> <git> [arg...]
|
||||
# 声明资源引用构建 with_git
|
||||
|
||||
# framework_plugin_include <target> <plugin.cmake>
|
||||
# 该宏定义了从指定的 plugin.cmake 中获取插件共享构建资源
|
||||
# 标记 FRAMEWORK_WANT_INCLUDE 为 ON,让 include(plugin.cmake) 时产生策略性引用构建
|
||||
# 清空 FRAMEWORK_INCLUDE_EXPORTS 以便干净的引用资源(头文件目录)得以填充到此处
|
||||
# 清空 FRAMEWORK_SOURCES_EXPORTS 以便干净的引用资源(源文件声明)得以填充到此处
|
||||
# 框架构建将头文件目录 使用原生方案 追加到目标属性
|
||||
# 框架构建将源文件使用 spark_file_glob 解析一切可能的存在,直接提供到目标的构建
|
||||
macro(framework_plugin_include _target _plug_cmake)
|
||||
spark_framework_include(${_target} ${_plug_cmake})
|
||||
endmacro(framework_plugin_include _target _plug_cmake)
|
||||
|
||||
# framework_plugin_include_with_git <target> <git_repo_url> [git_args...]
|
||||
# 该宏定义了从指定的 git 仓库中获取插件源代码,并检查是否有 plugin.cmake,再转到引用资源构建
|
||||
function(framework_plugin_include_with_git _target GIT_REPO_URL)
|
||||
spark_framework_include_with_git(${_target} ${GIT_REPO_URL} ${ARGN})
|
||||
endfunction(framework_plugin_include_with_git _target GIT_REPO_URL)
|
||||
|
||||
# add_framework_plugin_with_git(https://gitee.com/ndd-community/notepad--plugin.plantuml-preview --branch=cmake-plugins-dev)
|
|
@ -0,0 +1,113 @@
|
|||
# framework.cmake
|
||||
# add_framework_plugin <target> [dir...|file...]
|
||||
# 提供本地构建
|
||||
# add_framework_plugin_with_git <git> [arg...]
|
||||
# 提供 with_git 在线引用构建
|
||||
|
||||
# add_framework_plugin [<dir>...] [<file>...]
|
||||
# 构建一个基于 framework 的插件
|
||||
# 基于提供的包含源代码文件的的路径,或指定的要构建的源代码
|
||||
macro(add_framework_plugin _target)
|
||||
|
||||
# 拟定:如果是 FRAMEWORK_WANT_INCLUDE 则不构建
|
||||
if(FRAMEWORK_WANT_INCLUDE)
|
||||
return()
|
||||
endif(FRAMEWORK_WANT_INCLUDE)
|
||||
|
||||
set(${_target}_ALIAS ${_target})
|
||||
if(WITH_GIT)
|
||||
set(${_target}_ALIAS online-${_target})
|
||||
unset(WITH_GIT)
|
||||
endif(WITH_GIT)
|
||||
|
||||
option(${${_target}_ALIAS}_ENABLE "是否确认构建 ${_target} 插件" OFF)
|
||||
|
||||
if(${${${_target}_ALIAS}_ENABLE})
|
||||
set(${_target}_ENABLE ON)
|
||||
set(${_target}_ARGN ${ARGN})
|
||||
# set(${_target}_DIR_OR_SOURCES)
|
||||
foreach(arg IN LISTS ${_target}_ARGN)
|
||||
list(APPEND ${_target}_DIR_OR_SOURCES ${arg})
|
||||
endforeach(arg IN LISTS ${_target}_ARGN)
|
||||
|
||||
# 相对于使用宏 add_framework_plugin 的位置约定
|
||||
set(FRAMEWORK_DIR ${CMAKE_CURRENT_LIST_DIR}/framework)
|
||||
if(NOT EXISTS FRAMEWORK_DIR)
|
||||
# 相对于真实 CMakeLists.txt 节点的位置
|
||||
set(FRAMEWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR}/framework)
|
||||
endif(NOT EXISTS FRAMEWORK_DIR)
|
||||
|
||||
spark_add_library_path(${_target} SHARED
|
||||
${FRAMEWORK_DIR}
|
||||
${${_target}_DIR_OR_SOURCES}
|
||||
)
|
||||
target_include_directories(${_target} PRIVATE
|
||||
${PROJECT_SOURCE_DIR}/src
|
||||
${PROJECT_SOURCE_DIR}/src/cceditor
|
||||
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/src
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/src/Qsci
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/scintilla/src
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/scintilla/include
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/scintilla/lexlib
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/scintilla/boostregex
|
||||
)
|
||||
# target_link_libraries(${_target} QSci)
|
||||
target_link_QSci(${_target})
|
||||
if(USE_QT6)
|
||||
# target_link_qt6_Core5Compat(${_target}) # 兼容性: Qt6 可使用 Core5Compat 少量更改 Qt5 部分
|
||||
# target_link_qt6_PrintSupport(${_target})
|
||||
# target_link_qt6_XmlPatterns(${_target}) # Bug 初期配置时无此依赖要求
|
||||
else()
|
||||
# target_link_qt5_PrintSupport(${_target})
|
||||
# target_link_qt5_XmlPatterns(${_target})
|
||||
endif(USE_QT6)
|
||||
|
||||
set_target_properties(${_target}
|
||||
PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:${PROJECT_NAME}>/plugin
|
||||
LIBRARY_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:${PROJECT_NAME}>/plugin
|
||||
ARCHIVE_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:${PROJECT_NAME}>/plugin)
|
||||
|
||||
|
||||
if(WIN32 AND NOTEPAD_BUILD_BY_SHARED)
|
||||
# 在 Windows 中构建时,需要关注此库的构建形式,QScintilla 应该以何种方式编译
|
||||
target_compile_definitions(${_target}
|
||||
PRIVATE
|
||||
NOTEPAD_PLUGIN_MANAGER
|
||||
QSCINTILLA_DLL # 目前在 Windows 中使用 QSci 库时应该采用 Q_DECL_IMPORT
|
||||
# 控制 QSCINTILLA_EXPORT 符号应为 Q_DECL_IMPORT
|
||||
)
|
||||
else()
|
||||
# 在 Windows 中构建时,需要关注此库的构建形式,QScintilla 应该以何种方式编译
|
||||
target_compile_definitions(${_target}
|
||||
PRIVATE
|
||||
NOTEPAD_PLUGIN_MANAGER
|
||||
# QSCINTILLA_DLL # 目前在 Windows 中使用 QSci 库时应该采用 Q_DECL_IMPORT
|
||||
# 控制 QSCINTILLA_EXPORT 符号应为 Q_DECL_IMPORT
|
||||
)
|
||||
endif(WIN32 AND NOTEPAD_BUILD_BY_SHARED)
|
||||
|
||||
|
||||
spark_cmake_debug(
|
||||
">>>>>>>>>>>>>>>>>>>>>>>>>>> ${_target} CMake Debug <<<<<<<<<<<<<<<<<<<<<<<<<<<"
|
||||
"${_target} LINK_LIBRARIES: $<TARGET_PROPERTY:${_target},LINK_LIBRARIES>"
|
||||
"${_target} COMPILE_DEFINITIONS: $<TARGET_PROPERTY:${_target},COMPILE_DEFINITIONS>"
|
||||
"${_target} INTERFACE: $<TARGET_PROPERTY:${_target},INTERFACE>"
|
||||
"${_target} TARGET_FILE_BASE_NAME: $<TARGET_FILE_BASE_NAME:${_target}>"
|
||||
"${_target} TARGET_FILE_NAME: $<TARGET_FILE_NAME:${_target}>"
|
||||
">>>>>>>>>>>>>>>>>>>>>>>>>>> ${_target} CMake Debug <<<<<<<<<<<<<<<<<<<<<<<<<<<"
|
||||
)
|
||||
|
||||
endif(${${${_target}_ALIAS}_ENABLE})
|
||||
|
||||
endmacro(add_framework_plugin _target)
|
||||
|
||||
|
||||
# support git plugin
|
||||
# add_framework_plugin_with_git <git_repo_url> [git_args...]
|
||||
# 该宏定义了从指定的 git 仓库中获取插件源代码,并进行简单的构建
|
||||
macro(add_framework_plugin_with_git GIT_REPO_URL)
|
||||
set(WITH_GIT ON)
|
||||
spark_framework_include_with_git(_ ${GIT_REPO_URL} ${ARGN})
|
||||
endmacro(add_framework_plugin_with_git GIT_REPO_URL)
|
|
@ -0,0 +1,14 @@
|
|||
#include "pluginframeworkhelper.h"
|
||||
|
||||
QVariant PluginFrameworkHelper::DoNewEdit(QWidget *notepad, PluginWantDo plugin_callback)
|
||||
{
|
||||
QVariant var;
|
||||
plugin_callback(notepad, IPluginFramework::NewEdit, (void*)&var);
|
||||
return var;
|
||||
}
|
||||
|
||||
bool PluginFrameworkHelper::DoChangeSyntax(QWidget *notepad, PluginWantDo plugin_callback, IPluginFramework::SyntaxType syntax)
|
||||
{
|
||||
int v = syntax;
|
||||
return plugin_callback(notepad, IPluginFramework::ChangeSyntax, (void*)&v);
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef PLUGINFRAMEWORKHELPER_H
|
||||
#define PLUGINFRAMEWORKHELPER_H
|
||||
|
||||
#include "IPluginFramework.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
#include <qsciscintilla.h>
|
||||
|
||||
class PluginFrameworkHelper
|
||||
{
|
||||
public:
|
||||
static QVariant DoNewEdit(QWidget *notepad, PluginWantDo plugin_callback);
|
||||
static bool DoChangeSyntax(QWidget *notepad, PluginWantDo plugin_callback, IPluginFramework::SyntaxType syntax);
|
||||
};
|
||||
|
||||
#endif // PLUGINFRAMEWORKHELPER_H
|
|
@ -0,0 +1,131 @@
|
|||
# linux-terminal-plugin/CMakeLists.txt
|
||||
# 用于在源代码中构建一个插件的模板
|
||||
|
||||
# 如果不是在源代码中构建插件,请不要使用这个部分
|
||||
# 如果想在源代码中添加更多内置模板
|
||||
# 请替换 linux-terminal-plugin 为你的插件名称
|
||||
# linux-terminal-plugin -> your plugin name
|
||||
|
||||
set(LOCAL_PLUGIN_NAME "linux-terminal-plugin")
|
||||
|
||||
# linux-terminal-plugin 核心构建
|
||||
# 在模块化构建中,这个部分代表着构建 linux-terminal-plugin 插件
|
||||
# 1. 默认构建时产出的目标为 linux-terminal-plugin
|
||||
# 2. 在此处可对 linux-terminal-plugin 目标进行详细的构建计划
|
||||
|
||||
if(TRUE)
|
||||
# 准备构建 linux-terminal-plugin 主程序扩展
|
||||
spark_file_glob(LocalSources
|
||||
./*.h ./*.cpp # ./*.ui
|
||||
)
|
||||
spark_add_library(${LOCAL_PLUGIN_NAME} SHARED ${LocalSources})
|
||||
target_include_directories(${LOCAL_PLUGIN_NAME} PRIVATE
|
||||
${PROJECT_SOURCE_DIR}/src
|
||||
${PROJECT_SOURCE_DIR}/src/cceditor
|
||||
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/src
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/src/Qsci
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/scintilla/src
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/scintilla/include
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/scintilla/lexlib
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/scintilla/boostregex
|
||||
)
|
||||
# target_link_libraries(${LOCAL_PLUGIN_NAME} QSci)
|
||||
target_link_QSci(${LOCAL_PLUGIN_NAME})
|
||||
if(USE_QT6)
|
||||
# target_link_qt6_Core5Compat(${LOCAL_PLUGIN_NAME}) # 兼容性: Qt6 可使用 Core5Compat 少量更改 Qt5 部分
|
||||
# target_link_qt6_PrintSupport(${LOCAL_PLUGIN_NAME})
|
||||
# target_link_qt6_XmlPatterns(${LOCAL_PLUGIN_NAME}) # Bug 初期配置时无此依赖要求
|
||||
else()
|
||||
# target_link_qt5_PrintSupport(${LOCAL_PLUGIN_NAME})
|
||||
# target_link_qt5_XmlPatterns(${LOCAL_PLUGIN_NAME})
|
||||
endif(USE_QT6)
|
||||
|
||||
# 确保生成到 Notepad-- 的相对 plugin 目录下
|
||||
set_target_properties(${LOCAL_PLUGIN_NAME}
|
||||
PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:${PROJECT_NAME}>/plugin
|
||||
LIBRARY_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:${PROJECT_NAME}>/plugin
|
||||
ARCHIVE_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:${PROJECT_NAME}>/plugin)
|
||||
|
||||
# 控制是否安装到 bin/plugin 而各种配方之下,每个位置或许都不一样(特别是 Linux)
|
||||
# install(TARGETS ${LOCAL_PLUGIN_NAME} DESTINATION bin/plugin)
|
||||
endif(TRUE)
|
||||
|
||||
|
||||
# ----------------- linux-terminal-plugin 构建宏支持相关 ----------------- #
|
||||
|
||||
if(WIN32 AND NOTEPAD_BUILD_BY_SHARED)
|
||||
# 在 Windows 中构建时,需要关注此库的构建形式,QScintilla 应该以何种方式编译
|
||||
target_compile_definitions(${LOCAL_PLUGIN_NAME}
|
||||
PRIVATE
|
||||
NOTEPAD_PLUGIN_MANAGER
|
||||
QSCINTILLA_DLL # 目前在 Windows 中使用 QSci 库时应该采用 Q_DECL_IMPORT
|
||||
# 控制 QSCINTILLA_EXPORT 符号应为 Q_DECL_IMPORT
|
||||
)
|
||||
else()
|
||||
# 在 Windows 中构建时,需要关注此库的构建形式,QScintilla 应该以何种方式编译
|
||||
target_compile_definitions(${LOCAL_PLUGIN_NAME}
|
||||
PRIVATE
|
||||
NOTEPAD_PLUGIN_MANAGER
|
||||
# QSCINTILLA_DLL # 目前在 Windows 中使用 QSci 库时应该采用 Q_DECL_IMPORT
|
||||
# 控制 QSCINTILLA_EXPORT 符号应为 Q_DECL_IMPORT
|
||||
)
|
||||
endif(WIN32 AND NOTEPAD_BUILD_BY_SHARED)
|
||||
|
||||
if(UNIX)
|
||||
# 默认在 Unix/Linux 中仅需要定义一个内部插件宏管理器
|
||||
target_compile_definitions(${LOCAL_PLUGIN_NAME}
|
||||
PRIVATE
|
||||
NOTEPAD_PLUGIN_MANAGER
|
||||
)
|
||||
endif(UNIX)
|
||||
|
||||
# ----------------- linux-terminal-plugin 构建的外部项目依赖 ----------------- #
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/SparkExternalProject.cmake)
|
||||
|
||||
# 1. 提供 lxqt 系列项目使用的配置依赖
|
||||
spark_add_external_git_cmake_project(lxqt-build-tool
|
||||
https://www.gitlink.org.cn/zinface/lxqt-build-tools.git
|
||||
""
|
||||
""
|
||||
""
|
||||
GIT_SHALLOW TRUE)
|
||||
|
||||
# 2. QTerminal 项目,依赖于 lxqt-build-tool 配置来构建
|
||||
spark_add_external_git_cmake_project(qtermwidget_git
|
||||
https://www.gitlink.org.cn/zinface/qtermwidget.git
|
||||
# 配置编译时使用 lxqt-build-tool 提供的内容,安装时路径为"该项目内的安装目录"
|
||||
"-DCMAKE_PREFIX_PATH=${lxqt-build-tool-install};-DCMAKE_INSTALL_PREFIX=\${prj_install}"
|
||||
"--;-j12"
|
||||
""
|
||||
GIT_SHALLOW TRUE)
|
||||
|
||||
# -------------------------------------------------------------------------------
|
||||
# 3. 构建完成时,引入平台函数
|
||||
# 一个静态的 qtermwidget5 库应该为
|
||||
# libqtermwidget5.a 或 qtermwidget5.lib
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/platforms/utils.cmake)
|
||||
get_current_platform_lib_name(libqtermwidget5_lib FALSE qtermwidget5)
|
||||
|
||||
add_library(qtermwidget SHARED IMPORTED)
|
||||
set_target_properties(qtermwidget
|
||||
PROPERTIES
|
||||
IMPORTED_LOCATION ${qtermwidget_git-install}/lib/${libqtermwidget5_lib}
|
||||
INTERFACE_LINK_DIRECTORIES ${qtermwidget_git-install}/lib)
|
||||
target_include_directories(${LOCAL_PLUGIN_NAME}
|
||||
PUBLIC
|
||||
${qtermwidget_git-install}/include)
|
||||
|
||||
# ----------------- linux-terminal-plugin 构建的外部项目依赖 ----------------- #
|
||||
# 1.明确声明 qtermwidget_git 依赖于 lxqt-build-tool
|
||||
add_dependencies(qtermwidget_git lxqt-build-tool)
|
||||
|
||||
# 2.明确声明 qtermwidget 依赖于 qtermwidget_git
|
||||
add_dependencies(qtermwidget qtermwidget_git)
|
||||
|
||||
# 3.明确声明 qtermwidget 依赖于 qtermwidget_git
|
||||
add_dependencies(${LOCAL_PLUGIN_NAME} qtermwidget qtermwidget_git lxqt-build-tool)
|
||||
|
||||
# 4. 链接 qtermwidget 目标
|
||||
target_link_libraries(${LOCAL_PLUGIN_NAME} qtermwidget)
|
|
@ -0,0 +1,81 @@
|
|||
#include "ndd_plugin_implement.h"
|
||||
|
||||
#include <qsciscintilla.h>
|
||||
#include <QDebug>
|
||||
#include <QMainWindow>
|
||||
#include <QTabBar>
|
||||
|
||||
NddPluginImplement::NddPluginImplement(QWidget *parent, QsciScintilla *pEdit) : QWidget(parent)
|
||||
, currentWidget(parent)
|
||||
, currentEdit(pEdit)
|
||||
, m_dockWidget(nullptr)
|
||||
, m_dockTitleBarWidget(nullptr)
|
||||
, m_dockEmptyTitleBarWidget(new QWidget())
|
||||
, m_tabWidget(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
NddPluginImplement::~NddPluginImplement()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void NddPluginImplement::setMenuActions(QMenu *menu)
|
||||
{
|
||||
auto actionNewTerminal = menu->addAction("New Terminal");
|
||||
connect(actionNewTerminal, &QAction::triggered, this, [&](){
|
||||
|
||||
auto mainWindow = dynamic_cast<QMainWindow*>(currentWidget);
|
||||
|
||||
if(!mainWindow) {
|
||||
qDebug() << "None";
|
||||
return;
|
||||
}
|
||||
qDebug() << "Yep";
|
||||
|
||||
if (!m_dockWidget) {
|
||||
m_dockWidget = new QDockWidget(mainWindow);
|
||||
m_dockTitleBarWidget = m_dockWidget->titleBarWidget();
|
||||
m_dockWidget->setTitleBarWidget(m_dockEmptyTitleBarWidget);
|
||||
m_dockWidget->setMinimumSize(100, 200);
|
||||
connect(m_dockWidget, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(onDockLocationChanged(Qt::DockWidgetArea)));
|
||||
mainWindow->addDockWidget(Qt::BottomDockWidgetArea, m_dockWidget);
|
||||
}
|
||||
|
||||
if (!m_dockWidget->isVisible())
|
||||
m_dockWidget->show();
|
||||
|
||||
if (!m_tabWidget) {
|
||||
m_tabWidget = new QTabWidget(m_dockWidget);
|
||||
m_tabWidget->setTabsClosable(true);
|
||||
m_tabWidget->setMovable(true);
|
||||
m_tabWidget->tabBar()->setStyleSheet("QTabBar::tab{padding-left:10px}");
|
||||
connect(m_tabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(onTabCloseRequested(int)));
|
||||
m_dockWidget->setWidget(m_tabWidget);
|
||||
}
|
||||
|
||||
int tabIndex = m_tabWidget->addTab(new QTermWidget(), "New Terminal");
|
||||
m_tabWidget->setCurrentIndex(tabIndex);
|
||||
});
|
||||
}
|
||||
|
||||
void NddPluginImplement::onDockLocationChanged(Qt::DockWidgetArea area)
|
||||
{
|
||||
if (area == Qt::NoDockWidgetArea) {
|
||||
m_dockWidget->setTitleBarWidget(m_dockTitleBarWidget);
|
||||
}
|
||||
else {
|
||||
m_dockWidget->setTitleBarWidget(m_dockEmptyTitleBarWidget);
|
||||
}
|
||||
}
|
||||
|
||||
void NddPluginImplement::onTabCloseRequested(int index)
|
||||
{
|
||||
auto widget = m_tabWidget->widget(index);
|
||||
if (widget)
|
||||
delete widget;
|
||||
|
||||
if (m_tabWidget->count() == 0)
|
||||
m_dockWidget->hide();
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
#ifndef NDD_PLUGIN_IMPLEMENT_H
|
||||
#define NDD_PLUGIN_IMPLEMENT_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QMenu>
|
||||
#include <QDockWidget>
|
||||
#include <QTabWidget>
|
||||
#include <qtermwidget5/qtermwidget.h>
|
||||
|
||||
class QsciScintilla;
|
||||
class NddPluginImplement : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NddPluginImplement(QWidget *parent = nullptr, QsciScintilla *pEdit = nullptr);
|
||||
~NddPluginImplement();
|
||||
|
||||
void setMenuActions(QMenu *menu);
|
||||
void setCurrentEditFunc(std::function<QsciScintilla* ()> func) {
|
||||
getCurrentEditFunc = func;
|
||||
}
|
||||
|
||||
private:
|
||||
// 目前看来需要准备一个完整内部状态
|
||||
QWidget *currentWidget;
|
||||
QsciScintilla *currentEdit;
|
||||
std::function<QsciScintilla* ()> getCurrentEditFunc;
|
||||
|
||||
private slots:
|
||||
void onDockLocationChanged(Qt::DockWidgetArea area);
|
||||
void onTabCloseRequested(int index);
|
||||
|
||||
private:
|
||||
QDockWidget* m_dockWidget;
|
||||
|
||||
QWidget* m_dockTitleBarWidget;
|
||||
QWidget* m_dockEmptyTitleBarWidget;
|
||||
QTabWidget* m_tabWidget;
|
||||
};
|
||||
|
||||
#endif // NDD_PLUGIN_IMPLEMENT_H
|
|
@ -0,0 +1,11 @@
|
|||
#include <qobject.h>
|
||||
#include <qstring.h>
|
||||
#include <include/pluginGl.h>
|
||||
#include <functional>
|
||||
#include <qsciscintilla.h>
|
||||
#include "ndd_plugin_implement.h"
|
||||
|
||||
NOTEPAD_PLUGIN_METADATA_IDENTIFY_V1("Linux Terminal", "0.1", "author", u8"基于 LXQT QTerminal 的插件", "");
|
||||
|
||||
|
||||
NOTEPAD_PLUGIN_METADATA_IMPLEMENT_V1(NddPluginImplement, false);
|
|
@ -0,0 +1,136 @@
|
|||
# opencc-demo-plugin/CMakeLists.txt
|
||||
# 用于在源代码中构建一个插件的模板
|
||||
|
||||
# 如果不是在源代码中构建插件,请不要使用这个部分
|
||||
# 如果想在源代码中添加更多内置模板
|
||||
# 请替换 opencc-demo-plugin 为你的插件名称
|
||||
# opencc-demo-plugin -> your plugin name
|
||||
|
||||
set(LOCAL_PLUGIN_NAME "opencc-demo-plugin")
|
||||
|
||||
# opencc-demo-plugin 核心构建
|
||||
# 在模块化构建中,这个部分代表着构建 opencc-demo-plugin 插件
|
||||
# 1. 默认构建时产出的目标为 opencc-demo-plugin
|
||||
# 2. 在此处可对 opencc-demo-plugin 目标进行详细的构建计划
|
||||
|
||||
if(TRUE)
|
||||
# 准备构建 opencc-demo-plugin 主程序扩展
|
||||
spark_file_glob(LocalSources
|
||||
./*.h ./*.cpp ./*.ui
|
||||
)
|
||||
spark_add_library(${LOCAL_PLUGIN_NAME} SHARED ${LocalSources})
|
||||
target_include_directories(${LOCAL_PLUGIN_NAME} PRIVATE
|
||||
${PROJECT_SOURCE_DIR}/src
|
||||
${PROJECT_SOURCE_DIR}/src/cceditor
|
||||
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/src
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/src/Qsci
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/scintilla/src
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/scintilla/include
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/scintilla/lexlib
|
||||
${PROJECT_SOURCE_DIR}/src/qscint/scintilla/boostregex
|
||||
)
|
||||
# target_link_libraries(${LOCAL_PLUGIN_NAME} QSci)
|
||||
target_link_QSci(${LOCAL_PLUGIN_NAME})
|
||||
if(USE_QT6)
|
||||
# target_link_qt6_Core5Compat(${LOCAL_PLUGIN_NAME}) # 兼容性: Qt6 可使用 Core5Compat 少量更改 Qt5 部分
|
||||
# target_link_qt6_PrintSupport(${LOCAL_PLUGIN_NAME})
|
||||
# target_link_qt6_XmlPatterns(${LOCAL_PLUGIN_NAME}) # Bug 初期配置时无此依赖要求
|
||||
else()
|
||||
# target_link_qt5_PrintSupport(${LOCAL_PLUGIN_NAME})
|
||||
# target_link_qt5_XmlPatterns(${LOCAL_PLUGIN_NAME})
|
||||
endif(USE_QT6)
|
||||
|
||||
# 确保生成到 Notepad-- 的相对 plugin 目录下
|
||||
set_target_properties(${LOCAL_PLUGIN_NAME}
|
||||
PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:${PROJECT_NAME}>/plugin
|
||||
LIBRARY_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:${PROJECT_NAME}>/plugin
|
||||
ARCHIVE_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:${PROJECT_NAME}>/plugin)
|
||||
|
||||
# 控制是否安装到 bin/plugin 而各种配方之下,每个位置或许都不一样(特别是 Linux)
|
||||
# install(TARGETS ${LOCAL_PLUGIN_NAME} DESTINATION bin/plugin)
|
||||
endif(TRUE)
|
||||
|
||||
|
||||
# ----------------- opencc-demo-plugin 构建宏支持相关 ----------------- #
|
||||
|
||||
if(WIN32 AND NOTEPAD_BUILD_BY_SHARED)
|
||||
# 在 Windows 中构建时,需要关注此库的构建形式,QScintilla 应该以何种方式编译
|
||||
target_compile_definitions(${LOCAL_PLUGIN_NAME}
|
||||
PRIVATE
|
||||
NOTEPAD_PLUGIN_MANAGER
|
||||
QSCINTILLA_DLL # 目前在 Windows 中使用 QSci 库时应该采用 Q_DECL_IMPORT
|
||||
# 控制 QSCINTILLA_EXPORT 符号应为 Q_DECL_IMPORT
|
||||
)
|
||||
else()
|
||||
# 在 Windows 中构建时,需要关注此库的构建形式,QScintilla 应该以何种方式编译
|
||||
target_compile_definitions(${LOCAL_PLUGIN_NAME}
|
||||
PRIVATE
|
||||
NOTEPAD_PLUGIN_MANAGER
|
||||
# QSCINTILLA_DLL # 目前在 Windows 中使用 QSci 库时应该采用 Q_DECL_IMPORT
|
||||
# 控制 QSCINTILLA_EXPORT 符号应为 Q_DECL_IMPORT
|
||||
)
|
||||
endif(WIN32 AND NOTEPAD_BUILD_BY_SHARED)
|
||||
|
||||
if(UNIX)
|
||||
# 默认在 Unix/Linux 中仅需要定义一个内部插件宏管理器
|
||||
target_compile_definitions(${LOCAL_PLUGIN_NAME}
|
||||
PRIVATE
|
||||
NOTEPAD_PLUGIN_MANAGER
|
||||
)
|
||||
endif(UNIX)
|
||||
|
||||
|
||||
# ----------------- opencc-demo 构建的外部项目依赖 ----------------- #
|
||||
|
||||
set(libopencc "opencc_git")
|
||||
set(libopencc_name "OpenCC")
|
||||
set(libopencc_version "master")
|
||||
set(libopencc_url "https://gitee.com/mirrors/opencc")
|
||||
set(libopencc_prefix ${CMAKE_CURRENT_BINARY_DIR}/${libopencc_name}-${libopencc_version})
|
||||
set(libopencc_src ${libopencc_prefix}/src/${libopencc})
|
||||
set(libopencc_build ${libopencc_prefix}/src/${libopencc}-build)
|
||||
set(libopencc_install ${libopencc_prefix}/src/${libopencc}-install)
|
||||
set(libopencc_flags "-DBUILD_SHARED_LIBS=OFF;-DCMAKE_INSTALL_PREFIX=../${libopencc}-install")
|
||||
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/platforms/utils.cmake)
|
||||
get_current_platform_lib_name(libopencc_lib FALSE opencc)
|
||||
get_current_platform_lib_name(libmarisa_lib FALSE marisa)
|
||||
|
||||
include(ExternalProject)
|
||||
ExternalProject_Add(${libopencc}
|
||||
PREFIX ${libopencc_prefix}
|
||||
GIT_REPOSITORY ${libopencc_url}
|
||||
GIT_TAG ${libopencc_version}
|
||||
# GIT_SHALLOW TRUE
|
||||
CONFIGURE_COMMAND ${CMAKE_COMMAND} -S ${libopencc_src} -B ${libopencc_build} ${libopencc_flags}
|
||||
# CMAKE_GENERATOR
|
||||
BUILD_COMMAND ${CMAKE_COMMAND} --build ${libopencc_build} --config $<CONFIG>
|
||||
# INSTALL_COMMAND ${CMAKE_COMMAND} --install ${libopencc_build} --prefix ${libopencc_install}
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} --install ${libopencc_build} --config $<CONFIG>
|
||||
# TEST_COMMAND
|
||||
GIT_REMOTE_UPDATE_STRATEGY CHECKOUT
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
|
||||
add_library(opencc STATIC IMPORTED)
|
||||
set_target_properties(opencc
|
||||
PROPERTIES
|
||||
IMPORTED_LOCATION ${libopencc_install}/lib/${libopencc_lib}
|
||||
INTERFACE_LINK_LIBRARIES ${libopencc_install}/lib/${libmarisa_lib})
|
||||
target_include_directories(${LOCAL_PLUGIN_NAME}
|
||||
PUBLIC
|
||||
${libopencc_install}/include)
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
# 确保 opencc_git 在此插件之前构建完成
|
||||
add_dependencies(${LOCAL_PLUGIN_NAME} opencc_git)
|
||||
target_link_libraries(${LOCAL_PLUGIN_NAME} opencc)
|
||||
|
||||
if(WIN32)
|
||||
target_compile_definitions(${LOCAL_PLUGIN_NAME}
|
||||
PRIVATE
|
||||
OPENCC_EXPORT=)
|
||||
endif(WIN32)
|
|
@ -0,0 +1,42 @@
|
|||
# ExternalOpenCCGit.cmake
|
||||
# 这是一个单独的提供的外部依赖模板
|
||||
|
||||
# ----------------- opencc-demo 构建的外部项目依赖 ----------------- #
|
||||
|
||||
set(libopencc "opencc_git")
|
||||
set(libopencc_name "OpenCC")
|
||||
set(libopencc_version "master")
|
||||
set(libopencc_url "https://gitee.com/mirrors/opencc")
|
||||
set(libopencc_prefix ${CMAKE_CURRENT_BINARY_DIR}/${libopencc_name}-${libopencc_version})
|
||||
set(libopencc_src ${libopencc_prefix}/src/${libopencc})
|
||||
set(libopencc_build ${libopencc_prefix}/src/${libopencc}-build)
|
||||
set(libopencc_install ${libopencc_prefix}/src/${libopencc}-install)
|
||||
set(libopencc_flags "-DBUILD_SHARED_LIBS=OFF;-DCMAKE_INSTALL_PREFIX=../${libopencc}-install")
|
||||
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/platforms/utils.cmake)
|
||||
get_current_platform_lib_name(libopencc_lib FALSE opencc)
|
||||
get_current_platform_lib_name(libmarisa_lib FALSE marisa)
|
||||
|
||||
include(ExternalProject)
|
||||
ExternalProject_Add(${libopencc}
|
||||
PREFIX ${libopencc_prefix}
|
||||
GIT_REPOSITORY ${libopencc_url}
|
||||
GIT_TAG ${libopencc_version}
|
||||
# GIT_SHALLOW TRUE
|
||||
CONFIGURE_COMMAND ${CMAKE_COMMAND} -S ${libopencc_src} -B ${libopencc_build} ${libopencc_flags}
|
||||
# CMAKE_GENERATOR
|
||||
# BUILD_COMMAND ${CMAKE_COMMAND} --build ${libopencc_build} --config $<CONFIG>
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} --install ${libopencc_build} --prefix ${libopencc_install}
|
||||
# TEST_COMMAND
|
||||
GIT_REMOTE_UPDATE_STRATEGY CHECKOUT
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
|
||||
add_library(opencc STATIC IMPORTED)
|
||||
set_target_properties(opencc
|
||||
PROPERTIES
|
||||
IMPORTED_LOCATION ${libopencc_install}/lib/${libopencc_lib}
|
||||
INTERFACE_LINK_LIBRARIES ${libopencc_install}/lib/${libmarisa_lib}
|
||||
INCLUDE_DIRECTORIES ${libopencc_install}/include)
|
||||
|
||||
# ----------------------------------------------------------------
|
|
@ -0,0 +1,124 @@
|
|||
#include "ndd_plugin_implement.h"
|
||||
#include "ui_ndd_plugin_implement.h"
|
||||
|
||||
#include <qsciscintilla.h>
|
||||
#include <QDebug>
|
||||
#include <QDockWidget>
|
||||
#include <QSplitter>
|
||||
#include <QThreadPool>
|
||||
#include <qpushbutton.h>
|
||||
#include <qsciscintilla.h>
|
||||
|
||||
NddPluginImplement::NddPluginImplement(QWidget *parent, QsciScintilla *pEdit) : QMainWindow(parent)
|
||||
, currentWidget(parent)
|
||||
, currentEdit(pEdit)
|
||||
, ui(new Ui::NddPluginImplement)
|
||||
, m_dockWidget(new QDockWidget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
QSplitter *splitter = new QSplitter(Qt::Horizontal, this);
|
||||
splitter->addWidget(ui->textEdit);
|
||||
splitter->addWidget(ui->textBrowser);
|
||||
splitter->setChildrenCollapsible(false);
|
||||
splitter->setHandleWidth(5);
|
||||
|
||||
ui->horizontalLayout_2->addWidget(splitter);
|
||||
|
||||
#if WIN32
|
||||
connect(ui->pushButton, &QPushButton::clicked, this, [&](){
|
||||
task = new OpenCCTask(this, ui->textEdit->toPlainText());
|
||||
task->setCn2Tn(ui->radioCnTn->isChecked());
|
||||
connect(task, &OpenCCTask::complete, this, [=](const QString text) {
|
||||
this->ui->textBrowser->setText(text);
|
||||
});
|
||||
task->run();
|
||||
task->deleteLater();
|
||||
});
|
||||
#else
|
||||
ui->pushButton->hide();
|
||||
#endif
|
||||
}
|
||||
|
||||
NddPluginImplement::~NddPluginImplement()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void NddPluginImplement::setMenuActions(QMenu *menu)
|
||||
{
|
||||
connect(menu->addAction("Show Ui"), &QAction::triggered, this, [=](){
|
||||
// on_pushButton_clicked();
|
||||
this->setParent(nullptr);
|
||||
this->show();
|
||||
this->resize(QSize(570,400));
|
||||
this->ui->tabWidget->setCurrentWidget(ui->tab);
|
||||
});
|
||||
|
||||
connect(menu->addAction("Show Sider"), &QAction::triggered, this, [=](){
|
||||
auto mainWindow = dynamic_cast<QMainWindow*>(currentWidget);
|
||||
if(!mainWindow) {
|
||||
qDebug() << "None";
|
||||
return;
|
||||
}
|
||||
|
||||
m_dockWidget->setMinimumSize(100, 200);
|
||||
mainWindow->addDockWidget(Qt::RightDockWidgetArea, m_dockWidget);
|
||||
|
||||
if (!m_dockWidget->isVisible())
|
||||
m_dockWidget->show();
|
||||
|
||||
m_dockWidget->setWidget(this);
|
||||
|
||||
ui->tabWidget->setCurrentWidget(ui->tab_2);
|
||||
});
|
||||
}
|
||||
|
||||
void NddPluginImplement::convertCn2TnInEditBrowser(bool cn2tn)
|
||||
{
|
||||
task = new OpenCCTask(this, ui->textEdit->toPlainText());
|
||||
task->setCn2Tn(cn2tn);
|
||||
connect(task, &OpenCCTask::complete, this, [=](const QString text) {
|
||||
this->ui->textBrowser->setText(text);
|
||||
});
|
||||
#if WIN32
|
||||
task->run();
|
||||
task->deleteLater();
|
||||
#else
|
||||
QThreadPool::globalInstance()->start(task);
|
||||
#endif
|
||||
}
|
||||
|
||||
void NddPluginImplement::convertCn2TnInCurrentEdit(bool cn2tn)
|
||||
{
|
||||
task = new OpenCCTask(this, getCurrentEditFunc()->text());
|
||||
task->setCn2Tn(cn2tn);
|
||||
connect(task, &OpenCCTask::complete, this, [=](const QString text) {
|
||||
getCurrentEditFunc()->setText(text);
|
||||
});
|
||||
#if WIN32
|
||||
task->run();
|
||||
task->deleteLater();
|
||||
#else
|
||||
QThreadPool::globalInstance()->start(task);
|
||||
#endif
|
||||
}
|
||||
|
||||
void NddPluginImplement::on_textEdit_textChanged()
|
||||
{
|
||||
#if WIN32
|
||||
// 不采用实时任务
|
||||
#else
|
||||
convertCn2TnInEditBrowser(this->ui->radioCnTn->isChecked());
|
||||
#endif
|
||||
}
|
||||
|
||||
void NddPluginImplement::on_pushButtonCn2Tn_clicked(bool checked)
|
||||
{
|
||||
convertCn2TnInCurrentEdit(true);
|
||||
}
|
||||
|
||||
void NddPluginImplement::on_pushButtonTn2Cn_clicked(bool checked)
|
||||
{
|
||||
convertCn2TnInCurrentEdit(false);
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
#ifndef NDD_PLUGIN_IMPLEMENT_H
|
||||
#define NDD_PLUGIN_IMPLEMENT_H
|
||||
|
||||
#include "opencctask.h"
|
||||
#include <QMainWindow>
|
||||
|
||||
class QsciScintilla;
|
||||
namespace Ui {
|
||||
class NddPluginImplement;
|
||||
}
|
||||
class NddPluginImplement : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NddPluginImplement(QWidget *parent = nullptr, QsciScintilla *pEdit = nullptr);
|
||||
~NddPluginImplement();
|
||||
|
||||
void setMenuActions(QMenu *menu);
|
||||
void setCurrentEditFunc(std::function<QsciScintilla* ()> func) {
|
||||
getCurrentEditFunc = func;
|
||||
}
|
||||
|
||||
void convertCn2TnInEditBrowser(bool cn2tn);
|
||||
void convertCn2TnInCurrentEdit(bool cn2tn);
|
||||
|
||||
private slots:
|
||||
void on_textEdit_textChanged();
|
||||
|
||||
void on_pushButtonCn2Tn_clicked(bool checked);
|
||||
|
||||
void on_pushButtonTn2Cn_clicked(bool checked);
|
||||
|
||||
private:
|
||||
// 目前看来需要准备一个完整内部状态
|
||||
QWidget *currentWidget;
|
||||
QsciScintilla *currentEdit;
|
||||
std::function<QsciScintilla* ()> getCurrentEditFunc;
|
||||
|
||||
private:
|
||||
Ui::NddPluginImplement *ui;
|
||||
QDockWidget *m_dockWidget;
|
||||
|
||||
OpenCCTask *task;
|
||||
};
|
||||
|
||||
#endif // NDD_PLUGIN_IMPLEMENT_H
|
|
@ -0,0 +1,192 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>NddPluginImplement</class>
|
||||
<widget class="QMainWindow" name="NddPluginImplement">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>570</width>
|
||||
<height>400</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>简繁转换面板 - Demo</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>Tab 1</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QTextEdit" name="textEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="textBrowser"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioCnTn">
|
||||
<property name="text">
|
||||
<string>简>繁</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioTnCn">
|
||||
<property name="text">
|
||||
<string>繁>简</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="text">
|
||||
<string>Convert</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
<attribute name="title">
|
||||
<string>Tab 2</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>繁 > 简:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonTn2Cn">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>繁简转换</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>简 > 繁:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonCn2Tn">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>简繁转换</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>570</width>
|
||||
<height>27</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -0,0 +1,43 @@
|
|||
#include "opencctask.h"
|
||||
|
||||
#include "opencc/opencc.h"
|
||||
|
||||
OpenCCTask::OpenCCTask(QObject *parent, QString text) : QObject(parent)
|
||||
, m_text(text)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void OpenCCTask::run()
|
||||
{
|
||||
opencc::SimpleConverter converter(cn2Tn()?"s2t.json":"t2s.json");
|
||||
std::string s = converter.Convert(m_text.toStdString().data());
|
||||
QString result = QString::fromStdString(s);
|
||||
emit complete(result);
|
||||
}
|
||||
|
||||
QString OpenCCTask::text() const
|
||||
{
|
||||
return m_text;
|
||||
}
|
||||
|
||||
void OpenCCTask::setText(const QString &newText)
|
||||
{
|
||||
if (m_text == newText)
|
||||
return;
|
||||
m_text = newText;
|
||||
emit textChanged();
|
||||
}
|
||||
|
||||
bool OpenCCTask::cn2Tn() const
|
||||
{
|
||||
return m_cn2Tn;
|
||||
}
|
||||
|
||||
void OpenCCTask::setCn2Tn(bool newCn2Tn)
|
||||
{
|
||||
if (m_cn2Tn == newCn2Tn)
|
||||
return;
|
||||
m_cn2Tn = newCn2Tn;
|
||||
emit cn2TnChanged();
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
#ifndef OPENCCTASK_H
|
||||
#define OPENCCTASK_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QRunnable>
|
||||
|
||||
class OpenCCTask : public QObject , public QRunnable
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
|
||||
Q_PROPERTY(bool cn2Tn READ cn2Tn WRITE setCn2Tn NOTIFY cn2TnChanged)
|
||||
|
||||
public:
|
||||
explicit OpenCCTask(QObject *parent = nullptr, QString text = "");
|
||||
|
||||
// enum TaskType {
|
||||
// NormalType = 0
|
||||
// };
|
||||
// Q_FLAGS(TaskType);
|
||||
// Q_DECLARE_FLAGS(TaskTypes, TaskType);
|
||||
|
||||
// void setTaskType(TaskType type = NormalType);
|
||||
|
||||
|
||||
public:
|
||||
// QRunnable interface
|
||||
void run() override;
|
||||
|
||||
|
||||
signals:
|
||||
void complete(const QString s);
|
||||
void textChanged();
|
||||
void cn2TnChanged();
|
||||
|
||||
public:
|
||||
QString text() const;
|
||||
void setText(const QString &newText);
|
||||
bool cn2Tn() const;
|
||||
void setCn2Tn(bool newCn2Tn);
|
||||
|
||||
private:
|
||||
QString m_text;
|
||||
bool m_cn2Tn;
|
||||
};
|
||||
|
||||
#endif // OPENCCTASK_H
|
|
@ -0,0 +1,11 @@
|
|||
#include <qobject.h>
|
||||
#include <qstring.h>
|
||||
#include <include/pluginGl.h>
|
||||
#include <functional>
|
||||
#include <qsciscintilla.h>
|
||||
#include "ndd_plugin_implement.h"
|
||||
|
||||
|
||||
NOTEPAD_PLUGIN_METADATA_IDENTIFY_V1(u8"简繁转换面板", "0.1", "zinface", u8"一个简单的简繁转换面板", "");
|
||||
|
||||
NOTEPAD_PLUGIN_METADATA_IMPLEMENT_V1(NddPluginImplement, false);
|
|
@ -0,0 +1,52 @@
|
|||
#include "baseplugin.h"
|
||||
#include "pluginframeworkhelper.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
|
||||
BasePlugin::BasePlugin(QObject *parent)
|
||||
: QObject{parent}
|
||||
{}
|
||||
|
||||
BasePlugin &BasePlugin::instance()
|
||||
{
|
||||
static BasePlugin _plugin;
|
||||
return _plugin;
|
||||
}
|
||||
|
||||
QString BasePlugin::PluginName()
|
||||
{
|
||||
return "base-plugin";
|
||||
}
|
||||
|
||||
QString BasePlugin::PluginVersion()
|
||||
{
|
||||
return "v0.1";
|
||||
}
|
||||
|
||||
QString BasePlugin::PluginAuthor()
|
||||
{
|
||||
return "author";
|
||||
}
|
||||
|
||||
QString BasePlugin::PluginComment()
|
||||
{
|
||||
return u8"基本插件 - 由生成器生成";
|
||||
}
|
||||
|
||||
IPluginFramework::MenuType BasePlugin::PluginMenuType()
|
||||
{
|
||||
return MenuType::None;
|
||||
}
|
||||
|
||||
void BasePlugin::PluginTrigger()
|
||||
{
|
||||
QMessageBox::information(nullptr, "tip", "This is default tip message.");
|
||||
}
|
||||
|
||||
void BasePlugin::registerPluginActions(QMenu *rootMenu)
|
||||
{
|
||||
//Actions: Will never enter here.
|
||||
}
|
||||
|
||||
// Plug-in implementation wrapper
|
||||
NDD_DECLARE_PLUGIN(BasePlugin::instance())
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef BASEPLUGIN_H
|
||||
#define BASEPLUGIN_H
|
||||
|
||||
#include <IPluginFramework.h>
|
||||
#include <QObject>
|
||||
|
||||
class BasePlugin : public QObject, public IPluginFramework
|
||||
{
|
||||
Q_OBJECT
|
||||
explicit BasePlugin(QObject *parent = nullptr);
|
||||
public:
|
||||
static BasePlugin &instance();
|
||||
|
||||
|
||||
// IPluginFramework interface
|
||||
public:
|
||||
QString PluginName();
|
||||
QString PluginVersion();
|
||||
QString PluginAuthor();
|
||||
QString PluginComment();
|
||||
MenuType PluginMenuType();
|
||||
void PluginTrigger();
|
||||
void registerPluginActions(QMenu *rootMenu);
|
||||
|
||||
/** 当前版本 IPluginManager 中已经为此实现 - 如需加载时执行自定义代码请重写 registerNotepad 实现.
|
||||
并在其实现内首行调用 IPluginFramework::registerNotepad(notepad);
|
||||
*/
|
||||
// void registerNotepad(QWidget *notepad);
|
||||
// void registerStrFileName(QString str_file_name);
|
||||
// void registerCurrentEditCallback(std::function<QsciScintilla *(QWidget *)> get_cur_edit_callback);
|
||||
// void registerPluginCallBack(std::function<bool (QWidget *, int, void *)> plugin_callback);
|
||||
};
|
||||
|
||||
#endif // BASEPLUGIN_H
|
|
@ -0,0 +1,110 @@
|
|||
#include "basesecondaryplugin.h"
|
||||
#include "pluginframeworkhelper.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
|
||||
BaseSecondaryPlugin::BaseSecondaryPlugin(QObject *parent)
|
||||
: QObject{parent}
|
||||
{}
|
||||
|
||||
BaseSecondaryPlugin &BaseSecondaryPlugin::instance()
|
||||
{
|
||||
static BaseSecondaryPlugin _plugin;
|
||||
return _plugin;
|
||||
}
|
||||
|
||||
QString BaseSecondaryPlugin::PluginName()
|
||||
{
|
||||
return "base-secondary-plugin";
|
||||
}
|
||||
|
||||
QString BaseSecondaryPlugin::PluginVersion()
|
||||
{
|
||||
return "v0.1";
|
||||
}
|
||||
|
||||
QString BaseSecondaryPlugin::PluginAuthor()
|
||||
{
|
||||
return "author";
|
||||
}
|
||||
|
||||
QString BaseSecondaryPlugin::PluginComment()
|
||||
{
|
||||
return "基本二级菜单插件";
|
||||
}
|
||||
|
||||
IPluginFramework::MenuType BaseSecondaryPlugin::PluginMenuType()
|
||||
{
|
||||
return MenuType::SecondaryMenu;
|
||||
}
|
||||
|
||||
void BaseSecondaryPlugin::PluginTrigger()
|
||||
{
|
||||
//Trigger: Will never enter here.
|
||||
}
|
||||
|
||||
void BaseSecondaryPlugin::registerPluginActions(QMenu *rootMenu)
|
||||
{
|
||||
rootMenu->addAction("Default", this, [this](){
|
||||
QMessageBox::information(nullptr, "tip", "This is default tip message.");
|
||||
});
|
||||
|
||||
connect(rootMenu->addAction(u8"第一项打印"), &QAction::triggered, this, [](){
|
||||
// 普通的菜单项
|
||||
qDebug() << "action1";
|
||||
});
|
||||
|
||||
connect(rootMenu->addAction(u8"第二项打印"), &QAction::triggered, this, [](){
|
||||
// 普通的菜单项
|
||||
qDebug() << "action2";
|
||||
});
|
||||
|
||||
connect(rootMenu->addAction(u8"打印默认编辑器内容(源代码项注意)"), &QAction::triggered, this, [=](){
|
||||
// FAQ: 当第一次使用 m_editor 时,使用时可能会引发错误。
|
||||
// 此时 m_editor 可能是空的。
|
||||
if (m_editor == nullptr) {
|
||||
qDebug() << "Warring: m_editor == nullptr!";
|
||||
return;
|
||||
}
|
||||
qDebug() << m_editor->text();
|
||||
});
|
||||
|
||||
connect(rootMenu->addAction(u8"设置当前编辑器为默认"), &QAction::triggered, this, [=](){
|
||||
// 获取当前编辑器,并作为当前默认编辑器
|
||||
m_editor = s_get_cur_edit_callback(s_notepad);
|
||||
qDebug() << u8"设置完成";
|
||||
});
|
||||
|
||||
connect(rootMenu->addAction(u8"打印当前编辑器内容"), &QAction::triggered, this, [=](){
|
||||
// 获取当前编辑器,并直接打印编辑器内容
|
||||
auto editor = s_get_cur_edit_callback(s_notepad);
|
||||
qDebug() << editor->text();
|
||||
});
|
||||
|
||||
connect(rootMenu->addAction(u8"创建新的编辑器"), &QAction::triggered, this, [=](){
|
||||
// 创建一个新的编辑器
|
||||
QVariant editor = PluginFrameworkHelper::DoNewEdit(s_notepad, s_plugin_callback);
|
||||
qDebug() << editor.toString();
|
||||
});
|
||||
|
||||
connect(rootMenu->addAction(u8"改变当前编辑器语法 - Html"), &QAction::triggered, this, [=](){
|
||||
// 改变语法 Html
|
||||
bool re = PluginFrameworkHelper::DoChangeSyntax(s_notepad, s_plugin_callback, SyntaxType::Html);
|
||||
qDebug() << "Html" << re;
|
||||
});
|
||||
|
||||
connect(rootMenu->addAction(u8"改变当前编辑器语法 - Js"), &QAction::triggered, this, [=](){
|
||||
// 改变语法 Js
|
||||
bool re = PluginFrameworkHelper::DoChangeSyntax(s_notepad, s_plugin_callback, SyntaxType::Js);
|
||||
qDebug() << "Js" << re;
|
||||
});
|
||||
|
||||
connect(rootMenu->addAction(u8"改变当前编辑器语法 - Json"), &QAction::triggered, this, [=](){
|
||||
// 改变语法 Json
|
||||
bool re = PluginFrameworkHelper::DoChangeSyntax(s_notepad, s_plugin_callback, SyntaxType::Json);
|
||||
qDebug() << "Json" << re;
|
||||
});
|
||||
}
|
||||
|
||||
// Plug-in implementation wrapper
|
||||
NDD_DECLARE_PLUGIN(BaseSecondaryPlugin::instance())
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef BASESECONDARYPLUGIN_H
|
||||
#define BASESECONDARYPLUGIN_H
|
||||
|
||||
#include <IPluginFramework.h>
|
||||
#include <QObject>
|
||||
|
||||
class BaseSecondaryPlugin : public QObject, public IPluginFramework
|
||||
{
|
||||
Q_OBJECT
|
||||
explicit BaseSecondaryPlugin(QObject *parent = nullptr);
|
||||
public:
|
||||
static BaseSecondaryPlugin &instance();
|
||||
|
||||
|
||||
// IPluginFramework interface
|
||||
public:
|
||||
QString PluginName();
|
||||
QString PluginVersion();
|
||||
QString PluginAuthor();
|
||||
QString PluginComment();
|
||||
MenuType PluginMenuType();
|
||||
void PluginTrigger();
|
||||
void registerPluginActions(QMenu *rootMenu);
|
||||
|
||||
/** 当前版本 IPluginManager 中已经为此实现 - 如需加载时执行自定义代码请重写 registerNotepad 实现.
|
||||
并在其实现内首行调用 IPluginFramework::registerNotepad(notepad);
|
||||
*/
|
||||
// void registerNotepad(QWidget *notepad);
|
||||
// void registerStrFileName(QString str_file_name);
|
||||
// void registerCurrentEditCallback(std::function<QsciScintilla *(QWidget *)> get_cur_edit_callback);
|
||||
// void registerPluginCallBack(std::function<bool (QWidget *, int, void *)> plugin_callback);
|
||||
|
||||
|
||||
QsciScintilla *m_editor;
|
||||
};
|
||||
|
||||
#endif // BASESECONDARYPLUGIN_H
|
|
@ -0,0 +1,93 @@
|
|||
#include "basesecondarywidgetplugin.h"
|
||||
#include "pluginframeworkhelper.h"
|
||||
#include "pluginviewer.h"
|
||||
|
||||
#include <QDockWidget>
|
||||
#include <QMessageBox>
|
||||
|
||||
BaseSecondaryWidgetPlugin::BaseSecondaryWidgetPlugin(QObject *parent)
|
||||
: QObject{parent}
|
||||
{}
|
||||
|
||||
BaseSecondaryWidgetPlugin &BaseSecondaryWidgetPlugin::instance()
|
||||
{
|
||||
static BaseSecondaryWidgetPlugin _plugin;
|
||||
return _plugin;
|
||||
}
|
||||
|
||||
QString BaseSecondaryWidgetPlugin::PluginName()
|
||||
{
|
||||
return "base-secondary-widget-plugin";
|
||||
}
|
||||
|
||||
QString BaseSecondaryWidgetPlugin::PluginVersion()
|
||||
{
|
||||
return "v0.1";
|
||||
}
|
||||
|
||||
QString BaseSecondaryWidgetPlugin::PluginAuthor()
|
||||
{
|
||||
return "author";
|
||||
}
|
||||
|
||||
QString BaseSecondaryWidgetPlugin::PluginComment()
|
||||
{
|
||||
return "二级菜单高级 UI 插件";
|
||||
}
|
||||
|
||||
IPluginFramework::MenuType BaseSecondaryWidgetPlugin::PluginMenuType()
|
||||
{
|
||||
return MenuType::SecondaryMenu;
|
||||
}
|
||||
|
||||
void BaseSecondaryWidgetPlugin::PluginTrigger()
|
||||
{
|
||||
//Trigger: Will never enter here.
|
||||
}
|
||||
|
||||
void BaseSecondaryWidgetPlugin::registerPluginActions(QMenu *rootMenu)
|
||||
{
|
||||
rootMenu->addAction("Default", this, [this](){
|
||||
QMessageBox::information(nullptr, "tip", "This is default tip message.");
|
||||
});
|
||||
|
||||
rootMenu->addAction("Show Ui", this, [=](){
|
||||
auto viewer = new PluginViewer();
|
||||
viewer->show();
|
||||
});
|
||||
|
||||
rootMenu->addAction("Show Sider", this, [=](){
|
||||
auto notepad = dynamic_cast<QMainWindow*>(s_notepad);
|
||||
|
||||
auto viewer = new PluginViewer(s_notepad);
|
||||
viewer->show();
|
||||
viewer->setMinimumWidth(300);
|
||||
|
||||
auto dock =new QDockWidget("Plugin Sider Viewer", s_notepad);
|
||||
connect(viewer, &QObject::destroyed, dock, &QObject::deleteLater);
|
||||
|
||||
dock->setAllowedAreas(Qt::DockWidgetArea::LeftDockWidgetArea | Qt::DockWidgetArea::RightDockWidgetArea);
|
||||
dock->setWidget(viewer);
|
||||
|
||||
(dynamic_cast<QMainWindow*>(s_notepad))->addDockWidget(Qt::RightDockWidgetArea, dock);
|
||||
});
|
||||
|
||||
rootMenu->addAction("Show Bottom", this, [=](){
|
||||
auto notepad = dynamic_cast<QMainWindow*>(s_notepad);
|
||||
|
||||
auto viewer = new PluginViewer(s_notepad);
|
||||
viewer->show();
|
||||
viewer->setMinimumHeight(100);
|
||||
|
||||
auto dock =new QDockWidget("Plugin Bottom Viewer", s_notepad);
|
||||
connect(viewer, &QObject::destroyed, dock, &QObject::deleteLater);
|
||||
|
||||
dock->setAllowedAreas(Qt::DockWidgetArea::BottomDockWidgetArea);
|
||||
dock->setWidget(viewer);
|
||||
|
||||
(dynamic_cast<QMainWindow*>(s_notepad))->addDockWidget(Qt::BottomDockWidgetArea, dock);
|
||||
});
|
||||
}
|
||||
|
||||
// Plug-in implementation wrapper
|
||||
NDD_DECLARE_PLUGIN(BaseSecondaryWidgetPlugin::instance())
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef BASESECONDARYWIDGETPLUGIN_H
|
||||
#define BASESECONDARYWIDGETPLUGIN_H
|
||||
|
||||
#include <IPluginFramework.h>
|
||||
#include <QObject>
|
||||
|
||||
class BaseSecondaryWidgetPlugin : public QObject, public IPluginFramework
|
||||
{
|
||||
Q_OBJECT
|
||||
explicit BaseSecondaryWidgetPlugin(QObject *parent = nullptr);
|
||||
public:
|
||||
static BaseSecondaryWidgetPlugin &instance();
|
||||
|
||||
|
||||
// IPluginFramework interface
|
||||
public:
|
||||
QString PluginName();
|
||||
QString PluginVersion();
|
||||
QString PluginAuthor();
|
||||
QString PluginComment();
|
||||
MenuType PluginMenuType();
|
||||
void PluginTrigger();
|
||||
void registerPluginActions(QMenu *rootMenu);
|
||||
|
||||
/** 当前版本 IPluginManager 中已经为此实现 - 如需加载时执行自定义代码请重写 registerNotepad 实现.
|
||||
并在其实现内首行调用 IPluginFramework::registerNotepad(notepad);
|
||||
*/
|
||||
// void registerNotepad(QWidget *notepad);
|
||||
// void registerStrFileName(QString str_file_name);
|
||||
// void registerCurrentEditCallback(std::function<QsciScintilla *(QWidget *)> get_cur_edit_callback);
|
||||
// void registerPluginCallBack(std::function<bool (QWidget *, int, void *)> plugin_callback);
|
||||
};
|
||||
|
||||
#endif // BASESECONDARYWIDGETPLUGIN_H
|
|
@ -0,0 +1,14 @@
|
|||
#include "pluginviewer.h"
|
||||
#include "ui_pluginviewer.h"
|
||||
|
||||
PluginViewer::PluginViewer(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::PluginViewer)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
PluginViewer::~PluginViewer()
|
||||
{
|
||||
delete ui;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef PLUGINVIEWER_H
|
||||
#define PLUGINVIEWER_H
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
namespace Ui {
|
||||
class PluginViewer;
|
||||
}
|
||||
|
||||
class PluginViewer : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PluginViewer(QWidget *parent = nullptr);
|
||||
~PluginViewer();
|
||||
|
||||
private:
|
||||
Ui::PluginViewer *ui;
|
||||
};
|
||||
|
||||
#endif // PLUGINVIEWER_H
|