WingHexExplorer2/src/class/workspacemanager.cpp

238 lines
10 KiB
C++

/*==============================================================================
** 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 "workspacemanager.h"
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QMap>
WorkSpaceManager::WorkSpaceManager() {}
bool WorkSpaceManager::loadWorkSpace(const QString &filename, QString &file,
QMap<qsizetype, QString> &bookmarks,
QVector<QHexMetadataItem> &metas,
WorkSpaceInfo &infos) {
bool b = false;
QFile f(filename);
if (f.exists()) {
QJsonParseError err;
if (!f.open(QFile::ReadOnly))
return false;
QJsonDocument doc = QJsonDocument::fromJson(f.readAll(), &err);
f.close();
if (err.error == QJsonParseError::NoError) {
auto jobj = doc.object();
auto t = jobj.value("type");
if (!t.isUndefined() && t.isString()) {
auto type = t.toString();
if (!QString::compare(type, "workspace", Qt::CaseInsensitive)) {
auto ff = jobj.value("file");
if (!ff.isUndefined() && ff.isString()) {
auto fi = ff.toString();
QFileInfo finfo(fi);
file = finfo.isAbsolute()
? fi
: QFileInfo(filename).absolutePath() +
QDir::separator() + fi;
auto values = jobj.value("base");
if (!values.isUndefined() && values.isString()) {
auto ba = values.toString();
auto nbase = ba.toULongLong(&b);
if (b)
infos.base = nbase;
}
auto maxbytes =
QFileInfo(file).size(); // 简单排除非法标记
values = jobj.value("metas");
if (!values.isUndefined() && values.isArray()) {
auto metaitems = values.toArray();
for (auto item : metaitems) {
auto linem = item.toObject();
auto begin = linem.value("begin");
auto end = linem.value("end");
auto comment = linem.value("comment");
auto fgcolor = linem.value("fgcolor");
auto bgcolor = linem.value("bgcolor");
if (!begin.isUndefined() && begin.isString() &&
!end.isUndefined() && end.isString() &&
!comment.isUndefined() &&
comment.isString() &&
!fgcolor.isUndefined() &&
fgcolor.isString() &&
!bgcolor.isUndefined() &&
bgcolor.isString()) {
auto nbegin =
begin.toString().toLongLong(&b);
if (!b || nbegin >= maxbytes || nbegin < 0)
continue;
auto nend = end.toString().toLongLong(&b);
if (!b || nend >= maxbytes || nend < 0)
continue;
static auto NO_COLOR = QStringLiteral("-");
QColor fcolor, bcolor;
auto fgn = fgcolor.toString();
if (fgn != NO_COLOR) {
fcolor = QColor(fgn);
}
auto bgn = bgcolor.toString();
if (bgn != NO_COLOR) {
bcolor = QColor(bgn);
}
QHexMetadataItem metaitem;
metaitem.begin = nbegin;
metaitem.end = nend;
metaitem.comment = comment.toString();
metaitem.foreground = fcolor;
metaitem.background = bcolor;
metas.append(metaitem);
}
}
}
values = jobj.value("bookmarks");
if (!values.isUndefined() && values.isArray()) {
auto array = values.toArray();
for (auto item : array) {
if (!item.isUndefined() && item.isObject()) {
auto sitem = item.toObject();
auto pos = sitem.value("pos");
auto comment = sitem.value("comment");
if (!pos.isUndefined() && pos.isString() &&
!comment.isUndefined() &&
comment.isString()) {
auto b = false;
auto ipos =
pos.toString().toLongLong(&b);
if (!b || ipos < 0 || ipos >= maxbytes)
continue;
bookmarks.insert(ipos,
comment.toString());
}
}
}
}
values = jobj.value("plugindata");
if (!values.isUndefined() && values.isArray()) {
auto array = values.toArray();
for (auto item : array) {
if (!item.isUndefined() && item.isObject()) {
auto sitem = item.toObject();
auto plgobj = sitem.value("key");
auto valueobj = sitem.value("value");
if (!plgobj.isUndefined() &&
plgobj.isString() &&
!valueobj.isUndefined() &&
valueobj.isString()) {
auto plg = plgobj.toString();
auto value = QByteArray::fromBase64(
valueobj.toString().toLatin1());
if (plg.isEmpty() || value.isEmpty()) {
continue;
}
infos.pluginData.insert(plg, value);
}
}
}
}
return true;
}
}
}
}
}
return false;
}
QString WorkSpaceManager::getColorString(const QColor &color) {
static auto NO_COLOR = QStringLiteral("-");
if (color.isValid()) {
return color.name();
}
return NO_COLOR;
}
bool WorkSpaceManager::saveWorkSpace(
const QString &filename, const QString &file,
const QMap<qsizetype, QString> &bookmarklist,
const QVector<QHexMetadataItem> &metalist, const WorkSpaceInfo &infos) {
QFile f(filename);
if (f.open(QFile::WriteOnly)) {
QJsonObject jobj;
jobj.insert("type", "workspace");
QString ff = file;
QFileInfo fileInfo(file);
if (fileInfo.isAbsolute()) {
QDir dir(QFileInfo(f).absoluteDir());
QFileInfo fi(file);
ff = dir.relativeFilePath(fi.absoluteFilePath());
}
jobj.insert("file", ff);
jobj.insert("base", QString::number(infos.base));
QJsonArray metas;
for (auto &meta : metalist) {
QJsonObject obj;
obj.insert("begin", QString::number(meta.begin));
obj.insert("end", QString::number(meta.end));
obj.insert("comment", meta.comment);
obj.insert("fgcolor", getColorString(meta.foreground));
obj.insert("bgcolor", getColorString(meta.background));
metas.append(obj);
}
jobj.insert("metas", metas);
QJsonArray bookmarks;
for (auto p = bookmarklist.cbegin(); p != bookmarklist.cend(); ++p) {
QJsonObject i;
i.insert("pos", QString::number(p.key()));
i.insert("comment", p.value());
bookmarks.append(i);
}
jobj.insert("bookmarks", bookmarks);
// plugin data
QJsonArray plugindata;
for (auto p = infos.pluginData.begin(); p != infos.pluginData.end();
p++) {
QJsonObject i;
i.insert("key", p.key());
i.insert("value", QString::fromLatin1(p.value().toBase64()));
plugindata.append(i);
}
jobj.insert("plugindata", plugindata);
QJsonDocument jdoc(jobj);
if (f.write(jdoc.toJson(QJsonDocument::JsonFormat::Indented)) >= 0) {
f.close();
return true;
}
}
return false;
}