From b42880aa7e62dfa34a5b8fae27819890055c2f1d Mon Sep 17 00:00:00 2001 From: wingsummer <1326224942@qq.com> Date: Thu, 26 Jun 2025 19:45:55 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E8=80=85=E6=8F=92=E4=BB=B6=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E4=BB=A5=E5=8F=8A=E5=BC=95=E5=85=A5=E7=9B=B8=E5=85=B3=E7=A0=B4?= =?UTF-8?q?=E5=9D=8F=E6=80=A7=E6=9B=B4=E6=96=B0=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 1 + ShareMemoryDrv/ShareMemoryDrv.json | 1 + ShareMemoryDrv/lang/shmem_zh_CN.ts | 10 +- ShareMemoryDrv/sharememorydrv.cpp | 6 - ShareMemoryDrv/sharememorydrv.h | 7 - TestManager/CMakeLists.txt | 50 ++ TestManager/TestManager.json | 9 + .../testmanager.cpp | 41 +- TestManager/testmanager.h | 98 ++++ TestPlugin/CMakeLists.txt | 4 +- TestPlugin/TestPlugin.json | 1 + TestPlugin/lang/TestPlugin_zh_CN.ts | 60 +-- TestPlugin/testplugin.cpp | 33 +- TestPlugin/testplugin.h | 7 +- TestPlugin/testpluginpage.h | 43 -- TestPlugin/testsettingpage.cpp | 6 +- TestPlugin/testsettingpage.h | 6 +- WingPlugin | 2 +- favicon.rc | 2 +- images/monitor.png | Bin 0 -> 5774 bytes lang/zh_CN/winghex_zh_CN.ts | 500 +++++++++--------- lang/zh_TW/winghex_zh_TW.ts | 500 +++++++++--------- resources.qrc | 1 + src/class/WingAngelAPI.json | 1 + src/class/WingCStruct.json | 1 + src/class/pluginsystem.cpp | 272 ++++++---- src/class/pluginsystem.h | 19 +- src/class/skinmanager.cpp | 35 +- src/class/skinmanager.h | 2 + src/class/wingangelapi.cpp | 2 - src/class/wingangelapi.h | 1 - src/class/wingcstruct.cpp | 5 +- src/class/wingcstruct.h | 5 +- src/dialog/mainwindow.cpp | 7 +- src/dialog/mainwindow.h | 3 +- src/settings/pluginsettingdialog.cpp | 66 ++- src/settings/pluginsettingdialog.h | 2 - src/settings/pluginsettingdialog.ui | 18 + src/utilities.h | 10 +- 39 files changed, 1042 insertions(+), 795 deletions(-) create mode 100644 TestManager/CMakeLists.txt create mode 100644 TestManager/TestManager.json rename TestPlugin/testpluginpage.cpp => TestManager/testmanager.cpp (52%) create mode 100644 TestManager/testmanager.h delete mode 100644 TestPlugin/testpluginpage.h create mode 100644 images/monitor.png diff --git a/CMakeLists.txt b/CMakeLists.txt index 2301f9d..7704290 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,7 @@ add_definitions(-DAS_NO_THREADS) if(BUILD_TEST_PLUGIN) add_subdirectory(TestPlugin) + add_subdirectory(TestManager) endif() if(BUILD_SHARED_MEM_EXT) diff --git a/ShareMemoryDrv/ShareMemoryDrv.json b/ShareMemoryDrv/ShareMemoryDrv.json index 93848ee..bb0c13e 100644 --- a/ShareMemoryDrv/ShareMemoryDrv.json +++ b/ShareMemoryDrv/ShareMemoryDrv.json @@ -1,5 +1,6 @@ { "Id" : "shmem", + "SDK": 18, "Version" : "0.0.1", "Vendor" : "WingCloudStudio", "Author" : "wingsummer", diff --git a/ShareMemoryDrv/lang/shmem_zh_CN.ts b/ShareMemoryDrv/lang/shmem_zh_CN.ts index 6909362..2e3e7d1 100644 --- a/ShareMemoryDrv/lang/shmem_zh_CN.ts +++ b/ShareMemoryDrv/lang/shmem_zh_CN.ts @@ -4,27 +4,27 @@ SharedMemoryDriver - + SharedMemoryDriver 共享内存驱动 - + An extension for opening sshared memory in WingHexExplorer2. 一个提供羽云十六进制编辑器2的插件打开共享内存的驱动 - + ShareMemory 共享内存 - + SharedMemory 共享内存 - + PleaseInputID: 请输入标识: diff --git a/ShareMemoryDrv/sharememorydrv.cpp b/ShareMemoryDrv/sharememorydrv.cpp index e749b1a..b68e189 100644 --- a/ShareMemoryDrv/sharememorydrv.cpp +++ b/ShareMemoryDrv/sharememorydrv.cpp @@ -23,8 +23,6 @@ SharedMemoryDriver::SharedMemoryDriver() : WingHex::IWingDevice() {} SharedMemoryDriver::~SharedMemoryDriver() {} -int SharedMemoryDriver::sdkVersion() const { return WingHex::SDKVERSION; } - bool SharedMemoryDriver::init(const std::unique_ptr &set) { Q_UNUSED(set); return true; @@ -42,10 +40,6 @@ const QString SharedMemoryDriver::pluginComment() const { return tr("An extension for opening sshared memory in WingHexExplorer2."); } -QList SharedMemoryDriver::registeredPages() const { - return _plgps; -} - WingHex::WingIODevice *SharedMemoryDriver::onOpenFile(const QString &path) { return new SharedMemory(path, SharedMemory::ReadWrite, this); } diff --git a/ShareMemoryDrv/sharememorydrv.h b/ShareMemoryDrv/sharememorydrv.h index 6defbbf..6f2a467 100644 --- a/ShareMemoryDrv/sharememorydrv.h +++ b/ShareMemoryDrv/sharememorydrv.h @@ -34,15 +34,11 @@ public: // IWingPlugin interface public: - virtual int sdkVersion() const override; virtual bool init(const std::unique_ptr &set) override; virtual void unload(std::unique_ptr &set) override; virtual const QString pluginName() const override; virtual const QString pluginComment() const override; -public: - virtual QList registeredPages() const override; - // IWingDevice interface public: virtual QString onOpenFileBegin() override; @@ -50,9 +46,6 @@ public: virtual QIcon supportedFileIcon() const override; virtual WingHex::WingIODevice *onOpenFile(const QString &path) override; virtual bool onCloseFile(WingHex::WingIODevice *dev) override; - -private: - QList _plgps; }; #endif // SHAREDMEMORYDRIVER_H diff --git a/TestManager/CMakeLists.txt b/TestManager/CMakeLists.txt new file mode 100644 index 0000000..3aa2e58 --- /dev/null +++ b/TestManager/CMakeLists.txt @@ -0,0 +1,50 @@ +cmake_minimum_required(VERSION 3.16) + +project(TestManager) + +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) + +set(CMAKE_INCLUDE_CURRENT_DIR TRUE) + +# Test mode, please configure the main program directory to facilitate debugging + +# 测试模式,启用请配置主程序目录,方便调试 + +# vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +option(TEST_MODE TRUE) + +# For Qt +find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets) +find_package( + Qt${QT_VERSION_MAJOR} + COMPONENTS Widgets + REQUIRED) + +add_library(TestManager SHARED testmanager.h testmanager.cpp TestManager.json) + +set_target_properties(TestManager PROPERTIES SUFFIX ".wingman") + +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}") + + add_custom_command( + TARGET TestManager + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + $ ${WINGHEX_PATH}) +endif() + +target_link_libraries(TestManager PRIVATE Qt${QT_VERSION_MAJOR}::Widgets + WingPlugin) diff --git a/TestManager/TestManager.json b/TestManager/TestManager.json new file mode 100644 index 0000000..3216c64 --- /dev/null +++ b/TestManager/TestManager.json @@ -0,0 +1,9 @@ +{ + "Id": "TestManager", + "SDK": 18, + "Version": "0.0.1", + "Vendor": "WingCloudStudio", + "Author": "wingsummer", + "License": "AGPL-3.0", + "Url": "https://github.com/Wing-summer/WingHexExplorer2" +} diff --git a/TestPlugin/testpluginpage.cpp b/TestManager/testmanager.cpp similarity index 52% rename from TestPlugin/testpluginpage.cpp rename to TestManager/testmanager.cpp index 3596179..5e951cb 100644 --- a/TestPlugin/testpluginpage.cpp +++ b/TestManager/testmanager.cpp @@ -18,21 +18,40 @@ ** ============================================================================= */ -#include "testpluginpage.h" +#include "testmanager.h" -#include +TestManager::TestManager() : WingHex::IWingManager() { content = new TestPage; } -TestPluginPage::TestPluginPage(QWidget *parent) : WingHex::PluginPage(parent) { - auto layout = new QVBoxLayout(this); - _lbl = new QLabel(QStringLiteral("TestPluginPage"), this); - _lbl->setAlignment(Qt::AlignCenter); - layout->addWidget(_lbl); +TestManager::~TestManager() { + // no need to manual delete content + // the host will take the ownership } -QIcon TestPluginPage::categoryIcon() const { - return QIcon(QStringLiteral(":/images/TestPlugin/images/btn.png")); +bool TestManager::init(const std::unique_ptr &set) { + Q_UNUSED(set); + return true; } -QString TestPluginPage::name() const { return tr("TestPluginPage"); } +void TestManager::unload(std::unique_ptr &set) { Q_UNUSED(set); } -QString TestPluginPage::id() const { return QStringLiteral("TestPluginPage"); } +const QString TestManager::comment() const { + return QStringLiteral("Hello world!"); +} + +QList TestManager::registeredSettingPages() const { + return {content}; +} + +bool TestManager::enterGuard(const QMetaObject *sender, const QString &sig, + const QVariantList ¶ms) { + if (content->isDisableMsg()) { + if (sig.startsWith("msg")) { + // block all msg-prefix function + logWarn(QStringLiteral("Blocking: (%1) {%2}") + .arg(sender->className(), sig)); + return false; + } + } + + return true; +} diff --git a/TestManager/testmanager.h b/TestManager/testmanager.h new file mode 100644 index 0000000..8459d5a --- /dev/null +++ b/TestManager/testmanager.h @@ -0,0 +1,98 @@ +/*============================================================================== +** 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 TESTMANAGER_H +#define TESTMANAGER_H + +#include "WingPlugin/iwingmanager.h" + +#include +#include + +class TestManager : public WingHex::IWingManager { + Q_OBJECT + + // 这两行是必须,只有后面的 "TestManager.json" 你根据需要修改, + // 具体可见 QT 文档,剩下直接 CV 大法 + Q_PLUGIN_METADATA(IID "com.wingsummer.iwingmanager" FILE "TestManager.json") + Q_INTERFACES(WingHex::IWingManager) +public: + explicit TestManager(); + virtual ~TestManager(); + + // IWingPluginCoreBase interface +public: + virtual bool init(const std::unique_ptr &set) override; + virtual void unload(std::unique_ptr &set) override; + +public: + virtual const QString comment() const override; + + virtual QList + registeredSettingPages() const override; + +private: + class TestPage : public WingHex::SettingPage { + public: + TestPage() { + auto layout = new QVBoxLayout(this); + _cbblk = new QCheckBox(QStringLiteral("Disable msg*"), this); + _cbblk->setChecked(false); + layout->addWidget(_cbblk); + layout->addStretch(); + } + // PageBase interface + public: + virtual QIcon categoryIcon() const override { + return QIcon(WingHex::HOSTRESPIMG("monitor")); + } + virtual QString name() const override { + return QStringLiteral("TestManager"); + } + virtual QString id() const override { + return QStringLiteral("TestManager"); + } + + // SettingInterface interface + public: + virtual void apply() override { _isDisabled = _cbblk->isChecked(); } + virtual void reset() override { + _isDisabled = false; + _cbblk->setChecked(false); + } + virtual void cancel() override { _cbblk->setChecked(_isDisabled); } + + public: + bool isDisableMsg() const { return _isDisabled; } + + private: + QCheckBox *_cbblk; + bool _isDisabled = false; + }; + +public slots: + virtual bool enterGuard(const QMetaObject *sender, const QString &sig, + const QVariantList ¶ms) override; + +private: + TestPage *content; +}; + +#endif // TESTMANAGER_H diff --git a/TestPlugin/CMakeLists.txt b/TestPlugin/CMakeLists.txt index 6f74ef3..4effe18 100644 --- a/TestPlugin/CMakeLists.txt +++ b/TestPlugin/CMakeLists.txt @@ -64,9 +64,7 @@ add_library( testsettingpage.h testsettingpage.cpp testwingeditorviewwidget.h - testwingeditorviewwidget.cpp - testpluginpage.h - testpluginpage.cpp) + testwingeditorviewwidget.cpp) set_target_properties(TestPlugin PROPERTIES SUFFIX ".wingplg") diff --git a/TestPlugin/TestPlugin.json b/TestPlugin/TestPlugin.json index f60a5d3..1ebba8d 100644 --- a/TestPlugin/TestPlugin.json +++ b/TestPlugin/TestPlugin.json @@ -1,5 +1,6 @@ { "Id": "TestPlugin", + "SDK": 18, "Version": "0.0.1", "Vendor": "WingCloudStudio", "Dependencies": [ diff --git a/TestPlugin/lang/TestPlugin_zh_CN.ts b/TestPlugin/lang/TestPlugin_zh_CN.ts index e01e039..2999742 100644 --- a/TestPlugin/lang/TestPlugin_zh_CN.ts +++ b/TestPlugin/lang/TestPlugin_zh_CN.ts @@ -269,72 +269,64 @@ TestPlugin - + Test 测试 - - - - + + + + TestPlugin 测试插件 - + Button - 按钮 - - + Click 点击 - + A Test Plugin for WingHexExplorer2. 一个用来测试羽云十六进制编辑器2的插件 - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + InvalidParamsCount 无效参数个数 - - + + InvalidParam 非法参数 - + AllocArrayFailed 分配数组失败 - - TestPluginPage - - - TestPluginPage - 测试插件页 - - TestWingEditorViewWidget diff --git a/TestPlugin/testplugin.cpp b/TestPlugin/testplugin.cpp index bb3f86e..adce988 100644 --- a/TestPlugin/testplugin.cpp +++ b/TestPlugin/testplugin.cpp @@ -20,7 +20,6 @@ #include "testplugin.h" #include "testform.h" -#include "testpluginpage.h" #include "testsettingpage.h" #include "testwingeditorviewwidget.h" @@ -180,8 +179,6 @@ TestPlugin::TestPlugin() : WingHex::IWingPlugin() { TestPlugin::~TestPlugin() { destoryTestShareMem(); } -int TestPlugin::sdkVersion() const { return WingHex::SDKVERSION; } - bool TestPlugin::init(const std::unique_ptr &set) { auto v = set->value("Test", 0).toInt(); // 如果你之前启动过且正常推出,这个值一定是 5 @@ -247,17 +244,11 @@ bool TestPlugin::init(const std::unique_ptr &set) { _rtbinfo.append(rtinfo); } - { - auto sp = new TestSettingPage(QStringLiteral("Test1"), - QStringLiteral("This is a Test1")); - _setpages.insert(sp, true); - } + _setpages.append(new TestSettingPage( + QStringLiteral("Test1"), QStringLiteral("This is a Test1"), true)); - { - auto sp = new TestSettingPage(QStringLiteral("Test2"), - QStringLiteral("This is a Test2")); - _setpages.insert(sp, false); - } + _setpages.append(new TestSettingPage( + QStringLiteral("Test2"), QStringLiteral("This is a Test2"), false)); { WingHex::WingDockWidgetInfo info; @@ -274,11 +265,6 @@ bool TestPlugin::init(const std::unique_ptr &set) { _evws.append(ev); } - { - auto pp = new TestPluginPage; - _plgps.append(pp); - } - _tmenu = new QMenu(QStringLiteral("TestPlugin")); auto micon = QIcon(QStringLiteral(":/images/TestPlugin/images/btn.png")); _tmenu->setIcon(micon); @@ -298,9 +284,8 @@ void TestPlugin::unload(std::unique_ptr &set) { // 设个数字,那就是 5 测试一下配置是否正常工作 set->setValue("Test", 5); - for (auto p = _setpages.constKeyValueBegin(); - p != _setpages.constKeyValueEnd(); ++p) { - p->first->deleteLater(); + for (auto &p : _setpages) { + p->deleteLater(); } for (auto &item : _winfo) { @@ -332,14 +317,10 @@ TestPlugin::registeredRibbonTools() const { return _rtbinfo; } -QHash TestPlugin::registeredSettingPages() const { +QList TestPlugin::registeredSettingPages() const { return _setpages; } -QList TestPlugin::registeredPages() const { - return _plgps; -} - QList> TestPlugin::registeredEditorViewWidgets() const { return _evws; diff --git a/TestPlugin/testplugin.h b/TestPlugin/testplugin.h index 7ceb437..8afad84 100644 --- a/TestPlugin/testplugin.h +++ b/TestPlugin/testplugin.h @@ -40,7 +40,6 @@ public: // IWingPlugin interface (必须) public: - virtual int sdkVersion() const override; virtual bool init(const std::unique_ptr &set) override; virtual void unload(std::unique_ptr &set) override; virtual const QString pluginName() const override; @@ -57,9 +56,8 @@ public: virtual QMenu *registeredHexContextMenu() const override; virtual QList registeredRibbonTools() const override; - virtual QHash + virtual QList registeredSettingPages() const override; - virtual QList registeredPages() const override; virtual QList> registeredEditorViewWidgets() const override; virtual QHash registeredScriptFns() const override; @@ -124,9 +122,8 @@ private: QHash _scriptInfo; QList _winfo; QList _rtbinfo; - QHash _setpages; + QList _setpages; QList> _evws; - QList _plgps; QHash _scriptUnsafe; }; diff --git a/TestPlugin/testpluginpage.h b/TestPlugin/testpluginpage.h deleted file mode 100644 index 404aad9..0000000 --- a/TestPlugin/testpluginpage.h +++ /dev/null @@ -1,43 +0,0 @@ -/*============================================================================== -** 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 TESTPLUGINPAGE_H -#define TESTPLUGINPAGE_H - -#include "WingPlugin/settingpage.h" - -#include - -class TestPluginPage : public WingHex::PluginPage { - Q_OBJECT -public: - explicit TestPluginPage(QWidget *parent = nullptr); - - // PageBase interface -public: - virtual QIcon categoryIcon() const override; - virtual QString name() const override; - virtual QString id() const override; - -private: - QLabel *_lbl = nullptr; -}; - -#endif // TESTPLUGINPAGE_H diff --git a/TestPlugin/testsettingpage.cpp b/TestPlugin/testsettingpage.cpp index 9dcc635..0b4b2ea 100644 --- a/TestPlugin/testsettingpage.cpp +++ b/TestPlugin/testsettingpage.cpp @@ -23,8 +23,8 @@ #include TestSettingPage::TestSettingPage(const QString &id, const QString &content, - QWidget *parent) - : WingHex::SettingPage(parent), _id(id) { + bool isShowInRibbon, QWidget *parent) + : WingHex::SettingPage(parent), _id(id), _isShownInRibbton(isShowInRibbon) { auto layout = new QVBoxLayout(this); _lbl = new QLabel(content, this); _lbl->setAlignment(Qt::AlignCenter); @@ -39,6 +39,8 @@ QString TestSettingPage::name() const { return _id; } QString TestSettingPage::id() const { return _id; } +bool TestSettingPage::showInRibbon() const { return _isShownInRibbton; } + void TestSettingPage::apply() {} void TestSettingPage::reset() {} diff --git a/TestPlugin/testsettingpage.h b/TestPlugin/testsettingpage.h index 319145a..a5892c9 100644 --- a/TestPlugin/testsettingpage.h +++ b/TestPlugin/testsettingpage.h @@ -29,7 +29,7 @@ class TestSettingPage : public WingHex::SettingPage { Q_OBJECT public: explicit TestSettingPage(const QString &id, const QString &content, - QWidget *parent = nullptr); + bool isShowInRibbon, QWidget *parent = nullptr); // PageBase interface public: @@ -37,6 +37,8 @@ public: virtual QString name() const override; virtual QString id() const override; + virtual bool showInRibbon() const override; + // SettingPage interface public: virtual void apply() override; @@ -45,7 +47,7 @@ public: private: QLabel *_lbl = nullptr; - + bool _isShownInRibbton; QString _id; }; diff --git a/WingPlugin b/WingPlugin index ad56540..ec5bcd4 160000 --- a/WingPlugin +++ b/WingPlugin @@ -1 +1 @@ -Subproject commit ad5654088ab1da66ad93713ef5933a603fb8e2a3 +Subproject commit ec5bcd41309e175aa262f367011c1ad9fe7e9b31 diff --git a/favicon.rc b/favicon.rc index 7870513..836f5ee 100644 --- a/favicon.rc +++ b/favicon.rc @@ -68,7 +68,7 @@ BEGIN BLOCK "080404b0" BEGIN VALUE "CompanyName", "ƹңWingCloudStudio" - VALUE "FileDescription", "һǿƽ̨ʮƱ༭" + VALUE "FileDescription", "ʮƱ༭" VALUE "FileVersion", "1.0.0" VALUE "InternalName", "WingHexExplorer2.exe" VALUE "LegalCopyright", "AGPL-3.0" diff --git a/images/monitor.png b/images/monitor.png new file mode 100644 index 0000000000000000000000000000000000000000..4229c6138ba23eb033a90a1d204b7ea31e423cf3 GIT binary patch literal 5774 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 M07*qoM6N<$g7A`>jQ{`u literal 0 HcmV?d00001 diff --git a/lang/zh_CN/winghex_zh_CN.ts b/lang/zh_CN/winghex_zh_CN.ts index b88c5be..8b3e057 100644 --- a/lang/zh_CN/winghex_zh_CN.ts +++ b/lang/zh_CN/winghex_zh_CN.ts @@ -937,8 +937,8 @@ - - + + CopyToClipBoard 数据已拷贝到粘贴板 @@ -978,8 +978,8 @@ - - + + BookMark 书签 @@ -1022,8 +1022,8 @@ - - + + Reload 重新加载 @@ -1140,7 +1140,7 @@ - + Fill 填充 @@ -1285,7 +1285,7 @@ 导出结果 - + NothingToSave 没有保存的数据 @@ -1482,7 +1482,7 @@ - + LayoutRestoring... 恢复布局中... @@ -1493,7 +1493,7 @@ - + SaveLayout 保存布局 @@ -1570,491 +1570,491 @@ 关于 QT - + SetPageIDEmptyTryUseName 设置页 ID 为空,尝试使用名称作为 ID - + SetPageDupNameIgnored 设置页重复的 ID 名称,已忽略加载 - + Plugin %1 contains a duplicate ID (%2) that is already registered by plugin %3 插件 %1 包含重复 ID (%2),该 ID 已被插件 %3 注册 - - + + ChooseFile 选择文件 - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + Error 错误 - - + + FileNotExist 文件不存在! - - - - - + + + + + FilePermission 因文件权限无法继续! - + ProjectFile (*.wingpro) 项目文件 (*.wingpro) - + ReloadSuccessfully 文件重新加载成功! - + ReloadUnSuccessfully 文件重新加载失败! - - - - + + + + ChooseSaveFile 请选择保存文件路径: - + PasteFailedNote 粘贴失败,请注意权限或者内容长度 - + NoMoreClone 克隆已到上限,无法继续操作! - + FindFininishBusy 查找任务繁忙,请勿重复查找! - + MayTooMuchFindResult 搜索数量已到达上限,结果可能不全,建议请按区段搜索。 - + SaveLayoutSuccess 保存布局成功 - + SaveLayoutError 保存布局失败 - + HasClonedView 该编辑页已被克隆编辑,如果关闭,相关联的页也会被关闭,你确认继续吗? - + FileCloseBigFile 大文件读取模式下目标文件被关闭,该标签将会被关闭。 - - + + ReloadNeededYesOrNo 目标文件被修改,是否重新加载? - + SaveWorkSpace 保存工作区 - + WingHexWorkSpace (*.wingpro) 羽云十六进制工作区 (*.wingpro) - + ConfirmSave 正在关闭未保存的文件或工作区,你确定保存吗? - + [Info] 【信息】 - + [Warn] 【警告】 - + [Error] 【错误】 - + ConfirmAPPSave 你尝试关闭程序,但仍存在未保存的文件或工作区,你确定保存这些更改吗? - - - + + + SaveSuccessfully 保存成功! - - + + SaveWSError 保存工作区错误! - - + + Warn 警告 - + Opening... 打开文件中... - + WorkSpaceOpening... 打开工作区中... - + Reloading... 重载文件中... - + Saving... 保存中... - + SaveNewFirst 请首先保存新建的文件 - + AlreadyWorkSpace 已经是工作区,无需转化 - + ConvWorkSpaceFailed 转化为工作区失败 - + ConvWorkSpaceSuccess 转化为工作区成功 - + SavingAs... 另存为中... - + SaveUnSuccessfully 保存失败! - + Exporting... 导出中... - + ChooseExportFile 请选择导出文件路径: - + ExportSuccessfully 导出成功! - + ExportUnSuccessfully 导出失败! - + SavingSel... 保存选中字节中... - + SaveSelSuccess 保存选区字节成功! - + SaveSelError 保存选区字节失败,因文件不具有可写权限! - - + + CutToClipBoard 数据已剪切到粘贴板! - - + + UnCutToClipBoard 由于保持大小限制,数据剪切到粘贴板失败! - - + + UnCopyToClipBoard 由于保持大小限制,数据剪切到复制板失败! - - + + Finding... 查找中... - + DeleteSuccess 删除成功 - + DeleteFailed 删除失败 - + FindFininish 查找结果完毕! - + PleaseInputFill 请输入填充字节值 - + FillInputTruncWarn 填充输入数值过大,将会被截断填充 - + FillInputError 填充字节输入错误 - - + + InputComment 请输入批注: - - + + BookmarkDelSuccess 删除书签成功 - + BookmarkDelNoItem 无书签可删除 - + BookmarkClearSuccess 书签清空完毕 - - - + + + NoSelection 没有选区,无法继续的操作! - + NoMetaData 无可编辑标记 - + PleaseClearSel 请清空选择 - + MetaDelSuccess 元数据删除成功 - + MetaDelNoItem 无元数据可删除 - + MetaClearSuccess 元数据清空完毕 - + FindResultExporting... 查找结果导出中... - - + + EmptyFindResult 没有可导出的搜索结果! - + SaveFindResult 导出搜索结果成功! - + SaveFindResultError 导出结果失败! - + TooManyBytesDecode 超出解码字节限制…… - + NoTextFileMayInvalid 该文件不是文本文件,以文本方式预览并不是一个好的方式,你确认继续吗? - + LayoutSaving... 布局保存中... - + PleaseInput 请输入 - + LogExporting... 日志导出中... - + ExportLogError 导出日志失败! - + ExportLogSuccess 导出日志成功,路径: - + ClearLogSuccess 清空日志成功! - + BadNetwork 无法与远程服务器的更新检查建立连接,请检查网络。 - + NewestVersion 当前软件为最新版本 - + OlderVersion 你使用的软件为老版本,建议到 Github 和 Gitee 的仓库发行版下载更新。 - + CheckingUpdate 检查更新中…… - + Too much opened files 打开的文件过多,无法继续操作! - + FilePermissionSure2Quit 因文件权限无法保存,你确认要退出吗? - + UnknownErrorSure2Quit 因未知错误无法保存,你确认要退出吗? - + WorkSpaceUnSavedSure2Quit 工作区文件无法保存,你确认要退出吗? - + CopyLimit 拷贝字节超出限制 - + ErrOpenFileBelow 打开文件出现错误(由于权限不足),如下为打开错误的文件: @@ -2214,70 +2214,87 @@ 设备插件: - + + APIMonitor + + + + Plugin 插件 - - + + + ID ID - - + + Name 名称 - - + + + License 协议 - - + + + Author 作者 - - + + + Vendor 厂家 - - + + + Version 版本 - - + + NoMonitorPlugin + + + + + + Comment 说明 - - + + + URL 网址 - + pluginDependencies: 插件依赖 - + PUID: 插件唯一标志符: - + Version: 版本: @@ -2285,200 +2302,205 @@ PluginSystem - + LoadingPlugin 加载插件中: - + + InvalidPluginBrokenInfo 加载插件失败:损坏的插件数据 - + + + PluginBlockByManager + + + + AppClosingCanceled: 程序关闭被取消: - + - PluginID: - 插件 ID: - + FoundDrvPluginCount 总计发现设备拓展插件数目: - + PluginManagerNeedSingleton - + RegisterScriptFnUnSupportedTypes: 因脚本函数含有未支持的类型而注册失败: - - + + RegisterScriptFnInvalidSig: 因脚本函数签名非法而注册失败: - - + + RegisterScriptFnConflitSig: 因脚本函数签名冲突而注册失败: - + InvalidEnumName: 非法枚举名: - + InvalidEnumValue: 非法枚举值: - + InvalidMarcosRegister: 非法宏注册: - + + ErrLoadPluginSDKVersion 插件加载失败:非法插件 SDK 版本! - + ErrLoadPluginNoName 插件加载失败:非法插件名称! - + + ErrLoadInitPlugin 插件加载失败:初始化插件失败! - + PluginName : 插件名: - + PluginAuthor : 插件作者: - + PluginWidgetRegister 注册插件对象中…… - - ErrLoadExtPluginSDKVersion - 设备拓展插件加载失败:非法插件 SDK 版本! - - - + ExtPluginAuthor : 设备拓展插件作者: - + ExtPluginWidgetRegister 设备拓展注册插件对象中…… - + ErrLoadInitExtPlugin 设备拓展插件加载失败:初始化插件失败! - + ChooseFile 选择文件 - - + + Error 错误 - + FileNotExist 文件不存在! - + FilePermission 因文件权限无法继续! - + EmptyNameDockWidget: 空的贴边组件名: - + InvalidNameDockWidget: 无效贴边组件名: - + InvalidNullDockWidget: 无效空贴边组件: - + Not allowed operation in non-UI thread 该操作在非 UI 线程非法 - + UnsafePluginDir 不安全的插件目录,请将插件目录设置为仅管理员账户可写 - + + InvalidPluginID 加载插件失败:非法插件标识符 - + InvalidDupPlugin 加载插件失败:重复的插件标识符 - + FoundPluginCount 总计发现插件数目: - + PluginLoadingFailedSummary 有依赖插件加载失败总结 - + - Dependencies: - 依赖: - + PUID: 插件唯一标志符: - + Version: 版本: - + PluginLoadingFinished 加载插件完毕! @@ -2486,7 +2508,7 @@ QApplication - + OptionNeedRestart 该设置需要程序重启后生效 @@ -5221,12 +5243,12 @@ SkinManager - + Dark 暗黑 - + Light 浅色 @@ -5242,28 +5264,28 @@ WingAngelAPI - + AngelScriptService AngelScript 服务 - + A internal plugin that provides AngelScript scripts with the ability to call the host API. 为 AngelScript 脚本提供调用主机 API 能力的内部插件。 - + NotSupportedQMetaType: 不支持的 QT 数据元类型: - - + + Get Exception While ScriptCall: (%1) %2 脚本调用发生异常:(%1)%2 - + InvalidRetType: need 无效返回值:需要 @@ -5271,41 +5293,41 @@ WingCStruct - + WingCStruct 羽云文件结构分析器 - + Providing basic support for analyzing file structures 提供基础的文件结构分析支持 - - - - - - - - - - - - - + + + + + + + + + + + + + InvalidParamsCount 非法参数个数 - - - - - - - - + + + + + + + + InvalidParam 非法参数 diff --git a/lang/zh_TW/winghex_zh_TW.ts b/lang/zh_TW/winghex_zh_TW.ts index 5e69cea..b456b1d 100644 --- a/lang/zh_TW/winghex_zh_TW.ts +++ b/lang/zh_TW/winghex_zh_TW.ts @@ -937,8 +937,8 @@ - - + + CopyToClipBoard 數據已拷貝到粘貼板 @@ -978,8 +978,8 @@ - - + + BookMark 書簽 @@ -1022,8 +1022,8 @@ - - + + Reload 重新加載 @@ -1140,7 +1140,7 @@ - + Fill 填充 @@ -1285,7 +1285,7 @@ 導出結果 - + NothingToSave 沒有保存的數據 @@ -1482,7 +1482,7 @@ - + LayoutRestoring... 恢復佈局中... @@ -1493,7 +1493,7 @@ - + SaveLayout 保存佈局 @@ -1570,491 +1570,491 @@ 關於 QT - + SetPageIDEmptyTryUseName 設置頁 ID 為空,嘗試使用名稱作為 ID - + SetPageDupNameIgnored 設置頁重複的 ID 名稱,已忽略加載 - + Plugin %1 contains a duplicate ID (%2) that is already registered by plugin %3 插件 %1 包含重複 ID (%2),該 ID 已被插件 %3 註冊 - - + + ChooseFile 選擇檔 - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + Error 錯誤 - - + + FileNotExist 檔不存在! - - - - - + + + + + FilePermission 因檔許可權無法繼續! - + ProjectFile (*.wingpro) 專案檔 (*.wingpro) - + ReloadSuccessfully 檔重新加載成功! - + ReloadUnSuccessfully 檔重新加載失敗! - - - - + + + + ChooseSaveFile 請選擇保存檔路徑: - + PasteFailedNote 粘貼失敗,請注意許可權或者內容長度 - + NoMoreClone 克隆已到上限,無法繼續操作! - + FindFininishBusy 查找任務繁忙,請勿重複查找! - + MayTooMuchFindResult 搜索數量已到達上限,結果可能不全,建議請按區段搜索。 - + SaveLayoutSuccess 保存佈局成功 - + SaveLayoutError 保存佈局失敗 - + HasClonedView 該編輯頁已被克隆編輯,如果關閉,相關聯的頁也會被關閉,你確認繼續嗎? - + FileCloseBigFile 大檔讀取模式下目的檔案被關閉,該標籤將會被關閉。 - - + + ReloadNeededYesOrNo 目的檔案被修改,是否重新載入? - + SaveWorkSpace 保存工作區 - + WingHexWorkSpace (*.wingpro) 羽雲十六進制工作區 (*.wingpro) - + ConfirmSave 正在關閉未保存的檔或工作區,你確定保存嗎? - + [Info] 【資訊】 - + [Warn] 【警告】 - + [Error] 【錯誤】 - + ConfirmAPPSave 你嘗試關閉程式,但仍存在未保存的檔或工作區,你確定保存這些更改嗎? - - - + + + SaveSuccessfully 保存成功! - - + + SaveWSError 保存工作區錯誤! - - + + Warn 警告 - + Opening... 打開檔中... - + WorkSpaceOpening... 打開工作區中... - + Reloading... 重載檔中... - + Saving... 保存中... - + SaveNewFirst 請首先保存新建的檔 - + AlreadyWorkSpace 已經是工作區,無需轉化 - + ConvWorkSpaceFailed 轉化為工作區失敗 - + ConvWorkSpaceSuccess 轉化為工作區成功 - + SavingAs... 另存為中... - + SaveUnSuccessfully 保存失敗! - + Exporting... 導出中... - + ChooseExportFile 請選擇導出檔路徑: - + ExportSuccessfully 導出成功! - + ExportUnSuccessfully 導出失敗! - + SavingSel... 保存選中位元組中... - + SaveSelSuccess 保存選區位元組成功! - + SaveSelError 保存選區位元組失敗,因檔不具有可寫許可權! - - + + CutToClipBoard 數據已剪切到粘貼板! - - + + UnCutToClipBoard 由於保持大小限制,數據剪切到粘貼板失敗! - - + + UnCopyToClipBoard 由於保持大小限制,數據剪切到複製板失敗! - - + + Finding... 查找中... - + DeleteSuccess 刪除成功 - + DeleteFailed 刪除失敗 - + FindFininish 查找結果完畢! - + PleaseInputFill 請輸入填充位元組值 - + FillInputTruncWarn 填充輸入數值過大,將會被截斷填充 - + FillInputError 填充位元組輸入錯誤 - - + + InputComment 請輸入批註: - - + + BookmarkDelSuccess 刪除書簽成功 - + BookmarkDelNoItem 無書簽可刪除 - + BookmarkClearSuccess 書簽清空完畢 - - - + + + NoSelection 沒有選區,無法繼續的操作! - + NoMetaData 無可編輯標記 - + PleaseClearSel 請清空選擇 - + MetaDelSuccess 元數據刪除成功 - + MetaDelNoItem 無元數據可刪除 - + MetaClearSuccess 元數據清空完畢 - + FindResultExporting... 查找結果導出中... - - + + EmptyFindResult 沒有可導出的搜索結果! - + SaveFindResult 導出搜索結果成功! - + SaveFindResultError 導出結果失敗! - + TooManyBytesDecode 超出解碼位元組限制…… - + NoTextFileMayInvalid 該檔不是文本檔,以文本方式預覽並不是一個好的方式,你確認繼續嗎? - + LayoutSaving... 佈局保存中... - + PleaseInput 請輸入 - + LogExporting... 日誌導出中... - + ExportLogError 導出日誌失敗! - + ExportLogSuccess 導出日誌成功,路徑: - + ClearLogSuccess 清空日誌成功! - + BadNetwork 無法與遠程伺服器的更新檢查建立連接,請檢查網路。 - + NewestVersion 當前軟體為最新版本 - + OlderVersion 你使用的軟體為老版本,建議到 Github 和 Gitee 的倉庫發行版下載更新。 - + CheckingUpdate 檢查更新中…… - + Too much opened files 打開的檔過多,無法繼續操作! - + FilePermissionSure2Quit 因檔許可權無法保存,你確認要退出嗎? - + UnknownErrorSure2Quit 因未知錯誤無法保存,你確認要退出嗎? - + WorkSpaceUnSavedSure2Quit 工作區檔無法保存,你確認要退出嗎? - + CopyLimit 拷貝位元組超出限制 - + ErrOpenFileBelow 打開檔出現錯誤(由於許可權不足),如下為打開錯誤的檔: @@ -2214,70 +2214,87 @@ 設備插件: - + + APIMonitor + + + + Plugin 插件 - - + + + ID ID - - + + Name 名稱 - - + + + License 協議 - - + + + Author 作者 - - + + + Vendor 廠家 - - + + + Version 版本 - - + + NoMonitorPlugin + + + + + + Comment 說明 - - + + + URL 網址 - + pluginDependencies: 插件依賴 - + PUID: 插件唯一標誌符: - + Version: 版本: @@ -2285,200 +2302,205 @@ PluginSystem - + LoadingPlugin 加載插件中: - + + InvalidPluginBrokenInfo 加載插件失敗:損壞的插件數據 - + + + PluginBlockByManager + + + + AppClosingCanceled: 程式關閉被取消: - + - PluginID: - 插件 ID: - + FoundDrvPluginCount 總計發現設備拓展插件數目: - + PluginManagerNeedSingleton - + RegisterScriptFnUnSupportedTypes: 因腳本函數含有未支持的類型而註冊失敗: - - + + RegisterScriptFnInvalidSig: 因腳本函數簽名非法而註冊失敗: - - + + RegisterScriptFnConflitSig: 因腳本函數簽名衝突而註冊失敗: - + InvalidEnumName: 非法枚舉名: - + InvalidEnumValue: 非法枚舉值: - + InvalidMarcosRegister: 非法宏註冊: - + + ErrLoadPluginSDKVersion 插件加載失敗:非法插件 SDK 版本! - + ErrLoadPluginNoName 插件加載失敗:非法插件名稱! - + + ErrLoadInitPlugin 插件加載失敗:初始化插件失敗! - + PluginName : 插件名: - + PluginAuthor : 插件作者: - + PluginWidgetRegister 註冊插件對象中…… - - ErrLoadExtPluginSDKVersion - 設備拓展插件加載失敗:非法插件 SDK 版本! - - - + ExtPluginAuthor : 設備拓展插件作者: - + ExtPluginWidgetRegister 設備拓展註冊插件對象中…… - + ErrLoadInitExtPlugin 設備拓展插件加載失敗:初始化插件失敗! - + ChooseFile 選擇檔 - - + + Error 錯誤 - + FileNotExist 檔不存在! - + FilePermission 因檔許可權無法繼續! - + EmptyNameDockWidget: 空的貼邊組件名: - + InvalidNameDockWidget: 無效貼邊組件名: - + InvalidNullDockWidget: 無效空貼邊組件: - + Not allowed operation in non-UI thread 該操作在非 UI 線程非法 - + UnsafePluginDir 不安全的插件目錄,請將插件目錄設置為僅管理員帳戶可寫 - + + InvalidPluginID 加載插件失敗:非法插件識別字 - + InvalidDupPlugin 加載插件失敗:重複的插件識別字 - + FoundPluginCount 總計發現插件數目: - + PluginLoadingFailedSummary 有依賴插件加載失敗總結 - + - Dependencies: - 依賴: - + PUID: 插件唯一標誌符: - + Version: 版本: - + PluginLoadingFinished 加載插件完畢! @@ -2486,7 +2508,7 @@ QApplication - + OptionNeedRestart 該設置需要程式重啟後生效 @@ -5221,12 +5243,12 @@ SkinManager - + Dark 暗黑 - + Light 淺色 @@ -5242,28 +5264,28 @@ WingAngelAPI - + AngelScriptService AngelScript 服務 - + A internal plugin that provides AngelScript scripts with the ability to call the host API. 為 AngelScript 腳本提供調用主機 API 能力的內部插件。 - + NotSupportedQMetaType: 不支持的 QT 數據元類型: - - + + Get Exception While ScriptCall: (%1) %2 腳本調用發生異常:(%1)%2 - + InvalidRetType: need 無效返回值:需要 @@ -5271,41 +5293,41 @@ WingCStruct - + WingCStruct 羽雲檔結構分析器 - + Providing basic support for analyzing file structures 提供基礎的檔結構分析支持 - - - - - - - - - - - - - + + + + + + + + + + + + + InvalidParamsCount 非法參數個數 - - - - - - - - + + + + + + + + InvalidParam 非法參數 diff --git a/resources.qrc b/resources.qrc index c385d16..5d8ded0 100644 --- a/resources.qrc +++ b/resources.qrc @@ -61,6 +61,7 @@ images/metadatah.png images/metahide.png images/metashow.png + images/monitor.png images/new.png images/open.png images/openapp.png diff --git a/src/class/WingAngelAPI.json b/src/class/WingAngelAPI.json index f481d7d..ee44e3a 100644 --- a/src/class/WingAngelAPI.json +++ b/src/class/WingAngelAPI.json @@ -1,5 +1,6 @@ { "Id": "WingAngelAPI", + "SDK": 18, "Author": "wingsummer", "Version": "2.2.2", "Vendor": "WingCloudStudio", diff --git a/src/class/WingCStruct.json b/src/class/WingCStruct.json index e8cd029..b98c71c 100644 --- a/src/class/WingCStruct.json +++ b/src/class/WingCStruct.json @@ -1,5 +1,6 @@ { "Id" : "WingCStruct", + "SDK": 18, "Version" : "0.0.2", "Vendor" : "WingCloudStudio", "Author" : "wingsummer", diff --git a/src/class/pluginsystem.cpp b/src/class/pluginsystem.cpp index b1a2eea..cd92ca4 100644 --- a/src/class/pluginsystem.cpp +++ b/src/class/pluginsystem.cpp @@ -2520,6 +2520,12 @@ bool PluginSystem::checkErrAllAllowAndReport(const QObject *sender, return false; } +const std::optional &PluginSystem::monitorManagerInfo() const { + return _manInfo; +} + +IWingManager *PluginSystem::monitorManager() const { return _manager; } + IWingPlugin *PluginSystem::checkPluginAndReport(const QObject *sender, const char *func) { Q_ASSERT(func); @@ -3075,8 +3081,8 @@ IWingDevice *PluginSystem::device(qsizetype index) const { } template -std::optional -PluginSystem::loadPlugin(const QFileInfo &fileinfo, const QDir &setdir) { +std::optional PluginSystem::loadPlugin(const QFileInfo &fileinfo, + const QDir &setdir) { Q_ASSERT(_win); if (fileinfo.exists()) { @@ -3090,7 +3096,7 @@ PluginSystem::loadPlugin(const QFileInfo &fileinfo, const QDir &setdir) { auto lmeta = loader.metaData(); PluginStatus cret; - std::optional meta; + std::optional meta; if (lmeta.contains("MetaData")) { auto m = parsePluginMetadata(lmeta["MetaData"].toObject()); cret = checkPluginMetadata(m, std::is_same_v); @@ -3116,13 +3122,25 @@ PluginSystem::loadPlugin(const QFileInfo &fileinfo, const QDir &setdir) { case PluginStatus::DupID: Logger::critical(tr("InvalidDupPlugin")); return std::nullopt; + case PluginStatus::SDKVersion: + Logger::critical(tr("ErrLoadPluginSDKVersion")); + return std::nullopt; + } + + auto m = meta.value(); + if (_manager) { + if (!_manager->onLoadingPlugin(fileName, m)) { + Logger::critical(QStringLiteral("{ ") + m.id + + QStringLiteral("} ") + + tr("PluginBlockByManager")); + return std::nullopt; + } } auto p = qobject_cast(loader.instance()); if (Q_UNLIKELY(p == nullptr)) { Logger::critical(loader.errorString()); } else { - auto m = meta.value(); retranslateMetadata(p, m); loadPlugin(p, m, setdir); } @@ -3196,11 +3214,11 @@ PluginSystem::assginHandleForPluginView(IWingPlugin *plg, EditorView *view) { return id; } -PluginSystem::PluginInfo -PluginSystem::parsePluginMetadata(const QJsonObject &meta) { - PluginSystem::PluginInfo info; +PluginInfo PluginSystem::parsePluginMetadata(const QJsonObject &meta) { + PluginInfo info; info.id = meta["Id"].toString().trimmed(); + info.SDKVersion = meta["SDK"].toInt(); info.version = QVersionNumber::fromString(meta["Version"].toString().trimmed()); @@ -3238,6 +3256,10 @@ PluginSystem::PluginStatus PluginSystem::checkPluginMetadata(const PluginInfo &meta, bool isPlg) { constexpr auto puid_limit = 36; // same as uuid length, so enough + if (meta.SDKVersion != SDKVERSION) { + return PluginStatus::SDKVersion; + } + if (meta.id.length() > puid_limit) { return PluginStatus::InvalidID; } @@ -3560,8 +3582,7 @@ IWingDevice *PluginSystem::ext2Device(const QString &ext) { return *r; } -PluginSystem::PluginInfo -PluginSystem::getPluginInfo(IWingPluginBase *plg) const { +PluginInfo PluginSystem::getPluginInfo(IWingPluginBase *plg) const { Q_ASSERT(plg); return _pinfos.value(plg); } @@ -3596,7 +3617,7 @@ void PluginSystem::loadExtPlugin() { loadPlugin(item, udir); } - QList errorplg; + QList errorplg; if (!_lazyplgs.isEmpty()) { QStringList lazyplgs; lazyplgs.swap(_lazyplgs); @@ -3687,18 +3708,59 @@ void PluginSystem::try2LoadManagerPlugin() { auto lmeta = loader.metaData(); auto m = parsePluginMetadata(lmeta["MetaData"].toObject()); - // ID should not be empty - if (m.id.isEmpty()) { + auto cret = checkPluginMetadata(m, false); + + switch (cret) { + case PluginStatus::Valid: + break; + case PluginStatus::SDKVersion: + Logger::critical(tr("ErrLoadPluginSDKVersion")); + return; + case PluginStatus::InvalidID: + Logger::critical(tr("InvalidPluginID")); + return; + case PluginStatus::BrokenVersion: + Logger::critical(tr("InvalidPluginBrokenInfo")); + return; + case PluginStatus::DupID: + case PluginStatus::LackDependencies: + // monitor is the first plugin to load and + // should not have any dependency + Q_ASSERT(false); return; } auto p = qobject_cast(loader.instance()); if (p) { + QDir udir(Utilities::getAppDataPath()); + auto plgset = QStringLiteral("plgset"); + udir.mkdir(plgset); + if (!udir.cd(plgset)) { + throw CrashCode::PluginSetting; + } + + auto setp = std::make_unique(udir.absoluteFilePath(m.id), + QSettings::Format::IniFormat); + + if (!p->init(setp)) { + setp->deleteLater(); + Logger::critical(tr("ErrLoadInitPlugin")); + return; + } + applyFunctionTables(p, _plgFns); _manager = p; + + // translate the meta-data + m.author = p->retranslate(m.author); + m.vendor = p->retranslate(m.vendor); + m.license = p->retranslate(m.license); + _manInfo = m; - // TODO + registerRibbonTools(p->registeredRibbonTools()); + registeredSettingPages(QVariant::fromValue(p), + p->registeredSettingPages()); } } @@ -4160,10 +4222,6 @@ void PluginSystem::loadPlugin(IWingPlugin *p, PluginInfo &meta, QTranslator *p_tr = nullptr; try { - if (p->sdkVersion() != SDKVERSION) { - throw tr("ErrLoadPluginSDKVersion"); - } - if (!p->pluginName().trimmed().length()) { throw tr("ErrLoadPluginNoName"); } @@ -4193,61 +4251,12 @@ void PluginSystem::loadPlugin(IWingPlugin *p, PluginInfo &meta, _loadedplgs.append(p); _pinfos.insert(p, meta); - Logger::warning(tr("PluginName :") + p->pluginName()); - Logger::warning(tr("PluginAuthor :") + meta.author); - Logger::warning(tr("PluginWidgetRegister")); + Logger::info(tr("PluginName :") + p->pluginName()); + Logger::debug(tr("PluginAuthor :") + meta.author); + Logger::debug(tr("PluginWidgetRegister")); // ensure call only once - auto ribbonToolboxInfos = p->registeredRibbonTools(); - if (!ribbonToolboxInfos.isEmpty()) { - for (auto &item : ribbonToolboxInfos) { - if (_win->m_ribbonMaps.contains(item.catagory)) { - if (!item.toolboxs.isEmpty()) { - auto &cat = _win->m_ribbonMaps[item.catagory]; - for (auto &group : item.toolboxs) { - if (group.tools.isEmpty()) { - continue; - } - auto g = cat->addGroup(group.name); - for (auto &tool : group.tools) { - g->addButton(tool); - } - } - } - } else { - if (!item.toolboxs.isEmpty()) { - 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()) { - continue; - } - auto g = cat->addGroup(group.name); - for (auto &tool : group.tools) { - g->addButton(tool); - } - hasAdded = true; - } - if (!isSys) { - if (hasAdded) { - _win->m_ribbon->addTab(cat, item.displayName); - _win->m_ribbonMaps[item.catagory] = cat; - } else { - delete cat; - } - } - } - } - } - } - + registerRibbonTools(p->registeredRibbonTools()); registerPluginDockWidgets(p); { @@ -4264,18 +4273,8 @@ void PluginSystem::loadPlugin(IWingPlugin *p, PluginInfo &meta, } } - { - auto sp = p->registeredSettingPages(); - if (!sp.isEmpty()) { - for (auto page = sp.keyBegin(); page != sp.keyEnd(); ++page) { - auto pp = *page; - pp->setProperty("__plg__", QVariant::fromValue(p)); - } - _win->m_settingPages.insert(sp); - } - } - - registerPluginPages(p); + registeredSettingPages(QVariant::fromValue(p), + p->registeredSettingPages()); registerFns(p); registerEnums(p); @@ -4298,12 +4297,8 @@ void PluginSystem::loadPlugin(IWingDevice *p, PluginInfo &meta, QTranslator *p_tr = nullptr; try { - if (p->sdkVersion() != SDKVERSION) { - throw tr("ErrLoadExtPluginSDKVersion"); - } - - Logger::warning(tr("ExtPluginAuthor :") + meta.author); - Logger::warning(tr("ExtPluginWidgetRegister")); + Logger::debug(tr("ExtPluginAuthor :") + meta.author); + Logger::debug(tr("ExtPluginWidgetRegister")); p_tr = LanguageManager::instance().try2LoadPluginLang(meta.id); @@ -4326,7 +4321,6 @@ void PluginSystem::loadPlugin(IWingDevice *p, PluginInfo &meta, _loadeddevs.append(p); _pinfos.insert(p, meta); - registerPluginPages(p); registerMarcoDevice(p); // ok register into menu open @@ -4454,22 +4448,74 @@ void PluginSystem::registerPluginDockWidgets(IWingPluginBase *p) { } } -void PluginSystem::registerPluginPages(IWingPluginBase *p) { - auto rp = p->registeredPages(); - if (!rp.isEmpty()) { - for (auto &page : rp) { - page->setProperty("__plg__", QVariant::fromValue(p)); - } - _win->m_plgPages.append(rp); - } -} - void PluginSystem::registerMarcoDevice(IWingDevice *plg) { auto id = getPUID(plg).toUpper(); auto sep = QStringLiteral("_"); _scriptMarcos.append(sep + id + sep); } +void PluginSystem::registerRibbonTools( + const QList &tools) { + if (!tools.isEmpty()) { + for (auto &item : tools) { + if (_win->m_ribbonMaps.contains(item.catagory)) { + if (!item.toolboxs.isEmpty()) { + auto &cat = _win->m_ribbonMaps[item.catagory]; + for (auto &group : item.toolboxs) { + if (group.tools.isEmpty()) { + continue; + } + auto g = cat->addGroup(group.name); + for (auto &tool : group.tools) { + g->addButton(tool); + } + } + } + } else { + if (!item.toolboxs.isEmpty()) { + 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()) { + continue; + } + auto g = cat->addGroup(group.name); + for (auto &tool : group.tools) { + g->addButton(tool); + } + hasAdded = true; + } + if (!isSys) { + if (hasAdded) { + _win->m_ribbon->addTab(cat, item.displayName); + _win->m_ribbonMaps[item.catagory] = cat; + } else { + delete cat; + } + } + } + } + } + } +} + +void PluginSystem::registeredSettingPages(const QVariant &itptr, + const QList &pages) { + if (!pages.isEmpty()) { + for (auto &page : pages) { + page->setProperty("__plg__", itptr); + } + _win->m_settingPages.append(pages); + } +} + bool PluginSystem::checkThreadAff() { if (QThread::currentThread() != qApp->thread()) { Logger::warning(tr("Not allowed operation in non-UI thread")); @@ -4497,6 +4543,7 @@ void PluginSystem::loadAllPlugin() { try2LoadManagerPlugin(); auto &set = SettingManager::instance(); + // manager plugin can not block WingAngelAPI, only settings if (set.scriptEnabled()) { _angelplg = new WingAngelAPI; @@ -4520,7 +4567,6 @@ void PluginSystem::loadAllPlugin() { initCheckingEngine(); { - auto cstructplg = new WingCStruct; QFile cstructjson(QStringLiteral( ":/com.wingsummer.winghex/src/class/WingCStruct.json")); auto ret = cstructjson.open(QFile::ReadOnly); @@ -4532,16 +4578,23 @@ void PluginSystem::loadAllPlugin() { QJsonDocument doc = QJsonDocument::fromJson(cstruct); auto meta = parsePluginMetadata(doc.object()); - QDir setd(Utilities::getAppDataPath()); - auto plgset = QStringLiteral("plgset"); - setd.mkdir(plgset); - retranslateMetadata(cstructplg, meta); - loadPlugin(cstructplg, meta, setd); + // internal plugin has no filename + if (_manager->onLoadingPlugin({}, meta)) { + auto cstructplg = new WingCStruct; + QDir setd(Utilities::getAppDataPath()); + auto plgset = QStringLiteral("plgset"); + setd.mkdir(plgset); + retranslateMetadata(cstructplg, meta); + loadPlugin(cstructplg, meta, setd); + } else { + Logger::critical(QStringLiteral("{ ") + meta.id + + QStringLiteral("} ") + tr("PluginBlockByManager")); + } } Logger::newLine(); - bool ok; + bool ok = false; auto disAll = qEnvironmentVariableIntValue("WING_DISABLE_PLUGIN_SYSTEM", &ok); @@ -4603,6 +4656,13 @@ void PluginSystem::destory() { delete item; } _loadeddevs.clear(); + + if (_manager && _manInfo) { + auto set = std::make_unique( + udir.absoluteFilePath(_manInfo->id), QSettings::Format::IniFormat); + _manager->unload(set); + delete _manager; + } } EditorView *PluginSystem::pluginCurrentEditor(IWingPlugin *plg) const { diff --git a/src/class/pluginsystem.h b/src/class/pluginsystem.h index 4721511..070beeb 100644 --- a/src/class/pluginsystem.h +++ b/src/class/pluginsystem.h @@ -103,18 +103,9 @@ private: QExplicitlySharedDataPointer; public: - struct PluginInfo { - QString id; - QVersionNumber version; - QString vendor; - QList dependencies; - QString author; - QString license; - QString url; - }; - enum class PluginStatus { Valid, + SDKVersion, BrokenVersion, InvalidID, DupID, @@ -257,13 +248,19 @@ private: void registerMarcoDevice(IWingDevice *plg); private: + void registerRibbonTools(const QList &tools); + void registeredSettingPages(const QVariant &itptr, + const QList &pages); void registerPluginDockWidgets(IWingPluginBase *p); - void registerPluginPages(IWingPluginBase *p); public: // fpr crash checking QString currentLoadingPlugin() const; + IWingManager *monitorManager() const; + + const std::optional &monitorManagerInfo() const; + private: template T readBasicTypeContent(IWingPlugin *plg, qsizetype offset) { diff --git a/src/class/skinmanager.cpp b/src/class/skinmanager.cpp index fe257e3..57904fc 100644 --- a/src/class/skinmanager.cpp +++ b/src/class/skinmanager.cpp @@ -59,18 +59,35 @@ SkinManager &SkinManager::instance() { return instance; } -void SkinManager::setTheme(SkinManager::Theme theme) { m_theme = theme; } +void SkinManager::setTheme(SkinManager::Theme theme) { + if (m_theme != theme) { + m_theme = theme; + m_cache.clear(); + } +} QIcon SkinManager::themeIcon(const QString &name) { - switch (m_theme) { - case Theme::Dark: - return QIcon(QStringLiteral("://dark/") + name + - QStringLiteral(".svg")); - case Theme::Light: - return QIcon(QStringLiteral("://light/") + name + - QStringLiteral(".svg")); + auto picon = m_cache.find(name); + if (picon == m_cache.end()) { + switch (m_theme) { + case Theme::Dark: { + QIcon icon(QStringLiteral("://dark/") + name + + QStringLiteral(".svg")); + m_cache.insert(name, icon); + return icon; + } + case Theme::Light: { + QIcon icon(QStringLiteral("://light/") + name + + QStringLiteral(".svg")); + m_cache.insert(name, icon); + return icon; + } + default: + return {}; + } + } else { + return *picon; } - return {}; } SkinManager::Theme SkinManager::currentTheme() const { return m_theme; } diff --git a/src/class/skinmanager.h b/src/class/skinmanager.h index e0484d0..2dc9a7a 100644 --- a/src/class/skinmanager.h +++ b/src/class/skinmanager.h @@ -48,6 +48,8 @@ private: private: Theme m_theme; + QHash m_cache; + explicit SkinManager(); Q_DISABLE_COPY_MOVE(SkinManager) diff --git a/src/class/wingangelapi.cpp b/src/class/wingangelapi.cpp index 87c69f5..ca61051 100644 --- a/src/class/wingangelapi.cpp +++ b/src/class/wingangelapi.cpp @@ -44,8 +44,6 @@ WingAngelAPI::WingAngelAPI() { WingAngelAPI::~WingAngelAPI() {} -int WingAngelAPI::sdkVersion() const { return WingHex::SDKVERSION; } - bool WingAngelAPI::init(const std::unique_ptr &set) { Q_UNUSED(set); return true; diff --git a/src/class/wingangelapi.h b/src/class/wingangelapi.h index 3e49fac..a0bb6af 100644 --- a/src/class/wingangelapi.h +++ b/src/class/wingangelapi.h @@ -39,7 +39,6 @@ public: // IWingPlugin interface public: - virtual int sdkVersion() const override; virtual bool init(const std::unique_ptr &set) override; virtual void unload(std::unique_ptr &set) override; virtual const QString pluginName() const override; diff --git a/src/class/wingcstruct.cpp b/src/class/wingcstruct.cpp index 240d560..2d019fd 100644 --- a/src/class/wingcstruct.cpp +++ b/src/class/wingcstruct.cpp @@ -178,8 +178,6 @@ WingCStruct::WingCStruct() : WingHex::IWingPlugin() { WingCStruct::~WingCStruct() {} -int WingCStruct::sdkVersion() const { return WingHex::SDKVERSION; } - bool WingCStruct::init(const std::unique_ptr &set) { Q_UNUSED(set); resetEnv(); @@ -211,8 +209,7 @@ WingCStruct::RegisteredEvents WingCStruct::registeredEvents() const { return evs; } -QHash -WingCStruct::registeredSettingPages() const { +QList WingCStruct::registeredSettingPages() const { return _setpgs; } diff --git a/src/class/wingcstruct.h b/src/class/wingcstruct.h index 1609fda..2d75326 100644 --- a/src/class/wingcstruct.h +++ b/src/class/wingcstruct.h @@ -35,7 +35,6 @@ public: // IWingPluginBase interface public: - virtual int sdkVersion() const override; virtual bool init(const std::unique_ptr &set) override; virtual void unload(std::unique_ptr &set) override; virtual const QString pluginName() const override; @@ -47,7 +46,7 @@ public: // IWingPlugin interface public: virtual RegisteredEvents registeredEvents() const override; - virtual QHash + virtual QList registeredSettingPages() const override; virtual QHash registeredScriptFns() const override; virtual bool eventOnScriptPragma(const QString &script, @@ -118,7 +117,7 @@ private: private: CTypeParser _parser; - QHash _setpgs; + QList _setpgs; QHash _scriptInfo; QHash _scriptUnsafe; }; diff --git a/src/dialog/mainwindow.cpp b/src/dialog/mainwindow.cpp index 12c6a9a..b140fd4 100644 --- a/src/dialog/mainwindow.cpp +++ b/src/dialog/mainwindow.cpp @@ -1637,7 +1637,6 @@ void MainWindow::buildUpSettingDialog() { auto plgPage = new PluginSettingDialog(m_setdialog); connect(plgPage, &SettingPage::optionNeedRestartChanged, m_setdialog, &SettingDialog::toastTakeEffectReboot); - plgPage->buildUp(m_plgPages); m_setdialog->addPage(plgPage); id = plgPage->id(); Q_ASSERT(!id.isEmpty()); @@ -1662,9 +1661,7 @@ void MainWindow::buildUpSettingDialog() { usedIDs.append(id); qApp->processEvents(); - for (auto page_p = m_settingPages.constKeyValueBegin(); - page_p != m_settingPages.constKeyValueEnd(); ++page_p) { - auto page = page_p->first; + for (auto &page : m_settingPages) { auto name = page->name(); auto id = page->id(); @@ -1690,7 +1687,7 @@ void MainWindow::buildUpSettingDialog() { connect(page, &SettingPage::optionNeedRestartChanged, m_setdialog, &SettingDialog::toastTakeEffectReboot); m_setdialog->addPage(page); - if (page_p->second) { + if (page->showInRibbon()) { auto icon = page->categoryIcon(); addPannelAction(m_pluginSettingsGroup, icon, name, [=] { m_setdialog->showConfig(id); }); diff --git a/src/dialog/mainwindow.h b/src/dialog/mainwindow.h index 2a2283e..cee8132 100644 --- a/src/dialog/mainwindow.h +++ b/src/dialog/mainwindow.h @@ -564,8 +564,7 @@ private: QList m_hexContextMenu; QHash>> m_editorViewWidgets; - QHash m_settingPages; - QList m_plgPages; + QList m_settingPages; // these variables will be invalid after restoring state ads::CDockAreaWidget *m_leftViewArea = nullptr; diff --git a/src/settings/pluginsettingdialog.cpp b/src/settings/pluginsettingdialog.cpp index f48d39f..0d219db 100644 --- a/src/settings/pluginsettingdialog.cpp +++ b/src/settings/pluginsettingdialog.cpp @@ -18,7 +18,6 @@ #include "pluginsettingdialog.h" #include "class/pluginsystem.h" #include "class/settingmanager.h" -#include "dbghelper.h" #include "ui_pluginsettingdialog.h" #include "utilities.h" @@ -48,6 +47,7 @@ PluginSettingDialog::PluginSettingDialog(QWidget *parent) auto &plgsys = PluginSystem::instance(); auto pico = ICONRES("plugin"); ui->plglist->clear(); + for (auto &p : plgsys.plugins()) { auto pco = p->pluginIcon(); ui->plglist->addItem( @@ -63,17 +63,32 @@ PluginSettingDialog::PluginSettingDialog(QWidget *parent) new QListWidgetItem(pco.isNull() ? pico : pco, d->pluginName())); } ui->txtd->clear(); + + auto minfo = plgsys.monitorManagerInfo(); + if (minfo) { + auto sep = QStringLiteral(" : "); + + ui->txtm->append(getWrappedText(tr("ID") + sep + minfo->id)); + ui->txtm->append(getWrappedText(tr("License") + sep + minfo->license)); + ui->txtm->append(getWrappedText(tr("Author") + sep + minfo->author)); + ui->txtm->append(getWrappedText(tr("Vendor") + sep + minfo->vendor)); + ui->txtm->append( + getWrappedText(tr("Version") + sep + minfo->version.toString())); + ui->txtm->append(getWrappedText( + tr("URL") + sep + QStringLiteral("url + + QStringLiteral("\">") + minfo->url + QStringLiteral(""))); + ui->txtm->append(getWrappedText(tr("Comment") + sep)); + auto p = plgsys.monitorManager(); + if (p) { + ui->txtm->append(getWrappedText(p->comment())); + } + } else { + ui->txtm->setText(tr("NoMonitorPlugin")); + } } PluginSettingDialog::~PluginSettingDialog() { delete ui; } -void PluginSettingDialog::buildUp(const QList &pages) { - ASSERT_SINGLETON; - for (auto &page : pages) { - ui->tabWidget->addTab(page, page->categoryIcon(), page->name()); - } -} - void PluginSettingDialog::reload() { this->blockSignals(true); auto &set = SettingManager::instance(); @@ -112,17 +127,18 @@ void PluginSettingDialog::on_devlist_currentRowChanged(int currentRow) { auto info = plgsys.getPluginInfo(plg); ui->txtd->clear(); - ui->txtd->append(getWrappedText(tr("ID") + " : " + info.id)); - ui->txtd->append(getWrappedText(tr("Name") + " : " + plg->pluginName())); - ui->txtd->append(getWrappedText(tr("License") + " : " + info.license)); - ui->txtd->append(getWrappedText(tr("Author") + " : " + info.author)); - ui->txtd->append(getWrappedText(tr("Vendor") + " : " + info.vendor)); + static auto sep = QStringLiteral(" : "); + ui->txtd->append(getWrappedText(tr("ID") + sep + info.id)); + ui->txtd->append(getWrappedText(tr("Name") + sep + plg->pluginName())); + ui->txtd->append(getWrappedText(tr("License") + sep + info.license)); + ui->txtd->append(getWrappedText(tr("Author") + sep + info.author)); + ui->txtd->append(getWrappedText(tr("Vendor") + sep + info.vendor)); ui->txtd->append( - getWrappedText(tr("Version") + " : " + info.version.toString())); + getWrappedText(tr("Version") + sep + info.version.toString())); ui->txtd->append( - getWrappedText(tr("Comment") + " : " + plg->pluginComment())); + getWrappedText(tr("Comment") + sep + plg->pluginComment())); ui->txtd->append(getWrappedText( - tr("URL") + " : " + QStringLiteral("") + info.url + QStringLiteral(""))); } @@ -136,16 +152,16 @@ void PluginSettingDialog::on_plglist_currentRowChanged(int currentRow) { auto info = plgsys.getPluginInfo(plg); ui->txtc->clear(); - - ui->txtc->append(getWrappedText(tr("ID") + " : " + info.id)); - ui->txtc->append(getWrappedText(tr("Name") + " : " + plg->pluginName())); - ui->txtc->append(getWrappedText(tr("License") + " : " + info.license)); - ui->txtc->append(getWrappedText(tr("Author") + " : " + info.author)); - ui->txtc->append(getWrappedText(tr("Vendor") + " : " + info.vendor)); + static auto sep = QStringLiteral(" : "); + ui->txtc->append(getWrappedText(tr("ID") + sep + info.id)); + ui->txtc->append(getWrappedText(tr("Name") + sep + plg->pluginName())); + ui->txtc->append(getWrappedText(tr("License") + sep + info.license)); + ui->txtc->append(getWrappedText(tr("Author") + sep + info.author)); + ui->txtc->append(getWrappedText(tr("Vendor") + sep + info.vendor)); ui->txtc->append( - getWrappedText(tr("Version") + " : " + info.version.toString())); + getWrappedText(tr("Version") + sep + info.version.toString())); ui->txtc->append( - getWrappedText(tr("Comment") + " : " + plg->pluginComment())); + getWrappedText(tr("Comment") + sep + plg->pluginComment())); if (!info.dependencies.isEmpty()) { ui->txtc->append(getWrappedText(tr("pluginDependencies:"))); for (auto &d : info.dependencies) { @@ -156,7 +172,7 @@ void PluginSettingDialog::on_plglist_currentRowChanged(int currentRow) { } } ui->txtc->append(getWrappedText( - tr("URL") + " : " + QStringLiteral("") + info.url + QStringLiteral(" "))); } diff --git a/src/settings/pluginsettingdialog.h b/src/settings/pluginsettingdialog.h index a957106..ff1ac3b 100644 --- a/src/settings/pluginsettingdialog.h +++ b/src/settings/pluginsettingdialog.h @@ -32,8 +32,6 @@ public: explicit PluginSettingDialog(QWidget *parent = nullptr); ~PluginSettingDialog(); - void buildUp(const QList &pages); - private: Ui::PluginSettingDialog *ui; diff --git a/src/settings/pluginsettingdialog.ui b/src/settings/pluginsettingdialog.ui index 9f3bbe1..f9cd276 100644 --- a/src/settings/pluginsettingdialog.ui +++ b/src/settings/pluginsettingdialog.ui @@ -167,6 +167,24 @@ + + + + :/com.wingsummer.winghex/images/monitor.png:/com.wingsummer.winghex/images/monitor.png + + + APIMonitor + + + + + + true + + + + + diff --git a/src/utilities.h b/src/utilities.h index 536c54d..ebfda9b 100644 --- a/src/utilities.h +++ b/src/utilities.h @@ -57,7 +57,15 @@ Q_DECL_UNUSED static inline QString NAMEICONRES(const QString &name) { } Q_DECL_UNUSED static inline QIcon ICONRES(const QString &name) { - return QIcon(NAMEICONRES(name)); + static QHash cache; + auto picon = cache.find(name); + if (picon == cache.end()) { + QIcon icon(NAMEICONRES(name)); + cache.insert(name, icon); + return icon; + } else { + return *picon; + } } class Utilities {