feat: 移除数据可视化功能以轻量化;优化 WingAngelAPI 脚本注册;

This commit is contained in:
寂静的羽夏 2025-04-10 12:51:13 +08:00
parent d6680e3f11
commit f51630c6f0
29 changed files with 1379 additions and 3895 deletions

View File

@ -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

View File

@ -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 <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)

View File

@ -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.

View File

@ -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 <QDebug>
#include <QFile>
#include <QFont>
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<QJsonTreeItem *>(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<uchar *>(const_cast<char *>(ba.constData()));
const uchar *ba_end = cursor + ba.length();
const ushort *src = reinterpret_cast<const ushort *>(s.constBegin());
const ushort *const end = reinterpret_cast<const ushort *>(s.constEnd());
while (src != end) {
if (cursor >= ba_end - 6) {
// ensure we have enough space
int pos = cursor - reinterpret_cast<const uchar *>(ba.constData());
ba.resize(ba.size() * 2);
cursor = reinterpret_cast<uchar *>(ba.data()) + pos;
ba_end =
reinterpret_cast<const uchar *>(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<QUtf8BaseTraits>(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<const uchar *>(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<QJsonTreeItem *>(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<QJsonTreeItem *>(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<QJsonTreeItem *>(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<QJsonTreeItem *>(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<QJsonTreeItem *>(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<QJsonTreeItem *>(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;
}
}

View File

@ -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 <URL>
```
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")
```

View File

@ -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 <QAbstractItemModel>
#include <QIcon>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#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<QJsonTreeItem *> 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;
};

View File

@ -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 <QJsonValue>
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 <typename Traits, typename OutputPtr, typename InputPtr>
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 <typename Traits, typename OutputPtr, typename InputPtr>
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; }
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

View File

@ -79,7 +79,6 @@ add_subdirectory(3rdparty/QHexView)
add_subdirectory(3rdparty/WingCodeEdit)
add_subdirectory(3rdparty/Qt-Advanced-Docking-System)
add_subdirectory(3rdparty/AngelScript/sdk/angelscript/projects/cmake)
add_subdirectory(3rdparty/QJsonModel)
set(ANGEL_SCRIPT_ADDON_ROOT
"${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/AngelScript/sdk/add_on")
@ -272,7 +271,6 @@ set(CLASS_SRC
src/class/dockcomponentsfactory.cpp
src/class/diffutil.h
src/class/diffutil.cpp
src/class/clickcallback.h
src/class/crashhandler.h
src/class/crashhandler.cpp
src/class/pluginsystem.h
@ -315,8 +313,6 @@ set(MODEL_SRC
src/model/metadatamodel.cpp
src/model/checksummodel.h
src/model/checksummodel.cpp
src/model/qjsontablemodel.h
src/model/qjsontablemodel.cpp
src/model/dbgcallstackmodel.h
src/model/dbgcallstackmodel.cpp
src/model/dbgvarshowmodel.h
@ -380,7 +376,6 @@ endforeach()
set(TRANSLATION_PATH
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/QConsoleWidget
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/QHexView
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/QJsonModel
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/Qt-Advanced-Docking-System/src
${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/QWingRibbon
${CMAKE_CURRENT_SOURCE_DIR}/src)
@ -514,7 +509,6 @@ target_link_libraries(
WingPlugin
QHexView
WingCodeEdit
QJsonModel
angelscript
qtadvanceddocking-qt${QT_VERSION_MAJOR})

View File

@ -61,8 +61,6 @@ add_library(
ctltestform.h
ctltestform.cpp
ctltestform.ui
testtablemodel.h
testtablemodel.cpp
testsettingpage.h
testsettingpage.cpp
testwingeditorviewwidget.h
@ -91,4 +89,5 @@ if(TEST_MODE)
${WINGHEX_PLUGIN_PATH})
endif()
target_link_libraries(TestPlugin PRIVATE Qt${QT_VERSION_MAJOR}::Widgets WingPlugin)
target_link_libraries(TestPlugin PRIVATE Qt${QT_VERSION_MAJOR}::Widgets
WingPlugin)

View File

@ -185,12 +185,12 @@
<translation></translation>
</message>
<message>
<location filename="../testform.ui" line="1184"/>
<location filename="../testform.ui" line="1055"/>
<source>Others</source>
<translation></translation>
</message>
<message>
<location filename="../testform.ui" line="1245"/>
<location filename="../testform.ui" line="1116"/>
<source>Other APIs should be Test With Script</source>
<translation> API </translation>
</message>
@ -231,7 +231,6 @@
<location filename="../testform.ui" line="311"/>
<location filename="../testform.ui" line="707"/>
<location filename="../testform.ui" line="881"/>
<location filename="../testform.ui" line="1070"/>
<source>Type</source>
<translation></translation>
</message>
@ -266,32 +265,6 @@
<source>Color</source>
<translation></translation>
</message>
<message>
<location filename="../testform.ui" line="1055"/>
<source>DataVisual</source>
<translation></translation>
</message>
<message>
<location filename="../testform.cpp" line="340"/>
<location filename="../testform.cpp" line="349"/>
<source>UpdateTextTreeError</source>
<translation></translation>
</message>
<message>
<location filename="../testform.cpp" line="364"/>
<source>UpdateTextListByModelError</source>
<translation></translation>
</message>
<message>
<location filename="../testform.cpp" line="374"/>
<source>UpdateTextTableByModelError</source>
<translation></translation>
</message>
<message>
<location filename="../testform.cpp" line="385"/>
<source>UpdateTextTreeByModelError</source>
<translation></translation>
</message>
</context>
<context>
<name>TestPlugin</name>

View File

@ -24,7 +24,6 @@
#include "ctltestform.h"
#include "readertestform.h"
#include "testtablemodel.h"
#include <QAbstractTableModel>
#include <QFileSystemModel>
@ -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));

View File

@ -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

View File

@ -1050,135 +1050,6 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_8">
<attribute name="title">
<string>DataVisual</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_20">
<item>
<widget class="QTextEdit" name="teDataVisual"/>
</item>
<item>
<widget class="QGroupBox" name="groupBox_6">
<property name="minimumSize">
<size>
<width>0</width>
<height>150</height>
</size>
</property>
<property name="title">
<string>Type</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<property name="sizeConstraint">
<enum>QLayout::SizeConstraint::SetMinAndMaxSize</enum>
</property>
<item row="0" column="1">
<widget class="QPushButton" name="btnTextList">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">updateTextList (LineByLine)</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="btnTextTree">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">updateTextTree (Json)</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="btnTextTable">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">updateTextTable (Json)</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="btnTextListByModel">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">updateTextListByModel</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="btnText_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">updateText</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="btnTextTableByModel">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">updateTextTableByModel</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QPushButton" name="btnTextTreeByModel">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true">updateTextTreeByModel</string>
</property>
</widget>
</item>
<item row="1" column="1" rowspan="2">
<widget class="QLabel" name="label_13">
<property name="text">
<string notr="true">WingSummer</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_9">
<attribute name="title">
<string>Others</string>
@ -1278,18 +1149,18 @@
<resources/>
<connections>
<connection>
<sender>btnClearCtl</sender>
<sender>btnClearFile</sender>
<signal>clicked()</signal>
<receiver>tbCtlLogger</receiver>
<receiver>tbFileLogger</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>271</x>
<y>387</y>
<x>239</x>
<y>388</y>
</hint>
<hint type="destinationlabel">
<x>318</x>
<y>264</y>
<x>290</x>
<y>328</y>
</hint>
</hints>
</connection>
@ -1310,34 +1181,34 @@
</hints>
</connection>
<connection>
<sender>btnClearInput</sender>
<sender>btnClearCtl</sender>
<signal>clicked()</signal>
<receiver>tbInputLogger</receiver>
<receiver>tbCtlLogger</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>210</x>
<y>388</y>
<x>271</x>
<y>387</y>
</hint>
<hint type="destinationlabel">
<x>236</x>
<y>332</y>
<x>318</x>
<y>264</y>
</hint>
</hints>
</connection>
<connection>
<sender>btnClearFile</sender>
<sender>btnClearText</sender>
<signal>clicked()</signal>
<receiver>tbFileLogger</receiver>
<receiver>leToastText</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>239</x>
<y>388</y>
<x>569</x>
<y>271</y>
</hint>
<hint type="destinationlabel">
<x>290</x>
<y>328</y>
<x>468</x>
<y>229</y>
</hint>
</hints>
</connection>
@ -1358,18 +1229,18 @@
</hints>
</connection>
<connection>
<sender>btnClearText</sender>
<sender>btnClearInput</sender>
<signal>clicked()</signal>
<receiver>leToastText</receiver>
<receiver>tbInputLogger</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>569</x>
<y>271</y>
<x>210</x>
<y>388</y>
</hint>
<hint type="destinationlabel">
<x>468</x>
<y>229</y>
<x>236</x>
<y>332</y>
</hint>
</hints>
</connection>

View File

@ -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();
}

View File

@ -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 <QAbstractTableModel>
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

@ -1 +1 @@
Subproject commit 95b3250011d0bf76ebd77f9905dc77fd04a46ce7
Subproject commit 8d86c185041572bd4735b272669d4117765c2176

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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 <https://www.gnu.org/licenses/>.
** =============================================================================
*/
#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

View File

@ -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 <QDir>
#include <QFileInfoList>
#include <QJsonArray>
#include <QJsonDocument>
#include <QMessageBox>
#include <QPluginLoader>
#include <QScopeGuard>
@ -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<WingHex::IWingPlugin *>(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"));

View File

@ -32,7 +32,6 @@
#include <QVariant>
#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);

File diff suppressed because it is too large Load Diff

View File

@ -23,9 +23,7 @@
#include <QFileDialog>
#include <any>
#include <functional>
#include <vector>
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 <class T>
void registerAPI(asIScriptEngine *engine, const std::function<T> &fn,
const char *sig) {
_fnbuffer.push_back(fn);
auto r = engine->RegisterGlobalFunction(
sig, asMETHOD(std::function<T>, operator()),
asCALL_THISCALL_ASGLOBAL,
std::any_cast<std::function<T>>(&_fnbuffer.back()));
Q_ASSERT(r >= 0);
Q_UNUSED(r);
}
using WrapperFn = std::function<void(asIScriptGeneric *)>;
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<int> &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<std::any> _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<IWingPlugin::ScriptFnInfo> _sfns;
QHash<QString, QHash<QString, qsizetype>> _rfns;

View File

@ -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)

View File

@ -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<QDynamicPropertyChangeEvent *>(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<QDockWidget *>(
obj->property("__DOCK__").value<quintptr>());
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

View File

@ -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<ToolButtonIndex, QToolButton *> m_toolBtneditors;
QAction *m_aDelBookMark = nullptr;

View File

@ -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 <https://www.gnu.org/licenses/>.
** =============================================================================
*/
#include "qjsontablemodel.h"
#include <QJsonObject>
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();
}
}

View File

@ -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 <https://www.gnu.org/licenses/>.
** =============================================================================
*/
#ifndef QJSONTABLEMODEL_H
#define QJSONTABLEMODEL_H
#include <QAbstractTableModel>
#include <QHash>
#include <QJsonArray>
#include <QJsonDocument>
#include <QObject>
#include <QVector>
class QJsonTableModel : public QAbstractTableModel {
public:
typedef QHash<QString, QString> Heading;
typedef QVector<Heading> 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