feat: 完善插件系统;增加测试插件;完善 README;

This commit is contained in:
寂静的羽夏 2024-12-08 22:09:31 +08:00
parent 893f3112c7
commit e47b96b563
29 changed files with 852 additions and 91 deletions

View File

@ -60,6 +60,12 @@ RibbonTabContent *Ribbon::addTab(const QString &tabName) {
return ribbonTabContent;
}
void Ribbon::addTab(RibbonTabContent *tabContent, const QString &tabName) {
if (tabContent) {
QTabWidget::addTab(tabContent, tabName);
}
}
RibbonTabContent *Ribbon::addTab(const QIcon &tabIcon, const QString &tabName) {
// Note: superclass QTabWidget also has a function addTab()
RibbonTabContent *ribbonTabContent = new RibbonTabContent;

View File

@ -29,6 +29,11 @@ public:
/// \param[in] tabName Name of the tab
RibbonTabContent *addTab(const QString &tabName);
/// Add a tab to the ribbon.
///
/// \param[in] tabContent pointer of the tab
void addTab(RibbonTabContent *tabContent, const QString &tabName);
/// Add a tab to the ribbon.
///
/// \param[in] tabIcon Icon of the tab

View File

@ -17,6 +17,11 @@ find_package(
Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Network Concurrent
PrintSupport Xml LinguistTools)
option(BUILD_TEST_PLUGIN OFF)
if(BUILD_TEST_PLUGIN)
add_subdirectory(TestPlugin)
endif()
add_definitions(-DWINGHEX_VERSION="${PROJECT_VERSION}"
-DAPP_ORG="WingCloudStudio" -DAPP_NAME="${PROJECT_NAME}")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/WINGHEX_VERSION" ${PROJECT_VERSION})
@ -418,6 +423,7 @@ set(PROJECT_SOURCES
main.cpp
src/utilities.h
src/dbghelper.h
src/define.h
${QCONSOLEWIDGET_SRC}
${QPATHEDIT_SRC}
${WIDGET_FRAME_SRC}

View File

@ -107,6 +107,8 @@
  如果你想将本软件的代码用于闭源的商业代码,想要解除`GPL`系列的必须开源的限制,请必须亲自咨询我,商讨商业授权相关事宜。
  对于插件开发相关的,对应的开源协议就不一样了。只针对本仓库下的`src/plugin/iwingplugin.h`和`src/plugin/settingpage.h`遵守`BSD 3-Clause`协议,以允许想要做闭源和商业开发。对于本仓库下的`TestPlugin`的代码(除`TranslationUtils.cmake`这一个文件遵守`BSD 3-Clause`)遵守`MIT`协议。
### 使用声明
1. 本软件源代码不得私自应用于闭源商业用途除非你完整开源GPL协议的要求。如果要将软件仓库的代码商用闭源必须找我购买商业授权签订合同价格私聊非诚勿扰。

View File

@ -107,6 +107,8 @@ This software complies with the `AGPL-3.0` agreement. Please do not use it for p
If you want to use the code of this software for closed-source commercial code and want to lift the restriction of the `GPL` series that it must be open source, please consult me in person to discuss commercial licensing matters.
For plugin development, the corresponding open source agreements are different. Only `src/plugin/iwingplugin.h` and `src/plugin/settingpage.h` in this repository comply with the `BSD 3-Clause` agreement to allow closed-source and commercial development. The code of `TestPlugin` in this repository (except the file `TranslationUtils.cmake` which complies with `BSD 3-Clause`) complies with the `MIT` agreement.
### Usage Statement
1. The source code of this software shall not be used for closed-source commercial purposes unless you open source it completely (as required by the GPL agreement). If you want to commercially close the code of the software warehouse, you must contact me to purchase a commercial license and sign a contract. Please contact me for the price. Please do not disturb me if you are not serious.

103
TestPlugin/CMakeLists.txt Normal file
View File

@ -0,0 +1,103 @@
cmake_minimum_required(VERSION 3.16)
project(TestPlugin)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# Test mode, please configure the main program directory to facilitate debugging
# 便
# vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
option(TEST_MODE TRUE)
# Set the location where the SDK is stored. Only iwingplugin.h and settingpage.h
# are required.
# SDK iwingplugin.h settingpage.h
# vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
set(WINGHEX_SDK "${CMAKE_CURRENT_SOURCE_DIR}/../src/plugin")
set(PLUGIN_INTERFACE_FOUND FALSE)
set(PLUGIN_SETPAGE_FOUND FALSE)
if(EXISTS "${WINGHEX_SDK}/iwingplugin.h")
set(PLUGIN_INTERFACE_FOUND TRUE)
endif()
if(EXISTS "${WINGHEX_SDK}/settingpage.h")
set(PLUGIN_SETPAGE_FOUND TRUE)
endif()
if(PLUGIN_INTERFACE_FOUND AND PLUGIN_SETPAGE_FOUND)
message(STATUS "${WINGHEX_SDK} is valid SDK path")
else()
message(FATAL_ERROR "Invalid SDK path!")
endif()
set(WINGHEX_SDK_HEADER "${WINGHEX_SDK}/iwingplugin.h"
"${WINGHEX_SDK}/settingpage.h")
include_directories(${WINGHEX_SDK})
# For Qt
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets LinguistTools)
find_package(
Qt${QT_VERSION_MAJOR}
COMPONENTS Widgets LinguistTools
REQUIRED)
set(TS_FILES "${CMAKE_CURRENT_SOURCE_DIR}/lang/TestPlugin_zh_CN.ts")
set(TRANSLATION_PATH ${CMAKE_CURRENT_SOURCE_DIR})
if(${QT_VERSION_MAJOR} EQUAL 5)
qt5_create_translation(QM_FILES ${TRANSLATION_PATH} ${TS_FILES} OPTIONS
-no-obsolete)
elseif(${QT_VERSION_MAJOR} EQUAL 6)
qt6_create_translation(QM_FILES ${TRANSLATION_PATH} ${TS_FILES} OPTIONS
-no-obsolete)
else()
message(FATAL_ERROR "Unsupported QT version")
endif()
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/TranslationUtils.cmake)
add_plugin_translations_resource(QM_RES TestPlugin ${QM_FILES})
add_library(
TestPlugin SHARED
${WINGHEX_SDK_HEADER}
testplugin.h
testplugin.cpp
TestPlugin.json
testform.h
testform.cpp
testform.ui
${QM_FILES}
${QM_RES}
resources.qrc)
set_target_properties(TestPlugin PROPERTIES SUFFIX ".wingplg")
if(TEST_MODE)
# If you want to be able to debug easily every time you compile, please set
# this variable. Because this test plugin is a subproject of the main
# project, use CMAKE_BINARY_DIR
# 便 CMAKE_BINARY_DIR
# vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
set(WINGHEX_PATH "${CMAKE_BINARY_DIR}")
set(WINGHEX_PLUGIN_PATH "${WINGHEX_PATH}/plugin")
add_custom_command(
TARGET TestPlugin
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory ${WINGHEX_PLUGIN_PATH}
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:TestPlugin>
${WINGHEX_PLUGIN_PATH})
endif()
target_link_libraries(TestPlugin PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)

