1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
5** Contact: https://www.qt.io/licensing/
6**
7** This file is part of the test suite of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:GPL-EXCEPT$
10** Commercial License Usage
11** Licensees holding valid commercial Qt licenses may use this file in
12** accordance with the commercial license agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and The Qt Company. For licensing terms
15** and conditions see https://www.qt.io/terms-conditions. For further
16** information use the contact form at https://www.qt.io/contact-us.
17**
18** GNU General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU
20** General Public License version 3 as published by the Free Software
21** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
22** included in the packaging of this file. Please review the following
23** information to ensure the GNU General Public License requirements will
24** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25**
26** $QT_END_LICENSE$
27**
28****************************************************************************/
29
30
31#include <QtTest/QtTest>
32
33#include <qobject.h>
34#include <qmetaobject.h>
35
36struct CustomType
37{
38 int padding;
39 QString str;
40 CustomType(const QString &str = QString()) : str(str) {}
41 operator QString() const { return str; }
42 friend bool operator!=(const CustomType &a, const CustomType &b)
43 { return a.str != b.str; }
44};
45
46Q_DECLARE_METATYPE(CustomType)
47
48class tst_QMetaProperty : public QObject
49{
50 Q_OBJECT
51 Q_PROPERTY(EnumType value WRITE setValue READ getValue)
52 Q_PROPERTY(EnumType value2 WRITE set_value READ get_value)
53 Q_PROPERTY(QString value7 MEMBER value7 RESET resetValue7)
54 Q_PROPERTY(int value8 READ value8)
55 Q_PROPERTY(int value9 READ value9 CONSTANT)
56 Q_PROPERTY(int value10 READ value10 FINAL)
57 Q_PROPERTY(QMap<int, int> map MEMBER map)
58 Q_PROPERTY(CustomType custom MEMBER custom)
59
60private slots:
61 void hasStdCppSet();
62 void isConstant();
63 void isFinal();
64 void gadget();
65 void readAndWriteWithLazyRegistration();
66 void mapProperty();
67 void conversion();
68
69public:
70 enum EnumType { EnumType1 };
71
72 void setValue(EnumType) {}
73 EnumType getValue() const { return EnumType1; }
74 void set_value(EnumType) {}
75 EnumType get_value() const { return EnumType1; }
76
77 void resetValue7() { value7 = QStringLiteral("reset"); }
78 int value8() const { return 1; }
79 int value9() const { return 1; }
80 int value10() const { return 1; }
81
82 QString value7;
83 QMap<int, int> map;
84 CustomType custom;
85};
86
87void tst_QMetaProperty::hasStdCppSet()
88{
89 const QMetaObject *mo = metaObject();
90
91 QMetaProperty prop = mo->property(index: mo->indexOfProperty(name: "value"));
92 QVERIFY(prop.isValid());
93 QVERIFY(prop.hasStdCppSet());
94
95 prop = mo->property(index: mo->indexOfProperty(name: "value2"));
96 QVERIFY(prop.isValid());
97 QVERIFY(!prop.hasStdCppSet());
98}
99
100void tst_QMetaProperty::isConstant()
101{
102 const QMetaObject *mo = metaObject();
103
104 QMetaProperty prop = mo->property(index: mo->indexOfProperty(name: "value8"));
105 QVERIFY(prop.isValid());
106 QVERIFY(!prop.isConstant());
107
108 prop = mo->property(index: mo->indexOfProperty(name: "value9"));
109 QVERIFY(prop.isValid());
110 QVERIFY(prop.isConstant());
111}
112
113void tst_QMetaProperty::isFinal()
114{
115 const QMetaObject *mo = metaObject();
116
117 QMetaProperty prop = mo->property(index: mo->indexOfProperty(name: "value10"));
118 QVERIFY(prop.isValid());
119 QVERIFY(prop.isFinal());
120
121 prop = mo->property(index: mo->indexOfProperty(name: "value9"));
122 QVERIFY(prop.isValid());
123 QVERIFY(!prop.isFinal());
124}
125
126class MyGadget {
127 Q_GADGET
128 Q_PROPERTY(QString value READ getValue WRITE setValue RESET resetValue)
129public:
130 QString m_value;
131 void setValue(const QString &value) { m_value = value; }
132 QString getValue() { return m_value; }
133 void resetValue() { m_value = QLatin1String("reset"); }
134};
135
136void tst_QMetaProperty::gadget()
137{
138 const QMetaObject *mo = &MyGadget::staticMetaObject;
139 QMetaProperty valueProp = mo->property(index: mo->indexOfProperty(name: "value"));
140 QVERIFY(valueProp.isValid());
141 {
142 MyGadget g;
143 QString hello = QLatin1String("hello");
144 QVERIFY(valueProp.writeOnGadget(&g, hello));
145 QCOMPARE(g.m_value, QLatin1String("hello"));
146 QCOMPARE(valueProp.readOnGadget(&g), QVariant(hello));
147 QVERIFY(valueProp.resetOnGadget(&g));
148 QCOMPARE(valueProp.readOnGadget(&g), QVariant(QLatin1String("reset")));
149 }
150}
151
152struct CustomReadObject : QObject
153{
154 Q_OBJECT
155};
156
157struct CustomWriteObject : QObject
158{
159 Q_OBJECT
160};
161
162struct CustomWriteObjectChild : CustomWriteObject
163{
164 Q_OBJECT
165};
166
167struct TypeLazyRegistration : QObject
168{
169 Q_OBJECT
170 Q_PROPERTY(CustomReadObject *read MEMBER _read)
171 Q_PROPERTY(CustomWriteObject *write MEMBER _write)
172
173 CustomReadObject *_read;
174 CustomWriteObject *_write;
175
176public:
177 TypeLazyRegistration()
178 : _read()
179 , _write()
180 {}
181};
182
183void tst_QMetaProperty::readAndWriteWithLazyRegistration()
184{
185 QCOMPARE(QMetaType::type("CustomReadObject*"), int(QMetaType::UnknownType));
186 QCOMPARE(QMetaType::type("CustomWriteObject*"), int(QMetaType::UnknownType));
187
188 TypeLazyRegistration o;
189 QVERIFY(o.property("read").isValid());
190 QVERIFY(QMetaType::type("CustomReadObject*") != QMetaType::UnknownType);
191 QCOMPARE(QMetaType::type("CustomWriteObject*"), int(QMetaType::UnknownType));
192
193 CustomWriteObjectChild data;
194 QVariant value = QVariant::fromValue(value: &data); // this register CustomWriteObjectChild
195 // check if base classes are not registered automatically, otherwise this test would be meaningless
196 QCOMPARE(QMetaType::type("CustomWriteObject*"), int(QMetaType::UnknownType));
197 QVERIFY(o.setProperty("write", value));
198 QVERIFY(QMetaType::type("CustomWriteObject*") != QMetaType::UnknownType);
199 QCOMPARE(o.property("write").value<CustomWriteObjectChild*>(), &data);
200}
201
202void tst_QMetaProperty::mapProperty()
203{
204 map.insert(akey: 5, avalue: 9);
205 QVariant v1 = QVariant::fromValue(value: map);
206 QVariant v = property(name: "map");
207 QVERIFY(v.isValid());
208 QCOMPARE(map, (v.value<QMap<int,int> >()));
209}
210
211void tst_QMetaProperty::conversion()
212{
213 QMetaType::registerConverter<QString, CustomType>();
214 QMetaType::registerConverter<CustomType, QString>();
215
216 QString hello = QStringLiteral("Hello");
217
218 // Write to a QString property using a CustomType in a QVariant
219 QMetaProperty value7P = metaObject()->property(index: metaObject()->indexOfProperty(name: "value7"));
220 QVERIFY(value7P.isValid());
221 QVERIFY(value7P.write(this, QVariant::fromValue(CustomType(hello))));
222 QCOMPARE(value7, hello);
223
224 // Write to a CustomType property using a QString in a QVariant
225 QMetaProperty customP = metaObject()->property(index: metaObject()->indexOfProperty(name: "custom"));
226 QVERIFY(customP.isValid());
227 QVERIFY(customP.write(this, hello));
228 QCOMPARE(custom.str, hello);
229
230 // Something that cannot be converted should fail
231 QVERIFY(!customP.write(this, 45));
232 QVERIFY(!customP.write(this, QVariant::fromValue(this)));
233 QVERIFY(!value7P.write(this, QVariant::fromValue(this)));
234 QVERIFY(!value7P.write(this, QVariant::fromValue<QObject*>(this)));
235
236 // none of this should have changed the values
237 QCOMPARE(value7, hello);
238 QCOMPARE(custom.str, hello);
239
240 // Empty variant should be converted to default object
241 QVERIFY(customP.write(this, QVariant()));
242 QCOMPARE(custom.str, QString());
243 // or reset resetable
244 QVERIFY(value7P.write(this, QVariant()));
245 QCOMPARE(value7, QLatin1String("reset"));
246}
247
248QTEST_MAIN(tst_QMetaProperty)
249#include "tst_qmetaproperty.moc"
250

source code of qtbase/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp