diff --git a/3rdparty/QHexView/qhexview.cpp b/3rdparty/QHexView/qhexview.cpp index 4b8d181..413475b 100644 --- a/3rdparty/QHexView/qhexview.cpp +++ b/3rdparty/QHexView/qhexview.cpp @@ -176,7 +176,7 @@ QHexView::QHexView(QWidget *parent) QHexDocument::fromMemory(QByteArray(), false))); } -QHexView::~QHexView() {} +QHexView::~QHexView() { m_blinktimer->stop(); } QSharedPointer QHexView::document() { return m_document; } diff --git a/3rdparty/qtsingleapplication/src/qtsingleapplication.cpp b/3rdparty/qtsingleapplication/src/qtsingleapplication.cpp index 63aa7b1..59ade68 100644 --- a/3rdparty/qtsingleapplication/src/qtsingleapplication.cpp +++ b/3rdparty/qtsingleapplication/src/qtsingleapplication.cpp @@ -121,31 +121,12 @@ void QtSingleApplication::sysInit(const QString &appId) { } /*! - Creates a QtSingleApplication object. The application identifier - will be QCoreApplication::applicationFilePath(). \a argc, \a - argv, and \a GUIenabled are passed on to the QAppliation constructor. - - If you are creating a console application (i.e. setting \a - GUIenabled to false), you may consider using - QtSingleCoreApplication instead. + Creates a QtSingleApplication object. */ -QtSingleApplication::QtSingleApplication(int &argc, char **argv, - bool GUIenabled) - : QApplication(argc, argv, GUIenabled) { - sysInit(genBlockServerName()); -} - -/*! - Creates a QtSingleApplication object with the application - identifier \a appId. \a argc and \a argv are passed on to the - QAppliation constructor. -*/ - -QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, - char **argv) +QtSingleApplication::QtSingleApplication(int &argc, char **argv) : QApplication(argc, argv) { - sysInit(appId); + sysInit(genBlockServerName()); } /*! diff --git a/3rdparty/qtsingleapplication/src/qtsingleapplication.h b/3rdparty/qtsingleapplication/src/qtsingleapplication.h index f494cbf..c5939f4 100644 --- a/3rdparty/qtsingleapplication/src/qtsingleapplication.h +++ b/3rdparty/qtsingleapplication/src/qtsingleapplication.h @@ -12,9 +12,7 @@ class QtSingleApplication : public QApplication { Q_OBJECT public: - explicit QtSingleApplication(int &argc, char **argv, - bool GUIenabled = true); - explicit QtSingleApplication(const QString &id, int &argc, char **argv); + explicit QtSingleApplication(int &argc, char **argv); public: bool isRunning(); diff --git a/README.md b/README.md index c7e1c6c..be894b4 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,6 @@ - [有关仓库](#有关仓库) - [WIKI](#wiki) - [插件库](#插件库) -- [应用商店](#应用商店) --- @@ -33,7 +32,6 @@

-

- 开源不易,给个 Star 或者 [捐助](#捐助) 吧 @@ -95,6 +93,10 @@ > 对于 Qt 5 版本,仅支持 5.15.2 或更高版本,Qt 6 的话 6.6.2 或更高的版本,其他低版本由于关键库的 API 缺失和自身的一些 Bug,所以不提供支持。 +另外: + +> QT5 版本主动编译支持将会在 2025/05/26 停止,届时相关 GitAction 自动化测试将会撤销。如果因特殊需要 QT5 版本,请咨询我商业合作和付费技术支持。 +   该仓库代码使用 Qt 5.15.2 和 6.6.2 在最新版 Windows 和 Ubuntu 编译情况: ![Status](https://github.com/Wing-summer/WingHexExplorer2/actions/workflows/qt-build-test.yml/badge.svg) ## WingHexExplorer2 @@ -107,7 +109,7 @@   如果你想将本软件的代码用于闭源的商业代码,想要解除`GPL`系列的必须开源的限制,请必须亲自咨询我,商讨商业授权相关事宜。 -  对于插件开发相关的,对应的开源协议就不一样了。只针对本仓库下的`src/plugin/iwingplugin.h`和`src/plugin/settingpage.h`遵守`BSD 3-Clause`协议,以允许想要做闭源和商业开发。对于本仓库下的`TestPlugin`的代码(除`TranslationUtils.cmake`这一个文件遵守`BSD 3-Clause`)遵守`MIT`协议。 +  对于插件开发相关的,对应的开源协议就不一样了。只针对本仓库下的`src/plugin/iwingplugin.h`、`src/plugin/iwingpluginbase.h`、`src/plugin/iwingdevice.h`和`src/plugin/settingpage.h`遵守`BSD 3-Clause`协议,以允许想要做闭源和商业开发。对于本仓库下的`TestPlugin`的代码(除`TranslationUtils.cmake`这一个文件遵守`BSD 3-Clause`)遵守`MIT`协议。 ### 使用声明 @@ -176,8 +178,5 @@ ## 插件库 -> 敬请期待 - -## 应用商店 - -> 敬请期待 +- [WingAsm](https://github.com/Wing-summer/WingAsm) : 一个提供汇编和反汇编的插件,作者 **寂静的羽夏** ,协议 **APGL-v3.0** 。 +- [WingCStruct](https://github.com/Wing-summer/WingCStruct) : 一个提供分析文件结构基础支持的插件,作者 **寂静的羽夏** ,协议 **APGL-v3.0** 。 diff --git a/README_en.md b/README_en.md index fa77b2e..23051de 100644 --- a/README_en.md +++ b/README_en.md @@ -14,7 +14,6 @@ - [Related Repository](#related-repository) - [WIKI](#wiki) - [Plugins](#plugins) -- [App Store](#app-store) --- @@ -33,7 +32,6 @@

-

- Not easy to open source, please Star or [Donate](#donate) @@ -95,6 +93,10 @@ Make sure that you follow [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) while contrib > For Qt 5, only version 5.15.2 or higher is supported, and for Qt 6, only version 6.6.2 or higher is supported. Other lower versions are not supported due to missing APIs of key libraries and some bugs of their own. +And also: + +> Active compilation support for QT5 will be discontinued on 2025/05/26, and the related GitAction automated tests will be revoked at that time. If you need QT5 version for special purposes, please consult me ​​for commercial cooperation and paid technical support. + The repository code compiles with Qt 5.15.2 and 6.6.2 on the latest versions of Windows and Ubuntu: ![Status](https://github.com/Wing-summer/WingHexExplorer2/actions/workflows/qt-build-test.yml/badge.svg) ## WingHexExplorer2 @@ -107,7 +109,7 @@ 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. +For plugin development, the corresponding open source agreements are different. Only `src/plugin/iwingplugin.h`, `src/plugin/iwingpluginbase.h`, `src/plugin/iwingdevice.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 @@ -169,7 +171,7 @@ Of course, there are other repositories as mirror for Chinese users (which will - Gitee: - Gitlink: -- GitCode:I don't consider it, because "stealing code". +- GitCode:I don't consider it, because of "stealing code". ## WIKI @@ -177,8 +179,5 @@ Of course, there are other repositories as mirror for Chinese users (which will ## Plugins -> Stay tuned - -## App Store - -> Stay tuned +- [WingAsm](https://github.com/Wing-summer/WingAsm) : A plugin that provides assembly and disassembly features. Author: **wingsummer**. License: **APGL-v3.0**. +- [WingCStruct](https://github.com/Wing-summer/WingCStruct) : A plugin that provides basic support for analyzing file structures. Author: **wingsummer**. License: **APGL-v3.0**. diff --git a/TestPlugin/lang/TestPlugin_zh_CN.ts b/TestPlugin/lang/TestPlugin_zh_CN.ts index f9b7126..5586728 100644 --- a/TestPlugin/lang/TestPlugin_zh_CN.ts +++ b/TestPlugin/lang/TestPlugin_zh_CN.ts @@ -128,7 +128,7 @@ - + Text 文本 @@ -143,8 +143,8 @@ - - + + Clear 清空 @@ -155,7 +155,7 @@ - + Icon 图标 @@ -200,48 +200,89 @@ 元数据 - + + begin + + + + + length + + + + + foreground + + + + + background + + + + + comment + + + + + + Apply + + + + BookMark 书签 - - + + Position + + + + + Comment + + + + + MessageBox 信息框 - - - + + + Title 标题 - + Buttons 按钮组 - + DefaultButton 默认按钮 - + InputBox 输入框 - + Label 标签内容 - - - + + + Type 类型 @@ -251,64 +292,64 @@ 句柄 - + FileDialog 文件框 - + Filter 过滤器 - - + + Caption 标题 - + Options 选项组 - + ColorDialog 颜色框 - + Color 颜色 - + DataVisual 数据可视化 - - + + UpdateTextTreeError 更新文本树失败 - + UpdateTextListByModelError 通过模型更新文本列表失败 - + UpdateTextTableByModelError 通过模型更新文本表格失败 - + UpdateTextTreeByModelError 通过模型更新文本树失败 - + Choose 选择 diff --git a/TestPlugin/testform.cpp b/TestPlugin/testform.cpp index 71866f2..29309a2 100644 --- a/TestPlugin/testform.cpp +++ b/TestPlugin/testform.cpp @@ -53,6 +53,8 @@ TestForm::TestForm(WingHex::IWingPlugin *plg, QWidget *parent) initFileDialogOps(); initFileHandleListWidget(); + ui->sbposition->setRange(0, INT_MAX); + _click = std::bind(&TestForm::onDVClicked, this, std::placeholders::_1); _dblclick = std::bind(&TestForm::onDVDoubleClicked, this, std::placeholders::_1); @@ -532,3 +534,13 @@ void TestForm::on_btnCloseFile_clicked() { e.valueToKey(ret)); } } + +void TestForm::on_btnApplyBookMark_clicked() { + if (emit _plg->reader.existBookMark(ui->sbposition->value())) { + Q_UNUSED(emit _plg->controller.modBookMark(ui->sbposition->value(), + ui->lecomment->text())); + } else { + Q_UNUSED(emit _plg->controller.addBookMark(ui->sbposition->value(), + ui->lecomment->text())); + } +} diff --git a/TestPlugin/testform.h b/TestPlugin/testform.h index c052dad..76e862e 100644 --- a/TestPlugin/testform.h +++ b/TestPlugin/testform.h @@ -125,6 +125,8 @@ private slots: void on_btnCloseFile_clicked(); + void on_btnApplyBookMark_clicked(); + private: void initLogCombo(); diff --git a/TestPlugin/testform.ui b/TestPlugin/testform.ui index 69fb7dc..18a1868 100644 --- a/TestPlugin/testform.ui +++ b/TestPlugin/testform.ui @@ -620,11 +620,160 @@ Metadata + + + + + 8 + + + 8 + + + + + begin + + + + + + + + + + length + + + + + + + + + + foreground + + + + + + + + + + background + + + + + + + + + + comment + + + + + + + + + + + + + 0 + 30 + + + + Apply + + + + + + + Qt::Orientation::Vertical + + + + 20 + 169 + + + + + BookMark + + + 8 + + + + + 8 + + + 8 + + + + + Position + + + + + + + + + + Comment + + + + + + + + + + + + + 0 + 30 + + + + Apply + + + + + + + Qt::Orientation::Vertical + + + + 20 + 245 + + + + + diff --git a/images/openapp.png b/images/openapp.png new file mode 100644 index 0000000..1da1d89 Binary files /dev/null and b/images/openapp.png differ diff --git a/lang/zh_CN/winghex_zh_CN.ts b/lang/zh_CN/winghex_zh_CN.ts index 8e33c8f..986ddc1 100644 --- a/lang/zh_CN/winghex_zh_CN.ts +++ b/lang/zh_CN/winghex_zh_CN.ts @@ -76,20 +76,30 @@ AppManager - + GenericCallNotFullySupported 该软件脚本系统不完全支持通用调用,故软件将会退出。 - + SetupClang 启动 Clang 服务 - + OpeningFiles 打开文件 + + + + + + + + AlreadyOpened + 文件已被打开 + BookMarksModel @@ -272,7 +282,7 @@ DriverTips - 提示:如果处于编辑模式,请慎重编辑,否则会易导致磁盘数据丢失。如果因此导致的问题本软件概不负责!(*_*) + 提示:如果处于编辑模式,请慎重编辑!!! @@ -793,57 +803,57 @@ Logger - + [Trace] 【跟踪】 - + [Warn] 【警告】 - + [Info] 【信息】 - + [Debug] 【调试】 - + [Error] 【错误】 - + Critial 崩溃 - + Error 错误 - + Warning 警告 - + Info 信息 - + Debug 调试 - + Trace 跟踪 @@ -895,7 +905,7 @@ - + Plugin 插件 @@ -906,7 +916,7 @@ - + Log 日志 @@ -943,8 +953,8 @@ - - + + CopyToClipBoard 数据已拷贝到粘贴板 @@ -984,8 +994,8 @@ - - + + BookMark 书签 @@ -1025,7 +1035,7 @@ - + Basic 基础 @@ -1087,9 +1097,9 @@ - - + + General 基本 @@ -1172,7 +1182,7 @@ - + Fill 填充 @@ -1484,99 +1494,99 @@ 默认 - + RestoreLayout 恢复布局 - - + + SaveLayout 保存布局 - + ExportLog 导出日志 - + ClearLog 清空日志 - + ScriptEditor 脚本编辑器 - + Scripts 脚本仓库 - + PluginFunctions 插件功能 - + ScriptSetting 脚本设置 - + PluginSettings 插件设置 - + Info 信息 - + Software 软件 - + Sponsor 赞助 - + CheckUpdate 检查更新 - + Wiki 网页 Wiki - + AboutQT 关于 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 选择文件 @@ -1586,29 +1596,29 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + Error 错误 - - - - + + + + FileNotExist 文件不存在! @@ -1618,31 +1628,31 @@ - - - - - + + + + + FilePermission 因文件权限无法继续! - + ProjectFile (*.wingpro) 项目文件 (*.wingpro) - + Root Required! 需要管理员权限继续操作! - + ReloadSuccessfully 文件重新加载成功! - + ReloadUnSuccessfully 文件重新加载失败! @@ -1651,49 +1661,49 @@ - - - + + + ChooseSaveFile 请选择保存文件路径: - + NoMoreClone 克隆已到上限,无法继续操作! - + FindFininishBusy 查找任务繁忙,请勿重复查找! - + MayTooMuchFindResult 搜索数量已到达上限,结果可能不全,建议请按区段搜索。 - + SaveLayoutSuccess 保存布局成功 - + SaveLayoutError 保存布局失败 - + ConfirmSave 正在关闭未保存的文件或工作区,你确定保存吗? - + Column %1 列 %1 - + ConfirmAPPSave 你尝试关闭程序,但仍存在未保存的文件或工作区,你确定保存这些更改吗? @@ -1702,21 +1712,21 @@ - - + + SaveSuccessfully 保存成功! - - + + SaveWSError 保存工作区错误! - - - + + + Warn 警告 @@ -1726,173 +1736,178 @@ 脚本对象 - - - + + + SourceChanged 局部打开原始文件更改! - - + + SaveSourceFileError 由于原文件更改,保存文件失败! - + SaveUnSuccessfully 保存失败! - + ChooseExportFile 请选择导出文件路径: - + ExportSuccessfully 导出成功! - + ExportSourceFileError 由于原文件更改,导出文件失败! - + ExportUnSuccessfully 导出失败! - + SaveSelSuccess 保存选区字节成功! - + SaveSelError 保存选区字节失败,因文件不具有可写权限! - - + + CutToClipBoard 数据已剪切到粘贴板! - - + + UnCutToClipBoard 由于保持大小限制,数据剪切到粘贴板失败! - - + + UnCopyToClipBoard 由于保持大小限制,数据剪切到复制板失败! - + FindFininish 查找结果完毕! - + PleaseInputFill 请输入填充字节值 - + FillInputError 填充字节输入错误 - - + + InputComment 请输入批注: - - - + + + NoSelection 没有选区,无法继续的操作! - + NoMetaData 无可编辑标记 - - + + EmptyFindResult 没有可导出的搜索结果! - + SaveFindResult 导出搜索结果成功! - + SaveFindResultError 导出结果失败! - + TooManyBytesDecode 超出解码字节限制…… - + + PleaseInput + 请输入 + + + ExportLogError 导出日志失败! - + ExportLogSuccess 导出日志成功,路径: - + ClearLogSuccess 清空日志成功! - + BadNetwork 无法与远程服务器的更新检查建立连接,请检查网络。 - + NewestVersion 当前软件为最新版本 - + OlderVersion 你使用的软件为老版本,建议到 Github 和 Gitee 的仓库发行版下载更新。 - + CheckingUpdate 检查更新中…… - + Too much opened files 打开的文件过多,无法继续操作! - + CopyLimit 拷贝字节超出限制 - + ErrOpenFileBelow 打开文件出现错误(由于权限不足),如下为打开错误的文件: @@ -2077,12 +2092,12 @@ DevExtInfo - + 设备插件信息 DevExt: - + 设备插件: @@ -2093,64 +2108,64 @@ ID - + ID Name - 名称 + 名称 License - 协议 + 协议 Author - + 作者 Vendor - + 厂家 Version - 版本 + 版本 Comment - 批注 + 说明 URL - + 网址 pluginDependencies: - + 插件依赖 PUID: - 插件唯一标志符: + 插件唯一标志符: Version: - 版本: + 版本: @@ -2163,160 +2178,160 @@ InvalidPluginBrokenInfo - + 加载插件失败:损坏的插件数据 - + FoundDrvPluginCount 总计发现设备拓展插件数目: - + RegisteredFnDup 注册重复函数对象 - + ErrLoadPluginSign 插件加载失败:非法插件签名! - + ErrLoadPluginSDKVersion 插件加载失败:非法插件 SDK 版本! - + ErrLoadPluginNoName 插件加载失败:非法插件名称! - + ErrLoadInitPlugin 插件加载失败:初始化插件失败! - + PluginName : 插件名: - + PluginAuthor : 插件作者: - + PluginWidgetRegister 注册插件对象中…… - + ErrLoadExtPluginSign 设备拓展插件加载失败:非法插件签名! - + ErrLoadExtPluginSDKVersion 设备拓展插件加载失败:非法插件 SDK 版本! - + ErrLoadExtPluginNoName 设备拓展插件加载失败:非法插件名称! - + ExtPluginName : 设备拓展插件名: - + ExtPluginAuthor : 设备拓展插件作者: - + ExtPluginWidgetRegister 设备拓展注册插件对象中…… - + ErrLoadInitExtPlugin 设备拓展插件加载失败:初始化插件失败! - + EmptyNameDockWidget: 空的贴边组件名: - + InvalidNameDockWidget: 无效贴边组件名: - + InvalidNullDockWidget: 无效空贴边组件: - + [EvilCall] 【恶意调用】 - + Not allowed operation in non-UI thread 该操作在非 UI 线程非法 - + UnsafePluginDir 不安全的插件目录,请将插件目录设置为仅管理员账户可写 InvalidPluginID - + 加载插件失败:非法插件标识符 InvalidDupPlugin - + 加载插件失败:重复的插件标识符 - + FoundPluginCount 总计发现插件数目: - + PluginLoadingFailedSummary 有依赖插件加载失败总结 - + - PluginName: - 插件名: - + - Dependencies: - 依赖: - + PUID: 插件唯一标志符: - + Version: 版本: - + PluginLoadingFinished 加载插件完毕! @@ -2994,7 +3009,7 @@ Do you wish to keep up to date by reloading the file? - + NoHistoryDel 无打开历史项目可删除! @@ -3039,12 +3054,12 @@ Do you wish to keep up to date by reloading the file? 【结束】 - + FileNotExistClean 文件不存在,该选项已被清除! - + HistoryClearFinished 打开历史记录完成! diff --git a/lang/zh_TW/winghex_zh_TW.ts b/lang/zh_TW/winghex_zh_TW.ts index 8f4d685..95f8d2e 100644 --- a/lang/zh_TW/winghex_zh_TW.ts +++ b/lang/zh_TW/winghex_zh_TW.ts @@ -76,20 +76,30 @@ AppManager - + GenericCallNotFullySupported 該軟體腳本系統不完全支持通用調用,故軟體將會退出。 - + SetupClang 啟動 Clang 服務 - + OpeningFiles 打開檔 + + + + + + + + AlreadyOpened + 檔已被打開 + BookMarksModel @@ -272,7 +282,7 @@ DriverTips - 提示:如果處於編輯模式,請慎重編輯,否則會易導致磁片數據丟失。如果因此導致的問題本軟體概不負責!(*_*) + 提示:如果處於編輯模式,請慎重編輯!!! @@ -793,57 +803,57 @@ Logger - + [Trace] 【跟蹤】 - + [Warn] 【警告】 - + [Info] 【資訊】 - + [Debug] 【調試】 - + [Error] 【錯誤】 - + Critial 崩潰 - + Error 錯誤 - + Warning 警告 - + Info 資訊 - + Debug 調試 - + Trace 跟蹤 @@ -895,7 +905,7 @@ - + Plugin 插件 @@ -906,7 +916,7 @@ - + Log 日誌 @@ -943,8 +953,8 @@ - - + + CopyToClipBoard 數據已拷貝到粘貼板 @@ -984,8 +994,8 @@ - - + + BookMark 書簽 @@ -1025,7 +1035,7 @@ - + Basic 基礎 @@ -1087,9 +1097,9 @@ - - + + General 基本 @@ -1172,7 +1182,7 @@ - + Fill 填充 @@ -1308,7 +1318,7 @@ NoExtension - + 無擴展 @@ -1336,7 +1346,7 @@ OpenExt - + 打開 - 拓展 @@ -1484,99 +1494,99 @@ 默認 - + RestoreLayout 恢復佈局 - - + + SaveLayout 保存佈局 - + ExportLog 導出日誌 - + ClearLog 清空日誌 - + ScriptEditor 腳本編輯器 - + Scripts 腳本倉庫 - + PluginFunctions 插件功能 - + ScriptSetting 腳本設置 - + PluginSettings 插件設置 - + Info 資訊 - + Software 軟體 - + Sponsor 贊助 - + CheckUpdate 檢查更新 - + Wiki 網頁 Wiki - + AboutQT 關於 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 選擇檔 @@ -1586,29 +1596,29 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + Error 錯誤 - - - - + + + + FileNotExist 檔不存在! @@ -1618,31 +1628,31 @@ - - - - - + + + + + FilePermission 因檔許可權無法繼續! - + ProjectFile (*.wingpro) 專案檔 (*.wingpro) - + Root Required! 需要管理員許可權繼續操作! - + ReloadSuccessfully 檔重新加載成功! - + ReloadUnSuccessfully 檔重新加載失敗! @@ -1651,49 +1661,49 @@ - - - + + + ChooseSaveFile 請選擇保存檔路徑: - + NoMoreClone 克隆已到上限,無法繼續操作! - + FindFininishBusy 查找任務繁忙,請勿重複查找! - + MayTooMuchFindResult 搜索數量已到達上限,結果可能不全,建議請按區段搜索。 - + SaveLayoutSuccess 保存佈局成功 - + SaveLayoutError 保存佈局失敗 - + ConfirmSave 正在關閉未保存的檔或工作區,你確定保存嗎? - + Column %1 列 %1 - + ConfirmAPPSave 你嘗試關閉程式,但仍存在未保存的檔或工作區,你確定保存這些更改嗎? @@ -1702,21 +1712,21 @@ - - + + SaveSuccessfully 保存成功! - - + + SaveWSError 保存工作區錯誤! - - - + + + Warn 警告 @@ -1726,173 +1736,178 @@ 腳本對象 - - - + + + SourceChanged 局部打開原始檔更改! - - + + SaveSourceFileError 由於原文件更改,保存檔失敗! - + SaveUnSuccessfully 保存失敗! - + ChooseExportFile 請選擇導出檔路徑: - + ExportSuccessfully 導出成功! - + ExportSourceFileError 由於原文件更改,導出檔失敗! - + ExportUnSuccessfully 導出失敗! - + SaveSelSuccess 保存選區位元組成功! - + SaveSelError 保存選區位元組失敗,因檔不具有可寫許可權! - - + + CutToClipBoard 數據已剪切到粘貼板! - - + + UnCutToClipBoard 由於保持大小限制,數據剪切到粘貼板失敗! - - + + UnCopyToClipBoard 由於保持大小限制,數據剪切到複製板失敗! - + FindFininish 查找結果完畢! - + PleaseInputFill 請輸入填充位元組值 - + FillInputError 填充位元組輸入錯誤 - - + + InputComment 請輸入批註: - - - + + + NoSelection 沒有選區,無法繼續的操作! - + NoMetaData 無可編輯標記 - - + + EmptyFindResult 沒有可導出的搜索結果! - + SaveFindResult 導出搜索結果成功! - + SaveFindResultError 導出結果失敗! - + TooManyBytesDecode 超出解碼位元組限制…… - + + PleaseInput + 請輸入 + + + ExportLogError 導出日誌失敗! - + ExportLogSuccess 導出日誌成功,路徑: - + ClearLogSuccess 清空日誌成功! - + BadNetwork 無法與遠程伺服器的更新檢查建立連接,請檢查網路。 - + NewestVersion 當前軟體為最新版本 - + OlderVersion 你使用的軟體為老版本,建議到 Github 和 Gitee 的倉庫發行版下載更新。 - + CheckingUpdate 檢查更新中…… - + Too much opened files 打開的檔過多,無法繼續操作! - + CopyLimit 拷貝位元組超出限制 - + ErrOpenFileBelow 打開檔出現錯誤(由於許可權不足),如下為打開錯誤的檔: @@ -2077,12 +2092,12 @@ DevExtInfo - + 設備插件資訊 DevExt: - + 設備插件: @@ -2093,64 +2108,64 @@ ID - + ID Name - 名稱 + 名稱 License - 協議 + 協議 Author - + 作者 Vendor - + 廠家 Version - 版本 + 版本 Comment - 批註 + 說明 URL - + 網址 pluginDependencies: - + 插件依賴 PUID: - 插件唯一標誌符: + 插件唯一標誌符: Version: - 版本: + 版本: @@ -2158,165 +2173,165 @@ LoadingPlugin - + 加載插件中: InvalidPluginBrokenInfo - + 加載插件失敗:損壞的插件數據 - + FoundDrvPluginCount - + 總計發現設備拓展插件數目: - + RegisteredFnDup 註冊重複函數對象 - + ErrLoadPluginSign 插件加載失敗:非法插件簽名! - + ErrLoadPluginSDKVersion 插件加載失敗:非法插件 SDK 版本! - + ErrLoadPluginNoName 插件加載失敗:非法插件名稱! - + ErrLoadInitPlugin 插件加載失敗:初始化插件失敗! - + PluginName : 插件名: - + PluginAuthor : 插件作者: - + PluginWidgetRegister 註冊插件對象中…… - + ErrLoadExtPluginSign - + 設備拓展插件加載失敗:非法插件簽名! - + ErrLoadExtPluginSDKVersion - + 設備拓展插件加載失敗:非法插件 SDK 版本! - + ErrLoadExtPluginNoName - + 設備拓展插件加載失敗:非法插件名稱! - + ExtPluginName : - + 設備拓展插件名: - + ExtPluginAuthor : - + 設備拓展插件作者: - + ExtPluginWidgetRegister - + 設備拓展註冊插件對象中…… - + ErrLoadInitExtPlugin - + 設備拓展插件加載失敗:初始化插件失敗! - + EmptyNameDockWidget: 空的貼邊組件名: - + InvalidNameDockWidget: 無效貼邊組件名: - + InvalidNullDockWidget: 無效空貼邊組件: - + [EvilCall] 【惡意調用】 - + Not allowed operation in non-UI thread 該操作在非 UI 線程非法 - + UnsafePluginDir 不安全的插件目錄,請將插件目錄設置為僅管理員帳戶可寫 InvalidPluginID - + 加載插件失敗:非法插件識別字 InvalidDupPlugin - + 加載插件失敗:重複的插件識別字 - + FoundPluginCount 總計發現插件數目: - + PluginLoadingFailedSummary 有依賴插件加載失敗總結 - + - PluginName: - 插件名: - + - Dependencies: - 依賴: - + PUID: 插件唯一標誌符: - + Version: 版本: - + PluginLoadingFinished 加載插件完畢! @@ -2994,7 +3009,7 @@ Do you wish to keep up to date by reloading the file? - + NoHistoryDel 無打開歷史專案可刪除! @@ -3039,12 +3054,12 @@ Do you wish to keep up to date by reloading the file? 【結束】 - + FileNotExistClean 檔不存在,該選項已被清除! - + HistoryClearFinished 打開歷史記錄完成! diff --git a/resources.qrc b/resources.qrc index fa892e1..f8c41d0 100644 --- a/resources.qrc +++ b/resources.qrc @@ -59,6 +59,7 @@ images/metashow.png images/new.png images/open.png + images/openapp.png images/opendriver.png images/openother.png images/openr.png diff --git a/src/class/appmanager.cpp b/src/class/appmanager.cpp index c8b4b9f..bdc189b 100644 --- a/src/class/appmanager.cpp +++ b/src/class/appmanager.cpp @@ -23,6 +23,7 @@ #include "QConsoleWidget/commandhistorymanager.h" #include "angelscript.h" #include "clangformatmanager.h" +#include "control/toast.h" #include "dbghelper.h" #include "define.h" #include "dialog/mainwindow.h" @@ -157,12 +158,23 @@ void AppManager::openFile(const QString &file, bool autoDetect, qsizetype start, } if (ret == ErrFile::AlreadyOpened) { Q_ASSERT(editor); - editor->raise(); + if (_w->currentEditor() == editor) { + Toast::toast(_w, NAMEICONRES("openapp"), + tr("AlreadyOpened")); + } else { + editor->raise(); + } + editor->setFocus(); } } else if (ret == ErrFile::AlreadyOpened) { Q_ASSERT(editor); - editor->raise(); + if (_w->currentEditor() == editor) { + Toast::toast(_w, NAMEICONRES("openapp"), tr("AlreadyOpened")); + } else { + editor->raise(); + } + editor->setFocus(); } } @@ -174,7 +186,12 @@ void AppManager::openRawFile(const QString &file) { auto ret = _w->openFile(file, &editor); if (ret == ErrFile::AlreadyOpened) { Q_ASSERT(editor); - editor->raise(); + if (_w->currentEditor() == editor) { + Toast::toast(_w, NAMEICONRES("openapp"), tr("AlreadyOpened")); + } else { + editor->raise(); + } + editor->setFocus(); } } @@ -185,7 +202,12 @@ void AppManager::openDriver(const QString &driver) { auto ret = _w->openDriver(driver, &editor); if (ret == ErrFile::AlreadyOpened) { Q_ASSERT(editor); - editor->raise(); + if (_w->currentEditor() == editor) { + Toast::toast(_w, NAMEICONRES("openapp"), tr("AlreadyOpened")); + } else { + editor->raise(); + } + editor->setFocus(); } } @@ -198,7 +220,12 @@ void AppManager::openRegionFile(const QString ®ion, qsizetype start, auto ret = _w->openRegionFile(region, &editor, start, length); if (ret == ErrFile::AlreadyOpened) { Q_ASSERT(editor); - editor->raise(); + if (_w->currentEditor() == editor) { + Toast::toast(_w, NAMEICONRES("openapp"), tr("AlreadyOpened")); + } else { + editor->raise(); + } + editor->setFocus(); } } @@ -209,7 +236,12 @@ void AppManager::openWorkSpace(const QString &ws) { auto ret = _w->openWorkSpace(ws, &editor); if (ret == ErrFile::AlreadyOpened) { Q_ASSERT(editor); - editor->raise(); + if (_w->currentEditor() == editor) { + Toast::toast(_w, NAMEICONRES("openapp"), tr("AlreadyOpened")); + } else { + editor->raise(); + } + editor->setFocus(); } } diff --git a/src/class/layoutmanager.cpp b/src/class/layoutmanager.cpp index e49340c..23a9bbc 100644 --- a/src/class/layoutmanager.cpp +++ b/src/class/layoutmanager.cpp @@ -36,6 +36,28 @@ QByteArray LayoutManager::layout(const QString &v) const { qsizetype LayoutManager::layoutCount() const { return _layouts.size(); } +QDir LayoutManager::layoutDir() { + QDir pdir(Utilities::getAppDataPath()); + auto lname = QStringLiteral("layouts"); + return pdir.absoluteFilePath(lname); +} + +QString LayoutManager::getSavedLayoutName(const QString &id) { + auto pdir = layoutDir(); + auto trf = QStringLiteral("metatr.ini"); + auto sep = QStringLiteral("/"); + auto lid = id; + + QSettings set(pdir.absoluteFilePath(trf), QSettings::IniFormat); + auto name = LanguageManager::instance().defaultLocale().name(); + QString k = set.value(name + sep + id).toString().trimmed(); + if (!k.isEmpty()) { + lid = k; + } + + return lid; +} + LayoutManager::LayoutManager() { ASSERT_SINGLETON; QDir pdir(Utilities::getAppDataPath()); @@ -66,7 +88,7 @@ void LayoutManager::process(const QDir &dir, for (auto &l : dir.entryInfoList({"*.wing-layout"}, QDir::Files)) { QString k; if (set) { - k = set->value(name + sep + l.baseName()).toString(); + k = set->value(name + sep + l.baseName()).toString().trimmed(); } if (k.isEmpty()) { diff --git a/src/class/layoutmanager.h b/src/class/layoutmanager.h index 39ee30f..16b0379 100644 --- a/src/class/layoutmanager.h +++ b/src/class/layoutmanager.h @@ -36,6 +36,11 @@ public: qsizetype layoutCount() const; + static QDir layoutDir(); + + // only for exporting layout + QString getSavedLayoutName(const QString &id); + private: LayoutManager(); diff --git a/src/class/logger.cpp b/src/class/logger.cpp index 75247c6..641e324 100644 --- a/src/class/logger.cpp +++ b/src/class/logger.cpp @@ -88,6 +88,8 @@ Logger::Level Logger::logLevel() const { return _level; } void Logger::_log(const QString &message) { emit instance().log(message); } +void Logger::newLine() { _log({}); } + void Logger::trace(const QString &message) { if (instance()._level >= q5TRACE) { QString str = message; diff --git a/src/class/logger.h b/src/class/logger.h index 7df385f..8a6c3cf 100644 --- a/src/class/logger.h +++ b/src/class/logger.h @@ -54,8 +54,7 @@ signals: void log(const QString &message); public slots: - // internal use only - static void _log(const QString &message); + static void newLine(); // external use static void trace(const QString &message); @@ -71,6 +70,8 @@ private: virtual ~Logger(); + static void _log(const QString &message); + Q_DISABLE_COPY_MOVE(Logger) private: diff --git a/src/class/recentfilemanager.cpp b/src/class/recentfilemanager.cpp index 7fd5846..1cba40d 100644 --- a/src/class/recentfilemanager.cpp +++ b/src/class/recentfilemanager.cpp @@ -144,16 +144,35 @@ void RecentFileManager::addRecentFile(const RecentInfo &info) { } auto a = new QAction(m_menu); a->setData(QVariant::fromValue(info)); - a->setText(getDisplayFileName(info)); + + QMimeDatabase db; + auto mt = db.mimeTypeForFile(info.fileName); + + a->setText(getDisplayFileName(info) + QStringLiteral(" (") + mt.name() + + QStringLiteral(")")); a->setToolTip(getDisplayTooltip(info)); if (info.isWorkSpace) { a->setIcon(ICONRES(QStringLiteral("pro"))); + } else { + a->setIcon( + Utilities::getIconFromFile(qApp->style(), info.fileName)); } connect(a, &QAction::triggered, this, [=] { auto send = qobject_cast(sender()); if (send) { auto f = send->data().value(); if (existsPath(f)) { + auto idx = hitems.indexOf(a); + if (idx > 0) { + m_menu->removeAction(a); + + if (hitems.count()) + m_menu->insertAction(hitems.first(), a); + else + m_menu->addAction(a); + + hitems.move(idx, 0); + } emit triggered(f); } else { auto index = hitems.indexOf(send); diff --git a/src/control/editorview.cpp b/src/control/editorview.cpp index 3237534..2fcba7d 100644 --- a/src/control/editorview.cpp +++ b/src/control/editorview.cpp @@ -286,6 +286,7 @@ ErrFile EditorView::newFile(size_t index) { auto p = QHexDocument::fromMemory(QByteArray(), false); p->setDocSaved(); m_hex->setDocument(QSharedPointer(p)); + m_hex->cursor()->setInsertionMode(QHexCursor::InsertMode); connectDocSavedFlag(this); return ErrFile::Success; } diff --git a/src/dialog/mainwindow.cpp b/src/dialog/mainwindow.cpp index cc6a52c..defe3fb 100644 --- a/src/dialog/mainwindow.cpp +++ b/src/dialog/mainwindow.cpp @@ -1556,8 +1556,10 @@ RibbonTabContent *MainWindow::buildViewPage(RibbonTabContent *tab) { p->first, [this, layout]() { m_dock->restoreState(layout); })); } - addPannelAction(pannel, QStringLiteral("layout"), tr("RestoreLayout"), - EMPTY_FUNC, {}, menu); + m_toolBtneditors.insert( + ToolButtonIndex::LAYOUT_ACTION, + addPannelAction(pannel, QStringLiteral("layout"), + tr("RestoreLayout"), EMPTY_FUNC, {}, menu)); addPannelAction(pannel, QStringLiteral("layoutexport"), tr("SaveLayout"), &MainWindow::on_saveLayout); @@ -2807,14 +2809,27 @@ void MainWindow::on_fullScreen() { } void MainWindow::on_saveLayout() { - auto filename = WingFileDialog::getSaveFileName( - this, tr("SaveLayout"), m_lastusedpath, - QStringLiteral("Layout (*.wing-layout)")); - if (!filename.isEmpty()) { - QFile f(filename); + static auto suffix = QStringLiteral(".wing-layout"); + bool ok; + auto fileID = WingInputDialog::getText( + this, tr("SaveLayout"), tr("PleaseInput"), QLineEdit::Normal, {}, &ok); + if (ok) { + auto layoutDir = LayoutManager::layoutDir(); + QFile f(layoutDir.absoluteFilePath(fileID + suffix)); if (f.open(QFile::WriteOnly)) { - f.write(m_dock->saveState()); + auto layout = m_dock->saveState(); + f.write(layout); f.close(); + + // append saved layout + auto &lm = LayoutManager::instance(); + auto menu = + m_toolBtneditors[ToolButtonIndex::LAYOUT_ACTION]->menu(); + Q_ASSERT(menu); + menu->addAction( + newAction(lm.getSavedLayoutName(fileID), + [this, layout]() { m_dock->restoreState(layout); })); + Toast::toast(this, NAMEICONRES(QStringLiteral("layoutexport")), tr("SaveLayoutSuccess")); } else { diff --git a/src/dialog/mainwindow.h b/src/dialog/mainwindow.h index 88fa7a1..2612e86 100644 --- a/src/dialog/mainwindow.h +++ b/src/dialog/mainwindow.h @@ -87,6 +87,7 @@ private: UNDO_ACTION, REDO_ACTION, OPEN_EXT, + LAYOUT_ACTION, }; private: @@ -222,9 +223,11 @@ public: bool ignoreMd5, bool isExport = false); ErrFile closeEditor(EditorView *editor, bool force); - IWingPlugin::FileType getEditorViewFileType(EditorView *view); + EditorView *currentEditor(); private: + IWingPlugin::FileType getEditorViewFileType(EditorView *view); + QString saveLog(); ads::CDockWidget *buildDockWidget(ads::CDockManager *dock, @@ -250,7 +253,6 @@ private: void setCurrentHexEditorScale(qreal rate); - EditorView *currentEditor(); QHexView *currentHexView(); bool writeSafeCheck(bool isNewFile, const QString &savePath); diff --git a/src/plugin/pluginsystem.cpp b/src/plugin/pluginsystem.cpp index 935d9b1..51d027d 100644 --- a/src/plugin/pluginsystem.cpp +++ b/src/plugin/pluginsystem.cpp @@ -119,7 +119,7 @@ PluginSystem::loadPlugin(const QFileInfo &fileinfo, const QDir &setdir) { } else { loadPlugin(p, meta.value(), setdir); } - Logger::_log(""); + Logger::newLine(); } return std::nullopt; @@ -131,14 +131,17 @@ EditorView *PluginSystem::getCurrentPluginView(IWingPlugin *plg) { if (plg == nullptr) { return nullptr; } - if (!m_plgviewMap.contains(plg)) { - return nullptr; + if (!m_plgCurrentfid.contains(plg)) { + m_plgCurrentfid.insert(plg, -1); } - auto view = m_plgviewMap.value(plg).first; - if (view == nullptr) { - view = _win->m_curEditor; + + auto fid = m_plgCurrentfid[plg]; + auto &plgview = m_plgviewMap[plg]; + auto ctx = pluginContextById(plg, fid); + if (ctx) { + return ctx->view; } - return view; + return _win->m_curEditor; } EditorView *PluginSystem::handle2EditorView(IWingPlugin *plg, int handle) { @@ -146,14 +149,11 @@ EditorView *PluginSystem::handle2EditorView(IWingPlugin *plg, int handle) { return getCurrentPluginView(plg); } - auto handles = m_plgHandles.value(plg); - auto r = std::find_if(handles.begin(), handles.end(), - [handle](const QPair &d) { - return d.first == handle; - }); - if (r != handles.end()) { - return r->second; + auto ctx = pluginContextById(plg, handle); + if (ctx) { + return ctx->view; } + return nullptr; } @@ -164,7 +164,13 @@ PluginSystem::assginHandleForPluginView(IWingPlugin *plg, EditorView *view) { } auto id = m_idGen.get(); - m_plgHandles[plg].append(qMakePair(id, view)); + + PluginFileContext context; + context.fid = id; + context.linkedplg = plg; + context.view = view; + + m_plgviewMap[plg].append(context); m_viewBindings[view].append(plg); return id; } @@ -173,14 +179,15 @@ PluginSystem::PluginInfo PluginSystem::parsePluginMetadata(const QJsonObject &meta) { PluginSystem::PluginInfo info; - info.id = meta["Id"].toString(); - info.version = QVersionNumber::fromString(meta["Version"].toString()); + info.id = meta["Id"].toString().trimmed(); + info.version = + QVersionNumber::fromString(meta["Version"].toString().trimmed()); - info.name = meta["Name"].toString(); - info.vendor = meta["Vendor"].toString(); - info.author = meta["Author"].toString(); - info.license = meta["License"].toString(); - info.url = meta["Url"].toString(); + info.name = meta["Name"].toString().trimmed(); + info.vendor = meta["Vendor"].toString().trimmed(); + info.author = meta["Author"].toString().trimmed(); + info.license = meta["License"].toString().trimmed(); + info.url = meta["Url"].toString().trimmed(); auto dependsObj = meta["Dependencies"]; if (!dependsObj.isNull()) { @@ -189,12 +196,12 @@ PluginSystem::parsePluginMetadata(const QJsonObject &meta) { for (int i = 0; i < arr.size(); ++i) { auto d = arr.at(i); if (d.isObject()) { - auto id = d["Id"].toString(); + auto id = d["Id"].toString().trimmed(); if (id.isEmpty()) { continue; } - auto version = - QVersionNumber::fromString(d["Version"].toString()); + auto version = QVersionNumber::fromString( + d["Version"].toString().trimmed()); WingDependency dp; dp.puid = id; dp.version = version; @@ -215,8 +222,11 @@ PluginSystem::checkPluginMetadata(const PluginInfo &meta, bool isPlg) { return PluginStatus::InvalidID; } + if (meta.id.front().isDigit()) { + return PluginStatus::InvalidID; + } auto r = std::find_if(meta.id.begin(), meta.id.end(), [](const QChar &ch) { - return !ch.isLetterOrNumber(); + return !ch.isLetterOrNumber() && ch != '_'; }); if (r != meta.id.end()) { return PluginStatus::InvalidID; @@ -242,35 +252,38 @@ bool PluginSystem::checkPluginCanOpenedFile(IWingPlugin *plg) { if (plg == nullptr) { return false; } - return m_plgHandles[plg].size() <= UCHAR_MAX; + return m_plgviewMap[plg].size() <= UCHAR_MAX; } bool PluginSystem::checkPluginHasAlreadyOpened(IWingPlugin *plg, EditorView *view) { - auto &maps = m_plgHandles[plg]; - auto ret = std::find_if( - maps.begin(), maps.end(), - [view](const QPair &content) { - return content.second == view; - }); + auto &maps = m_plgviewMap[plg]; + auto ret = std::find_if(maps.begin(), maps.end(), + [view](const PluginFileContext &content) { + return content.view == view; + }); return ret != maps.end(); } void PluginSystem::cleanUpEditorViewHandle(EditorView *view) { if (m_viewBindings.contains(view)) { - auto v = m_viewBindings.value(view); + auto v = m_viewBindings[view]; // clean up for (auto &plg : v) { - auto handles = m_plgHandles.value(plg); + auto &handles = m_plgviewMap[plg]; #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) handles.erase(std::remove_if( handles.begin(), handles.end(), - [view, plg, this](const QPair &v) { - if (v.second == view) { + [view, this](const PluginFileContext &v) { + if (v.view == view) { + if (v.fid == m_plgCurrentfid[v.linkedplg]) { + m_plgCurrentfid[v.linkedplg] = -1; + } dispatchEvent( IWingPlugin::RegisteredEvent::PluginFileClosed, - {quintptr(plg), v.second->fileName(), v.first, + {quintptr(v.linkedplg), v.view->fileName(), + int(v.fid), QVariant::fromValue( _win->getEditorViewFileType(view))}); return true; @@ -279,68 +292,78 @@ void PluginSystem::cleanUpEditorViewHandle(EditorView *view) { })); #else - handles.removeIf( - [view, plg, this](const QPair &v) { - if (v.second == view) { - dispatchEvent( - IWingPlugin::RegisteredEvent::PluginFileClosed, - {quintptr(plg), v.second->fileName(), v.first, - QVariant::fromValue( - _win->getEditorViewFileType(view))}); - return true; + handles.removeIf([view, this](const PluginFileContext &v) { + if (v.view == view) { + if (v.fid == m_plgCurrentfid[v.linkedplg]) { + m_plgCurrentfid[v.linkedplg] = -1; } - return false; - }); + dispatchEvent( + IWingPlugin::RegisteredEvent::PluginFileClosed, + {quintptr(v.linkedplg), v.view->fileName(), int(v.fid), + QVariant::fromValue( + _win->getEditorViewFileType(view))}); + return true; + } + return false; + }); #endif } m_viewBindings.remove(view); - - // TODO cleanup } } bool PluginSystem::closeEditor(IWingPlugin *plg, int handle, bool force) { - if (handle > 0) { - auto &handles = m_plgHandles[plg]; - auto r = std::find_if( - handles.begin(), handles.end(), - [handle](const QPair &d) { - return (*d.first) == handle; - }); + if (handle >= 0) { + auto &handles = m_plgviewMap[plg]; + auto r = std::find_if(handles.begin(), handles.end(), + [handle](const PluginFileContext &d) { + return (*d.fid) == handle; + }); if (r == handles.end()) { return false; } - auto &bind = m_viewBindings[r->second]; + auto &bind = m_viewBindings[r->view]; + bind.removeOne(plg); if (bind.isEmpty()) { - _win->closeEditor(r->second, force); + _win->closeEditor(r->view, force); + m_viewBindings.remove(r->view); } + + if (m_plgCurrentfid[plg] == handle) { + m_plgCurrentfid[plg] = -1; + } + + handles.erase(r); } else { return false; } - m_plgviewMap.remove(plg); - m_plgHandles.remove(plg); - return true; } bool PluginSystem::closeHandle(IWingPlugin *plg, int handle) { - if (handle < 1) { + if (handle < 0) { return false; } - auto &handles = m_plgHandles[plg]; - auto r = - std::find_if(handles.begin(), handles.end(), - [handle](const QPair &d) { - return (*d.first) == handle; - }); + auto &handles = m_plgviewMap[plg]; + auto r = std::find_if( + handles.begin(), handles.end(), + [handle](const PluginFileContext &d) { return (*d.fid) == handle; }); if (r == handles.end()) { return false; } - auto &bind = m_viewBindings[r->second]; + auto &bind = m_viewBindings[r->view]; bind.removeOne(plg); + if (bind.isEmpty()) { + m_viewBindings.remove(r->view); + } + + if (m_plgCurrentfid[plg] == handle) { + m_plgCurrentfid[plg] = -1; + } + handles.erase(r); return true; } @@ -510,6 +533,7 @@ void PluginSystem::loadExtPlugin() { plugindir.setNameFilters({"*.wingplg"}); #endif + Logger::newLine(); checkDirRootSafe(plugindir); auto plgs = plugindir.entryInfoList(); @@ -541,7 +565,8 @@ void PluginSystem::loadExtPlugin() { if (!_lazyplgs.isEmpty()) { Logger::critical(tr("PluginLoadingFailedSummary")); - Logger::_log({}); + Logger::newLine(); + for (auto &lplg : errorplg) { Logger::critical(tr("- PluginName:") + lplg.name); Logger::critical(tr("- Dependencies:")); @@ -572,6 +597,7 @@ void PluginSystem::loadDevicePlugin() { devdir.setNameFilters({"*.wingdrv"}); #endif + Logger::newLine(); checkDirRootSafe(devdir); auto plgs = devdir.entryInfoList(); @@ -840,6 +866,10 @@ void PluginSystem::loadPlugin(IWingPlugin *p, PluginInfo &meta, emit pluginLoading(p->pluginName()); + if (meta.name.isEmpty()) { + meta.name = p->metaObject()->className(); + } + p_tr = LanguageManager::instance().try2LoadPluginLang(meta.name); connectLoadingInterface(p); @@ -950,7 +980,9 @@ void PluginSystem::loadPlugin(IWingPlugin *p, PluginInfo &meta, registerEvents(p); connectInterface(p); - m_plgviewMap.insert(p, qMakePair(nullptr, nullptr)); + // prepare for file contenxt + m_plgviewMap.insert(p, {}); + m_plgCurrentfid.insert(p, -1); } catch (const QString &error) { Logger::critical(error); if (p_tr) { @@ -980,6 +1012,9 @@ void PluginSystem::loadPlugin(IWingDevice *p, PluginInfo &meta, Logger::warning(tr("ExtPluginAuthor :") + meta.author); Logger::warning(tr("ExtPluginWidgetRegister")); + if (meta.name.isEmpty()) { + meta.name = p->metaObject()->className(); + } p_tr = LanguageManager::instance().try2LoadPluginLang(meta.name); connectLoadingInterface(p); @@ -1616,18 +1651,12 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { return false; } if (handle < 0) { - m_plgviewMap[plg].first = nullptr; + m_plgCurrentfid[plg] = -1; } else { - auto handles = m_plgHandles.value(plg); - auto ret = std::find_if( - handles.begin(), handles.end(), - [handle](const QPair &v) { - return v.first == handle; - }); - if (ret == handles.end()) { - return false; + auto ctx = pluginContextById(plg, handle); + if (ctx) { + m_plgCurrentfid[plg] = handle; } - m_plgviewMap[plg].first = ret->second; } return true; }); @@ -1641,22 +1670,16 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { auto cur = _win->m_curEditor; if (cur) { cur->raise(); - } else { - return false; + return true; } } else { - auto handles = m_plgHandles.value(plg); - auto ret = std::find_if( - handles.begin(), handles.end(), - [handle](const QPair &v) { - return v.first == handle; - }); - if (ret == handles.end()) { - return false; + auto ctx = pluginContextById(plg, handle); + if (ctx) { + ctx->view->raise(); + return true; } - ret->second->raise(); } - return true; + return false; }); connect(pctl, &WingPlugin::Controller::setLockedFile, _win, [=](bool b) -> bool { @@ -1730,43 +1753,40 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { }); connect(pctl, &WingPlugin::Controller::beginMarco, _win, [=](const QString &txt) -> bool { - QPair empty; - auto e = m_plgviewMap.value(plg, empty).first; - if (e) { - auto &info = m_plgviewMap[plg]; - if (info.second) { - return false; - } - info.second = new QUndoCommand(txt); - return true; + auto fid = m_plgCurrentfid[plg]; + if (fid < 0) { + return false; } - return false; + + auto r = pluginContextByIdIt(plg, fid); + if (r) { + (*r)->cmd = new QUndoCommand; + } + return true; }); connect(pctl, &WingPlugin::Controller::endMarco, _win, [=]() -> bool { - auto e = m_plgviewMap.value(plg).first; - if (e) { - auto &info = m_plgviewMap[plg]; - if (info.second) { - e->hexEditor()->document()->pushMakeUndo(info.second); - info.second = nullptr; - return true; - } + auto fid = m_plgCurrentfid[plg]; + if (fid < 0) { return false; } + + auto &info = m_plgviewMap[plg]; + auto &e = info[fid]; + if (e.cmd) { + return true; + } return false; }); connect(pctl, &WingPlugin::Controller::insertBytes, _win, [=](qsizetype offset, const QByteArray &data) -> bool { - QPair empty{nullptr, nullptr}; - auto mapitem = m_plgviewMap.value(plg, empty); - auto e = mapitem.first; + auto e = getCurrentPluginView(plg); if (e) { auto editor = e->hexEditor(); auto doc = editor->document(); - Q_ASSERT(m_plgviewMap.contains(plg)); - auto cmd = doc->MakeInsert(mapitem.second, editor->cursor(), - offset, data); - if (mapitem.second == nullptr && cmd) { + auto uc = pluginCurrentUndoCmd(plg); + auto cmd = + doc->MakeInsert(uc, editor->cursor(), offset, data); + if (uc == nullptr && cmd) { _rwlock.lockForWrite(); doc->pushMakeUndo(cmd); _rwlock.unlock(); @@ -1778,15 +1798,14 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { connect(pctl, &WingPlugin::Controller::writeBytes, _win, [=](qsizetype offset, const QByteArray &data) -> bool { QPair empty{nullptr, nullptr}; - auto mapitem = m_plgviewMap.value(plg, empty); - auto e = mapitem.first; + auto e = getCurrentPluginView(plg); if (e) { auto editor = e->hexEditor(); auto doc = editor->document(); - Q_ASSERT(m_plgviewMap.contains(plg)); - auto cmd = doc->MakeReplace(mapitem.second, - editor->cursor(), offset, data); - if (mapitem.second == nullptr && cmd) { + auto uc = pluginCurrentUndoCmd(plg); + auto cmd = + doc->MakeReplace(uc, editor->cursor(), offset, data); + if (uc == nullptr && cmd) { _rwlock.lockForWrite(); doc->pushMakeUndo(cmd); _rwlock.unlock(); @@ -1824,9 +1843,7 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { connect(pctl, &WingPlugin::Controller::insertString, _win, [=](qsizetype offset, const QString &value, const QString &encoding) -> bool { - QPair empty{nullptr, nullptr}; - auto mapitem = m_plgviewMap.value(plg, empty); - auto e = mapitem.first; + auto e = getCurrentPluginView(plg); if (e) { auto editor = e->hexEditor(); auto doc = editor->document(); @@ -1838,10 +1855,10 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { } auto unicode = Utilities::encodingString(value, enco); - - auto cmd = doc->MakeInsert(mapitem.second, editor->cursor(), - offset, unicode); - if (mapitem.second == nullptr && cmd) { + auto uc = pluginCurrentUndoCmd(plg); + auto cmd = + doc->MakeInsert(uc, editor->cursor(), offset, unicode); + if (uc == nullptr && cmd) { _rwlock.lockForWrite(); doc->pushMakeUndo(cmd); _rwlock.unlock(); @@ -1879,9 +1896,7 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { connect(pctl, &WingPlugin::Controller::writeString, _win, [=](qsizetype offset, const QString &value, const QString &encoding) -> bool { - QPair empty{nullptr, nullptr}; - auto mapitem = m_plgviewMap.value(plg, empty); - auto e = mapitem.first; + auto e = getCurrentPluginView(plg); if (e) { auto editor = e->hexEditor(); auto doc = editor->document(); @@ -1893,10 +1908,10 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { } auto unicode = Utilities::encodingString(value, enco); - - auto cmd = doc->MakeReplace( - mapitem.second, editor->cursor(), offset, unicode); - if (mapitem.second == nullptr && cmd) { + auto uc = pluginCurrentUndoCmd(plg); + auto cmd = + doc->MakeReplace(uc, editor->cursor(), offset, unicode); + if (uc == nullptr && cmd) { _rwlock.lockForWrite(); doc->pushMakeUndo(cmd); _rwlock.unlock(); @@ -1932,9 +1947,7 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { }); connect(pctl, &WingPlugin::Controller::appendString, _win, [=](const QString &value, const QString &encoding) -> bool { - QPair empty{nullptr, nullptr}; - auto mapitem = m_plgviewMap.value(plg, empty); - auto e = mapitem.first; + auto e = getCurrentPluginView(plg); if (e) { auto editor = e->hexEditor(); auto doc = editor->document(); @@ -1947,10 +1960,10 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { } auto unicode = Utilities::encodingString(value, enco); - Q_ASSERT(m_plgviewMap.contains(plg)); - auto cmd = doc->MakeInsert(mapitem.second, editor->cursor(), - offset, unicode); - if (mapitem.second == nullptr && cmd) { + auto uc = pluginCurrentUndoCmd(plg); + auto cmd = + doc->MakeInsert(uc, editor->cursor(), offset, unicode); + if (uc == nullptr && cmd) { _rwlock.lockForWrite(); doc->pushMakeUndo(cmd); _rwlock.unlock(); @@ -1962,17 +1975,15 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { connect(pctl, &WingPlugin::Controller::remove, _win, [=](qsizetype offset, qsizetype len) -> bool { - QPair empty{nullptr, nullptr}; - auto mapitem = m_plgviewMap.value(plg, empty); - auto e = mapitem.first; + auto e = getCurrentPluginView(plg); if (e) { auto editor = e->hexEditor(); auto doc = editor->document(); - Q_ASSERT(m_plgviewMap.contains(plg)); - auto cmd = doc->MakeRemove(mapitem.second, editor->cursor(), - offset, len); - if (mapitem.second == nullptr && cmd) { + auto uc = pluginCurrentUndoCmd(plg); + auto cmd = + doc->MakeRemove(uc, editor->cursor(), offset, len); + if (uc == nullptr && cmd) { _rwlock.lockForWrite(); doc->pushMakeUndo(cmd); _rwlock.unlock(); @@ -1982,18 +1993,15 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { return false; }); connect(pctl, &WingPlugin::Controller::removeAllBytes, _win, [=]() -> bool { - QPair empty{nullptr, nullptr}; - auto mapitem = m_plgviewMap.value(plg, empty); - auto e = mapitem.first; + auto e = getCurrentPluginView(plg); if (e) { auto editor = e->hexEditor(); auto doc = editor->document(); auto len = doc->length(); - Q_ASSERT(m_plgviewMap.contains(plg)); - auto cmd = - doc->MakeRemove(mapitem.second, editor->cursor(), 0, len); - if (mapitem.second == nullptr && cmd) { + auto uc = pluginCurrentUndoCmd(plg); + auto cmd = doc->MakeRemove(uc, editor->cursor(), 0, len); + if (uc == nullptr && cmd) { _rwlock.lockForWrite(); doc->pushMakeUndo(cmd); _rwlock.unlock(); @@ -2086,11 +2094,10 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { if (e) { auto doc = e->hexEditor()->document(); - Q_ASSERT(m_plgviewMap.contains(plg)); + auto uc = pluginCurrentUndoCmd(plg); auto cmd = doc->metadata()->MakeMetadata( - m_plgviewMap[plg].second, begin, begin + length, - fgcolor, bgcolor, comment); - if (cmd) { + uc, begin, begin + length, fgcolor, bgcolor, comment); + if (uc == nullptr && cmd) { doc->pushMakeUndo(cmd); return true; } @@ -2105,10 +2112,9 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { auto e = pluginCurrentEditor(plg); if (e) { auto doc = e->hexEditor()->document(); - Q_ASSERT(m_plgviewMap.contains(plg)); - auto cmd = doc->metadata()->MakeRemoveMetadata( - m_plgviewMap[plg].second, offset); - if (cmd) { + auto uc = pluginCurrentUndoCmd(plg); + auto cmd = doc->metadata()->MakeRemoveMetadata(uc, offset); + if (uc == nullptr && cmd) { doc->pushMakeUndo(cmd); return true; } @@ -2122,9 +2128,9 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { auto e = pluginCurrentEditor(plg); if (e) { auto doc = e->hexEditor()->document(); - Q_ASSERT(m_plgviewMap.contains(plg)); - auto cmd = doc->metadata()->MakeClear(m_plgviewMap[plg].second); - if (cmd) { + auto uc = pluginCurrentUndoCmd(plg); + auto cmd = doc->metadata()->MakeClear(uc); + if (uc == nullptr && cmd) { doc->pushMakeUndo(cmd); return true; } @@ -2140,11 +2146,10 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { auto e = pluginCurrentEditor(plg); if (e) { auto doc = e->hexEditor()->document(); - Q_ASSERT(m_plgviewMap.contains(plg)); + auto uc = pluginCurrentUndoCmd(plg); auto cmd = doc->metadata()->MakeComment( - m_plgviewMap[plg].second, begin, begin + length, - comment); - if (cmd) { + uc, begin, begin + length, comment); + if (uc == nullptr && cmd) { doc->pushMakeUndo(cmd); return true; } @@ -2160,10 +2165,10 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { auto e = pluginCurrentEditor(plg); if (e) { auto doc = e->hexEditor()->document(); - Q_ASSERT(m_plgviewMap.contains(plg)); + auto uc = pluginCurrentUndoCmd(plg); auto cmd = doc->metadata()->MakeForeground( - m_plgviewMap[plg].second, begin, begin + length, fgcolor); - if (cmd) { + uc, begin, begin + length, fgcolor); + if (uc == nullptr && cmd) { doc->pushMakeUndo(cmd); return true; } @@ -2179,10 +2184,10 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { auto e = pluginCurrentEditor(plg); if (e) { auto doc = e->hexEditor()->document(); - Q_ASSERT(m_plgviewMap.contains(plg)); + auto uc = pluginCurrentUndoCmd(plg); auto cmd = doc->metadata()->MakeBackground( - m_plgviewMap[plg].second, begin, begin + length, bgcolor); - if (cmd) { + uc, begin, begin + length, bgcolor); + if (uc == nullptr && cmd) { doc->pushMakeUndo(cmd); return true; } @@ -2263,10 +2268,9 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { auto e = pluginCurrentEditor(plg); if (e) { auto doc = e->hexEditor()->document(); - Q_ASSERT(m_plgviewMap.contains(plg)); - auto cmd = doc->MakeAddBookMark(m_plgviewMap[plg].second, - pos, comment); - if (cmd) { + auto uc = pluginCurrentUndoCmd(plg); + auto cmd = doc->MakeAddBookMark(uc, pos, comment); + if (uc == nullptr && cmd) { doc->pushMakeUndo(cmd); return true; } @@ -2281,10 +2285,9 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { auto e = pluginCurrentEditor(plg); if (e) { auto doc = e->hexEditor()->document(); - Q_ASSERT(m_plgviewMap.contains(plg)); - auto cmd = doc->MakeModBookMark(m_plgviewMap[plg].second, - pos, comment); - if (cmd) { + auto uc = pluginCurrentUndoCmd(plg); + auto cmd = doc->MakeModBookMark(uc, pos, comment); + if (uc == nullptr && cmd) { doc->pushMakeUndo(cmd); return true; } @@ -2299,10 +2302,9 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { auto e = pluginCurrentEditor(plg); if (e) { auto doc = e->hexEditor()->document(); - Q_ASSERT(m_plgviewMap.contains(plg)); - auto cmd = - doc->MakeRemoveBookMark(m_plgviewMap[plg].second, pos); - if (cmd) { + auto uc = pluginCurrentUndoCmd(plg); + auto cmd = doc->MakeRemoveBookMark(uc, pos); + if (uc == nullptr && cmd) { doc->pushMakeUndo(cmd); return true; } @@ -2316,9 +2318,9 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { auto e = pluginCurrentEditor(plg); if (e) { auto doc = e->hexEditor()->document(); - Q_ASSERT(m_plgviewMap.contains(plg)); - auto cmd = doc->MakeClearBookMark(m_plgviewMap[plg].second); - if (cmd) { + auto uc = pluginCurrentUndoCmd(plg); + auto cmd = doc->MakeClearBookMark(uc); + if (uc == nullptr && cmd) { doc->pushMakeUndo(cmd); return true; } @@ -2337,9 +2339,7 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { auto view = _win->newfileGUI(); if (view) { auto id = assginHandleForPluginView(plg, view); - auto &info = m_plgviewMap[plg]; - info.first = view; - info.second = nullptr; + m_plgCurrentfid[plg] = id; return ErrFile(int(*id)); } else { return ErrFile::Error; @@ -2361,9 +2361,7 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { return ErrFile::AlreadyOpened; } auto id = assginHandleForPluginView(plg, view); - auto &info = m_plgviewMap[plg]; - info.first = view; - info.second = nullptr; + m_plgCurrentfid[plg] = id; return ErrFile(int(*id)); } else { return ret; @@ -2386,9 +2384,7 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { return ErrFile::AlreadyOpened; } auto id = assginHandleForPluginView(plg, view); - auto &info = m_plgviewMap[plg]; - info.first = view; - info.second = nullptr; + m_plgCurrentfid[plg] = id; PluginSystem::instance().dispatchEvent( IWingPlugin::RegisteredEvent::PluginFileOpened, @@ -2418,9 +2414,7 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { return ErrFile::AlreadyOpened; } auto id = assginHandleForPluginView(plg, view); - auto &info = m_plgviewMap[plg]; - info.first = view; - info.second = nullptr; + m_plgCurrentfid[plg] = id; PluginSystem::instance().dispatchEvent( IWingPlugin::RegisteredEvent::PluginFileOpened, @@ -2450,9 +2444,7 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { return ErrFile::AlreadyOpened; } auto id = assginHandleForPluginView(plg, view); - auto &info = m_plgviewMap[plg]; - info.first = view; - info.second = nullptr; + m_plgCurrentfid[plg] = id; PluginSystem::instance().dispatchEvent( IWingPlugin::RegisteredEvent::PluginFileOpened, @@ -2481,9 +2473,7 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { return ErrFile::AlreadyOpened; } auto id = assginHandleForPluginView(plg, view); - auto &info = m_plgviewMap[plg]; - info.first = view; - info.second = nullptr; + m_plgCurrentfid[plg] = id; PluginSystem::instance().dispatchEvent( IWingPlugin::RegisteredEvent::PluginFileOpened, @@ -2576,9 +2566,8 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { } auto id = assginHandleForPluginView(plg, view); - auto &info = m_plgviewMap[plg]; - info.first = view; - info.second = nullptr; + m_plgCurrentfid[plg] = id; + return ErrFile(int(*id)); } return ErrFile::Error; @@ -2642,16 +2631,12 @@ void PluginSystem::connectControllerInterface(IWingPlugin *plg) { if (!checkThreadAff()) { return false; } - auto &maps = m_plgHandles[plg]; + auto &maps = m_plgviewMap[plg]; for (auto &item : maps) { - auto &bind = m_viewBindings[item.second]; - bind.removeOne(plg); - if (bind.isEmpty()) { - _win->closeEditor(item.second, true); - } + closeEditor(plg, item.fid, true); } - m_plgviewMap.remove(plg); - m_plgHandles.remove(plg); + m_plgCurrentfid[plg] = -1; + maps.clear(); return true; }); } @@ -2868,15 +2853,62 @@ void PluginSystem::loadAllPlugin() { loadExtPlugin(); } -EditorView *PluginSystem::pluginCurrentEditor(IWingPlugin *sender) const { - if (sender) { - QPair empty{nullptr, nullptr}; - auto editor = m_plgviewMap.value(sender, empty).first; - if (editor) { - return editor; - } else { +EditorView *PluginSystem::pluginCurrentEditor(IWingPlugin *plg) const { + if (plg) { + auto fid = m_plgCurrentfid[plg]; + if (fid < 0) { return _win->currentEditor(); } + + auto ctx = pluginContextById(plg, fid); + if (ctx) { + return ctx->view; + } + } + return nullptr; +} + +std::optional +PluginSystem::pluginContextById(IWingPlugin *plg, int fid) const { + if (fid < 0) { + return std::nullopt; + } + auto &handles = m_plgviewMap[plg]; + auto r = std::find_if( + handles.begin(), handles.end(), + [fid](const PluginFileContext &d) { return (*d.fid) == fid; }); + if (r == handles.end()) { + return std::nullopt; + } + return *r; +} + +std::optional::iterator> +PluginSystem::pluginContextByIdIt(IWingPlugin *plg, int fid) { + auto &handles = m_plgviewMap[plg]; + if (fid < 0) { + return std::nullopt; + } + auto r = std::find_if( + handles.begin(), handles.end(), + [fid](const PluginFileContext &d) { return (*d.fid) == fid; }); + if (r == handles.end()) { + return std::nullopt; + } + return r; +} + +QUndoCommand *PluginSystem::pluginCurrentUndoCmd(IWingPlugin *plg) const { + if (plg) { + auto fid = m_plgCurrentfid[plg]; + if (fid < 0) { + return nullptr; + } + + auto ctx = pluginContextById(plg, fid); + if (ctx) { + return ctx->cmd; + } } return nullptr; } diff --git a/src/plugin/pluginsystem.h b/src/plugin/pluginsystem.h index a884725..0c3364a 100644 --- a/src/plugin/pluginsystem.h +++ b/src/plugin/pluginsystem.h @@ -44,17 +44,23 @@ private: public: class UniqueId : public QSharedData { public: - UniqueId() : _id(0), _gen(nullptr) {} + UniqueId() : _id(-1), _gen(nullptr) {} UniqueId(UniqueIdGenerator *gen, int id) : _id(id), _gen(gen) { Q_ASSERT(gen); - Q_ASSERT(id > 0); + Q_ASSERT(id >= 0); +#ifdef QT_DEBUG + qDebug() << "[UniqueId] alloced: " << id; +#endif } ~UniqueId() { if (_gen) { _gen->release(_id); } +#ifdef QT_DEBUG + qDebug() << "[UniqueId] freed: " << _id; +#endif } operator int() { return _id; } @@ -65,7 +71,7 @@ private: }; public: - UniqueIdGenerator() : currentId(1) {} + UniqueIdGenerator() : currentId(0) {} QExplicitlySharedDataPointer get() { if (!releasedIds.isEmpty()) { @@ -113,6 +119,20 @@ public: }; Q_ENUM(PluginStatus) +private: + struct PluginFileContext { + SharedUniqueId fid; + EditorView *view = nullptr; + IWingPlugin *linkedplg = nullptr; + QUndoCommand *cmd = nullptr; + + ~PluginFileContext() { + if (cmd) { + delete cmd; + } + } + }; + public: static PluginSystem &instance(); @@ -194,7 +214,15 @@ private: static QString packLogMessage(const char *header, const QString &msg); - EditorView *pluginCurrentEditor(IWingPlugin *sender) const; + EditorView *pluginCurrentEditor(IWingPlugin *plg) const; + + std::optional + pluginContextById(IWingPlugin *plg, int fid) const; + + std::optional::iterator> + pluginContextByIdIt(IWingPlugin *plg, int fid); + + QUndoCommand *pluginCurrentUndoCmd(IWingPlugin *plg) const; private: void loadPlugin(IWingPlugin *p, PluginInfo &meta, @@ -246,17 +274,15 @@ private: bool insertBasicTypeContent(IWingPlugin *plg, qsizetype offset, const T &value) { Q_STATIC_ASSERT(std::is_integral_v || std::is_floating_point_v); - QPair empty{nullptr, nullptr}; - auto mapitem = m_plgviewMap.value(plg, empty); - auto e = mapitem.first; + auto e = getCurrentPluginView(plg); if (e) { auto editor = e->hexEditor(); auto doc = editor->document(); auto buffer = reinterpret_cast(&value); - - auto cmd = doc->MakeInsert(mapitem.second, editor->cursor(), offset, + auto uc = pluginCurrentUndoCmd(plg); + auto cmd = doc->MakeInsert(uc, editor->cursor(), offset, QByteArray(buffer, sizeof(T))); - if (mapitem.second == nullptr && cmd) { + if (uc == nullptr && cmd) { _rwlock.lockForWrite(); doc->pushMakeUndo(cmd); _rwlock.unlock(); @@ -270,17 +296,15 @@ private: bool writeBasicTypeContent(IWingPlugin *plg, qsizetype offset, const T &value) { Q_STATIC_ASSERT(std::is_integral_v || std::is_floating_point_v); - QPair empty{nullptr, nullptr}; - auto mapitem = m_plgviewMap.value(plg, empty); - auto e = mapitem.first; + auto e = getCurrentPluginView(plg); if (e) { auto editor = e->hexEditor(); auto doc = editor->document(); auto buffer = reinterpret_cast(&value); - - auto cmd = doc->MakeReplace(mapitem.second, editor->cursor(), - offset, QByteArray(buffer, sizeof(T))); - if (mapitem.second == nullptr && cmd) { + auto uc = pluginCurrentUndoCmd(plg); + auto cmd = doc->MakeReplace(uc, editor->cursor(), offset, + QByteArray(buffer, sizeof(T))); + if (uc == nullptr && cmd) { _rwlock.lockForWrite(); doc->pushMakeUndo(cmd); _rwlock.unlock(); @@ -293,17 +317,15 @@ private: template bool appendBasicTypeContent(IWingPlugin *plg, const T &value) { Q_STATIC_ASSERT(std::is_integral_v || std::is_floating_point_v); - QPair empty{nullptr, nullptr}; - auto mapitem = m_plgviewMap.value(plg, empty); - auto e = mapitem.first; + auto e = getCurrentPluginView(plg); if (e) { auto editor = e->hexEditor(); auto doc = editor->document(); auto buffer = reinterpret_cast(&value); - - auto cmd = doc->MakeAppend(mapitem.second, editor->cursor(), + auto uc = pluginCurrentUndoCmd(plg); + auto cmd = doc->MakeAppend(uc, editor->cursor(), QByteArray(buffer, sizeof(T))); - if (mapitem.second == nullptr && cmd) { + if (uc == nullptr && cmd) { _rwlock.lockForWrite(); doc->pushMakeUndo(cmd); _rwlock.unlock(); @@ -331,9 +353,8 @@ private: QMap> _evplgs; - QHash> m_plgviewMap; - QHash>> - m_plgHandles; + QHash> m_plgviewMap; + QHash m_plgCurrentfid; // fid QHash> m_viewBindings; UniqueIdGenerator m_idGen; diff --git a/src/translist.md b/src/translist.md index b753eed..0808911 100644 --- a/src/translist.md +++ b/src/translist.md @@ -1,2 +1,3 @@ * 简体中文:寂静的羽夏(wingsummer) +* 繁體中文:寂靜的羽夏(wingsummer)【通過繁簡文字轉化工具】