feat: 增加繁体中文;修复多语言支持;增加设备插件类;

This commit is contained in:
寂静的羽夏 2025-01-10 21:14:25 +08:00
parent 3dc1ab0ee8
commit 411118bd62
20 changed files with 6587 additions and 871 deletions

View File

@ -345,8 +345,10 @@ set(CODEEDIT_WIDGET
src/qcodeeditwidget/formatconfigmodel.h
src/qcodeeditwidget/formatconfigmodel.cpp)
set(PLUGIN_SRC src/plugin/iwingplugin.h src/plugin/pluginsystem.cpp
src/plugin/pluginsystem.h src/plugin/settingpage.h)
set(PLUGIN_SRC
src/plugin/iwingplugin.h src/plugin/iwingpluginbase.h
src/plugin/iwingdevice.h src/plugin/pluginsystem.cpp
src/plugin/pluginsystem.h src/plugin/settingpage.h)
# localization support
file(
@ -397,8 +399,9 @@ foreach(TS_FILE IN LISTS TS_FILES)
set(LANG_NEED_COPY_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/${TS_DIR}")
set(LANG_NEED_COPY "${LANG_NEED_COPY_PREFIX}/about.md"
"${LANG_NEED_COPY_PREFIX}/devs.md")
add_custom_target(
copy_lang_files
copy_lang_files_${LANG_NAME}
COMMAND ${CMAKE_COMMAND} -E copy ${LANG_NEED_COPY} ${QM_DIR}
COMMENT "Copying files to ${LANG_DEST}")
@ -407,12 +410,12 @@ foreach(TS_FILE IN LISTS TS_FILES)
set(LANG_COMPRESS_CONTENT "winghex.qm" "about.md" "devs.md")
add_custom_target(
pak_lang_files
pak_lang_files_${LANG_NAME}
COMMAND ${CMAKE_COMMAND} -E tar cf ${LANG_PAK_NAME} --format=zip
${LANG_COMPRESS_CONTENT}
WORKING_DIRECTORY "${QM_DIR}"
COMMENT "Compressing ${TS_FILE} into ${LANG_PAK_NAME}"
DEPENDS ${QM_FILES} copy_lang_files)
DEPENDS ${QM_FILES} copy_lang_files_${LANG_NAME})
set(TARGET_NAME "langgen_${LANG_NAME}")
add_custom_target(
@ -420,7 +423,7 @@ foreach(TS_FILE IN LISTS TS_FILES)
COMMAND ${CMAKE_COMMAND} -E copy ${LANG_PAK_NAME} ${QM_OUT_DIR}
WORKING_DIRECTORY "${QM_DIR}"
COMMENT "Copy ${TS_FILE} into ${LANG_PAK_NAME}"
DEPENDS pak_lang_files)
DEPENDS pak_lang_files_${LANG_NAME})
list(APPEND LANG_TARGETS ${TARGET_NAME})
endforeach()

View File

@ -26,22 +26,29 @@ option(TEST_MODE TRUE)
# vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
set(WINGHEX_SDK "${CMAKE_CURRENT_SOURCE_DIR}/../src/plugin")
set(PLUGIN_INTERFACE_BASE_FOUND FALSE)
set(PLUGIN_INTERFACE_FOUND FALSE)
set(PLUGIN_SETPAGE_FOUND FALSE)
if(EXISTS "${WINGHEX_SDK}/iwingpluginbase.h")
set(PLUGIN_INTERFACE_BASE_FOUND TRUE)
endif()
if(EXISTS "${WINGHEX_SDK}/iwingplugin.h")
set(PLUGIN_INTERFACE_FOUND TRUE)
endif()
if(EXISTS "${WINGHEX_SDK}/settingpage.h")
set(PLUGIN_SETPAGE_FOUND TRUE)
endif()
if(PLUGIN_INTERFACE_FOUND AND PLUGIN_SETPAGE_FOUND)
if(PLUGIN_INTERFACE_FOUND
AND PLUGIN_INTERFACE_BASE_FOUND
AND PLUGIN_SETPAGE_FOUND)
message(STATUS "${WINGHEX_SDK} is valid SDK path")
else()
message(FATAL_ERROR "Invalid SDK path!")
endif()
set(WINGHEX_SDK_HEADER "${WINGHEX_SDK}/iwingplugin.h"
"${WINGHEX_SDK}/settingpage.h")
set(WINGHEX_SDK_HEADER
"${WINGHEX_SDK}/iwingplugin.h" "${WINGHEX_SDK}/iwingpluginbase.h"
"${WINGHEX_SDK}/settingpage.h")
include_directories(${WINGHEX_SDK})
# For Qt

View File

@ -671,7 +671,7 @@
<name>GeneralSettingDialog</name>
<message>
<location filename="../../src/settings/generalsettingdialog.ui" line="38"/>
<location filename="../../src/settings/generalsettingdialog.cpp" line="112"/>
<location filename="../../src/settings/generalsettingdialog.cpp" line="116"/>
<source>General</source>
<translation></translation>
</message>
@ -2093,127 +2093,139 @@
<context>
<name>PluginSystem</name>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="74"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="75"/>
<source>LoadingPlugin</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="292"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="386"/>
<source>FoundDrvPluginCount</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="426"/>
<source>RegisteredFnDup</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="493"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="631"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="800"/>
<source>ErrLoadPluginSign</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="497"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="635"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="804"/>
<source>ErrLoadPluginSDKVersion</source>
<translation> SDK </translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="501"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="639"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="808"/>
<source>ErrLoadPluginNoName</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="506"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="644"/>
<source>ErrLoadInvalidPUID</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="511"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="649"/>
<source>ErrLoadLoadedPlugin</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="543"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="681"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="829"/>
<source>ErrLoadInitPlugin</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="556"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="694"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="811"/>
<source>PluginName :</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="557"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="695"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="812"/>
<source>PluginAuthor :</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="558"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="696"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="813"/>
<source>PluginWidgetRegister</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="620"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="854"/>
<source>EmptyNameDockWidget:</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="630"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="864"/>
<source>InvalidNameDockWidget:</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="637"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="872"/>
<source>InvalidNullDockWidget:</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="877"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="1012"/>
<source>[EvilCall]</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="2388"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="2357"/>
<source>Not allowed operation in non-UI thread</source>
<translation> UI 线</translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="2450"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="408"/>
<source>UnsafePluginDir</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="2456"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="325"/>
<source>FoundPluginCount</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="2479"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="348"/>
<source>PluginLoadingFailedSummary</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="2483"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="352"/>
<source>- PluginName:</source>
<translation>- </translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="2484"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="353"/>
<source>- Dependencies:</source>
<translation>- </translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="2486"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="355"/>
<source>PUID:</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="2487"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="356"/>
<source>Version:</source>
<translation></translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="2489"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="358"/>
<source>MD5:</source>
<translation>MD5 </translation>
</message>
<message>
<location filename="../../src/plugin/pluginsystem.cpp" line="2496"/>
<location filename="../../src/plugin/pluginsystem.cpp" line="365"/>
<source>PluginLoadingFinished</source>
<translation></translation>
</message>
@ -2709,23 +2721,23 @@ Do you wish to keep up to date by reloading the file?</source>
<translation></translation>
</message>
<message>
<location filename="../../src/class/aspreprocesser.cpp" line="511"/>
<location filename="../../src/class/aspreprocesser.cpp" line="406"/>
<source>Failed to open script file </source>
<translation></translation>
</message>
<message>
<location filename="../../src/class/aspreprocesser.cpp" line="336"/>
<location filename="../../src/class/aspreprocesser.cpp" line="383"/>
<location filename="../../src/class/aspreprocesser.cpp" line="246"/>
<location filename="../../src/class/aspreprocesser.cpp" line="292"/>
<source>Invalid file name for #include; it contains a line-break: </source>
<translation>#include </translation>
</message>
<message>
<location filename="../../src/class/aspreprocesser.cpp" line="402"/>
<location filename="../../src/class/aspreprocesser.cpp" line="311"/>
<source>Invalid file name for #include; it contains a line-break or unpaired symbol</source>
<translation>#include </translation>
</message>
<message>
<location filename="../../src/class/aspreprocesser.cpp" line="427"/>
<location filename="../../src/class/aspreprocesser.cpp" line="342"/>
<source>Invalid #pragma directive</source>
<translation>#pragma </translation>
</message>

