From f51630c6f01a00431baa06db658fd3b8a1be4441 Mon Sep 17 00:00:00 2001 From: wingsummer <1326224942@qq.com> Date: Thu, 10 Apr 2025 12:51:13 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=A7=BB=E9=99=A4=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=8F=AF=E8=A7=86=E5=8C=96=E5=8A=9F=E8=83=BD=E4=BB=A5=E8=BD=BB?= =?UTF-8?q?=E9=87=8F=E5=8C=96=EF=BC=9B=E4=BC=98=E5=8C=96=20WingAngelAPI=20?= =?UTF-8?q?=E8=84=9A=E6=9C=AC=E6=B3=A8=E5=86=8C=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 3rdparty/QJsonModel/.gitignore | 155 -- 3rdparty/QJsonModel/CMakeLists.txt | 25 - 3rdparty/QJsonModel/LICENSE | 21 - 3rdparty/QJsonModel/QJsonModel.cpp | 518 ------ 3rdparty/QJsonModel/README.md | 56 - 3rdparty/QJsonModel/include/QJsonModel.hpp | 115 -- 3rdparty/QJsonModel/include/details/QUtf8.hpp | 194 --- 3rdparty/QJsonModel/screen.png | Bin 50750 -> 0 bytes CMakeLists.txt | 6 - TestPlugin/CMakeLists.txt | 5 +- TestPlugin/lang/TestPlugin_zh_CN.ts | 31 +- TestPlugin/testform.cpp | 80 - TestPlugin/testform.h | 21 - TestPlugin/testform.ui | 177 +- TestPlugin/testtablemodel.cpp | 55 - TestPlugin/testtablemodel.h | 41 - WingPlugin | 2 +- lang/zh_CN/winghex_zh_CN.ts | 704 ++++---- lang/zh_TW/winghex_zh_TW.ts | 704 ++++---- src/class/clickcallback.h | 84 - src/class/pluginsystem.cpp | 191 +-- src/class/pluginsystem.h | 48 - src/class/wingangelapi.cpp | 1465 ++++++++--------- src/class/wingangelapi.h | 121 +- src/components.md | 1 - src/dialog/mainwindow.cpp | 286 ---- src/dialog/mainwindow.h | 25 - src/model/qjsontablemodel.cpp | 92 -- src/model/qjsontablemodel.h | 51 - 29 files changed, 1379 insertions(+), 3895 deletions(-) delete mode 100644 3rdparty/QJsonModel/.gitignore delete mode 100644 3rdparty/QJsonModel/CMakeLists.txt delete mode 100644 3rdparty/QJsonModel/LICENSE delete mode 100644 3rdparty/QJsonModel/QJsonModel.cpp delete mode 100644 3rdparty/QJsonModel/README.md delete mode 100644 3rdparty/QJsonModel/include/QJsonModel.hpp delete mode 100644 3rdparty/QJsonModel/include/details/QUtf8.hpp delete mode 100644 3rdparty/QJsonModel/screen.png delete mode 100644 TestPlugin/testtablemodel.cpp delete mode 100644 TestPlugin/testtablemodel.h delete mode 100644 src/class/clickcallback.h delete mode 100644 src/model/qjsontablemodel.cpp delete mode 100644 src/model/qjsontablemodel.h diff --git a/3rdparty/QJsonModel/.gitignore b/3rdparty/QJsonModel/.gitignore deleted file mode 100644 index c45a326..0000000 --- a/3rdparty/QJsonModel/.gitignore +++ /dev/null @@ -1,155 +0,0 @@ -# macOS -.DS_Store - -# Windows -Thumbs.db -ehthumbs.db - -# Folder config file commonly created by Windows Explorer -Desktop.ini - -# Recycle Bin used on file shares and remote volumes -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msm -*.msp - -# Windows shortcuts -*.lnk - -# Thumbnail cache files created by Windows -Thumbs.db -Thumbs.db:encryptable - -# Windows Desktop Search -*.pst -*.ost -*.log - -# Compiled Object files, Static and Dynamic libs -*.o -*.lo -*.la -*.a -*.class -*.so -*.lib -*.dll -*.exe - -# Python -__pycache__/ -*.pyc -*.pyo -*.pyd - -# Java -*.class - -# Eclipse -.project -.classpath -.settings/ - -# IntelliJ -.idea/ - -# Visual Studio Code -.vscode/ -.vscodium/ - -# Node.js -node_modules/ - -# Jupyter Notebook -.ipynb_checkpoints/ - -# Thumbnails -Thumbs/ -Thumbs.db - -# macOS metadata -._* - -# TextMate -*.tmproj -*.tmproject -.tmtags - -# Sublime Text -*.sublime-workspace -*.sublime-project - -# VS Code directories -.vscode/ - -# CodeKit -.codekit-config.json - -# Windows Installer files -*.cab -*.msi -*.msm -*.msp - -# Compiled files -*.com -*.class -*.dll -*.exe -*.o -*.so - -# Logs and databases -*.log -*.sql -*.sqlite -*.sqlite3 -*.xml - -# Binary and source packages -*.dmg -*.gz -*.iso -*.jar -*.tar -*.zip -*.rar -*.bin -*.war -*.ear -*.sar -*.bbl -*.pdf -*.xls -*.xlsx -*.ppt -*.pptx - -# Virtual environment -venv/ -env/ - -### Manually Entered -vim-debug/ -**/out/bin -**/out/lib -**/out/share -_deps -.cache/ -compile_commands.json -*.bak -docs/ -*.old - -# clangd cache -.cache/ -.vim/ -build/ -debug/ -realease/ -Release/ -Debug diff --git a/3rdparty/QJsonModel/CMakeLists.txt b/3rdparty/QJsonModel/CMakeLists.txt deleted file mode 100644 index c655342..0000000 --- a/3rdparty/QJsonModel/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -cmake_minimum_required(VERSION 3.26) - -project( - QJsonModel - VERSION 0.0.2 - LANGUAGES C CXX - # Save this for later: HOMEPAGE_URL - DESCRIPTION - "QJsonModel is a json tree model class for Qt6/C++17 based on QAbstractItemModel. MIT License." -) - -find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets) -find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets) - -if(MSVC) - string(APPEND CMAKE_CXX_FLAGS " /utf-8") - string(APPEND CMAKE_C_FLAGS " /utf-8") -endif() - -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) - -add_library(QJsonModel STATIC include/details/QUtf8.hpp include/QJsonModel.hpp - QJsonModel.cpp) - -target_link_libraries(QJsonModel PRIVATE Qt${QT_VERSION_MAJOR}::Widgets) diff --git a/3rdparty/QJsonModel/LICENSE b/3rdparty/QJsonModel/LICENSE deleted file mode 100644 index 97fdfda..0000000 --- a/3rdparty/QJsonModel/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2017 sacha schutz - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/3rdparty/QJsonModel/QJsonModel.cpp b/3rdparty/QJsonModel/QJsonModel.cpp deleted file mode 100644 index b31f20c..0000000 --- a/3rdparty/QJsonModel/QJsonModel.cpp +++ /dev/null @@ -1,518 +0,0 @@ -/* QJsonModel.cpp - * Copyright (c) 2011 SCHUTZ Sacha - * Copyright © 2024 Saul D. Beniquez - * - * License: - * The MIT License (MIT) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -// NOLINTBEGIN - -#include "QJsonModel.hpp" -#include -#include -#include - -inline bool contains(const QStringList &list, const QString &value) { - for (auto val : list) - if (value.contains(val, Qt::CaseInsensitive)) - return true; - - return false; -} - -QJsonTreeItem::QJsonTreeItem(QJsonTreeItem *parent) { mParent = parent; } - -QJsonTreeItem::~QJsonTreeItem() { qDeleteAll(mChilds); } - -void QJsonTreeItem::appendChild(QJsonTreeItem *item) { mChilds.append(item); } - -QJsonTreeItem *QJsonTreeItem::child(int row) { return mChilds.value(row); } - -QJsonTreeItem *QJsonTreeItem::parent() { return mParent; } - -int QJsonTreeItem::childCount() const { return mChilds.count(); } - -int QJsonTreeItem::row() const { - if (mParent) - return mParent->mChilds.indexOf(const_cast(this)); - - return 0; -} - -void QJsonTreeItem::setKey(const QString &key) { mKey = key; } - -void QJsonTreeItem::setValue(const QVariant &value) { mValue = value; } - -void QJsonTreeItem::setType(const QJsonValue::Type &type) { mType = type; } - -QString QJsonTreeItem::key() const { return mKey; } - -QVariant QJsonTreeItem::value() const { return mValue; } - -QJsonValue::Type QJsonTreeItem::type() const { return mType; } - -QJsonTreeItem *QJsonTreeItem::load(const QJsonValue &value, - const QStringList &exceptions, - QJsonTreeItem *parent) { - QJsonTreeItem *rootItem = new QJsonTreeItem(parent); - rootItem->setKey("root"); - - if (value.isObject()) { - // Get all QJsonValue childs - const QStringList keys = - value.toObject().keys(); // To prevent clazy-range warning - for (const QString &key : keys) { - if (contains(exceptions, key)) { - continue; - } - QJsonValue v = value.toObject().value(key); - QJsonTreeItem *child = load(v, exceptions, rootItem); - child->setKey(key); - child->setType(v.type()); - rootItem->appendChild(child); - } - } else if (value.isArray()) { - // Get all QJsonValue childs - int index = 0; - const QJsonArray array = - value.toArray(); // To prevent clazy-range warning - for (const QJsonValue &v : array) { - QJsonTreeItem *child = load(v, exceptions, rootItem); - child->setKey(QString::number(index)); - child->setType(v.type()); - rootItem->appendChild(child); - ++index; - } - } else { - rootItem->setValue(value.toVariant()); - rootItem->setType(value.type()); - } - - return rootItem; -} - -//========================================================================= - -inline uchar hexdig(uint u) { return (u < 0xa ? '0' + u : 'a' + u - 0xa); } - -QByteArray escapedString(const QString &s) { - QByteArray ba(s.length(), Qt::Uninitialized); - uchar *cursor = - reinterpret_cast(const_cast(ba.constData())); - const uchar *ba_end = cursor + ba.length(); - const ushort *src = reinterpret_cast(s.constBegin()); - const ushort *const end = reinterpret_cast(s.constEnd()); - while (src != end) { - if (cursor >= ba_end - 6) { - // ensure we have enough space - int pos = cursor - reinterpret_cast(ba.constData()); - ba.resize(ba.size() * 2); - cursor = reinterpret_cast(ba.data()) + pos; - ba_end = - reinterpret_cast(ba.constData()) + ba.length(); - } - uint u = *src++; - if (u < 0x80) { - if (u < 0x20 || u == 0x22 || u == 0x5c) { - *cursor++ = '\\'; - switch (u) { - case 0x22: - *cursor++ = '"'; - break; - case 0x5c: - *cursor++ = '\\'; - break; - case 0x8: - *cursor++ = 'b'; - break; - case 0xc: - *cursor++ = 'f'; - break; - case 0xa: - *cursor++ = 'n'; - break; - case 0xd: - *cursor++ = 'r'; - break; - case 0x9: - *cursor++ = 't'; - break; - default: - *cursor++ = 'u'; - *cursor++ = '0'; - *cursor++ = '0'; - *cursor++ = hexdig(u >> 4); - *cursor++ = hexdig(u & 0xf); - } - } else { - *cursor++ = (uchar)u; - } - } else if (QUtf8Functions::toUtf8(u, cursor, src, - end) < 0) { - // failed to get valid utf8 use JSON escape sequence - *cursor++ = '\\'; - *cursor++ = 'u'; - *cursor++ = hexdig(u >> 12 & 0x0f); - *cursor++ = hexdig(u >> 8 & 0x0f); - *cursor++ = hexdig(u >> 4 & 0x0f); - *cursor++ = hexdig(u & 0x0f); - } - } - ba.resize(cursor - reinterpret_cast(ba.constData())); - return ba; -} - -QJsonModel::QJsonModel(QObject *parent) - : QAbstractItemModel(parent), mRootItem{new QJsonTreeItem} { - mHeaders.append(tr("key")); - mHeaders.append(tr("value")); -} - -QJsonModel::QJsonModel(const QString &fileName, QObject *parent) - : QAbstractItemModel(parent), mRootItem{new QJsonTreeItem} { - mHeaders.append(tr("key")); - mHeaders.append(tr("value")); - load(fileName); -} - -QJsonModel::QJsonModel(QIODevice *device, QObject *parent) - : QAbstractItemModel(parent), mRootItem{new QJsonTreeItem} { - mHeaders.append(tr("key")); - mHeaders.append(tr("value")); - load(device); -} - -QJsonModel::QJsonModel(const QByteArray &json, QObject *parent) - : QAbstractItemModel(parent), mRootItem{new QJsonTreeItem} { - mHeaders.append(tr("key")); - mHeaders.append(tr("value")); - loadJson(json); -} - -QJsonModel::~QJsonModel() { delete mRootItem; } - -bool QJsonModel::load(const QString &fileName) { - QFile file(fileName); - bool success = false; - if (file.open(QIODevice::ReadOnly)) { - success = load(&file); - file.close(); - } else { - success = false; - } - - return success; -} - -bool QJsonModel::load(QIODevice *device) { return loadJson(device->readAll()); } - -bool QJsonModel::loadJson(const QByteArray &json) { - QJsonParseError error; - auto const &jdoc = QJsonDocument::fromJson(json, &error); - - if (error.error != QJsonParseError::NoError) { - return false; - } - - if (!jdoc.isNull()) { - beginResetModel(); - delete mRootItem; - if (jdoc.isArray()) { - mRootItem = - QJsonTreeItem::load(QJsonValue(jdoc.array()), mExceptions); - mRootItem->setType(QJsonValue::Array); - - } else { - mRootItem = - QJsonTreeItem::load(QJsonValue(jdoc.object()), mExceptions); - mRootItem->setType(QJsonValue::Object); - } - endResetModel(); - return true; - } - - qDebug() << Q_FUNC_INFO << "cannot load json"; - return false; -} - -QVariant QJsonModel::data(const QModelIndex &index, int role) const { - if (!index.isValid()) - return {}; - - QJsonTreeItem *item = static_cast(index.internalPointer()); - - if (role == Qt::DisplayRole) { - if (index.column() == 0) - return QString("%1").arg(item->key()); - - if (index.column() == 1) - return item->value(); - } else if (Qt::EditRole == role) { - if (index.column() == 1) - return item->value(); - } - - return {}; -} - -bool QJsonModel::setData(const QModelIndex &index, const QVariant &value, - int role) { - int col = index.column(); - if (Qt::EditRole == role) { - if (col == 1) { - QJsonTreeItem *item = - static_cast(index.internalPointer()); - item->setValue(value); - emit dataChanged(index, index, {Qt::EditRole}); - return true; - } - } - - return false; -} - -QVariant QJsonModel::headerData(int section, Qt::Orientation orientation, - int role) const { - if (role != Qt::DisplayRole) - return {}; - - if (orientation == Qt::Horizontal) - return mHeaders.value(section); - else - return {}; -} - -QModelIndex QJsonModel::index(int row, int column, - const QModelIndex &parent) const { - if (!hasIndex(row, column, parent)) - return {}; - - QJsonTreeItem *parentItem; - - if (!parent.isValid()) - parentItem = mRootItem; - else - parentItem = static_cast(parent.internalPointer()); - - QJsonTreeItem *childItem = parentItem->child(row); - if (childItem) - return createIndex(row, column, childItem); - else - return {}; -} - -QModelIndex QJsonModel::parent(const QModelIndex &index) const { - if (!index.isValid()) - return {}; - - QJsonTreeItem *childItem = - static_cast(index.internalPointer()); - QJsonTreeItem *parentItem = childItem->parent(); - - if (parentItem == mRootItem) - return QModelIndex(); - - return createIndex(parentItem->row(), 0, parentItem); -} - -int QJsonModel::rowCount(const QModelIndex &parent) const { - QJsonTreeItem *parentItem; - if (parent.column() > 0) - return 0; - - if (!parent.isValid()) - parentItem = mRootItem; - else - parentItem = static_cast(parent.internalPointer()); - - return parentItem->childCount(); -} - -int QJsonModel::columnCount(const QModelIndex &parent) const { - Q_UNUSED(parent) - return 2; -} - -Qt::ItemFlags QJsonModel::flags(const QModelIndex &index) const { - int col = index.column(); - auto item = static_cast(index.internalPointer()); - - auto isArray = QJsonValue::Array == item->type(); - auto isObject = QJsonValue::Object == item->type(); - - if ((col == 1) && !(isArray || isObject)) - return Qt::ItemIsEditable | QAbstractItemModel::flags(index); - else - return QAbstractItemModel::flags(index); -} - -QByteArray QJsonModel::json(bool compact) { - auto jsonValue = genJson(mRootItem); - QByteArray json; - if (jsonValue.isNull()) - return json; - - if (jsonValue.isArray()) - arrayToJson(jsonValue.toArray(), json, 0, compact); - else - objectToJson(jsonValue.toObject(), json, 0, compact); - - return json; -} - -void QJsonModel::objectToJson(QJsonObject jsonObject, QByteArray &json, - int indent, bool compact) { - json += compact ? "{" : "{\n"; - objectContentToJson(jsonObject, json, indent + (compact ? 0 : 1), compact); - json += QByteArray(4 * indent, ' '); - json += compact ? "}" : "}\n"; -} -void QJsonModel::arrayToJson(QJsonArray jsonArray, QByteArray &json, int indent, - bool compact) { - json += compact ? "[" : "[\n"; - arrayContentToJson(jsonArray, json, indent + (compact ? 0 : 1), compact); - json += QByteArray(4 * indent, ' '); - json += compact ? "]" : "]\n"; -} - -void QJsonModel::arrayContentToJson(QJsonArray jsonArray, QByteArray &json, - int indent, bool compact) { - if (jsonArray.size() <= 0) - return; - - QByteArray indentString(4 * indent, ' '); - int i = 0; - while (1) { - json += indentString; - valueToJson(jsonArray.at(i), json, indent, compact); - if (++i == jsonArray.size()) { - if (!compact) - json += '\n'; - break; - } - json += compact ? "," : ",\n"; - } -} -void QJsonModel::objectContentToJson(QJsonObject jsonObject, QByteArray &json, - int indent, bool compact) { - if (jsonObject.size() <= 0) - return; - - QByteArray indentString(4 * indent, ' '); - int i = 0; - while (1) { - QString key = jsonObject.keys().at(i); - json += indentString; - json += '"'; - json += escapedString(key); - json += compact ? "\":" : "\": "; - valueToJson(jsonObject.value(key), json, indent, compact); - if (++i == jsonObject.size()) { - if (!compact) - json += '\n'; - break; - } - json += compact ? "," : ",\n"; - } -} - -void QJsonModel::valueToJson(QJsonValue jsonValue, QByteArray &json, int indent, - bool compact) { - QJsonValue::Type type = jsonValue.type(); - switch (type) { - case QJsonValue::Bool: - json += jsonValue.toBool() ? "true" : "false"; - break; - case QJsonValue::Double: { - const double d = jsonValue.toDouble(); - if (qIsFinite(d)) { - json += QByteArray::number(d, 'f', QLocale::FloatingPointShortest); - } else { - json += "null"; // +INF || -INF || NaN (see RFC4627#section2.4) - } - break; - } - case QJsonValue::String: - json += '"'; - json += escapedString(jsonValue.toString()); - json += '"'; - break; - case QJsonValue::Array: - json += compact ? "[" : "[\n"; - arrayContentToJson(jsonValue.toArray(), json, - indent + (compact ? 0 : 1), compact); - json += QByteArray(4 * indent, ' '); - json += ']'; - break; - case QJsonValue::Object: - json += compact ? "{" : "{\n"; - objectContentToJson(jsonValue.toObject(), json, - indent + (compact ? 0 : 1), compact); - json += QByteArray(4 * indent, ' '); - json += '}'; - break; - case QJsonValue::Null: - default: - json += "null"; - } -} - -void QJsonModel::addException(const QStringList &exceptions) { - mExceptions = exceptions; -} - -QJsonValue QJsonModel::genJson(QJsonTreeItem *item) const { - auto type = item->type(); - int nchild = item->childCount(); - - if (QJsonValue::Object == type) { - QJsonObject jo; - for (int i = 0; i < nchild; ++i) { - auto ch = item->child(i); - auto key = ch->key(); - jo.insert(key, genJson(ch)); - } - return jo; - } else if (QJsonValue::Array == type) { - QJsonArray arr; - for (int i = 0; i < nchild; ++i) { - auto ch = item->child(i); - arr.append(genJson(ch)); - } - return arr; - } else { - QJsonValue va; -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - switch (item->value().typeId()) { -#else - switch (item->value().userType()) { -#endif - case QMetaType::Bool: { - va = item->value().toBool(); - break; - } - default: - va = item->value().toString(); - break; - } - return va; - } -} diff --git a/3rdparty/QJsonModel/README.md b/3rdparty/QJsonModel/README.md deleted file mode 100644 index 2364fa5..0000000 --- a/3rdparty/QJsonModel/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# QJsonModel -QJsonModel is a JSON tree model class for Qt6/C++17 based on QAbstractItemModel. - -QJsonModel was originally written by Sacha Shutz (https://github.com/dridk). - -This fork is also released under the MIT License. - - -![QJsonModel](https://gitea.beniquez.me/sdaveb/QJsonModel/raw/branch/master/screen.png) - -## Build Instructions - -### Build Tools -- CMake (version 3.21 or higher) -- C++17-compatible compiler - -### Building the Project -1. Clone the repository: - ``` - git clone - ``` - -2. Navigate to the project directory: - ``` - cd elemental-game - ``` -3. Configure your build system: - ```bash - cmake -B debug -G Unix Makefiles - # or - cmake -B debug -G Ninja # this is faster and more modern - ``` -4. Invoke your build system - ``` - cmake --build debug - ``` -### Usage - CMake - -You can add this library to your CMake projects using FetchContent() -or CPM_AddPackage(). - -Here's how to do it with CPM_AddPackage: - -``` -COMING SOON -``` - -### Usage - C++ - -#### -```cpp -QJsonModel * model = new QJsonModel; -QTreeView * view = new QTreeView; -view->setModel(model); -model->load("example.json") -``` diff --git a/3rdparty/QJsonModel/include/QJsonModel.hpp b/3rdparty/QJsonModel/include/QJsonModel.hpp deleted file mode 100644 index 6ab4605..0000000 --- a/3rdparty/QJsonModel/include/QJsonModel.hpp +++ /dev/null @@ -1,115 +0,0 @@ -/* QJsonModel.hpp - * Copyright (c) 2011 SCHUTZ Sacha - * Copyright © 2024 Saul D. Beniquez - * - * License: - * The MIT License (MIT) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#pragma once - -#include -#include -#include -#include -#include - -#include "details/QUtf8.hpp" - -class QJsonModel; -class QJsonItem; - -class QJsonTreeItem { -public: - QJsonTreeItem(QJsonTreeItem *parent = nullptr); - ~QJsonTreeItem(); - void appendChild(QJsonTreeItem *item); - QJsonTreeItem *child(int row); - QJsonTreeItem *parent(); - int childCount() const; - int row() const; - void setKey(const QString &key); - void setValue(const QVariant &value); - void setType(const QJsonValue::Type &type); - QString key() const; - QVariant value() const; - QJsonValue::Type type() const; - - static QJsonTreeItem *load(const QJsonValue &value, - const QStringList &exceptions = {}, - QJsonTreeItem *parent = nullptr); - -protected: -private: - QString mKey; - QVariant mValue; - QJsonValue::Type mType; - QList mChilds; - QJsonTreeItem *mParent = nullptr; -}; - -//--------------------------------------------------- - -class QJsonModel : public QAbstractItemModel { - Q_OBJECT -public: - explicit QJsonModel(QObject *parent = nullptr); - QJsonModel(const QString &fileName, QObject *parent = nullptr); - QJsonModel(QIODevice *device, QObject *parent = nullptr); - QJsonModel(const QByteArray &json, QObject *parent = nullptr); - ~QJsonModel(); - bool load(const QString &fileName); - bool load(QIODevice *device); - bool loadJson(const QByteArray &json); - QVariant data(const QModelIndex &index, int role) const override; - bool setData(const QModelIndex &index, const QVariant &value, - int role = Qt::EditRole) override; - QVariant headerData(int section, Qt::Orientation orientation, - int role) const override; - QModelIndex index(int row, int column, - const QModelIndex &parent = QModelIndex()) const override; - QModelIndex parent(const QModelIndex &index) const override; - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - int columnCount(const QModelIndex &parent = QModelIndex()) const override; - Qt::ItemFlags flags(const QModelIndex &index) const override; - QByteArray json(bool compact = false); - QByteArray jsonToByte(QJsonValue jsonValue); - void objectToJson(QJsonObject jsonObject, QByteArray &json, int indent, - bool compact); - void arrayToJson(QJsonArray jsonArray, QByteArray &json, int indent, - bool compact); - void arrayContentToJson(QJsonArray jsonArray, QByteArray &json, int indent, - bool compact); - void objectContentToJson(QJsonObject jsonObject, QByteArray &json, - int indent, bool compact); - void valueToJson(QJsonValue jsonValue, QByteArray &json, int indent, - bool compact); - //! List of tags to skip during JSON parsing - void addException(const QStringList &exceptions); - -private: - QJsonValue genJson(QJsonTreeItem *) const; - QJsonTreeItem *mRootItem = nullptr; - QStringList mHeaders; - //! List of exceptions (e.g. comments). Case insensitive, compairs on - //! "contains". - QStringList mExceptions; -}; diff --git a/3rdparty/QJsonModel/include/details/QUtf8.hpp b/3rdparty/QJsonModel/include/details/QUtf8.hpp deleted file mode 100644 index a57ae72..0000000 --- a/3rdparty/QJsonModel/include/details/QUtf8.hpp +++ /dev/null @@ -1,194 +0,0 @@ -/* QUtf8.hpp - * Copyright © 2024 Saul D. Beniquez - * License: - * The MIT License (MIT) - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include - -namespace QUtf8Functions { -/// returns 0 on success; errors can only happen if \a u is a surrogate: -/// Error if \a u is a low surrogate; -/// if \a u is a high surrogate, Error if the next isn't a low one, -/// EndOfString if we run into the end of the string. -template -inline int toUtf8(ushort u, OutputPtr &dst, InputPtr &src, InputPtr end) { - if (!Traits::skipAsciiHandling && u < 0x80) { - // U+0000 to U+007F (US-ASCII) - one byte - Traits::appendByte(dst, uchar(u)); - return 0; - } else if (u < 0x0800) { - // U+0080 to U+07FF - two bytes - // first of two bytes - Traits::appendByte(dst, 0xc0 | uchar(u >> 6)); - } else { - if (!QChar::isSurrogate(u)) { - // U+0800 to U+FFFF (except U+D800-U+DFFF) - three bytes - if (!Traits::allowNonCharacters && QChar::isNonCharacter(u)) - return Traits::Error; - // first of three bytes - Traits::appendByte(dst, 0xe0 | uchar(u >> 12)); - } else { - // U+10000 to U+10FFFF - four bytes - // need to get one extra codepoint - if (Traits::availableUtf16(src, end) == 0) - return Traits::EndOfString; - ushort low = Traits::peekUtf16(src); - if (!QChar::isHighSurrogate(u)) - return Traits::Error; - if (!QChar::isLowSurrogate(low)) - return Traits::Error; - Traits::advanceUtf16(src); - uint ucs4 = QChar::surrogateToUcs4(u, low); - if (!Traits::allowNonCharacters && QChar::isNonCharacter(ucs4)) - return Traits::Error; - // first byte - Traits::appendByte(dst, 0xf0 | (uchar(ucs4 >> 18) & 0xf)); - // second of four bytes - Traits::appendByte(dst, 0x80 | (uchar(ucs4 >> 12) & 0x3f)); - // for the rest of the bytes - u = ushort(ucs4); - } - // second to last byte - Traits::appendByte(dst, 0x80 | (uchar(u >> 6) & 0x3f)); - } - // last byte - Traits::appendByte(dst, 0x80 | (u & 0x3f)); - return 0; -} -inline bool isContinuationByte(uchar b) { return (b & 0xc0) == 0x80; } -/// returns the number of characters consumed (including \a b) in case of -/// success; returns negative in case of error: Traits::Error or -/// Traits::EndOfString -template -inline int fromUtf8(uchar b, OutputPtr &dst, InputPtr &src, InputPtr end) { - int charsNeeded; - uint min_uc; - uint uc; - if (!Traits::skipAsciiHandling && b < 0x80) { - // US-ASCII - Traits::appendUtf16(dst, b); - return 1; - } - if (!Traits::isTrusted && Q_UNLIKELY(b <= 0xC1)) { - // an UTF-8 first character must be at least 0xC0 - // however, all 0xC0 and 0xC1 first bytes can only produce overlong - // sequences - return Traits::Error; - } else if (b < 0xe0) { - charsNeeded = 2; - min_uc = 0x80; - uc = b & 0x1f; - } else if (b < 0xf0) { - charsNeeded = 3; - min_uc = 0x800; - uc = b & 0x0f; - } else if (b < 0xf5) { - charsNeeded = 4; - min_uc = 0x10000; - uc = b & 0x07; - } else { - // the last Unicode character is U+10FFFF - // it's encoded in UTF-8 as "\xF4\x8F\xBF\xBF" - // therefore, a byte higher than 0xF4 is not the UTF-8 first byte - return Traits::Error; - } - int bytesAvailable = Traits::availableBytes(src, end); - if (Q_UNLIKELY(bytesAvailable < charsNeeded - 1)) { - // it's possible that we have an error instead of just unfinished bytes - if (bytesAvailable > 0 && !isContinuationByte(Traits::peekByte(src, 0))) - return Traits::Error; - if (bytesAvailable > 1 && !isContinuationByte(Traits::peekByte(src, 1))) - return Traits::Error; - return Traits::EndOfString; - } - // first continuation character - b = Traits::peekByte(src, 0); - if (!isContinuationByte(b)) - return Traits::Error; - uc <<= 6; - uc |= b & 0x3f; - if (charsNeeded > 2) { - // second continuation character - b = Traits::peekByte(src, 1); - if (!isContinuationByte(b)) - return Traits::Error; - uc <<= 6; - uc |= b & 0x3f; - if (charsNeeded > 3) { - // third continuation character - b = Traits::peekByte(src, 2); - if (!isContinuationByte(b)) - return Traits::Error; - uc <<= 6; - uc |= b & 0x3f; - } - } - // we've decoded something; safety-check it - if (!Traits::isTrusted) { - if (uc < min_uc) - return Traits::Error; - if (QChar::isSurrogate(uc) || uc > QChar::LastValidCodePoint) - return Traits::Error; - if (!Traits::allowNonCharacters && QChar::isNonCharacter(uc)) - return Traits::Error; - } - // write the UTF-16 sequence - if (!QChar::requiresSurrogates(uc)) { - // UTF-8 decoded and no surrogates are required - // detach if necessary - Traits::appendUtf16(dst, ushort(uc)); - } else { - // UTF-8 decoded to something that requires a surrogate pair - Traits::appendUcs4(dst, uc); - } - Traits::advanceByte(src, charsNeeded - 1); - return charsNeeded; -} -} // namespace QUtf8Functions - -struct QUtf8BaseTraits { - static const bool isTrusted = false; - static const bool allowNonCharacters = true; - static const bool skipAsciiHandling = false; - static const int Error = -1; - static const int EndOfString = -2; - static bool isValidCharacter(uint u) { return int(u) >= 0; } - static void appendByte(uchar *&ptr, uchar b) { *ptr++ = b; } - static uchar peekByte(const uchar *ptr, int n = 0) { return ptr[n]; } - static qptrdiff availableBytes(const uchar *ptr, const uchar *end) { - return end - ptr; - } - static void advanceByte(const uchar *&ptr, int n = 1) { ptr += n; } - static void appendUtf16(ushort *&ptr, ushort uc) { *ptr++ = uc; } - static void appendUcs4(ushort *&ptr, uint uc) { - appendUtf16(ptr, QChar::highSurrogate(uc)); - appendUtf16(ptr, QChar::lowSurrogate(uc)); - } - static ushort peekUtf16(const ushort *ptr, int n = 0) { return ptr[n]; } - static qptrdiff availableUtf16(const ushort *ptr, const ushort *end) { - return end - ptr; - } - static void advanceUtf16(const ushort *&ptr, int n = 1) { ptr += n; } - // it's possible to output to UCS-4 too - static void appendUtf16(uint *&ptr, ushort uc) { *ptr++ = uc; } - static void appendUcs4(uint *&ptr, uint uc) { *ptr++ = uc; } -}; diff --git a/3rdparty/QJsonModel/screen.png b/3rdparty/QJsonModel/screen.png deleted file mode 100644 index 6d904d39645356c505f025ca2555f725eb7142cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50750 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

