From 6678c7b9ff8831f71e52a74c05bd21e01c75c952 Mon Sep 17 00:00:00 2001 From: wingsummer <1326224942@qq.com> Date: Sat, 26 Jul 2025 19:34:51 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=8D=81=E5=85=AD=E8=BF=9B=E5=88=B6?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E5=8C=BA=E6=B3=A8=E5=86=8C=E7=9A=84=E8=8F=9C?= =?UTF-8?q?=E5=8D=95=E6=94=AF=E6=8C=81=E7=BC=96=E8=BE=91=E5=99=A8=E4=B8=8A?= =?UTF-8?q?=E4=B8=8B=E6=96=87=EF=BC=9B=E7=94=A8=E6=88=B7=E4=BA=A4=E4=BA=92?= =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 5 +- TestHexExt/testhexext.cpp | 35 +- TestHexExt/testhexext.h | 12 +- WingPlugin | 2 +- lang/zh_CN/winghex_zh_CN.ts | 755 +++++++++++++++--------------- lang/zh_TW/winghex_zh_TW.ts | 755 +++++++++++++++--------------- main.cpp | 147 +++++- mkinstaller/config.ini | 60 +++ src/class/ascompletion.cpp | 1 - src/class/aspreprocesser.cpp | 283 ++++------- src/class/aspreprocesser.h | 8 +- src/class/consolehighlighanim.cpp | 98 ++++ src/class/consolehighlighanim.h | 55 +++ src/class/editorviewcontext.cpp | 6 +- src/class/editorviewcontext.h | 1 + src/class/pluginsystem.cpp | 39 +- src/class/pluginsystem.h | 2 + src/control/editorview.cpp | 45 +- src/control/editorview.h | 3 +- src/define.h | 3 +- src/dialog/mainwindow.cpp | 22 +- src/dialog/mainwindow.h | 3 + theme/dark/stylesheet.qss | 6 +- theme/light/stylesheet.qss | 6 +- 24 files changed, 1351 insertions(+), 1001 deletions(-) create mode 100644 mkinstaller/config.ini create mode 100644 src/class/consolehighlighanim.cpp create mode 100644 src/class/consolehighlighanim.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3311bb2..9fe0d41 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,7 @@ option(BUILD_TEST_PLUGIN OFF) option(BUILD_SHARED_MEM_EXT OFF) add_definitions(-DAS_NO_THREADS) +add_definitions(-DWING_SYSTEM_NAME="${CMAKE_SYSTEM_NAME}") if(BUILD_TEST_PLUGIN) add_subdirectory(TestPlugin) @@ -308,7 +309,9 @@ set(CLASS_SRC src/class/changedstringlist.h src/class/changedstringlist.cpp src/class/editorviewcontext.h - src/class/editorviewcontext.cpp) + src/class/editorviewcontext.cpp + src/class/consolehighlighanim.h + src/class/consolehighlighanim.cpp) set(INTERNAL_PLG_SRC src/class/wingangelapi.h src/class/wingangelapi.cpp diff --git a/TestHexExt/testhexext.cpp b/TestHexExt/testhexext.cpp index bf17633..b5a1995 100644 --- a/TestHexExt/testhexext.cpp +++ b/TestHexExt/testhexext.cpp @@ -31,6 +31,7 @@ TestHexExt::TestHexExt() : WingHex::IWingHexEditorPlugin() { a->setChecked(true); connect(a, &QAction::toggled, this, &TestHexExt::setColVisible); m_context->addAction(a); + m_aVisCol = a; } bool TestHexExt::init(const std::unique_ptr &set) { @@ -52,7 +53,8 @@ TestHexExt::registeredRibbonTools() const { } QMargins TestHexExt::contentMargins(WingHex::HexEditorContext *context) const { - if (!_visCol) { + auto visCol = context->property("TestHexExt.colVis").toBool(); + if (!visCol) { return {}; } auto lines = context->documentLines(); @@ -65,9 +67,23 @@ QMargins TestHexExt::contentMargins(WingHex::HexEditorContext *context) const { return {int(colLen) + 1, 0, 0, 0}; } +void TestHexExt::prepareCallEditorContext(WingHex::HexEditorContext *context) { + _curContext = context; + auto b = isShowLinePannel(context); + m_aVisCol->blockSignals(true); + m_aVisCol->setChecked(b); + m_aVisCol->blockSignals(false); +} + +void TestHexExt::finishCallEditorContext(WingHex::HexEditorContext *context) { + Q_UNUSED(context); + _curContext = nullptr; +} + void TestHexExt::onPaintEvent(QPainter *painter, const QWidget *w, WingHex::HexEditorContext *context) { - if (!_visCol) { + auto visCol = isShowLinePannel(context); + if (!visCol) { return; } painter->save(); @@ -104,4 +120,17 @@ void TestHexExt::onPaintEvent(QPainter *painter, const QWidget *w, painter->restore(); } -void TestHexExt::setColVisible(bool b) { _visCol = b; } +bool TestHexExt::isShowLinePannel(WingHex::HexEditorContext *context) { + auto pp = context->property("TestHexExt.colVis"); + if (pp.isNull()) { + context->setProperty("TestHexExt.colVis", true); + return true; + } + return pp.toBool(); +} + +void TestHexExt::setColVisible(bool b) { + if (_curContext) { + _curContext->setProperty("TestHexExt.colVis", b); + } +} diff --git a/TestHexExt/testhexext.h b/TestHexExt/testhexext.h index 7b8ad56..7405ef8 100644 --- a/TestHexExt/testhexext.h +++ b/TestHexExt/testhexext.h @@ -52,16 +52,26 @@ public: virtual QMargins contentMargins(WingHex::HexEditorContext *context) const override; +public: + virtual void + prepareCallEditorContext(WingHex::HexEditorContext *context) override; + virtual void + finishCallEditorContext(WingHex::HexEditorContext *context) override; + public: virtual void onPaintEvent(QPainter *painter, const QWidget *w, WingHex::HexEditorContext *context) override; +private: + bool isShowLinePannel(WingHex::HexEditorContext *context); + private slots: void setColVisible(bool b); private: QMenu *m_context; - bool _visCol = true; + QAction *m_aVisCol; + WingHex::HexEditorContext *_curContext = nullptr; }; #endif // TESTHEXEXT_H diff --git a/WingPlugin b/WingPlugin index fad7748..4492bf2 160000 --- a/WingPlugin +++ b/WingPlugin @@ -1 +1 @@ -Subproject commit fad774858664d6a137c21b0c2af73ca209cc2f47 +Subproject commit 4492bf2aaba267b80ec324c456f0584dcd0efc03 diff --git a/lang/zh_CN/winghex_zh_CN.ts b/lang/zh_CN/winghex_zh_CN.ts index f4eb9bd..7712af6 100644 --- a/lang/zh_CN/winghex_zh_CN.ts +++ b/lang/zh_CN/winghex_zh_CN.ts @@ -97,6 +97,82 @@ + + AsPreprocesser + + + IfDefNoWord + ifdef 未定义宏 + + + + IfDefInvalidWord + ifdef 非法宏 + + + + CalIfFailed + 宏条件判断发生错误 + + + + + + + + + UnexceptedToken + 非法标识 + + + + + InvalidDef + 无效定义 + + + + ReservedMarcoType + 被保留的宏样式 + + + + MarcoNotFound: + 宏未找到: + + + + + NoMatchingIf + 未匹配的宏条件 + + + + DupElseDef + 重复的另外条件宏 + + + + + Invalid file name for #include; it contains a line-break: + #include 的文件名无效;它包含换行符: + + + + Invalid file name for #include; it contains a line-break or unpaired symbol + #include 的文件名无效;它包含换行符或不成对的符号 + + + + Invalid #pragma directive + #pragma 指令无效 + + + + Failed to open script file + 打开脚本文件失败 + + BookMarkAddCommand @@ -515,7 +591,7 @@ 未命名 - + Not allowed operation in non-UI thread 该操作在非 UI 线程非法 @@ -901,7 +977,7 @@ - + View 视图 @@ -912,7 +988,7 @@ - + WingHexExplorer 羽云十六进制编辑器 @@ -938,8 +1014,8 @@ - - + + Plugin 插件 @@ -949,300 +1025,300 @@ 设置 - - + + Log 日志 - + ExportFindResult 导出搜索结果 - + ClearFindResult 清空记录 - - + + FindResult 搜索结果 - - - - - - - + + + + + + + Copy 复制 - - - - - + + + + + CopyToClipBoard 数据已拷贝到粘贴板 - + LittleEndian 小端 - + BigEndian 大端 - + Number 数值 - - + + CheckSum 校验和 - - + + DeleteBookMark 删除书签 - - + + ClearBookMark 清空书签 - - - - + + + + BookMark 书签 - - + + DecodeText 解码字符串 - + ScriptConsole 脚本控制台 - - + + Basic 基础 - + New 新建 - + OpenF 打开文件 - + OpenWorkSpace 打开工作区 - + RecentFiles 最近打开 - - - + + + Reload 重新加载 - - + + Save 保存 - + SaveAs 另存为 - + ConvertWS 转为工作区 - + Export 导出 - + SaveSel 保存选区字节 - - - - + + + + General 基本 - + Undo 撤销 - + Redo 恢复 - + Cut 剪切 - + Paste 粘贴 - + Delete 删除 - + Clone 克隆 - + Lookup 查询 - + Find 查找 - + Goto 跳转 - - + + Encoding 编码 - + FileInfo 文件信息 - - + + Hex 十六进制 - + CutHex 剪切(十六进制) - + CopyHex 复制(十六进制) - + PasteHex 粘贴(十六进制) - - + + Fill 填充 - + FillZero 填充零 - - - - - + + + + + MetaData 标注 - + DeleteMetadata 删除标注 - + ClearMetadata 清空标注 - + MetaDataEdit 编辑标注 - + DeleteMetaData 删除标注 - + ClearMetaData 清空标注 - + Display 显示 - + ViewText 文本预览 - + Scale 缩放 @@ -1322,87 +1398,87 @@ 启动完毕 - + NoExtension 无扩展 - - + + ExportResult 导出结果 - + NothingToSave 没有保存的数据 - + OpenExt 打开 - 拓展 - + ResetScale 重置缩放 - + ShowMetafg 标注前景色 - + ShowMetabg 标注背景色 - + ShowMetaComment 批注 - + MetaShowAll 显示所有标注 - + MetaHideAll 隐藏所有标注 - + FileStatus 文件状态 - + InfoSave 是否保存 - + ReadOnly 可读写 - + SetLocked 启用/禁用锁定编辑 - + ErrUnLock 锁定编辑失败 - + SetOver 启用/禁用改变大小 @@ -1417,198 +1493,198 @@ 脚本引擎启动失败,将自动禁用该功能。 - + UnsignedHex 无符号 Hex - + BgScriptOutputHere 后台脚本执行将会在这里输出 - + SelectAll 全选 - - + + Clear 清空 - + AbortScript 终止脚本 - + BgScriptOutput 后台脚本输出 - + ErrUnOver 锁定文件大小失败 - + Window 窗体 - + Editor 编辑器 - + Tools 工具 - + HexEditorLayout 编辑器布局 - + SetBaseAddr 设置基址 - + addressBase 基址 - + inputAddressBase 请输入基址 - + WarnBigBaseAddress 基址过大,你得到的地址将会不正确! - + ErrBaseAddress 非法基址输入 - + SetColInfo 显示/隐藏地址栏 - + SetHeaderInfo 显示/隐藏表头 - + SetAsciiString 显示/隐藏解码字符串 - + Layout 布局 - + Fullscreen 全屏 - + Default 默认 - - + + LayoutRestoring... 恢复布局中... - + RestoreLayout 恢复布局 - - + + SaveLayout 保存布局 - - + + ExportLog 导出日志 - - + + ClearLog 清空日志 - + InsepctQt 监视 Qt - + ScriptEditor 脚本编辑器 - + Scripts 脚本仓库 - + PluginFunctions 插件功能 - + ScriptSetting 脚本设置 - + PluginSettings 插件设置 - + Info 信息 - + Software 软件 - + Sponsor 赞助 - + CheckUpdate 检查更新 - + Wiki 网页 Wiki @@ -1618,506 +1694,506 @@ - + UndoStack - + 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 选择文件 - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + Error 错误 - - + + FileNotExist 文件不存在! - - - - - + + + + + FilePermission 因文件权限无法继续! - + ProjectFile (*.wingpro) 项目文件 (*.wingpro) - + ReloadSuccessfully 文件重新加载成功! - + ReloadUnSuccessfully 文件重新加载失败! - - - - + + + + ChooseSaveFile 请选择保存文件路径: - + PasteFailedNote 粘贴失败,请注意权限或者内容长度 - + NoMoreClone 克隆已到上限,无法继续操作! - + FindFininishBusy 查找任务繁忙,请勿重复查找! - + MayTooMuchFindResult 搜索数量已到达上限,结果可能不全,建议请按区段搜索。 - + SaveLayoutSuccess 保存布局成功 - + SaveLayoutError 保存布局失败 - + HasClonedView 该编辑页已被克隆编辑,如果关闭,相关联的页也会被关闭,你确认继续吗? - + [MetaAdd] - + 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 打开文件出现错误(由于权限不足),如下为打开错误的文件: @@ -2442,7 +2518,7 @@ 加载插件失败:损坏的插件数据 - + PluginBlockByManager @@ -2474,14 +2550,14 @@ 插件加载失败:非法插件 SDK 版本! - + ErrLoadPluginNoName 插件加载失败:非法插件名称! - + ErrLoadInitPlugin 插件加载失败:初始化插件失败! @@ -2491,73 +2567,73 @@ - + PluginName : 插件名: - + PluginAuthor : 插件作者: - + PluginWidgetRegister 注册插件对象中…… - + ExtPluginAuthor : 设备拓展插件作者: - + ExtPluginWidgetRegister 设备拓展注册插件对象中…… - + ErrLoadInitExtPlugin 设备拓展插件加载失败:初始化插件失败! - + ChooseFile 选择文件 - - + + Error 错误 - + FileNotExist 文件不存在! - + FilePermission 因文件权限无法继续! - + EmptyNameDockWidget: 空的贴边组件名: - + InvalidNameDockWidget: 无效贴边组件名: - + InvalidNullDockWidget: 无效空贴边组件: - + Not allowed operation in non-UI thread 该操作在非 UI 线程非法 @@ -2804,79 +2880,6 @@ Close Tab 关闭标签 - - - Failed to open script file - 打开脚本文件失败 - - - - - Invalid file name for #include; it contains a line-break: - #include 的文件名无效;它包含换行符: - - - - IfDefNoWord - ifdef 未定义宏 - - - - IfDefInvalidWord - ifdef 非法宏 - - - - - - - - - UnexceptedToken - 非法标识 - - - - CalIfFailed - 宏条件判断发生错误 - - - - - InvalidDef - 无效定义 - - - - ReservedMarcoType - 被保留的宏样式 - - - - MarcoNotFound: - 宏未找到: - - - - - NoMatchingIf - 未匹配的宏条件 - - - - DupElseDef - 重复的另外条件宏 - - - - Invalid file name for #include; it contains a line-break or unpaired symbol - #include 的文件名无效;它包含换行符或不成对的符号 - - - - Invalid #pragma directive - #pragma 指令无效 - RecentFileManager diff --git a/lang/zh_TW/winghex_zh_TW.ts b/lang/zh_TW/winghex_zh_TW.ts index c7d4fb4..5525bf5 100644 --- a/lang/zh_TW/winghex_zh_TW.ts +++ b/lang/zh_TW/winghex_zh_TW.ts @@ -97,6 +97,82 @@ + + AsPreprocesser + + + IfDefNoWord + ifdef 未定義宏 + + + + IfDefInvalidWord + ifdef 非法宏 + + + + CalIfFailed + 宏條件判斷發生錯誤 + + + + + + + + + UnexceptedToken + 非法標識 + + + + + InvalidDef + 無效定義 + + + + ReservedMarcoType + 被保留的宏樣式 + + + + MarcoNotFound: + 宏未找到: + + + + + NoMatchingIf + 未匹配的宏條件 + + + + DupElseDef + 重複的另外條件宏 + + + + + Invalid file name for #include; it contains a line-break: + #include 的檔案名無效;它包含換行符: + + + + Invalid file name for #include; it contains a line-break or unpaired symbol + #include 的檔案名無效;它包含換行符或不成對的符號 + + + + Invalid #pragma directive + #pragma 指令無效 + + + + Failed to open script file + 打開腳本檔失敗 + + BookMarkAddCommand @@ -515,7 +591,7 @@ 未命名 - + Not allowed operation in non-UI thread 該操作在非 UI 線程非法 @@ -901,7 +977,7 @@ - + View 視圖 @@ -912,7 +988,7 @@ - + WingHexExplorer 羽雲十六進制編輯器 @@ -938,8 +1014,8 @@ - - + + Plugin 插件 @@ -949,300 +1025,300 @@ 設置 - - + + Log 日誌 - + ExportFindResult 導出搜索結果 - + ClearFindResult 清空記錄 - - + + FindResult 搜索結果 - - - - - - - + + + + + + + Copy 複製 - - - - - + + + + + CopyToClipBoard 數據已拷貝到粘貼板 - + LittleEndian 小端 - + BigEndian 大端 - + Number 數值 - - + + CheckSum 校驗和 - - + + DeleteBookMark 刪除書簽 - - + + ClearBookMark 清空書簽 - - - - + + + + BookMark 書簽 - - + + DecodeText 解碼字串 - + ScriptConsole 腳本控制臺 - - + + Basic 基礎 - + New 新建 - + OpenF 打開檔 - + OpenWorkSpace 打開工作區 - + RecentFiles 最近打開 - - - + + + Reload 重新加載 - - + + Save 保存 - + SaveAs 另存為 - + ConvertWS 轉為工作區 - + Export 導出 - + SaveSel 保存選區位元組 - - - - + + + + General 基本 - + Undo 撤銷 - + Redo 恢復 - + Cut 剪切 - + Paste 粘貼 - + Delete 刪除 - + Clone 克隆 - + Lookup 查詢 - + Find 查找 - + Goto 跳轉 - - + + Encoding 編碼 - + FileInfo 檔資訊 - - + + Hex 十六進制 - + CutHex 剪切(十六進制) - + CopyHex 複製(十六進制) - + PasteHex 粘貼(十六進制) - - + + Fill 填充 - + FillZero 填充零 - - - - - + + + + + MetaData 標注 - + DeleteMetadata 刪除標注 - + ClearMetadata 清空標注 - + MetaDataEdit 編輯標注 - + DeleteMetaData 刪除標注 - + ClearMetaData 清空標注 - + Display 顯示 - + ViewText 文本預覽 - + Scale 縮放 @@ -1322,87 +1398,87 @@ 啟動完畢 - + NoExtension 無擴展 - - + + ExportResult 導出結果 - + NothingToSave 沒有保存的數據 - + OpenExt 打開 - 拓展 - + ResetScale 重置縮放 - + ShowMetafg 標注前景色 - + ShowMetabg 標注背景色 - + ShowMetaComment 批註 - + MetaShowAll 顯示所有標注 - + MetaHideAll 隱藏所有標注 - + FileStatus 檔狀態 - + InfoSave 是否保存 - + ReadOnly 可讀寫 - + SetLocked 啟用/禁用鎖定編輯 - + ErrUnLock 鎖定編輯失敗 - + SetOver 啟用/禁用改變大小 @@ -1417,198 +1493,198 @@ 腳本引擎啟動失敗,將自動禁用該功能。 - + UnsignedHex 無符號 Hex - + BgScriptOutputHere 後臺腳本執行將會在這裏輸出 - + SelectAll 全選 - - + + Clear 清空 - + AbortScript 終止腳本 - + BgScriptOutput 後臺腳本輸出 - + ErrUnOver 鎖定檔大小失敗 - + Window 窗體 - + Editor 編輯器 - + Tools 工具 - + HexEditorLayout 編輯器佈局 - + SetBaseAddr 設置基址 - + addressBase 基址 - + inputAddressBase 請輸入基址 - + WarnBigBaseAddress 基址過大,你得到的地址將會不正確! - + ErrBaseAddress 非法基址輸入 - + SetColInfo 顯示/隱藏地址欄 - + SetHeaderInfo 顯示/隱藏表頭 - + SetAsciiString 顯示/隱藏解碼字串 - + Layout 佈局 - + Fullscreen 全屏 - + Default 默認 - - + + LayoutRestoring... 恢復佈局中... - + RestoreLayout 恢復佈局 - - + + SaveLayout 保存佈局 - - + + ExportLog 導出日誌 - - + + ClearLog 清空日誌 - + InsepctQt 監視 Qt - + ScriptEditor 腳本編輯器 - + Scripts 腳本倉庫 - + PluginFunctions 插件功能 - + ScriptSetting 腳本設置 - + PluginSettings 插件設置 - + Info 資訊 - + Software 軟體 - + Sponsor 贊助 - + CheckUpdate 檢查更新 - + Wiki 網頁 Wiki @@ -1618,506 +1694,506 @@ - + UndoStack - + 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 選擇檔 - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + Error 錯誤 - - + + FileNotExist 檔不存在! - - - - - + + + + + FilePermission 因檔許可權無法繼續! - + ProjectFile (*.wingpro) 專案檔 (*.wingpro) - + ReloadSuccessfully 檔重新加載成功! - + ReloadUnSuccessfully 檔重新加載失敗! - - - - + + + + ChooseSaveFile 請選擇保存檔路徑: - + PasteFailedNote 粘貼失敗,請注意許可權或者內容長度 - + NoMoreClone 克隆已到上限,無法繼續操作! - + FindFininishBusy 查找任務繁忙,請勿重複查找! - + MayTooMuchFindResult 搜索數量已到達上限,結果可能不全,建議請按區段搜索。 - + SaveLayoutSuccess 保存佈局成功 - + SaveLayoutError 保存佈局失敗 - + HasClonedView 該編輯頁已被克隆編輯,如果關閉,相關聯的頁也會被關閉,你確認繼續嗎? - + [MetaAdd] - + 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 打開檔出現錯誤(由於許可權不足),如下為打開錯誤的檔: @@ -2442,7 +2518,7 @@ 加載插件失敗:損壞的插件數據 - + PluginBlockByManager @@ -2474,14 +2550,14 @@ 插件加載失敗:非法插件 SDK 版本! - + ErrLoadPluginNoName 插件加載失敗:非法插件名稱! - + ErrLoadInitPlugin 插件加載失敗:初始化插件失敗! @@ -2491,73 +2567,73 @@ - + PluginName : 插件名: - + PluginAuthor : 插件作者: - + PluginWidgetRegister 註冊插件對象中…… - + ExtPluginAuthor : 設備拓展插件作者: - + ExtPluginWidgetRegister 設備拓展註冊插件對象中…… - + ErrLoadInitExtPlugin 設備拓展插件加載失敗:初始化插件失敗! - + ChooseFile 選擇檔 - - + + Error 錯誤 - + FileNotExist 檔不存在! - + FilePermission 因檔許可權無法繼續! - + EmptyNameDockWidget: 空的貼邊組件名: - + InvalidNameDockWidget: 無效貼邊組件名: - + InvalidNullDockWidget: 無效空貼邊組件: - + Not allowed operation in non-UI thread 該操作在非 UI 線程非法 @@ -2804,79 +2880,6 @@ Close Tab 關閉標籤 - - - Failed to open script file - 打開腳本檔失敗 - - - - - Invalid file name for #include; it contains a line-break: - #include 的檔案名無效;它包含換行符: - - - - IfDefNoWord - ifdef 未定義宏 - - - - IfDefInvalidWord - ifdef 非法宏 - - - - - - - - - UnexceptedToken - 非法標識 - - - - CalIfFailed - 宏條件判斷發生錯誤 - - - - - InvalidDef - 無效定義 - - - - ReservedMarcoType - 被保留的宏樣式 - - - - MarcoNotFound: - 宏未找到: - - - - - NoMatchingIf - 未匹配的宏條件 - - - - DupElseDef - 重複的另外條件宏 - - - - Invalid file name for #include; it contains a line-break or unpaired symbol - #include 的檔案名無效;它包含換行符或不成對的符號 - - - - Invalid #pragma directive - #pragma 指令無效 - RecentFileManager diff --git a/main.cpp b/main.cpp index e867d33..67534fc 100644 --- a/main.cpp +++ b/main.cpp @@ -1,8 +1,118 @@ #include "class/appmanager.h" +#include "class/languagemanager.h" #include "class/settingmanager.h" +#include "class/wingmessagebox.h" #include "define.h" +#include +#include +#include + +void loadEnvConfig(int argc, char *argv[]) { + QFileInfo info(argv[0]); + QDir appDir(info.absoluteDir()); + + if (!appDir.exists(QStringLiteral("config.ini"))) { + return; + } + + auto path = appDir.absoluteFilePath(QStringLiteral("config.ini")); + QSettings set(path, QSettings::IniFormat); + + // General + for (auto &kv : set.childKeys()) { + qputenv(qPrintable(kv), set.value(kv).toByteArray()); + } + + auto groups = set.childGroups(); + auto evaluate = [](const QProcessEnvironment &env, + const QString &statement) { + // Parse and evaluate statements: + // $NAME -> check existence + // $NAME=VALUE -> ignore-case full match + // $NAME==VALUE -> case-sensitive full match + // $NAME:=VALUE -> ignore-case contains + // $NAME::=VALUE -> case-sensitive contains + // VALUE: unless pure digits, must be enclosed in "" or '' + + static const QRegularExpression re( + R"(^\$([A-Za-z_][A-Za-z0-9_]*)(?:\s*(==|::=|:=|=)\s*(\d+|"[^"]*"|'[^']*'))?$)"); + auto match = re.match(statement); + if (!match.hasMatch()) { + qWarning("[main::loadEnvConfig] Invalid syntax: %s", + qUtf8Printable(statement)); + return false; + } + + auto name = match.captured(1); + auto op = match.captured(2); + auto value = match.captured(3); + + // Existence check: no operator provided + if (op.isEmpty()) { + return env.contains(name); + } + + if (!value.isEmpty() && + ((value.startsWith('"') && value.endsWith('"')) || + (value.startsWith('\'') && value.endsWith('\'')))) { + value.removeFirst().removeLast(); + } + + auto var = env.value(name); + + // Evaluate based on operator + if (op == QStringLiteral(":=") || op == QStringLiteral("::=")) { + const QStringList items = var.split(QDir::listSeparator()); + for (const QString &item : items) { + if (op == QStringLiteral(":=")) { + if (item.contains(value, Qt::CaseInsensitive)) { + return true; + } + } else { + if (item.contains(value, Qt::CaseSensitive)) { + return true; + } + } + } + return false; + } + + if (op == "=") { + return QString::compare(var, value, Qt::CaseInsensitive) == 0; + } else if (op == "==") { + return var == value; + } else { + qWarning("[main::loadEnvConfig] Unknown operator: %s", + qUtf8Printable(op)); + } + + return false; + }; + + auto env = QProcessEnvironment::systemEnvironment(); + + constexpr auto syslen = std::char_traits::length(WING_SYSTEM_NAME); + if (syslen) { + set.beginGroup(WING_SYSTEM_NAME); + for (auto &kv : set.childKeys()) { + qputenv(qPrintable(kv), set.value(kv).toByteArray()); + } + set.endGroup(); + } + + for (auto &g : groups) { + if (evaluate(env, g)) { + set.beginGroup(g); + for (auto &kv : set.childKeys()) { + qputenv(qPrintable(kv), set.value(kv).toByteArray()); + } + set.endGroup(); + } + } +} + int main(int argc, char *argv[]) { /* 有关对在 QT5 的 Win 平台禁用高 dpi 支持 * 的原因说明: @@ -18,23 +128,13 @@ int main(int argc, char *argv[]) { QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); #endif + loadEnvConfig(argc, argv); + QApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); -#ifdef Q_OS_LINUX - // fix wayland issue (a workaround): floating dock not work - // reference: - // https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/ - // issues/714#issuecomment-2802752677 - auto denv = qgetenv("XDG_SESSION_TYPE"); - if (denv.isEmpty() || - denv.compare(QByteArrayLiteral("wayland"), Qt::CaseInsensitive) == 0) { - qputenv("QT_QPA_PLATFORM", "xcb"); - } -#endif - - QApplication::setApplicationName(APP_NAME); - QApplication::setOrganizationName(APP_ORG); - QApplication::setApplicationVersion(WINGHEX_VERSION); + QApplication::setApplicationName(QStringLiteral(APP_NAME)); + QApplication::setOrganizationName(QStringLiteral(APP_ORG)); + QApplication::setApplicationVersion(QStringLiteral(WINGHEX_VERSION)); try { AppManager a(argc, argv); @@ -61,5 +161,22 @@ int main(int argc, char *argv[]) { return a.exec(); } catch (CrashCode errCode) { return int(errCode); + } catch (const std::bad_alloc &) { + auto &lang = LanguageManager::instance(); + auto df = lang.defaultLocale(); + + // this exception can only occur when your memory are too limit or + // you are writing more than 2GB with QByteArray on 32-bit operating + // system. + if (QLocale::China == df.territory()) { + WingMessageBox::critical( + nullptr, QStringLiteral(APP_NAME), + QStringLiteral("崩溃啦!发生内存溢出异常!")); + } else { + WingMessageBox::critical( + nullptr, QStringLiteral(APP_NAME), + QStringLiteral("WingHexExplorer2 is out of memory. Crashed!")); + } + return int(CrashCode::OutofMemory); } } diff --git a/mkinstaller/config.ini b/mkinstaller/config.ini new file mode 100644 index 0000000..5c7181b --- /dev/null +++ b/mkinstaller/config.ini @@ -0,0 +1,60 @@ +; ========= 羽云十六进制编辑器2应用环境配置文件说明 ========== +; +; 如果区块名开头没有 $ ,则认为普通区块,General 会在所有的操作系统生效 +; 如果你想在某些操作系统生效,可以指定区块名为:Windows, Linux 和 Darwin +; 对于 Linux 系统,如果包含 uname 工具,则区块名为 uname -s 的输出结果 +; + +; ================= 配置文件区块扩展语法说明 ================= +; +; 语句格式: +; $NAME [OPERATOR VALUE] +; +; 各字段说明: +; $ • 语句起始标记,必需 +; +; NAME • 环境变量名 +; • 以字母或“_”开头,后续可包含字母、数字或“_” +; +; OPERATOR • 可选运算符: +; = 忽略大小写全匹配 +; == 区分大小写全匹配 +; := 忽略大小写子串包含 +; ::= 区分大小写子串包含 +; +; VALUE • 可选比较值,仅在 OPERATOR 存在时使用 +; • 格式必须是: +; — 纯数字(例如 12345) +; — 或用双引号包裹的字符串("text") +; — 或用单引号包裹的字符串('text') +; +; 存在性检查: +; 若仅写 “$NAME”,无 OPERATOR 和 VALUE,即检查该环境变量是否已定义 +; +; --------------------- 示例 --------------------- +; $XDG_SESSION_TYPE="wayland" +; → 忽略大小写地检查 XDG_SESSION_TYPE 是否等于 “wayland” +; +; $PATH:="/usr/local/bin" +; → 忽略大小写地检查 PATH 中是否包含 “/usr/local/bin” +; +; $HOME==12345 +; → 区分大小写地检查 HOME 是否等于数字 12345 +; +; $LD_LIBRARY_PATH::="/lib64" +; → 区分大小写地检查 LD_LIBRARY_PATH 中是否包含 “/lib64” +; +; $HOME +; → 检查 HOME 是否已定义(存在性检查) +; ===================================================== + +[General] +WING_DISABLE_PLUGIN_SYSTEM=0 +WING_DISABLE_EXTDRV=0 +WING_DISABLE_PLUGIN=0 +WING_DEBUG=0 + +[$XDG_SESSION_TYPE="wayland"] +QT_QPA_PLATFORM=xcb + + diff --git a/src/class/ascompletion.cpp b/src/class/ascompletion.cpp index 72dbf57..bfb65fc 100644 --- a/src/class/ascompletion.cpp +++ b/src/class/ascompletion.cpp @@ -497,7 +497,6 @@ QList AsCompletion::parseDocument() { // first preprocess the code AsPreprocesser prepc(engine); - prepc.setIsCodeCompleteMode(true); prepc.setIncludeCallback(&AsCompletion::includeCallBack, this); auto r = prepc.loadSectionFromMemory(QStringLiteral("ASCOMPLETION"), diff --git a/src/class/aspreprocesser.cpp b/src/class/aspreprocesser.cpp index a0f6822..0806ce9 100644 --- a/src/class/aspreprocesser.cpp +++ b/src/class/aspreprocesser.cpp @@ -186,13 +186,15 @@ int AsPreprocesser::processScriptSection(const QByteArray &script, QStack> m_condtionStack; + bool isEndLine = true; + while (pos < modifiedScript.size()) { auto SECTION = sectionname.toUtf8(); asUINT len = 0; asETokenClass t = engine->ParseToken(modifiedScript.data() + pos, modifiedScript.size() - pos, &len); - if (t == asTC_UNKNOWN && modifiedScript[pos] == '#' && + if (isEndLine && t == asTC_UNKNOWN && modifiedScript[pos] == '#' && (pos + 1 < modifiedScript.size())) { int start = pos++; @@ -217,12 +219,7 @@ int AsPreprocesser::processScriptSection(const QByteArray &script, if (std::any_of(modifiedScript.data() + pos, modifiedScript.data() + pos + len, [](char ch) { return ch == '\n'; })) { - if (_isCodeCompleteMode) { - pos = modifiedScript.indexOf('\n', pos); - continue; - } - - auto str = QObject::tr("IfDefNoWord"); + auto str = tr("IfDefNoWord"); engine->WriteMessage(SECTION, getLineCount(modifiedScript, pos), 1, asMSGTYPE_ERROR, str.toUtf8()); @@ -234,16 +231,6 @@ int AsPreprocesser::processScriptSection(const QByteArray &script, } if (isIfDef || isIfnDef) { - if (_isCodeCompleteMode) { - auto pos = modifiedScript.indexOf('\n', start); - if (pos < 0) { - overwriteCode(modifiedScript, start, - modifiedScript.size() - start - 1); - } else { - overwriteCode(modifiedScript, start, pos - start); - } - continue; - } if (t == asTC_IDENTIFIER) { QByteArray word = modifiedScript.sliced(pos, len); @@ -267,23 +254,13 @@ int AsPreprocesser::processScriptSection(const QByteArray &script, qDebug().noquote() << modifiedScript; #endif } else { - auto str = QObject::tr("IfDefInvalidWord"); + auto str = tr("IfDefInvalidWord"); engine->WriteMessage(SECTION, getLineCount(modifiedScript, pos), 1, asMSGTYPE_ERROR, str.toUtf8()); return asERROR; } } else if (isIf) { - if (_isCodeCompleteMode) { - auto pos = modifiedScript.indexOf('\n', start); - if (pos < 0) { - overwriteCode(modifiedScript, start, - modifiedScript.size() - start - 1); - } else { - overwriteCode(modifiedScript, start, pos - start); - } - continue; - } // evalutate the string auto npos = modifiedScript.indexOf('\n', pos); QByteArray codes; @@ -303,7 +280,7 @@ int AsPreprocesser::processScriptSection(const QByteArray &script, ok); if (ret < 0) { - auto str = QObject::tr("CalIfFailed"); + auto str = tr("CalIfFailed"); engine->WriteMessage(SECTION, getLineCount(modifiedScript, pos), 1, asMSGTYPE_ERROR, str.toUtf8()); @@ -324,20 +301,6 @@ int AsPreprocesser::processScriptSection(const QByteArray &script, QByteArray word = modifiedScript.sliced(pos, len); pos += len; - if (_isCodeCompleteMode) { - defineWord(word, {}); - auto pos = modifiedScript.indexOf('\n', start); - if (pos < 0) { - overwriteCode(modifiedScript, start, - modifiedScript.size() - start - - 1); - } else { - overwriteCode(modifiedScript, start, - pos - start); - } - continue; - } - t = engine->ParseToken(modifiedScript.data() + pos, modifiedScript.size() - pos, &len); @@ -366,7 +329,7 @@ int AsPreprocesser::processScriptSection(const QByteArray &script, defineWord(word, v); } break; default: - auto str = QObject::tr("UnexceptedToken"); + auto str = tr("UnexceptedToken"); engine->WriteMessage( SECTION, getLineCount(modifiedScript, pos), 1, @@ -381,42 +344,20 @@ int AsPreprocesser::processScriptSection(const QByteArray &script, // ensure end line if (endLinePassFailed(modifiedScript, pos)) { - auto str = QObject::tr("UnexceptedToken"); + auto str = tr("UnexceptedToken"); engine->WriteMessage( SECTION, getLineCount(modifiedScript, pos), 1, asMSGTYPE_ERROR, str.toUtf8()); return asERROR; } } else { - if (_isCodeCompleteMode) { - auto pos = modifiedScript.indexOf('\n', start); - if (pos < 0) { - overwriteCode(modifiedScript, start, - modifiedScript.size() - start - - 1); - } else { - overwriteCode(modifiedScript, start, - pos - start); - } - continue; - } - auto str = QObject::tr("InvalidDef"); + auto str = tr("InvalidDef"); engine->WriteMessage(SECTION, getLineCount(modifiedScript, pos), 1, asMSGTYPE_ERROR, str.toUtf8()); return asERROR; } } else if (isUnDef) { - if (_isCodeCompleteMode) { - auto pos = modifiedScript.indexOf('\n', start); - if (pos < 0) { - overwriteCode(modifiedScript, start, - modifiedScript.size() - start - 1); - } else { - overwriteCode(modifiedScript, start, pos - start); - } - continue; - } if (t == asTC_IDENTIFIER) { QByteArray word = modifiedScript.sliced(pos, len); @@ -427,13 +368,13 @@ int AsPreprocesser::processScriptSection(const QByteArray &script, constexpr auto PREFIX = "__"; if (word.startsWith(PREFIX) && word.endsWith(PREFIX)) { // Warning - auto str = QObject::tr("ReservedMarcoType"); + auto str = tr("ReservedMarcoType"); engine->WriteMessage( SECTION, getLineCount(modifiedScript, pos), 1, asMSGTYPE_WARNING, str.toUtf8()); } else { if (!definedWords.remove(word)) { - auto str = QObject::tr("MarcoNotFound:") + word; + auto str = tr("MarcoNotFound:") + word; engine->WriteMessage( SECTION, getLineCount(modifiedScript, pos), 1, asMSGTYPE_WARNING, str.toUtf8()); @@ -442,14 +383,14 @@ int AsPreprocesser::processScriptSection(const QByteArray &script, // ensure end line if (endLinePassFailed(modifiedScript, pos)) { - auto str = QObject::tr("UnexceptedToken"); + auto str = tr("UnexceptedToken"); engine->WriteMessage( SECTION, getLineCount(modifiedScript, pos), 1, asMSGTYPE_ERROR, str.toUtf8()); return asERROR; } } else { - auto str = QObject::tr("InvalidDef"); + auto str = tr("InvalidDef"); engine->WriteMessage(SECTION, getLineCount(modifiedScript, pos), 1, asMSGTYPE_ERROR, str.toUtf8()); @@ -457,12 +398,8 @@ int AsPreprocesser::processScriptSection(const QByteArray &script, } } } else if (token == "else") { - if (_isCodeCompleteMode) { - overwriteCode(modifiedScript, start, pos - start); - continue; - } if (m_condtionStack.isEmpty()) { - auto str = QObject::tr("NoMatchingIf"); + auto str = tr("NoMatchingIf"); engine->WriteMessage(SECTION, getLineCount(modifiedScript, pos), 1, asMSGTYPE_ERROR, str.toUtf8()); @@ -478,14 +415,14 @@ int AsPreprocesser::processScriptSection(const QByteArray &script, // ensure end line if (endLinePassFailed(modifiedScript, pos - 1)) { - auto str = QObject::tr("UnexceptedToken"); + auto str = tr("UnexceptedToken"); engine->WriteMessage( SECTION, getLineCount(modifiedScript, pos), 1, asMSGTYPE_ERROR, str.toUtf8()); return asERROR; } } else { - auto str = QObject::tr("DupElseDef"); + auto str = tr("DupElseDef"); engine->WriteMessage(SECTION, getLineCount(modifiedScript, pos), 1, asMSGTYPE_ERROR, str.toUtf8()); @@ -496,13 +433,9 @@ int AsPreprocesser::processScriptSection(const QByteArray &script, qDebug().noquote() << modifiedScript; #endif } else if (token == "endif") { - if (_isCodeCompleteMode) { - overwriteCode(modifiedScript, start, pos - start); - continue; - } // Only remove the #endif if there was a matching #if if (m_condtionStack.isEmpty()) { - auto str = QObject::tr("NoMatchingIf"); + auto str = tr("NoMatchingIf"); engine->WriteMessage(SECTION, getLineCount(modifiedScript, pos), 1, asMSGTYPE_ERROR, str.toUtf8()); @@ -514,7 +447,7 @@ int AsPreprocesser::processScriptSection(const QByteArray &script, // ensure end line if (endLinePassFailed(modifiedScript, pos)) { - auto str = QObject::tr("UnexceptedToken"); + auto str = tr("UnexceptedToken"); engine->WriteMessage(SECTION, getLineCount(modifiedScript, pos), 1, asMSGTYPE_ERROR, str.toUtf8()); @@ -524,67 +457,71 @@ int AsPreprocesser::processScriptSection(const QByteArray &script, qDebug().noquote() << modifiedScript; #endif } - } else { - if (!_isCodeCompleteMode) { - if (t == asTC_IDENTIFIER) { - // define replace - auto word = modifiedScript.sliced(pos, len); - if (word == PROMISE_AWAIT) { - auto npos = pos + len; - asUINT total = 0; - auto t = engine->ParseToken( - modifiedScript.data() + npos, - modifiedScript.size() - npos, &total); - if (t == asTC_WHITESPACE) { - npos += total; - t = engine->ParseToken(modifiedScript.data() + npos, - modifiedScript.size() - npos, - &total); - if (t == asTC_IDENTIFIER) { - // ok - auto word = modifiedScript.sliced(npos, total); - auto data = "(" + word + - ")." PROMISE_YIELD - "()." PROMISE_UNWRAP "()"; - auto oldLen = npos - pos + word.length(); - modifiedScript.replace(pos, oldLen, data); - pos = npos; - pos += data.length() - oldLen + word.length(); - continue; - } - } - auto str = QObject::tr("UnexceptedToken"); - engine->WriteMessage(SECTION, - getLineCount(modifiedScript, pos), - 1, asMSGTYPE_ERROR, str.toUtf8()); - return asERROR; - } else if (word == "__LINE__") { - auto data = QByteArray::number( - getLineCount(modifiedScript, pos)); - modifiedScript.replace(pos, len, data); - pos += data.length(); - continue; - } else if (word == "__SECTION__") { - auto data = SECTION; - data.prepend('"').append('"'); - modifiedScript.replace(pos, len, data); - pos += data.length(); - continue; - } else if (word == "__SECTION_BASE__") { - auto data = QFileInfo(SECTION).baseName().toUtf8(); - data.prepend('"').append('"'); - modifiedScript.replace(pos, len, data); - pos += data.length(); - continue; - } else { - auto rword = findReplaceResult(word); - if (word != rword) { - modifiedScript.replace(pos, len, rword); - len = rword.length(); + isEndLine = true; + } else { + if (t == asTC_IDENTIFIER) { + // define replace + auto word = modifiedScript.sliced(pos, len); + if (word == PROMISE_AWAIT) { + auto npos = pos + len; + asUINT total = 0; + auto t = engine->ParseToken(modifiedScript.data() + npos, + modifiedScript.size() - npos, + &total); + if (t == asTC_WHITESPACE) { + npos += total; + t = engine->ParseToken(modifiedScript.data() + npos, + modifiedScript.size() - npos, + &total); + if (t == asTC_IDENTIFIER) { + // ok + auto word = modifiedScript.sliced(npos, total); + auto data = "(" + word + + ")." PROMISE_YIELD "()." PROMISE_UNWRAP + "()"; + auto oldLen = npos - pos + word.length(); + modifiedScript.replace(pos, oldLen, data); + pos = npos; + pos += data.length() - oldLen + word.length(); + continue; } } + + auto str = tr("UnexceptedToken"); + engine->WriteMessage(SECTION, + getLineCount(modifiedScript, pos), 1, + asMSGTYPE_ERROR, str.toUtf8()); + return asERROR; + } else if (word == "__LINE__") { + auto data = + QByteArray::number(getLineCount(modifiedScript, pos)); + modifiedScript.replace(pos, len, data); + pos += data.length(); + continue; + } else if (word == "__SECTION__") { + auto data = SECTION; + data.prepend('"').append('"'); + modifiedScript.replace(pos, len, data); + pos += data.length(); + continue; + } else if (word == "__SECTION_BASE__") { + auto data = QFileInfo(SECTION).baseName().toUtf8(); + data.prepend('"').append('"'); + modifiedScript.replace(pos, len, data); + pos += data.length(); + continue; + } else { + auto rword = findReplaceResult(word); + if (word != rword) { + modifiedScript.replace(pos, len, rword); + len = rword.length(); + } } + } else if (t == asTC_WHITESPACE) { + isEndLine = std::any_of(modifiedScript.data() + pos, + modifiedScript.data() + pos + len, + [](char ch) { return ch == '\n'; }); } pos += len; } @@ -644,11 +581,11 @@ int AsPreprocesser::processScriptSection(const QByteArray &script, // line breaks auto p = includefile.indexOf('\n'); if (p >= 0) { - auto str = - QObject::tr("Invalid file name for #include; " - "it contains a line-break: ") + - QStringLiteral("'") + includefile.left(p) + - QStringLiteral("'"); + auto str = tr("Invalid file name for #include; " + "it contains a line-break: ") + + QStringLiteral("'") + + includefile.left(p) + + QStringLiteral("'"); engine->WriteMessage( sectionname.toUtf8(), getLineCount(modifiedScript, pos), 1, @@ -690,12 +627,11 @@ int AsPreprocesser::processScriptSection(const QByteArray &script, auto p = includefile.indexOf('\n'); auto ws = includefile.indexOf(' '); if (!includefile.isEmpty() && p >= 0 && ws >= 0) { - auto str = - QObject::tr( - "Invalid file name for #include; " - "it contains a line-break: ") + - QStringLiteral("'") + includefile.left(p) + - QStringLiteral("'"); + auto str = tr("Invalid file name for #include; " + "it contains a line-break: ") + + QStringLiteral("'") + + includefile.left(p) + + QStringLiteral("'"); engine->WriteMessage( sectionname.toUtf8(), getLineCount(modifiedScript, pos), 1, @@ -710,10 +646,9 @@ int AsPreprocesser::processScriptSection(const QByteArray &script, pos - start); } } else { - auto str = - QObject::tr("Invalid file name for #include; " - "it contains a line-break or " - "unpaired symbol"); + auto str = tr("Invalid file name for #include; " + "it contains a line-break or " + "unpaired symbol"); engine->WriteMessage(sectionname.toUtf8(), 0, 0, asMSGTYPE_ERROR, str.toUtf8()); } @@ -734,20 +669,17 @@ int AsPreprocesser::processScriptSection(const QByteArray &script, // to avoid compiler error overwriteCode(modifiedScript, start, pos - start); - if (!_isCodeCompleteMode) { - int r = pragmaCallback - ? pragmaCallback(pragmaText, this, - sectionname, pragmaParam) - : -1; - if (r < 0) { - engine->WriteMessage( - sectionname.toUtf8(), - getLineCount(modifiedScript, pos), 1, - asMSGTYPE_ERROR, - QObject::tr("Invalid #pragma directive") - .toUtf8()); - return r; - } + int r = pragmaCallback + ? pragmaCallback(pragmaText, this, sectionname, + pragmaParam) + : -1; + if (r < 0) { + engine->WriteMessage( + sectionname.toUtf8(), + getLineCount(modifiedScript, pos), 1, + asMSGTYPE_ERROR, + tr("Invalid #pragma directive").toUtf8()); + return r; } } } @@ -810,8 +742,7 @@ int AsPreprocesser::loadScriptSection(const QString &filename) { if (!f.open(QFile::ReadOnly)) { // Write a message to the engine's message callback - auto msg = QObject::tr("Failed to open script file ") + - QStringLiteral("'") + + auto msg = tr("Failed to open script file ") + QStringLiteral("'") + QFileInfo(filename).absoluteFilePath() + QStringLiteral("'"); engine->WriteMessage(filename.toUtf8(), 0, 0, asMSGTYPE_ERROR, msg.toUtf8()); @@ -1022,12 +953,6 @@ QByteArray AsPreprocesser::findReplaceResult(const QByteArray &v) { return r; } -bool AsPreprocesser::isCodeCompleteMode() const { return _isCodeCompleteMode; } - -void AsPreprocesser::setIsCodeCompleteMode(bool newIsCodeCompleteMode) { - _isCodeCompleteMode = newIsCodeCompleteMode; -} - QHash AsPreprocesser::definedMacros() const { return definedWords; } diff --git a/src/class/aspreprocesser.h b/src/class/aspreprocesser.h index 869aa63..ba5ae27 100644 --- a/src/class/aspreprocesser.h +++ b/src/class/aspreprocesser.h @@ -35,6 +35,7 @@ #pragma warning(disable : 4786) #endif +#include #include #include #include @@ -74,6 +75,7 @@ typedef int (*PRAGMACALLBACK_t)(const QByteArray &pragmaText, * * #ifndef */ class AsPreprocesser { + Q_DECLARE_TR_FUNCTIONS(AsPreprocesser) public: explicit AsPreprocesser(asIScriptEngine *engine); virtual ~AsPreprocesser(); @@ -113,9 +115,6 @@ public: QString sectionName(unsigned int idx) const; - bool isCodeCompleteMode() const; - void setIsCodeCompleteMode(bool newIsCodeCompleteMode); - QHash definedMacros() const; protected: @@ -155,9 +154,6 @@ protected: QStringList includedScripts; QHash definedWords; - -private: - bool _isCodeCompleteMode = false; }; #endif // ASPREPROCESSER_H diff --git a/src/class/consolehighlighanim.cpp b/src/class/consolehighlighanim.cpp new file mode 100644 index 0000000..a19a354 --- /dev/null +++ b/src/class/consolehighlighanim.cpp @@ -0,0 +1,98 @@ +/*============================================================================== +** Copyright (C) 2024-2027 WingSummer +** +** This program is free software: you can redistribute it and/or modify it under +** the terms of the GNU Affero General Public License as published by the Free +** Software Foundation, version 3. +** +** This program is distributed in the hope that it will be useful, but WITHOUT +** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +** details. +** +** You should have received a copy of the GNU Affero General Public License +** along with this program. If not, see . +** ============================================================================= +*/ + +#include "consolehighlighanim.h" + +#include +#include +#include + +ConsoleHighlighAnim::ConsoleHighlighAnim(QObject *parent) + : QObject(parent), m_highlightColor(qApp->palette().highlight().color()), + m_alpha(0), _w(nullptr), _anim(nullptr) { + _anim = new QPropertyAnimation(this, QByteArrayLiteral("alpha"), this); + _anim->setStartValue(10); + _anim->setEndValue(100); + _anim->setDuration(1000); + _anim->setEasingCurve(QEasingCurve::InOutQuad); + _anim->setLoopCount(5); + connect(_anim, &QPropertyAnimation::finished, this, [this]() { + if (_w) { + _w->setStyleSheet({}); + } + }); +} + +int ConsoleHighlighAnim::getAlpha() const { return m_alpha; } + +void ConsoleHighlighAnim::setAlpha(int newAlpha) { + if (m_alpha == newAlpha) + return; + m_alpha = newAlpha; + + auto clsname = _w->metaObject()->className(); + auto ss = QStringLiteral("background-color: rgba(%1, %2, %3, %4);") + .arg(m_highlightColor.red()) + .arg(m_highlightColor.green()) + .arg(m_highlightColor.blue()) + .arg(m_alpha); + if (clsname) { + ss.prepend('{').prepend(clsname).append('}'); + } + + if (_w) { + _w->setStyleSheet(ss); + } + + Q_EMIT alphaChanged(); +} + +QWidget *ConsoleHighlighAnim::widget() const { return _w; } + +void ConsoleHighlighAnim::setWidget(QWidget *newW) { + if (_w) { + _w->setStyleSheet({}); + } + _w = newW; + auto ss = QStringLiteral("background-color: rgba(%1, %2, %3, %4);") + .arg(m_highlightColor.red()) + .arg(m_highlightColor.green()) + .arg(m_highlightColor.blue()) + .arg(m_alpha); + if (_w) { + _w->setStyleSheet(ss); + } +} + +void ConsoleHighlighAnim::start() { + if (_w == nullptr) { + return; + } + if (_anim->state() == QPropertyAnimation::Stopped) { + _anim->start(); + } +} + +void ConsoleHighlighAnim::stop() { + if (_anim->state() == QPropertyAnimation::Running) { + _anim->stop(); + + if (_w) { + _w->setStyleSheet({}); + } + } +} diff --git a/src/class/consolehighlighanim.h b/src/class/consolehighlighanim.h new file mode 100644 index 0000000..14fa015 --- /dev/null +++ b/src/class/consolehighlighanim.h @@ -0,0 +1,55 @@ +/*============================================================================== +** Copyright (C) 2024-2027 WingSummer +** +** This program is free software: you can redistribute it and/or modify it under +** the terms of the GNU Affero General Public License as published by the Free +** Software Foundation, version 3. +** +** This program is distributed in the hope that it will be useful, but WITHOUT +** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +** details. +** +** You should have received a copy of the GNU Affero General Public License +** along with this program. If not, see . +** ============================================================================= +*/ +#ifndef CONSOLEHIGHLIGHANIM_H +#define CONSOLEHIGHLIGHANIM_H + +#include +#include +#include + +class ConsoleHighlighAnim : public QObject { + Q_OBJECT + + Q_PROPERTY(int alpha READ getAlpha WRITE setAlpha NOTIFY alphaChanged FINAL) + +public: + explicit ConsoleHighlighAnim(QObject *parent = nullptr); + +public: + int getAlpha() const; + void setAlpha(int newAlpha); + + QWidget *widget() const; + void setWidget(QWidget *newW); + +public: + void start(); + + // 停止动画并清除样式 + void stop(); + +signals: + void alphaChanged(); + +private: + QColor m_highlightColor; + int m_alpha; + QWidget *_w; + QPropertyAnimation *_anim; +}; + +#endif // CONSOLEHIGHLIGHANIM_H diff --git a/src/class/editorviewcontext.cpp b/src/class/editorviewcontext.cpp index 7a9ffbe..a8365ba 100644 --- a/src/class/editorviewcontext.cpp +++ b/src/class/editorviewcontext.cpp @@ -18,10 +18,14 @@ #include "editorviewcontext.h" EditorViewContext::EditorViewContext(QHexView *view) - : WingHex::HexEditorContext(), _view(view) { + : WingHex::HexEditorContext(view), _view(view) { Q_ASSERT(view); } +QString EditorViewContext::docFileName() const { + return _view->windowFilePath(); +} + QFontMetricsF EditorViewContext::fontMetrics() const { return _view->fontMetrics(); } diff --git a/src/class/editorviewcontext.h b/src/class/editorviewcontext.h index 5bdcbdd..7747ae6 100644 --- a/src/class/editorviewcontext.h +++ b/src/class/editorviewcontext.h @@ -27,6 +27,7 @@ public: // HexEditorPalette interface public: + virtual QString docFileName() const override; virtual QFontMetricsF fontMetrics() const override; virtual QColor headerColor() const override; virtual QColor addressColor() const override; diff --git a/src/class/pluginsystem.cpp b/src/class/pluginsystem.cpp index abb4417..55f2fdf 100644 --- a/src/class/pluginsystem.cpp +++ b/src/class/pluginsystem.cpp @@ -4063,12 +4063,7 @@ void PluginSystem::try2LoadHexExtPlugin() { _manHexInfo = m; - { - auto menu = p->registeredHexContextMenu(); - if (menu) { - _win->m_hexContextMenu.append(menu); - } - } + registerHexContextMenu(p); registerRibbonTools(p->registeredRibbonTools()); registeredSettingPages(QVariant::fromValue(p), p->registeredSettingPages()); @@ -4142,6 +4137,30 @@ void PluginSystem::registerEvents(IWingPlugin *plg) { } } +void PluginSystem::registerHexContextMenu(IWingHexEditorInterface *inter) { + Q_ASSERT(inter); + auto menu = inter->registeredHexContextMenu(); + if (menu) { + _win->m_hexContextMenu.append(menu); + connect(menu, &QMenu::aboutToShow, this, [menu, inter]() { + auto pp = menu->property("__CONTEXT__"); + auto ptr = + reinterpret_cast(pp.value()); + if (ptr) { + inter->prepareCallEditorContext(ptr); + } + }); + connect(menu, &QMenu::triggered, this, [menu, inter]() { + auto pp = menu->property("__CONTEXT__"); + auto ptr = + reinterpret_cast(pp.value()); + if (ptr) { + inter->finishCallEditorContext(ptr); + } + }); + } +} + void PluginSystem::applyFunctionTables(QObject *plg, const CallTable &fns) { plg->setProperty("__CALL_TABLE__", QVariant::fromValue(fns)); plg->setProperty("__CALL_POINTER__", quintptr(this)); @@ -4217,13 +4236,7 @@ void PluginSystem::loadPlugin(IWingPlugin *p, PluginInfo &meta, // ensure call only once registerRibbonTools(p->registeredRibbonTools()); registerPluginDockWidgets(p); - - { - auto menu = p->registeredHexContextMenu(); - if (menu) { - _win->m_hexContextMenu.append(menu); - } - } + registerHexContextMenu(p); { auto vieww = p->registeredEditorViewWidgets(); diff --git a/src/class/pluginsystem.h b/src/class/pluginsystem.h index 2e512e9..cbef530 100644 --- a/src/class/pluginsystem.h +++ b/src/class/pluginsystem.h @@ -224,6 +224,8 @@ private: private: void registerEvents(IWingPlugin *plg); + void registerHexContextMenu(IWingHexEditorInterface *inter); + void applyFunctionTables(QObject *plg, const CallTable &fns); bool isPluginLoaded(const WingDependency &d); diff --git a/src/control/editorview.cpp b/src/control/editorview.cpp index b5cfe5d..7fac6c1 100644 --- a/src/control/editorview.cpp +++ b/src/control/editorview.cpp @@ -333,8 +333,9 @@ ErrFile EditorView::newFile(size_t index) { removeMonitorPaths(); auto istr = QString::number(index); - m_fileName = tr("Untitled") + istr; - this->setWindowTitle(m_fileName); + auto fname = tr("Untitled") + istr; + m_hex->setWindowFilePath(fname); + this->setWindowTitle(fname); m_docType = DocumentType::File; m_isWorkSpace = false; m_isNewFile = true; @@ -371,7 +372,8 @@ ErrFile EditorView::openFile(const QString &filename) { m_hex->setKeepSize(true); m_docType = DocumentType::File; - m_fileName = info.absoluteFilePath(); + auto fName = info.absoluteFilePath(); + m_hex->setWindowFilePath(fName); m_isNewFile = false; p->setDocSaved(); @@ -379,8 +381,8 @@ ErrFile EditorView::openFile(const QString &filename) { connectDocSavedFlag(this); auto tab = this->tabWidget(); - tab->setIcon(Utilities::getIconFromFile(style(), m_fileName)); - tab->setToolTip(m_fileName); + tab->setIcon(Utilities::getIconFromFile(style(), fName)); + tab->setToolTip(fName); addMonitorPath(); } @@ -435,7 +437,7 @@ ErrFile EditorView::openExtFile(const QString &ext, const QString &file) { _file = file; m_docType = DocumentType::Extension; - m_fileName = fileName; + m_hex->setWindowFilePath(fileName); m_isNewFile = false; p->setDocSaved(); @@ -513,7 +515,7 @@ ErrFile EditorView::save(const QString &workSpaceName, const QString &path, return this->cloneParent()->save(workSpaceName, path, isExport, workSpaceAttr); } - auto fileName = path.isEmpty() ? m_fileName : path; + auto fileName = path.isEmpty() ? m_hex->windowFilePath() : path; auto doc = m_hex->document(); #ifdef Q_OS_LINUX @@ -589,7 +591,8 @@ ErrFile EditorView::save(const QString &workSpaceName, const QString &path, } } - if (!doc->isDocSaved() || m_fileName != fileName || isNewFile()) { + if (!doc->isDocSaved() || m_hex->windowFilePath() != fileName || + isNewFile()) { if (m_docType == DocumentType::Extension) { if (_dev->isOpen()) { _dev->close(); @@ -611,7 +614,8 @@ ErrFile EditorView::save(const QString &workSpaceName, const QString &path, if (doc->saveTo(&file, !isExport)) { file.close(); if (!isExport) { - m_fileName = QFileInfo(fileName).absoluteFilePath(); + m_hex->setWindowFilePath( + QFileInfo(fileName).absoluteFilePath()); if (isNewFile()) { auto buffer = new QFileBuffer; @@ -660,7 +664,7 @@ ErrFile EditorView::reload() { switch (documentType()) { case DocumentType::File: - return openFile(m_fileName); + return openFile(m_hex->windowFilePath()); case DocumentType::Extension: return openExtFile(_ext, _file); default: @@ -741,13 +745,14 @@ void EditorView::connectDocSavedFlag(EditorView *editor) { connect(editor->m_hex->document().get(), &QHexDocument::documentSaved, this, [=](bool b) { QString fileName; + auto fName = m_hex->windowFilePath(); if (editor->isNewFile()) { - fileName = m_fileName; + fileName = fName; } else if (editor->isExtensionFile()) { - auto idx = m_fileName.indexOf('}'); - fileName = m_fileName.mid(idx); + auto idx = fName.indexOf('}'); + fileName = fName.mid(idx); } else { - fileName = QFileInfo(m_fileName).fileName(); + fileName = QFileInfo(fName).fileName(); } QString content; @@ -770,7 +775,7 @@ void EditorView::connectDocSavedFlag(EditorView *editor) { auto tab = this->tabWidget(); if (tab->icon().isNull()) { tab->setIcon( - Utilities::getIconFromFile(style(), m_fileName)); + Utilities::getIconFromFile(style(), fName)); } } }); @@ -784,7 +789,7 @@ void EditorView::removeMonitorPaths() { _watcher.removePaths(files); } -void EditorView::addMonitorPath() { _watcher.addPath(m_fileName); } +void EditorView::addMonitorPath() { _watcher.addPath(m_hex->windowFilePath()); } BookMarksModel *EditorView::bookmarksModel() const { return m_bookmarks; } @@ -2144,12 +2149,12 @@ EditorView *EditorView::clone() { connect(ev, &EditorView::sigOnMetadata, this, &EditorView::sigOnMetadata); connect(ev, &EditorView::sigOnBookMark, this, &EditorView::sigOnBookMark); - auto doc = this->m_hex->document(); + auto doc = m_hex->document(); ev->m_cloneParent = this; ev->m_hex->setDocument(doc, ev->m_hex->cursor()); - ev->m_fileName = this->m_fileName; + ev->m_hex->setWindowFilePath(m_hex->windowFilePath()); ev->setWindowTitle(this->windowTitle() + QStringLiteral(" : ") + QString::number(cloneIndex + 1)); @@ -2234,7 +2239,7 @@ QString EditorView::fileName() const { if (isCloneFile()) { return this->cloneParent()->fileName(); } - return m_fileName; + return m_hex->windowFilePath(); } bool EditorView::eventFilter(QObject *watched, QEvent *event) { @@ -2247,3 +2252,5 @@ bool EditorView::eventFilter(QObject *watched, QEvent *event) { } return ads::CDockWidget::eventFilter(watched, event); } + +EditorViewContext *EditorView::editorContext() const { return _context; } diff --git a/src/control/editorview.h b/src/control/editorview.h index 94fe59f..6a858ea 100644 --- a/src/control/editorview.h +++ b/src/control/editorview.h @@ -217,6 +217,8 @@ public: void applySettings(); + EditorViewContext *editorContext() const; + private: inline qsizetype findAvailCloneIndex(); @@ -570,7 +572,6 @@ private: QMenu *m_menu = nullptr; QHash m_others; - QString m_fileName; bool m_isNewFile = true; QByteArray m_md5; diff --git a/src/define.h b/src/define.h index 40cfa77..1a1b081 100644 --- a/src/define.h +++ b/src/define.h @@ -6,7 +6,8 @@ enum class CrashCode : int { LanguageFile, PluginSetting, ScriptInitFailed, - GenericCallNotSupported + GenericCallNotSupported, + OutofMemory }; namespace AsUserDataType { diff --git a/src/dialog/mainwindow.cpp b/src/dialog/mainwindow.cpp index 3ec9107..4666d15 100644 --- a/src/dialog/mainwindow.cpp +++ b/src/dialog/mainwindow.cpp @@ -465,6 +465,9 @@ void MainWindow::buildUpDockSystem(QWidget *container) { swapEditor(m_curEditor, editview); _editorLock.unlock(); } else { + for (auto &menu : m_hexContextMenu) { + menu->setProperty("__CONTEXT__", {}); + } m_findresult->setModel(_findEmptyResult); m_bookmarks->setModel(_bookMarkEmpty); m_metadatas->setModel(_metadataEmpty); @@ -1083,10 +1086,13 @@ ads::CDockAreaWidget * MainWindow::buildUpScriptBgOutputDock(ads::CDockManager *dock, ads::DockWidgetArea area, ads::CDockAreaWidget *areaw) { + m_bgScriptOutput = new QPlainTextEdit(this); m_bgScriptOutput->setPlaceholderText(tr("BgScriptOutputHere")); m_bgScriptOutput->setReadOnly(true); + _hlAnim = new ConsoleHighlighAnim(m_bgScriptOutput); + auto a = newAction( ICONRES(QStringLiteral("mStr")), tr("SelectAll"), [this]() { m_bgScriptOutput->selectAll(); }, QKeySequence::SelectAll); @@ -1116,6 +1122,13 @@ MainWindow::buildUpScriptBgOutputDock(ads::CDockManager *dock, auto dw = buildDockWidget(dock, QStringLiteral("BgScriptOutput"), tr("BgScriptOutput"), m_bgScriptOutput); + _hlAnim->setWidget(dw->tabWidget()); + + auto e = new EventFilter(QEvent::Show, dw); + connect(e, &EventFilter::eventTriggered, this, + [this]() { _hlAnim->stop(); }); + m_bgScriptOutput->installEventFilter(e); + return dock->addDockWidget(area, dw, areaw); } @@ -3333,7 +3346,6 @@ void MainWindow::swapEditor(EditorView *old, EditorView *cur) { doc->disconnect(m_aShowMetaComment); } - Q_ASSERT(cur); auto hexeditor = cur->hexEditor(); auto needReload = cur->property("__RELOAD__").toBool(); if (needReload) { @@ -3434,6 +3446,10 @@ void MainWindow::swapEditor(EditorView *old, EditorView *cur) { m_metadatas->selectionModel()->hasSelection()); }); + for (auto &menu : m_hexContextMenu) { + menu->setProperty("__CONTEXT__", quintptr(cur->editorContext())); + } + _undoView->setStack(doc->undoStack()); m_curEditor = cur; @@ -3959,6 +3975,10 @@ void MainWindow::onOutputBgScriptOutput( lastInfo.first = message.type; lastInfo.second = qMakePair(message.row, message.col); + + if (!m_bgScriptOutput->isVisible()) { + _hlAnim->start(); + } } void MainWindow::closeEvent(QCloseEvent *event) { diff --git a/src/dialog/mainwindow.h b/src/dialog/mainwindow.h index b4934db..ccf1c9d 100644 --- a/src/dialog/mainwindow.h +++ b/src/dialog/mainwindow.h @@ -44,6 +44,7 @@ #include "Qt-Advanced-Docking-System/src/DockManager.h" #include "Qt-Advanced-Docking-System/src/DockWidget.h" #include "WingPlugin/iwingplugin.h" +#include "class/consolehighlighanim.h" #include "class/recentfilemanager.h" #include "control/editorview.h" #include "control/qtableviewext.h" @@ -479,6 +480,8 @@ private: ScriptingConsole *m_scriptConsole = nullptr; QPlainTextEdit *m_bgScriptOutput = nullptr; + ConsoleHighlighAnim *_hlAnim = nullptr; + bool m_isfinding = false; ads::CDockWidget *m_find = nullptr; QMenu *m_menuFind = nullptr; diff --git a/theme/dark/stylesheet.qss b/theme/dark/stylesheet.qss index b52d4b3..e10c3e8 100644 --- a/theme/dark/stylesheet.qss +++ b/theme/dark/stylesheet.qss @@ -2741,12 +2741,12 @@ ads--CDockWidgetTab[activeTab="true"] ads--CDockWidgetTab QLabel { - background-color: #1b1d20; + background-color: transparent; } -ads--CDockWidgetTab[activeTab="true"] QLabel +ads--CDockWidgetTab[activeTab="false"]:hover { - background-color: #202326; + background-color: rgba(61, 173, 232, 0.1); } ads--CDockContainerWidget > QSplitter{ diff --git a/theme/light/stylesheet.qss b/theme/light/stylesheet.qss index 3eed801..06bd590 100644 --- a/theme/light/stylesheet.qss +++ b/theme/light/stylesheet.qss @@ -2741,12 +2741,12 @@ ads--CDockWidgetTab[activeTab="true"] ads--CDockWidgetTab QLabel { - background-color: #d9d8d7; + background-color: transparent; } -ads--CDockWidgetTab[activeTab="true"] QLabel +ads--CDockWidgetTab[activeTab="false"]:hover { - background-color: #eff0f1; + background-color: rgba(61, 173, 232, 0.2); } ads--CDockContainerWidget > QSplitter{