1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the test suite of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
21 | ** included in the packaging of this file. Please review the following |
22 | ** information to ensure the GNU General Public License requirements will |
23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
24 | ** |
25 | ** $QT_END_LICENSE$ |
26 | ** |
27 | ****************************************************************************/ |
28 | #include <qtest.h> |
29 | #include <QtQml/qqmlengine.h> |
30 | #include <QtQml/qqmlcomponent.h> |
31 | #include <QtQuick/qquickview.h> |
32 | #include <private/qquickdesignersupportitems_p.h> |
33 | #include <private/qquickdesignersupportmetainfo_p.h> |
34 | #include <private/qquickdesignersupportproperties_p.h> |
35 | #include <private/qquickdesignersupportstates_p.h> |
36 | #include <private/qquickdesignersupportpropertychanges_p.h> |
37 | #include <private/qquickitem_p.h> |
38 | #include <private/qquickstate_p.h> |
39 | #include <private/qquickstate_p_p.h> |
40 | #include <private/qquickstategroup_p.h> |
41 | #include <private/qquickpropertychanges_p.h> |
42 | #include <private/qquickrectangle_p.h> |
43 | #include "../../shared/util.h" |
44 | #include "../shared/visualtestutil.h" |
45 | |
46 | using namespace QQuickVisualTestUtil; |
47 | |
48 | class tst_qquickdesignersupport : public QQmlDataTest |
49 | { |
50 | Q_OBJECT |
51 | public: |
52 | tst_qquickdesignersupport() {} |
53 | |
54 | private slots: |
55 | void customData(); |
56 | void customDataBindings(); |
57 | void objectProperties(); |
58 | void dynamicProperty(); |
59 | void createComponent(); |
60 | void basicStates(); |
61 | void statesPropertyChanges(); |
62 | void testNotifyPropertyChangeCallBack(); |
63 | void testFixResourcePathsForObjectCallBack(); |
64 | void testComponentOnCompleteSignal(); |
65 | void testPropertyNames(); |
66 | }; |
67 | |
68 | void tst_qquickdesignersupport::customData() |
69 | { |
70 | QScopedPointer<QQuickView> view(new QQuickView); |
71 | view->engine()->setOutputWarningsToStandardError(false); |
72 | view->setSource(testFileUrl(fileName: "test.qml" )); |
73 | |
74 | QVERIFY(view->errors().isEmpty()); |
75 | |
76 | QQuickItem *rootItem = view->rootObject(); |
77 | |
78 | QVERIFY(rootItem); |
79 | |
80 | QScopedPointer<QObject> newItemScopedPointer(QQuickDesignerSupportItems::createPrimitive(typeName: QLatin1String("QtQuick/Item" ), majorNumber: 2, minorNumber: 6, context: view->rootContext())); |
81 | QObject *newItem = newItemScopedPointer.data(); |
82 | |
83 | QVERIFY(newItem); |
84 | QVERIFY(qobject_cast<QQuickItem*>(newItem)); |
85 | |
86 | QQuickDesignerSupportProperties::registerCustomData(object: newItem); |
87 | QVERIFY(QQuickDesignerSupportProperties::getResetValue(newItem, "width" ).isValid()); |
88 | int defaultWidth = QQuickDesignerSupportProperties::getResetValue(object: newItem, propertyName: "width" ).toInt(); |
89 | QCOMPARE(defaultWidth, 0); |
90 | |
91 | newItem->setProperty(name: "width" , value: 200); |
92 | QCOMPARE(newItem->property("width" ).toInt(), 200); |
93 | |
94 | //Check if reseting property does work |
95 | QQuickDesignerSupportProperties::doResetProperty(object: newItem, context: view->rootContext(), propertyName: "width" ); |
96 | QCOMPARE(newItem->property("width" ).toInt(), 0); |
97 | |
98 | //Setting a binding on width |
99 | QQuickDesignerSupportProperties::setPropertyBinding(object: newItem, |
100 | context: view->engine()->contextForObject(newItem), |
101 | propertyName: "width" , |
102 | expression: QLatin1String("Math.max(0, 200)" )); |
103 | QCOMPARE(newItem->property("width" ).toInt(), 200); |
104 | QVERIFY(QQuickDesignerSupportProperties::hasBindingForProperty(newItem, |
105 | view->engine()->contextForObject(newItem), |
106 | "width" , |
107 | nullptr)); |
108 | |
109 | //Check if reseting property does work after setting binding |
110 | QQuickDesignerSupportProperties::doResetProperty(object: newItem, context: view->rootContext(), propertyName: "width" ); |
111 | QCOMPARE(newItem->property("width" ).toInt(), 0); |
112 | |
113 | //No custom data available for the rootItem, because not registered by QQuickDesignerSupportProperties::registerCustomData |
114 | QVERIFY(!QQuickDesignerSupportProperties::getResetValue(rootItem, "width" ).isValid()); |
115 | |
116 | newItemScopedPointer.reset(); //Delete the item and check if item gets removed from the hash and an invalid QVariant is returned. |
117 | |
118 | QVERIFY(!QQuickDesignerSupportProperties::getResetValue(newItem, "width" ).isValid()); |
119 | } |
120 | |
121 | void tst_qquickdesignersupport::customDataBindings() |
122 | { |
123 | QScopedPointer<QQuickView> view(new QQuickView); |
124 | view->engine()->setOutputWarningsToStandardError(false); |
125 | view->setSource(testFileUrl(fileName: "test.qml" )); |
126 | |
127 | QVERIFY(view->errors().isEmpty()); |
128 | |
129 | QQuickItem *rootItem = view->rootObject(); |
130 | |
131 | QVERIFY(rootItem); |
132 | |
133 | QQuickItem *testComponent = findItem<QQuickItem>(parent: view->rootObject(), objectName: QLatin1String("testComponent" )); |
134 | |
135 | QVERIFY(testComponent); |
136 | QQuickDesignerSupportProperties::registerCustomData(object: testComponent); |
137 | QQuickDesignerSupportProperties::hasValidResetBinding(object: testComponent, propertyName: "x" ); |
138 | QVERIFY(QQuickDesignerSupportProperties::hasBindingForProperty(testComponent, |
139 | view->engine()->contextForObject(testComponent), |
140 | "x" , |
141 | nullptr)); |
142 | |
143 | QCOMPARE(testComponent->property("x" ).toInt(), 200); |
144 | |
145 | |
146 | //Set property to 100 and ovveride the default binding |
147 | QQmlProperty property(testComponent, "x" , view->engine()->contextForObject(testComponent)); |
148 | QVERIFY(property.write(100)); |
149 | QCOMPARE(testComponent->property("x" ).toInt(), 100); |
150 | |
151 | QVERIFY(!QQuickDesignerSupportProperties::hasBindingForProperty(testComponent, |
152 | view->engine()->contextForObject(testComponent), |
153 | "x" , |
154 | nullptr)); |
155 | |
156 | //Reset the binding to the default |
157 | QQuickDesignerSupportProperties::doResetProperty(object: testComponent, |
158 | context: view->engine()->contextForObject(testComponent), |
159 | propertyName: "x" ); |
160 | |
161 | QVERIFY(QQuickDesignerSupportProperties::hasBindingForProperty(testComponent, |
162 | view->engine()->contextForObject(testComponent), |
163 | "x" , |
164 | nullptr)); |
165 | QCOMPARE(testComponent->property("x" ).toInt(), 200); |
166 | |
167 | |
168 | |
169 | //Set a different binding/expression |
170 | QQuickDesignerSupportProperties::setPropertyBinding(object: testComponent, |
171 | context: view->engine()->contextForObject(testComponent), |
172 | propertyName: "x" , |
173 | expression: QLatin1String("Math.max(0, 300)" )); |
174 | |
175 | QVERIFY(QQuickDesignerSupportProperties::hasBindingForProperty(testComponent, |
176 | view->engine()->contextForObject(testComponent), |
177 | "x" , |
178 | nullptr)); |
179 | |
180 | QCOMPARE(testComponent->property("x" ).toInt(), 300); |
181 | |
182 | |
183 | |
184 | //Reset the binding to the default |
185 | QQuickDesignerSupportProperties::doResetProperty(object: testComponent, |
186 | context: view->engine()->contextForObject(testComponent), |
187 | propertyName: "x" ); |
188 | |
189 | |
190 | QVERIFY(QQuickDesignerSupportProperties::hasBindingForProperty(testComponent, |
191 | view->engine()->contextForObject(testComponent), |
192 | "x" , |
193 | nullptr)); |
194 | QCOMPARE(testComponent->property("x" ).toInt(), 200); |
195 | } |
196 | |
197 | void tst_qquickdesignersupport::objectProperties() |
198 | { |
199 | QScopedPointer<QQuickView> view(new QQuickView); |
200 | view->engine()->setOutputWarningsToStandardError(false); |
201 | view->setSource(testFileUrl(fileName: "test.qml" )); |
202 | |
203 | QVERIFY(view->errors().isEmpty()); |
204 | |
205 | QQuickItem *rootItem = view->rootObject(); |
206 | |
207 | QVERIFY(rootItem); |
208 | |
209 | QQuickItem *rectangleItem = findItem<QQuickItem>(parent: view->rootObject(), objectName: QLatin1String("rectangleItem" )); |
210 | QVERIFY(rectangleItem); |
211 | |
212 | |
213 | //Read gradient property as QObject |
214 | int propertyIndex = rectangleItem->metaObject()->indexOfProperty(name: "containmentMask" ); |
215 | QVERIFY(propertyIndex > 0); |
216 | QMetaProperty metaProperty = rectangleItem->metaObject()->property(index: propertyIndex); |
217 | QVERIFY(metaProperty.isValid()); |
218 | |
219 | QVERIFY(QQuickDesignerSupportProperties::isPropertyQObject(metaProperty)); |
220 | |
221 | QObject *containmentItem = QQuickDesignerSupportProperties::readQObjectProperty(metaProperty, object: rectangleItem); |
222 | QVERIFY(containmentItem); |
223 | |
224 | |
225 | //The width property is not a QObject |
226 | propertyIndex = rectangleItem->metaObject()->indexOfProperty(name: "width" ); |
227 | QVERIFY(propertyIndex > 0); |
228 | metaProperty = rectangleItem->metaObject()->property(index: propertyIndex); |
229 | QVERIFY(metaProperty.isValid()); |
230 | QVERIFY(!QQuickDesignerSupportProperties::isPropertyQObject(metaProperty)); |
231 | } |
232 | |
233 | void tst_qquickdesignersupport::dynamicProperty() |
234 | { |
235 | QScopedPointer<QQuickView> view(new QQuickView); |
236 | view->engine()->setOutputWarningsToStandardError(false); |
237 | view->setSource(testFileUrl(fileName: "test.qml" )); |
238 | |
239 | QVERIFY(view->errors().isEmpty()); |
240 | |
241 | QQuickItem *rootItem = view->rootObject(); |
242 | |
243 | QVERIFY(rootItem); |
244 | |
245 | QQuickItem *simpleItem = findItem<QQuickItem>(parent: view->rootObject(), objectName: QLatin1String("simpleItem" )); |
246 | |
247 | QVERIFY(simpleItem); |
248 | |
249 | QQuickDesignerSupportProperties::registerNodeInstanceMetaObject(object: simpleItem, engine: view->engine()); |
250 | QQuickDesignerSupportProperties::getPropertyCache(object: simpleItem, engine: view->engine()); |
251 | |
252 | QQuickDesignerSupportProperties::createNewDynamicProperty(object: simpleItem, engine: view->engine(), name: QLatin1String("dynamicProperty" )); |
253 | |
254 | QQmlProperty property(simpleItem, "dynamicProperty" , view->engine()->contextForObject(simpleItem)); |
255 | QVERIFY(property.isValid()); |
256 | QVERIFY(property.write(QLatin1String("test" ))); |
257 | |
258 | |
259 | QCOMPARE(property.read().toString(), QLatin1String("test" )); |
260 | |
261 | //Force evalutation of all bindings |
262 | QQuickDesignerSupport::refreshExpressions(context: view->rootContext()); |
263 | |
264 | //Check if expression to dynamic property gets properly resolved |
265 | property = QQmlProperty(simpleItem, "testProperty" , view->engine()->contextForObject(simpleItem)); |
266 | QVERIFY(property.isValid()); |
267 | QCOMPARE(property.read().toString(), QLatin1String("test" )); |
268 | } |
269 | |
270 | void tst_qquickdesignersupport::createComponent() |
271 | { |
272 | QScopedPointer<QQuickView> view(new QQuickView); |
273 | view->engine()->setOutputWarningsToStandardError(false); |
274 | view->setSource(testFileUrl(fileName: "test.qml" )); |
275 | |
276 | QVERIFY(view->errors().isEmpty()); |
277 | |
278 | QQuickItem *rootItem = view->rootObject(); |
279 | |
280 | QVERIFY(rootItem); |
281 | |
282 | QObject *testComponentObject = QQuickDesignerSupportItems::createComponent(componentUrl: testFileUrl(fileName: "TestComponent.qml" ), context: view->rootContext()); |
283 | QVERIFY(testComponentObject); |
284 | |
285 | QVERIFY(QQuickDesignerSupportMetaInfo::isSubclassOf(testComponentObject, "QtQuick/Item" )); |
286 | } |
287 | |
288 | void tst_qquickdesignersupport::basicStates() |
289 | { |
290 | QScopedPointer<QQuickView> view(new QQuickView); |
291 | view->engine()->setOutputWarningsToStandardError(false); |
292 | view->setSource(testFileUrl(fileName: "test.qml" )); |
293 | |
294 | QVERIFY(view->errors().isEmpty()); |
295 | |
296 | QQuickItem *rootItem = view->rootObject(); |
297 | |
298 | QVERIFY(rootItem); |
299 | |
300 | QQuickStateGroup *stateGroup = QQuickItemPrivate::get(item: rootItem)->_states(); |
301 | |
302 | QVERIFY(stateGroup); |
303 | |
304 | QCOMPARE(stateGroup->states().count(), 2 ); |
305 | |
306 | QQuickState *state01 = stateGroup->states().first(); |
307 | QQuickState *state02 = stateGroup->states().last(); |
308 | |
309 | QVERIFY(state01); |
310 | QVERIFY(state02); |
311 | |
312 | QCOMPARE(state01->property("name" ).toString(), QLatin1String("state01" )); |
313 | QCOMPARE(state02->property("name" ).toString(), QLatin1String("state02" )); |
314 | |
315 | QVERIFY(!QQuickDesignerSupportStates::isStateActive(state01, view->rootContext())); |
316 | QVERIFY(!QQuickDesignerSupportStates::isStateActive(state01, view->rootContext())); |
317 | |
318 | QQuickDesignerSupportStates::activateState(object: state01, context: view->rootContext()); |
319 | QVERIFY(QQuickDesignerSupportStates::isStateActive(state01, view->rootContext())); |
320 | |
321 | QQuickDesignerSupportStates::activateState(object: state02, context: view->rootContext()); |
322 | QVERIFY(QQuickDesignerSupportStates::isStateActive(state02, view->rootContext())); |
323 | QVERIFY(!QQuickDesignerSupportStates::isStateActive(state01, view->rootContext())); |
324 | |
325 | QQuickDesignerSupportStates::deactivateState(object: state02); |
326 | QVERIFY(!QQuickDesignerSupportStates::isStateActive(state01, view->rootContext())); |
327 | QVERIFY(!QQuickDesignerSupportStates::isStateActive(state01, view->rootContext())); |
328 | } |
329 | |
330 | void tst_qquickdesignersupport::statesPropertyChanges() |
331 | { |
332 | QScopedPointer<QQuickView> view(new QQuickView); |
333 | view->engine()->setOutputWarningsToStandardError(false); |
334 | view->setSource(testFileUrl(fileName: "test.qml" )); |
335 | |
336 | QVERIFY(view->errors().isEmpty()); |
337 | |
338 | QQuickItem *rootItem = view->rootObject(); |
339 | |
340 | QVERIFY(rootItem); |
341 | |
342 | QQuickItem *simpleItem = findItem<QQuickItem>(parent: view->rootObject(), objectName: QLatin1String("simpleItem" )); |
343 | |
344 | QVERIFY(simpleItem); |
345 | |
346 | QQuickStateGroup *stateGroup = QQuickItemPrivate::get(item: rootItem)->_states(); |
347 | |
348 | QVERIFY(stateGroup); |
349 | |
350 | QCOMPARE(stateGroup->states().count(), 2 ); |
351 | |
352 | QQuickState *state01 = stateGroup->states().first(); |
353 | QQuickState *state02 = stateGroup->states().last(); |
354 | |
355 | QVERIFY(state01); |
356 | QVERIFY(state02); |
357 | |
358 | QCOMPARE(state01->property("name" ).toString(), QLatin1String("state01" )); |
359 | QCOMPARE(state02->property("name" ).toString(), QLatin1String("state02" )); |
360 | |
361 | //PropertyChanges are parsed lazily |
362 | QQuickDesignerSupportStates::activateState(object: state01, context: view->rootContext()); |
363 | QQuickDesignerSupportStates::deactivateState(object: state01); |
364 | |
365 | QQuickStatePrivate *statePrivate01 = static_cast<QQuickStatePrivate *>(QQuickStatePrivate::get(o: state01)); |
366 | |
367 | QCOMPARE(state01->operationCount(), 1); |
368 | |
369 | QCOMPARE(statePrivate01->operations.count(), 1); |
370 | |
371 | QQuickStateOperation *propertyChange = statePrivate01->operations.at(i: 0).data(); |
372 | |
373 | QCOMPARE(QQuickDesignerSupportPropertyChanges::stateObject(propertyChange), state01); |
374 | |
375 | QQuickDesignerSupportPropertyChanges::changeValue(propertyChanges: propertyChange, propertyName: "width" , value: 300); |
376 | |
377 | QCOMPARE(simpleItem->property("width" ).toInt(), 0); |
378 | QQuickDesignerSupportStates::activateState(object: state01, context: view->rootContext()); |
379 | QCOMPARE(simpleItem->property("width" ).toInt(), 300); |
380 | QQuickDesignerSupportStates::deactivateState(object: state01); |
381 | QCOMPARE(simpleItem->property("width" ).toInt(), 0); |
382 | |
383 | //Set "base state value" in state1 using the revert list |
384 | QQuickDesignerSupportStates::activateState(object: state01, context: view->rootContext()); |
385 | QQuickDesignerSupportStates::changeValueInRevertList(state: state01, target: simpleItem, propertyName: "width" , value: 200); |
386 | QCOMPARE(simpleItem->property("width" ).toInt(), 300); |
387 | QQuickDesignerSupportStates::deactivateState(object: state01); |
388 | QCOMPARE(simpleItem->property("width" ).toInt(), 200); |
389 | |
390 | |
391 | //Create new PropertyChanges |
392 | QQuickPropertyChanges *newPropertyChange = new QQuickPropertyChanges(); |
393 | newPropertyChange->setParent(state01); |
394 | QQmlListProperty<QQuickStateOperation> changes = state01->changes(); |
395 | QQuickStatePrivate::operations_append(prop: &changes, op: newPropertyChange); |
396 | |
397 | newPropertyChange->setObject(rootItem); |
398 | |
399 | QQuickDesignerSupportPropertyChanges::attachToState(propertyChanges: newPropertyChange); |
400 | |
401 | QCOMPARE(rootItem, QQuickDesignerSupportPropertyChanges::targetObject(newPropertyChange)); |
402 | |
403 | QCOMPARE(state01->operationCount(), 2); |
404 | QCOMPARE(statePrivate01->operations.count(), 2); |
405 | |
406 | QCOMPARE(QQuickDesignerSupportPropertyChanges::stateObject(newPropertyChange), state01); |
407 | |
408 | //Set color for rootItem in state1 |
409 | QQuickDesignerSupportPropertyChanges::changeValue(propertyChanges: newPropertyChange, propertyName: "color" , value: QColor(Qt::red)); |
410 | |
411 | QQuickDesignerSupportStates::activateState(object: state01, context: view->rootContext()); |
412 | QCOMPARE(rootItem->property("color" ).value<QColor>(), QColor(Qt::red)); |
413 | QQuickDesignerSupportStates::deactivateState(object: state01); |
414 | QCOMPARE(rootItem->property("color" ).value<QColor>(), QColor(Qt::white)); |
415 | |
416 | QQuickDesignerSupportPropertyChanges::removeProperty(propertyChanges: newPropertyChange, propertyName: "color" ); |
417 | QQuickDesignerSupportStates::activateState(object: state01, context: view->rootContext()); |
418 | QCOMPARE(rootItem->property("color" ).value<QColor>(), QColor(Qt::white)); |
419 | |
420 | } |
421 | |
422 | static QObject * s_object = nullptr; |
423 | static QQuickDesignerSupport::PropertyName s_propertyName; |
424 | |
425 | static void notifyPropertyChangeCallBackFunction(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName) |
426 | { |
427 | s_object = object; |
428 | s_propertyName = propertyName; |
429 | } |
430 | |
431 | static void (*notifyPropertyChangeCallBackPointer)(QObject *, const QQuickDesignerSupport::PropertyName &) = ¬ifyPropertyChangeCallBackFunction; |
432 | |
433 | |
434 | void tst_qquickdesignersupport::testNotifyPropertyChangeCallBack() |
435 | { |
436 | QScopedPointer<QQuickView> view(new QQuickView); |
437 | view->engine()->setOutputWarningsToStandardError(false); |
438 | view->setSource(testFileUrl(fileName: "test.qml" )); |
439 | |
440 | QVERIFY(view->errors().isEmpty()); |
441 | |
442 | QQuickItem *rootItem = view->rootObject(); |
443 | |
444 | QVERIFY(rootItem); |
445 | |
446 | QQuickRectangle *rectangle = static_cast<QQuickRectangle *>(rootItem); |
447 | QVERIFY(rectangle); |
448 | |
449 | QQuickDesignerSupportProperties::registerNodeInstanceMetaObject(object: rectangle, engine: view->engine()); |
450 | |
451 | QQuickGradient *gradient = new QQuickGradient(rectangle); |
452 | |
453 | QQuickDesignerSupportMetaInfo::registerNotifyPropertyChangeCallBack(callback: notifyPropertyChangeCallBackPointer); |
454 | |
455 | rectangle->setProperty(name: "gradient" , value: QVariant::fromValue<QJSValue>(value: view->engine()->newQObject(object: gradient))); |
456 | |
457 | QVERIFY(s_object); |
458 | QCOMPARE(s_object, rootItem); |
459 | QCOMPARE(s_propertyName, QQuickDesignerSupport::PropertyName("gradient" )); |
460 | } |
461 | |
462 | static void fixResourcePathsForObjectCallBackFunction(QObject *object) |
463 | { |
464 | s_object = object; |
465 | } |
466 | |
467 | static void (*fixResourcePathsForObjectCallBackPointer)(QObject *) = &fixResourcePathsForObjectCallBackFunction; |
468 | |
469 | void tst_qquickdesignersupport::testFixResourcePathsForObjectCallBack() |
470 | { |
471 | QScopedPointer<QQuickView> view(new QQuickView); |
472 | view->engine()->setOutputWarningsToStandardError(false); |
473 | view->setSource(testFileUrl(fileName: "test.qml" )); |
474 | |
475 | QVERIFY(view->errors().isEmpty()); |
476 | |
477 | QQuickItem *rootItem = view->rootObject(); |
478 | |
479 | QVERIFY(rootItem); |
480 | |
481 | s_object = nullptr; |
482 | |
483 | QQuickDesignerSupportItems::registerFixResourcePathsForObjectCallBack(callback: fixResourcePathsForObjectCallBackPointer); |
484 | |
485 | QQuickItem *simpleItem = findItem<QQuickItem>(parent: view->rootObject(), objectName: QLatin1String("simpleItem" )); |
486 | |
487 | QVERIFY(simpleItem); |
488 | |
489 | QQuickDesignerSupportItems::tweakObjects(object: simpleItem); |
490 | |
491 | //Check that the fixResourcePathsForObjectCallBack was called on simpleItem |
492 | QCOMPARE(simpleItem , s_object); |
493 | } |
494 | |
495 | void doComponentCompleteRecursive(QObject *object) |
496 | { |
497 | if (object) { |
498 | QQuickItem *item = qobject_cast<QQuickItem*>(object); |
499 | |
500 | if (item && DesignerSupport::isComponentComplete(item)) |
501 | return; |
502 | |
503 | DesignerSupport::emitComponentCompleteSignalForAttachedProperty(item: object); |
504 | |
505 | QList<QObject*> childList = object->children(); |
506 | |
507 | if (item) { |
508 | foreach (QQuickItem *childItem, item->childItems()) { |
509 | if (!childList.contains(t: childItem)) |
510 | childList.append(t: childItem); |
511 | } |
512 | } |
513 | |
514 | foreach (QObject *child, childList) |
515 | doComponentCompleteRecursive(object: child); |
516 | |
517 | if (item) { |
518 | static_cast<QQmlParserStatus*>(item)->componentComplete(); |
519 | } else { |
520 | QQmlParserStatus *qmlParserStatus = dynamic_cast< QQmlParserStatus*>(object); |
521 | if (qmlParserStatus) |
522 | qmlParserStatus->componentComplete(); |
523 | } |
524 | } |
525 | } |
526 | |
527 | void tst_qquickdesignersupport::testComponentOnCompleteSignal() |
528 | { |
529 | { |
530 | QScopedPointer<QQuickView> view(new QQuickView); |
531 | view->engine()->setOutputWarningsToStandardError(false); |
532 | view->setSource(testFileUrl(fileName: "componentTest.qml" )); |
533 | |
534 | QVERIFY(view->errors().isEmpty()); |
535 | QQuickItem *rootItem = view->rootObject(); |
536 | QVERIFY(rootItem); |
537 | |
538 | QQuickItem *item = findItem<QQuickItem>(parent: view->rootObject(), objectName: QLatin1String("topLevelComplete" )); |
539 | QVERIFY(item); |
540 | QCOMPARE(item->property("color" ).value<QColor>(), QColor("red" )); |
541 | |
542 | item = findItem<QQuickItem>(parent: view->rootObject(), objectName: QLatin1String("implemented" )); |
543 | QVERIFY(item); |
544 | QCOMPARE(item->property("color" ).value<QColor>(), QColor("blue" )); |
545 | |
546 | item = findItem<QQuickItem>(parent: view->rootObject(), objectName: QLatin1String("most inner" )); |
547 | QVERIFY(item); |
548 | QCOMPARE(item->property("color" ).value<QColor>(), QColor("green" )); |
549 | } |
550 | |
551 | { |
552 | ComponentCompleteDisabler disableComponentComplete; |
553 | |
554 | QScopedPointer<QQuickView> view(new QQuickView); |
555 | view->engine()->setOutputWarningsToStandardError(false); |
556 | view->setSource(testFileUrl(fileName: "componentTest.qml" )); |
557 | |
558 | QVERIFY(view->errors().isEmpty()); |
559 | QQuickItem *rootItem = view->rootObject(); |
560 | QVERIFY(rootItem); |
561 | |
562 | QQuickItem *item = findItem<QQuickItem>(parent: view->rootObject(), objectName: QLatin1String("topLevelComplete" )); |
563 | QVERIFY(item); |
564 | QCOMPARE(item->property("color" ).value<QColor>(), QColor("white" )); |
565 | |
566 | item = findItem<QQuickItem>(parent: view->rootObject(), objectName: QLatin1String("implemented" )); |
567 | QVERIFY(item); |
568 | QCOMPARE(item->property("color" ).value<QColor>(), QColor("white" )); |
569 | |
570 | item = findItem<QQuickItem>(parent: view->rootObject(), objectName: QLatin1String("most inner" )); |
571 | QVERIFY(item); |
572 | QCOMPARE(item->property("color" ).value<QColor>(), QColor("white" )); |
573 | |
574 | doComponentCompleteRecursive(object: rootItem); |
575 | |
576 | item = findItem<QQuickItem>(parent: view->rootObject(), objectName: QLatin1String("topLevelComplete" )); |
577 | QVERIFY(item); |
578 | QCOMPARE(item->property("color" ).value<QColor>(), QColor("red" )); |
579 | |
580 | item = findItem<QQuickItem>(parent: view->rootObject(), objectName: QLatin1String("implemented" )); |
581 | QVERIFY(item); |
582 | QCOMPARE(item->property("color" ).value<QColor>(), QColor("blue" )); |
583 | |
584 | item = findItem<QQuickItem>(parent: view->rootObject(), objectName: QLatin1String("most inner" )); |
585 | QVERIFY(item); |
586 | QCOMPARE(item->property("color" ).value<QColor>(), QColor("green" )); |
587 | } |
588 | } |
589 | |
590 | void tst_qquickdesignersupport::testPropertyNames() |
591 | { |
592 | #ifdef Q_CC_MINGW |
593 | QSKIP("QQuickDesignerSupportProperties::registerCustomData segfaults on mingw. QTBUG-90869" ); |
594 | #endif |
595 | |
596 | QScopedPointer<QQuickView> view(new QQuickView); |
597 | view->engine()->setOutputWarningsToStandardError(false); |
598 | view->setSource(testFileUrl(fileName: "propertyNameTest.qml" )); |
599 | |
600 | QVERIFY(view->errors().isEmpty()); |
601 | QQuickItem *rootItem = view->rootObject(); |
602 | QVERIFY(rootItem); |
603 | |
604 | QQuickDesignerSupport::PropertyNameList names = QQuickDesignerSupportProperties::allPropertyNames(object: rootItem); |
605 | QVERIFY(!names.isEmpty()); |
606 | QVERIFY(names.contains("width" )); |
607 | QVERIFY(names.contains("height" )); |
608 | QVERIFY(names.contains("clip" )); |
609 | QVERIFY(names.contains("opacity" )); |
610 | QVERIFY(names.contains("childrenRect" )); |
611 | QVERIFY(names.contains("activeFocus" )); |
612 | QVERIFY(names.contains("border.width" )); |
613 | names = QQuickDesignerSupportProperties::propertyNameListForWritableProperties(object: rootItem); |
614 | QVERIFY(!names.isEmpty()); |
615 | QVERIFY(names.contains("width" )); |
616 | QVERIFY(names.contains("height" )); |
617 | QVERIFY(names.contains("opacity" )); |
618 | QVERIFY(names.contains("clip" )); |
619 | QVERIFY(!names.contains("childrenRect" )); |
620 | QVERIFY(!names.contains("activeFocus" )); |
621 | QVERIFY(names.contains("border.width" )); |
622 | |
623 | QQuickItem *recursiveProperty = findItem<QQuickItem>(parent: rootItem, objectName: QLatin1String("recursiveProperty" )); |
624 | QVERIFY(recursiveProperty); |
625 | names = QQuickDesignerSupportProperties::allPropertyNames(object: recursiveProperty); |
626 | QVERIFY(!names.isEmpty()); |
627 | QVERIFY(names.contains("testProperty" )); |
628 | QVERIFY(names.contains("myproperty.testProperty" )); |
629 | |
630 | names = QQuickDesignerSupportProperties::propertyNameListForWritableProperties(object: recursiveProperty); |
631 | QVERIFY(!names.isEmpty()); |
632 | QVERIFY(!names.contains("testProperty" )); |
633 | } |
634 | |
635 | QTEST_MAIN(tst_qquickdesignersupport) |
636 | |
637 | #include "tst_qquickdesignersupport.moc" |
638 | |