diff --git a/.github/workflows/clang-format-check.yml b/.github/workflows/clang-format-check.yml index 8347078..6b815cf 100644 --- a/.github/workflows/clang-format-check.yml +++ b/.github/workflows/clang-format-check.yml @@ -9,6 +9,6 @@ jobs: - name: Run clang-format style check for C/C++/Protobuf programs. uses: jidicula/clang-format-action@v4.14.0 with: - clang-format-version: '12' + clang-format-version: '19' exclude-regex: '(qt-template|mkinstaller)' fallback-style: 'LLVM' # optional diff --git a/3rdparty/QConsoleWidget/QConsoleWidget.cpp b/3rdparty/QConsoleWidget/QConsoleWidget.cpp index d45c7aa..be6cc9c 100644 --- a/3rdparty/QConsoleWidget/QConsoleWidget.cpp +++ b/3rdparty/QConsoleWidget/QConsoleWidget.cpp @@ -19,10 +19,6 @@ #include #include -#define STDIN_FILENO 0 /* Standard input. */ -#define STDOUT_FILENO 1 /* Standard output. */ -#define STDERR_FILENO 2 /* Standard error output. */ - QConsoleWidget::QConsoleWidget(QWidget *parent) : WingCodeEdit(parent), mode_(Output) { @@ -93,14 +89,11 @@ void QConsoleWidget::handleReturnKey() { if (!code.isEmpty()) history_.add(code); - // append the newline char and // send signal / update iodevice - code += "\n"; if (iodevice_->isOpen()) iodevice_->consoleWidgetInput(code); - else { - emit consoleCommand(code); - } + + emit consoleCommand(code); } void QConsoleWidget::handleTabKey() { @@ -446,9 +439,4 @@ QTextStream &inputMode(QTextStream &s) { d->widget()->setMode(QConsoleWidget::Input); return s; } -QTextStream &outChannel(QTextStream &s) { - QConsoleIODevice *d = qobject_cast(s.device()); - if (d) - d->setCurrentWriteChannel(STDOUT_FILENO); - return s; -} +QTextStream &outChannel(QTextStream &s) { return s; } diff --git a/3rdparty/QHexView/document/qhexmetadata.h b/3rdparty/QHexView/document/qhexmetadata.h index a3f6f7a..e400fcd 100644 --- a/3rdparty/QHexView/document/qhexmetadata.h +++ b/3rdparty/QHexView/document/qhexmetadata.h @@ -38,8 +38,8 @@ using qhash_result_t = uint; // copying from QT6 source code for supporting QT5's qHashMulti namespace QtPrivate { template -inline constexpr bool - QNothrowHashableHelper_v = noexcept(qHash(std::declval())); +inline constexpr bool QNothrowHashableHelper_v = + noexcept(qHash(std::declval())); template struct QNothrowHashable : std::false_type {}; diff --git a/3rdparty/qtsingleapplication/src/qtlockedfile.cpp b/3rdparty/qtsingleapplication/src/qtlockedfile.cpp index 247c9bf..3132d4a 100644 --- a/3rdparty/qtsingleapplication/src/qtlockedfile.cpp +++ b/3rdparty/qtsingleapplication/src/qtlockedfile.cpp @@ -40,11 +40,12 @@ Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate) { Qt::HANDLE mutex; if (doCreate) { - QT_WA({ mutex = CreateMutexW(NULL, FALSE, LPCWSTR(mname.utf16())); }, - { - mutex = CreateMutexA(NULL, FALSE, - mname.toLocal8Bit().constData()); - }); + QT_WA( + { mutex = CreateMutexW(NULL, FALSE, LPCWSTR(mname.utf16())); }, + { + mutex = + CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); + }); if (!mutex) { qErrnoWarning("QtLockedFile::lock(): CreateMutex failed"); return 0; diff --git a/CMakeLists.txt b/CMakeLists.txt index c27b8ab..214d523 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -173,9 +173,13 @@ set(DIALOG_SRC src/dialog/historydeldialog.ui src/dialog/crashreport.h src/dialog/crashreport.cpp - src/dialog/crashreport.ui) + src/dialog/crashreport.ui + src/dialog/showtextdialog.cpp + src/dialog/showtextdialog.h) set(CONTROL_SRC + src/control/codeedit.h + src/control/codeedit.cpp src/control/editorview.h src/control/editorview.cpp src/control/toast.h @@ -275,7 +279,8 @@ set(CLASS_SRC src/class/pluginsystem.h src/class/pluginsystem.cpp src/class/inspectqtloghelper.h - src/class/inspectqtloghelper.cpp) + src/class/inspectqtloghelper.cpp + src/class/codeinfotip.h) set(INTERNAL_PLG_SRC src/class/wingangelapi.h src/class/wingangelapi.cpp diff --git a/images/viewtxt.png b/images/viewtxt.png new file mode 100644 index 0000000..43f7e27 Binary files /dev/null and b/images/viewtxt.png differ diff --git a/lang/zh_CN/winghex_zh_CN.ts b/lang/zh_CN/winghex_zh_CN.ts index 3866018..84d6cc5 100644 --- a/lang/zh_CN/winghex_zh_CN.ts +++ b/lang/zh_CN/winghex_zh_CN.ts @@ -74,25 +74,25 @@ AppManager - + GenericCallNotFullySupported 该软件脚本系统不完全支持通用调用,故软件将会退出。 - + SetupClang 启动 Clang 服务 - + OpeningFiles 打开文件 - - - - + + + + AlreadyOpened 文件已被打开 @@ -4361,32 +4361,32 @@ ScriptingConsole - + Scripting console for WingHexExplorer 羽云十六进制编辑器脚本控制台 - + >>>> Powered by AngelScript <<<< >>>> 由 AngelScript 引擎提供支持 <<<< - + [Info] 【信息】 - + [Warn] 【警告】 - + [Error] 【错误】 - + [Console] 【控制台】 @@ -4404,401 +4404,401 @@ 因权限无法打开脚本 - + File 文件 - + Edit 编辑 - + Debugger 调试器 - + Setting 设置 - + About 关于 - + InvalidSourceFile 非法代码文件 - + Basic 基础 - + New 新建 - + OpenF 打开文件 - + RecentFiles 最近打开 - + Reload 重新加载 - + Save 保存 - + SaveAs 另存为 - + General 基本 - + Undo 撤销 - + Redo 恢复 - + Cut 剪切 - + Copy 复制 - + Paste 粘贴 - + Delete 删除 - + Lookup 查询 - + Find 查找 - + Replace 替换 - + Goto 跳转 - - + + Format 代码样式 - + CodeFormat 代码格式化 - + Window 窗体 - - + + Editor 编辑器 - + Tools 工具 - + Layout 布局 - + Fullscreen 全屏 - + RestoreLayout 恢复默认布局 - + BreakPoint 断点 - + ToggleBreakPoint 切换断点 - + AddBreakPoint 添加断点 - + Settings 设置 - + ClangFormat Clang Format - + Local 本地 - + Global 全局 - + Variables 变量 - + ConsoleOutput 输出 - + StackTrace 栈跟踪 - + Symbol 符号 - - - - - - + + + + + + Error 错误 - + Too much opened files 打开的文件过多,无法继续操作! - + ConfirmSave 正在关闭未保存的脚本文件,你确定保存吗? - + ScriptSaveFailedClose 脚本保存失败,你仍确认关闭吗? - + Debuging... 调试中... - + Running... 运行中... - - + + ChooseFile 选择文件 - - - + + + FilePermission 因文件权限无法继续! - + ReloadSuccessfully 文件重新加载成功! - + ReloadUnSuccessfully 文件重新加载失败! - + ChooseSaveFile 请选择保存文件路径: - - + + SaveSuccessfully 保存成功! - + SaveUnSuccessfully 保存失败! - + FormatCodeFailed 代码格式化失败 - - + + CannotSave2RunScript 无法保存,故无法继续运行脚本。 - - + + ScriptStillRunning 脚本仍在运行,你确定要退出吗? - + ConfirmScriptSave 你尝试关闭程序,但仍存在未保存的脚本文件,你确定保存这些更改吗? - + View 视图 - + Debug 调试 - + Run 运行 - + RunWithDbg 调试运行 - + Pause 暂停 - + Continue 继续 - + Stop 停止 - + Restart 重启 - + StepInto 单步步入 - + StepOver 单步步过 - + StepOut 单步跳出 - + RemoveBreakPoint 删除断点 - + Info 信息 - + Software 软件 - + Sponsor 赞助 - + Wiki 网页 Wiki - + AboutQT 关于 QT @@ -4842,6 +4842,64 @@ 在启动 Windows 资源管理器的路径中找不到 explorer.exe。 + + ShowTextDialog + + + TextBroswer + + + + + TooHugeFile + + + + + Edit + 编辑 + + + + View + 视图 + + + + General + 基本 + + + + Copy + 复制 + + + + Find + 查找 + + + + Goto + 跳转 + + + + Encoding + 编码 + + + + Display + 显示 + + + + CopyToClipBoard + 数据已拷贝到粘贴板 + + SkinManager diff --git a/lang/zh_TW/winghex_zh_TW.ts b/lang/zh_TW/winghex_zh_TW.ts index be5f0e5..8c35cb8 100644 --- a/lang/zh_TW/winghex_zh_TW.ts +++ b/lang/zh_TW/winghex_zh_TW.ts @@ -74,25 +74,25 @@ AppManager - + GenericCallNotFullySupported 該軟體腳本系統不完全支持通用調用,故軟體將會退出。 - + SetupClang 啟動 Clang 服務 - + OpeningFiles 打開檔 - - - - + + + + AlreadyOpened 檔已被打開 @@ -4361,32 +4361,32 @@ ScriptingConsole - + Scripting console for WingHexExplorer 羽雲十六進制編輯器腳本控制臺 - + >>>> Powered by AngelScript <<<< >>>> 由 AngelScript 引擎提供支持 <<<< - + [Info] 【資訊】 - + [Warn] 【警告】 - + [Error] 【錯誤】 - + [Console] 【控制臺】 @@ -4404,401 +4404,401 @@ 因許可權無法打開腳本 - + File - + Edit 編輯 - + Debugger 調試器 - + Setting 設置 - + About 關於 - + InvalidSourceFile 非法代碼檔 - + Basic 基礎 - + New 新建 - + OpenF 打開檔 - + RecentFiles 最近打開 - + Reload 重新加載 - + Save 保存 - + SaveAs 另存為 - + General 基本 - + Undo 撤銷 - + Redo 恢復 - + Cut 剪切 - + Copy 複製 - + Paste 粘貼 - + Delete 刪除 - + Lookup 查詢 - + Find 查找 - + Replace 替換 - + Goto 跳轉 - - + + Format 代碼樣式 - + CodeFormat 代碼格式化 - + Window 窗體 - - + + Editor 編輯器 - + Tools 工具 - + Layout 佈局 - + Fullscreen 全屏 - + RestoreLayout 恢復默認佈局 - + BreakPoint 中斷點 - + ToggleBreakPoint 切換中斷點 - + AddBreakPoint 添加中斷點 - + Settings 設置 - + ClangFormat Clang Format - + Local 本地 - + Global 全局 - + Variables 變數 - + ConsoleOutput 輸出 - + StackTrace 棧跟蹤 - + Symbol 符號 - - - - - - + + + + + + Error 錯誤 - + Too much opened files 打開的檔過多,無法繼續操作! - + ConfirmSave 正在關閉未保存的腳本檔,你確定保存嗎? - + ScriptSaveFailedClose 腳本保存失敗,你仍確認關閉嗎? - + Debuging... 調試中... - + Running... 運行中... - - + + ChooseFile 選擇檔 - - - + + + FilePermission 因檔許可權無法繼續! - + ReloadSuccessfully 檔重新加載成功! - + ReloadUnSuccessfully 檔重新加載失敗! - + ChooseSaveFile 請選擇保存檔路徑: - - + + SaveSuccessfully 保存成功! - + SaveUnSuccessfully 保存失敗! - + FormatCodeFailed 代碼格式化失敗 - - + + CannotSave2RunScript 無法保存,故無法繼續運行腳本。 - - + + ScriptStillRunning 腳本仍在運行,你確定要退出嗎? - + ConfirmScriptSave 你嘗試關閉程式,但仍存在未保存的腳本檔,你確定保存這些更改嗎? - + View 視圖 - + Debug 調試 - + Run 運行 - + RunWithDbg 調試運行 - + Pause 暫停 - + Continue 繼續 - + Stop 停止 - + Restart 重啟 - + StepInto 單步步入 - + StepOver 單步步過 - + StepOut 單步跳出 - + RemoveBreakPoint 刪除中斷點 - + Info 資訊 - + Software 軟體 - + Sponsor 贊助 - + Wiki 網頁 Wiki - + AboutQT 關於 QT @@ -4842,6 +4842,64 @@ 在啟動 Windows 資源管理器的路徑中找不到 explorer.exe。 + + ShowTextDialog + + + TextBroswer + + + + + TooHugeFile + + + + + Edit + 編輯 + + + + View + 視圖 + + + + General + 基本 + + + + Copy + 複製 + + + + Find + 查找 + + + + Goto + 跳轉 + + + + Encoding + 編碼 + + + + Display + 顯示 + + + + CopyToClipBoard + 數據已拷貝到粘貼板 + + SkinManager diff --git a/resources.qrc b/resources.qrc index 49a381b..6d9d6d8 100644 --- a/resources.qrc +++ b/resources.qrc @@ -106,6 +106,7 @@ images/unover.png images/unsaved.png images/update.png + images/viewtxt.png images/wiki.png images/win.png images/workspace.png @@ -151,5 +152,7 @@ images/completion/CVunion.png images/completion/classnew.png - + + src/angelscript.xml + diff --git a/src/angelscript.xml b/src/angelscript.xml new file mode 100644 index 0000000..fb57029 --- /dev/null +++ b/src/angelscript.xml @@ -0,0 +1,164 @@ + + + + + + abstract + and + break + case + cast + catch + class + const + continue + default + delete + do + else + enum + explicit + external + false + final + float + for + from + funcdef + function + get + if + import + in + inout + interface + is + mixin + namespace + not + null + or + out + override + private + property + protected + return + set + shared + super + switch + this + true + try + typedef + while + xor + + + void + bool + uint + uint8 + uint16 + uint32 + uint64 + int + double + int8 + int16 + int32 + int64 + auto + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/class/angelobjstring.cpp b/src/class/angelobjstring.cpp index aeb8083..2076f60 100644 --- a/src/class/angelobjstring.cpp +++ b/src/class/angelobjstring.cpp @@ -29,8 +29,8 @@ QString AngelObjString::stringToString(void *obj, asDebugger *dbg) { Q_UNUSED(dbg); // We know the received object is a string - QString *val = reinterpret_cast(obj); - return *val; + QString val = *reinterpret_cast(obj); + return val; } QString AngelObjString::arrayToString(void *obj, asDebugger *dbg) { diff --git a/src/class/appmanager.cpp b/src/class/appmanager.cpp index 78971f6..6a22dbe 100644 --- a/src/class/appmanager.cpp +++ b/src/class/appmanager.cpp @@ -37,6 +37,8 @@ #include "utilities.h" #include "wingmessagebox.h" +#include + AppManager *AppManager::_instance = nullptr; AppManager::AppManager(int &argc, char *argv[]) @@ -81,6 +83,10 @@ AppManager::AppManager(int &argc, char *argv[]) SkinManager::instance(); + // add angelscript highlight support + auto &repo = WingCodeEdit::syntaxRepo(); + repo.addCustomSearchPath(QStringLiteral(":/WingScript/Angelscript")); + auto dontSplash = set.dontUseSplash(); SplashDialog *splash = nullptr; diff --git a/src/class/ascompletion.cpp b/src/class/ascompletion.cpp index 563d088..0c0956a 100644 --- a/src/class/ascompletion.cpp +++ b/src/class/ascompletion.cpp @@ -36,15 +36,12 @@ AsCompletion::AsCompletion(asIScriptEngine *engine, WingCodeEdit *p) : WingCompleter(p), parser(engine), _engine(engine) { Q_ASSERT(engine); - // addTrigger(*DOT_TRIGGER); - // addTrigger(*DBL_COLON_TRIGGER); - - // // unleash the power of call tips - // addTrigger(*LEFT_PARE_TRIGGER); - // // clear the tips - // addTrigger(*SEMI_COLON_TRIGGER); - - // setTrigWordLen(3); + setTriggerList({*DOT_TRIGGER, *DBL_COLON_TRIGGER, + // unleash the power of call tips + *LEFT_PARE_TRIGGER, + // clear the tips + *SEMI_COLON_TRIGGER}); + setTriggerAmount(3); } AsCompletion::~AsCompletion() {} diff --git a/src/class/codeinfotip.h b/src/class/codeinfotip.h new file mode 100644 index 0000000..d078bff --- /dev/null +++ b/src/class/codeinfotip.h @@ -0,0 +1,35 @@ +/*============================================================================== +** 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 CODEINFOTIP_H +#define CODEINFOTIP_H + +#include + +class CodeInfoTip { +public: + enum class Type { Class, Function, Enum, Variable }; + +public: + QString name; + Type type; + QString nameSpace; + + QString args; // only function use +}; + +#endif // CODEINFOTIP_H diff --git a/src/control/codeedit.cpp b/src/control/codeedit.cpp new file mode 100644 index 0000000..7278df8 --- /dev/null +++ b/src/control/codeedit.cpp @@ -0,0 +1,20 @@ +/*============================================================================== +** 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 "codeedit.h" + +CodeEdit::CodeEdit(QWidget *parent) : WingCodeEdit(parent) {} diff --git a/src/control/codeedit.h b/src/control/codeedit.h new file mode 100644 index 0000000..c313898 --- /dev/null +++ b/src/control/codeedit.h @@ -0,0 +1,35 @@ +/*============================================================================== +** 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 CODEEDIT_H +#define CODEEDIT_H + +#include "WingCodeEdit/wingcodeedit.h" + +class CodeEdit : public WingCodeEdit { + Q_OBJECT + +public: + explicit CodeEdit(QWidget *parent = nullptr); + +signals: + void contentModified(bool b); + +private: +}; + +#endif // CODEEDIT_H diff --git a/src/control/scripteditor.cpp b/src/control/scripteditor.cpp index 4dc2713..b8ca3eb 100644 --- a/src/control/scripteditor.cpp +++ b/src/control/scripteditor.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -42,7 +43,7 @@ ScriptEditor::ScriptEditor(QWidget *parent) this->setFocusPolicy(Qt::StrongFocus); this->setObjectName(QStringLiteral("ScriptEditor")); - m_editor = new WingCodeEdit(this); + m_editor = new CodeEdit(this); m_editor->setAutoIndent(true); m_editor->setMatchBraces(true); m_editor->setShowLongLineEdge(true); @@ -64,6 +65,9 @@ ScriptEditor::ScriptEditor(QWidget *parent) break; } + m_editor->setSyntax( + m_editor->syntaxRepo().definitionForName("AngelScript")); + connect(m_editor, &WingCodeEdit::symbolMarkLineMarginClicked, this, &ScriptEditor::onToggleMark); @@ -154,7 +158,7 @@ void ScriptEditor::processTitle() { } } -WingCodeEdit *ScriptEditor::editor() const { return m_editor; } +CodeEdit *ScriptEditor::editor() const { return m_editor; } bool ScriptEditor::formatCode() { bool ok; diff --git a/src/control/scripteditor.h b/src/control/scripteditor.h index fa7bb95..bc8ebc6 100644 --- a/src/control/scripteditor.h +++ b/src/control/scripteditor.h @@ -19,7 +19,7 @@ #define SCRIPTEDITOR_H #include "Qt-Advanced-Docking-System/src/DockWidget.h" -#include "wingcodeedit.h" +#include "control/codeedit.h" class ScriptEditor : public ads::CDockWidget { Q_OBJECT @@ -30,7 +30,7 @@ public: QString fileName() const; - WingCodeEdit *editor() const; + CodeEdit *editor() const; bool formatCode(); @@ -49,7 +49,7 @@ private: void processTitle(); private: - WingCodeEdit *m_editor = nullptr; + CodeEdit *m_editor = nullptr; QString m_fileName; }; diff --git a/src/control/scriptingconsole.cpp b/src/control/scriptingconsole.cpp index 50496e5..bb9c452 100644 --- a/src/control/scriptingconsole.cpp +++ b/src/control/scriptingconsole.cpp @@ -20,13 +20,16 @@ #include "class/scriptconsolemachine.h" #include "qregularexpression.h" +#include +#include + #include #include #include #include ScriptingConsole::ScriptingConsole(QWidget *parent) : QConsoleWidget(parent) { - _warnCharFmt.setForeground(QColorConstants::Svg::gold); + setSyntax(syntaxRepo().definitionForName("AngelScript")); } ScriptingConsole::~ScriptingConsole() {} @@ -93,11 +96,11 @@ void ScriptingConsole::init() { } void ScriptingConsole::initOutput() { + _s << QStringLiteral(R"(""")") << Qt::endl; write(tr("Scripting console for WingHexExplorer")); - _s << Qt::endl; write(tr(">>>> Powered by AngelScript <<<<")); - _s << Qt::endl << Qt::endl; + _s << Qt::endl << QStringLiteral(R"(""")") << Qt::endl; appendCommandPrompt(); setMode(Input); } diff --git a/src/control/scriptingconsole.h b/src/control/scriptingconsole.h index f1226fc..2bd5c26 100644 --- a/src/control/scriptingconsole.h +++ b/src/control/scriptingconsole.h @@ -71,7 +71,6 @@ private: QMutex _queueLocker; bool _waitforRead = false; - QTextCharFormat _warnCharFmt; std::function _getInputFn; }; diff --git a/src/dialog/scriptingdialog.cpp b/src/dialog/scriptingdialog.cpp index 0b942c8..104c819 100644 --- a/src/dialog/scriptingdialog.cpp +++ b/src/dialog/scriptingdialog.cpp @@ -177,30 +177,32 @@ void ScriptingDialog::initConsole() { } } + const auto bpMark = QStringLiteral("bp"); + const auto curSym = QStringLiteral("cur"); + const auto hitCur = QStringLiteral("curbp"); + // remove the last mark if (!_lastCurLine.first.isEmpty() && _lastCurLine.second >= 0) { - // auto lastCur = QCodeEdit::managed(_lastCurLine.first); - // auto doc = lastCur->document(); - // auto line = doc->line(_lastCurLine.second - 1); - // if (line.hasMark(curMark)) { - // line.removeMark(curMark); - // } else if (line.hasMark(curHitMark)) { - // line.removeMark(curHitMark); - // line.addMark(bpMark); - // } + auto lastCur = findEditorView(_lastCurLine.first); + auto e = lastCur->editor(); + auto symID = e->symbolMark(_lastCurLine.second); + + if (symID == curSym) { + e->removeSymbolMark(_lastCurLine.second); + } else if (symID == hitCur) { + e->addSymbolMark(_lastCurLine.second, bpMark); + } } auto editor = e->editor(); // add the new mark - // auto doc = editor->document(); - // auto line = doc->line(lineNr - 1); - // if (line.hasMark(bpMark)) { - // line.removeMark(bpMark); - // line.addMark(curHitMark); - // } else { - // line.addMark(curMark); - // } + auto symID = editor->symbolMark(lineNr); + if (symID == bpMark) { + editor->addSymbolMark(lineNr, hitCur); + } else { + editor->addSymbolMark(lineNr, curSym); + } // editor->ensureVisible(lineNr - 1); @@ -812,44 +814,39 @@ void ScriptingDialog::swapEditor(ScriptEditor *old, ScriptEditor *cur) { } if (old != nullptr) { - // auto editor = old->editor(); - // editor->disconnect(SIGNAL(copyAvailable(bool))); - // editor->disconnect(SIGNAL(contentModified(bool))); - // editor->disconnect(SIGNAL(undoAvailable(bool))); - // editor->disconnect(SIGNAL(redoAvailable(bool))); - // editor->disconnect(SIGNAL(zoomed())); + auto editor = old->editor(); + editor->disconnect(SIGNAL(copyAvailable(bool))); + editor->disconnect(SIGNAL(contentModified(bool))); + editor->disconnect(SIGNAL(undoAvailable(bool))); + editor->disconnect(SIGNAL(redoAvailable(bool))); + editor->disconnect(SIGNAL(copyAvailable(bool))); } - // auto editor = cur->editor(); - // m_Tbtneditors.value(ToolButtonIndex::UNDO_ACTION) - // ->setEnabled(editor->canUndo()); - // m_Tbtneditors.value(ToolButtonIndex::REDO_ACTION) - // ->setEnabled(editor->canRedo()); - // m_Tbtneditors.value(ToolButtonIndex::SAVE_ACTION) - // ->setEnabled(Utilities::fileCanWrite(editor->fileName()) && - // editor->isContentModified()); - // m_Tbtneditors.value(ToolButtonIndex::COPY_ACTION) - // ->setEnabled(editor->cursor().hasSelection()); + auto editor = cur->editor(); + m_Tbtneditors.value(ToolButtonIndex::UNDO_ACTION) + ->setEnabled(editor->document()->isUndoAvailable()); + m_Tbtneditors.value(ToolButtonIndex::REDO_ACTION) + ->setEnabled(editor->document()->isRedoAvailable()); + m_Tbtneditors.value(ToolButtonIndex::SAVE_ACTION) + ->setEnabled(Utilities::fileCanWrite(cur->fileName()) && + editor->document()->isModified()); + m_Tbtneditors.value(ToolButtonIndex::COPY_ACTION) + ->setEnabled(editor->textCursor().hasSelection()); - // connect(editor, &QEditor::copyAvailable, - // m_Tbtneditors.value(ToolButtonIndex::COPY_ACTION), - // &QToolButton::setEnabled); - // connect(editor, &QEditor::contentModified, this, [=] { - // m_Tbtneditors.value(ToolButtonIndex::SAVE_ACTION) - // ->setEnabled(Utilities::fileCanWrite(editor->fileName()) && - // editor->isContentModified()); - // }); - // connect(editor, &QEditor::undoAvailable, - // m_Tbtneditors.value(ToolButtonIndex::UNDO_ACTION), - // &QToolButton::setEnabled); - // connect(editor, &QEditor::redoAvailable, - // m_Tbtneditors.value(ToolButtonIndex::REDO_ACTION), - // &QToolButton::setEnabled); - // connect(editor, &QEditor::zoomed, this, [=] { - // Toast::toast(this, NAMEICONRES(QStringLiteral("scale")), - // QString::number(editor->scaleRate() * 100) + - // QStringLiteral("%")); - // }); + connect(editor, &CodeEdit::copyAvailable, + m_Tbtneditors.value(ToolButtonIndex::COPY_ACTION), + &QToolButton::setEnabled); + connect(editor, &CodeEdit::contentModified, this, [=] { + m_Tbtneditors.value(ToolButtonIndex::SAVE_ACTION) + ->setEnabled(Utilities::fileCanWrite(cur->fileName()) && + editor->document()->isModified()); + }); + connect(editor, &CodeEdit::undoAvailable, + m_Tbtneditors.value(ToolButtonIndex::UNDO_ACTION), + &QToolButton::setEnabled); + connect(editor, &CodeEdit::redoAvailable, + m_Tbtneditors.value(ToolButtonIndex::REDO_ACTION), + &QToolButton::setEnabled); m_curEditor = cur; } diff --git a/src/dialog/showtextdialog.cpp b/src/dialog/showtextdialog.cpp new file mode 100644 index 0000000..fbd2520 --- /dev/null +++ b/src/dialog/showtextdialog.cpp @@ -0,0 +1,170 @@ +/*============================================================================== +** 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 "showtextdialog.h" + +#include "class/qkeysequences.h" +#include "class/wingmessagebox.h" +#include "control/codeedit.h" +#include "control/toast.h" +#include "dialog/encodingdialog.h" + +#include +#include + +constexpr auto EMPTY_FUNC = [] {}; + +ShowTextDialog::ShowTextDialog(QWidget *parent) : FramelessDialogBase(parent) { + this->setUpdatesEnabled(false); + + // build up UI + buildUpRibbonBar(); + + auto cw = new QWidget(this); + cw->setSizePolicy( + QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); + auto layout = new QVBoxLayout(cw); + layout->setContentsMargins(1, 0, 1, 0); + layout->setSpacing(0); + layout->addWidget(q_check_ptr(m_ribbon)); + + m_edit = new WingCodeEdit(this); + // auto editor = m_edit->editor(); + // editor->setCodec(QStringLiteral("ASCII")); + // connect(editor, &QEditor::needLoading, this, + // [this]() { load(m_last.buffer, m_last.offset, m_last.size); }); + + m_edit->setReadOnly(true); + m_edit->setAcceptDrops(false); + m_edit->setUndoRedoEnabled(false); + // m_edit->createSimpleBasicContextMenu(true, true); + layout->addWidget(m_edit); + + m_status = new QStatusBar(this); + layout->addWidget(m_status); + buildUpContent(cw); + + // ok, preparing for starting... + this->setWindowTitle(tr("TextBroswer")); + this->setWindowIcon(ICONRES(QStringLiteral("viewtxt"))); + this->setMinimumSize(800, 600); + + this->setUpdatesEnabled(true); +} + +ShowTextDialog::~ShowTextDialog() {} + +void ShowTextDialog::load(QHexBuffer *buffer, const QString encoding, + qsizetype offset, qsizetype size) { + // auto editor = m_edit->editor(); + // editor->blockSignals(true); + // editor->setCodec(encoding); + // load(buffer, offset, size); + // editor->blockSignals(false); +} + +void ShowTextDialog::load(QHexBuffer *buffer, qsizetype offset, + qsizetype size) { + if (buffer == nullptr || offset < 0) { + return; + } + + m_canceled = false; + + if (size < 0) { + size = buffer->length(); + } + + if (size >= std::numeric_limits::max()) { + WingMessageBox::critical(this, this->windowTitle(), tr("TooHugeFile")); + return; + } + + // auto editor = m_edit->editor(); + // editor->setUpdatesEnabled(false); + + // auto doc = editor->document(); + // auto orign = offset; + + // editor->setUpdatesEnabled(true); + // m_status->showMessage(editor->codecName()); +} + +void ShowTextDialog::buildUpRibbonBar() { + m_ribbon = new Ribbon(this); + m_ribbon->setAcceptDrops(false); + buildEditPage(m_ribbon->addTab(tr("Edit"))); + buildViewPage(m_ribbon->addTab(tr("View"))); +} + +RibbonTabContent *ShowTextDialog::buildEditPage(RibbonTabContent *tab) { + auto shortcuts = QKeySequences::instance(); + { + auto pannel = tab->addGroup(tr("General")); + + auto a = addPannelAction(pannel, QStringLiteral("copy"), tr("Copy"), + &ShowTextDialog::on_copyfile); + setPannelActionToolTip(a, QKeySequence::Copy); + + a = addPannelAction(pannel, QStringLiteral("find"), tr("Find"), + &ShowTextDialog::on_findfile); + setPannelActionToolTip(a, QKeySequence::Find); + + a = addPannelAction(pannel, QStringLiteral("jmp"), tr("Goto"), + &ShowTextDialog::on_gotoline); + setPannelActionToolTip(a, + shortcuts.keySequence(QKeySequences::Key::GOTO)); + + addPannelAction(pannel, QStringLiteral("encoding"), tr("Encoding"), + &ShowTextDialog::on_encoding, + shortcuts.keySequence(QKeySequences::Key::ENCODING)); + } + + return tab; +} + +RibbonTabContent *ShowTextDialog::buildViewPage(RibbonTabContent *tab) { + auto shortcuts = QKeySequences::instance(); + + auto pannel = tab->addGroup(tr("Display")); + + return tab; +} + +void ShowTextDialog::on_copyfile() { + // m_edit->editor()->copy(); + Toast::toast(this, NAMEICONRES(QStringLiteral("copy")), + tr("CopyToClipBoard")); +} + +void ShowTextDialog::on_findfile() { + // m_edit->editor()->find(); +} + +void ShowTextDialog::on_gotoline() { + // m_edit->editor()->gotoLine(); +} + +void ShowTextDialog::on_encoding() { + EncodingDialog d; + if (d.exec()) { + auto res = d.getResult(); + // m_edit->editor()->setCodec(res); + } +} + +void ShowTextDialog::on_cancel() { m_canceled = true; } diff --git a/src/dialog/showtextdialog.h b/src/dialog/showtextdialog.h new file mode 100644 index 0000000..9cef865 --- /dev/null +++ b/src/dialog/showtextdialog.h @@ -0,0 +1,137 @@ +/*============================================================================== +** 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 SHOWTEXTDIALOG_H +#define SHOWTEXTDIALOG_H + +#include "QHexView/document/buffer/qhexbuffer.h" + +#include "QWingRibbon/ribbon.h" + +#include "QWingRibbon/ribbonbuttongroup.h" +#include "QWingRibbon/ribbontabcontent.h" + +#include "WingCodeEdit/wingcodeedit.h" +#include "framelessdialogbase.h" +#include "utilities.h" + +#include +#include +#include + +class ShowTextDialog : public FramelessDialogBase { + Q_OBJECT +public: + explicit ShowTextDialog(QWidget *parent = nullptr); + virtual ~ShowTextDialog(); + +public: + void load(QHexBuffer *buffer, const QString encoding, qsizetype offset = 0, + qsizetype size = -1); + void load(QHexBuffer *buffer, qsizetype offset = 0, qsizetype size = -1); + +private: + void buildUpRibbonBar(); + + RibbonTabContent *buildEditPage(RibbonTabContent *tab); + RibbonTabContent *buildViewPage(RibbonTabContent *tab); + +private: + template + inline QToolButton * + addPannelAction(RibbonButtonGroup *pannel, const QString &iconName, + const QString &title, Func &&slot, + const QKeySequence &shortcut = QKeySequence(), + QMenu *menu = nullptr) { + return addPannelAction(pannel, ICONRES(iconName), title, slot, shortcut, + menu); + } + + template + inline QToolButton * + addPannelAction(RibbonButtonGroup *pannel, const QIcon &icon, + const QString &title, Func &&slot, + const QKeySequence &shortcut = QKeySequence(), + QMenu *menu = nullptr) { + Q_ASSERT(pannel); + auto a = new QToolButton(pannel); + a->setText(title); + a->setIcon(icon); + setPannelActionToolTip(a, shortcut); + + if (!shortcut.isEmpty()) { + auto shortCut = new QShortcut(shortcut, this); + shortCut->setContext(Qt::WindowShortcut); + connect(shortCut, &QShortcut::activated, a, &QToolButton::click); + } + + a->setMenu(menu); + if (menu) { + a->setPopupMode(QToolButton::InstantPopup); + } + connect(a, &QToolButton::clicked, this, slot); + pannel->addButton(a); + return a; + } + + template + inline QAction *newAction(const QString &title, Func &&slot, + const QKeySequence &shortcut = QKeySequence()) { + auto a = new QAction; + a->setText(title); + a->setShortcutVisibleInContextMenu(true); + a->setShortcut(shortcut); + connect(a, &QAction::triggered, this, slot); + return a; + } + + inline void + setPannelActionToolTip(QToolButton *action, + const QKeySequence &shortcut = QKeySequence()) { + Q_ASSERT(action); + auto title = action->text(); + action->setToolTip( + shortcut.isEmpty() + ? QStringLiteral("

%1

").arg(title) + : QStringLiteral( + "

%1

%2

") + .arg(title, shortcut.toString())); + } + +private slots: + void on_copyfile(); + void on_findfile(); + void on_gotoline(); + void on_encoding(); + + void on_cancel(); + +private: + Ribbon *m_ribbon = nullptr; + WingCodeEdit *m_edit = nullptr; + bool m_canceled = false; + + QStatusBar *m_status = nullptr; + + struct { + QHexBuffer *buffer = nullptr; + qsizetype offset = 0; + qsizetype size = -1; + } m_last; +}; + +#endif // SHOWTEXTDIALOG_H