1/****************************************************************************
2**
3** Copyright (C) 2013 Research In Motion.
4** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
5** Contact: https://www.qt.io/licensing/
6**
7** This file is part of the Qt3D module 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#include "../../shared/util.h"
31#include "stringmodel.h"
32
33#include <qtest.h>
34#include <QSignalSpy>
35#include <QDebug>
36
37#include <Qt3DQuick/private/quick3dnodeinstantiator_p.h>
38
39#include <QtQml/qqmlengine.h>
40#include <QtQml/qqmlcomponent.h>
41#include <QtQml/qqmlcontext.h>
42
43using namespace Qt3DCore::Quick;
44
45class tst_quick3dnodeinstantiator: public QQmlDataTest
46{
47 Q_OBJECT
48
49private slots:
50 void createNone();
51 void createSingle();
52 void createMultiple();
53 void createNested();
54 void stringModel();
55 void activeProperty();
56 void intModelChange();
57 void createAndRemove();
58};
59
60void tst_quick3dnodeinstantiator::createNone()
61{
62 QQmlEngine engine;
63 QQmlComponent component(&engine, testFileUrl(fileName: "createNone.qml"));
64 const auto root = qobject_cast<Qt3DCore::QNode*>(object: component.create());
65 QVERIFY(root != 0);
66 const auto instantiator = root->findChild<Quick3DNodeInstantiator*>();
67 QVERIFY(instantiator != 0);
68 QCOMPARE(instantiator->isActive(), true);
69 QCOMPARE(instantiator->count(), 0);
70 QCOMPARE(instantiator->property("success").toBool(), true);
71 QVERIFY(instantiator->delegate()->isReady());
72}
73
74void tst_quick3dnodeinstantiator::createSingle()
75{
76 QQmlEngine engine;
77 QQmlComponent component(&engine, testFileUrl(fileName: "createSingle.qml"));
78 const auto root = qobject_cast<Qt3DCore::QNode*>(object: component.create());
79 QVERIFY(root != 0);
80 const auto instantiator = root->findChild<Quick3DNodeInstantiator*>();
81 QVERIFY(instantiator != 0);
82 QCOMPARE(instantiator->isActive(), true);
83 QCOMPARE(instantiator->count(), 1);
84 QVERIFY(instantiator->delegate()->isReady());
85
86 QObject *object = instantiator->object();
87 QVERIFY(object);
88 QCOMPARE(object->parent(), root);
89 QCOMPARE(object->property("success").toBool(), true);
90 QCOMPARE(object->property("idx").toInt(), 0);
91}
92
93void tst_quick3dnodeinstantiator::createMultiple()
94{
95 QQmlEngine engine;
96 QQmlComponent component(&engine, testFileUrl(fileName: "createMultiple.qml"));
97 const auto root = qobject_cast<Qt3DCore::QNode*>(object: component.create());
98 QVERIFY(root != 0);
99 const auto instantiator = root->findChild<Quick3DNodeInstantiator*>();
100 QVERIFY(instantiator != 0);
101 QCOMPARE(instantiator->isActive(), true);
102 QCOMPARE(instantiator->count(), 10);
103
104 for (int i = 0; i < 10; i++) {
105 QObject *object = instantiator->objectAt(index: i);
106 QVERIFY(object);
107 QCOMPARE(object->parent(), root);
108 QCOMPARE(object->property("success").toBool(), true);
109 QCOMPARE(object->property("idx").toInt(), i);
110 }
111}
112
113void tst_quick3dnodeinstantiator::createNested()
114{
115 QQmlEngine engine;
116 QQmlComponent component(&engine, testFileUrl(fileName: "createNested.qml"));
117 const auto root = qobject_cast<Qt3DCore::QNode*>(object: component.create());
118 QVERIFY(root != 0);
119
120 auto instantiators = root->findChildren<Quick3DNodeInstantiator*>();
121 QCOMPARE(instantiators.count(), 4);
122
123 const auto outerInstantiator = instantiators.takeFirst();
124 QCOMPARE(outerInstantiator->isActive(), true);
125 QCOMPARE(outerInstantiator->count(), 3);
126
127 for (const auto instantiator : instantiators) {
128 QCOMPARE(instantiator->isActive(), true);
129 QCOMPARE(instantiator->count(), 4);
130
131 for (int i = 0; i < 4; i++) {
132 auto object = instantiator->objectAt(index: i);
133 QVERIFY(object);
134 QCOMPARE(object->parent(), root);
135 QCOMPARE(object->property("success").toBool(), true);
136 QCOMPARE(object->property("idx").toInt(), i);
137 }
138 }
139}
140
141void tst_quick3dnodeinstantiator::stringModel()
142{
143 QQmlEngine engine;
144 QQmlComponent component(&engine, testFileUrl(fileName: "stringModel.qml"));
145 const auto root = qobject_cast<Qt3DCore::QNode*>(object: component.create());
146 QVERIFY(root != 0);
147 const auto instantiator = root->findChild<Quick3DNodeInstantiator*>();
148 QVERIFY(instantiator != 0);
149 QCOMPARE(instantiator->isActive(), true);
150 QCOMPARE(instantiator->count(), 4);
151
152 for (int i = 0; i < 4; i++) {
153 QObject *object = instantiator->objectAt(index: i);
154 QVERIFY(object);
155 QCOMPARE(object->parent(), root);
156 QCOMPARE(object->property("success").toBool(), true);
157 }
158}
159
160void tst_quick3dnodeinstantiator::activeProperty()
161{
162 QQmlEngine engine;
163 QQmlComponent component(&engine, testFileUrl(fileName: "inactive.qml"));
164 const auto root = qobject_cast<Qt3DCore::QNode*>(object: component.create());
165 QVERIFY(root != 0);
166 const auto instantiator = root->findChild<Quick3DNodeInstantiator*>();
167 QVERIFY(instantiator != 0);
168 QSignalSpy activeSpy(instantiator, SIGNAL(activeChanged()));
169 QSignalSpy countSpy(instantiator, SIGNAL(countChanged()));
170 QSignalSpy objectSpy(instantiator, SIGNAL(objectChanged()));
171 QSignalSpy modelSpy(instantiator, SIGNAL(modelChanged()));
172 QCOMPARE(instantiator->isActive(), false);
173 QCOMPARE(instantiator->count(), 0);
174 QVERIFY(instantiator->delegate()->isReady());
175
176 QCOMPARE(activeSpy.count(), 0);
177 QCOMPARE(countSpy.count(), 0);
178 QCOMPARE(objectSpy.count(), 0);
179 QCOMPARE(modelSpy.count(), 0);
180
181 instantiator->setActive(true);
182 QCOMPARE(instantiator->isActive(), true);
183 QCOMPARE(instantiator->count(), 1);
184
185 QCOMPARE(activeSpy.count(), 1);
186 QCOMPARE(countSpy.count(), 1);
187 QCOMPARE(objectSpy.count(), 1);
188 QCOMPARE(modelSpy.count(), 0);
189
190 QObject *object = instantiator->object();
191 QVERIFY(object);
192 QCOMPARE(object->parent(), root);
193 QCOMPARE(object->property("success").toBool(), true);
194 QCOMPARE(object->property("idx").toInt(), 0);
195}
196
197void tst_quick3dnodeinstantiator::intModelChange()
198{
199 QQmlEngine engine;
200 QQmlComponent component(&engine, testFileUrl(fileName: "createMultiple.qml"));
201 const auto root = qobject_cast<Qt3DCore::QNode*>(object: component.create());
202 QVERIFY(root != 0);
203 const auto instantiator = root->findChild<Quick3DNodeInstantiator*>();
204 QVERIFY(instantiator != 0);
205 QSignalSpy activeSpy(instantiator, SIGNAL(activeChanged()));
206 QSignalSpy countSpy(instantiator, SIGNAL(countChanged()));
207 QSignalSpy objectSpy(instantiator, SIGNAL(objectChanged()));
208 QSignalSpy modelSpy(instantiator, SIGNAL(modelChanged()));
209 QCOMPARE(instantiator->count(), 10);
210
211 QCOMPARE(activeSpy.count(), 0);
212 QCOMPARE(countSpy.count(), 0);
213 QCOMPARE(objectSpy.count(), 0);
214 QCOMPARE(modelSpy.count(), 0);
215
216 instantiator->setModel(QVariant(2));
217 QCOMPARE(instantiator->count(), 2);
218
219 QCOMPARE(activeSpy.count(), 0);
220 QCOMPARE(countSpy.count(), 1);
221 QCOMPARE(objectSpy.count(), 2);
222 QCOMPARE(modelSpy.count(), 1);
223
224 for (int i = 0; i < 2; i++) {
225 QObject *object = instantiator->objectAt(index: i);
226 QVERIFY(object);
227 QCOMPARE(object->parent(), root);
228 QCOMPARE(object->property("success").toBool(), true);
229 QCOMPARE(object->property("idx").toInt(), i);
230 }
231}
232
233void tst_quick3dnodeinstantiator::createAndRemove()
234{
235 QQmlEngine engine;
236 QQmlComponent component(&engine, testFileUrl(fileName: "createAndRemove.qml"));
237 StringModel *model = new StringModel("model1");
238 engine.rootContext()->setContextProperty("model1", model);
239 QObject *rootObject = component.create();
240 QVERIFY(rootObject != 0);
241
242 Quick3DNodeInstantiator *instantiator =
243 qobject_cast<Quick3DNodeInstantiator*>(object: rootObject->findChild<QObject*>(aName: "instantiator1"));
244 QVERIFY(instantiator != 0);
245 model->drop(count: 1);
246 QVector<QString> names;
247 names << "Beta" << "Gamma" << "Delta";
248 for (int i = 0; i < 3; i++) {
249 QObject *object = instantiator->objectAt(index: i);
250 QVERIFY(object);
251 QCOMPARE(object->property("datum").toString(), names[i]);
252 }
253}
254QTEST_MAIN(tst_quick3dnodeinstantiator)
255
256#include "tst_quick3dnodeinstantiator.moc"
257

source code of qt3d/tests/auto/quick3d/quick3dnodeinstantiator/tst_quick3dnodeinstantiator.cpp