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
46using namespace QQuickVisualTestUtil;
47
48class tst_qquickdesignersupport : public QQmlDataTest
49{
50 Q_OBJECT
51public:
52 tst_qquickdesignersupport() {}
53
54private 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
68void 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
121void 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
197void 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
233void 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
270void 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
288void 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
330void 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
422static QObject * s_object = nullptr;
423static QQuickDesignerSupport::PropertyName s_propertyName;
424
425static void notifyPropertyChangeCallBackFunction(QObject *object, const QQuickDesignerSupport::PropertyName &propertyName)
426{
427 s_object = object;
428 s_propertyName = propertyName;
429}
430
431static void (*notifyPropertyChangeCallBackPointer)(QObject *, const QQuickDesignerSupport::PropertyName &) = &notifyPropertyChangeCallBackFunction;
432
433
434void 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
462static void fixResourcePathsForObjectCallBackFunction(QObject *object)
463{
464 s_object = object;
465}
466
467static void (*fixResourcePathsForObjectCallBackPointer)(QObject *) = &fixResourcePathsForObjectCallBackFunction;
468
469void 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
495void 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
527void 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
590void 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
635QTEST_MAIN(tst_qquickdesignersupport)
636
637#include "tst_qquickdesignersupport.moc"
638

source code of qtdeclarative/tests/auto/quick/qquickdesignersupport/tst_qquickdesignersupport.cpp