Files
z-bar-qt/Plugins/ZShell/Config/ConfigSection.cpp
T

88 lines
2.7 KiB
C++

#include "ConfigSection.hpp"
#include <QMetaType>
#include <QVariant>
namespace {
// Property index to start scanning from - skips QObject's own "objectName"
// property, which we never want in the JSON.
int firstOwnProperty() {
return QObject::staticMetaObject.propertyCount();
}
}
ConfigSection::ConfigSection(QObject *parent) : QObject(parent) {}
void ConfigSection::wireSignals() {
if (m_wired) return;
m_wired = true;
const QMetaObject *mo = metaObject();
const int slotIdx = mo->indexOfSlot("onPropertyChanged()");
Q_ASSERT(slotIdx != -1);
const QMetaMethod slot = mo->method(slotIdx);
const int start = firstOwnProperty();
for (int i = start; i < mo->propertyCount(); ++i) {
const QMetaProperty prop = mo->property(i);
if (prop.metaType().flags().testFlag(QMetaType::PointerToQObject)) {
if (auto *child = qobject_cast<ConfigSection *>(prop.read(this).value<QObject *>())) {
// Child sections bubble their changes straight up as our
// own changed() - no need to also react to our own notify.
connect(child, &ConfigSection::changed, this, &ConfigSection::changed);
continue;
}
}
if (prop.hasNotifySignal())
connect(this, prop.notifySignal(), this, slot);
}
}
void ConfigSection::onPropertyChanged() {
Q_EMIT changed();
}
void ConfigSection::fromJson(const QJsonObject &obj) {
const QMetaObject *mo = metaObject();
const int start = firstOwnProperty();
for (int i = start; i < mo->propertyCount(); ++i) {
const QMetaProperty prop = mo->property(i);
const QLatin1String name(prop.name());
if (!obj.contains(name)) continue;
if (prop.metaType().flags().testFlag(QMetaType::PointerToQObject)) {
if (auto *child = qobject_cast<ConfigSection *>(prop.read(this).value<QObject *>())) {
child->fromJson(obj.value(name).toObject());
continue;
}
}
if (prop.isWritable())
prop.write(this, obj.value(name).toVariant());
}
}
QJsonObject ConfigSection::toJson() const {
QJsonObject obj;
const QMetaObject *mo = metaObject();
const int start = firstOwnProperty();
for (int i = start; i < mo->propertyCount(); ++i) {
const QMetaProperty prop = mo->property(i);
if (prop.metaType().flags().testFlag(QMetaType::PointerToQObject)) {
if (auto *child = qobject_cast<ConfigSection *>(prop.read(this).value<QObject *>())) {
obj.insert(QLatin1String(prop.name()), child->toJson());
continue;
}
}
obj.insert(QLatin1String(prop.name()), QJsonValue::fromVariant(prop.read(this)));
}
return obj;
}