2ea8205b08cd6ea52aba9b50e3a28fea2e68e702
[profile/ivi/qtdeclarative.git] / tests / auto / declarative / qsgpositioners / tst_qsgpositioners.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the test suite of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #include <QtTest/QtTest>
42 #include <private/qlistmodelinterface_p.h>
43 #include <qsgview.h>
44 #include <qdeclarativeengine.h>
45 #include <private/qsgrectangle_p.h>
46 #include <private/qsgpositioners_p.h>
47 #include <private/qdeclarativetransition_p.h>
48 #include <private/qsgitem_p.h>
49 #include <qdeclarativeexpression.h>
50 #include <QtWidgets/qgraphicswidget.h>
51 #include "../../../shared/util.h"
52
53 #ifdef Q_OS_SYMBIAN
54 // In Symbian OS test data is located in applications private dir
55 #define SRCDIR "."
56 #endif
57
58 class tst_qsgpositioners : public QObject
59 {
60     Q_OBJECT
61 public:
62     tst_qsgpositioners();
63
64 private slots:
65     void test_horizontal();
66     void test_horizontal_rtl();
67     void test_horizontal_spacing();
68     void test_horizontal_spacing_rightToLeft();
69     void test_horizontal_animated();
70     void test_horizontal_animated_rightToLeft();
71     void test_horizontal_animated_disabled();
72     void test_vertical();
73     void test_vertical_spacing();
74     void test_vertical_animated();
75     void test_grid();
76     void test_grid_topToBottom();
77     void test_grid_rightToLeft();
78     void test_grid_spacing();
79     void test_grid_row_column_spacing();
80     void test_grid_animated();
81     void test_grid_animated_rightToLeft();
82     void test_grid_zero_columns();
83     void test_propertychanges();
84     void test_repeater();
85     void test_flow();
86     void test_flow_rightToLeft();
87     void test_flow_topToBottom();
88     void test_flow_resize();
89     void test_flow_resize_rightToLeft();
90     void test_flow_implicit_resize();
91     void test_conflictinganchors();
92     void test_mirroring();
93     void test_allInvisible();
94     void test_attachedproperties();
95     void test_attachedproperties_data();
96     void test_attachedproperties_dynamic();
97
98 private:
99     QSGView *createView(const QString &filename, bool wait=true);
100 };
101
102 tst_qsgpositioners::tst_qsgpositioners()
103 {
104 }
105
106 void tst_qsgpositioners::test_horizontal()
107 {
108     QSGView *canvas = createView(SRCDIR "/data/horizontal.qml");
109
110     canvas->rootObject()->setProperty("testRightToLeft", false);
111
112     QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one");
113     QVERIFY(one != 0);
114
115     QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two");
116     QVERIFY(two != 0);
117
118     QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three");
119     QVERIFY(three != 0);
120
121     QCOMPARE(one->x(), 0.0);
122     QCOMPARE(one->y(), 0.0);
123     QCOMPARE(two->x(), 50.0);
124     QCOMPARE(two->y(), 0.0);
125     QCOMPARE(three->x(), 70.0);
126     QCOMPARE(three->y(), 0.0);
127
128     QSGItem *row = canvas->rootObject()->findChild<QSGItem*>("row");
129     QCOMPARE(row->width(), 110.0);
130     QCOMPARE(row->height(), 50.0);
131
132     delete canvas;
133 }
134
135 void tst_qsgpositioners::test_horizontal_rtl()
136 {
137     QSGView *canvas = createView(SRCDIR "/data/horizontal.qml");
138
139     canvas->rootObject()->setProperty("testRightToLeft", true);
140
141     QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one");
142     QVERIFY(one != 0);
143
144     QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two");
145     QVERIFY(two != 0);
146
147     QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three");
148     QVERIFY(three != 0);
149
150     QCOMPARE(one->x(), 60.0);
151     QCOMPARE(one->y(), 0.0);
152     QCOMPARE(two->x(), 40.0);
153     QCOMPARE(two->y(), 0.0);
154     QCOMPARE(three->x(), 0.0);
155     QCOMPARE(three->y(), 0.0);
156
157     QSGItem *row = canvas->rootObject()->findChild<QSGItem*>("row");
158     QCOMPARE(row->width(), 110.0);
159     QCOMPARE(row->height(), 50.0);
160
161     // Change the width of the row and check that items stay to the right
162     row->setWidth(200);
163     QTRY_COMPARE(one->x(), 150.0);
164     QCOMPARE(one->y(), 0.0);
165     QCOMPARE(two->x(), 130.0);
166     QCOMPARE(two->y(), 0.0);
167     QCOMPARE(three->x(), 90.0);
168     QCOMPARE(three->y(), 0.0);
169
170     delete canvas;
171 }
172
173 void tst_qsgpositioners::test_horizontal_spacing()
174 {
175     QSGView *canvas = createView(SRCDIR "/data/horizontal-spacing.qml");
176
177     canvas->rootObject()->setProperty("testRightToLeft", false);
178
179     QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one");
180     QVERIFY(one != 0);
181
182     QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two");
183     QVERIFY(two != 0);
184
185     QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three");
186     QVERIFY(three != 0);
187
188     QCOMPARE(one->x(), 0.0);
189     QCOMPARE(one->y(), 0.0);
190     QCOMPARE(two->x(), 60.0);
191     QCOMPARE(two->y(), 0.0);
192     QCOMPARE(three->x(), 90.0);
193     QCOMPARE(three->y(), 0.0);
194
195     QSGItem *row = canvas->rootObject()->findChild<QSGItem*>("row");
196     QCOMPARE(row->width(), 130.0);
197     QCOMPARE(row->height(), 50.0);
198
199     delete canvas;
200 }
201
202 void tst_qsgpositioners::test_horizontal_spacing_rightToLeft()
203 {
204     QSGView *canvas = createView(SRCDIR "/data/horizontal-spacing.qml");
205
206     canvas->rootObject()->setProperty("testRightToLeft", true);
207
208     QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one");
209     QVERIFY(one != 0);
210
211     QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two");
212     QVERIFY(two != 0);
213
214     QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three");
215     QVERIFY(three != 0);
216
217     QCOMPARE(one->x(), 80.0);
218     QCOMPARE(one->y(), 0.0);
219     QCOMPARE(two->x(), 50.0);
220     QCOMPARE(two->y(), 0.0);
221     QCOMPARE(three->x(), 00.0);
222     QCOMPARE(three->y(), 0.0);
223
224     QSGItem *row = canvas->rootObject()->findChild<QSGItem*>("row");
225     QCOMPARE(row->width(), 130.0);
226     QCOMPARE(row->height(), 50.0);
227
228     delete canvas;
229 }
230
231 void tst_qsgpositioners::test_horizontal_animated()
232 {
233     QSGView *canvas = createView(SRCDIR "/data/horizontal-animated.qml", false);
234
235     canvas->rootObject()->setProperty("testRightToLeft", false);
236
237     QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one");
238     QVERIFY(one != 0);
239
240     QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two");
241     QVERIFY(two != 0);
242
243     QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three");
244     QVERIFY(three != 0);
245
246     //Note that they animate in
247     QCOMPARE(one->x(), -100.0);
248     QCOMPARE(two->x(), -100.0);
249     QCOMPARE(three->x(), -100.0);
250
251     QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn
252
253     QSGItem *row = canvas->rootObject()->findChild<QSGItem*>("row");
254     QVERIFY(row);
255     QCOMPARE(row->width(), 100.0);
256     QCOMPARE(row->height(), 50.0);
257
258     //QTRY_COMPARE used instead of waiting for the expected time of animation completion
259     //Note that this means the duration of the animation is NOT tested
260
261     QTRY_COMPARE(one->x(), 0.0);
262     QTRY_COMPARE(one->y(), 0.0);
263     QTRY_COMPARE(two->isVisible(), false);
264     QTRY_COMPARE(two->x(), -100.0);//Not 'in' yet
265     QTRY_COMPARE(two->y(), 0.0);
266     QTRY_COMPARE(three->x(), 50.0);
267     QTRY_COMPARE(three->y(), 0.0);
268
269     //Add 'two'
270     two->setVisible(true);
271     QTRY_COMPARE(two->isVisible(), true);
272     QTRY_COMPARE(row->width(), 150.0);
273     QTRY_COMPARE(row->height(), 50.0);
274
275     QTest::qWait(0);//Let the animation start
276     QCOMPARE(two->x(), -100.0);
277     QCOMPARE(three->x(), 50.0);
278
279     QTRY_COMPARE(two->x(), 50.0);
280     QTRY_COMPARE(three->x(), 100.0);
281
282     delete canvas;
283 }
284
285 void tst_qsgpositioners::test_horizontal_animated_rightToLeft()
286 {
287     QSGView *canvas = createView(SRCDIR "/data/horizontal-animated.qml", false);
288
289     canvas->rootObject()->setProperty("testRightToLeft", true);
290
291     QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one");
292     QVERIFY(one != 0);
293
294     QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two");
295     QVERIFY(two != 0);
296
297     QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three");
298     QVERIFY(three != 0);
299
300     //Note that they animate in
301     QCOMPARE(one->x(), -100.0);
302     QCOMPARE(two->x(), -100.0);
303     QCOMPARE(three->x(), -100.0);
304
305     QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn
306
307     QSGItem *row = canvas->rootObject()->findChild<QSGItem*>("row");
308     QVERIFY(row);
309     QCOMPARE(row->width(), 100.0);
310     QCOMPARE(row->height(), 50.0);
311
312     //QTRY_COMPARE used instead of waiting for the expected time of animation completion
313     //Note that this means the duration of the animation is NOT tested
314
315     QTRY_COMPARE(one->x(), 50.0);
316     QTRY_COMPARE(one->y(), 0.0);
317     QTRY_COMPARE(two->isVisible(), false);
318     QTRY_COMPARE(two->x(), -100.0);//Not 'in' yet
319     QTRY_COMPARE(two->y(), 0.0);
320     QTRY_COMPARE(three->x(), 0.0);
321     QTRY_COMPARE(three->y(), 0.0);
322
323     //Add 'two'
324     two->setVisible(true);
325     QTRY_COMPARE(two->isVisible(), true);
326
327     // New size should propagate after visible change
328     QTRY_COMPARE(row->width(), 150.0);
329     QTRY_COMPARE(row->height(), 50.0);
330
331     QTest::qWait(0);//Let the animation start
332     QCOMPARE(one->x(), 50.0);
333     QCOMPARE(two->x(), -100.0);
334
335     QTRY_COMPARE(one->x(), 100.0);
336     QTRY_COMPARE(two->x(), 50.0);
337
338     delete canvas;
339 }
340
341 void tst_qsgpositioners::test_horizontal_animated_disabled()
342 {
343     QSGView *canvas = createView(SRCDIR "/data/horizontal-animated-disabled.qml");
344
345     QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one");
346     QVERIFY(one != 0);
347
348     QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two");
349     QVERIFY(two != 0);
350
351     QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three");
352     QVERIFY(three != 0);
353
354     QSGItem *row = canvas->rootObject()->findChild<QSGItem*>("row");
355     QVERIFY(row);
356
357     qApp->processEvents();
358
359     QCOMPARE(one->x(), 0.0);
360     QCOMPARE(one->y(), 0.0);
361     QCOMPARE(two->isVisible(), false);
362     QCOMPARE(two->x(), -100.0);//Not 'in' yet
363     QCOMPARE(two->y(), 0.0);
364     QCOMPARE(three->x(), 50.0);
365     QCOMPARE(three->y(), 0.0);
366
367     //Add 'two'
368     two->setVisible(true);
369     QCOMPARE(two->isVisible(), true);
370     qApp->processEvents();
371     QCOMPARE(row->width(), 150.0);
372     QCOMPARE(row->height(), 50.0);
373
374     qApp->processEvents();
375     QCOMPARE(two->x(), 50.0);
376     QCOMPARE(three->x(), 100.0);
377
378     delete canvas;
379 }
380
381 void tst_qsgpositioners::test_vertical()
382 {
383     QSGView *canvas = createView(SRCDIR "/data/vertical.qml");
384
385     QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one");
386     QVERIFY(one != 0);
387
388     QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two");
389     QVERIFY(two != 0);
390
391     QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three");
392     QVERIFY(three != 0);
393
394     QCOMPARE(one->x(), 0.0);
395     QCOMPARE(one->y(), 0.0);
396     QCOMPARE(two->x(), 0.0);
397     QCOMPARE(two->y(), 50.0);
398     QCOMPARE(three->x(), 0.0);
399     QCOMPARE(three->y(), 60.0);
400
401     QSGItem *column = canvas->rootObject()->findChild<QSGItem*>("column");
402     QVERIFY(column);
403     QCOMPARE(column->height(), 80.0);
404     QCOMPARE(column->width(), 50.0);
405
406     delete canvas;
407 }
408
409 void tst_qsgpositioners::test_vertical_spacing()
410 {
411     QSGView *canvas = createView(SRCDIR "/data/vertical-spacing.qml");
412
413     QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one");
414     QVERIFY(one != 0);
415
416     QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two");
417     QVERIFY(two != 0);
418
419     QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three");
420     QVERIFY(three != 0);
421
422     QCOMPARE(one->x(), 0.0);
423     QCOMPARE(one->y(), 0.0);
424     QCOMPARE(two->x(), 0.0);
425     QCOMPARE(two->y(), 60.0);
426     QCOMPARE(three->x(), 0.0);
427     QCOMPARE(three->y(), 80.0);
428
429     QSGItem *column = canvas->rootObject()->findChild<QSGItem*>("column");
430     QCOMPARE(column->height(), 100.0);
431     QCOMPARE(column->width(), 50.0);
432
433     delete canvas;
434 }
435
436 void tst_qsgpositioners::test_vertical_animated()
437 {
438     QSGView *canvas = createView(SRCDIR "/data/vertical-animated.qml", false);
439
440     //Note that they animate in
441     QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one");
442     QVERIFY(one != 0);
443     QCOMPARE(one->y(), -100.0);
444
445     QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two");
446     QVERIFY(two != 0);
447     QCOMPARE(two->y(), -100.0);
448
449     QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three");
450     QVERIFY(three != 0);
451     QCOMPARE(three->y(), -100.0);
452
453     QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn
454
455     QSGItem *column = canvas->rootObject()->findChild<QSGItem*>("column");
456     QVERIFY(column);
457     QCOMPARE(column->height(), 100.0);
458     QCOMPARE(column->width(), 50.0);
459
460     //QTRY_COMPARE used instead of waiting for the expected time of animation completion
461     //Note that this means the duration of the animation is NOT tested
462
463     QTRY_COMPARE(one->y(), 0.0);
464     QTRY_COMPARE(one->x(), 0.0);
465     QTRY_COMPARE(two->isVisible(), false);
466     QTRY_COMPARE(two->y(), -100.0);//Not 'in' yet
467     QTRY_COMPARE(two->x(), 0.0);
468     QTRY_COMPARE(three->y(), 50.0);
469     QTRY_COMPARE(three->x(), 0.0);
470
471     //Add 'two'
472     two->setVisible(true);
473     QTRY_COMPARE(two->isVisible(), true);
474     QTRY_COMPARE(column->height(), 150.0);
475     QTRY_COMPARE(column->width(), 50.0);
476     QTest::qWait(0);//Let the animation start
477     QCOMPARE(two->y(), -100.0);
478     QCOMPARE(three->y(), 50.0);
479
480     QTRY_COMPARE(two->y(), 50.0);
481     QTRY_COMPARE(three->y(), 100.0);
482
483     delete canvas;
484 }
485
486 void tst_qsgpositioners::test_grid()
487 {
488     QSGView *canvas = createView(SRCDIR "/data/gridtest.qml");
489
490     QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one");
491     QVERIFY(one != 0);
492     QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two");
493     QVERIFY(two != 0);
494     QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three");
495     QVERIFY(three != 0);
496     QSGRectangle *four = canvas->rootObject()->findChild<QSGRectangle*>("four");
497     QVERIFY(four != 0);
498     QSGRectangle *five = canvas->rootObject()->findChild<QSGRectangle*>("five");
499     QVERIFY(five != 0);
500
501     QCOMPARE(one->x(), 0.0);
502     QCOMPARE(one->y(), 0.0);
503     QCOMPARE(two->x(), 50.0);
504     QCOMPARE(two->y(), 0.0);
505     QCOMPARE(three->x(), 70.0);
506     QCOMPARE(three->y(), 0.0);
507     QCOMPARE(four->x(), 0.0);
508     QCOMPARE(four->y(), 50.0);
509     QCOMPARE(five->x(), 50.0);
510     QCOMPARE(five->y(), 50.0);
511
512     QSGGrid *grid = canvas->rootObject()->findChild<QSGGrid*>("grid");
513     QCOMPARE(grid->flow(), QSGGrid::LeftToRight);
514     QCOMPARE(grid->width(), 100.0);
515     QCOMPARE(grid->height(), 100.0);
516
517     delete canvas;
518 }
519
520 void tst_qsgpositioners::test_grid_topToBottom()
521 {
522     QSGView *canvas = createView(SRCDIR "/data/grid-toptobottom.qml");
523
524     QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one");
525     QVERIFY(one != 0);
526     QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two");
527     QVERIFY(two != 0);
528     QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three");
529     QVERIFY(three != 0);
530     QSGRectangle *four = canvas->rootObject()->findChild<QSGRectangle*>("four");
531     QVERIFY(four != 0);
532     QSGRectangle *five = canvas->rootObject()->findChild<QSGRectangle*>("five");
533     QVERIFY(five != 0);
534
535     QCOMPARE(one->x(), 0.0);
536     QCOMPARE(one->y(), 0.0);
537     QCOMPARE(two->x(), 0.0);
538     QCOMPARE(two->y(), 50.0);
539     QCOMPARE(three->x(), 0.0);
540     QCOMPARE(three->y(), 100.0);
541     QCOMPARE(four->x(), 50.0);
542     QCOMPARE(four->y(), 0.0);
543     QCOMPARE(five->x(), 50.0);
544     QCOMPARE(five->y(), 50.0);
545
546     QSGGrid *grid = canvas->rootObject()->findChild<QSGGrid*>("grid");
547     QCOMPARE(grid->flow(), QSGGrid::TopToBottom);
548     QCOMPARE(grid->width(), 100.0);
549     QCOMPARE(grid->height(), 120.0);
550
551     delete canvas;
552 }
553
554 void tst_qsgpositioners::test_grid_rightToLeft()
555 {
556     QSGView *canvas = createView(SRCDIR "/data/gridtest.qml");
557
558     canvas->rootObject()->setProperty("testRightToLeft", true);
559
560     QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one");
561     QVERIFY(one != 0);
562     QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two");
563     QVERIFY(two != 0);
564     QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three");
565     QVERIFY(three != 0);
566     QSGRectangle *four = canvas->rootObject()->findChild<QSGRectangle*>("four");
567     QVERIFY(four != 0);
568     QSGRectangle *five = canvas->rootObject()->findChild<QSGRectangle*>("five");
569     QVERIFY(five != 0);
570
571     QCOMPARE(one->x(), 50.0);
572     QCOMPARE(one->y(), 0.0);
573     QCOMPARE(two->x(), 30.0);
574     QCOMPARE(two->y(), 0.0);
575     QCOMPARE(three->x(), 0.0);
576     QCOMPARE(three->y(), 0.0);
577     QCOMPARE(four->x(), 50.0);
578     QCOMPARE(four->y(), 50.0);
579     QCOMPARE(five->x(), 40.0);
580     QCOMPARE(five->y(), 50.0);
581
582     QSGGrid *grid = canvas->rootObject()->findChild<QSGGrid*>("grid");
583     QCOMPARE(grid->layoutDirection(), Qt::RightToLeft);
584     QCOMPARE(grid->width(), 100.0);
585     QCOMPARE(grid->height(), 100.0);
586
587     // Change the width of the grid and check that items stay to the right
588     grid->setWidth(200);
589     QTRY_COMPARE(one->x(), 150.0);
590     QCOMPARE(one->y(), 0.0);
591     QCOMPARE(two->x(), 130.0);
592     QCOMPARE(two->y(), 0.0);
593     QCOMPARE(three->x(), 100.0);
594     QCOMPARE(three->y(), 0.0);
595     QCOMPARE(four->x(), 150.0);
596     QCOMPARE(four->y(), 50.0);
597     QCOMPARE(five->x(), 140.0);
598     QCOMPARE(five->y(), 50.0);
599
600     delete canvas;
601 }
602
603 void tst_qsgpositioners::test_grid_spacing()
604 {
605     QSGView *canvas = createView(SRCDIR "/data/grid-spacing.qml");
606
607     QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one");
608     QVERIFY(one != 0);
609     QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two");
610     QVERIFY(two != 0);
611     QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three");
612     QVERIFY(three != 0);
613     QSGRectangle *four = canvas->rootObject()->findChild<QSGRectangle*>("four");
614     QVERIFY(four != 0);
615     QSGRectangle *five = canvas->rootObject()->findChild<QSGRectangle*>("five");
616     QVERIFY(five != 0);
617
618     QCOMPARE(one->x(), 0.0);
619     QCOMPARE(one->y(), 0.0);
620     QCOMPARE(two->x(), 54.0);
621     QCOMPARE(two->y(), 0.0);
622     QCOMPARE(three->x(), 78.0);
623     QCOMPARE(three->y(), 0.0);
624     QCOMPARE(four->x(), 0.0);
625     QCOMPARE(four->y(), 54.0);
626     QCOMPARE(five->x(), 54.0);
627     QCOMPARE(five->y(), 54.0);
628
629     QSGItem *grid = canvas->rootObject()->findChild<QSGItem*>("grid");
630     QCOMPARE(grid->width(), 128.0);
631     QCOMPARE(grid->height(), 104.0);
632
633     delete canvas;
634 }
635
636 void tst_qsgpositioners::test_grid_row_column_spacing()
637 {
638     QSGView *canvas = createView(SRCDIR "/data/grid-row-column-spacing.qml");
639
640     QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one");
641     QVERIFY(one != 0);
642     QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two");
643     QVERIFY(two != 0);
644     QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three");
645     QVERIFY(three != 0);
646     QSGRectangle *four = canvas->rootObject()->findChild<QSGRectangle*>("four");
647     QVERIFY(four != 0);
648     QSGRectangle *five = canvas->rootObject()->findChild<QSGRectangle*>("five");
649     QVERIFY(five != 0);
650
651     QCOMPARE(one->x(), 0.0);
652     QCOMPARE(one->y(), 0.0);
653     QCOMPARE(two->x(), 61.0);
654     QCOMPARE(two->y(), 0.0);
655     QCOMPARE(three->x(), 92.0);
656     QCOMPARE(three->y(), 0.0);
657     QCOMPARE(four->x(), 0.0);
658     QCOMPARE(four->y(), 57.0);
659     QCOMPARE(five->x(), 61.0);
660     QCOMPARE(five->y(), 57.0);
661
662     QSGItem *grid = canvas->rootObject()->findChild<QSGItem*>("grid");
663     QCOMPARE(grid->width(), 142.0);
664     QCOMPARE(grid->height(), 107.0);
665
666     delete canvas;
667 }
668
669 void tst_qsgpositioners::test_grid_animated()
670 {
671     QSGView *canvas = createView(SRCDIR "/data/grid-animated.qml", false);
672
673     canvas->rootObject()->setProperty("testRightToLeft", false);
674
675     //Note that all animate in
676     QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one");
677     QVERIFY(one != 0);
678     QCOMPARE(one->x(), -100.0);
679     QCOMPARE(one->y(), -100.0);
680
681     QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two");
682     QVERIFY(two != 0);
683     QCOMPARE(two->x(), -100.0);
684     QCOMPARE(two->y(), -100.0);
685
686     QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three");
687     QVERIFY(three != 0);
688     QCOMPARE(three->x(), -100.0);
689     QCOMPARE(three->y(), -100.0);
690
691     QSGRectangle *four = canvas->rootObject()->findChild<QSGRectangle*>("four");
692     QVERIFY(four != 0);
693     QCOMPARE(four->x(), -100.0);
694     QCOMPARE(four->y(), -100.0);
695
696     QSGRectangle *five = canvas->rootObject()->findChild<QSGRectangle*>("five");
697     QVERIFY(five != 0);
698     QCOMPARE(five->x(), -100.0);
699     QCOMPARE(five->y(), -100.0);
700
701     QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn
702
703     QSGItem *grid = canvas->rootObject()->findChild<QSGItem*>("grid");
704     QVERIFY(grid);
705     QCOMPARE(grid->width(), 150.0);
706     QCOMPARE(grid->height(), 100.0);
707
708     //QTRY_COMPARE used instead of waiting for the expected time of animation completion
709     //Note that this means the duration of the animation is NOT tested
710
711     QTRY_COMPARE(one->y(), 0.0);
712     QTRY_COMPARE(one->x(), 0.0);
713     QTRY_COMPARE(two->isVisible(), false);
714     QTRY_COMPARE(two->y(), -100.0);
715     QTRY_COMPARE(two->x(), -100.0);
716     QTRY_COMPARE(three->y(), 0.0);
717     QTRY_COMPARE(three->x(), 50.0);
718     QTRY_COMPARE(four->y(), 0.0);
719     QTRY_COMPARE(four->x(), 100.0);
720     QTRY_COMPARE(five->y(), 50.0);
721     QTRY_COMPARE(five->x(), 0.0);
722
723     //Add 'two'
724     two->setVisible(true);
725     QCOMPARE(two->isVisible(), true);
726     QCOMPARE(grid->width(), 150.0);
727     QCOMPARE(grid->height(), 100.0);
728     QTest::qWait(0);//Let the animation start
729     QCOMPARE(two->x(), -100.0);
730     QCOMPARE(two->y(), -100.0);
731     QCOMPARE(one->x(), 0.0);
732     QCOMPARE(one->y(), 0.0);
733     QCOMPARE(three->x(), 50.0);
734     QCOMPARE(three->y(), 0.0);
735     QCOMPARE(four->x(), 100.0);
736     QCOMPARE(four->y(), 0.0);
737     QCOMPARE(five->x(), 0.0);
738     QCOMPARE(five->y(), 50.0);
739     //Let the animation complete
740     QTRY_COMPARE(two->x(), 50.0);
741     QTRY_COMPARE(two->y(), 0.0);
742     QTRY_COMPARE(one->x(), 0.0);
743     QTRY_COMPARE(one->y(), 0.0);
744     QTRY_COMPARE(three->x(), 100.0);
745     QTRY_COMPARE(three->y(), 0.0);
746     QTRY_COMPARE(four->x(), 0.0);
747     QTRY_COMPARE(four->y(), 50.0);
748     QTRY_COMPARE(five->x(), 50.0);
749     QTRY_COMPARE(five->y(), 50.0);
750
751     delete canvas;
752 }
753
754 void tst_qsgpositioners::test_grid_animated_rightToLeft()
755 {
756     QSGView *canvas = createView(SRCDIR "/data/grid-animated.qml", false);
757
758     canvas->rootObject()->setProperty("testRightToLeft", true);
759
760     //Note that all animate in
761     QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one");
762     QVERIFY(one != 0);
763     QCOMPARE(one->x(), -100.0);
764     QCOMPARE(one->y(), -100.0);
765
766     QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two");
767     QVERIFY(two != 0);
768     QCOMPARE(two->x(), -100.0);
769     QCOMPARE(two->y(), -100.0);
770
771     QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three");
772     QVERIFY(three != 0);
773     QCOMPARE(three->x(), -100.0);
774     QCOMPARE(three->y(), -100.0);
775
776     QSGRectangle *four = canvas->rootObject()->findChild<QSGRectangle*>("four");
777     QVERIFY(four != 0);
778     QCOMPARE(four->x(), -100.0);
779     QCOMPARE(four->y(), -100.0);
780
781     QSGRectangle *five = canvas->rootObject()->findChild<QSGRectangle*>("five");
782     QVERIFY(five != 0);
783     QCOMPARE(five->x(), -100.0);
784     QCOMPARE(five->y(), -100.0);
785
786     QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn
787
788     QSGItem *grid = canvas->rootObject()->findChild<QSGItem*>("grid");
789     QVERIFY(grid);
790     QCOMPARE(grid->width(), 150.0);
791     QCOMPARE(grid->height(), 100.0);
792
793     //QTRY_COMPARE used instead of waiting for the expected time of animation completion
794     //Note that this means the duration of the animation is NOT tested
795
796     QTRY_COMPARE(one->y(), 0.0);
797     QTRY_COMPARE(one->x(), 100.0);
798     QTRY_COMPARE(two->isVisible(), false);
799     QTRY_COMPARE(two->y(), -100.0);
800     QTRY_COMPARE(two->x(), -100.0);
801     QTRY_COMPARE(three->y(), 0.0);
802     QTRY_COMPARE(three->x(), 50.0);
803     QTRY_COMPARE(four->y(), 0.0);
804     QTRY_COMPARE(four->x(), 0.0);
805     QTRY_COMPARE(five->y(), 50.0);
806     QTRY_COMPARE(five->x(), 100.0);
807
808     //Add 'two'
809     two->setVisible(true);
810     QCOMPARE(two->isVisible(), true);
811     QCOMPARE(grid->width(), 150.0);
812     QCOMPARE(grid->height(), 100.0);
813     QTest::qWait(0);//Let the animation start
814     QCOMPARE(two->x(), -100.0);
815     QCOMPARE(two->y(), -100.0);
816     QCOMPARE(one->x(), 100.0);
817     QCOMPARE(one->y(), 0.0);
818     QCOMPARE(three->x(), 50.0);
819     QCOMPARE(three->y(), 0.0);
820     QCOMPARE(four->x(), 0.0);
821     QCOMPARE(four->y(), 0.0);
822     QCOMPARE(five->x(), 100.0);
823     QCOMPARE(five->y(), 50.0);
824     //Let the animation complete
825     QTRY_COMPARE(two->x(), 50.0);
826     QTRY_COMPARE(two->y(), 0.0);
827     QTRY_COMPARE(one->x(), 100.0);
828     QTRY_COMPARE(one->y(), 0.0);
829     QTRY_COMPARE(three->x(), 0.0);
830     QTRY_COMPARE(three->y(), 0.0);
831     QTRY_COMPARE(four->x(), 100.0);
832     QTRY_COMPARE(four->y(), 50.0);
833     QTRY_COMPARE(five->x(), 50.0);
834     QTRY_COMPARE(five->y(), 50.0);
835
836     delete canvas;
837 }
838
839 void tst_qsgpositioners::test_grid_zero_columns()
840 {
841     QSGView *canvas = createView(SRCDIR "/data/gridzerocolumns.qml");
842
843     QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one");
844     QVERIFY(one != 0);
845     QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two");
846     QVERIFY(two != 0);
847     QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three");
848     QVERIFY(three != 0);
849     QSGRectangle *four = canvas->rootObject()->findChild<QSGRectangle*>("four");
850     QVERIFY(four != 0);
851     QSGRectangle *five = canvas->rootObject()->findChild<QSGRectangle*>("five");
852     QVERIFY(five != 0);
853
854     QCOMPARE(one->x(), 0.0);
855     QCOMPARE(one->y(), 0.0);
856     QCOMPARE(two->x(), 50.0);
857     QCOMPARE(two->y(), 0.0);
858     QCOMPARE(three->x(), 70.0);
859     QCOMPARE(three->y(), 0.0);
860     QCOMPARE(four->x(), 120.0);
861     QCOMPARE(four->y(), 0.0);
862     QCOMPARE(five->x(), 0.0);
863     QCOMPARE(five->y(), 50.0);
864
865     QSGItem *grid = canvas->rootObject()->findChild<QSGItem*>("grid");
866     QCOMPARE(grid->width(), 170.0);
867     QCOMPARE(grid->height(), 60.0);
868
869     delete canvas;
870 }
871
872 void tst_qsgpositioners::test_propertychanges()
873 {
874     QSGView *canvas = createView(SRCDIR "/data/propertychangestest.qml");
875
876     QSGGrid *grid = qobject_cast<QSGGrid*>(canvas->rootObject());
877     QVERIFY(grid != 0);
878     QDeclarativeTransition *rowTransition = canvas->rootObject()->findChild<QDeclarativeTransition*>("rowTransition");
879     QDeclarativeTransition *columnTransition = canvas->rootObject()->findChild<QDeclarativeTransition*>("columnTransition");
880
881     QSignalSpy addSpy(grid, SIGNAL(addChanged()));
882     QSignalSpy moveSpy(grid, SIGNAL(moveChanged()));
883     QSignalSpy columnsSpy(grid, SIGNAL(columnsChanged()));
884     QSignalSpy rowsSpy(grid, SIGNAL(rowsChanged()));
885
886     QVERIFY(grid);
887     QVERIFY(rowTransition);
888     QVERIFY(columnTransition);
889     QCOMPARE(grid->add(), columnTransition);
890     QCOMPARE(grid->move(), columnTransition);
891     QCOMPARE(grid->columns(), 4);
892     QCOMPARE(grid->rows(), -1);
893
894     grid->setAdd(rowTransition);
895     grid->setMove(rowTransition);
896     QCOMPARE(grid->add(), rowTransition);
897     QCOMPARE(grid->move(), rowTransition);
898     QCOMPARE(addSpy.count(),1);
899     QCOMPARE(moveSpy.count(),1);
900
901     grid->setAdd(rowTransition);
902     grid->setMove(rowTransition);
903     QCOMPARE(addSpy.count(),1);
904     QCOMPARE(moveSpy.count(),1);
905
906     grid->setAdd(0);
907     grid->setMove(0);
908     QCOMPARE(addSpy.count(),2);
909     QCOMPARE(moveSpy.count(),2);
910
911     grid->setColumns(-1);
912     grid->setRows(3);
913     QCOMPARE(grid->columns(), -1);
914     QCOMPARE(grid->rows(), 3);
915     QCOMPARE(columnsSpy.count(),1);
916     QCOMPARE(rowsSpy.count(),1);
917
918     grid->setColumns(-1);
919     grid->setRows(3);
920     QCOMPARE(columnsSpy.count(),1);
921     QCOMPARE(rowsSpy.count(),1);
922
923     grid->setColumns(2);
924     grid->setRows(2);
925     QCOMPARE(columnsSpy.count(),2);
926     QCOMPARE(rowsSpy.count(),2);
927
928     delete canvas;
929 }
930
931 void tst_qsgpositioners::test_repeater()
932 {
933     QSGView *canvas = createView(SRCDIR "/data/repeatertest.qml");
934
935     QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one");
936     QVERIFY(one != 0);
937
938     QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two");
939     QVERIFY(two != 0);
940
941     QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three");
942     QVERIFY(three != 0);
943
944     QCOMPARE(one->x(), 0.0);
945     QCOMPARE(one->y(), 0.0);
946     QCOMPARE(two->x(), 50.0);
947     QCOMPARE(two->y(), 0.0);
948     QCOMPARE(three->x(), 100.0);
949     QCOMPARE(three->y(), 0.0);
950
951     delete canvas;
952 }
953
954 void tst_qsgpositioners::test_flow()
955 {
956     QSGView *canvas = createView(SRCDIR "/data/flowtest.qml");
957
958     canvas->rootObject()->setProperty("testRightToLeft", false);
959
960     QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one");
961     QVERIFY(one != 0);
962     QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two");
963     QVERIFY(two != 0);
964     QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three");
965     QVERIFY(three != 0);
966     QSGRectangle *four = canvas->rootObject()->findChild<QSGRectangle*>("four");
967     QVERIFY(four != 0);
968     QSGRectangle *five = canvas->rootObject()->findChild<QSGRectangle*>("five");
969     QVERIFY(five != 0);
970
971     QCOMPARE(one->x(), 0.0);
972     QCOMPARE(one->y(), 0.0);
973     QCOMPARE(two->x(), 50.0);
974     QCOMPARE(two->y(), 0.0);
975     QCOMPARE(three->x(), 0.0);
976     QCOMPARE(three->y(), 50.0);
977     QCOMPARE(four->x(), 0.0);
978     QCOMPARE(four->y(), 70.0);
979     QCOMPARE(five->x(), 50.0);
980     QCOMPARE(five->y(), 70.0);
981
982     QSGItem *flow = canvas->rootObject()->findChild<QSGItem*>("flow");
983     QVERIFY(flow);
984     QCOMPARE(flow->width(), 90.0);
985     QCOMPARE(flow->height(), 120.0);
986
987     delete canvas;
988 }
989
990 void tst_qsgpositioners::test_flow_rightToLeft()
991 {
992     QSGView *canvas = createView(SRCDIR "/data/flowtest.qml");
993
994     canvas->rootObject()->setProperty("testRightToLeft", true);
995
996     QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one");
997     QVERIFY(one != 0);
998     QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two");
999     QVERIFY(two != 0);
1000     QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three");
1001     QVERIFY(three != 0);
1002     QSGRectangle *four = canvas->rootObject()->findChild<QSGRectangle*>("four");
1003     QVERIFY(four != 0);
1004     QSGRectangle *five = canvas->rootObject()->findChild<QSGRectangle*>("five");
1005     QVERIFY(five != 0);
1006
1007     QCOMPARE(one->x(), 40.0);
1008     QCOMPARE(one->y(), 0.0);
1009     QCOMPARE(two->x(), 20.0);
1010     QCOMPARE(two->y(), 0.0);
1011     QCOMPARE(three->x(), 40.0);
1012     QCOMPARE(three->y(), 50.0);
1013     QCOMPARE(four->x(), 40.0);
1014     QCOMPARE(four->y(), 70.0);
1015     QCOMPARE(five->x(), 30.0);
1016     QCOMPARE(five->y(), 70.0);
1017
1018     QSGItem *flow = canvas->rootObject()->findChild<QSGItem*>("flow");
1019     QVERIFY(flow);
1020     QCOMPARE(flow->width(), 90.0);
1021     QCOMPARE(flow->height(), 120.0);
1022
1023     delete canvas;
1024 }
1025
1026 void tst_qsgpositioners::test_flow_topToBottom()
1027 {
1028     QSGView *canvas = createView(SRCDIR "/data/flowtest-toptobottom.qml");
1029
1030     canvas->rootObject()->setProperty("testRightToLeft", false);
1031
1032     QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one");
1033     QVERIFY(one != 0);
1034     QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two");
1035     QVERIFY(two != 0);
1036     QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three");
1037     QVERIFY(three != 0);
1038     QSGRectangle *four = canvas->rootObject()->findChild<QSGRectangle*>("four");
1039     QVERIFY(four != 0);
1040     QSGRectangle *five = canvas->rootObject()->findChild<QSGRectangle*>("five");
1041     QVERIFY(five != 0);
1042
1043     QCOMPARE(one->x(), 0.0);
1044     QCOMPARE(one->y(), 0.0);
1045     QCOMPARE(two->x(), 50.0);
1046     QCOMPARE(two->y(), 0.0);
1047     QCOMPARE(three->x(), 50.0);
1048     QCOMPARE(three->y(), 50.0);
1049     QCOMPARE(four->x(), 100.0);
1050     QCOMPARE(four->y(), 00.0);
1051     QCOMPARE(five->x(), 100.0);
1052     QCOMPARE(five->y(), 50.0);
1053
1054     QSGItem *flow = canvas->rootObject()->findChild<QSGItem*>("flow");
1055     QVERIFY(flow);
1056     QCOMPARE(flow->height(), 90.0);
1057     QCOMPARE(flow->width(), 150.0);
1058
1059     canvas->rootObject()->setProperty("testRightToLeft", true);
1060
1061     QVERIFY(flow);
1062     QCOMPARE(flow->height(), 90.0);
1063     QCOMPARE(flow->width(), 150.0);
1064
1065     QCOMPARE(one->x(), 100.0);
1066     QCOMPARE(one->y(), 0.0);
1067     QCOMPARE(two->x(), 80.0);
1068     QCOMPARE(two->y(), 0.0);
1069     QCOMPARE(three->x(), 50.0);
1070     QCOMPARE(three->y(), 50.0);
1071     QCOMPARE(four->x(), 0.0);
1072     QCOMPARE(four->y(), 0.0);
1073     QCOMPARE(five->x(), 40.0);
1074     QCOMPARE(five->y(), 50.0);
1075
1076     delete canvas;
1077 }
1078
1079 void tst_qsgpositioners::test_flow_resize()
1080 {
1081     QSGView *canvas = createView(SRCDIR "/data/flowtest.qml");
1082
1083     QSGItem *root = qobject_cast<QSGItem*>(canvas->rootObject());
1084     QVERIFY(root);
1085     root->setWidth(125);
1086     root->setProperty("testRightToLeft", false);
1087
1088     QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one");
1089     QVERIFY(one != 0);
1090     QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two");
1091     QVERIFY(two != 0);
1092     QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three");
1093     QVERIFY(three != 0);
1094     QSGRectangle *four = canvas->rootObject()->findChild<QSGRectangle*>("four");
1095     QVERIFY(four != 0);
1096     QSGRectangle *five = canvas->rootObject()->findChild<QSGRectangle*>("five");
1097     QVERIFY(five != 0);
1098
1099     QTRY_COMPARE(one->x(), 0.0);
1100     QTRY_COMPARE(one->y(), 0.0);
1101     QTRY_COMPARE(two->x(), 50.0);
1102     QTRY_COMPARE(two->y(), 0.0);
1103     QTRY_COMPARE(three->x(), 70.0);
1104     QTRY_COMPARE(three->y(), 0.0);
1105     QTRY_COMPARE(four->x(), 0.0);
1106     QTRY_COMPARE(four->y(), 50.0);
1107     QTRY_COMPARE(five->x(), 50.0);
1108     QTRY_COMPARE(five->y(), 50.0);
1109
1110     delete canvas;
1111 }
1112
1113 void tst_qsgpositioners::test_flow_resize_rightToLeft()
1114 {
1115     QSGView *canvas = createView(SRCDIR "/data/flowtest.qml");
1116
1117     QSGItem *root = qobject_cast<QSGItem*>(canvas->rootObject());
1118     QVERIFY(root);
1119     root->setWidth(125);
1120     root->setProperty("testRightToLeft", true);
1121
1122     QSGRectangle *one = canvas->rootObject()->findChild<QSGRectangle*>("one");
1123     QTRY_VERIFY(one != 0);
1124     QSGRectangle *two = canvas->rootObject()->findChild<QSGRectangle*>("two");
1125     QVERIFY(two != 0);
1126     QSGRectangle *three = canvas->rootObject()->findChild<QSGRectangle*>("three");
1127     QVERIFY(three != 0);
1128     QSGRectangle *four = canvas->rootObject()->findChild<QSGRectangle*>("four");
1129     QVERIFY(four != 0);
1130     QSGRectangle *five = canvas->rootObject()->findChild<QSGRectangle*>("five");
1131     QVERIFY(five != 0);
1132
1133     QCOMPARE(one->x(), 75.0);
1134     QCOMPARE(one->y(), 0.0);
1135     QCOMPARE(two->x(), 55.0);
1136     QCOMPARE(two->y(), 0.0);
1137     QCOMPARE(three->x(), 5.0);
1138     QCOMPARE(three->y(), 0.0);
1139     QCOMPARE(four->x(), 75.0);
1140     QCOMPARE(four->y(), 50.0);
1141     QCOMPARE(five->x(), 65.0);
1142     QCOMPARE(five->y(), 50.0);
1143
1144     delete canvas;
1145 }
1146
1147 void tst_qsgpositioners::test_flow_implicit_resize()
1148 {
1149     QSGView *canvas = createView(SRCDIR "/data/flow-testimplicitsize.qml");
1150     QVERIFY(canvas->rootObject() != 0);
1151
1152     QSGFlow *flow = canvas->rootObject()->findChild<QSGFlow*>("flow");
1153     QVERIFY(flow != 0);
1154
1155     QCOMPARE(flow->width(), 100.0);
1156     QCOMPARE(flow->height(), 120.0);
1157
1158     canvas->rootObject()->setProperty("flowLayout", 0);
1159     QCOMPARE(flow->flow(), QSGFlow::LeftToRight);
1160     QCOMPARE(flow->width(), 220.0);
1161     QCOMPARE(flow->height(), 50.0);
1162
1163     canvas->rootObject()->setProperty("flowLayout", 1);
1164     QCOMPARE(flow->flow(), QSGFlow::TopToBottom);
1165     QCOMPARE(flow->width(), 100.0);
1166     QCOMPARE(flow->height(), 120.0);
1167
1168     canvas->rootObject()->setProperty("flowLayout", 2);
1169     QCOMPARE(flow->layoutDirection(), Qt::RightToLeft);
1170     QCOMPARE(flow->width(), 220.0);
1171     QCOMPARE(flow->height(), 50.0);
1172
1173     delete canvas;
1174 }
1175
1176 QString warningMessage;
1177
1178 void interceptWarnings(QtMsgType type, const char *msg)
1179 {
1180     Q_UNUSED( type );
1181     warningMessage = msg;
1182 }
1183
1184 void tst_qsgpositioners::test_conflictinganchors()
1185 {
1186     QtMsgHandler oldMsgHandler = qInstallMsgHandler(interceptWarnings);
1187     QDeclarativeEngine engine;
1188     QDeclarativeComponent component(&engine);
1189
1190     component.setData("import QtQuick 2.0\nColumn { Item {} }", QUrl::fromLocalFile(""));
1191     QSGItem *item = qobject_cast<QSGItem*>(component.create());
1192     QVERIFY(item);
1193     QVERIFY(warningMessage.isEmpty());
1194     delete item;
1195
1196     component.setData("import QtQuick 2.0\nRow { Item {} }", QUrl::fromLocalFile(""));
1197     item = qobject_cast<QSGItem*>(component.create());
1198     QVERIFY(item);
1199     QVERIFY(warningMessage.isEmpty());
1200     delete item;
1201
1202     component.setData("import QtQuick 2.0\nGrid { Item {} }", QUrl::fromLocalFile(""));
1203     item = qobject_cast<QSGItem*>(component.create());
1204     QVERIFY(item);
1205     QVERIFY(warningMessage.isEmpty());
1206     delete item;
1207
1208     component.setData("import QtQuick 2.0\nFlow { Item {} }", QUrl::fromLocalFile(""));
1209     item = qobject_cast<QSGItem*>(component.create());
1210     QVERIFY(item);
1211     QVERIFY(warningMessage.isEmpty());
1212     delete item;
1213
1214     component.setData("import QtQuick 2.0\nColumn { Item { anchors.top: parent.top } }", QUrl::fromLocalFile(""));
1215     item = qobject_cast<QSGItem*>(component.create());
1216     QVERIFY(item);
1217     QCOMPARE(warningMessage, QString("file::2:1: QML Column: Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column"));
1218     warningMessage.clear();
1219     delete item;
1220
1221     component.setData("import QtQuick 2.0\nColumn { Item { anchors.centerIn: parent } }", QUrl::fromLocalFile(""));
1222     item = qobject_cast<QSGItem*>(component.create());
1223     QVERIFY(item);
1224     QCOMPARE(warningMessage, QString("file::2:1: QML Column: Cannot specify top, bottom, verticalCenter, fill or centerIn anchors for items inside Column"));
1225     warningMessage.clear();
1226     delete item;
1227
1228     component.setData("import QtQuick 2.0\nColumn { Item { anchors.left: parent.left } }", QUrl::fromLocalFile(""));
1229     item = qobject_cast<QSGItem*>(component.create());
1230     QVERIFY(item);
1231     QVERIFY(warningMessage.isEmpty());
1232     warningMessage.clear();
1233     delete item;
1234
1235     component.setData("import QtQuick 2.0\nRow { Item { anchors.left: parent.left } }", QUrl::fromLocalFile(""));
1236     item = qobject_cast<QSGItem*>(component.create());
1237     QVERIFY(item);
1238     QCOMPARE(warningMessage, QString("file::2:1: QML Row: Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row"));
1239     warningMessage.clear();
1240     delete item;
1241
1242     component.setData("import QtQuick 2.0\nRow { Item { anchors.fill: parent } }", QUrl::fromLocalFile(""));
1243     item = qobject_cast<QSGItem*>(component.create());
1244     QVERIFY(item);
1245     QCOMPARE(warningMessage, QString("file::2:1: QML Row: Cannot specify left, right, horizontalCenter, fill or centerIn anchors for items inside Row"));
1246     warningMessage.clear();
1247     delete item;
1248
1249     component.setData("import QtQuick 2.0\nRow { Item { anchors.top: parent.top } }", QUrl::fromLocalFile(""));
1250     item = qobject_cast<QSGItem*>(component.create());
1251     QVERIFY(item);
1252     QVERIFY(warningMessage.isEmpty());
1253     warningMessage.clear();
1254     delete item;
1255
1256     component.setData("import QtQuick 2.0\nGrid { Item { anchors.horizontalCenter: parent.horizontalCenter } }", QUrl::fromLocalFile(""));
1257     item = qobject_cast<QSGItem*>(component.create());
1258     QVERIFY(item);
1259     QCOMPARE(warningMessage, QString("file::2:1: QML Grid: Cannot specify anchors for items inside Grid"));
1260     warningMessage.clear();
1261     delete item;
1262
1263     component.setData("import QtQuick 2.0\nGrid { Item { anchors.centerIn: parent } }", QUrl::fromLocalFile(""));
1264     item = qobject_cast<QSGItem*>(component.create());
1265     QVERIFY(item);
1266     QCOMPARE(warningMessage, QString("file::2:1: QML Grid: Cannot specify anchors for items inside Grid"));
1267     warningMessage.clear();
1268     delete item;
1269
1270     component.setData("import QtQuick 2.0\nFlow { Item { anchors.verticalCenter: parent.verticalCenter } }", QUrl::fromLocalFile(""));
1271     item = qobject_cast<QSGItem*>(component.create());
1272     QVERIFY(item);
1273     QCOMPARE(warningMessage, QString("file::2:1: QML Flow: Cannot specify anchors for items inside Flow"));
1274     delete item;
1275
1276     component.setData("import QtQuick 2.0\nFlow { Item { anchors.fill: parent } }", QUrl::fromLocalFile(""));
1277     item = qobject_cast<QSGItem*>(component.create());
1278     QVERIFY(item);
1279     QCOMPARE(warningMessage, QString("file::2:1: QML Flow: Cannot specify anchors for items inside Flow"));
1280     qInstallMsgHandler(oldMsgHandler);
1281     delete item;
1282 }
1283
1284 void tst_qsgpositioners::test_mirroring()
1285 {
1286     QList<QString> qmlFiles;
1287     qmlFiles << "horizontal.qml" << "gridtest.qml" << "flowtest.qml";
1288     QList<QString> objectNames;
1289     objectNames << "one" << "two" << "three" << "four" << "five";
1290
1291     foreach(const QString qmlFile, qmlFiles) {
1292         QSGView *canvasA = createView(QString(SRCDIR) + "/data/" + qmlFile);
1293         QSGItem *rootA = qobject_cast<QSGItem*>(canvasA->rootObject());
1294
1295         QSGView *canvasB = createView(QString(SRCDIR) + "/data/" + qmlFile);
1296         QSGItem *rootB = qobject_cast<QSGItem*>(canvasB->rootObject());
1297
1298         rootA->setProperty("testRightToLeft", true); // layoutDirection: Qt.RightToLeft
1299
1300         // LTR != RTL
1301         foreach(const QString objectName, objectNames) {
1302             // horizontal.qml only has three items
1303             if (qmlFile == QString("horizontal.qml") && objectName == QString("four"))
1304                 break;
1305             QSGItem *itemA = rootA->findChild<QSGItem*>(objectName);
1306             QSGItem *itemB = rootB->findChild<QSGItem*>(objectName);
1307             QTRY_VERIFY(itemA->x() != itemB->x());
1308         }
1309
1310         QSGItemPrivate* rootPrivateB = QSGItemPrivate::get(rootB);
1311
1312         rootPrivateB->effectiveLayoutMirror = true; // LayoutMirroring.enabled: true
1313         rootPrivateB->isMirrorImplicit = false;
1314         rootPrivateB->inheritMirrorFromItem = true; // LayoutMirroring.childrenInherit: true
1315         rootPrivateB->resolveLayoutMirror();
1316
1317         // RTL == mirror
1318         foreach(const QString objectName, objectNames) {
1319             // horizontal.qml only has three items
1320             if (qmlFile == QString("horizontal.qml") && objectName == QString("four"))
1321                 break;
1322             QSGItem *itemA = rootA->findChild<QSGItem*>(objectName);
1323             QSGItem *itemB = rootB->findChild<QSGItem*>(objectName);
1324             QTRY_COMPARE(itemA->x(), itemB->x());
1325         }
1326
1327         rootA->setProperty("testRightToLeft", false); // layoutDirection: Qt.LeftToRight
1328         rootB->setProperty("testRightToLeft", true); // layoutDirection: Qt.RightToLeft
1329
1330         // LTR == RTL + mirror
1331         foreach(const QString objectName, objectNames) {
1332             // horizontal.qml only has three items
1333             if (qmlFile == QString("horizontal.qml") && objectName == QString("four"))
1334                 break;
1335             QSGItem *itemA = rootA->findChild<QSGItem*>(objectName);
1336             QSGItem *itemB = rootB->findChild<QSGItem*>(objectName);
1337             QTRY_COMPARE(itemA->x(), itemB->x());
1338         }
1339         delete canvasA;
1340         delete canvasB;
1341     }
1342 }
1343
1344 void tst_qsgpositioners::test_allInvisible()
1345 {
1346     //QTBUG-19361
1347     QSGView *canvas = createView(SRCDIR "/data/allInvisible.qml");
1348
1349     QSGItem *root = qobject_cast<QSGItem*>(canvas->rootObject());
1350     QVERIFY(root);
1351
1352     QSGRow *row = canvas->rootObject()->findChild<QSGRow*>("row");
1353     QVERIFY(row != 0);
1354     QVERIFY(row->width() == 0);
1355     QVERIFY(row->height() == 0);
1356     QSGColumn *column = canvas->rootObject()->findChild<QSGColumn*>("column");
1357     QVERIFY(column != 0);
1358     QVERIFY(column->width() == 0);
1359     QVERIFY(column->height() == 0);
1360 }
1361
1362 void tst_qsgpositioners::test_attachedproperties()
1363 {
1364     QFETCH(QString, filename);
1365
1366     QSGView *canvas = createView(filename);
1367     QVERIFY(canvas->rootObject() != 0);
1368
1369     QSGRectangle *greenRect = canvas->rootObject()->findChild<QSGRectangle *>("greenRect");
1370     QVERIFY(greenRect != 0);
1371
1372     int posIndex = greenRect->property("posIndex").toInt();
1373     QVERIFY(posIndex == 0);
1374     bool isFirst = greenRect->property("isFirstItem").toBool();
1375     QVERIFY(isFirst == true);
1376     bool isLast = greenRect->property("isLastItem").toBool();
1377     QVERIFY(isLast == false);
1378
1379     QSGRectangle *yellowRect = canvas->rootObject()->findChild<QSGRectangle *>("yellowRect");
1380     QVERIFY(yellowRect != 0);
1381
1382     posIndex = yellowRect->property("posIndex").toInt();
1383     QVERIFY(posIndex == -1);
1384     isFirst = yellowRect->property("isFirstItem").toBool();
1385     QVERIFY(isFirst == false);
1386     isLast = yellowRect->property("isLastItem").toBool();
1387     QVERIFY(isLast == false);
1388
1389     yellowRect->metaObject()->invokeMethod(yellowRect, "onDemandPositioner");
1390
1391     posIndex = yellowRect->property("posIndex").toInt();
1392     QVERIFY(posIndex == 1);
1393     isFirst = yellowRect->property("isFirstItem").toBool();
1394     QVERIFY(isFirst == false);
1395     isLast = yellowRect->property("isLastItem").toBool();
1396     QVERIFY(isLast == true);
1397
1398     delete canvas;
1399 }
1400
1401 void tst_qsgpositioners::test_attachedproperties_data()
1402 {
1403     QTest::addColumn<QString>("filename");
1404
1405     QTest::newRow("column") << SRCDIR "/data/attachedproperties-column.qml";
1406     QTest::newRow("row") << SRCDIR "/data/attachedproperties-row.qml";
1407     QTest::newRow("grid") << SRCDIR "/data/attachedproperties-grid.qml";
1408     QTest::newRow("flow") << SRCDIR "/data/attachedproperties-flow.qml";
1409 }
1410
1411 void tst_qsgpositioners::test_attachedproperties_dynamic()
1412 {
1413     QSGView *canvas = createView(SRCDIR "/data/attachedproperties-dynamic.qml");
1414     QVERIFY(canvas->rootObject() != 0);
1415
1416     QSGRow *row = canvas->rootObject()->findChild<QSGRow *>("pos");
1417     QVERIFY(row != 0);
1418
1419     QSGRectangle *rect0 = canvas->rootObject()->findChild<QSGRectangle *>("rect0");
1420     QVERIFY(rect0 != 0);
1421
1422     int posIndex = rect0->property("index").toInt();
1423     QVERIFY(posIndex == 0);
1424     bool isFirst = rect0->property("firstItem").toBool();
1425     QVERIFY(isFirst == true);
1426     bool isLast = rect0->property("lastItem").toBool();
1427     QVERIFY(isLast == false);
1428
1429     QSGRectangle *rect1 = canvas->rootObject()->findChild<QSGRectangle *>("rect1");
1430     QVERIFY(rect1 != 0);
1431
1432     posIndex = rect1->property("index").toInt();
1433     QVERIFY(posIndex == 1);
1434     isFirst = rect1->property("firstItem").toBool();
1435     QVERIFY(isFirst == false);
1436     isLast = rect1->property("lastItem").toBool();
1437     QVERIFY(isLast == true);
1438
1439     row->metaObject()->invokeMethod(row, "createSubRect");
1440
1441     QTRY_VERIFY(rect1->property("index").toInt() == 1);
1442     QTRY_VERIFY(rect1->property("firstItem").toBool() == false);
1443     QTRY_VERIFY(rect1->property("lastItem").toBool() == false);
1444
1445     QSGRectangle *rect2 = canvas->rootObject()->findChild<QSGRectangle *>("rect2");
1446     QVERIFY(rect2 != 0);
1447
1448     posIndex = rect2->property("index").toInt();
1449     QVERIFY(posIndex == 2);
1450     isFirst = rect2->property("firstItem").toBool();
1451     QVERIFY(isFirst == false);
1452     isLast = rect2->property("lastItem").toBool();
1453     QVERIFY(isLast == true);
1454
1455     row->metaObject()->invokeMethod(row, "destroySubRect");
1456
1457     qApp->processEvents(QEventLoop::DeferredDeletion);
1458
1459     QTRY_VERIFY(rect1->property("index").toInt() == 1);
1460     QTRY_VERIFY(rect1->property("firstItem").toBool() == false);
1461     QTRY_VERIFY(rect1->property("lastItem").toBool() == true);
1462
1463     delete canvas;
1464 }
1465
1466 QSGView *tst_qsgpositioners::createView(const QString &filename, bool wait)
1467 {
1468     QSGView *canvas = new QSGView(0);
1469
1470     canvas->setSource(QUrl::fromLocalFile(filename));
1471     canvas->show();
1472     if (wait)
1473         QTest::qWaitForWindowShown(canvas); //It may not relayout until the next frame, so it needs to be drawn
1474
1475     return canvas;
1476 }
1477
1478
1479 QTEST_MAIN(tst_qsgpositioners)
1480
1481 #include "tst_qsgpositioners.moc"