x^ZzfvTo8cpWL}-$a6b#xf}}=`#V49-1QRg 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控制器 - + Others 其他 - + Other APIs should be Test With Script 其他 API 应该用脚本测试,不提供可视化方式 @@ -231,7 +231,6 @@ - Type 类型 @@ -266,32 +265,6 @@ Color 颜色 - - - DataVisual - 数据可视化 - - - - - UpdateTextTreeError - 更新文本树失败 - - - - UpdateTextListByModelError - 通过模型更新文本列表失败 - - - - UpdateTextTableByModelError - 通过模型更新文本表格失败 - - - - UpdateTextTreeByModelError - 通过模型更新文本树失败 - TestPlugin diff --git a/TestPlugin/testform.cpp b/TestPlugin/testform.cpp index 0716ee8..267ea27 100644 --- a/TestPlugin/testform.cpp +++ b/TestPlugin/testform.cpp @@ -24,7 +24,6 @@ #include "ctltestform.h" #include "readertestform.h" -#include "testtablemodel.h" #include #include @@ -37,8 +36,6 @@ TestForm::TestForm(WingHex::IWingPlugin *plg, QWidget *parent) : WingHex::WingPluginWidget(plg, parent), ui(new Ui::TestForm) { ui->setupUi(this); - ui->teDataVisual->setAcceptRichText(false); - ui->saReader->widget()->layout()->addWidget( new ReaderTestForm(plg, ui->tbReaderLogger, this)); ui->saCtl->widget()->layout()->addWidget( @@ -56,10 +53,6 @@ TestForm::TestForm(WingHex::IWingPlugin *plg, QWidget *parent) ui->lblauthor->setPixmap( WingHex::HOSTRESPIMG(QStringLiteral("author"), QStringLiteral(".jpg"))); - - _click = std::bind(&TestForm::onDVClicked, this, std::placeholders::_1); - _dblclick = - std::bind(&TestForm::onDVDoubleClicked, this, std::placeholders::_1); } TestForm::~TestForm() { delete ui; } @@ -153,16 +146,6 @@ QFileDialog::Options TestForm::getFileDialogOptions() const { return options; } -void TestForm::onDVClicked(const QModelIndex &index) { - logWarn(QStringLiteral("[Test - Click] ") + - index.model()->data(index).toString()); -} - -void TestForm::onDVDoubleClicked(const QModelIndex &index) { - msgWarning(this, QStringLiteral("Test - DoubleClick"), - index.model()->data(index).toString()); -} - void TestForm::on_btnSendLog_clicked() { auto txt = ui->leLogText->text(); switch (Level(ui->cbLogLevel->currentIndex())) { @@ -323,69 +306,6 @@ void TestForm::on_btnGetColor_clicked() { } } -void TestForm::on_btnText_2_clicked() { - dataVisualText(ui->teDataVisual->toPlainText(), QStringLiteral("TestForm")); -} - -void TestForm::on_btnTextList_clicked() { - auto txts = ui->teDataVisual->toPlainText().split('\n'); - dataVisualTextList(txts, QStringLiteral("TestForm"), _click, _dblclick); -} - -void TestForm::on_btnTextTree_clicked() { - auto ret = - dataVisualTextTree(ui->teDataVisual->toPlainText(), - QStringLiteral("TestForm"), _click, _dblclick); - if (!ret) { - msgCritical(this, QStringLiteral("Test"), tr("UpdateTextTreeError")); - } -} - -void TestForm::on_btnTextTable_clicked() { - auto ret = dataVisualTextTable( - ui->teDataVisual->toPlainText(), {"wingsummer", "wingsummer"}, {}, - QStringLiteral("TestForm"), _click, _dblclick); - if (!ret) { - msgCritical(this, QStringLiteral("Test"), tr("UpdateTextTreeError")); - } -} - -void TestForm::on_btnTextListByModel_clicked() { - auto model = new QStringListModel; - QStringList buffer; - for (int i = 0; i < WingHex::SDKVERSION; ++i) { - buffer.append("wingsummer" % QString::number(i)); - } - model->setStringList(buffer); - auto ret = dataVisualTextListByModel(model, QStringLiteral("TestForm"), - _click, _dblclick); - if (!ret) { - msgCritical(this, QStringLiteral("Test"), - tr("UpdateTextListByModelError")); - } -} - -void TestForm::on_btnTextTableByModel_clicked() { - auto model = new TestTableModel; - auto ret = dataVisualTextTableByModel(model, QStringLiteral("TestForm"), - _click, _dblclick); - if (!ret) { - msgCritical(this, QStringLiteral("Test"), - tr("UpdateTextTableByModelError")); - } -} - -void TestForm::on_btnTextTreeByModel_clicked() { - auto model = new QFileSystemModel; - model->setRootPath(QDir::currentPath()); - auto ret = dataVisualTextTreeByModel(model, QStringLiteral("TestForm"), - _click, _dblclick); - if (!ret) { - msgCritical(this, QStringLiteral("Test"), - tr("UpdateTextTreeByModelError")); - } -} - void TestForm::on_btnStatusVisible_clicked() { if (ui->rbLockedFile->isChecked()) { Q_UNUSED(setLockedFile(true)); diff --git a/TestPlugin/testform.h b/TestPlugin/testform.h index 27d964c..429703e 100644 --- a/TestPlugin/testform.h +++ b/TestPlugin/testform.h @@ -85,20 +85,6 @@ private slots: void on_btnGetColor_clicked(); - void on_btnText_2_clicked(); - - void on_btnTextList_clicked(); - - void on_btnTextTree_clicked(); - - void on_btnTextTable_clicked(); - - void on_btnTextListByModel_clicked(); - - void on_btnTextTableByModel_clicked(); - - void on_btnTextTreeByModel_clicked(); - void on_btnStatusVisible_clicked(); void on_btnStatusInvisible_clicked(); @@ -121,15 +107,8 @@ private: QFileDialog::Options getFileDialogOptions() const; - void onDVClicked(const QModelIndex &index); - - void onDVDoubleClicked(const QModelIndex &index); - private: Ui::TestForm *ui; - - WingHex::ClickedCallBack _click; - WingHex::ClickedCallBack _dblclick; }; #endif // TESTFORM_H diff --git a/TestPlugin/testform.ui b/TestPlugin/testform.ui index 8dfd319..5a8b0c3 100644 --- a/TestPlugin/testform.ui +++ b/TestPlugin/testform.ui @@ -1050,135 +1050,6 @@ - - - DataVisual - - - - - - - - - - 0 - 150 - - - - Type - - - - QLayout::SizeConstraint::SetMinAndMaxSize - - - - - - 0 - 0 - - - - updateTextList (LineByLine) - - - - - - - - 0 - 0 - - - - updateTextTree (Json) - - - - - - - - 0 - 0 - - - - updateTextTable (Json) - - - - - - - - 0 - 0 - - - - updateTextListByModel - - - - - - - - 0 - 0 - - - - updateText - - - - - - - - 0 - 0 - - - - updateTextTableByModel - - - - - - - - 0 - 0 - - - - updateTextTreeByModel - - - - - - - WingSummer - - - Qt::AlignmentFlag::AlignCenter - - - - - - - - Others @@ -1278,18 +1149,18 @@ - btnClearCtl + btnClearFile clicked() - tbCtlLogger + tbFileLogger clear() - 271 - 387 + 239 + 388 - 318 - 264 + 290 + 328 @@ -1310,34 +1181,34 @@ - btnClearInput + btnClearCtl clicked() - tbInputLogger + tbCtlLogger clear() - 210 - 388 + 271 + 387 - 236 - 332 + 318 + 264 - btnClearFile + btnClearText clicked() - tbFileLogger + leToastText clear() - 239 - 388 + 569 + 271 - 290 - 328 + 468 + 229 @@ -1358,18 +1229,18 @@ - btnClearText + btnClearInput clicked() - leToastText + tbInputLogger clear() - 569 - 271 + 210 + 388 - 468 - 229 + 236 + 332 diff --git a/TestPlugin/testtablemodel.cpp b/TestPlugin/testtablemodel.cpp deleted file mode 100644 index da3e3fe..0000000 --- a/TestPlugin/testtablemodel.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/*============================================================================== -** Copyright (C) 2024-2027 WingSummer -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** ============================================================================= -*/ - -#include "testtablemodel.h" -#include "WingPlugin/iwingpluginbase.h" - -TestTableModel::TestTableModel(QObject *parent) : QAbstractTableModel(parent) {} - -int TestTableModel::rowCount(const QModelIndex &parent) const { - Q_UNUSED(parent); - return WingHex::SDKVERSION; -} - -int TestTableModel::columnCount(const QModelIndex &parent) const { - Q_UNUSED(parent); - return 5; -} - -QVariant TestTableModel::data(const QModelIndex &index, int role) const { - switch (role) { - case Qt::DisplayRole: - case Qt::ToolTipRole: { - return QStringLiteral("(%1, %2)").arg(index.row()).arg(index.column()); - } - case Qt::TextAlignmentRole: - return Qt::AlignCenter; - } - return QVariant(); -} - -QVariant TestTableModel::headerData(int section, Qt::Orientation orientation, - int role) const { - Q_UNUSED(orientation); - if (role == Qt::DisplayRole) { - return section + 1; - } - return QVariant(); -} diff --git a/TestPlugin/testtablemodel.h b/TestPlugin/testtablemodel.h deleted file mode 100644 index e438987..0000000 --- a/TestPlugin/testtablemodel.h +++ /dev/null @@ -1,41 +0,0 @@ -/*============================================================================== -** Copyright (C) 2024-2027 WingSummer -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and associated documentation files (the "Software"), to deal -** in the Software without restriction, including without limitation the rights -** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -** copies of the Software, and to permit persons to whom the Software is -** furnished to do so. -** -** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -** THE SOFTWARE. -** ============================================================================= -*/ - -#ifndef TESTTABLEMODEL_H -#define TESTTABLEMODEL_H - -#include - -class TestTableModel : public QAbstractTableModel { - Q_OBJECT -public: - explicit TestTableModel(QObject *parent = nullptr); - - // QAbstractItemModel interface -public: - virtual int rowCount(const QModelIndex &parent) const override; - virtual int columnCount(const QModelIndex &parent) const override; - virtual QVariant data(const QModelIndex &index, int role) const override; - - virtual QVariant headerData(int section, Qt::Orientation orientation, - int role) const override; -}; - -#endif // TESTTABLEMODEL_H diff --git a/WingPlugin b/WingPlugin index 95b3250..8d86c18 160000 --- a/WingPlugin +++ b/WingPlugin @@ -1 +1 @@ -Subproject commit 95b3250011d0bf76ebd77f9905dc77fd04a46ce7 +Subproject commit 8d86c185041572bd4735b272669d4117765c2176 diff --git a/lang/zh_CN/winghex_zh_CN.ts b/lang/zh_CN/winghex_zh_CN.ts index d3cbe3c..26f316b 100644 --- a/lang/zh_CN/winghex_zh_CN.ts +++ b/lang/zh_CN/winghex_zh_CN.ts @@ -871,7 +871,7 @@ - + View 视图 @@ -908,8 +908,8 @@ - - + + Plugin 插件 @@ -919,325 +919,295 @@ 设置 - - + + Log 日志 - + ExportFindResult 导出搜索结果 - + ClearFindResult 清空记录 - - + + FindResult 搜索结果 - - - - - - - + + + + Copy 复制 - - - - - - - - + + + + + CopyToClipBoard 数据已拷贝到粘贴板 - + LittleEndian 小端 - + BigEndian 大端 - + Number 数值 - - + + CheckSum 校验和 - - + + DeleteBookMark 删除书签 - - + + ClearBookMark 清空书签 - - - - + + + + BookMark 书签 - - + + DecodeText 解码字符串 - + ScriptConsole 脚本控制台 - - - DVList - 可视化列表 - - - - - DVTree - 可视化树数据 - - - - - DVTable - 可视化表格 - - - - - DVText - 可视化文本 - - - - + + 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 缩放 @@ -1317,767 +1287,736 @@ 启动完毕 - + NoExtension 无扩展 - - - - - - + + ExportResult 导出结果 - - - + NothingToSave 没有保存的数据 - - - - - ClearResult - 清空结果 - - - + OpenExt 打开 - 拓展 - + ResetScale 重置缩放 - + ShowMetafg 标注前景色 - + ShowMetabg 标注背景色 - + ShowMetaComment 批注 - + MetaShowAll 显示所有标注 - + MetaHideAll 隐藏所有标注 - + FileStatus 文件状态 - + InfoSave 是否保存 - + ReadOnly 可读写 - + SetLocked 启用/禁用锁定编辑 - + ErrUnLock 锁定编辑失败 - + SetOver 启用/禁用改变大小 - + UnsignedHex 无符号 Hex - + 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 - + 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 请选择保存文件路径: - + NoMoreClone 克隆已到上限,无法继续操作! - + FindFininishBusy 查找任务繁忙,请勿重复查找! - + MayTooMuchFindResult 搜索数量已到达上限,结果可能不全,建议请按区段搜索。 - + SaveLayoutSuccess 保存布局成功 - + SaveLayoutError 保存布局失败 - + HasClonedView 该编辑页已被克隆编辑,如果关闭,相关联的页也会被关闭,你确认继续吗? - + SaveWorkSpace 保存工作区 - + WingHexWorkSpace (*.wingpro) 羽云十六进制工作区 (*.wingpro) - + ConfirmSave 正在关闭未保存的文件或工作区,你确定保存吗? - + [Info] 【信息】 - + [Warn] 【警告】 - + [Error] 【错误】 - - Column %1 - 列 %1 - - - + 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 打开文件出现错误(由于权限不足),如下为打开错误的文件: @@ -2308,155 +2247,155 @@ PluginSystem - + LoadingPlugin 加载插件中: - + InvalidPluginBrokenInfo 加载插件失败:损坏的插件数据 - + AppClosingCanceled: 程序关闭被取消: - + - PluginID: - 插件 ID: - + FoundDrvPluginCount 总计发现设备拓展插件数目: - + RegisterScriptFnUnSupportedTypes: 因脚本函数含有未支持的类型而注册失败: - - + + RegisterScriptFnInvalidSig: 因脚本函数签名非法而注册失败: - - + + RegisterScriptFnConflitSig: 因脚本函数签名冲突而注册失败: - + InvalidEnumName: 非法枚举名: - + InvalidEnumValue: 非法枚举值: - + InvalidMarcosRegister: 非法宏注册: - + ErrLoadPluginSDKVersion 插件加载失败:非法插件 SDK 版本! - + ErrLoadPluginNoName 插件加载失败:非法插件名称! - + ErrLoadInitPlugin 插件加载失败:初始化插件失败! - + PluginName : 插件名: - + PluginAuthor : 插件作者: - + PluginWidgetRegister 注册插件对象中…… - + ErrLoadExtPluginSDKVersion 设备拓展插件加载失败:非法插件 SDK 版本! - + ExtPluginAuthor : 设备拓展插件作者: - + ExtPluginWidgetRegister 设备拓展注册插件对象中…… - + ErrLoadInitExtPlugin 设备拓展插件加载失败:初始化插件失败! - + ChooseFile 选择文件 - - + + Error 错误 - + FileNotExist 文件不存在! - + FilePermission 因文件权限无法继续! - + EmptyNameDockWidget: 空的贴边组件名: - + InvalidNameDockWidget: 无效贴边组件名: - + InvalidNullDockWidget: 无效空贴边组件: - + Not allowed operation in non-UI thread 该操作在非 UI 线程非法 - + UnsafePluginDir 不安全的插件目录,请将插件目录设置为仅管理员账户可写 @@ -2466,42 +2405,42 @@ 【非法调用】 - + InvalidPluginID 加载插件失败:非法插件标识符 - + InvalidDupPlugin 加载插件失败:重复的插件标识符 - + FoundPluginCount 总计发现插件数目: - + PluginLoadingFailedSummary 有依赖插件加载失败总结 - + - Dependencies: - 依赖: - + PUID: 插件唯一标志符: - + Version: 版本: - + PluginLoadingFinished 加载插件完毕! @@ -2655,25 +2594,6 @@ 说明: - - QJsonModel - - - - - - key - - - - - - - - value - - - QMessageBox @@ -5155,28 +5075,28 @@ WingAngelAPI - + AngelScriptService AngelScript 服务 - + A internal plugin that provides AngelScript scripts with the ability to call the host API. 为 AngelScript 脚本提供调用主机 API 能力的内部插件。 - + NotSupportedQMetaType: 不支持的 QT 数据元类型: - - + + Get Exception While ScriptCall: (%1) %2 脚本调用发生异常:(%1)%2 - + InvalidRetType: need 无效返回值:需要 diff --git a/lang/zh_TW/winghex_zh_TW.ts b/lang/zh_TW/winghex_zh_TW.ts index a79ca77..a70b244 100644 --- a/lang/zh_TW/winghex_zh_TW.ts +++ b/lang/zh_TW/winghex_zh_TW.ts @@ -871,7 +871,7 @@ - + View 視圖 @@ -908,8 +908,8 @@ - - + + Plugin 插件 @@ -919,325 +919,295 @@ 設置 - - + + Log 日誌 - + ExportFindResult 導出搜索結果 - + ClearFindResult 清空記錄 - - + + FindResult 搜索結果 - - - - - - - + + + + Copy 複製 - - - - - - - - + + + + + CopyToClipBoard 數據已拷貝到粘貼板 - + LittleEndian 小端 - + BigEndian 大端 - + Number 數值 - - + + CheckSum 校驗和 - - + + DeleteBookMark 刪除書簽 - - + + ClearBookMark 清空書簽 - - - - + + + + BookMark 書簽 - - + + DecodeText 解碼字串 - + ScriptConsole 腳本控制臺 - - - DVList - 可視化列表 - - - - - DVTree - 可視化樹數據 - - - - - DVTable - 可視化表格 - - - - - DVText - 可視化文本 - - - - + + 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 縮放 @@ -1317,767 +1287,736 @@ 啟動完畢 - + NoExtension 無擴展 - - - - - - + + ExportResult 導出結果 - - - + NothingToSave 沒有保存的數據 - - - - - ClearResult - 清空結果 - - - + OpenExt 打開 - 拓展 - + ResetScale 重置縮放 - + ShowMetafg 標注前景色 - + ShowMetabg 標注背景色 - + ShowMetaComment 批註 - + MetaShowAll 顯示所有標注 - + MetaHideAll 隱藏所有標注 - + FileStatus 檔狀態 - + InfoSave 是否保存 - + ReadOnly 可讀寫 - + SetLocked 啟用/禁用鎖定編輯 - + ErrUnLock 鎖定編輯失敗 - + SetOver 啟用/禁用改變大小 - + UnsignedHex 無符號 Hex - + 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 - + 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 請選擇保存檔路徑: - + NoMoreClone 克隆已到上限,無法繼續操作! - + FindFininishBusy 查找任務繁忙,請勿重複查找! - + MayTooMuchFindResult 搜索數量已到達上限,結果可能不全,建議請按區段搜索。 - + SaveLayoutSuccess 保存佈局成功 - + SaveLayoutError 保存佈局失敗 - + HasClonedView 該編輯頁已被克隆編輯,如果關閉,相關聯的頁也會被關閉,你確認繼續嗎? - + SaveWorkSpace 保存工作區 - + WingHexWorkSpace (*.wingpro) 羽雲十六進制工作區 (*.wingpro) - + ConfirmSave 正在關閉未保存的檔或工作區,你確定保存嗎? - + [Info] 【資訊】 - + [Warn] 【警告】 - + [Error] 【錯誤】 - - Column %1 - 列 %1 - - - + 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 打開檔出現錯誤(由於許可權不足),如下為打開錯誤的檔: @@ -2308,155 +2247,155 @@ PluginSystem - + LoadingPlugin 加載插件中: - + InvalidPluginBrokenInfo 加載插件失敗:損壞的插件數據 - + AppClosingCanceled: 程式關閉被取消: - + - PluginID: - 插件 ID: - + FoundDrvPluginCount 總計發現設備拓展插件數目: - + RegisterScriptFnUnSupportedTypes: 因腳本函數含有未支持的類型而註冊失敗: - - + + RegisterScriptFnInvalidSig: 因腳本函數簽名非法而註冊失敗: - - + + RegisterScriptFnConflitSig: 因腳本函數簽名衝突而註冊失敗: - + InvalidEnumName: 非法枚舉名: - + InvalidEnumValue: 非法枚舉值: - + InvalidMarcosRegister: 非法宏註冊: - + ErrLoadPluginSDKVersion 插件加載失敗:非法插件 SDK 版本! - + ErrLoadPluginNoName 插件加載失敗:非法插件名稱! - + ErrLoadInitPlugin 插件加載失敗:初始化插件失敗! - + PluginName : 插件名: - + PluginAuthor : 插件作者: - + PluginWidgetRegister 註冊插件對象中…… - + ErrLoadExtPluginSDKVersion 設備拓展插件加載失敗:非法插件 SDK 版本! - + ExtPluginAuthor : 設備拓展插件作者: - + ExtPluginWidgetRegister 設備拓展註冊插件對象中…… - + ErrLoadInitExtPlugin 設備拓展插件加載失敗:初始化插件失敗! - + ChooseFile 選擇檔 - - + + Error 錯誤 - + FileNotExist 檔不存在! - + FilePermission 因檔許可權無法繼續! - + EmptyNameDockWidget: 空的貼邊組件名: - + InvalidNameDockWidget: 無效貼邊組件名: - + InvalidNullDockWidget: 無效空貼邊組件: - + Not allowed operation in non-UI thread 該操作在非 UI 線程非法 - + UnsafePluginDir 不安全的插件目錄,請將插件目錄設置為僅管理員帳戶可寫 @@ -2466,42 +2405,42 @@ 【非法調用】 - + InvalidPluginID 加載插件失敗:非法插件識別字 - + InvalidDupPlugin 加載插件失敗:重複的插件識別字 - + FoundPluginCount 總計發現插件數目: - + PluginLoadingFailedSummary 有依賴插件加載失敗總結 - + - Dependencies: - 依賴: - + PUID: 插件唯一標誌符: - + Version: 版本: - + PluginLoadingFinished 加載插件完畢! @@ -2655,25 +2594,6 @@ 說明: - - QJsonModel - - - - - - key - - - - - - - - value - - - QMessageBox @@ -5155,28 +5075,28 @@ WingAngelAPI - + AngelScriptService AngelScript 服務 - + A internal plugin that provides AngelScript scripts with the ability to call the host API. 為 AngelScript 腳本提供調用主機 API 能力的內部插件。 - + NotSupportedQMetaType: 不支持的 QT 數據元類型: - - + + Get Exception While ScriptCall: (%1) %2 腳本調用發生異常:(%1)%2 - + InvalidRetType: need 無效返回值:需要 diff --git a/src/class/clickcallback.h b/src/class/clickcallback.h deleted file mode 100644 index e6b4939..0000000 --- a/src/class/clickcallback.h +++ /dev/null @@ -1,84 +0,0 @@ -/*============================================================================== -** 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 CLICKCALLBACK_H -#define CLICKCALLBACK_H - -#include "WingPlugin/iwingplugin.h" -#include "angelscript.h" - -class ClickCallBack { -public: - ClickCallBack() {} - - ClickCallBack(const WingHex::ClickedCallBack &b) : _call(b) {} - - explicit ClickCallBack(asIScriptEngine *engine, asIScriptFunction *func) - : _engine(engine), _func(func) { - if (_engine && _func) { - _func->AddRef(); - } - } - - ~ClickCallBack() { - if (_func) { - _func->Release(); - } - } - -public: - ClickCallBack &operator=(const WingHex::ClickedCallBack &_Right) { - *this = ClickCallBack(_Right); - return *this; - } - - ClickCallBack &operator=(WingHex::ClickedCallBack &&_Right) { - *this = ClickCallBack(_Right); - return *this; - } - -public: - explicit operator bool() const noexcept { - return _call || (_engine && _func); - } - - void operator()(const QModelIndex &index) { - if (_call) { - _call(index); - } else { - if (_engine && _func) { - auto ctx = _engine->CreateContext(); - if (ctx) { - auto r = ctx->Prepare(_func); - if (r >= 0) { - auto idx = index; - ctx->SetArgObject(0, &idx); - ctx->Execute(); - } - ctx->Release(); - } - } - } - } - -private: - WingHex::ClickedCallBack _call; - asIScriptEngine *_engine = nullptr; - asIScriptFunction *_func = nullptr; -}; - -#endif // CLICKCALLBACK_H diff --git a/src/class/pluginsystem.cpp b/src/class/pluginsystem.cpp index bca36f2..f5a8e63 100644 --- a/src/class/pluginsystem.cpp +++ b/src/class/pluginsystem.cpp @@ -17,7 +17,6 @@ #include "pluginsystem.h" #include "AngelScript/sdk/angelscript/source/as_builder.h" -#include "QJsonModel/include/QJsonModel.hpp" #include "Qt-Advanced-Docking-System/src/DockAreaWidget.h" #include "class/languagemanager.h" #include "class/logger.h" @@ -33,10 +32,11 @@ #include "dialog/colorpickerdialog.h" #include "dialog/framelessdialogbase.h" #include "dialog/mainwindow.h" -#include "model/qjsontablemodel.h" #include #include +#include +#include #include #include #include @@ -1787,99 +1787,6 @@ bool PluginSystem::closeAllFiles(QObject *sender) { return true; } -bool PluginSystem::dataVisualText(QObject *sender, const QString &data, - const QString &title) { - auto plg = checkPluginAndReport(sender, __func__); - if (plg == nullptr || !checkThreadAff()) { - return false; - } - _win->m_infotxt->setProperty("__TITLE__", title); - _win->m_infotxt->setText(data); - return true; -} - -bool PluginSystem::dataVisualTextList(QObject *sender, const QStringList &data, - const QString &title, - ClickedCallBack clicked, - ClickedCallBack dblClicked) { - auto plg = checkPluginAndReport(sender, __func__); - if (plg == nullptr || !checkThreadAff()) { - return false; - } - return updateTextList_API(data, title, clicked, dblClicked); -} - -bool PluginSystem::dataVisualTextTree(QObject *sender, const QString &json, - const QString &title, - ClickedCallBack clicked, - ClickedCallBack dblClicked) { - auto plg = checkPluginAndReport(sender, __func__); - if (plg == nullptr || !checkThreadAff()) { - return false; - } - return updateTextTree_API(json, title, clicked, dblClicked); -} - -bool PluginSystem::dataVisualTextTable(QObject *sender, const QString &json, - const QStringList &headers, - const QStringList &headerNames, - const QString &title, - ClickedCallBack clicked, - ClickedCallBack dblClicked) { - auto plg = checkPluginAndReport(sender, __func__); - if (plg == nullptr || !checkThreadAff()) { - return false; - } - return updateTextTable_API(json, headers, headerNames, title, clicked, - dblClicked); -} - -bool PluginSystem::dataVisualTextListByModel(QObject *sender, - QAbstractItemModel *model, - const QString &title, - ClickedCallBack clicked, - ClickedCallBack dblClicked) { - auto plg = checkPluginAndReport(sender, __func__); - if (plg == nullptr || !checkThreadAff()) { - return false; - } - if (model) { - auto oldmodel = _win->m_infolist->model(); - if (oldmodel) { - oldmodel->deleteLater(); - } - _win->m_infolist->setProperty("__TITLE__", title); - _win->m_infolist->setModel(model); - _win->m_infoclickfn = clicked; - _win->m_infodblclickfn = dblClicked; - return true; - } - return false; -} - -bool PluginSystem::dataVisualTextTreeByModel(QObject *sender, - QAbstractItemModel *model, - const QString &title, - ClickedCallBack clicked, - ClickedCallBack dblClicked) { - auto plg = checkPluginAndReport(sender, __func__); - if (plg == nullptr || !checkThreadAff()) { - return false; - } - if (model) { - auto oldmodel = _win->m_infotree->model(); - if (oldmodel) { - oldmodel->deleteLater(); - } - _win->m_infotree->setProperty("__TITLE__", title); - _win->m_infotree->setModel(model); - _win->m_infotreeclickfn = clicked; - _win->m_infotreedblclickfn = dblClicked; - return true; - } - return false; -} - bool PluginSystem::checkErrAllAllowAndReport(QObject *sender, const char *func) { auto p = qobject_cast(sender); @@ -1904,29 +1811,6 @@ IWingPlugin *PluginSystem::checkPluginAndReport(QObject *sender, return p; } -bool PluginSystem::dataVisualTextTableByModel(QObject *sender, - QAbstractItemModel *model, - const QString &title, - ClickedCallBack clicked, - ClickedCallBack dblClicked) { - auto plg = checkPluginAndReport(sender, __func__); - if (plg == nullptr || !checkThreadAff()) { - return false; - } - if (model) { - auto oldmodel = _win->m_infotable->model(); - if (oldmodel) { - oldmodel->deleteLater(); - } - _win->m_infotable->setProperty("__TITLE__", title); - _win->m_infotable->setModel(model); - _win->m_infotableclickfn = clicked; - _win->m_infotabledblclickfn = dblClicked; - return true; - } - return false; -} - ErrFile PluginSystem::saveAsCurrent(QObject *sender, const QString &savename) { auto plg = checkPluginAndReport(sender, __func__); if (plg == nullptr) { @@ -3716,77 +3600,6 @@ void PluginSystem::registerMarcoDevice(IWingDevice *plg) { _scriptMarcos.append(sep + id + sep); } -bool PluginSystem::updateTextList_API(const QStringList &data, - const QString &title, - const ClickCallBack &click, - const ClickCallBack &dblclick) { - auto oldmodel = _win->m_infolist->model(); - if (oldmodel) { - oldmodel->deleteLater(); - } - _win->m_infolist->setProperty("__TITLE__", title); - auto model = new QStringListModel(data); - _win->m_infolist->setModel(model); - _win->m_infoclickfn = click; - _win->m_infodblclickfn = dblclick; - return true; -} - -bool PluginSystem::updateTextTree_API(const QString &json, const QString &title, - const ClickCallBack &click, - const ClickCallBack &dblclick) { - auto oldmodel = _win->m_infotree->model(); - if (oldmodel) { - oldmodel->deleteLater(); - } - _win->m_infotree->setProperty("__TITLE__", title); - auto model = new QJsonModel; - if (model->loadJson(json.toUtf8())) { - _win->m_infotree->setModel(model); - _win->m_infotreeclickfn = click; - _win->m_infotreedblclickfn = dblclick; - return true; - } - return false; -} - -bool PluginSystem::updateTextTable_API(const QString &json, - const QStringList &headers, - const QStringList &headerNames, - const QString &title, - const ClickCallBack &click, - const ClickCallBack &dblclick) { - auto oldmodel = _win->m_infotable->model(); - if (oldmodel) { - oldmodel->deleteLater(); - } - - QJsonTableModel::Header header; - if (headers.size() > headerNames.size()) { - for (auto &name : headers) { - QJsonTableModel::Heading heading; - heading["index"] = name; - heading["title"] = name; - header.append(heading); - } - } else { - auto np = headerNames.cbegin(); - for (auto p = headers.cbegin(); p != headers.cend(); ++p, ++np) { - QJsonTableModel::Heading heading; - heading["index"] = *p; - heading["title"] = *np; - header.append(heading); - } - } - _win->m_infotable->setProperty("__TITLE__", title); - auto model = new QJsonTableModel(header); - model->setJson(QJsonDocument::fromJson(json.toUtf8())); - _win->m_infotable->setModel(model); - _win->m_infotableclickfn = click; - _win->m_infotabledblclickfn = dblclick; - return true; -} - bool PluginSystem::checkThreadAff() { if (QThread::currentThread() != qApp->thread()) { Logger::warning(tr("Not allowed operation in non-UI thread")); diff --git a/src/class/pluginsystem.h b/src/class/pluginsystem.h index 363b722..93a337e 100644 --- a/src/class/pluginsystem.h +++ b/src/class/pluginsystem.h @@ -32,7 +32,6 @@ #include #include "WingPlugin/iwingdevice.h" -#include "class/clickcallback.h" #include "class/wingangelapi.h" #include "control/editorview.h" @@ -258,18 +257,6 @@ private: void registerPluginDockWidgets(IWingPluginBase *p); void registerPluginPages(IWingPluginBase *p); -public: - bool updateTextList_API(const QStringList &data, const QString &title, - const ClickCallBack &click, - const ClickCallBack &dblclick); - bool updateTextTree_API(const QString &json, const QString &title, - const ClickCallBack &click, - const ClickCallBack &dblclick); - bool updateTextTable_API(const QString &json, const QStringList &headers, - const QStringList &headerNames, - const QString &title, const ClickCallBack &click, - const ClickCallBack &dblclick); - public: // fpr crash checking QString currentLoadingPlugin() const; @@ -735,41 +722,6 @@ public: // extension WING_SERVICE bool closeAllFiles(QObject *sender); -public: - WING_SERVICE bool dataVisualText(QObject *sender, const QString &data, - const QString &title); - - WING_SERVICE bool dataVisualTextList(QObject *sender, - const QStringList &data, - const QString &title, - WingHex::ClickedCallBack clicked, - WingHex::ClickedCallBack dblClicked); - - WING_SERVICE bool dataVisualTextTree(QObject *sender, const QString &json, - const QString &title, - WingHex::ClickedCallBack clicked, - WingHex::ClickedCallBack dblClicked); - - WING_SERVICE bool dataVisualTextTable(QObject *sender, const QString &json, - const QStringList &headers, - const QStringList &headerNames, - const QString &title, - WingHex::ClickedCallBack clicked, - WingHex::ClickedCallBack dblClicked); - - // API for Qt Plugin Only - WING_SERVICE bool dataVisualTextListByModel( - QObject *sender, QAbstractItemModel *model, const QString &title, - WingHex::ClickedCallBack clicked, WingHex::ClickedCallBack dblClicked); - - WING_SERVICE bool dataVisualTextTableByModel( - QObject *sender, QAbstractItemModel *model, const QString &title, - WingHex::ClickedCallBack clicked, WingHex::ClickedCallBack dblClicked); - - WING_SERVICE bool dataVisualTextTreeByModel( - QObject *sender, QAbstractItemModel *model, const QString &title, - WingHex::ClickedCallBack clicked, WingHex::ClickedCallBack dblClicked); - private: WingHex::IWingPlugin *checkPluginAndReport(QObject *sender, const char *func); diff --git a/src/class/wingangelapi.cpp b/src/class/wingangelapi.cpp index bb500ed..56b5254 100644 --- a/src/class/wingangelapi.cpp +++ b/src/class/wingangelapi.cpp @@ -40,11 +40,9 @@ WingAngelAPI::WingAngelAPI() { #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) qRegisterMetaType>(); #endif - - _fnbuffer.reserve(PluginSystem::instance().pluginAPICount()); } -WingAngelAPI::~WingAngelAPI() { _fnbuffer.clear(); } +WingAngelAPI::~WingAngelAPI() {} int WingAngelAPI::sdkVersion() const { return WingHex::SDKVERSION; } @@ -151,7 +149,6 @@ void WingAngelAPI::installAPI(ScriptMachine *machine) { installHexReaderAPI(engine); installHexControllerAPI(engine); - installDataVisualAPI(engine); installScriptEnums(engine); installScriptFns(engine); @@ -253,11 +250,6 @@ void WingAngelAPI::installBasicTypes(asIScriptEngine *engine) { Q_ASSERT(r >= 0); Q_UNUSED(r); - r = engine->RegisterFuncdef( - "void ClickCallBack(const ModelIndex &in index)"); - Q_ASSERT(r >= 0); - Q_UNUSED(r); - installHexBaseType(engine); } @@ -266,35 +258,35 @@ void WingAngelAPI::installLogAPI(asIScriptEngine *engine) { Q_ASSERT(r >= 0); Q_UNUSED(r); - registerAPI( - engine, std::bind(&WingAngelAPI::logInfo, this, std::placeholders::_1), - "void info(const string &in message)"); + registerAPI(engine, + asMETHODPR(WingAngelAPI, logInfo, (const QString &), void), + "void info(const string &in message)"); - registerAPI( - engine, std::bind(&WingAngelAPI::logTrace, this, std::placeholders::_1), - "void trace(const string &in message)"); + registerAPI(engine, + asMETHODPR(WingAngelAPI, logTrace, (const QString &), void), + "void trace(const string &in message)"); - registerAPI( - engine, std::bind(&WingAngelAPI::logDebug, this, std::placeholders::_1), - "void debug(const string &in message)"); + registerAPI(engine, + asMETHODPR(WingAngelAPI, logDebug, (const QString &), void), + "void debug(const string &in message)"); - registerAPI( - engine, std::bind(&WingAngelAPI::logWarn, this, std::placeholders::_1), - "void warn(const string &in message)"); + registerAPI(engine, + asMETHODPR(WingAngelAPI, logWarn, (const QString &), void), + "void warn(const string &in message)"); - registerAPI( - engine, std::bind(&WingAngelAPI::logError, this, std::placeholders::_1), - "void error(const string &in message)"); + registerAPI(engine, + asMETHODPR(WingAngelAPI, logError, (const QString &), void), + "void error(const string &in message)"); engine->SetDefaultNamespace(""); } void WingAngelAPI::installExtAPI(asIScriptEngine *engine) { // toast(message, iconPath) - registerAPI( + registerAPI( engine, - std::bind(&WingAngelAPI::toast, this, std::placeholders::_2, - std::placeholders::_1), + asMETHODPR(WingAngelAPI, _UI_Toast, (const QString &, const QString &), + void), "void toast(const string &in message, const string &in icon =\"\")"); } @@ -303,75 +295,66 @@ void WingAngelAPI::installMsgboxAPI(asIScriptEngine *engine) { Q_ASSERT(r >= 0); Q_UNUSED(r); - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::msgAboutQt, this, nullptr, - std::placeholders::_1), - "void aboutQt(const string &in title =\"\")"); + registerAPI(engine, + asMETHODPR(WingAngelAPI, _MSG_AboutQt, (const QString &), void), + "void aboutQt(const string &in title =\"\")"); - registerAPI( + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::msgInformation, this, nullptr, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4), + asMETHODPR(WingAngelAPI, _MSG_Information, + (const QString &, const QString &, + QMessageBox::StandardButtons, QMessageBox::StandardButton), + QMessageBox::StandardButton), "void information(const string &in title, const string &in text, " "msgbox::buttons buttons = msgbox::buttons::Ok, " "msgbox::buttons defaultButton = msgbox::buttons::NoButton)"); - registerAPI( + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::msgQuestion, this, nullptr, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4), + asMETHODPR(WingAngelAPI, _MSG_Question, + (const QString &, const QString &, + QMessageBox::StandardButtons, QMessageBox::StandardButton), + QMessageBox::StandardButton), "void question(const string &in title, const string &in text, " "msgbox::buttons buttons = msgbox::buttons::Yes | " "msgbox::buttons::No, " "msgbox::buttons defaultButton = msgbox::buttons::NoButton)"); - registerAPI( + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::msgWarning, this, nullptr, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4), + asMETHODPR(WingAngelAPI, _MSG_Warning, + (const QString &, const QString &, + QMessageBox::StandardButtons, QMessageBox::StandardButton), + QMessageBox::StandardButton), "void warning(const string &in title, const string &in text, " "msgbox::buttons buttons = msgbox::buttons::Ok, " "msgbox::buttons defaultButton = msgbox::buttons::NoButton)"); - registerAPI( + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::msgCritical, this, nullptr, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4), + asMETHODPR(WingAngelAPI, _MSG_Critical, + (const QString &, const QString &, + QMessageBox::StandardButtons, QMessageBox::StandardButton), + QMessageBox::StandardButton), "void critical(const string &in title, const string &in text, " "msgbox::buttons buttons = msgbox::buttons::Ok, " "msgbox::buttons defaultButton = msgbox::buttons::NoButton)"); - registerAPI( + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::msgbox, this, nullptr, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4, - std::placeholders::_5), + asMETHODPR(WingAngelAPI, _MSG_msgbox, + (QMessageBox::Icon, const QString &, const QString &, + QMessageBox::StandardButtons, QMessageBox::StandardButton), + QMessageBox::StandardButton), "void msgbox(msgbox::icon icon, const string &in title, " "const string &in text, " "msgbox::buttons buttons = msgbox::buttons::NoButton, " "msgbox::buttons defaultButton = msgbox::buttons::NoButton)"); - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::msgAbout, this, nullptr, - std::placeholders::_1, std::placeholders::_2), - "void about(const string &in title, const string &in text)"); + registerAPI(engine, + asMETHODPR(WingAngelAPI, _MSG_About, + (const QString &, const QString &), void), + "void about(const string &in title, const string &in text)"); engine->SetDefaultNamespace(""); } @@ -381,64 +364,55 @@ void WingAngelAPI::installInputboxAPI(asIScriptEngine *engine) { Q_ASSERT(r >= 0); Q_UNUSED(r); - registerAPI( + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::dlgGetText, this, nullptr, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4, - std::placeholders::_5, std::placeholders::_6), + asMETHODPR(WingAngelAPI, _InputBox_GetText, + (const QString &, const QString &, QLineEdit::EchoMode, + const QString &, bool *, Qt::InputMethodHints), + QString), "string getText(const string &in title, const string &in label, " "inputbox::EchoMode echo = inputbox::Normal, " "const string &in text = \"\", bool &out ok = false, " "inputbox::InputMethodHints inputMethodHints = inputbox::ImhNone)"); - registerAPI( + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::dlgGetMultiLineText, this, nullptr, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4, - std::placeholders::_5), + asMETHODPR(WingAngelAPI, _InputBox_GetMultiLineText, + (const QString &, const QString &, const QString &, bool *, + Qt::InputMethodHints inputMethodHints), + QString), "string getMultiLineText(const string &in title, " "const string &in label, " "const string &in text = \"\", bool &out ok = false, " "inputbox::InputMethodHints inputMethodHints = inputbox::ImhNone)"); - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::dlgGetInt, this, nullptr, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4, - std::placeholders::_5, std::placeholders::_6, - std::placeholders::_7), - "int getInt(const string &in title, const string &in label, " - "int &in value = 0, int &in minValue = -2147483647, " - "int &in maxValue = 2147483647, " - "int &in step = 1, bool &out ok = false)"); + registerAPI(engine, + asMETHODPR(WingAngelAPI, _InputBox_GetInt, + (const QString &, const QString &, int, int, int, + int, bool *), + int), + "int getInt(const string &in title, const string &in label, " + "int &in value = 0, int &in minValue = -2147483647, " + "int &in maxValue = 2147483647, " + "int &in step = 1, bool &out ok = false)"); - registerAPI( + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::dlgGetDouble, this, nullptr, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4, - std::placeholders::_5, std::placeholders::_6, - std::placeholders::_7, std::placeholders::_8), + asMETHODPR(WingAngelAPI, _InputBox_GetDouble, + (const QString &, const QString &, double, double, double, + int, bool *, double), + double), "double getDouble(const string &in title, const string &in label, " "double &in value = 0, double &in minValue = -2147483647, " "double &in maxValue = 2147483647, int &in decimals = 1, " "bool &out ok = false, double &in step = 1)"); - registerAPI( + registerAPI( engine, - std::bind(&WingAngelAPI::_InputBox_getItem, this, std::placeholders::_1, - std::placeholders::_2, std::placeholders::_3, - std::placeholders::_4, std::placeholders::_5, - std::placeholders::_6, std::placeholders::_7), + asMETHODPR(WingAngelAPI, _InputBox_getItem, + (const QString &, const QString &, const CScriptArray &, int, + bool, bool *, Qt::InputMethodHints), + QString), "string getItem(const string &in title, const string &in label, " "const string[] &in items, int current = 0, " "bool editable = true, bool &out ok = false, " @@ -452,46 +426,41 @@ void WingAngelAPI::installFileDialogAPI(asIScriptEngine *engine) { Q_ASSERT(r >= 0); Q_UNUSED(r); - registerAPI( + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::dlgGetExistingDirectory, this, nullptr, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3), + asMETHODPR(WingAngelAPI, _FileDialog_GetExistingDirectory, + (const QString &, const QString &, QFileDialog::Options), + QString), "string getExistingDirectory(const string &in caption = \"\", " "const string &in dir = \"\", " "filedlg::options &in options = filedlg::options::ShowDirsOnly)"); - registerAPI( + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::dlgGetOpenFileName, this, nullptr, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4, - std::placeholders::_5), + asMETHODPR(WingAngelAPI, _FileDialog_GetOpenFileName, + (const QString &, const QString &, const QString &, + QString *, QFileDialog::Options), + QString), "string getOpenFileName(const string &in caption = \"\", " "const string &in dir = \"\", const string &in filter = \"\", " "string &out selectedFilter = \"\", filedlg::options &in options = 0)"); - registerAPI( + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::dlgGetSaveFileName, this, nullptr, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4, - std::placeholders::_5), + asMETHODPR(WingAngelAPI, _FileDialog_GetSaveFileName, + (const QString &, const QString &, const QString &, + QString *, QFileDialog::Options), + QString), "string getSaveFileName(const string &in caption = \"\", " "const string &in dir = \"\", const string &in filter = \"\", " "string &out selectedFilter = \"\", filedlg::options &in options = 0)"); - registerAPI( + registerAPI( engine, - std::bind(&WingAngelAPI::_FileDialog_getOpenFileNames, this, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4, - std::placeholders::_5), + asMETHODPR(WingAngelAPI, _FileDialog_getOpenFileNames, + (const QString &, const QString &, const QString &, + QString *, QFileDialog::Options), + CScriptArray *), "string[]@ getOpenFileNames(const string &in caption = \"\", " "const string &in dir = \"\", const string &in filter = \"\", " "string &out selectedFilter = \"\", filedlg::options &in options = 0)"); @@ -504,11 +473,9 @@ void WingAngelAPI::installColorDialogAPI(asIScriptEngine *engine) { Q_ASSERT(r >= 0); Q_UNUSED(r); - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::dlgGetColor, this, - std::placeholders::_1, nullptr), - "color getColor(const string &in caption)"); + registerAPI(engine, + asMETHODPR(WingAngelAPI, _Color_get, (const QString &), QColor), + "color getColor(const string &in caption)"); engine->SetDefaultNamespace(""); } @@ -577,191 +544,168 @@ void WingAngelAPI::installHexReaderAPI(asIScriptEngine *engine) { Q_ASSERT(r >= 0); Q_UNUSED(r); - registerAPI( - engine, std::bind(&WingHex::IWingPlugin::isCurrentDocEditing, this), + registerAPI( + engine, + asMETHODPR(WingHex::IWingPlugin, isCurrentDocEditing, (void), bool), "bool isCurrentDocEditing()"); - - registerAPI( - engine, std::bind(&WingHex::IWingPlugin::currentDocFilename, this), + registerAPI( + engine, + asMETHODPR(WingHex::IWingPlugin, currentDocFilename, (void), QString), "string currentDocFilename()"); - - registerAPI( - engine, std::bind(&WingHex::IWingPlugin::isInsertionMode, this), - "bool isInsertionMode()"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::isReadOnly, this), - "bool isReadOnly()"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::isKeepSize, this), - "bool isKeepSize()"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::isLocked, this), - "bool isLocked()"); - - registerAPI( - engine, std::bind(&WingHex::IWingPlugin::currentPos, this), - "HexPosition currentPos()"); - - registerAPI( - engine, std::bind(&WingHex::IWingPlugin::stringVisible, this), - "bool stringVisible()"); - - registerAPI( - engine, std::bind(&WingHex::IWingPlugin::addressVisible, this), - "bool addressVisible()"); - - registerAPI( - engine, std::bind(&WingHex::IWingPlugin::headerVisible, this), - "bool headerVisible()"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::isModified, this), - "bool isModified()"); - - registerAPI( - engine, std::bind(&WingHex::IWingPlugin::documentLines, this), + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, isInsertionMode, (void), bool), + "bool isInsertionMode()"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, isReadOnly, (void), bool), + "bool isReadOnly()"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, isKeepSize, (void), bool), + "bool isKeepSize()"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, isLocked, (void), bool), + "bool isLocked()"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, currentPos, (void), + WingHex::HexPosition), + "HexPosition currentPos()"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, stringVisible, (void), bool), + "bool stringVisible()"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, addressVisible, (void), bool), + "bool addressVisible()"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, headerVisible, (void), bool), + "bool headerVisible()"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, isModified, (void), bool), + "bool isModified()"); + registerAPI( + engine, + asMETHODPR(WingHex::IWingPlugin, documentLines, (void), qsizetype), QSIZETYPE_WRAP("documentLines()")); - - registerAPI( - engine, std::bind(&WingHex::IWingPlugin::documentBytes, this), + registerAPI( + engine, + asMETHODPR(WingHex::IWingPlugin, documentBytes, (void), qsizetype), QSIZETYPE_WRAP("documentBytes()")); - - registerAPI( - engine, std::bind(&WingHex::IWingPlugin::currentRow, this), - QSIZETYPE_WRAP("currentRow()")); - - registerAPI( - engine, std::bind(&WingHex::IWingPlugin::currentColumn, this), + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, currentRow, (void), qsizetype), + QSIZETYPE_WRAP("currentRow()")); + registerAPI( + engine, + asMETHODPR(WingHex::IWingPlugin, currentColumn, (void), qsizetype), QSIZETYPE_WRAP("currentColumn()")); - - registerAPI( - engine, std::bind(&WingHex::IWingPlugin::currentOffset, this), + registerAPI( + engine, + asMETHODPR(WingHex::IWingPlugin, currentOffset, (void), qsizetype), QSIZETYPE_WRAP("currentOffset()")); - - registerAPI( - engine, std::bind(&WingHex::IWingPlugin::selectedLength, this), + registerAPI( + engine, + asMETHODPR(WingHex::IWingPlugin, selectedLength, (void), qsizetype), QSIZETYPE_WRAP("selectedLength()")); - registerAPI( + registerAPI(engine, + asMETHODPR(WingAngelAPI, _HexReader_selectedBytes, (qsizetype), + CScriptArray *), + "byte[]@ selectedBytes(" QSIZETYPE " index)"); + registerAPI(engine, + asMETHODPR(WingAngelAPI, _HexReader_selectionBytes, (void), + CScriptArray *), + "byte[][]@ selectionBytes()"); + + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, selectionStart, (qsizetype), + WingHex::HexPosition), + "HexPosition selectionStart(" QSIZETYPE " index)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, selectionEnd, (qsizetype), + WingHex::HexPosition), + "HexPosition selectionEnd(" QSIZETYPE " index)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, selectionLength, (qsizetype), + qsizetype), + QSIZETYPE_WRAP("selectionLength(" QSIZETYPE " index)")); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, selectionCount, (), qsizetype), + QSIZETYPE_WRAP("selectionCount()")); + + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, addressBase, (void), quintptr), + QPTR_WRAP("addressBase()")); + + registerAPI(engine, + asMETHODPR(WingAngelAPI, _HexReader_readBytes, + (qsizetype, qsizetype), CScriptArray *), + "byte[]@ readBytes(" QSIZETYPE " offset," QSIZETYPE " len)"); + + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, readInt8, (qsizetype), qint8), + "int8 readInt8(" QSIZETYPE " offset)"); + registerAPI( engine, - std::bind(&WingAngelAPI::_HexReader_selectedBytes, this, - std::placeholders::_1), - "byte[]@ selectedBytes(" QSIZETYPE " index)"); + asMETHODPR(WingHex::IWingPlugin, readUInt8, (qsizetype), quint8), + "uint8 readUInt8(" QSIZETYPE " offset)"); - registerAPI( - engine, std::bind(&WingAngelAPI::_HexReader_selectionBytes, this), - "byte[][]@ selectionBytes()"); - registerAPI( + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::selectionStart, this, - std::placeholders::_1), - "HexPosition selectionStart(" QSIZETYPE " index)"); - registerAPI( + asMETHODPR(WingHex::IWingPlugin, readInt16, (qsizetype), qint16), + "int16 readInt16(" QSIZETYPE " offset)"); + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::selectionEnd, this, - std::placeholders::_1), - "HexPosition selectionEnd(" QSIZETYPE " index)"); - registerAPI( + asMETHODPR(WingHex::IWingPlugin, readUInt16, (qsizetype), quint16), + "uint16 readUInt16(" QSIZETYPE " offset)"); + + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::selectionLength, this, - std::placeholders::_1), - QSIZETYPE_WRAP("selectionLength(" QSIZETYPE " index)")); - - registerAPI( - engine, std::bind(&WingHex::IWingPlugin::selectionCount, this), - QSIZETYPE_WRAP("selectionCount()")); - - registerAPI( - engine, std::bind(&WingHex::IWingPlugin::addressBase, this), - QPTR_WRAP("addressBase()")); - - registerAPI( + asMETHODPR(WingHex::IWingPlugin, readInt32, (qsizetype), qint32), + "int readInt32(" QSIZETYPE " offset)"); + registerAPI( engine, - std::bind(&WingAngelAPI::_HexReader_readBytes, this, - std::placeholders::_1, std::placeholders::_2), - "byte[]@ readBytes(" QSIZETYPE " offset," QSIZETYPE " len)"); + asMETHODPR(WingHex::IWingPlugin, readUInt32, (qsizetype), quint32), + "uint readUInt32(" QSIZETYPE " offset)"); - registerAPI( + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::readInt8, this, std::placeholders::_1), - "int8 readInt8(" QSIZETYPE " offset)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::readUInt8, - this, std::placeholders::_1), - "uint8 readUInt8(" QSIZETYPE " offset)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::readInt16, - this, std::placeholders::_1), - "int16 readInt16(" QSIZETYPE " offset)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::readUInt16, - this, std::placeholders::_1), - "uint16 readUInt16(" QSIZETYPE " offset)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::readInt32, - this, std::placeholders::_1), - "int readInt32(" QSIZETYPE " offset)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::readUInt32, - this, std::placeholders::_1), - "uint readUInt32(" QSIZETYPE " offset)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::readInt64, - this, std::placeholders::_1), - "int64 readInt64(" QSIZETYPE " offset)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::readUInt64, - this, std::placeholders::_1), - "uint64 readUInt64(" QSIZETYPE " offset)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::readFloat, - this, std::placeholders::_1), - "float readFloat(" QSIZETYPE " offset)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::readDouble, - this, std::placeholders::_1), - "double readDouble(" QSIZETYPE " offset)"); - - registerAPI( + asMETHODPR(WingHex::IWingPlugin, readInt64, (qsizetype), qint64), + "int64 readInt64(" QSIZETYPE " offset)"); + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::readString, this, - std::placeholders::_1, std::placeholders::_2), - "string readInt64(" QSIZETYPE " offset, string &in encoding = \"\")"); + asMETHODPR(WingHex::IWingPlugin, readUInt64, (qsizetype), quint64), + "uint64 readUInt64(" QSIZETYPE " offset)"); - registerAPI( + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, readFloat, (qsizetype), float), + "float readFloat(" QSIZETYPE " offset)"); + registerAPI( engine, - std::bind(&WingAngelAPI::_HexReader_findNext, this, - std::placeholders::_1, std::placeholders::_2), - QSIZETYPE_WRAP("findNext(" QSIZETYPE " begin, byte[] &in ba)")); + asMETHODPR(WingHex::IWingPlugin, readDouble, (qsizetype), double), + "double readDouble(" QSIZETYPE " offset)"); - registerAPI( + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, readString, + (qsizetype, const QString &), QString), + "string readString(" QSIZETYPE + " offset, string &in encoding = \"\")"); + + registerAPI(engine, + asMETHODPR(WingAngelAPI, _HexReader_findNext, + (qsizetype, const CScriptArray &), qsizetype), + QSIZETYPE_WRAP("findNext(" QSIZETYPE " begin, byte[] &in ba)")); + registerAPI( engine, - std::bind(&WingAngelAPI::_HexReader_findPrevious, this, - std::placeholders::_1, std::placeholders::_2), + asMETHODPR(WingAngelAPI, _HexReader_findPrevious, + (qsizetype, const CScriptArray &), qsizetype), QSIZETYPE_WRAP("findPrevious(" QSIZETYPE " begin, byte[] &in ba)")); - registerAPI( + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::bookMarkComment, this, - std::placeholders::_1), + asMETHODPR(WingHex::IWingPlugin, bookMarkComment, (qsizetype), QString), "string bookMarkComment(" QSIZETYPE " pos)"); - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::existBookMark, - this, std::placeholders::_1), - "bool existBookMark(" QSIZETYPE " pos)"); + registerAPI( + engine, + asMETHODPR(WingHex::IWingPlugin, existBookMark, (qsizetype), bool), + "bool existBookMark(" QSIZETYPE " pos)"); engine->SetDefaultNamespace(""); } @@ -771,505 +715,353 @@ void WingAngelAPI::installHexControllerAPI(asIScriptEngine *engine) { Q_ASSERT(r >= 0); Q_UNUSED(r); - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::switchDocument, - this, std::placeholders::_1), - "bool switchDocument(int handle)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, switchDocument, (int), bool), + "bool switchDocument(int handle)"); - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::setLockedFile, - this, std::placeholders::_1), - "bool setLockedFile(bool b)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::setKeepSize, this, - std::placeholders::_1), - "bool setKeepSize(bool b)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::setStringVisible, - this, std::placeholders::_1), - "bool setStringVisible(bool b)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::setAddressVisible, - this, std::placeholders::_1), - "bool setAddressVisible(bool b)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::setHeaderVisible, - this, std::placeholders::_1), - "bool setHeaderVisible(bool b)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::setAddressBase, - this, std::placeholders::_1), - "bool setAddressBase(" QPTR " base)"); - - registerAPI( + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, setLockedFile, (bool), bool), + "bool setLockedFile(bool b)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, setKeepSize, (bool), bool), + "bool setKeepSize(bool b)"); + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::beginMarco, this, - std::placeholders::_1), + asMETHODPR(WingHex::IWingPlugin, setStringVisible, (bool), bool), + "bool setStringVisible(bool b)"); + registerAPI( + engine, + asMETHODPR(WingHex::IWingPlugin, setAddressVisible, (bool), bool), + "bool setAddressVisible(bool b)"); + registerAPI( + engine, + asMETHODPR(WingHex::IWingPlugin, setHeaderVisible, (bool), bool), + "bool setHeaderVisible(bool b)"); + + registerAPI( + engine, + asMETHODPR(WingHex::IWingPlugin, setAddressBase, (quintptr), bool), + "bool setAddressBase(" QPTR " base)"); + + registerAPI( + engine, + asMETHODPR(WingHex::IWingPlugin, beginMarco, (const QString &), bool), "bool beginMarco(string &in name = \"\")"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, endMarco, (void), bool), + "bool endMarco()"); - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::endMarco, this), - "bool endMarco()"); - - registerAPI( + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::writeInt8, this, std::placeholders::_1, - std::placeholders::_2), + asMETHODPR(WingHex::IWingPlugin, writeInt8, (qsizetype, qint8), bool), "bool writeInt8(" QSIZETYPE " offset, int8 value)"); - - registerAPI( + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::writeUInt8, this, - std::placeholders::_1, std::placeholders::_2), + asMETHODPR(WingHex::IWingPlugin, writeUInt8, (qsizetype, quint8), bool), "bool writeUInt8(" QSIZETYPE " offset, uint8 value)"); - - registerAPI( + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::writeInt16, this, - std::placeholders::_1, std::placeholders::_2), + asMETHODPR(WingHex::IWingPlugin, writeInt16, (qsizetype, qint16), bool), "bool writeInt16(" QSIZETYPE " offset, int16 value)"); - - registerAPI( + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, writeUInt16, + (qsizetype, quint16), bool), + "bool writeUInt16(" QSIZETYPE " offset, uint16 value)"); + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::writeUInt16, this, - std::placeholders::_1, std::placeholders::_2), - "bool writeUInt16(" QSIZETYPE " offset, uint16 value)"); - - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::writeInt32, this, - std::placeholders::_1, std::placeholders::_2), + asMETHODPR(WingHex::IWingPlugin, writeInt32, (qsizetype, qint32), bool), "bool writeInt32(" QSIZETYPE " offset, int value)"); - - registerAPI( + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, writeUInt32, + (qsizetype, quint32), bool), + "bool writeUInt32(" QSIZETYPE " offset, uint value)"); + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::writeUInt32, this, - std::placeholders::_1, std::placeholders::_2), - "bool writeUInt32(" QSIZETYPE " offset, uint value)"); - - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::writeInt64, this, - std::placeholders::_1, std::placeholders::_2), + asMETHODPR(WingHex::IWingPlugin, writeInt64, (qsizetype, qint64), bool), "bool writeInt64(" QSIZETYPE " offset, int64 value)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, writeUInt64, + (qsizetype, quint64), bool), + "bool writeUInt64(" QSIZETYPE " offset, uint64 value)"); - registerAPI( + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::writeUInt64, this, - std::placeholders::_1, std::placeholders::_2), - "bool writeUInt64(" QSIZETYPE " offset, uint64 value)"); - - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::writeFloat, this, - std::placeholders::_1, std::placeholders::_2), + asMETHODPR(WingHex::IWingPlugin, writeFloat, (qsizetype, float), bool), "bool writeFloat(" QSIZETYPE " offset, float value)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, writeDouble, + (qsizetype, double), bool), + "bool writeDouble(" QSIZETYPE " offset, double value)"); - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::writeDouble, this, - std::placeholders::_1, std::placeholders::_2), - "bool writeDouble(" QSIZETYPE " offset, double value)"); + registerAPI(engine, + asMETHODPR(WingAngelAPI, _HexController_writeBytes, + (qsizetype, const CScriptArray &), bool), + "bool writeBytes(" QSIZETYPE " offset, byte[] &in data)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, writeString, + (qsizetype, const QString &, const QString &), bool), + "bool writeString(" QSIZETYPE " offset, string &in value, " + "string &in encoding = \"\")"); - registerAPI( + registerAPI( engine, - std::bind(&WingAngelAPI::_HexController_writeBytes, this, - std::placeholders::_1, std::placeholders::_2), - "bool writeBytes(" QSIZETYPE " offset, byte[] &in data)"); - - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::writeString, this, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3), - "bool writeString(" QSIZETYPE " offset, string &in value, " - "string &in encoding = \"\")"); - - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::insertInt8, this, - std::placeholders::_1, std::placeholders::_2), + asMETHODPR(WingHex::IWingPlugin, insertInt8, (qsizetype, qint8), bool), "bool insertInt8(" QSIZETYPE " offset, int8 value)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, insertUInt8, + (qsizetype, quint8), bool), + "bool insertUInt8(" QSIZETYPE " offset, uint8 value)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, insertInt16, + (qsizetype, qint16), bool), + "bool insertInt16(" QSIZETYPE " offset, int16 value)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, insertUInt16, + (qsizetype, quint16), bool), + "bool insertUInt16(" QSIZETYPE " offset, uint16 value)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, insertInt32, + (qsizetype, qint32), bool), + "bool insertInt32(" QSIZETYPE " offset, int value)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, insertUInt32, + (qsizetype, quint32), bool), + "bool insertUInt32(" QSIZETYPE " offset, uint value)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, insertInt64, + (qsizetype, qint64), bool), + "bool insertInt64(" QSIZETYPE " offset, int64 value)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, insertUInt64, + (qsizetype, quint64), bool), + "bool insertUInt64(" QSIZETYPE " offset, uint64 value)"); - registerAPI( + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::insertUInt8, this, - std::placeholders::_1, std::placeholders::_2), - "bool insertUInt8(" QSIZETYPE " offset, uint8 value)"); - - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::insertInt16, this, - std::placeholders::_1, std::placeholders::_2), - "bool insertInt16(" QSIZETYPE " offset, int16 value)"); - - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::insertUInt16, this, - std::placeholders::_1, std::placeholders::_2), - "bool insertUInt16(" QSIZETYPE " offset, uint16 value)"); - - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::insertInt32, this, - std::placeholders::_1, std::placeholders::_2), - "bool insertInt32(" QSIZETYPE " offset, int value)"); - - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::insertUInt32, this, - std::placeholders::_1, std::placeholders::_2), - "bool insertUInt32(" QSIZETYPE " offset, uint value)"); - - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::insertInt64, this, - std::placeholders::_1, std::placeholders::_2), - "bool insertInt64(" QSIZETYPE " offset, int64 value)"); - - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::insertUInt64, this, - std::placeholders::_1, std::placeholders::_2), - "bool insertUInt64(" QSIZETYPE " offset, uint64 value)"); - - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::insertFloat, this, - std::placeholders::_1, std::placeholders::_2), + asMETHODPR(WingHex::IWingPlugin, insertFloat, (qsizetype, float), bool), "bool insertFloat(" QSIZETYPE " offset, float value)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, insertDouble, + (qsizetype, double), bool), + "bool insertDouble(" QSIZETYPE " offset, double value)"); - registerAPI( + registerAPI(engine, + asMETHODPR(WingAngelAPI, _HexController_insertBytes, + (qsizetype, const CScriptArray &), bool), + "bool insertBytes(" QSIZETYPE " offset, byte[] &in data)"); + + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, insertString, + (qsizetype, const QString &, const QString &), bool), + "bool insertString(" QSIZETYPE " offset, string &in value, " + "string &in encoding = \"\")"); + + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, appendInt8, (qint8), bool), + "bool appendInt8(int8 value)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, appendUInt8, (quint8), bool), + "bool appendUInt8(uint8 value)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, appendInt16, (qint16), bool), + "bool appendInt16(int16 value)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, appendUInt16, (quint16), bool), + "bool appendUInt16(uint16 value)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, appendInt32, (qint32), bool), + "bool appendInt32(int value)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, appendUInt32, (quint32), bool), + "bool appendUInt32(uint value)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, appendInt64, (qint64), bool), + "bool appendInt64(int64 value)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, appendUInt64, (quint64), bool), + "bool appendUInt64(uint value)"); + + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, appendFloat, (float), bool), + "bool appendFloat(float value)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, appendDouble, (double), bool), + "bool appendDouble(double value)"); + + registerAPI(engine, + asMETHODPR(WingAngelAPI, _HexController_appendBytes, + (const CScriptArray &), bool), + "bool appendBytes(byte[] &in data)"); + + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::insertDouble, this, - std::placeholders::_1, std::placeholders::_2), - "bool insertDouble(" QSIZETYPE " offset, double value)"); - - registerAPI( - engine, - std::bind(&WingAngelAPI::_HexController_insertBytes, this, - std::placeholders::_1, std::placeholders::_2), - "bool insertBytes(" QSIZETYPE " offset, byte[] &in data)"); - - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::insertString, this, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3), - "bool insertString(" QSIZETYPE " offset, string &in value, " - "string &in encoding = \"\")"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::appendInt8, this, - std::placeholders::_1), - "bool appendInt8(int8 value)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::appendUInt8, - this, std::placeholders::_1), - "bool appendUInt8(uint8 value)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::appendInt16, - this, std::placeholders::_1), - "bool appendInt16(int16 value)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::appendUInt16, - this, std::placeholders::_1), - "bool appendUInt16(uint16 value)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::appendInt32, - this, std::placeholders::_1), - "bool appendInt32(int value)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::appendUInt32, - this, std::placeholders::_1), - "bool appendUInt32(uint value)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::appendInt64, - this, std::placeholders::_1), - "bool appendInt64(int64 value)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::appendUInt64, - this, std::placeholders::_1), - "bool appendUInt64(uint64 value)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::appendFloat, this, - std::placeholders::_1), - "bool appendFloat(float value)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::appendDouble, - this, std::placeholders::_1), - "bool appendDouble(double value)"); - - registerAPI( - engine, - std::bind(&WingAngelAPI::_HexController_appendBytes, this, - std::placeholders::_1), - "bool appendBytes(byte[] &in data)"); - - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::appendString, this, - std::placeholders::_1, std::placeholders::_2), + asMETHODPR(WingHex::IWingPlugin, appendString, + (const QString &, const QString &), bool), "bool appendString(string &in value, string &in encoding = \"\")"); - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::removeBytes, this, - std::placeholders::_1, std::placeholders::_2), - "bool removeBytes(" QSIZETYPE " offset, " QSIZETYPE " len)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, removeBytes, + (qsizetype, qsizetype), bool), + "bool removeBytes(" QSIZETYPE " offset, " QSIZETYPE " len)"); - registerAPI( + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, moveTo, + (qsizetype, qsizetype, int, bool), bool), + "bool moveTo(" QSIZETYPE " line, " QSIZETYPE + " column, int nibbleindex = -1, bool clearSelection = true)"); + registerAPI( engine, - std::bind(QOverload::of( - &WingHex::IWingPlugin::moveTo), - this, std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4), - "bool moveTo(" QSIZETYPE " line, " QSIZETYPE - " column, int nibbleindex = -1, bool clearSelection = true)"); - - registerAPI( - engine, - std::bind(QOverload::of(&WingHex::IWingPlugin::moveTo), - this, std::placeholders::_1, std::placeholders::_2), + asMETHODPR(WingHex::IWingPlugin, moveTo, (qsizetype, bool), bool), "bool moveTo(" QSIZETYPE " offset, bool clearSelection = true)"); - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::select, this, std::placeholders::_1, - std::placeholders::_2, std::placeholders::_3), - "bool select(" QSIZETYPE " offset, " QSIZETYPE - " len, SelectionMode mode = SelectionMode::Add)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, select, + (qsizetype, qsizetype, WingHex::SelectionMode), + bool), + "bool select(" QSIZETYPE " offset, " QSIZETYPE + " len, SelectionMode mode = SelectionMode::Add)"); - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::setInsertionMode, - this, std::placeholders::_1), - "bool setInsertionMode(bool b)"); - - registerAPI( + registerAPI( engine, - std::bind( - QOverload::of(&WingHex::IWingPlugin::metadata), - this, std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4, - std::placeholders::_5), + asMETHODPR(WingHex::IWingPlugin, setInsertionMode, (bool), bool), + "bool setInsertionMode(bool b)"); + + registerAPI( + engine, + asMETHODPR(WingHex::IWingPlugin, metadata, + (qsizetype, qsizetype, const QColor &, const QColor &, + const QString &), + bool), "bool metadata(" QSIZETYPE " begin, " QSIZETYPE " length, color &in fgcolor, color &in bgcolor, string &in comment)"); - registerAPI( + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::removeMetadata, this, - std::placeholders::_1), + asMETHODPR(WingHex::IWingPlugin, removeMetadata, (qsizetype), bool), "bool removeMetadata(" QSIZETYPE " offset)"); - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::clearMetadata, this), - "bool clearMetadata()"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, clearMetadata, (), bool), + "bool clearMetadata()"); - registerAPI( + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, foreground, + (qsizetype, qsizetype, const QColor &), bool), + "bool foreground(" QSIZETYPE " begin, " QSIZETYPE + " length, color &in fgcolor)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, background, + (qsizetype, qsizetype, const QColor &), bool), + "bool background(" QSIZETYPE " begin, " QSIZETYPE + " length, color &in bgcolor)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, comment, + (qsizetype, qsizetype, const QString &), bool), + "bool comment(" QSIZETYPE " begin, " QSIZETYPE + " length, string &in comment)"); + + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, setMetaVisible, (bool), bool), + "bool setMetaVisible(bool b)"); + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::foreground, this, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3), - "bool foreground(" QSIZETYPE " begin, " QSIZETYPE - " length, color &in fgcolor)"); - - registerAPI( + asMETHODPR(WingHex::IWingPlugin, setMetafgVisible, (bool), bool), + "bool setMetafgVisible(bool b)"); + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::background, this, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3), - "bool background(" QSIZETYPE " begin, " QSIZETYPE - " length, color &in bgcolor)"); - - registerAPI( + asMETHODPR(WingHex::IWingPlugin, setMetabgVisible, (bool), bool), + "bool setMetabgVisible(bool b)"); + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::comment, this, std::placeholders::_1, - std::placeholders::_2, std::placeholders::_3), - "bool comment(" QSIZETYPE " begin, " QSIZETYPE - " length, string &in comment)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::setMetaVisible, - this, std::placeholders::_1), - "bool setMetaVisible(bool b)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::setMetafgVisible, - this, std::placeholders::_1), - "bool setMetafgVisible(bool b)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::setMetabgVisible, - this, std::placeholders::_1), - "bool setMetabgVisible(bool b)"); - - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::setMetaCommentVisible, this, - std::placeholders::_1), + asMETHODPR(WingHex::IWingPlugin, setMetaCommentVisible, (bool), bool), "bool setMetaCommentVisible(bool b)"); - registerAPI( - engine, std::bind(&WingHex::IWingPlugin::newFile, this), - "ErrFile newFile()"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, newFile, (), WingHex::ErrFile), + "ErrFile newFile()"); - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::openFile, this, std::placeholders::_1), - "ErrFile openFile(string &in filename)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, openFile, (const QString &), + WingHex::ErrFile), + "ErrFile openFile(string &in filename)"); - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::openExtFile, this, - std::placeholders::_1, std::placeholders::_2), - "ErrFile openExtFile(string &in ext, string &in file)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, openExtFile, + (const QString &, const QString &), + WingHex::ErrFile), + "ErrFile openExtFile(string &in ext, string &in file)"); - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::closeFile, this, std::placeholders::_1, - std::placeholders::_2), - "ErrFile closeFile(int handle, bool force = false)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, closeFile, (int, bool), + WingHex::ErrFile), + "ErrFile closeFile(int handle, bool force = false)"); - registerAPI( + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::closeHandle, this, - std::placeholders::_1), + asMETHODPR(WingHex::IWingPlugin, closeHandle, (int), WingHex::ErrFile), "ErrFile closeHandle(int handle)"); - registerAPI( + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::saveFile, this, std::placeholders::_1), + asMETHODPR(WingHex::IWingPlugin, saveFile, (int), WingHex::ErrFile), "ErrFile saveFile(int handle)"); - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::exportFile, this, - std::placeholders::_1, std::placeholders::_2), - "ErrFile exportFile(int handle, string &in savename)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, exportFile, + (int, const QString &), WingHex::ErrFile), + "ErrFile exportFile(int handle, string &in savename)"); - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::saveAsFile, this, - std::placeholders::_1, std::placeholders::_2), - "ErrFile saveAsFile(int handle, string &in savename)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, saveAsFile, + (int, const QString &), WingHex::ErrFile), + "ErrFile saveAsFile(int handle, string &in savename)"); - registerAPI( - engine, std::bind(&WingHex::IWingPlugin::openCurrent, this), + registerAPI( + engine, + asMETHODPR(WingHex::IWingPlugin, openCurrent, (), WingHex::ErrFile), "ErrFile openCurrent()"); - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::closeCurrent, this, - std::placeholders::_1), - "ErrFile closeCurrent(bool force = false)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, closeCurrent, (bool), + WingHex::ErrFile), + "ErrFile closeCurrent(bool force = false)"); - registerAPI( - engine, std::bind(&WingHex::IWingPlugin::saveCurrent, this), + registerAPI( + engine, + asMETHODPR(WingHex::IWingPlugin, saveCurrent, (), WingHex::ErrFile), "ErrFile saveCurrent()"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, saveAsCurrent, + (const QString &), WingHex::ErrFile), + "ErrFile saveAsCurrent(string &in savename)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, exportCurrent, + (const QString &), WingHex::ErrFile), + "ErrFile exportCurrent(string &in savename)"); - registerAPI( + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, addBookMark, + (qsizetype, const QString &), bool), + "bool addBookMark(" QSIZETYPE " pos, string &in comment)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, modBookMark, + (qsizetype, const QString &), bool), + "bool modBookMark(" QSIZETYPE " pos, string &in comment)"); + registerAPI( engine, - std::bind(&WingHex::IWingPlugin::saveAsCurrent, this, - std::placeholders::_1), - "ErrFile saveAsCurrent(string &in savename)"); - - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::exportCurrent, this, - std::placeholders::_1), - "ErrFile exportCurrent(string &in savename)"); - - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::addBookMark, this, - std::placeholders::_1, std::placeholders::_2), - "bool addBookMark(" QSIZETYPE " pos, string &in comment)"); - - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::modBookMark, this, - std::placeholders::_1, std::placeholders::_2), - "bool modBookMark(" QSIZETYPE " pos, string &in comment)"); - - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::removeBookMark, this, - std::placeholders::_1), + asMETHODPR(WingHex::IWingPlugin, removeBookMark, (qsizetype), bool), "bool removeBookMark(" QSIZETYPE " pos)"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, clearBookMark, (), bool), + "bool clearBookMark()"); - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::clearBookMark, this), - "bool clearBookMark()"); + registerAPI(engine, + asMETHODPR(WingHex::IWingPlugin, openWorkSpace, + (const QString &), WingHex::ErrFile), + "ErrFile openWorkSpace(string &in filename)"); - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::openWorkSpace, this, - std::placeholders::_1), - "ErrFile openWorkSpace(string &in filename)"); - - registerAPI(engine, - std::bind(&WingHex::IWingPlugin::closeAllFiles, this), - "bool closeAll()"); - - engine->SetDefaultNamespace(""); -} - -void WingAngelAPI::installDataVisualAPI(asIScriptEngine *engine) { - int r = engine->SetDefaultNamespace("visual"); - Q_ASSERT(r >= 0); - Q_UNUSED(r); - - registerAPI( - engine, - std::bind(&WingHex::IWingPlugin::dataVisualText, this, - std::placeholders::_1, std::placeholders::_2), - "bool updateText(string &in data, string &in title=\"\")"); - - registerAPI( - engine, - std::bind(&WingAngelAPI::_DataVisual_updateTextList, this, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4), - "bool updateTextList(string[] &in data, string &in title=\"\", " - "ClickCallBack @clickfn = null, ClickCallBack @dblclick = null)"); - - registerAPI( - engine, - std::bind(&WingAngelAPI::_DataVisual_updateTextTree, this, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4), - "bool updateTextTree(string &in json, string &in title=\"\", " - "ClickCallBack @clickfn = null, ClickCallBack @dblclick = null)"); - - registerAPI( - engine, - std::bind(&WingAngelAPI::_DataVisual_updateTextTable, this, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4, - std::placeholders::_5, std::placeholders::_6), - "bool updateTextTable(string &in json, string[] &in headers, " - "string[] &in headerNames = {}, string &in title=\"\", " - "ClickCallBack @clickfn = null, ClickCallBack @dblclick = null)"); + registerAPI(engine, asMETHOD(WingHex::IWingPlugin, closeAllFiles), + "bool closeAll()"); engine->SetDefaultNamespace(""); } @@ -1357,6 +1149,14 @@ void WingAngelAPI::installScriptEnums(asIScriptEngine *engine) { } } +void WingAngelAPI::registerAPI(asIScriptEngine *engine, const asSFuncPtr &fn, + const char *sig) { + auto r = + engine->RegisterGlobalFunction(sig, fn, asCALL_THISCALL_ASGLOBAL, this); + Q_ASSERT(r >= 0); + Q_UNUSED(r); +} + QStringList WingAngelAPI::cArray2QStringList(const CScriptArray &array, int stringID, bool *ok) { bool b = array.GetElementTypeId() == stringID; @@ -2247,42 +2047,6 @@ void WingAngelAPI::cleanUpHandles(const QVector &handles) { _handles = handles; } -QString WingAngelAPI::_InputBox_getItem(const QString &title, - const QString &label, - const CScriptArray &items, int current, - bool editable, bool *ok, - Qt::InputMethodHints inputMethodHints) { - asIScriptContext *ctx = asGetActiveContext(); - if (ctx) { - auto engine = ctx->GetEngine(); - Q_ASSERT(engine); - auto stringID = engine->GetTypeIdByDecl("string"); - Q_ASSERT(stringID >= 0); - - bool o = false; - auto ret = cArray2QStringList(items, stringID, &o); - if (o) { - return WingInputDialog::getItem(nullptr, title, label, ret, current, - editable, ok, inputMethodHints); - } else { - *ok = false; - return {}; - } - } - return {}; -} - -CScriptArray *WingAngelAPI::_FileDialog_getOpenFileNames( - const QString &caption, const QString &dir, const QString &filter, - QString *selectedFilter, QFileDialog::Options options) { - return retarrayWrapperFunction( - [&]() -> QStringList { - return WingFileDialog::getOpenFileNames( - nullptr, caption, dir, filter, selectedFilter, options); - }, - "array"); -} - CScriptArray *WingAngelAPI::_HexReader_selectedBytes(qsizetype index) { return byteArrayWrapperFunction( [this, index]() -> QByteArray { return selectedBytes(index); }); @@ -2422,10 +2186,78 @@ bool WingAngelAPI::_HexController_appendBytes(const CScriptArray &ba) { return false; } -bool WingAngelAPI::_DataVisual_updateTextList(const CScriptArray &data, - const QString &title, - asIScriptFunction *click, - asIScriptFunction *dblclick) { +void WingAngelAPI::_UI_Toast(const QString &message, const QString &icon) { + toast(QPixmap(icon), message); +} + +QColor WingAngelAPI::_Color_get(const QString &caption) { + return dlgGetColor(caption); +} + +void WingAngelAPI::_MSG_AboutQt(const QString &title) { + msgAboutQt(nullptr, title); +} + +QMessageBox::StandardButton +WingAngelAPI::_MSG_Information(const QString &title, const QString &text, + QMessageBox::StandardButtons buttons, + QMessageBox::StandardButton defaultButton) { + return msgInformation(nullptr, title, text, buttons, defaultButton); +} + +QMessageBox::StandardButton +WingAngelAPI::_MSG_Question(const QString &title, const QString &text, + QMessageBox::StandardButtons buttons, + QMessageBox::StandardButton defaultButton) { + return msgQuestion(nullptr, title, text, buttons, defaultButton); +} + +QMessageBox::StandardButton +WingAngelAPI::_MSG_Warning(const QString &title, const QString &text, + QMessageBox::StandardButtons buttons, + QMessageBox::StandardButton defaultButton) { + return msgWarning(nullptr, title, text, buttons, defaultButton); +} + +QMessageBox::StandardButton +WingAngelAPI::_MSG_Critical(const QString &title, const QString &text, + QMessageBox::StandardButtons buttons, + QMessageBox::StandardButton defaultButton) { + return msgCritical(nullptr, title, text, buttons, defaultButton); +} + +void WingAngelAPI::_MSG_About(const QString &title, const QString &text) { + return msgAbout(nullptr, title, text); +} + +QMessageBox::StandardButton +WingAngelAPI::_MSG_msgbox(QMessageBox::Icon icon, const QString &title, + const QString &text, + QMessageBox::StandardButtons buttons, + QMessageBox::StandardButton defaultButton) { + return msgbox(nullptr, icon, title, text, buttons, defaultButton); +} + +QString WingAngelAPI::_InputBox_GetText(const QString &title, + const QString &label, + QLineEdit::EchoMode echo, + const QString &text, bool *ok, + Qt::InputMethodHints inputMethodHints) { + return dlgGetText(nullptr, title, label, echo, text, ok, inputMethodHints); +} + +QString WingAngelAPI::_InputBox_GetMultiLineText( + const QString &title, const QString &label, const QString &text, bool *ok, + Qt::InputMethodHints inputMethodHints) { + return dlgGetMultiLineText(nullptr, title, label, text, ok, + inputMethodHints); +} + +QString WingAngelAPI::_InputBox_getItem(const QString &title, + const QString &label, + const CScriptArray &items, int current, + bool editable, bool *ok, + Qt::InputMethodHints inputMethodHints) { asIScriptContext *ctx = asGetActiveContext(); if (ctx) { auto engine = ctx->GetEngine(); @@ -2433,65 +2265,60 @@ bool WingAngelAPI::_DataVisual_updateTextList(const CScriptArray &data, auto stringID = engine->GetTypeIdByDecl("string"); Q_ASSERT(stringID >= 0); - // we dont call visual.updateTextList bool o = false; - auto ret = cArray2QStringList(data, stringID, &o); + auto ret = cArray2QStringList(items, stringID, &o); if (o) { - ClickCallBack c(engine, click); - ClickCallBack dblc(engine, dblclick); - - return PluginSystem::instance().updateTextList_API(ret, title, c, - dblc); + return WingInputDialog::getItem(nullptr, title, label, ret, current, + editable, ok, inputMethodHints); + } else { + *ok = false; + return {}; } } - return false; + return {}; } -bool WingAngelAPI::_DataVisual_updateTextTree(const QString &json, - const QString &title, - asIScriptFunction *click, - asIScriptFunction *dblclick) { - asIScriptContext *ctx = asGetActiveContext(); - if (ctx) { - auto engine = ctx->GetEngine(); - Q_ASSERT(engine); - - // we dont call visual.updateTextTree - ClickCallBack c(engine, click); - ClickCallBack dblc(engine, dblclick); - - return PluginSystem::instance().updateTextTree_API(json, title, c, - dblc); - } - return false; +int WingAngelAPI::_InputBox_GetInt(const QString &title, const QString &label, + int value, int minValue, int maxValue, + int step, bool *ok) { + return dlgGetInt(nullptr, title, label, value, minValue, maxValue, step, + ok); } -bool WingAngelAPI::_DataVisual_updateTextTable(const QString &json, - const CScriptArray &headers, - const CScriptArray &headerNames, - const QString &title, - asIScriptFunction *click, - asIScriptFunction *dblclick) { - asIScriptContext *ctx = asGetActiveContext(); - if (ctx) { - auto engine = ctx->GetEngine(); - Q_ASSERT(engine); - auto stringID = engine->GetTypeIdByDecl("string"); - Q_ASSERT(stringID >= 0); - - // we dont call visual.updateTextTable - bool o = false; - auto h = cArray2QStringList(headers, stringID, &o); - if (o) { - auto hn = cArray2QStringList(headerNames, stringID, &o); - if (o) { - ClickCallBack c(engine, click); - ClickCallBack dblc(engine, dblclick); - - return PluginSystem::instance().updateTextTable_API( - json, h, hn, title, c, dblc); - } - } - } - return false; +double WingAngelAPI::_InputBox_GetDouble(const QString &title, + const QString &label, double value, + double minValue, double maxValue, + int decimals, bool *ok, double step) { + return dlgGetDouble(nullptr, title, label, value, minValue, maxValue, + decimals, ok, step); +} + +QString WingAngelAPI::_FileDialog_GetExistingDirectory( + const QString &caption, const QString &dir, QFileDialog::Options options) { + return dlgGetExistingDirectory(nullptr, caption, dir, options); +} + +QString WingAngelAPI::_FileDialog_GetOpenFileName( + const QString &caption, const QString &dir, const QString &filter, + QString *selectedFilter, QFileDialog::Options options) { + return dlgGetOpenFileName(nullptr, caption, dir, filter, selectedFilter, + options); +} + +CScriptArray *WingAngelAPI::_FileDialog_getOpenFileNames( + const QString &caption, const QString &dir, const QString &filter, + QString *selectedFilter, QFileDialog::Options options) { + return retarrayWrapperFunction( + [&]() -> QStringList { + return WingFileDialog::getOpenFileNames( + nullptr, caption, dir, filter, selectedFilter, options); + }, + "array"); +} + +QString WingAngelAPI::_FileDialog_GetSaveFileName( + const QString &caption, const QString &dir, const QString &filter, + QString *selectedFilter, QFileDialog::Options options) { + return dlgGetSaveFileName(nullptr, caption, dir, filter, selectedFilter, + options); } diff --git a/src/class/wingangelapi.h b/src/class/wingangelapi.h index 2a55fb0..3e49fac 100644 --- a/src/class/wingangelapi.h +++ b/src/class/wingangelapi.h @@ -23,9 +23,7 @@ #include -#include #include -#include class asIScriptEngine; class ScriptMachine; @@ -97,25 +95,13 @@ private: void installHexBaseType(asIScriptEngine *engine); void installHexReaderAPI(asIScriptEngine *engine); void installHexControllerAPI(asIScriptEngine *engine); - void installDataVisualAPI(asIScriptEngine *engine); void installScriptFns(asIScriptEngine *engine); void installScriptUnSafeFns(asIScriptEngine *engine); void installScriptEnums(asIScriptEngine *engine); private: - template - void registerAPI(asIScriptEngine *engine, const std::function &fn, - const char *sig) { - _fnbuffer.push_back(fn); - auto r = engine->RegisterGlobalFunction( - sig, asMETHOD(std::function, operator()), - asCALL_THISCALL_ASGLOBAL, - std::any_cast>(&_fnbuffer.back())); - Q_ASSERT(r >= 0); - Q_UNUSED(r); - } - - using WrapperFn = std::function; + void registerAPI(asIScriptEngine *engine, const asSFuncPtr &fn, + const char *sig); private: QStringList cArray2QStringList(const CScriptArray &array, int stringID, @@ -203,17 +189,6 @@ private: void cleanUpHandles(const QVector &handles); private: - QString _InputBox_getItem(const QString &title, const QString &label, - const CScriptArray &items, int current, - bool editable, bool *ok, - Qt::InputMethodHints inputMethodHints); - - CScriptArray *_FileDialog_getOpenFileNames(const QString &caption, - const QString &dir, - const QString &filter, - QString *selectedFilter, - QFileDialog::Options options); - CScriptArray *_HexReader_selectedBytes(qsizetype index); CScriptArray *_HexReader_selectionBytes(); @@ -230,26 +205,86 @@ private: bool _HexController_appendBytes(const CScriptArray &ba); -private: - bool _DataVisual_updateTextList(const CScriptArray &data, - const QString &title, - asIScriptFunction *click, - asIScriptFunction *dblclick); + void _UI_Toast(const QString &message, const QString &icon); - bool _DataVisual_updateTextTree(const QString &json, const QString &title, - asIScriptFunction *click, - asIScriptFunction *dblclick); - - bool _DataVisual_updateTextTable(const QString &json, - const CScriptArray &headers, - const CScriptArray &headerNames, - const QString &title, - asIScriptFunction *click, - asIScriptFunction *dblclick); + QColor _Color_get(const QString &caption); private: - std::vector _fnbuffer; + void _MSG_AboutQt(const QString &title); + QMessageBox::StandardButton + _MSG_Information(const QString &title, const QString &text, + QMessageBox::StandardButtons buttons, + QMessageBox::StandardButton defaultButton); + + QMessageBox::StandardButton + _MSG_Question(const QString &title, const QString &text, + QMessageBox::StandardButtons buttons, + QMessageBox::StandardButton defaultButton); + + QMessageBox::StandardButton + _MSG_Warning(const QString &title, const QString &text, + QMessageBox::StandardButtons buttons, + QMessageBox::StandardButton defaultButton); + + QMessageBox::StandardButton + _MSG_Critical(const QString &title, const QString &text, + QMessageBox::StandardButtons buttons, + QMessageBox::StandardButton defaultButton); + + void _MSG_About(const QString &title, const QString &text); + + QMessageBox::StandardButton + _MSG_msgbox(QMessageBox::Icon icon, const QString &title, + const QString &text, QMessageBox::StandardButtons buttons, + QMessageBox::StandardButton defaultButton); + +private: + QString _InputBox_GetText(const QString &title, const QString &label, + QLineEdit::EchoMode echo, const QString &text, + bool *ok, Qt::InputMethodHints inputMethodHints); + + QString _InputBox_GetMultiLineText(const QString &title, + const QString &label, + const QString &text, bool *ok, + Qt::InputMethodHints inputMethodHints); + + QString _InputBox_getItem(const QString &title, const QString &label, + const CScriptArray &items, int current, + bool editable, bool *ok, + Qt::InputMethodHints inputMethodHints); + + int _InputBox_GetInt(const QString &title, const QString &label, int value, + int minValue, int maxValue, int step, bool *ok); + + double _InputBox_GetDouble(const QString &title, const QString &label, + double value, double minValue, double maxValue, + int decimals, bool *ok, double step); + +private: + QString _FileDialog_GetExistingDirectory(const QString &caption, + const QString &dir, + QFileDialog::Options options); + + QString _FileDialog_GetOpenFileName(const QString &caption, + const QString &dir, + const QString &filter, + QString *selectedFilter, + QFileDialog::Options options); + + CScriptArray *_FileDialog_getOpenFileNames(const QString &caption, + const QString &dir, + const QString &filter, + QString *selectedFilter, + QFileDialog::Options options); + + QString _FileDialog_GetSaveFileName(const QString &caption, + const QString &dir, + const QString &filter, + QString *selectedFilter, + QFileDialog::Options options); + +private: QVector _sfns; QHash> _rfns; diff --git a/src/components.md b/src/components.md index aee5214..b955e62 100644 --- a/src/components.md +++ b/src/components.md @@ -13,5 +13,4 @@ The following components are all third-party components used by the software. Th * [cpptrace](https://github.com/jeremy-rifkin/cpptrace) (MIT) * [QConsoleWidget](https://github.com/gapost/qconsolewidget) (MIT, **FORK** -> AGPL-3.0) * [QColorPicker](https://github.com/arsdever/qcolorpicker) (MIT) -* [QtJsonModel](https://github.com/dridk/QJsonmodel) (MIT) * [Qt](https://www.qt.io/) (LGPL) diff --git a/src/dialog/mainwindow.cpp b/src/dialog/mainwindow.cpp index 07950fc..136334d 100644 --- a/src/dialog/mainwindow.cpp +++ b/src/dialog/mainwindow.cpp @@ -565,7 +565,6 @@ void MainWindow::buildUpDockSystem(QWidget *container) { qApp->processEvents(); } - buildUpVisualDataDock(m_dock, ads::CenterDockWidgetArea, bottomLeftArea); qApp->processEvents(); m_bottomViewArea = bottomRightArea; @@ -1029,265 +1028,6 @@ MainWindow::buildUpScriptBgOutputDock(ads::CDockManager *dock, return dock->addDockWidget(area, dw, areaw); } -ads::CDockAreaWidget * -MainWindow::buildUpVisualDataDock(ads::CDockManager *dock, - ads::DockWidgetArea area, - ads::CDockAreaWidget *areaw) { - using namespace ads; - - auto efilter = new EventFilter(QEvent::DynamicPropertyChange, this); - connect(efilter, &EventFilter::eventTriggered, this, - [](QObject *obj, QEvent *event) { - auto e = static_cast(event); - constexpr auto ppname = "__TITLE__"; - if (e->propertyName() == QByteArray(ppname)) { - auto title = obj->property(ppname).toString(); - auto display = obj->property("__DISPLAY__").toString(); - auto dock = reinterpret_cast( - obj->property("__DOCK__").value()); - if (dock) { - if (!title.isEmpty()) { - display += QStringLiteral("(") + title + - QStringLiteral(")"); - } - dock->setWindowTitle(display); - } - } - }); - - constexpr auto dpname = "__DISPLAY__"; - constexpr auto dockpname = "__DOCK__"; - - m_infolist = new QListView(this); - m_infolist->setEditTriggers(QListView::EditTrigger::NoEditTriggers); - connect(m_infolist, &QListView::clicked, this, - [this](const QModelIndex &index) { - if (m_infoclickfn) { - m_infoclickfn(index); - } - }); - connect(m_infolist, &QListView::doubleClicked, this, - [this](const QModelIndex &index) { - if (m_infodblclickfn) { - m_infodblclickfn(index); - } - }); - auto dw = buildDockWidget(dock, QStringLiteral("DVList"), tr("DVList"), - m_infolist); - m_infolist->setProperty(dpname, tr("DVList")); - m_infolist->setProperty(dockpname, quintptr(dw)); - m_infolist->installEventFilter(efilter); - m_infolist->setContextMenuPolicy(Qt::ActionsContextMenu); - m_infolist->addAction( - newAction(QStringLiteral("copy"), tr("Copy"), [this]() { - auto idx = m_infolist->currentIndex(); - if (idx.isValid()) { - qApp->clipboard()->setText( - m_infolist->model()->data(idx).toString()); - Toast::toast(this, NAMEICONRES(QStringLiteral("copy")), - tr("CopyToClipBoard")); - } - })); - m_infolist->addAction( - newAction(QStringLiteral("export"), tr("ExportResult"), [this]() { - auto model = m_infotable->model(); - if (!model) { - Toast::toast(this, NAMEICONRES(QStringLiteral("save")), - tr("NothingToSave")); - return; - } - - auto filename = WingFileDialog::getSaveFileName( - this, tr("ChooseSaveFile"), m_lastusedpath, - QStringLiteral("TXT (*.txt)")); - if (filename.isEmpty()) { - return; - } - QFile f(filename); - if (!f.open(QFile::WriteOnly | QFile::Text)) { - WingMessageBox::critical(this, tr("Error"), - tr("FilePermission")); - return; - } - - auto total = model->rowCount(); - for (int i = 0; i < total; ++i) { - f.write(model->data(model->index(i, 0)).toString().toUtf8()); - f.write("\n"); - } - f.close(); - Toast::toast(this, NAMEICONRES(QStringLiteral("save")), - tr("SaveSuccessfully")); - })); - m_infolist->addAction( - newAction(QStringLiteral("del"), tr("ClearResult"), [this]() { - auto model = m_infolist->model(); - model->removeRows(0, model->rowCount()); - m_infolist->setProperty("__TITLE__", {}); - })); - auto ar = dock->addDockWidget(area, dw, areaw); - - m_infotree = new QTreeView(this); - m_infotree->setEditTriggers(QTreeView::EditTrigger::NoEditTriggers); - connect(m_infotree, &QTreeView::clicked, this, - [this](const QModelIndex &index) { - if (m_infotreeclickfn) { - m_infotreeclickfn(index); - } - }); - connect(m_infotree, &QTreeView::doubleClicked, this, - [this](const QModelIndex &index) { - if (m_infotreedblclickfn) { - m_infotreedblclickfn(index); - } - }); - dw = buildDockWidget(dock, QStringLiteral("DVTree"), tr("DVTree"), - m_infotree); - m_infotree->setProperty(dpname, tr("DVTree")); - m_infotree->setProperty(dockpname, quintptr(dw)); - m_infotree->installEventFilter(efilter); - m_infotree->setContextMenuPolicy(Qt::ActionsContextMenu); - m_infotree->addAction( - newAction(QStringLiteral("copy"), tr("Copy"), [this]() { - auto idx = m_infotree->currentIndex(); - if (idx.isValid()) { - qApp->clipboard()->setText( - m_infotree->model()->data(idx).toString()); - Toast::toast(this, NAMEICONRES(QStringLiteral("copy")), - tr("CopyToClipBoard")); - } - })); - m_infotree->addAction( - newAction(QStringLiteral("export"), tr("ExportResult"), [this]() { - auto model = m_infotable->model(); - if (!model) { - Toast::toast(this, NAMEICONRES(QStringLiteral("save")), - tr("NothingToSave")); - return; - } - - auto filename = WingFileDialog::getSaveFileName( - this, tr("ChooseSaveFile"), m_lastusedpath, - QStringLiteral("Json (*.json)")); - if (filename.isEmpty()) { - return; - } - - QJsonArray rootArray; - for (int row = 0; row < model->rowCount(); ++row) { - QModelIndex index = model->index(row, 0); - rootArray.append(extractModelData(model, index)); - } - - QJsonDocument jsonDocument(rootArray); - QFile file(filename); - if (!file.open(QFile::WriteOnly | QFile::Text)) { - WingMessageBox::critical(this, tr("Error"), - tr("FilePermission")); - return; - } - - file.write(jsonDocument.toJson(QJsonDocument::Indented)); - file.close(); - Toast::toast(this, NAMEICONRES(QStringLiteral("save")), - tr("SaveSuccessfully")); - })); - m_infotree->addAction( - newAction(QStringLiteral("del"), tr("ClearResult"), [this]() { - auto model = m_infotree->model(); - model->removeRows(0, model->rowCount()); - m_infotree->setProperty("__TITLE__", {}); - })); - dock->addDockWidget(CenterDockWidgetArea, dw, ar); - - m_infotable = new QTableView(this); - m_infotable->setEditTriggers(QTableView::EditTrigger::NoEditTriggers); - connect(m_infotable, &QTableView::clicked, this, - [this](const QModelIndex &index) { - if (m_infotableclickfn) { - m_infotableclickfn(index); - } - }); - connect(m_infotable, &QTableView::doubleClicked, this, - [this](const QModelIndex &index) { - if (m_infotabledblclickfn) { - m_infotabledblclickfn(index); - } - }); - dw = buildDockWidget(dock, QStringLiteral("DVTable"), tr("DVTable"), - m_infotable); - m_infotable->setProperty(dpname, tr("DVTable")); - m_infotable->setProperty(dockpname, quintptr(dw)); - m_infotable->installEventFilter(efilter); - m_infotable->setContextMenuPolicy(Qt::ActionsContextMenu); - m_infotable->addAction( - newAction(QStringLiteral("copy"), tr("Copy"), [this]() { - auto idx = m_infotable->currentIndex(); - if (idx.isValid()) { - qApp->clipboard()->setText( - m_infotable->model()->data(idx).toString()); - Toast::toast(this, NAMEICONRES(QStringLiteral("copy")), - tr("CopyToClipBoard")); - } - })); - m_infotable->addAction( - newAction(QStringLiteral("export"), tr("ExportResult"), [this]() { - auto model = m_infotable->model(); - saveTableContent(model); - })); - m_infotable->addAction( - newAction(QStringLiteral("del"), tr("ClearResult"), [this]() { - auto model = m_infotable->model(); - model->removeRows(0, model->rowCount()); - m_infotable->setProperty("__TITLE__", {}); - })); - dock->addDockWidget(CenterDockWidgetArea, dw, ar); - - m_infotxt = new QTextBrowser(this); - dw = buildDockWidget(dock, QStringLiteral("DVText"), tr("DVText"), - m_infotxt); - m_infotxt->setProperty(dpname, tr("DVText")); - m_infotxt->setProperty(dockpname, quintptr(dw)); - m_infotxt->installEventFilter(efilter); - m_infotxt->setContextMenuPolicy(Qt::CustomContextMenu); - auto menu = m_infotxt->createStandardContextMenu(); - menu->addSeparator(); - menu->addAction( - newAction(QStringLiteral("export"), tr("ExportResult"), [this]() { - auto filename = WingFileDialog::getSaveFileName( - this, tr("ChooseSaveFile"), m_lastusedpath, - QStringLiteral("TXT (*.txt)")); - if (filename.isEmpty()) { - return; - } - - QFile file(filename); - if (!file.open(QFile::WriteOnly | QFile::Text)) { - WingMessageBox::critical(this, tr("Error"), - tr("FilePermission")); - return; - } - - file.write(m_infotxt->toPlainText().toUtf8()); - - Toast::toast(this, NAMEICONRES(QStringLiteral("save")), - tr("SaveSuccessfully")); - })); - menu->addAction( - newAction(QStringLiteral("del"), tr("ClearResult"), [this]() { - m_infotxt->clear(); - m_infotxt->setProperty("__TITLE__", {}); - })); - connect(m_infotxt, &QTextBrowser::customContextMenuRequested, this, - [=](const QPoint &pos) { - menu->popup(m_infotxt->viewport()->mapToGlobal(pos)); - }); - - dock->addDockWidget(CenterDockWidgetArea, dw, ar); - - return ar; -} - RibbonTabContent *MainWindow::buildFilePage(RibbonTabContent *tab) { auto shortcuts = QKeySequences::instance(); { @@ -4035,32 +3775,6 @@ void MainWindow::onOutputBgScriptOutput( lastInfo.second = qMakePair(message.row, message.col); } -QJsonObject MainWindow::extractModelData(const QAbstractItemModel *model, - const QModelIndex &parent) { - QJsonObject jsonObject; - - // Add data for the current row - for (int col = 0; col < model->columnCount(parent); ++col) { - QVariant data = - model->data(model->index(parent.row(), col, parent.parent())); - QString header = model->headerData(col, Qt::Horizontal).toString(); - jsonObject[header.isEmpty() ? tr("Column %1").arg(col) : header] = - data.toString(); - } - - // Recursively add child rows - QJsonArray children; - for (int row = 0; row < model->rowCount(parent); ++row) { - QModelIndex childIndex = model->index(row, 0, parent); - children.append(extractModelData(model, childIndex)); - } - - if (!children.isEmpty()) - jsonObject["children"] = children; - - return jsonObject; -} - void MainWindow::closeEvent(QCloseEvent *event) { // plugin first checking diff --git a/src/dialog/mainwindow.h b/src/dialog/mainwindow.h index 04c5a64..a900c2e 100644 --- a/src/dialog/mainwindow.h +++ b/src/dialog/mainwindow.h @@ -43,7 +43,6 @@ #include "Qt-Advanced-Docking-System/src/DockManager.h" #include "Qt-Advanced-Docking-System/src/DockWidget.h" #include "WingPlugin/iwingplugin.h" -#include "class/clickcallback.h" #include "class/recentfilemanager.h" #include "class/scriptmanager.h" #include "control/editorview.h" @@ -64,9 +63,6 @@ class MainWindow : public FramelessMainWindow { friend class PluginSystem; - using ClickedCallBack = ClickCallBack; - using DblClickedCallBack = ClickCallBack; - public: explicit MainWindow(SplashDialog *splash); virtual ~MainWindow() override; @@ -125,9 +121,6 @@ private: ads::CDockAreaWidget * buildUpScriptBgOutputDock(ads::CDockManager *dock, ads::DockWidgetArea area, ads::CDockAreaWidget *areaw = nullptr); - ads::CDockAreaWidget * - buildUpVisualDataDock(ads::CDockManager *dock, ads::DockWidgetArea area, - ads::CDockAreaWidget *areaw = nullptr); RibbonTabContent *buildFilePage(RibbonTabContent *tab); RibbonTabContent *buildEditPage(RibbonTabContent *tab); @@ -268,10 +261,6 @@ private: void onOutputBgScriptOutput(const ScriptMachine::MessageInfo &message); -private: - QJsonObject extractModelData(const QAbstractItemModel *model, - const QModelIndex &parent = QModelIndex()); - protected: virtual void closeEvent(QCloseEvent *event) override; @@ -507,20 +496,6 @@ private: QTableViewExt *m_metadatas = nullptr; MetaDataModel *_metadataEmpty = nullptr; - // data visualization widgets - QListView *m_infolist = nullptr; - ClickedCallBack m_infoclickfn; - DblClickedCallBack m_infodblclickfn; - - QTreeView *m_infotree = nullptr; - ClickedCallBack m_infotreeclickfn; - DblClickedCallBack m_infotreedblclickfn; - - QTableView *m_infotable = nullptr; - QTextBrowser *m_infotxt = nullptr; - ClickedCallBack m_infotableclickfn; - DblClickedCallBack m_infotabledblclickfn; - QMap m_toolBtneditors; QAction *m_aDelBookMark = nullptr; diff --git a/src/model/qjsontablemodel.cpp b/src/model/qjsontablemodel.cpp deleted file mode 100644 index d74a0e3..0000000 --- a/src/model/qjsontablemodel.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/*============================================================================== -** 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 "qjsontablemodel.h" -#include - -QJsonTableModel::QJsonTableModel(const QJsonTableModel::Header &header, - QObject *parent) - : QAbstractTableModel(parent), m_header(header) {} - -bool QJsonTableModel::setJson(const QJsonDocument &json) { - return setJson(json.array()); -} - -bool QJsonTableModel::setJson(const QJsonArray &array) { - beginResetModel(); - m_json = array; - endResetModel(); - return true; -} - -QVariant QJsonTableModel::headerData(int section, Qt::Orientation orientation, - int role) const { - if (role != Qt::DisplayRole) { - return QVariant(); - } - - switch (orientation) { - case Qt::Horizontal: - return m_header[section]["title"]; - case Qt::Vertical: - // return section + 1; - return QVariant(); - default: - return QVariant(); - } -} - -int QJsonTableModel::rowCount(const QModelIndex &parent) const { - Q_UNUSED(parent); - return m_json.size(); -} - -int QJsonTableModel::columnCount(const QModelIndex &parent) const { - Q_UNUSED(parent); - return m_header.size(); -} - -QJsonObject QJsonTableModel::getJsonObject(const QModelIndex &index) const { - const QJsonValue &value = m_json[index.row()]; - return value.toObject(); -} - -QVariant QJsonTableModel::data(const QModelIndex &index, int role) const { - switch (role) { - case Qt::DisplayRole: { - QJsonObject obj = getJsonObject(index); - const QString &key = m_header[index.column()]["index"]; - if (obj.contains(key)) { - QJsonValue v = obj[key]; - - if (v.isString()) { - return v.toString(); - } else if (v.isDouble()) { - return QString::number(v.toDouble()); - } else { - return QVariant(); - } - } else { - return QVariant(); - } - } - case Qt::ToolTipRole: - return QVariant(); - default: - return QVariant(); - } -} diff --git a/src/model/qjsontablemodel.h b/src/model/qjsontablemodel.h deleted file mode 100644 index ead3e9a..0000000 --- a/src/model/qjsontablemodel.h +++ /dev/null @@ -1,51 +0,0 @@ -/*============================================================================== -** 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 QJSONTABLEMODEL_H -#define QJSONTABLEMODEL_H - -#include -#include -#include -#include -#include -#include - -class QJsonTableModel : public QAbstractTableModel { -public: - typedef QHash Heading; - typedef QVector Header; - QJsonTableModel(const Header &header, QObject *parent = 0); - - bool setJson(const QJsonDocument &json); - bool setJson(const QJsonArray &array); - - virtual QJsonObject getJsonObject(const QModelIndex &index) const; - - virtual QVariant headerData(int section, Qt::Orientation orientation, - int role = Qt::DisplayRole) const; - virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; - virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; - virtual QVariant data(const QModelIndex &index, - int role = Qt::DisplayRole) const; - -private: - Header m_header; - QJsonArray m_json; -}; - -#endif // QJSONTABLEMODEL_H