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 | |
29 | #include <qtest.h> |
30 | #include <QUrl> |
31 | #include <QFileInfo> |
32 | #include <QDir> |
33 | #include <QQmlEngine> |
34 | #include <QQmlComponent> |
35 | #include <QtQml/qqml.h> |
36 | #include <QtQml/qqmlprivate.h> |
37 | #include <QtQml/qqmlproperty.h> |
38 | #include <QDebug> |
39 | #include <private/qquickstate_p.h> |
40 | #include "../../shared/util.h" |
41 | |
42 | class tst_qqmllistreference : public QQmlDataTest |
43 | { |
44 | Q_OBJECT |
45 | public: |
46 | tst_qqmllistreference() {} |
47 | |
48 | private: |
49 | void modeData(); |
50 | |
51 | private slots: |
52 | void initTestCase(); |
53 | void qmllistreference(); |
54 | void qmllistreference_invalid(); |
55 | void isValid(); |
56 | void object(); |
57 | void listElementType(); |
58 | void canAppend(); |
59 | void canAt(); |
60 | void canClear(); |
61 | void canCount(); |
62 | void canReplace(); |
63 | void canRemoveLast(); |
64 | void isReadable(); |
65 | void isManipulable(); |
66 | void append(); |
67 | void at(); |
68 | void clear_data() { modeData(); } |
69 | void clear(); |
70 | void count(); |
71 | void replace_data() { modeData(); } |
72 | void replace(); |
73 | void removeLast_data() { modeData(); } |
74 | void removeLast(); |
75 | void copy(); |
76 | void qmlmetaproperty(); |
77 | void engineTypes(); |
78 | void variantToList(); |
79 | void listProperty(); |
80 | }; |
81 | |
82 | class TestType : public QObject |
83 | { |
84 | Q_OBJECT |
85 | Q_PROPERTY(QQmlListProperty<TestType> data READ dataProperty) |
86 | Q_PROPERTY(int intProperty READ intProperty) |
87 | |
88 | public: |
89 | enum Mode { |
90 | SyntheticClear, |
91 | SyntheticReplace, |
92 | SyntheticClearAndReplace, |
93 | SyntheticRemoveLast, |
94 | SyntheticRemoveLastAndReplace, |
95 | AutomaticReference, |
96 | AutomaticPointer |
97 | }; |
98 | |
99 | static void append(QQmlListProperty<TestType> *p, TestType *v) { |
100 | reinterpret_cast<QList<TestType *> *>(p->data)->append(t: v); |
101 | } |
102 | static int count(QQmlListProperty<TestType> *p) { |
103 | return reinterpret_cast<QList<TestType *> *>(p->data)->count(); |
104 | } |
105 | static TestType *at(QQmlListProperty<TestType> *p, int idx) { |
106 | return reinterpret_cast<QList<TestType *> *>(p->data)->at(i: idx); |
107 | } |
108 | static void clear(QQmlListProperty<TestType> *p) { |
109 | return reinterpret_cast<QList<TestType *> *>(p->data)->clear(); |
110 | } |
111 | static void replace(QQmlListProperty<TestType> *p, int idx, TestType *v) { |
112 | return reinterpret_cast<QList<TestType *> *>(p->data)->replace(i: idx, t: v); |
113 | } |
114 | static void removeLast(QQmlListProperty<TestType> *p) { |
115 | return reinterpret_cast<QList<TestType *> *>(p->data)->removeLast(); |
116 | } |
117 | |
118 | TestType(Mode mode = AutomaticReference) |
119 | { |
120 | switch (mode) { |
121 | case SyntheticClear: |
122 | property = QQmlListProperty<TestType>(this, &data, append, count, at, nullptr, |
123 | replace, removeLast); |
124 | break; |
125 | case SyntheticReplace: |
126 | property = QQmlListProperty<TestType>(this, &data, append, count, at, clear, |
127 | nullptr, removeLast); |
128 | break; |
129 | case SyntheticClearAndReplace: |
130 | property = QQmlListProperty<TestType>(this, &data, append, count, at, nullptr, |
131 | nullptr, removeLast); |
132 | break; |
133 | case SyntheticRemoveLast: |
134 | property = QQmlListProperty<TestType>(this, &data, append, count, at, clear, |
135 | replace, nullptr); |
136 | break; |
137 | case SyntheticRemoveLastAndReplace: |
138 | property = QQmlListProperty<TestType>(this, &data, append, count, at, clear, |
139 | nullptr, nullptr); |
140 | break; |
141 | case AutomaticReference: |
142 | property = QQmlListProperty<TestType>(this, data); |
143 | break; |
144 | case AutomaticPointer: |
145 | property = QQmlListProperty<TestType>(this, &data); |
146 | break; |
147 | } |
148 | } |
149 | |
150 | QQmlListProperty<TestType> dataProperty() { return property; } |
151 | int intProperty() const { return 10; } |
152 | |
153 | QList<TestType *> data; |
154 | QQmlListProperty<TestType> property; |
155 | }; |
156 | |
157 | Q_DECLARE_METATYPE(TestType::Mode) |
158 | |
159 | void tst_qqmllistreference::modeData() |
160 | { |
161 | QTest::addColumn<TestType::Mode>(name: "mode" ); |
162 | QTest::addRow(format: "AutomaticReference" ) << TestType::AutomaticReference; |
163 | QTest::addRow(format: "AutomaticPointer" ) << TestType::AutomaticPointer; |
164 | QTest::addRow(format: "SyntheticClear" ) << TestType::SyntheticClear; |
165 | QTest::addRow(format: "SyntheticReplace" ) << TestType::SyntheticReplace; |
166 | QTest::addRow(format: "SyntheticClearAndReplace" ) << TestType::SyntheticClearAndReplace; |
167 | QTest::addRow(format: "SyntheticRemoveLast" ) << TestType::SyntheticRemoveLast; |
168 | QTest::addRow(format: "SyntheticRemoveLastAndReplace" ) << TestType::SyntheticRemoveLastAndReplace; |
169 | } |
170 | |
171 | void tst_qqmllistreference::initTestCase() |
172 | { |
173 | QQmlDataTest::initTestCase(); |
174 | qmlRegisterAnonymousType<TestType>(uri: "Test" , versionMajor: 1); |
175 | } |
176 | |
177 | void tst_qqmllistreference::qmllistreference() |
178 | { |
179 | TestType tt; |
180 | |
181 | QQmlListReference r(&tt, "data" ); |
182 | QVERIFY(r.isValid()); |
183 | QCOMPARE(r.count(), 0); |
184 | |
185 | tt.data.append(t: &tt); |
186 | QCOMPARE(r.count(), 1); |
187 | } |
188 | |
189 | void tst_qqmllistreference::qmllistreference_invalid() |
190 | { |
191 | TestType tt; |
192 | |
193 | // Invalid |
194 | { |
195 | QQmlListReference r; |
196 | QVERIFY(!r.isValid()); |
197 | QVERIFY(!r.object()); |
198 | QVERIFY(!r.listElementType()); |
199 | QVERIFY(!r.canAt()); |
200 | QVERIFY(!r.canClear()); |
201 | QVERIFY(!r.canCount()); |
202 | QVERIFY(!r.append(nullptr)); |
203 | QVERIFY(!r.at(10)); |
204 | QVERIFY(!r.clear()); |
205 | QCOMPARE(r.count(), 0); |
206 | QVERIFY(!r.isReadable()); |
207 | QVERIFY(!r.isManipulable()); |
208 | } |
209 | |
210 | // Non-property |
211 | { |
212 | QQmlListReference r(&tt, "blah" ); |
213 | QVERIFY(!r.isValid()); |
214 | QVERIFY(!r.object()); |
215 | QVERIFY(!r.listElementType()); |
216 | QVERIFY(!r.canAt()); |
217 | QVERIFY(!r.canClear()); |
218 | QVERIFY(!r.canCount()); |
219 | QVERIFY(!r.append(nullptr)); |
220 | QVERIFY(!r.at(10)); |
221 | QVERIFY(!r.clear()); |
222 | QCOMPARE(r.count(), 0); |
223 | QVERIFY(!r.isReadable()); |
224 | QVERIFY(!r.isManipulable()); |
225 | } |
226 | |
227 | // Non-list property |
228 | { |
229 | QQmlListReference r(&tt, "intProperty" ); |
230 | QVERIFY(!r.isValid()); |
231 | QVERIFY(!r.object()); |
232 | QVERIFY(!r.listElementType()); |
233 | QVERIFY(!r.canAt()); |
234 | QVERIFY(!r.canClear()); |
235 | QVERIFY(!r.canCount()); |
236 | QVERIFY(!r.append(nullptr)); |
237 | QVERIFY(!r.at(10)); |
238 | QVERIFY(!r.clear()); |
239 | QCOMPARE(r.count(), 0); |
240 | QVERIFY(!r.isReadable()); |
241 | QVERIFY(!r.isManipulable()); |
242 | } |
243 | } |
244 | |
245 | void tst_qqmllistreference::isValid() |
246 | { |
247 | TestType *tt = new TestType; |
248 | |
249 | { |
250 | QQmlListReference ref; |
251 | QVERIFY(!ref.isValid()); |
252 | } |
253 | |
254 | { |
255 | QQmlListReference ref(tt, "blah" ); |
256 | QVERIFY(!ref.isValid()); |
257 | } |
258 | |
259 | { |
260 | QQmlListReference ref(tt, "data" ); |
261 | QVERIFY(ref.isValid()); |
262 | delete tt; |
263 | QVERIFY(!ref.isValid()); |
264 | } |
265 | } |
266 | |
267 | void tst_qqmllistreference::object() |
268 | { |
269 | TestType *tt = new TestType; |
270 | |
271 | { |
272 | QQmlListReference ref; |
273 | QVERIFY(!ref.object()); |
274 | } |
275 | |
276 | { |
277 | QQmlListReference ref(tt, "blah" ); |
278 | QVERIFY(!ref.object()); |
279 | } |
280 | |
281 | { |
282 | QQmlListReference ref(tt, "data" ); |
283 | QCOMPARE(ref.object(), tt); |
284 | delete tt; |
285 | QVERIFY(!ref.object()); |
286 | } |
287 | } |
288 | |
289 | void tst_qqmllistreference::listElementType() |
290 | { |
291 | TestType *tt = new TestType; |
292 | |
293 | { |
294 | QQmlListReference ref; |
295 | QVERIFY(!ref.listElementType()); |
296 | } |
297 | |
298 | { |
299 | QQmlListReference ref(tt, "blah" ); |
300 | QVERIFY(!ref.listElementType()); |
301 | } |
302 | |
303 | { |
304 | QQmlListReference ref(tt, "data" ); |
305 | QCOMPARE(ref.listElementType(), &TestType::staticMetaObject); |
306 | delete tt; |
307 | QVERIFY(!ref.listElementType()); |
308 | } |
309 | } |
310 | |
311 | void tst_qqmllistreference::canAppend() |
312 | { |
313 | TestType *tt = new TestType; |
314 | |
315 | { |
316 | QQmlListReference ref; |
317 | QVERIFY(!ref.canAppend()); |
318 | } |
319 | |
320 | { |
321 | QQmlListReference ref(tt, "blah" ); |
322 | QVERIFY(!ref.canAppend()); |
323 | } |
324 | |
325 | { |
326 | QQmlListReference ref(tt, "data" ); |
327 | QVERIFY(ref.canAppend()); |
328 | delete tt; |
329 | QVERIFY(!ref.canAppend()); |
330 | } |
331 | |
332 | { |
333 | TestType tt; |
334 | tt.property.append = nullptr; |
335 | QQmlListReference ref(&tt, "data" ); |
336 | QVERIFY(!ref.canAppend()); |
337 | } |
338 | } |
339 | |
340 | void tst_qqmllistreference::canAt() |
341 | { |
342 | TestType *tt = new TestType; |
343 | |
344 | { |
345 | QQmlListReference ref; |
346 | QVERIFY(!ref.canAt()); |
347 | } |
348 | |
349 | { |
350 | QQmlListReference ref(tt, "blah" ); |
351 | QVERIFY(!ref.canAt()); |
352 | } |
353 | |
354 | { |
355 | QQmlListReference ref(tt, "data" ); |
356 | QVERIFY(ref.canAt()); |
357 | delete tt; |
358 | QVERIFY(!ref.canAt()); |
359 | } |
360 | |
361 | { |
362 | TestType tt; |
363 | tt.property.at = nullptr; |
364 | QQmlListReference ref(&tt, "data" ); |
365 | QVERIFY(!ref.canAt()); |
366 | } |
367 | } |
368 | |
369 | void tst_qqmllistreference::canClear() |
370 | { |
371 | TestType *tt = new TestType; |
372 | |
373 | { |
374 | QQmlListReference ref; |
375 | QVERIFY(!ref.canClear()); |
376 | } |
377 | |
378 | { |
379 | QQmlListReference ref(tt, "blah" ); |
380 | QVERIFY(!ref.canClear()); |
381 | } |
382 | |
383 | { |
384 | QQmlListReference ref(tt, "data" ); |
385 | QVERIFY(ref.canClear()); |
386 | delete tt; |
387 | QVERIFY(!ref.canClear()); |
388 | } |
389 | |
390 | { |
391 | TestType tt; |
392 | tt.property.clear = nullptr; |
393 | QQmlListReference ref(&tt, "data" ); |
394 | QVERIFY(!ref.canClear()); |
395 | } |
396 | } |
397 | |
398 | void tst_qqmllistreference::canCount() |
399 | { |
400 | TestType *tt = new TestType; |
401 | |
402 | { |
403 | QQmlListReference ref; |
404 | QVERIFY(!ref.canCount()); |
405 | } |
406 | |
407 | { |
408 | QQmlListReference ref(tt, "blah" ); |
409 | QVERIFY(!ref.canCount()); |
410 | } |
411 | |
412 | { |
413 | QQmlListReference ref(tt, "data" ); |
414 | QVERIFY(ref.canCount()); |
415 | delete tt; |
416 | QVERIFY(!ref.canCount()); |
417 | } |
418 | |
419 | { |
420 | TestType tt; |
421 | tt.property.count = nullptr; |
422 | QQmlListReference ref(&tt, "data" ); |
423 | QVERIFY(!ref.canCount()); |
424 | } |
425 | } |
426 | |
427 | void tst_qqmllistreference::canReplace() |
428 | { |
429 | QScopedPointer<TestType> tt(new TestType); |
430 | |
431 | { |
432 | QQmlListReference ref; |
433 | QVERIFY(!ref.canReplace()); |
434 | } |
435 | |
436 | { |
437 | QQmlListReference ref(tt.data(), "blah" ); |
438 | QVERIFY(!ref.canReplace()); |
439 | } |
440 | |
441 | { |
442 | QQmlListReference ref(tt.data(), "data" ); |
443 | QVERIFY(ref.canReplace()); |
444 | tt.reset(); |
445 | QVERIFY(!ref.canReplace()); |
446 | } |
447 | |
448 | { |
449 | TestType tt; |
450 | tt.property.replace = nullptr; |
451 | QQmlListReference ref(&tt, "data" ); |
452 | QVERIFY(!ref.canReplace()); |
453 | } |
454 | } |
455 | |
456 | void tst_qqmllistreference::canRemoveLast() |
457 | { |
458 | QScopedPointer<TestType> tt(new TestType); |
459 | |
460 | { |
461 | QQmlListReference ref; |
462 | QVERIFY(!ref.canRemoveLast()); |
463 | } |
464 | |
465 | { |
466 | QQmlListReference ref(tt.data(), "blah" ); |
467 | QVERIFY(!ref.canRemoveLast()); |
468 | } |
469 | |
470 | { |
471 | QQmlListReference ref(tt.data(), "data" ); |
472 | QVERIFY(ref.canRemoveLast()); |
473 | tt.reset(); |
474 | QVERIFY(!ref.canRemoveLast()); |
475 | } |
476 | |
477 | { |
478 | TestType tt; |
479 | tt.property.removeLast = nullptr; |
480 | QQmlListReference ref(&tt, "data" ); |
481 | QVERIFY(!ref.canRemoveLast()); |
482 | } |
483 | } |
484 | |
485 | void tst_qqmllistreference::isReadable() |
486 | { |
487 | TestType *tt = new TestType; |
488 | |
489 | { |
490 | QQmlListReference ref; |
491 | QVERIFY(!ref.isReadable()); |
492 | } |
493 | |
494 | { |
495 | QQmlListReference ref(tt, "blah" ); |
496 | QVERIFY(!ref.isReadable()); |
497 | } |
498 | |
499 | { |
500 | QQmlListReference ref(tt, "data" ); |
501 | QVERIFY(ref.isReadable()); |
502 | delete tt; |
503 | QVERIFY(!ref.isReadable()); |
504 | } |
505 | |
506 | { |
507 | TestType tt; |
508 | tt.property.count = nullptr; |
509 | QQmlListReference ref(&tt, "data" ); |
510 | QVERIFY(!ref.isReadable()); |
511 | } |
512 | } |
513 | |
514 | void tst_qqmllistreference::isManipulable() |
515 | { |
516 | TestType *tt = new TestType; |
517 | |
518 | { |
519 | QQmlListReference ref; |
520 | QVERIFY(!ref.isManipulable()); |
521 | } |
522 | |
523 | { |
524 | QQmlListReference ref(tt, "blah" ); |
525 | QVERIFY(!ref.isManipulable()); |
526 | } |
527 | |
528 | { |
529 | QQmlListReference ref(tt, "data" ); |
530 | QVERIFY(ref.isManipulable()); |
531 | delete tt; |
532 | QVERIFY(!ref.isManipulable()); |
533 | } |
534 | |
535 | { |
536 | TestType tt; |
537 | tt.property.count = nullptr; |
538 | QQmlListReference ref(&tt, "data" ); |
539 | QVERIFY(!ref.isManipulable()); |
540 | } |
541 | } |
542 | |
543 | void tst_qqmllistreference::append() |
544 | { |
545 | TestType *tt = new TestType; |
546 | QObject object; |
547 | |
548 | { |
549 | QQmlListReference ref; |
550 | QVERIFY(!ref.append(tt)); |
551 | } |
552 | |
553 | { |
554 | QQmlListReference ref(tt, "blah" ); |
555 | QVERIFY(!ref.append(tt)); |
556 | } |
557 | |
558 | { |
559 | QQmlListReference ref(tt, "data" ); |
560 | QVERIFY(ref.append(tt)); |
561 | QCOMPARE(tt->data.count(), 1); |
562 | QCOMPARE(tt->data.at(0), tt); |
563 | QVERIFY(!ref.append(&object)); |
564 | QCOMPARE(tt->data.count(), 1); |
565 | QCOMPARE(tt->data.at(0), tt); |
566 | QVERIFY(ref.append(nullptr)); |
567 | QCOMPARE(tt->data.count(), 2); |
568 | QCOMPARE(tt->data.at(0), tt); |
569 | QVERIFY(!tt->data.at(1)); |
570 | delete tt; |
571 | QVERIFY(!ref.append(nullptr)); |
572 | } |
573 | |
574 | { |
575 | TestType tt; |
576 | tt.property.append = nullptr; |
577 | QQmlListReference ref(&tt, "data" ); |
578 | QVERIFY(!ref.append(&tt)); |
579 | } |
580 | } |
581 | |
582 | void tst_qqmllistreference::at() |
583 | { |
584 | TestType *tt = new TestType; |
585 | tt->data.append(t: tt); |
586 | tt->data.append(t: 0); |
587 | tt->data.append(t: tt); |
588 | |
589 | { |
590 | QQmlListReference ref; |
591 | QVERIFY(!ref.at(0)); |
592 | } |
593 | |
594 | { |
595 | QQmlListReference ref(tt, "blah" ); |
596 | QVERIFY(!ref.at(0)); |
597 | } |
598 | |
599 | { |
600 | QQmlListReference ref(tt, "data" ); |
601 | QCOMPARE(ref.at(0), tt); |
602 | QVERIFY(!ref.at(1)); |
603 | QCOMPARE(ref.at(2), tt); |
604 | delete tt; |
605 | QVERIFY(!ref.at(0)); |
606 | } |
607 | |
608 | { |
609 | TestType tt; |
610 | tt.data.append(t: &tt); |
611 | tt.property.at = nullptr; |
612 | QQmlListReference ref(&tt, "data" ); |
613 | QVERIFY(!ref.at(0)); |
614 | } |
615 | } |
616 | |
617 | void tst_qqmllistreference::clear() |
618 | { |
619 | QFETCH(TestType::Mode, mode); |
620 | TestType *tt = new TestType(mode); |
621 | tt->data.append(t: tt); |
622 | tt->data.append(t: 0); |
623 | tt->data.append(t: tt); |
624 | |
625 | { |
626 | QQmlListReference ref; |
627 | QVERIFY(!ref.clear()); |
628 | } |
629 | |
630 | { |
631 | QQmlListReference ref(tt, "blah" ); |
632 | QVERIFY(!ref.clear()); |
633 | } |
634 | |
635 | { |
636 | QQmlListReference ref(tt, "data" ); |
637 | QVERIFY(ref.clear()); |
638 | QCOMPARE(tt->data.count(), 0); |
639 | delete tt; |
640 | QVERIFY(!ref.clear()); |
641 | } |
642 | |
643 | { |
644 | TestType tt; |
645 | tt.property.clear = nullptr; |
646 | QQmlListReference ref(&tt, "data" ); |
647 | QVERIFY(!ref.clear()); |
648 | } |
649 | } |
650 | |
651 | void tst_qqmllistreference::count() |
652 | { |
653 | TestType *tt = new TestType; |
654 | tt->data.append(t: tt); |
655 | tt->data.append(t: 0); |
656 | tt->data.append(t: tt); |
657 | |
658 | { |
659 | QQmlListReference ref; |
660 | QCOMPARE(ref.count(), 0); |
661 | } |
662 | |
663 | { |
664 | QQmlListReference ref(tt, "blah" ); |
665 | QCOMPARE(ref.count(), 0); |
666 | } |
667 | |
668 | { |
669 | QQmlListReference ref(tt, "data" ); |
670 | QCOMPARE(ref.count(), 3); |
671 | tt->data.removeAt(i: 1); |
672 | QCOMPARE(ref.count(), 2); |
673 | delete tt; |
674 | QCOMPARE(ref.count(), 0); |
675 | } |
676 | |
677 | { |
678 | TestType tt; |
679 | tt.data.append(t: &tt); |
680 | tt.property.count = nullptr; |
681 | QQmlListReference ref(&tt, "data" ); |
682 | QCOMPARE(ref.count(), 0); |
683 | } |
684 | } |
685 | |
686 | void tst_qqmllistreference::replace() |
687 | { |
688 | QFETCH(TestType::Mode, mode); |
689 | QScopedPointer<TestType> tt(new TestType(mode)); |
690 | tt->data.append(t: tt.get()); |
691 | tt->data.append(t: nullptr); |
692 | tt->data.append(t: tt.get()); |
693 | |
694 | { |
695 | QQmlListReference ref(tt.get(), "data" ); |
696 | QVERIFY(ref.replace(1, tt.get())); |
697 | QCOMPARE(ref.at(1), tt.get()); |
698 | QVERIFY(ref.replace(2, nullptr)); |
699 | QCOMPARE(ref.at(2), nullptr); |
700 | QCOMPARE(ref.count(), 3); |
701 | tt.reset(); |
702 | QVERIFY(!ref.replace(0, tt.get())); |
703 | } |
704 | |
705 | { |
706 | TestType tt; |
707 | tt.data.append(t: &tt); |
708 | tt.property.replace = nullptr; |
709 | QQmlListReference ref(&tt, "data" ); |
710 | QVERIFY(!ref.replace(0, nullptr)); |
711 | } |
712 | } |
713 | |
714 | void tst_qqmllistreference::removeLast() |
715 | { |
716 | QFETCH(TestType::Mode, mode); |
717 | QScopedPointer<TestType> tt(new TestType(mode)); |
718 | tt->data.append(t: tt.get()); |
719 | tt->data.append(t: nullptr); |
720 | tt->data.append(t: tt.get()); |
721 | |
722 | { |
723 | QQmlListReference ref; |
724 | QVERIFY(!ref.removeLast()); |
725 | } |
726 | |
727 | { |
728 | QQmlListReference ref(tt.get(), "blah" ); |
729 | QVERIFY(!ref.removeLast()); |
730 | } |
731 | |
732 | { |
733 | QQmlListReference ref(tt.get(), "data" ); |
734 | QCOMPARE(tt->data.count(), 3); |
735 | QVERIFY(ref.removeLast()); |
736 | QCOMPARE(tt->data.count(), 2); |
737 | tt.reset(); |
738 | QVERIFY(!ref.removeLast()); |
739 | } |
740 | |
741 | { |
742 | TestType tt; |
743 | tt.property.removeLast = nullptr; |
744 | QQmlListReference ref(&tt, "data" ); |
745 | ref.append(&tt); |
746 | QVERIFY(!ref.removeLast()); |
747 | } |
748 | } |
749 | |
750 | void tst_qqmllistreference::copy() |
751 | { |
752 | TestType tt; |
753 | tt.data.append(t: &tt); |
754 | tt.data.append(t: 0); |
755 | tt.data.append(t: &tt); |
756 | |
757 | QQmlListReference *r1 = new QQmlListReference(&tt, "data" ); |
758 | QCOMPARE(r1->count(), 3); |
759 | |
760 | QQmlListReference r2(*r1); |
761 | QQmlListReference r3; |
762 | r3 = *r1; |
763 | |
764 | QCOMPARE(r2.count(), 3); |
765 | QCOMPARE(r3.count(), 3); |
766 | |
767 | delete r1; |
768 | |
769 | QCOMPARE(r2.count(), 3); |
770 | QCOMPARE(r3.count(), 3); |
771 | |
772 | tt.data.removeAt(i: 2); |
773 | |
774 | QCOMPARE(r2.count(), 2); |
775 | QCOMPARE(r3.count(), 2); |
776 | } |
777 | |
778 | void tst_qqmllistreference::qmlmetaproperty() |
779 | { |
780 | TestType tt; |
781 | tt.data.append(t: &tt); |
782 | tt.data.append(t: 0); |
783 | tt.data.append(t: &tt); |
784 | |
785 | QQmlProperty prop(&tt, QLatin1String("data" )); |
786 | QVariant v = prop.read(); |
787 | QCOMPARE(v.userType(), qMetaTypeId<QQmlListReference>()); |
788 | QQmlListReference ref = qvariant_cast<QQmlListReference>(v); |
789 | QCOMPARE(ref.count(), 3); |
790 | QCOMPARE(ref.listElementType(), &TestType::staticMetaObject); |
791 | } |
792 | |
793 | void tst_qqmllistreference::engineTypes() |
794 | { |
795 | QQmlEngine engine; |
796 | QQmlComponent component(&engine, testFileUrl(fileName: "engineTypes.qml" )); |
797 | |
798 | QObject *o = component.create(); |
799 | QVERIFY(o); |
800 | |
801 | QQmlProperty p1(o, QLatin1String("myList" )); |
802 | QCOMPARE(p1.propertyTypeCategory(), QQmlProperty::List); |
803 | |
804 | QQmlProperty p2(o, QLatin1String("myList" ), engine.rootContext()); |
805 | QCOMPARE(p2.propertyTypeCategory(), QQmlProperty::List); |
806 | QVariant v = p2.read(); |
807 | QCOMPARE(v.userType(), qMetaTypeId<QQmlListReference>()); |
808 | QQmlListReference ref = qvariant_cast<QQmlListReference>(v); |
809 | QCOMPARE(ref.count(), 2); |
810 | QVERIFY(ref.listElementType()); |
811 | QVERIFY(ref.listElementType() != &QObject::staticMetaObject); |
812 | |
813 | delete o; |
814 | } |
815 | |
816 | void tst_qqmllistreference::variantToList() |
817 | { |
818 | QQmlEngine engine; |
819 | QQmlComponent component(&engine, testFileUrl(fileName: "variantToList.qml" )); |
820 | |
821 | QObject *o = component.create(); |
822 | QVERIFY(o); |
823 | |
824 | QCOMPARE(o->property("value" ).userType(), qMetaTypeId<QQmlListReference>()); |
825 | QCOMPARE(o->property("test" ).toInt(), 1); |
826 | |
827 | delete o; |
828 | } |
829 | |
830 | void tst_qqmllistreference::listProperty() |
831 | { |
832 | QQmlEngine engine; |
833 | QQmlComponent component(&engine, testFileUrl(fileName: "propertyList.qml" )); |
834 | |
835 | QScopedPointer<QObject> object( component.create() ); |
836 | QVERIFY(object != nullptr); |
837 | |
838 | QCOMPARE( object->property("state" ).toString(), QStringLiteral("MyState2" ) ); |
839 | QQmlListReference list( object.data(), "states" ); |
840 | QCOMPARE( list.count(), 2 ); |
841 | |
842 | QQuickState* state1 = dynamic_cast<QQuickState*>( list.at( 0 ) ); |
843 | QVERIFY(state1 != nullptr); |
844 | QCOMPARE( state1->name(), QStringLiteral("MyState1" ) ); |
845 | QQuickState* state2 = dynamic_cast<QQuickState*>( list.at( 1 ) ); |
846 | QVERIFY(state2 != nullptr); |
847 | |
848 | QCOMPARE( state2->name(), QStringLiteral("MyState2" ) ); |
849 | } |
850 | |
851 | |
852 | QTEST_MAIN(tst_qqmllistreference) |
853 | |
854 | #include "tst_qqmllistreference.moc" |
855 | |