36
TestPlugin/README.md Normal file
View File

@ -0,0 +1,36 @@
# TestPlugin
## How to Build
Create a build directory and run
cmake -DCMAKE_PREFIX_PATH=<path_to_qtcreator> -DCMAKE_BUILD_TYPE=RelWithDebInfo <path_to_plugin_source>
cmake --build .
where `<path_to_qtcreator>` is the relative or absolute path to a Qt Creator build directory, or to a
combined binary and development package (Windows / Linux), or to the `Qt Creator.app/Contents/Resources/`
directory of a combined binary and development package (macOS), and `<path_to_plugin_source>` is the
relative or absolute path to this plugin directory.
## How to Run
Run a compatible Qt Creator with the additional command line argument
-pluginpath <path_to_plugin>
where `<path_to_plugin>` is the path to the resulting plugin library in the build directory
(`<plugin_build>/lib/qtcreator/plugins` on Windows and Linux,
`<plugin_build>/Qt Creator.app/Contents/PlugIns` on macOS).
You might want to add `-temporarycleansettings` (or `-tcs`) to ensure that the opened Qt Creator
instance cannot mess with your user-global Qt Creator settings.
When building and running the plugin from Qt Creator, you can use
-pluginpath "%{buildDir}/lib/qtcreator/plugins" -tcs
on Windows and Linux, or
-pluginpath "%{buildDir}/Qt Creator.app/Contents/PlugIns" -tcs
for the `Command line arguments` field in the run settings.

View File

@ -0,0 +1,13 @@
{
"Id" : "testplugin",
"Name" : "TestPlugin",
"Version" : "0.0.1",
"CompatVersion" : "0.0.1",
"Vendor" : "WingCloudStudio",
"VendorId" : "wingcloudstudio",
"Copyright" : "wingsummer",
"License" : "AGPL-3.0",
"Description" : "A Test Plugin for WingHexExplorer2",
"Url" : "https://github.com/Wing-summer/WingHexExplorer2",
"DocumentationUrl" : ""
}

View File

@ -0,0 +1,29 @@
BSD 3-Clause License
Copyright (c) 2019-2022, Pedro López-Cabanillas
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,51 @@
# ==============================================================================
# Copyright (C) 2024-2027 WingSummer
#
# You can redistribute this file and/or modify it under the terms of the BSD
# 3-Clause.
#
# THIS FILE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# =============================================================================
if(NOT TARGET Qt${QT_VERSION_MAJOR}::lconvert)
message(
FATAL_ERROR
"The package \"Qt${QT_VERSION_MAJOR}LinguistTools\" is required.")
endif()
set(Qt_LCONVERT_EXECUTABLE Qt${QT_VERSION_MAJOR}::lconvert)
function(ADD_PLUGIN_TRANSLATIONS_RESOURCE res_file target)
set(_qm_files ${ARGN})
set(_res_file ${CMAKE_CURRENT_BINARY_DIR}/app_translations.qrc)
file(
WRITE ${_res_file}
"<!DOCTYPE RCC><RCC version=\"1.0\">\n <qresource prefix=\"/PLGLANG/${target}\">\n"
)
foreach(_lang ${_qm_files})
get_filename_component(_filename ${_lang} NAME)
file(APPEND ${_res_file} " <file>${_filename}</file>\n")
endforeach()
file(APPEND ${_res_file} " </qresource>\n</RCC>\n")
set(${res_file}
${_res_file}
PARENT_SCOPE)
endfunction()
add_custom_target(
lupdate
COMMAND ${Qt${QT_VERSION_MAJOR}_LUPDATE_EXECUTABLE} -recursive
${PROJECT_SOURCE_DIR} -ts *.ts
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
COMMENT "Updating translations")