11
lang/zh_TW/about.md Normal file
View File

@ -0,0 +1,11 @@
一個自由的強大免費的十六進制編輯器,基於 QT C++ 進行開發,作者是寂靜的羽夏。
如有 Bug, 歡迎回饋到 [Github](https://github.com/Wing-summer/WingHexExplorer2/issues) 上,如果你訪問這有困難的話,也可以回饋到 [Gitee](https://gitee.com/wing-cloud/WingHexExplorer2/issues) 上。如果實在不行,可以通過我的 [博客園](https://www.cnblogs.com/wingsummer) 上公告欄的任意一種聯繫方式來告訴我。不過我還是希望你回饋到 Github 上方便我寫遞交注釋的。
開源不易,也歡迎贊助或者參與代碼和文檔貢獻,我默認會將您放入倉庫首頁進行鳴謝:
* Github 上:[軟體貢獻者](https://github.com/Wing-summer/WingHexExplorer2?tab=readme-ov-file#%E4%BB%A3%E7%A0%81%E8%B4%A1%E7%8C%AE%E8%80%85) | [文檔貢獻者](https://github.com/Wing-summer/WingHexExplorer2/wiki/README)
* Gitee 上:[軟體貢獻者](https://gitee.com/wing-cloud/WingHexExplorer2#%E4%BB%A3%E7%A0%81%E8%B4%A1%E7%8C%AE%E8%80%85) | [文檔貢獻者](https://gitee.com/wing-cloud/WingHexExplorer2/wikis/README)
許可證AGPL-3.0

2
lang/zh_TW/devs.md Normal file
View File

@ -0,0 +1,2 @@
* 寂靜的羽夏wingsummer專案發起人程式作者

5472
lang/zh_TW/winghex.ts Normal file

File diff suppressed because it is too large Load Diff

View File

@ -22,22 +22,29 @@ if(NOT EXISTS "${WINGHEX_SDK}")
message(FATAL_ERROR "Please config the SDK Path - WINGHEX_SDK")
endif()
set(PLUGIN_INTERFACE_BASE_FOUND FALSE)
set(PLUGIN_INTERFACE_FOUND FALSE)
set(PLUGIN_SETPAGE_FOUND FALSE)
if(EXISTS "${WINGHEX_SDK}/iwingpluginbase.h")
set(PLUGIN_INTERFACE_BASE_FOUND TRUE)
endif()
if(EXISTS "${WINGHEX_SDK}/iwingplugin.h")
set(PLUGIN_INTERFACE_FOUND TRUE)
endif()
if(EXISTS "${WINGHEX_SDK}/settingpage.h")
set(PLUGIN_SETPAGE_FOUND TRUE)
endif()
if(PLUGIN_INTERFACE_FOUND AND PLUGIN_SETPAGE_FOUND)
if(PLUGIN_INTERFACE_FOUND
AND PLUGIN_INTERFACE_BASE_FOUND
AND PLUGIN_SETPAGE_FOUND)
message(STATUS "${WINGHEX_SDK} is valid SDK path")
else()
message(FATAL_ERROR "Invalid SDK path!")
endif()
set(WINGHEX_SDK_HEADER "${WINGHEX_SDK}/iwingplugin.h"
"${WINGHEX_SDK}/settingpage.h")
set(WINGHEX_SDK_HEADER
"${WINGHEX_SDK}/iwingplugin.h" "${WINGHEX_SDK}/iwingpluginbase.h"
"${WINGHEX_SDK}/settingpage.h")
include_directories(${WINGHEX_SDK})
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets LinguistTools)

View File

@ -49,20 +49,6 @@ int AsPreprocesser::AddSectionFromFile(const QString &filename) {
return 0;
}
int AsPreprocesser::AddSectionFromMemory(const QString &sectionName,
const QByteArray &code,
int lineOffset) {
if (IncludeIfNotAlreadyIncluded(sectionName)) {
int r = ProcessScriptSection(code, 0, sectionName, lineOffset);
if (r < 0)
return r;
else
return 1;
}
return 0;
}
QList<AsPreprocesser::ScriptData> AsPreprocesser::GetScriptData() const {
return modifiedScripts;
}
@ -98,13 +84,37 @@ QString AsPreprocesser::GetSectionName(unsigned int idx) const {
return includedScripts.at(idx);
}
void AsPreprocesser::ClearAll() {
includedScripts.clear();
std::optional<QString>
AsPreprocesser::ReadLineAndSkip(const QString &sectionName) {
if (_currentScripts.contains(sectionName)) {
auto &scriptInfo = _currentScripts[sectionName];
auto begin = *scriptInfo.first;
if (begin < 0) {
return std::nullopt;
}
currentClass.clear();
currentNamespace.clear();
auto strpos = scriptInfo.second->indexOf('\n', begin);
QString ret;
int overLen = 0;
if (strpos < 0) {
ret = scriptInfo.second->mid(*scriptInfo.first);
overLen = scriptInfo.second->length() - strpos;
} else {
overLen = strpos - begin + 1;
ret = scriptInfo.second->mid(*scriptInfo.first, overLen);
}
OverwriteCode(*scriptInfo.second, begin, overLen);
*scriptInfo.first = strpos;
return ret;
}
return std::nullopt;
}
void AsPreprocesser::ClearAll() { includedScripts.clear(); }
int AsPreprocesser::ProcessScriptSection(const QByteArray &script, int length,
const QString &sectionname,
int lineOffset) {
@ -120,14 +130,19 @@ int AsPreprocesser::ProcessScriptSection(const QByteArray &script, int length,
// First perform the checks for #if directives to exclude code that
// shouldn't be compiled
unsigned int pos = 0;
qsizetype pos = 0;
_currentScripts.insert(sectionname, qMakePair(&pos, &modifiedScript));
LocalGuardHelper guard(
[this, sectionname]() { _currentScripts.remove(sectionname); });
int nested = 0;
while (qsizetype(pos) < modifiedScript.size()) {
while (pos < modifiedScript.size()) {
asUINT len = 0;
asETokenClass t = engine->ParseToken(modifiedScript.data() + pos,
modifiedScript.size() - pos, &len);
if (t == asTC_UNKNOWN && modifiedScript[pos] == '#' &&
(qsizetype(pos) + 1 < modifiedScript.size())) {
(pos + 1 < modifiedScript.size())) {
int start = pos++;
// Is this an #if directive?
@ -175,14 +190,9 @@ int AsPreprocesser::ProcessScriptSection(const QByteArray &script, int length,
pos += len;
}
// Preallocate memory
QString name, declaration;
QVector<QString> metadata;
declaration.reserve(100);
// Then check for meta data and pre-processor directives
// Then check for pre-processor directives
pos = 0;
while (qsizetype(pos) < modifiedScript.size()) {
while (pos >= 0 && pos < modifiedScript.size()) {
asUINT len = 0;
asETokenClass t = engine->ParseToken(modifiedScript.data() + pos,
modifiedScript.size() - pos, &len);
@ -199,108 +209,8 @@ int AsPreprocesser::ProcessScriptSection(const QByteArray &script, int length,
continue;
}
// Check if class or interface so the metadata for members can be
// gathered
if (currentClass.isEmpty() &&
(token == "class" || token == "interface")) {
// Get the identifier after "class"
do {
pos += len;
if (qsizetype(pos) >= modifiedScript.size()) {
t = asTC_UNKNOWN;
break;
}
t = engine->ParseToken(modifiedScript.data() + pos,
modifiedScript.size() - pos, &len);
} while (t == asTC_COMMENT || t == asTC_WHITESPACE);
if (t == asTC_IDENTIFIER) {
currentClass = modifiedScript.mid(pos, len);
// Search until first { or ; is encountered
while (qsizetype(pos) < modifiedScript.length()) {
engine->ParseToken(modifiedScript.data() + pos,
modifiedScript.size() - pos, &len);
// If start of class section encountered stop
if (modifiedScript[pos] == '{') {
pos += len;
break;
} else if (modifiedScript[pos] == ';') {
// The class declaration has ended and there are no
// children
currentClass.clear();
pos += len;
break;
}
// Check next symbol
pos += len;
}
}
continue;
}
// Check if end of class
if (currentClass != "" && token == "}") {
currentClass = "";
pos += len;
continue;
}
// Check if namespace so the metadata for members can be gathered
if (token == "namespace") {
// Get the scope after "namespace". It can be composed of multiple
// nested namespaces, e.g. A::B::C
do {
do {
pos += len;
t = engine->ParseToken(modifiedScript.data() + pos,
modifiedScript.size() - pos, &len);
} while (t == asTC_COMMENT || t == asTC_WHITESPACE);
if (t == asTC_IDENTIFIER) {
if (currentNamespace != "")
currentNamespace += "::";
currentNamespace += modifiedScript.mid(pos, len);
}
} while (
t == asTC_IDENTIFIER ||
(t == asTC_KEYWORD && modifiedScript.mid(pos, len) == "::"));
// Search until first { is encountered
while (qsizetype(pos) < modifiedScript.length()) {
engine->ParseToken(modifiedScript.data() + pos,
modifiedScript.size() - pos, &len);
// If start of namespace section encountered stop
if (modifiedScript[pos] == '{') {
pos += len;
break;
}
// Check next symbol
pos += len;
}
continue;
}
// Check if end of namespace
if (currentNamespace != "" && token == "}") {
auto found = currentNamespace.lastIndexOf("::");
if (found >= 0) {
currentNamespace.remove(found, currentNamespace.size() - found);
} else {
currentNamespace = "";
}
pos += len;
continue;
}
// Is this a preprocessor directive?
if (token == "#" && (qsizetype(pos + 1) < modifiedScript.size())) {
if (token == "#" && (pos + 1 < modifiedScript.size())) {
int start = pos++;
t = engine->ParseToken(modifiedScript.data() + pos,
@ -355,8 +265,7 @@ int AsPreprocesser::ProcessScriptSection(const QByteArray &script, int length,
// find the next '>'
auto rpos = pos;
bool found = false;
for (; qsizetype(rpos) < modifiedScript.size();
++rpos) {
for (; rpos < modifiedScript.size(); ++rpos) {
if (modifiedScript[rpos] == '>') {
found = true;
break;
@ -409,7 +318,7 @@ int AsPreprocesser::ProcessScriptSection(const QByteArray &script, int length,
} else if (token == "pragma") {
// Read until the end of the line
pos += len;
for (; qsizetype(pos) < modifiedScript.size() &&
for (; pos < modifiedScript.size() &&
modifiedScript[pos] != '\n';
pos++)
;
@ -417,8 +326,14 @@ int AsPreprocesser::ProcessScriptSection(const QByteArray &script, int length,
// Call the pragma callback
auto pragmaText =
modifiedScript.mid(start + 7, pos - start - 7);
// Overwrite the pragma directive with space characters
// to avoid compiler error
OverwriteCode(modifiedScript, start, pos - start);
int r = pragmaCallback
? pragmaCallback(pragmaText, this, pragmaParam)
? pragmaCallback(pragmaText, this, sectionname,
pragmaParam)
: -1;
if (r < 0) {
// TODO: Report the correct line number
@ -427,30 +342,10 @@ int AsPreprocesser::ProcessScriptSection(const QByteArray &script, int length,
QObject::tr("Invalid #pragma directive").toUtf8());
return r;
}
// Overwrite the pragma directive with space characters
// to avoid compiler error
OverwriteCode(modifiedScript, start, pos - start);
}
} else {
// Check for lines starting with #!, e.g. shebang
// interpreter directive. These will be treated as comments
// and removed by the preprocessor
if (modifiedScript[pos] == '!') {
// Read until the end of the line
pos += len;
for (; qsizetype(pos) < modifiedScript.size() &&
modifiedScript[pos] != '\n';
pos++)
;
// Overwrite the directive with space characters to
// avoid compiler error
OverwriteCode(modifiedScript, start, pos - start);
}
}
}
// Don't search for metadata/includes within statement blocks or
// Don't search for includes within statement blocks or
// between tokens in statements
else {
pos = SkipStatement(modifiedScript, pos);
@ -574,6 +469,10 @@ int AsPreprocesser::SkipStatement(const QByteArray &modifiedScript, int pos) {
return pos;
}
int AsPreprocesser::ReadLine(const QByteArray &modifiedScript, int pos) {
return modifiedScript.indexOf('\n', pos);
}
int AsPreprocesser::ExcludeCode(QByteArray &modifiedScript, int pos) {
asUINT len = 0;
int nested = 0;

View File

@ -39,6 +39,8 @@
#include <QSet>
#include <QVector>
#include <optional>
class AsPreprocesser;
class asCScriptCode;
@ -56,7 +58,8 @@ typedef int (*INCLUDECALLBACK_t)(const QString &include, bool quotedInclude,
// based on that. If the callback returns a negative value the builder will
// report an error and abort the compilation.
typedef int (*PRAGMACALLBACK_t)(const QByteArray &pragmaText,
AsPreprocesser *builder, void *userParam);
AsPreprocesser *builder,
const QString &sectionname, void *userParam);
// Helper class for loading and pre-processing script files to
// support include directives and metadata declarations
@ -73,6 +76,16 @@ public:
QByteArray script;
};
private:
class LocalGuardHelper {
std::function<void()> _dctorfn;
public:
LocalGuardHelper(const std::function<void()> &dctorfn)
: _dctorfn(dctorfn) {}
~LocalGuardHelper() { _dctorfn(); }
};
public:
// Load a script section from a file on disk
// Returns 1 if the file was included
@ -80,14 +93,6 @@ public:
// <0 on error
int AddSectionFromFile(const QString &filename);
// Load a script section from memory
// Returns 1 if the section was included
// 0 if a section with the same name had already been included
// before
// <0 on error
int AddSectionFromMemory(const QString &sectionName, const QByteArray &code,
int lineOffset = 0);
QList<ScriptData> GetScriptData() const;
// Returns the engine
@ -107,6 +112,8 @@ public:
QString GetSectionName(unsigned int idx) const;
std::optional<QString> ReadLineAndSkip(const QString &sectionName);
protected:
void ClearAll();
int ProcessScriptSection(const QByteArray &script, int length,
@ -116,6 +123,8 @@ protected:
int SkipStatement(const QByteArray &modifiedScript, int pos);
int ReadLine(const QByteArray &modifiedScript, int pos);
int ExcludeCode(QByteArray &modifiedScript, int pos);
void OverwriteCode(QByteArray &modifiedScript, int start, int len);
@ -131,12 +140,11 @@ protected:
PRAGMACALLBACK_t pragmaCallback;
void *pragmaParam;
QString currentClass;
QString currentNamespace;
QVector<QString> includedScripts;
QVector<QString> definedWords;
QHash<QString, QPair<qsizetype *, QByteArray *>> _currentScripts;
};
#endif // ASPREPROCESSER_H

View File

@ -37,8 +37,13 @@ LanguageManager &LanguageManager::instance() {
return ins;
}
QString LanguageManager::langDisplay(const QString &lang) const {
return m_langMap.value(lang, lang);
}
LanguageManager::LanguageManager() {
m_langMap = {{"zh_CN", QStringLiteral("简体中文")}};
m_langMap = {{"zh_CN", QStringLiteral("简体中文")},
{"zh_TW", QStringLiteral("繁體中文")}};
auto langPath =
qApp->applicationDirPath() + QDir::separator() + QStringLiteral("lang");
@ -46,6 +51,7 @@ LanguageManager::LanguageManager() {
QDir langDir(langPath);
Q_ASSERT(langDir.exists());
QHash<QString, QLocale> localeMap;
auto langFiles = langDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
for (auto &langinfo : langFiles) {
auto lang = langinfo.fileName();
@ -54,7 +60,7 @@ LanguageManager::LanguageManager() {
continue;
}
m_langs << lang;
m_localeMap.insert(lang, locale);
localeMap.insert(lang, locale);
}
auto lang = SettingManager::instance().defaultLang();
@ -74,7 +80,7 @@ LanguageManager::LanguageManager() {
}
bool found = false;
for (auto p = m_localeMap.begin(); p != m_localeMap.end(); ++p) {
for (auto p = localeMap.begin(); p != localeMap.end(); ++p) {
#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
if (p->territory() == _defaultLocale.territory() &&
#else
@ -87,9 +93,11 @@ LanguageManager::LanguageManager() {
}
}
if (!found) {
_defaultLocale = m_localeMap.value(m_langs.first());
_defaultLocale = localeMap.value(m_langs.first());
}
m_langs = localeMap.keys();
auto qtPath =
#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
QLibraryInfo::path(QLibraryInfo::TranslationsPath);
@ -122,10 +130,6 @@ LanguageManager::LanguageManager() {
} else {
abortAndExit();
}
for (auto &lang : m_langs) {
m_langsDisplay << m_langMap.value(lang, lang);
}
}
bool LanguageManager::unpackTr(const QString &filename) {
@ -178,6 +182,8 @@ void LanguageManager::abortAndExit() {
throw CrashCode::LanguageFile;
}
QStringList LanguageManager::langs() const { return m_langs; }
QLocale LanguageManager::defaultLocale() const { return _defaultLocale; }
QTranslator *LanguageManager::try2LoadPluginLang(const QString &plgID) {
@ -198,5 +204,3 @@ QTranslator *LanguageManager::try2LoadPluginLang(const QString &plgID) {
}
LanguageManager::LanguageData LanguageManager::data() const { return _data; }
QStringList LanguageManager::langsDisplay() const { return m_langsDisplay; }

View File

@ -37,7 +37,7 @@ public:
public:
static LanguageManager &instance();
QStringList langsDisplay() const;
QString langDisplay(const QString &lang) const;
LanguageData data() const;
@ -45,6 +45,8 @@ public:
QTranslator *try2LoadPluginLang(const QString &plgID);
QStringList langs() const;
private:
LanguageManager();
@ -61,9 +63,7 @@ private:
QLocale _defaultLocale;
QStringList m_langs;
QStringList m_langsDisplay;
QHash<QString, QString> m_langMap;
QHash<QString, QLocale> m_localeMap;
};
#endif // LANGUAGEMANAGER_H

View File

@ -445,7 +445,7 @@ void ScriptMachine::cleanUpDbgContext(asIScriptContext *context) {
asDebugger::deleteDbgContextInfo(dbgContext);
}
void ScriptMachine::cleanUpPluginSysIDFunction(asIScriptFunction *fn) {
void ScriptMachine::cleanUpPluginSysIDFunction(asIScriptFunction *) {
// do nothing
// UserData_API is readonly and it will delete later by its allocator
// UserData_PluginFn is just an id, not a valid pointer to data
@ -516,38 +516,38 @@ void ScriptMachine::returnContextCallback(asIScriptEngine *engine,
}
int ScriptMachine::pragmaCallback(const QByteArray &pragmaText,
AsPreprocesser *builder, void *userParam) {
Q_UNUSED(pragmaText);
Q_UNUSED(builder);
AsPreprocesser *builder,
const QString &sectionname, void *userParam) {
Q_UNUSED(userParam);
// Maybe I will use these codes next time
// asIScriptEngine *engine = builder->GetEngine();
asIScriptEngine *engine = builder->GetEngine();
// Filter the pragmaText so only what is of interest remains
// With this the user can add comments and use different whitespaces
// without affecting the result
// asUINT pos = 0;
// asUINT length = 0;
// QStringList tokens;
// while (pos < pragmaText.size()) {
// asETokenClass tokenClass =
// engine->ParseToken(pragmaText.data() + pos, 0, &length);
// if (tokenClass == asTC_IDENTIFIER || tokenClass == asTC_KEYWORD ||
// tokenClass == asTC_VALUE) {
// auto token = pragmaText.mid(pos, length);
// tokens << token;
// }
// if (tokenClass == asTC_UNKNOWN)
// return -1;
// pos += length;
// }
// Interpret the result
// if (cleanText == " debug") {
// // g_doDebug = true;
// return 0;
// }
asUINT pos = 0;
asUINT length = 0;
QStringList tokens;
while (pos < pragmaText.size()) {
asETokenClass tokenClass =
engine->ParseToken(pragmaText.data() + pos, 0, &length);
if (tokenClass == asTC_IDENTIFIER || tokenClass == asTC_KEYWORD ||
tokenClass == asTC_VALUE) {
auto token = pragmaText.mid(pos, length);
tokens << token;
}
if (tokenClass == asTC_UNKNOWN)
return -1;
pos += length;
}
auto pn = tokens.takeFirst();
if (PluginSystem::instance().dispatchEvent(
IWingPlugin::RegisteredEvent::ScriptPragma,
{quintptr(builder), sectionname, pn, tokens})) {
return 0;
}
// The #pragma directive was not accepted
return -1;

View File

@ -133,7 +133,8 @@ private:
asIScriptContext *ctx, void *param);
static int pragmaCallback(const QByteArray &pragmaText,
AsPreprocesser *builder, void *userParam);
AsPreprocesser *builder,
const QString &sectionname, void *userParam);
static int includeCallback(const QString &include, bool quotedInclude,
const QString &from, AsPreprocesser *builder,

View File

@ -159,7 +159,7 @@ MainWindow::MainWindow(SplashDialog *splash) : FramelessMainWindow() {
splash->setInfoText(tr("LoadingPlg:") + plgName);
});
plg.setMainWindow(this);
plg.LoadPlugin();
plg.loadAllPlugin();
if (set.scriptEnabled()) {
// At this time, AngelScript service plugin has started

54
src/plugin/iwingdevice.h Normal file
View File

@ -0,0 +1,54 @@
/*==============================================================================
** Copyright (C) 2024-2027 WingSummer
**
** You can redistribute this file and/or modify it under the terms of the
** BSD 3-Clause.
**
** THIS FILE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
** POSSIBILITY OF SUCH DAMAGE.
** =============================================================================
*/
#ifndef IWINGDEVICE_H
#define IWINGDEVICE_H
#include "iwingpluginbase.h"
#include <optional>
namespace WingHex {
class IWingDevice : public IWingPluginBase {
Q_OBJECT
public:
struct DeviceInfo {
QIODevice *dev;
bool needLargeBuffer;
};
virtual QStringList supportedFileIDs() = 0;
public:
virtual QPair<QString, QVariantList> onOpenFileBegin() { return {}; }
virtual std::optional<DeviceInfo>
onOpenFile(const QString &path, const QVariantList &params) = 0;
virtual bool onCloseFile(QIODevice *dev) = 0;
};
} // namespace WingHex
Q_DECLARE_INTERFACE(WingHex::IWingDevice, "com.wingsummer.iwingdevice")
#endif // IWINGDEVICE_H

View File

@ -21,25 +21,20 @@
#ifndef IWINGPLUGIN_H
#define IWINGPLUGIN_H
#include "settingpage.h"
#include "iwingpluginbase.h"
#include <functional>
#include <memory>
#include <QCryptographicHash>
#include <QDockWidget>
#include <QList>
#include <QMap>
#include <QMenu>
#include <QObject>
#include <QToolBar>
#include <QToolButton>
#include <QWidget>
#include <QtCore>
#include <QFileDialog>
#include <QInputDialog>
#include <QMessageBox>
#include <QMetaObject>
/**
@ -49,19 +44,6 @@
namespace WingHex {
using qusizetype = QIntegerForSizeof<std::size_t>::Unsigned;
Q_DECL_UNUSED constexpr auto SDKVERSION = 15;
Q_DECL_UNUSED static QString PLUGINDIR() {
return QCoreApplication::applicationDirPath() + QStringLiteral("/plugin");
}
Q_DECL_UNUSED static QString HOSTRESPIMG(const QString &name) {
return QStringLiteral(":/com.wingsummer.winghex/images/") + name +
QStringLiteral(".png");
}
Q_NAMESPACE
enum ErrFile : int {
Success = 0,
@ -289,108 +271,6 @@ signals:
bool closeAllPluginFiles();
};
class MessageBox : public QObject {
Q_OBJECT
signals:
void aboutQt(QWidget *parent = nullptr, const QString &title = QString());
QMessageBox::StandardButton information(
QWidget *parent, const QString &title, const QString &text,
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
QMessageBox::StandardButton question(
QWidget *parent, const QString &title, const QString &text,
QMessageBox::StandardButtons buttons =
QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No),
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
QMessageBox::StandardButton
warning(QWidget *parent, const QString &title, const QString &text,
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
QMessageBox::StandardButton
critical(QWidget *parent, const QString &title, const QString &text,
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
void about(QWidget *parent, const QString &title, const QString &text);
QMessageBox::StandardButton
msgbox(QWidget *parent, QMessageBox::Icon icon, const QString &title,
const QString &text,
QMessageBox::StandardButtons buttons = QMessageBox::NoButton,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
};
class InputBox : public QObject {
Q_OBJECT
signals:
Q_REQUIRED_RESULT QString
getText(QWidget *parent, const QString &title, const QString &label,
QLineEdit::EchoMode echo = QLineEdit::Normal,
const QString &text = QString(), bool *ok = nullptr,
Qt::InputMethodHints inputMethodHints = Qt::ImhNone);
Q_REQUIRED_RESULT QString getMultiLineText(
QWidget *parent, const QString &title, const QString &label,
const QString &text = QString(), bool *ok = nullptr,
Qt::InputMethodHints inputMethodHints = Qt::ImhNone);
Q_REQUIRED_RESULT QString
getItem(QWidget *parent, const QString &title, const QString &label,
const QStringList &items, int current = 0, bool editable = true,
bool *ok = nullptr,
Qt::InputMethodHints inputMethodHints = Qt::ImhNone);
Q_REQUIRED_RESULT int getInt(QWidget *parent, const QString &title,
const QString &label, int value = 0,
int minValue = -2147483647,
int maxValue = 2147483647, int step = 1,
bool *ok = nullptr);
Q_REQUIRED_RESULT double getDouble(QWidget *parent, const QString &title,
const QString &label, double value = 0,
double minValue = -2147483647,
double maxValue = 2147483647,
int decimals = 1, bool *ok = nullptr,
double step = 1);
};
class FileDialog : public QObject {
Q_OBJECT
signals:
Q_REQUIRED_RESULT QString getExistingDirectory(
QWidget *parent = nullptr, const QString &caption = QString(),
const QString &dir = QString(),
QFileDialog::Options options = QFileDialog::ShowDirsOnly);
Q_REQUIRED_RESULT QString getOpenFileName(
QWidget *parent = nullptr, const QString &caption = QString(),
const QString &dir = QString(), const QString &filter = QString(),
QString *selectedFilter = nullptr,
QFileDialog::Options options = QFileDialog::Options());
Q_REQUIRED_RESULT QStringList getOpenFileNames(
QWidget *parent = nullptr, const QString &caption = QString(),
const QString &dir = QString(), const QString &filter = QString(),
QString *selectedFilter = nullptr,
QFileDialog::Options options = QFileDialog::Options());
Q_REQUIRED_RESULT QString getSaveFileName(
QWidget *parent = nullptr, const QString &caption = QString(),
const QString &dir = QString(), const QString &filter = QString(),
QString *selectedFilter = nullptr,
QFileDialog::Options options = QFileDialog::Options());
};
class ColorDialog : public QObject {
Q_OBJECT
signals:
Q_REQUIRED_RESULT QColor getColor(const QString &caption,
QWidget *parent = nullptr);
};
class DataVisual : public QObject {
Q_OBJECT
public:
@ -430,15 +310,6 @@ signals:
} // namespace WingPlugin
const auto WINGSUMMER = QStringLiteral("wingsummer");
struct WingDockWidgetInfo {
QString widgetName;
QString displayName;
QWidget *widget = nullptr;
Qt::DockWidgetArea area = Qt::DockWidgetArea::NoDockWidgetArea;
};
struct WingRibbonToolBoxInfo {
struct RibbonCatagories {
const QString FILE = QStringLiteral("File");
@ -499,31 +370,17 @@ signals:
void raiseView();
};
struct WingDependency {
QString puid;
uint version;
QByteArray md5; // optional, but recommend
};
struct SenderInfo {
QString plgcls;
QString puid;
QVariant meta;
};
#ifdef WING_SERVICE
#undef WING_SERVICE
#endif
#define WING_SERVICE Q_INVOKABLE
// for bad broken Qt API
#define WINGAPI_ARG(type, data) QArgument<type>(#type, data)
#define WINGAPI_RETURN_ARG(type, data) QReturnArgument<type>(#type, data)
enum class AppTheme { Dark, Light };
class IWingPlugin : public QObject {
class IWingPlugin : public IWingPluginBase {
Q_OBJECT
public:
typedef std::function<QVariant(const QVariantList &)> ScriptFn;
@ -572,25 +429,15 @@ public:
FileSaved = 1u << 4,
FileSwitched = 1u << 5,
FileClosed = 1u << 6,
ScriptPragma = 1u << 7 // TODO
ScriptPragma = 1u << 7
};
Q_DECLARE_FLAGS(RegisteredEvents, RegisteredEvent)
enum class PluginFileEvent { Opened, Saved, Switched, Closed };
public:
virtual int sdkVersion() const = 0;
virtual const QString signature() const = 0;
virtual ~IWingPlugin() = default;
virtual bool init(const std::unique_ptr<QSettings> &set) = 0;
virtual void unload(std::unique_ptr<QSettings> &set) = 0;
virtual const QString pluginName() const = 0;
virtual QIcon pluginIcon() const { return {}; }
virtual const QString pluginAuthor() const = 0;
virtual uint pluginVersion() const = 0;
virtual const QString pluginComment() const = 0;
virtual QList<WingDependency> dependencies() const { return {}; }
virtual RegisteredEvents registeredEvents() const {
@ -598,9 +445,6 @@ public:
}
public:
virtual QList<WingDockWidgetInfo> registeredDockWidgets() const {
return {};
}
virtual QMenu *registeredHexContextMenu() const { return nullptr; }
virtual QList<WingRibbonToolBoxInfo> registeredRibbonTools() const {
return {};
@ -609,7 +453,7 @@ public:
virtual QHash<SettingPage *, bool> registeredSettingPages() const {
return {};
}
virtual QList<PluginPage *> registeredPages() const { return {}; }
virtual QList<QSharedPointer<WingEditorViewWidget::Creator>>
registeredEditorViewWidgets() const {
return {};
@ -658,25 +502,9 @@ public:
return false;
}
virtual void eventScriptPragmaFinished() {}
signals:
// extension and exposed to WingHexAngelScript
void toast(const QPixmap &icon, const QString &message);
void trace(const QString &message);
void debug(const QString &message);
void warn(const QString &message);
void error(const QString &message);
void info(const QString &message);
// theme
WingHex::AppTheme currentAppTheme();
// not available for AngelScript
// only for plugin UI extenstion
QDialog *createDialog(QWidget *content);
bool raiseDockWidget(QWidget *w);
bool invokeService(const QString &puid, const char *method,
Qt::ConnectionType type, QGenericReturnArgument ret,
QGenericArgument val0 = QGenericArgument(nullptr),
@ -739,10 +567,6 @@ public:
public:
WingPlugin::Reader reader;
WingPlugin::Controller controller;
WingPlugin::MessageBox msgbox;
WingPlugin::InputBox inputbox;
WingPlugin::FileDialog filedlg;
WingPlugin::ColorDialog colordlg;
WingPlugin::DataVisual visual;
};

View File

@ -0,0 +1,231 @@
/*==============================================================================
** Copyright (C) 2024-2027 WingSummer
**
** You can redistribute this file and/or modify it under the terms of the
** BSD 3-Clause.
**
** THIS FILE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
** POSSIBILITY OF SUCH DAMAGE.
** =============================================================================
*/
#ifndef IWINGPLUGINBASE_H
#define IWINGPLUGINBASE_H
#include "settingpage.h"
#include <QCoreApplication>
#include <QFileDialog>
#include <QIcon>
#include <QInputDialog>
#include <QMessageBox>
#include <QObject>
#include <QSettings>
namespace WingHex {
using qusizetype = QIntegerForSizeof<std::size_t>::Unsigned;
Q_DECL_UNUSED constexpr auto SDKVERSION = 15;
Q_DECL_UNUSED static QString PLUGINDIR() {
return QCoreApplication::applicationDirPath() + QStringLiteral("/plugin");
}
Q_DECL_UNUSED static QString HOSTRESPIMG(const QString &name) {
return QStringLiteral(":/com.wingsummer.winghex/images/") + name +
QStringLiteral(".png");
}
namespace WingPlugin {
class MessageBox : public QObject {
Q_OBJECT
signals:
void aboutQt(QWidget *parent = nullptr, const QString &title = QString());
QMessageBox::StandardButton information(
QWidget *parent, const QString &title, const QString &text,
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
QMessageBox::StandardButton question(
QWidget *parent, const QString &title, const QString &text,
QMessageBox::StandardButtons buttons =
QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No),
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
QMessageBox::StandardButton
warning(QWidget *parent, const QString &title, const QString &text,
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
QMessageBox::StandardButton
critical(QWidget *parent, const QString &title, const QString &text,
QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
void about(QWidget *parent, const QString &title, const QString &text);
QMessageBox::StandardButton
msgbox(QWidget *parent, QMessageBox::Icon icon, const QString &title,
const QString &text,
QMessageBox::StandardButtons buttons = QMessageBox::NoButton,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
};
class InputBox : public QObject {
Q_OBJECT
signals:
Q_REQUIRED_RESULT QString
getText(QWidget *parent, const QString &title, const QString &label,
QLineEdit::EchoMode echo = QLineEdit::Normal,
const QString &text = QString(), bool *ok = nullptr,
Qt::InputMethodHints inputMethodHints = Qt::ImhNone);
Q_REQUIRED_RESULT QString getMultiLineText(
QWidget *parent, const QString &title, const QString &label,
const QString &text = QString(), bool *ok = nullptr,
Qt::InputMethodHints inputMethodHints = Qt::ImhNone);
Q_REQUIRED_RESULT QString
getItem(QWidget *parent, const QString &title, const QString &label,
const QStringList &items, int current = 0, bool editable = true,
bool *ok = nullptr,
Qt::InputMethodHints inputMethodHints = Qt::ImhNone);
Q_REQUIRED_RESULT int getInt(QWidget *parent, const QString &title,
const QString &label, int value = 0,
int minValue = -2147483647,
int maxValue = 2147483647, int step = 1,
bool *ok = nullptr);
Q_REQUIRED_RESULT double getDouble(QWidget *parent, const QString &title,
const QString &label, double value = 0,
double minValue = -2147483647,
double maxValue = 2147483647,
int decimals = 1, bool *ok = nullptr,
double step = 1);
};
class FileDialog : public QObject {
Q_OBJECT
signals:
Q_REQUIRED_RESULT QString getExistingDirectory(
QWidget *parent = nullptr, const QString &caption = QString(),
const QString &dir = QString(),
QFileDialog::Options options = QFileDialog::ShowDirsOnly);
Q_REQUIRED_RESULT QString getOpenFileName(
QWidget *parent = nullptr, const QString &caption = QString(),
const QString &dir = QString(), const QString &filter = QString(),
QString *selectedFilter = nullptr,
QFileDialog::Options options = QFileDialog::Options());
Q_REQUIRED_RESULT QStringList getOpenFileNames(
QWidget *parent = nullptr, const QString &caption = QString(),
const QString &dir = QString(), const QString &filter = QString(),
QString *selectedFilter = nullptr,
QFileDialog::Options options = QFileDialog::Options());
Q_REQUIRED_RESULT QString getSaveFileName(
QWidget *parent = nullptr, const QString &caption = QString(),
const QString &dir = QString(), const QString &filter = QString(),
QString *selectedFilter = nullptr,
QFileDialog::Options options = QFileDialog::Options());
};
class ColorDialog : public QObject {
Q_OBJECT
signals:
Q_REQUIRED_RESULT QColor getColor(const QString &caption,
QWidget *parent = nullptr);
};
} // namespace WingPlugin
struct WingDependency {
QString puid;
uint version;
QByteArray md5; // optional, but recommend
};
struct WingDockWidgetInfo {
QString widgetName;
QString displayName;
QWidget *widget = nullptr;
Qt::DockWidgetArea area = Qt::DockWidgetArea::NoDockWidgetArea;
};
#ifdef WING_SERVICE
#undef WING_SERVICE
#endif
#define WING_SERVICE Q_INVOKABLE
const auto WINGSUMMER = QStringLiteral("wingsummer");
enum class AppTheme { Dark, Light };
class IWingPluginBase : public QObject {
Q_OBJECT
public:
virtual ~IWingPluginBase() = default;
public:
virtual int sdkVersion() const = 0;
virtual const QString signature() const = 0;
virtual bool init(const std::unique_ptr<QSettings> &set) = 0;
virtual void unload(std::unique_ptr<QSettings> &set) = 0;
virtual const QString pluginName() const = 0;
virtual QIcon pluginIcon() const { return {}; }
virtual const QString pluginAuthor() const = 0;
virtual uint pluginVersion() const = 0;
virtual const QString pluginComment() const = 0;
public:
virtual QList<WingDockWidgetInfo> registeredDockWidgets() const {
return {};
}
virtual QList<PluginPage *> registeredPages() const { return {}; }
signals:
void toast(const QPixmap &icon, const QString &message);
void trace(const QString &message);
void debug(const QString &message);
void warn(const QString &message);
void error(const QString &message);
void info(const QString &message);
bool raiseDockWidget(QWidget *w);
// theme
WingHex::AppTheme currentAppTheme();
// not available for AngelScript
// only for plugin UI extenstion
QDialog *createDialog(QWidget *content);
public:
WingPlugin::MessageBox msgbox;
WingPlugin::InputBox inputbox;
WingPlugin::FileDialog filedlg;
WingPlugin::ColorDialog colordlg;
};
} // namespace WingHex
#endif // IWINGPLUGINBASE_H

File diff suppressed because it is too large Load Diff

View File

@ -31,6 +31,7 @@
#include "class/wingangelapi.h"
#include "control/editorview.h"
#include "plugin/iwingdevice.h"
using namespace WingHex;
@ -97,14 +98,34 @@ public:
void setMainWindow(MainWindow *win);
QWidget *mainWindow() const;
void LoadPlugin();
void UnloadPlugin();
void loadAllPlugin();
void unloadAllPlugin();
const QList<IWingPlugin *> &plugins() const;
const IWingPlugin *plugin(qsizetype index) const;
WingAngelAPI *angelApi() const;
void cleanUpEditorViewHandle(EditorView *view);
bool dispatchEvent(IWingPlugin::RegisteredEvent event,
const QVariantList &params);
private:
void loadExtPlugin();
void loadDevicePlugin();
void checkDirRootSafe(const QDir &dir);
template <typename T>
void loadPlugin(const QFileInfo &filename, const QDir &setdir);
WingAngelAPI *angelApi() const;
bool closeEditor(IWingPlugin *plg, int handle, bool force);
bool checkPluginCanOpenedFile(IWingPlugin *plg);
bool checkPluginHasAlreadyOpened(IWingPlugin *plg, EditorView *view);
EditorView *getCurrentPluginView(IWingPlugin *plg);
@ -113,35 +134,34 @@ public:
SharedUniqueId assginHandleForPluginView(IWingPlugin *plg,
EditorView *view);
bool checkPluginCanOpenedFile(IWingPlugin *plg);
bool checkPluginHasAlreadyOpened(IWingPlugin *plg, EditorView *view);
void cleanUpEditorViewHandle(EditorView *view);
bool closeEditor(IWingPlugin *plg, int handle, bool force);
void dispatchEvent(IWingPlugin::RegisteredEvent event,
const QVariantList &params);
private:
void registerFns(IWingPlugin *plg);
void registerEnums(IWingPlugin *plg);
void registerEvents(IWingPlugin *plg);
QString type2AngelScriptString(IWingPlugin::MetaType type, bool isArg);
static QString type2AngelScriptString(IWingPlugin::MetaType type,
bool isArg);
QString getScriptFnSig(const QString &fnName,
const IWingPlugin::ScriptFnInfo &fninfo);
static QString getScriptFnSig(const QString &fnName,
const IWingPlugin::ScriptFnInfo &fninfo);
QString getPUID(IWingPlugin *p);
static QString getPUID(IWingPlugin *p);
bool isPluginLoaded(const WingDependency &d);
bool checkThreadAff();
static QString packLogMessage(const char *header, const QString &msg);
EditorView *pluginCurrentEditor(IWingPlugin *sender) const;
private:
void loadPlugin(IWingPlugin *p, const QString &fileName,
const std::optional<QDir> &setdir);
void loadPlugin(IWingDevice *p, const QString &fileName,
const std::optional<QDir> &setdir);
private:
void connectInterface(IWingPlugin *plg);
void connectLoadingInterface(IWingPlugin *plg);
void connectBaseInterface(IWingPlugin *plg);
@ -149,11 +169,17 @@ private:
void connectControllerInterface(IWingPlugin *plg);
void connectUIInterface(IWingPlugin *plg);
bool checkThreadAff();
static QString packLogMessage(const char *header, const QString &msg);
private:
void connectInterface(IWingDevice *plg);
void connectLoadingInterface(IWingDevice *plg);
EditorView *pluginCurrentEditor(IWingPlugin *sender) const;
private:
void connectBaseInterface(IWingPluginBase *plg);
void connectUIInterface(IWingPluginBase *plg);
void registerPluginDockWidgets(IWingPluginBase *p);
void registerPluginPages(IWingPluginBase *p);
private:
private:
template <typename T>
T readBasicTypeContent(IWingPlugin *plg, qsizetype offset) {

View File

@ -74,13 +74,17 @@ void GeneralSettingDialog::reload() {
auto &set = SettingManager::instance();
auto langs = LanguageManager::instance().langsDisplay();
ui->cbLanguage->addItems(langs);
auto lang = set.defaultLang();
if (lang.isEmpty()) {
auto &lang = LanguageManager::instance();
auto langs = lang.langs();
for (auto &l : langs) {
ui->cbLanguage->addItem(lang.langDisplay(l), l);
}
auto deflang = set.defaultLang();
if (deflang.isEmpty()) {
ui->cbLanguage->setCurrentIndex(0);
} else {
ui->cbLanguage->setCurrentIndex(langs.indexOf(lang) + 1);
ui->cbLanguage->setCurrentIndex(langs.indexOf(deflang) + 1);
}
ui->sbFontSize->setValue(set.appfontSize());
@ -115,6 +119,7 @@ QString GeneralSettingDialog::id() const { return QStringLiteral("General"); }
void GeneralSettingDialog::apply() {
auto &set = SettingManager::instance();
set.setDefaultLang(ui->cbLanguage->currentData().toString());
set.setAppfontSize(ui->sbFontSize->value());
set.setAppFontFamily(ui->cbFont->currentText());
set.setThemeID(ui->cbTheme->currentIndex());