summaryrefslogtreecommitdiff
path: root/g_object.cpp
diff options
context:
space:
mode:
authorNikita Kostovsky <nikita@kostovsky.me>2025-09-19 20:54:13 +0200
committerNikita Kostovsky <nikita@kostovsky.me>2025-09-19 20:54:13 +0200
commite7019763076cbbe3d52c2a03133c3ded5558f017 (patch)
treebcf5ff116630bebaa09492bdcdaf08a54dfd1e28 /g_object.cpp
initial commit
Diffstat (limited to 'g_object.cpp')
-rw-r--r--g_object.cpp180
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;
+}