BIN
TestPlugin/images/btn.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
TestPlugin/images/test.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="zh_CN">
<context>
<name>TestForm</name>
<message>
<location filename="../testform.ui" line="20"/>
<source>TestForm</source>
<translation></translation>
</message>
<message>
<location filename="../testform.ui" line="30"/>
<source>Basic</source>
<translation></translation>
</message>
<message>
<location filename="../testform.ui" line="35"/>
<source>Reader</source>
<translation></translation>
</message>
<message>
<location filename="../testform.ui" line="40"/>
<source>Controller</source>
<translation></translation>
</message>
<message>
<location filename="../testform.ui" line="45"/>
<source>MessageBox</source>
<translation></translation>
</message>
<message>
<location filename="../testform.ui" line="50"/>
<source>InputBox</source>
<translation></translation>
</message>
<message>
<location filename="../testform.ui" line="55"/>
<source>FileDialog</source>
<translation></translation>
</message>
<message>
<location filename="../testform.ui" line="60"/>
<source>ColorDialog</source>
<translation></translation>
</message>
<message>
<location filename="../testform.ui" line="65"/>
<source>DataVisual</source>
<translation></translation>
</message>
</context>
<context>
<name>TestPlugin</name>
<message>
<location filename="../testplugin.cpp" line="56"/>
<source>Test</source>
<translation></translation>
</message>
<message>
<location filename="../testplugin.cpp" line="66"/>
<location filename="../testplugin.cpp" line="79"/>
<source>TestPlugin</source>
<translation></translation>
</message>
<message>
<location filename="../testplugin.cpp" line="86"/>
<source>A Test Plugin for WingHexExplorer2.</source>
<translation>2</translation>
</message>
</context>
</TS>

6
TestPlugin/resources.qrc Normal file
View File

@ -0,0 +1,6 @@
<RCC>
<qresource prefix="/images/TestPlugin">
<file>images/btn.png</file>
<file>images/test.png</file>
</qresource>
</RCC>

28
TestPlugin/testform.cpp Normal file
View File

@ -0,0 +1,28 @@
/*==============================================================================
** Copyright (C) 2024-2027 WingSummer
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
** THE SOFTWARE.
** =============================================================================
*/
#include "testform.h"
#include "ui_testform.h"
TestForm::TestForm(QWidget *parent) : QWidget(parent), ui(new Ui::TestForm) {
ui->setupUi(this);
}
TestForm::~TestForm() { delete ui; }

41
TestPlugin/testform.h Normal file
View File

@ -0,0 +1,41 @@
/*==============================================================================
** Copyright (C) 2024-2027 WingSummer
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
** THE SOFTWARE.
** =============================================================================
*/
#ifndef TESTFORM_H
#define TESTFORM_H
#include <QWidget>
namespace Ui {
class TestForm;
}
class TestForm : public QWidget {
Q_OBJECT
public:
explicit TestForm(QWidget *parent = nullptr);
~TestForm();
private:
Ui::TestForm *ui;
};
#endif // TESTFORM_H

74
TestPlugin/testform.ui Normal file
View File

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TestForm</class>
<widget class="QWidget" name="TestForm">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>400</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>600</width>
<height>400</height>
</size>
</property>
<property name="windowTitle">
<string>TestForm</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string>Basic</string>
</attribute>
</widget>
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Reader</string>
</attribute>
</widget>
<widget class="QWidget" name="tab_3">
<attribute name="title">
<string>Controller</string>
</attribute>
</widget>
<widget class="QWidget" name="tab_4">
<attribute name="title">
<string>MessageBox</string>
</attribute>
</widget>
<widget class="QWidget" name="tab_5">
<attribute name="title">
<string>InputBox</string>
</attribute>
</widget>
<widget class="QWidget" name="tab_6">
<attribute name="title">
<string>FileDialog</string>
</attribute>
</widget>
<widget class="QWidget" name="tab_7">
<attribute name="title">
<string>ColorDialog</string>
</attribute>
</widget>
<widget class="QWidget" name="tab_8">
<attribute name="title">
<string>DataVisual</string>
</attribute>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

116
TestPlugin/testplugin.cpp Normal file
View File

