WingHexExplorer2/src/class/scripteditortheme.cpp

234 lines
7.7 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 "scripteditortheme.h"
#include <QFile>
#include <QFontDatabase>
#include <QMetaEnum>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
ScriptEditorTheme::ScriptEditorTheme(QObject *parent) : QObject(parent) {}
ScriptEditorTheme::ScriptEditorTheme(const QString &filename, QObject *parent)
: QObject(parent) {
if (!filename.isEmpty() && QFile::exists(filename)) {
loadTheme(filename);
}
}
ScriptEditorTheme::ColorScheme
ScriptEditorTheme::colorScheme(Styles style) const {
return m_colors.value(style);
}
void ScriptEditorTheme::setColorScheme(Styles style,
const ColorScheme &scheme) {
m_colors[style] = scheme;
}
bool ScriptEditorTheme::loadTheme(const QString &filename) {
QFile xmlFile(filename);
if (!xmlFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
return false;
}
QXmlStreamReader xmlReader(&xmlFile);
QString name;
QString version;
QString author;
QString comment;
auto e = QMetaEnum::fromType<Styles>();
while (!xmlReader.atEnd() && !xmlReader.hasError()) {
QXmlStreamReader::TokenType token = xmlReader.readNext();
if (token == QXmlStreamReader::StartDocument) {
if (xmlReader.name() != QStringLiteral("style-scheme")) {
return false;
}
auto attr = xmlReader.attributes();
if (readAttr(attr, QStringLiteral("name"), name)) {
readAttr(attr, QStringLiteral("version"), version);
readAttr(attr, QStringLiteral("author"), author);
readAttr(attr, QStringLiteral("comment"), comment);
} else {
return false;
}
continue;
}
ColorScheme scheme;
QString styleAttr;
if (token == QXmlStreamReader::StartElement) {
if (xmlReader.name() == QStringLiteral("style")) {
auto attr = xmlReader.attributes();
if (readAttr(attr, QStringLiteral("name"), styleAttr)) {
auto v = e.keyToValue(styleAttr.toUtf8());
if (v < 0) {
continue;
}
if (readAttr(attr, QStringLiteral("foreground"),
styleAttr)) {
QColor color(styleAttr);
if (color.isValid()) {
scheme.foreground = color;
}
}
if (readAttr(attr, QStringLiteral("background"),
styleAttr)) {
QColor color(styleAttr);
if (color.isValid()) {
scheme.background = color;
}
}
if (readAttr(attr, QStringLiteral("fontfamily"),
styleAttr)) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
if (QFontDatabase::hasFamily(styleAttr)) {
#else
if (QFontDatabase().hasFamily(styleAttr)) {
#endif
scheme.fontFamily = styleAttr;
}
}
if (readAttr(attr, QStringLiteral("underLine"),
styleAttr)) {
scheme.underLine =
QTextCharFormat::UnderlineStyle(styleAttr.toInt());
}
if (readAttr(attr, QStringLiteral("bold"), styleAttr)) {
bool ok;
scheme.isBold = string2Bool(styleAttr, ok);
if (!ok) {
scheme.isBold = false;
}
}
if (readAttr(attr, QStringLiteral("italic"), styleAttr)) {
bool ok;
scheme.isItalic = string2Bool(styleAttr, ok);
if (!ok) {
scheme.isItalic = false;
}
}
} else {
continue;
}
}
}
}
m_name = name;
m_version = version;
m_author = author;
m_comment = comment;
m_isValid = true;
return true;
}
bool ScriptEditorTheme::saveTheme(const QString &filename) {
QFile xmlFile(filename);
if (!xmlFile.open(QFile::WriteOnly | QFile::Text)) {
return false;
}
QXmlStreamWriter stream(&xmlFile);
stream.setAutoFormatting(true);
stream.writeStartDocument();
auto e = QMetaEnum::fromType<Styles>();
for (auto p = m_colors.begin(); p != m_colors.end(); p++) {
stream.writeStartElement("style");
stream.writeAttribute(QStringLiteral("name"),
e.valueToKey(int(p.key())));
auto v = p.value();
if (v.foreground.isValid()) {
stream.writeAttribute(QStringLiteral("foreground"),
v.foreground.name());
}
if (v.background.isValid()) {
stream.writeAttribute(QStringLiteral("background"),
v.background.name());
}
if (!v.fontFamily.isEmpty()) {
stream.writeAttribute(QStringLiteral("fontfamily"), v.fontFamily);
}
if (v.underLine != QTextCharFormat::NoUnderline) {
stream.writeAttribute(QStringLiteral("underLine"),
QString::number(v.underLine));
}
if (v.isBold) {
stream.writeAttribute(QStringLiteral("bold"),
bool2String(v.isBold));
}
if (v.isItalic) {
stream.writeAttribute(QStringLiteral("italic"),
bool2String(v.isBold));
}
stream.writeEndElement();
}
stream.writeEndDocument();
xmlFile.close();
return true;
}
bool ScriptEditorTheme::isValid() const { return m_isValid; }
bool ScriptEditorTheme::readAttr(const QXmlStreamAttributes &attrs,
const QString &name, QString &output) {
if (attrs.hasAttribute(name)) {
output = attrs.value(name).toString();
return true;
}
return false;
}
bool ScriptEditorTheme::string2Bool(const QString &str, bool &ok) {
if (str.compare(QStringLiteral("true"), Qt::CaseInsensitive) == 0) {
ok = true;
return true;
} else if (str.compare(QStringLiteral("false"), Qt::CaseInsensitive) == 0) {
ok = true;
return false;
} else {
ok = false;
return false;
}
}
QString ScriptEditorTheme::bool2String(bool b) {
return b ? QStringLiteral("true") : QStringLiteral("false");
}
QString ScriptEditorTheme::comment() const { return m_comment; }
QString ScriptEditorTheme::author() const { return m_author; }
QString ScriptEditorTheme::version() const { return m_version; }
QString ScriptEditorTheme::name() const { return m_name; }