浏览代码

cmake-plugin: 添加基于源代码构建的外部插件扩展测试插件,一个简单的二级菜单与扩展实现

zinface 2 年之前
父节点
当前提交
cd8364c16f

+ 2 - 0
src/plugin/CMakeLists.txt

@@ -19,5 +19,7 @@ if(USE_NOTEPAD_PLUGIN)
     add_subdirectory(opencc-demo-plugin)
     add_subdirectory(opencc-demo-plugin)
     # 一个简单的版本更新检查的插件
     # 一个简单的版本更新检查的插件
     add_subdirectory(versionUpdate)
     add_subdirectory(versionUpdate)
+    # 一个简单的可二次扩展的插件
+    add_subdirectory(external-plugin)
 
 
 endif(USE_NOTEPAD_PLUGIN)
 endif(USE_NOTEPAD_PLUGIN)

+ 89 - 0
src/plugin/external-plugin/CMakeLists.txt

@@ -0,0 +1,89 @@
+# 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_aux_source_paths(LocalSources
+        .
+    )
+    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-say SHARED external-plugin/base.cpp)
+set_target_properties(external-plugin-say
+    PROPERTIES
+        LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/plugin/external-plugins")

+ 59 - 0
src/plugin/external-plugin/external-plugin/base.cpp

@@ -0,0 +1,59 @@
+#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--";
+}
+
+struct externalplugin plugin = {
+    .type = ActionBase,
+    .meta = "打印 Hello",
+    .func = sayHello,
+};
+
+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
+    }
+};

+ 24 - 0
src/plugin/external-plugin/external-plugin/interface/external.h

@@ -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__

+ 131 - 0
src/plugin/external-plugin/ndd_plugin_implement.cpp

@@ -0,0 +1,131 @@
+#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 <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;
+      }
+    });
+  }
+}

+ 33 - 0
src/plugin/external-plugin/ndd_plugin_implement.h

@@ -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

+ 31 - 0
src/plugin/external-plugin/ndd_plugin_implement.ui

@@ -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>

+ 11 - 0
src/plugin/external-plugin/plugin.cpp

@@ -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("外部插件扩展测试", "0.1", "zinface", u8"基于 QMainWindow Ui 的插件", "");
+
+NOTEPAD_PLUGIN_METADATA_IMPLEMENT_V1(NddPluginImplement, false);