File indexing completed on 2024-05-19 15:26:48

0001 /*
0002  * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best>
0003  *
0004  * SPDX-License-Identifier: GPL-3.0-or-later
0005  */
0006 
0007 #include <QtTest/QtTest>
0008 #include <QPoint>
0009 #include <QMetaProperty>
0010 
0011 #include "model/property/object_list_property.hpp"
0012 #include "model/property/reference_property.hpp"
0013 #include "model/document.hpp"
0014 
0015 #define fake_i18n kli18n
0016 
0017 using namespace glaxnimate::model;
0018 using namespace glaxnimate;
0019 
0020 struct PropertyChangedInspector
0021 {
0022     PropertyChangedInspector() = default;
0023     PropertyChangedInspector(const PropertyChangedInspector&) = delete;
0024     PropertyChangedInspector& operator=(const PropertyChangedInspector&) = delete;
0025 
0026     void connect(Object& obj)
0027     {
0028         QObject::connect(&obj, &Object::property_changed, [this](const BaseProperty* prop, const QVariant& value){(*this)(prop->name(), value);});
0029     }
0030 
0031     void operator()(const QString& name, const QVariant& value)
0032     {
0033         this->name = name;
0034         this->value = value;
0035         called = true;
0036     }
0037 
0038     bool not_called()
0039     {
0040         return !called;
0041     }
0042 
0043     bool called_with(const QString& name, const QVariant& value)
0044     {
0045         return called && this->name == name && this->value == value;
0046     }
0047 
0048     void reset()
0049     {
0050         name = QString{};
0051         value = {};
0052         called = false;
0053     }
0054 
0055 
0056     QString name;
0057     QVariant value;
0058     bool called = false;
0059 };
0060 
0061 class MetaTestSubject : public DocumentNode
0062 {
0063     Q_OBJECT
0064 
0065     GLAXNIMATE_PROPERTY(int, prop_scalar, 123)
0066     GLAXNIMATE_PROPERTY_REFERENCE(MetaTestSubject, prop_ref, &MetaTestSubject::valid_references, &MetaTestSubject::is_valid_reference)
0067     GLAXNIMATE_PROPERTY_LIST(MetaTestSubject, prop_list)
0068 
0069 public:
0070     QIcon instance_icon() const override { return {}; }
0071     QIcon tree_icon() const override { return {}; }
0072     DocumentNode* docnode_parent() const override { return {}; }
0073     int docnode_child_count() const override { return {}; }
0074     DocumentNode* docnode_child(int) const override { return {}; }
0075     int docnode_child_index(DocumentNode*) const override { return -1; }
0076 
0077     std::vector<DocumentNode*> valid_references() const
0078     {
0079         return {
0080             const_cast<MetaTestSubject*>(this)
0081         };
0082     }
0083     bool is_valid_reference(DocumentNode* p)
0084     {
0085         return p == this;
0086     }
0087 
0088     using DocumentNode::DocumentNode;
0089 
0090     double foo_val(int bar) { return bar / 2.0; }
0091     double foo_val_const(int bar) const { return bar / 2.0; }
0092     double foo_ref(const int& bar) { return bar / 2.0; }
0093     double foo_ref_const(const int& bar) const { return bar / 2.0; }
0094 };
0095 
0096 
0097 class TestProperty: public QObject
0098 {
0099     Q_OBJECT
0100 
0101 private Q_SLOTS:
0102 
0103     void test_property_default()
0104     {
0105         PropertyChangedInspector pci;
0106         Object obj(nullptr);
0107         pci.connect(obj);
0108 
0109         Property<int> prop(&obj, fake_i18n("foo"), 456);
0110         QVERIFY(pci.not_called());
0111         QCOMPARE(prop.get(), 456);
0112     }
0113 
0114     void test_property_get_set()
0115     {
0116         PropertyChangedInspector pci;
0117         Object obj(nullptr);
0118         pci.connect(obj);
0119 
0120         Property<int> prop(&obj, fake_i18n("foo"));
0121         prop.set(123);
0122         QVERIFY(pci.called_with("foo", 123));
0123         QCOMPARE(prop.get(), 123);
0124     }
0125 
0126     void test_property_variant()
0127     {
0128         PropertyChangedInspector pci;
0129         Object obj(nullptr);
0130         pci.connect(obj);
0131 
0132         Property<int> prop(&obj, fake_i18n("foo"), 123);
0133         QCOMPARE(prop.value(), QVariant(123));
0134         QVERIFY(prop.set_value(QVariant(456)));
0135         QVERIFY(pci.called_with("foo", 456));
0136         QCOMPARE(prop.value(), QVariant(456));
0137         pci.reset();
0138         QVERIFY(!prop.set_value(QVariant(QPoint(1, 2))));
0139         QCOMPARE(prop.get(), 456);
0140         QVERIFY(pci.not_called());
0141     }
0142 
0143     void test_traits_get_type()
0144     {
0145         QCOMPARE(model::PropertyTraits::get_type<int>(), model::PropertyTraits::Int);
0146         QCOMPARE(model::PropertyTraits::get_type<float>(), model::PropertyTraits::Float);
0147         QCOMPARE(model::PropertyTraits::get_type<bool>(), model::PropertyTraits::Bool);
0148         QCOMPARE(model::PropertyTraits::get_type<QString>(), model::PropertyTraits::String);
0149         QCOMPARE(model::PropertyTraits::get_type<model::PropertyTraits::Type>(), model::PropertyTraits::Enum);
0150     }
0151 
0152     void test_metaobject()
0153     {
0154         Document doc("foo");
0155         MetaTestSubject test_subject(&doc);
0156         MetaTestSubject other(&doc);
0157 
0158         QMetaObject mop = DocumentNode::staticMetaObject;
0159         QMetaObject mo = MetaTestSubject::staticMetaObject;
0160 
0161         QCOMPARE(mo.propertyCount(), mop.propertyCount() + 3);
0162 
0163         QMetaProperty prop_0 = mo.property(mop.propertyCount() + 0);
0164         QCOMPARE(prop_0.name(), "prop_scalar");
0165         QVERIFY(prop_0.isWritable());
0166         QVERIFY(prop_0.isReadable());
0167         QVERIFY(prop_0.isScriptable());
0168         QCOMPARE(prop_0.read(&test_subject).toInt(), 123);
0169         QVERIFY(prop_0.write(&test_subject, QVariant(621)));
0170         QCOMPARE(prop_0.read(&test_subject).toInt(), 621);
0171         QCOMPARE(test_subject.prop_scalar.get(), 621);
0172         QVERIFY(!prop_0.write(&test_subject, QVariant("xyz")));
0173         QCOMPARE(test_subject.prop_scalar.get(), 621);
0174 
0175         QMetaProperty prop_1 = mo.property(mop.propertyCount() + 1);
0176         QCOMPARE(prop_1.name(), "prop_ref");
0177         QVERIFY(prop_1.isWritable());
0178         QVERIFY(prop_1.isReadable());
0179         QVERIFY(prop_1.isScriptable());
0180         QCOMPARE((quintptr)prop_1.read(&test_subject).value<MetaTestSubject*>(), 0);
0181         QVERIFY(prop_1.write(&test_subject, QVariant::fromValue(&test_subject)));
0182         QCOMPARE((quintptr)prop_1.read(&test_subject).value<MetaTestSubject*>(), (quintptr)&test_subject);
0183         QCOMPARE((quintptr)test_subject.prop_ref.get(), (quintptr)&test_subject);
0184         // invalid references shouldn't be set
0185         prop_1.write(&test_subject, QVariant::fromValue(&other));
0186         QCOMPARE((quintptr)test_subject.prop_ref.get(), (quintptr)&test_subject);
0187 
0188         QMetaProperty prop_2 = mo.property(mop.propertyCount() + 2);
0189         QCOMPARE(prop_2.name(), "prop_list");
0190         QVERIFY(!prop_2.isWritable());
0191         QVERIFY(prop_2.isReadable());
0192         QVERIFY(prop_2.isScriptable());
0193         QCOMPARE(prop_2.read(&test_subject).toList().size(), 0);
0194         test_subject.prop_list.insert(std::make_unique<MetaTestSubject>(&doc));
0195         QCOMPARE(test_subject.prop_list.size(), 1);
0196         QCOMPARE(prop_2.read(&test_subject).toList().size(), 1);
0197         QCOMPARE(prop_2.read(&test_subject).toList()[0].value<MetaTestSubject*>(), test_subject.prop_list[0]);
0198     }
0199 
0200     void test_callback_val()
0201     {
0202         Document doc("foo");
0203         MetaTestSubject test_subject(&doc);
0204         PropertyCallback<double, int> pc;
0205         QVERIFY(!pc);
0206         pc = &MetaTestSubject::foo_val;
0207         QVERIFY(pc);
0208         QCOMPARE(pc(&test_subject, 3), 1.5);
0209         pc = nullptr;
0210         QVERIFY(!pc);
0211     }
0212 
0213     void test_callback_val_const()
0214     {
0215         Document doc("foo");
0216         MetaTestSubject test_subject(&doc);
0217         PropertyCallback<double, int> pc;
0218         QVERIFY(!pc);
0219         pc = &MetaTestSubject::foo_val_const;
0220         QVERIFY(pc);
0221         QCOMPARE(pc(&test_subject, 3), 1.5);
0222         pc = nullptr;
0223         QVERIFY(!pc);
0224     }
0225 
0226     void test_callback_ref()
0227     {
0228         Document doc("foo");
0229         MetaTestSubject test_subject(&doc);
0230         PropertyCallback<double, int> pc;
0231         QVERIFY(!pc);
0232         pc = &MetaTestSubject::foo_ref;
0233         QVERIFY(pc);
0234         QCOMPARE(pc(&test_subject, 3), 1.5);
0235         pc = nullptr;
0236         QVERIFY(!pc);
0237     }
0238 
0239     void test_callback_ref_const()
0240     {
0241         Document doc("foo");
0242         MetaTestSubject test_subject(&doc);
0243         PropertyCallback<double, int> pc;
0244         QVERIFY(!pc);
0245         pc = &MetaTestSubject::foo_ref_const;
0246         QVERIFY(pc);
0247         QCOMPARE(pc(&test_subject, 3), 1.5);
0248         pc = nullptr;
0249         QVERIFY(!pc);
0250     }
0251 };
0252 
0253 QTEST_GUILESS_MAIN(TestProperty)
0254 #include "test_property.moc"