diff options
| author | Nikita Kostovsky <nikita@kostovsky.me> | 2025-09-19 20:54:13 +0200 |
|---|---|---|
| committer | Nikita Kostovsky <nikita@kostovsky.me> | 2025-09-19 20:54:13 +0200 |
| commit | e7019763076cbbe3d52c2a03133c3ded5558f017 (patch) | |
| tree | bcf5ff116630bebaa09492bdcdaf08a54dfd1e28 /g_object.cpp | |
initial commit
Diffstat (limited to 'g_object.cpp')
| -rw-r--r-- | g_object.cpp | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/g_object.cpp b/g_object.cpp new file mode 100644 index 0000000..09cbc27 --- /dev/null +++ b/g_object.cpp @@ -0,0 +1,180 @@ +#include "g_object.h" + +// qt +#include <QDataStream> +#include <QLineF> +#include <QPointF> + +G_Object::G_Object(QObject* parent) + : QObject(parent) +{ +} + +G_Object::G_Object(const QJsonObject& json, QObject* parent) + : QObject(parent) +{ + // use G_Object static offset, not virtual + constructFromJson(json); +} + +G_Object::G_Object(const QJsonValue& json, QObject* parent) + : QObject(parent) +{ + constructFromJson(json.toObject()); +} + +G_Object::G_Object(const G_Object& other, QObject* parent) + : QObject(parent) +{ + // NOTE: always G_Object's assignment operator will be called, not derived + *this = other; +} + +G_Object& G_Object::operator=(const G_Object& other) +{ + // use G_Object static offset, not virtual + for (int i = staticMetaObject.propertyOffset(); + i < metaObject()->propertyCount(); + i++) + { + auto key = metaObject()->property(i).name(); + auto value = metaObject()->property(i).read(this); + if (value != other.property(key)) + { + setProperty(key, other.property(key)); + } + } + + return *this; +} + +G_Object& G_Object::operator=(const QJsonObject& json) +{ + constructFromJson(json); + + return *this; +} + +G_Object& G_Object::operator=(const QJsonValue& json) +{ + constructFromJson(json.toObject()); + + return *this; +} + +G_Object::operator const QJsonValue() const +{ + return this->operator const QJsonObject(); +} + +bool G_Object::operator==(const G_Object& other) const +{ + for (int i = staticMetaObject.propertyOffset(); + i < metaObject()->propertyCount(); + i++) + { + auto key = metaObject()->property(i).name(); + + if (property(key) != other.property(key)) + { + return false; + } + } + + return true; +} + +bool G_Object::constructFromJson(const QJsonObject& json) +{ + auto offset = staticMetaObject.propertyOffset(); + auto properiesCount = metaObject()->propertyCount(); + + for (int i = offset; i < properiesCount; i++) + { + auto key = metaObject()->property(i).name(); + auto type = metaObject()->property(i).userType(); + auto jsonValue = json[key]; + auto variantValue = jsonValue.toVariant(); + + if (variantValue.isNull()) + { + if (type == QMetaType::Double) + { + setProperty(key, std::numeric_limits<double>::quiet_NaN()); + } + else if (type == QMetaType::Float) + { + setProperty(key, std::numeric_limits<float>::quiet_NaN()); + } + else + { + return false; + } + + continue; + } + + auto converted = variantValue.convert(type); + + if (!converted) + { + qDebug() << Q_FUNC_INFO << "cannot convert" << key + << "property from type" + << QMetaType::typeName(variantValue.userType()) + << "to type" << QMetaType::typeName(type); + + return false; + } + + setProperty(key, variantValue); + } + + return true; +} + +G_Object::operator const QJsonObject() const +{ + QJsonObject result; + + // use G_Object static offset, not virtual + for (int i = staticMetaObject.propertyOffset(); + i < metaObject()->propertyCount(); + i++) + { + auto key = metaObject()->property(i).name(); + auto type = metaObject()->property(i).userType(); + auto value = metaObject()->property(i).read(this); + + if (value.isNull()) + { + continue; + } + + auto converted = value.convert(type); + + if (!converted) + { + qDebug() << "G_Object::operator const QJsonObject() const:" + << "cannot convert" << key << "property from type" + << QMetaType::typeName(value.userType()) << "to type" + << QMetaType::typeName(type); + } + + result[key] = QJsonValue::fromVariant(value); + } + + return result; +} + +QDebug operator<<(QDebug d, const G_Object& o) +{ + d << o.metaObject()->className() << ":\n"; + + for (int i = 0; i < o.metaObject()->propertyCount(); i++) + { + d << "\t" << o.metaObject()->property(i).name() << ":\t" + << o.metaObject()->property(i).read(&o) << Qt::endl; + } + + return d; +} |