@ -0,0 +1,116 @@
/*==============================================================================
** Copyright (C) 2024-2027 WingSummer
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
** THE SOFTWARE.
** =============================================================================
*/
#include "testplugin.h"
#include "testform.h"
TestPlugin::TestPlugin() : puid(QStringLiteral("TestPlugin2")) {
// 在构造函数中,所有的 API 都无法调用。插件的翻译文件也不会自动加载。
// 在构造函数中,仅适合做一些为初始化准备的操作。
// 插件的语言文件会在初始化前自动加载,如果初始化失败则会被卸载
// 初始化会传递一个配置类,插件系统会统一管理放到统一的地方,使用 INI 保存
// 你可以自行管理,但不建议,统一管理方便使用者备份和转移插件配置
}
TestPlugin::~TestPlugin() {}
int TestPlugin::sdkVersion() const { return WingHex::SDKVERSION; }
const QString TestPlugin::signature() const { return WingHex::WINGSUMMER; }
bool TestPlugin::init(const QSettings &set) {
auto v = set.value("Test", 0).toInt();
// 如果你之前启动过且正常推出,这个值一定是 5
qDebug() << v;
// 和日志与 UI 相关的接口此时可用,剩余的 API 初始化成功才可用
_tform = emit createDialog(new TestForm);
using TBInfo = WingHex::WingRibbonToolBoxInfo;
TBInfo::RibbonCatagories cats;
auto tb = new QToolButton;
// 这里有一个约定,对于含有图片的,前缀应为:/images/插件的 PUID
// 其他资源,前缀应为:/res/插件的 PUID 或 /resources/插件的 PUID
// 如果想省劲,可以统一为 /插件的 PUID但别一个 / 完事。
// 这很容易发生资源文件冲突!!!
tb->setIcon(QIcon(QStringLiteral(":/images/TestPlugin/images/test.png")));
tb->setText(tr("Test"));
connect(tb, &QToolButton::clicked, this, [=] {
if (_tform) {
_tform->show();
_tform->raise();
}
});
_rtbinfo = {WingHex::WingRibbonToolBoxInfo{
.catagory = cats.PLUGIN,
.toolboxs = {
TBInfo::Toolbox{.name = tr("TestPlugin"), .tools = {tb}}}}};
return true;
}
void TestPlugin::unload(QSettings &set) {
// 设个数字,那就是 5 测试一下配置是否正常工作
set.setValue("Test", 5);
_tform->close();
_tform->deleteLater();
}
const QString TestPlugin::pluginName() const { return tr("TestPlugin"); }
const QString TestPlugin::pluginAuthor() const { return WingHex::WINGSUMMER; }
uint TestPlugin::pluginVersion() const { return WingHex::SDKVERSION; }
const QString TestPlugin::pluginComment() const {
return tr("A Test Plugin for WingHexExplorer2.");
}
QList<WingHex::WingDockWidgetInfo> TestPlugin::registeredDockWidgets() const {
return {};
}
QMenu *TestPlugin::registeredHexContextMenu() const { return _tmenu; }
QList<WingHex::WingRibbonToolBoxInfo>
TestPlugin::registeredRibbonTools() const {
return _rtbinfo;
}
QHash<WingHex::SettingPage *, bool> TestPlugin::registeredSettingPages() const {
return {};
}
QList<WingHex::PluginPage *> TestPlugin::registeredPages() const { return {}; }
QList<WingHex::WingEditorViewWidget *>
TestPlugin::registeredEditorViewWidgets() const {
return {};
}
QString TestPlugin::getPuid() const { return puid; }
QHash<QString, WingHex::IWingPlugin::ScriptFnInfo>
TestPlugin::registeredScriptFn() {
return {};
}

82
TestPlugin/testplugin.h Normal file
View File

@ -0,0 +1,82 @@
/*==============================================================================
** Copyright (C) 2024-2027 WingSummer
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
** THE SOFTWARE.
** =============================================================================
*/
#ifndef TESTPLUGIN_H
#define TESTPLUGIN_H
#include "iwingplugin.h"
class TestPlugin final : public WingHex::IWingPlugin {
Q_OBJECT
// 可选:用于自定义插件唯一标帜,请不要随意取名,否则很可能会和其他插件冲突导致无法加载
// 如果不注明,则是插件的类名作为唯一标帜,所以也不要随意给插件类起名字
// 当然,你可以在构造函数中,使用 setProperty("puid", yourID) 来实现自定义
Q_PROPERTY(QString puid READ getPuid CONSTANT FINAL)
// 这两行是必须,只有后面的 "TestPlugin.json" 你根据需要修改,
// 具体可见 QT 文档,剩下直接 CV 大法
Q_PLUGIN_METADATA(IID "com.wingsummer.iwingplugin" FILE "TestPlugin.json")
Q_INTERFACES(WingHex::IWingPlugin)
public:
explicit TestPlugin();
virtual ~TestPlugin();
// IWingPlugin interface (必须)
public:
virtual int sdkVersion() const override;
virtual const QString signature() const override;
virtual bool init(const QSettings &set) override;
virtual void unload(QSettings &set) override;
virtual const QString pluginName() const override;
virtual const QString pluginAuthor() const override;
virtual uint pluginVersion() const override;
virtual const QString pluginComment() const override;
// IWingPlugin interface (可选)
public:
// 有关注册开头register 开头)的函数,插件系统不保证有且只调用一次
// 所以最好不要为了偷懒,在实现里面 new 和做相应操作
virtual QList<WingHex::WingDockWidgetInfo>
registeredDockWidgets() const override;
virtual QMenu *registeredHexContextMenu() const override;
virtual QList<WingHex::WingRibbonToolBoxInfo>
registeredRibbonTools() const override;
virtual QHash<WingHex::SettingPage *, bool>
registeredSettingPages() const override;
virtual QList<WingHex::PluginPage *> registeredPages() const override;
virtual QList<WingHex::WingEditorViewWidget *>
registeredEditorViewWidgets() const override;
virtual QHash<QString, ScriptFnInfo> registeredScriptFn() override;
private:
QString getPuid() const;
private:
QDialog *_tform = nullptr;
QMenu *_tmenu = nullptr;
const QString puid;
QList<WingHex::WingRibbonToolBoxInfo> _rtbinfo;
};
#endif // TESTPLUGIN_H

