changes to config plugin, reduce file amount + code, fix greeter
This commit is contained in:
@@ -0,0 +1,270 @@
|
||||
#include "configobject.hpp"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QMetaObject>
|
||||
#include <QStringList>
|
||||
#include <QVariant>
|
||||
|
||||
namespace ZShell::config {
|
||||
|
||||
ConfigObject::ConfigObject(QObject* parent) : ConfigNode(parent) {}
|
||||
|
||||
void ConfigObject::loadFromJson(const QJsonValue& json) {
|
||||
const auto obj = json.toObject();
|
||||
const auto* meta = metaObject();
|
||||
|
||||
QSet<QString> known;
|
||||
|
||||
for (int i = basePropertyOffset(); i < meta->propertyCount(); ++i) {
|
||||
auto prop = meta->property(i);
|
||||
const auto key = QString::fromUtf8(prop.name());
|
||||
|
||||
known.insert(key);
|
||||
|
||||
if (!obj.contains(key)) continue;
|
||||
|
||||
const auto jsonVal = obj.value(key);
|
||||
|
||||
if (prop.metaType().flags().testFlag(QMetaType::PointerToQObject)) {
|
||||
if (auto* const node = prop.read(this).value<ConfigNode*>()) {
|
||||
node->loadFromJson(jsonVal);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!prop.isWritable()) continue;
|
||||
|
||||
if (prop.metaType().id() == QMetaType::QStringList) {
|
||||
QStringList list;
|
||||
const auto jsonArr = jsonVal.toArray();
|
||||
for (const auto& v : jsonArr)
|
||||
list.append(v.toString());
|
||||
prop.write(this, QVariant::fromValue(list));
|
||||
m_loadedKeys.insert(key);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prop.metaType().id() == QMetaType::QVariantList) {
|
||||
prop.write(this, jsonVal.toVariant());
|
||||
m_loadedKeys.insert(key);
|
||||
continue;
|
||||
}
|
||||
|
||||
prop.write(this, jsonVal.toVariant());
|
||||
m_loadedKeys.insert(key);
|
||||
}
|
||||
|
||||
m_extras = {};
|
||||
for (auto it = obj.begin(); it != obj.end(); ++it) {
|
||||
if (!known.contains(it.key())) {
|
||||
m_extras.insert(it.key(), it.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QJsonValue ConfigObject::toJson() const {
|
||||
QJsonObject obj;
|
||||
const auto* meta = metaObject();
|
||||
|
||||
for (int i = basePropertyOffset(); i < meta->propertyCount(); ++i) {
|
||||
const auto prop = meta->property(i);
|
||||
|
||||
if (!prop.isReadable()) continue;
|
||||
|
||||
const auto key = QString::fromUtf8(prop.name());
|
||||
|
||||
const auto value = prop.read(this);
|
||||
|
||||
if (prop.metaType().flags().testFlag(QMetaType::PointerToQObject)) {
|
||||
if (auto* const node = value.value<ConfigNode*>()) {
|
||||
const auto childJson = node->toJson();
|
||||
if (!childJson.isUndefined()) obj.insert(key, childJson);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_loadedKeys.contains(key)) continue;
|
||||
|
||||
if (!prop.isWritable()) continue;
|
||||
|
||||
if (prop.metaType().id() == QMetaType::QStringList) {
|
||||
QJsonArray arr;
|
||||
const auto strList = value.toStringList();
|
||||
for (const auto& s : strList)
|
||||
arr.append(s);
|
||||
obj.insert(key, arr);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prop.metaType().id() == QMetaType::QVariantList) {
|
||||
obj.insert(key, QJsonArray::fromVariantList(value.toList()));
|
||||
continue;
|
||||
}
|
||||
|
||||
obj.insert(key, QJsonValue::fromVariant(value));
|
||||
}
|
||||
|
||||
for (auto it = m_extras.begin(); it != m_extras.end(); ++it)
|
||||
obj.insert(it.key(), it.value());
|
||||
|
||||
if (obj.isEmpty()) return QJsonValue::Undefined;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
void ConfigObject::clearLoadedKeys() {
|
||||
m_loadedKeys.clear();
|
||||
m_extras = {};
|
||||
|
||||
const auto* meta = metaObject();
|
||||
for (int i = basePropertyOffset(); i < meta->propertyCount(); ++i) {
|
||||
auto prop = meta->property(i);
|
||||
if (auto* const node = prop.read(this).value<ConfigNode*>())
|
||||
node->clearLoadedKeys();
|
||||
}
|
||||
}
|
||||
|
||||
QStringList ConfigObject::identityKeys() const {
|
||||
return {};
|
||||
}
|
||||
|
||||
QStringList ConfigObject::unknownKeys() const {
|
||||
auto keys = m_extras.keys();
|
||||
|
||||
const auto* meta = metaObject();
|
||||
for (int i = basePropertyOffset(); i < meta->propertyCount(); ++i) {
|
||||
const auto prop = meta->property(i);
|
||||
auto* const node = prop.read(this).value<ConfigNode*>();
|
||||
if (!node) continue;
|
||||
|
||||
const auto childKeys = node->unknownKeys();
|
||||
for (const auto& childKey : childKeys)
|
||||
keys.append(joinPath(QString::fromUtf8(prop.name()), childKey));
|
||||
}
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
QList<ConfigNode*> ConfigObject::childNodes() const {
|
||||
QList<ConfigNode*> nodes;
|
||||
|
||||
const auto* meta = metaObject();
|
||||
for (int i = basePropertyOffset(); i < meta->propertyCount(); ++i) {
|
||||
const auto prop = meta->property(i);
|
||||
|
||||
if (auto* const node = prop.read(this).value<ConfigNode*>())
|
||||
nodes.append(node);
|
||||
}
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
void ConfigObject::syncValuesFromGlobal() {
|
||||
const auto* meta = metaObject();
|
||||
|
||||
for (int i = basePropertyOffset(); i < meta->propertyCount(); ++i) {
|
||||
auto prop = meta->property(i);
|
||||
const auto key = QString::fromUtf8(prop.name());
|
||||
|
||||
if (auto* const node = prop.read(this).value<ConfigNode*>()) {
|
||||
if (auto* const globalNode =
|
||||
prop.read(m_global).value<ConfigNode*>())
|
||||
node->syncFromGlobal(globalNode);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!prop.isWritable()) continue;
|
||||
|
||||
if (!m_loadedKeys.contains(key)) {
|
||||
auto val = prop.read(m_global);
|
||||
prop.write(this, val);
|
||||
m_loadedKeys.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigObject::resyncFromGlobal() {
|
||||
if (!m_global) return;
|
||||
|
||||
const auto* meta = metaObject();
|
||||
for (int i = basePropertyOffset(); i < meta->propertyCount(); ++i) {
|
||||
auto prop = meta->property(i);
|
||||
const auto key = QString::fromUtf8(prop.name());
|
||||
|
||||
if (auto* const node = prop.read(this).value<ConfigNode*>()) {
|
||||
node->resyncFromGlobal();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!prop.isWritable()) continue;
|
||||
|
||||
if (!m_loadedKeys.contains(key)) {
|
||||
prop.write(this, prop.read(m_global));
|
||||
m_loadedKeys.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ConfigObject::isPropertyLoaded(const QString& name) const {
|
||||
return m_loadedKeys.contains(name);
|
||||
}
|
||||
|
||||
bool ConfigObject::isGlobalOnly(const QString& name) const {
|
||||
return m_globalOnlyKeys.contains(name);
|
||||
}
|
||||
|
||||
QStringList ConfigObject::globalOnlyKeys() const {
|
||||
return {m_globalOnlyKeys.begin(), m_globalOnlyKeys.end()};
|
||||
}
|
||||
|
||||
void ConfigObject::resetOption(const QString& name) {
|
||||
m_loadedKeys.remove(name);
|
||||
|
||||
const int idx = metaObject()->indexOfProperty(name.toUtf8().constData());
|
||||
if (idx < 0) return;
|
||||
|
||||
const auto prop = metaObject()->property(idx);
|
||||
|
||||
if (auto* const node = prop.read(this).value<ConfigNode*>()) {
|
||||
node->clearLoadedKeys();
|
||||
node->resyncFromGlobal();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_global && prop.isWritable()) prop.write(this, prop.read(m_global));
|
||||
}
|
||||
|
||||
void ConfigObject::onGlobalPropertiesChanged(
|
||||
const QMap<QString, QVariant>& changed) {
|
||||
for (auto it = changed.begin(); it != changed.end(); ++it) {
|
||||
if (m_loadedKeys.contains(it.key()) || isGlobalOnly(it.key())) continue;
|
||||
|
||||
int idx = metaObject()->indexOfProperty(it.key().toUtf8().constData());
|
||||
if (idx >= 0) {
|
||||
metaObject()->property(idx).write(this, it.value());
|
||||
m_loadedKeys.remove(it.key());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString ConfigObject::childPath(const ConfigNode* child) const {
|
||||
const auto* meta = metaObject();
|
||||
for (int i = basePropertyOffset(); i < meta->propertyCount(); ++i) {
|
||||
const auto prop = meta->property(i);
|
||||
|
||||
if (prop.read(this).value<ConfigNode*>() == child)
|
||||
return QString::fromUtf8(prop.name());
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void ConfigObject::markPropertyLoaded(const QString& name) {
|
||||
m_loadedKeys.insert(name);
|
||||
}
|
||||
|
||||
void ConfigObject::markGlobalOnly(const QString& name) {
|
||||
m_globalOnlyKeys.insert(name);
|
||||
}
|
||||
|
||||
} // namespace ZShell::config
|
||||
Reference in New Issue
Block a user