View File

@ -1966,62 +1966,62 @@
<context>
<name>PluginSystem</name>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="57"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="69"/>
<source>LoadingPlugin</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="274"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="297"/>
<source>ErrLoadPluginSign</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="278"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="301"/>
<source>ErrLoadPluginSDKVersion</source>
<translation> SDK </translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="282"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="305"/>
<source>ErrLoadPluginNoName</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="289"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="310"/>
<source>ErrLoadLoadedPlugin</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="295"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="331"/>
<source>ErrLoadInitPlugin</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="309"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="338"/>
<source>PluginName :</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="310"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="339"/>
<source>PluginAuthor :</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="311"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="340"/>
<source>PluginWidgetRegister</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="1778"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="1836"/>
<source>Creating UI widget is not allowed in non-UI thread</source>
<translation>线</translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="1829"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="1887"/>
<source>FoundPluginCount</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="1835"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="1900"/>
<source>PluginLoadingFinished</source>
<translation></translation>
</message>
@ -5007,17 +5007,17 @@ Do you wish to keep up to date by reloading the file?</source>
<context>
<name>WingAngelAPI</name>
<message>
<location filename="../../src/class/wingangelapi.cpp" line="66"/>
<location filename="../../src/class/wingangelapi.cpp" line="69"/>
<source>AngelScriptService</source>
<translation>AngelScript </translation>
</message>
<message>
<location filename="../../src/class/wingangelapi.cpp" line="74"/>
<location filename="../../src/class/wingangelapi.cpp" line="77"/>
<source>A internal plugin that provides AngelScript scripts with the ability to call the host API.</source>
<translation> AngelScript API </translation>
</message>
<message>
<location filename="../../src/class/wingangelapi.cpp" line="1867"/>
<location filename="../../src/class/wingangelapi.cpp" line="1870"/>
<source>NotSupportedQMetaType:</source>
<translation> QT </translation>
</message>

View File

@ -1,6 +1,8 @@
#include "class/appmanager.h"
#include "class/settingmanager.h"
#include "define.h"
int main(int argc, char *argv[]) {
/* 有关对在 QT5 的 Win 平台禁用高 dpi 支持
*
@ -41,7 +43,7 @@ int main(int argc, char *argv[]) {
}
return a.exec();
} catch (int errCode) {
return errCode;
} catch (CrashCode errCode) {
return int(errCode);
}
}

View File

@ -18,6 +18,7 @@
#include "languagemanager.h"
#include "class/settingmanager.h"
#include "define.h"
#include "wingmessagebox.h"
#include <QApplication>
@ -174,11 +175,28 @@ void LanguageManager::abortAndExit() {
"solve the problem."));
}
throw(-1);
throw CrashCode::LanguageFile;
}
QLocale LanguageManager::defaultLocale() const { return _defaultLocale; }
QTranslator *LanguageManager::try2LoadPluginLang(const QString &plgID) {
QDir langDir(QStringLiteral(":/PLGLANG"));
if (!langDir.cd(plgID)) {
return nullptr;
}
auto translator = new QTranslator(this);
if (translator->load(_defaultLocale, plgID, QStringLiteral("_"),
langDir.absolutePath())) {
if (qApp->installTranslator(translator)) {
return translator;
}
}
translator->deleteLater();
return nullptr;
}
LanguageManager::LanguageData LanguageManager::data() const { return _data; }
QStringList LanguageManager::langsDisplay() const { return m_langsDisplay; }

View File

@ -22,6 +22,7 @@
#include <QLocale>
#include <QObject>
#include <QStringList>
#include <QTranslator>
class LanguageManager : public QObject {
Q_OBJECT
@ -42,6 +43,8 @@ public:
QLocale defaultLocale() const;
QTranslator *try2LoadPluginLang(const QString &plgID);
private:
LanguageManager();

View File

@ -55,12 +55,15 @@ int WingAngelAPI::sdkVersion() const { return WingHex::SDKVERSION; }
const QString WingAngelAPI::signature() const { return WingHex::WINGSUMMER; }
bool WingAngelAPI::init(const QList<WingHex::WingPluginInfo> &loadedplugin) {
Q_UNUSED(loadedplugin);
bool WingAngelAPI::init(const QSettings &set) {
Q_UNUSED(set);
return true;
}
void WingAngelAPI::unload() { this->disconnect(); }
void WingAngelAPI::unload(QSettings &set) {
Q_UNUSED(set);
this->disconnect();
}
const QString WingAngelAPI::pluginName() const {
return tr("AngelScriptService");

View File

@ -39,9 +39,8 @@ public:
public:
virtual int sdkVersion() const override;
virtual const QString signature() const override;
virtual bool
init(const QList<WingHex::WingPluginInfo> &loadedplugin) override;
virtual void unload() override;
virtual bool init(const QSettings &set) override;
virtual void unload(QSettings &set) override;
virtual const QString pluginName() const override;
virtual const QString pluginAuthor() const override;
virtual uint pluginVersion() const override;

6
src/define.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef DEFINE_H
#define DEFINE_H
enum class CrashCode : int { LanguageFile = 1, PluginSetting };
#endif // DEFINE_H

View File

@ -45,7 +45,7 @@
namespace WingHex {
Q_DECL_UNUSED constexpr auto SDKVERSION = 13;
Q_DECL_UNUSED constexpr auto SDKVERSION = 14;
Q_DECL_UNUSED static QString PLUGINDIR() {
return QCoreApplication::applicationDirPath() + QStringLiteral("/plugin");
@ -147,8 +147,8 @@ signals:
bool isLocked();
qsizetype documentLines();
qsizetype documentBytes();
HexPosition currentPos();
HexPosition selectionPos();
WingHex::HexPosition currentPos();
WingHex::HexPosition selectionPos();
qsizetype currentRow();
qsizetype currentColumn();
qsizetype currentOffset();
@ -191,23 +191,19 @@ signals:
// metadata
bool lineHasMetadata(qsizetype line);
QList<HexMetadataItem> getMetadatas(qsizetype offset);
QList<WingHex::HexMetadataItem> getMetadatas(qsizetype offset);
// bookmark
bool lineHasBookMark(qsizetype line);
QList<qsizetype> getsBookmarkPos(qsizetype line);
BookMark bookMark(qsizetype pos);
WingHex::BookMark bookMark(qsizetype pos);
QString bookMarkComment(qsizetype pos);
QList<BookMark> getBookMarks();
QList<WingHex::BookMark> getBookMarks();
bool existBookMark(qsizetype pos);
// extension
QStringList getSupportedEncodings();
QString currentEncoding();
// not available for AngelScript
// only for plugin UI extenstion
QDialog *createDialog(QWidget *content);
};
class Controller : public QObject {
@ -283,21 +279,22 @@ signals:
bool setMetaCommentVisible(bool b);
// mainwindow
ErrFile newFile();
ErrFile openFile(const QString &filename);
ErrFile openRegionFile(const QString &filename, qsizetype start = 0,
qsizetype length = 1024);
ErrFile openDriver(const QString &driver);
ErrFile closeFile(int handle, bool force = false);
ErrFile saveFile(int handle, bool ignoreMd5 = false);
ErrFile exportFile(int handle, const QString &savename,
bool ignoreMd5 = false);
WingHex::ErrFile newFile();
WingHex::ErrFile openFile(const QString &filename);
WingHex::ErrFile openRegionFile(const QString &filename,
qsizetype start = 0,
qsizetype length = 1024);
WingHex::ErrFile openDriver(const QString &driver);
WingHex::ErrFile closeFile(int handle, bool force = false);
WingHex::ErrFile saveFile(int handle, bool ignoreMd5 = false);
WingHex::ErrFile exportFile(int handle, const QString &savename,
bool ignoreMd5 = false);
bool exportFileGUI();
ErrFile saveAsFile(int handle, const QString &savename,
bool ignoreMd5 = false);
WingHex::ErrFile saveAsFile(int handle, const QString &savename,
bool ignoreMd5 = false);
bool saveAsFileGUI();
ErrFile closeCurrentFile(bool force = false);
ErrFile saveCurrentFile(bool ignoreMd5 = false);
WingHex::ErrFile closeCurrentFile(bool force = false);
WingHex::ErrFile saveCurrentFile(bool ignoreMd5 = false);
bool openFileGUI();
bool openRegionFileGUI();
bool openDriverGUI();
@ -313,7 +310,7 @@ signals:
bool clearBookMark();
// workspace
ErrFile openWorkSpace(const QString &filename);
WingHex::ErrFile openWorkSpace(const QString &filename);
bool setCurrentEncoding(const QString &encoding);
};
@ -426,14 +423,6 @@ signals:
} // namespace WingPlugin
struct WingPluginInfo {
QString pluginName;
QString pluginAuthor;
uint pluginVersion;
QString puid;
QString pluginComment;
};
const auto WINGSUMMER = QStringLiteral("wingsummer");
struct WingDockWidgetInfo {
@ -534,8 +523,8 @@ public:
virtual const QString signature() const = 0;
virtual ~IWingPlugin() = default;
virtual bool init(const QList<WingPluginInfo> &loadedplugin) = 0;
virtual void unload() = 0;
virtual bool init(const QSettings &set) = 0;
virtual void unload(QSettings &set) = 0;
virtual const QString pluginName() const = 0;
virtual const QString pluginAuthor() const = 0;
virtual uint pluginVersion() const = 0;
@ -569,6 +558,10 @@ signals:
void error(const QString &message);
void info(const QString &message);
// not available for AngelScript
// only for plugin UI extenstion
QDialog *createDialog(QWidget *content);
public:
WingPlugin::Reader reader;
WingPlugin::Controller controller;
@ -581,8 +574,6 @@ public:
} // namespace WingHex
constexpr auto IWINGPLUGIN_INTERFACE_IID = "com.wingsummer.iwingplugin";
Q_DECLARE_INTERFACE(WingHex::IWingPlugin, IWINGPLUGIN_INTERFACE_IID)
Q_DECLARE_INTERFACE(WingHex::IWingPlugin, "com.wingsummer.iwingplugin")
#endif // IWINGPLUGIN_H

View File

@ -18,13 +18,16 @@
#include "pluginsystem.h"
#include "QJsonModel/include/QJsonModel.hpp"
#include "Qt-Advanced-Docking-System/src/DockAreaWidget.h"
#include "class/languagemanager.h"
#include "class/logger.h"
#include "class/settingmanager.h"
#include "class/wingfiledialog.h"
#include "class/winginputdialog.h"
#include "class/wingmessagebox.h"
#include "control/toast.h"
#include "define.h"
#include "dialog/colorpickerdialog.h"
#include "dialog/framelessdialogbase.h"
#include "dialog/mainwindow.h"
#include "model/qjsontablemodel.h"
@ -37,8 +40,17 @@
PluginSystem::PluginSystem(QObject *parent) : QObject(parent) {}
PluginSystem::~PluginSystem() {
QDir udir(Utilities::getAppDataPath());
auto plgset = QStringLiteral("plgset");
udir.mkdir(plgset);
if (!udir.cd(plgset)) {
qApp->exit(int(CrashCode::PluginSetting));
}
for (auto &item : loadedplgs) {
item->unload();
QSettings set(udir.absoluteFilePath(item->metaObject()->className()),
QSettings::Format::IniFormat);
item->unload(set);
delete item;
}
}
@ -49,7 +61,7 @@ const IWingPlugin *PluginSystem::plugin(qsizetype index) const {
return loadedplgs.at(index);
}
void PluginSystem::loadPlugin(QFileInfo fileinfo) {
void PluginSystem::loadPlugin(const QFileInfo &fileinfo, const QDir &setdir) {
Q_ASSERT(_win);
if (fileinfo.exists()) {
@ -59,7 +71,7 @@ void PluginSystem::loadPlugin(QFileInfo fileinfo) {
if (Q_UNLIKELY(p == nullptr)) {
Logger::critical(loader.errorString());
} else {
if (!loadPlugin(p)) {
if (!loadPlugin(p, setdir)) {
loader.unload();
}
}
@ -267,8 +279,19 @@ QString PluginSystem::getScriptFnSig(const QString &fnName,
return sig + params.join(',') + QStringLiteral(")");
}
bool PluginSystem::loadPlugin(IWingPlugin *p) {
QList<WingPluginInfo> loadedplginfos;
QString PluginSystem::getPUID(IWingPlugin *p) {
if (p) {
auto prop = p->property("puid").toString().trimmed();
auto pid = QString(p->metaObject()->className());
return prop.isEmpty() ? pid : prop;
} else {
return {};
}
}
bool PluginSystem::loadPlugin(IWingPlugin *p, const QDir &setdir) {
QTranslator *p_tr = nullptr;
try {
if (p->signature() != WINGSUMMER) {
throw tr("ErrLoadPluginSign");
@ -282,34 +305,41 @@ bool PluginSystem::loadPlugin(IWingPlugin *p) {
throw tr("ErrLoadPluginNoName");
}
auto prop = p->property("puid").toString().trimmed();
auto puid =
prop.isEmpty() ? QString(p->metaObject()->className()) : prop;
auto puid = getPUID(p);
if (loadedpuid.contains(puid)) {
throw tr("ErrLoadLoadedPlugin");
}
emit pluginLoading(p->pluginName());
if (!p->init(loadedplginfos)) {
throw tr("ErrLoadInitPlugin");
auto pid = QString(p->metaObject()->className());
p_tr = LanguageManager::instance().try2LoadPluginLang(pid);
connectLoadingInterface(p);
QSettings *setp;
if (setdir == QDir()) {
setp = new QSettings;
} else {
setp = new QSettings(
setdir.absoluteFilePath(p->metaObject()->className()),
QSettings::Format::IniFormat);
}
WingPluginInfo info;
info.puid = puid;
info.pluginName = p->pluginName();
info.pluginAuthor = p->pluginAuthor();
info.pluginComment = p->pluginComment();
info.pluginVersion = p->pluginVersion();
if (!p->init(*setp)) {
setp->deleteLater();
throw tr("ErrLoadInitPlugin");
}
setp->deleteLater();
loadedplginfos.push_back(info);
loadedplgs.push_back(p);
loadedpuid << puid;
Logger::warning(tr("PluginName :") + info.pluginName);
Logger::warning(tr("PluginAuthor :") + info.pluginAuthor);
Logger::warning(tr("PluginName :") + p->pluginName());
Logger::warning(tr("PluginAuthor :") + p->pluginAuthor());
Logger::warning(tr("PluginWidgetRegister"));
// ensure call only once
auto ribbonToolboxInfos = p->registeredRibbonTools();
if (!ribbonToolboxInfos.isEmpty()) {
for (auto &item : ribbonToolboxInfos) {
@ -328,7 +358,14 @@ bool PluginSystem::loadPlugin(IWingPlugin *p) {
}
} else {
if (!item.toolboxs.isEmpty()) {
auto cat = _win->m_ribbon->addTab(item.displayName);
bool isSys = false;
RibbonTabContent *cat;
if (_win->m_ribbonMaps.contains(item.catagory)) {
isSys = true;
cat = _win->m_ribbonMaps.value(item.catagory);
} else {
cat = new RibbonTabContent;
}
bool hasAdded = false;
for (auto &group : item.toolboxs) {
if (group.tools.isEmpty()) {
@ -340,10 +377,13 @@ bool PluginSystem::loadPlugin(IWingPlugin *p) {
}
hasAdded = true;
}
if (hasAdded) {
_win->m_ribbonMaps[item.catagory] = cat;
} else {
_win->m_ribbon->removeTab(cat);
if (!isSys) {
if (hasAdded) {
_win->m_ribbon->addTab(cat, item.displayName);
_win->m_ribbonMaps[item.catagory] = cat;
} else {
delete cat;
}
}
}
}
@ -430,20 +470,26 @@ bool PluginSystem::loadPlugin(IWingPlugin *p) {
}
registerFns(p);
connectInterface(p);
m_plgviewMap.insert(p, nullptr);
} catch (const QString &error) {
Logger::critical(error);
if (p_tr) {
p_tr->deleteLater();
}
return false;
}
return true;
}
void PluginSystem::connectInterface(IWingPlugin *plg) {
connectBaseInterface(plg);
connectReaderInterface(plg);
connectControllerInterface(plg);
}
void PluginSystem::connectLoadingInterface(IWingPlugin *plg) {
connectBaseInterface(plg);
connectUIInterface(plg);
}
@ -472,6 +518,18 @@ void PluginSystem::connectBaseInterface(IWingPlugin *plg) {
Logger::critical(
packLogMessage(plg->metaObject()->className(), message));
});
connect(plg, &IWingPlugin::createDialog, this,
[=](QWidget *w) -> QDialog * {
if (w) {
auto d = new FramelessDialogBase;
d->buildUpContent(w);
d->setWindowTitle(w->windowTitle());
d->setWindowIcon(w->windowIcon());
return d;
} else {
return nullptr;
}
});
}
void PluginSystem::connectReaderInterface(IWingPlugin *plg) {
@ -1799,7 +1857,7 @@ void PluginSystem::LoadPlugin() {
_angelplg = new WingAngelAPI;
auto ret = loadPlugin(_angelplg);
auto ret = loadPlugin(_angelplg, QDir());
Q_ASSERT(ret);
Q_UNUSED(ret);
@ -1828,8 +1886,15 @@ void PluginSystem::LoadPlugin() {
auto plgs = plugindir.entryInfoList();
Logger::info(tr("FoundPluginCount") + QString::number(plgs.count()));
QDir udir(Utilities::getAppDataPath());
auto plgset = QStringLiteral("plgset");
udir.mkdir(plgset);
if (!udir.cd(plgset)) {
throw CrashCode::PluginSetting;
}
for (auto &item : plgs) {
loadPlugin(item);
loadPlugin(item, udir);
}
Logger::info(tr("PluginLoadingFinished"));

View File

@ -101,7 +101,7 @@ public:
const QList<IWingPlugin *> &plugins() const;
const IWingPlugin *plugin(qsizetype index) const;
void loadPlugin(QFileInfo filename);
void loadPlugin(const QFileInfo &filename, const QDir &setdir);
WingAngelAPI *angelApi() const;
@ -123,10 +123,13 @@ private:
QString getScriptFnSig(const QString &fnName,
const IWingPlugin::ScriptFnInfo &fninfo);
QString getPUID(IWingPlugin *p);
private:
bool loadPlugin(IWingPlugin *p);
bool loadPlugin(IWingPlugin *p, const QDir &setdir);
void connectInterface(IWingPlugin *plg);
void connectLoadingInterface(IWingPlugin *plg);
void connectBaseInterface(IWingPlugin *plg);
void connectReaderInterface(IWingPlugin *plg);
void connectControllerInterface(IWingPlugin *plg);