Work around remaining 'make check' failures.
[profile/ivi/qtdeclarative.git] / tests / auto / declarative / qdeclarativeanchors / tst_qdeclarativeanchors.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 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #include <qtest.h>
42 #include <QSignalSpy>
43 #include <QtGui/QGraphicsWidget>
44 #include <private/qgraphicsitem_p.h>
45 #include <QtDeclarative/qdeclarativeengine.h>
46 #include <QtDeclarative/qdeclarativecomponent.h>
47 #include <QtDeclarative/qdeclarativeview.h>
48 #include <private/qdeclarativerectangle_p.h>
49 #include <private/qdeclarativetext_p.h>
50 #include <QtDeclarative/private/qdeclarativeanchors_p_p.h>
51 #include <QtDeclarative/private/qdeclarativeitem_p.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 Q_DECLARE_METATYPE(QDeclarativeAnchors::Anchor)
59 Q_DECLARE_METATYPE(QDeclarativeAnchorLine::AnchorLine)
60
61
62 class tst_qdeclarativeanchors : public QObject
63 {
64     Q_OBJECT
65 public:
66     tst_qdeclarativeanchors() {}
67
68 private slots:
69     void basicAnchors();
70     void basicAnchorsQGraphicsWidget();
71     void basicAnchorsRTL();
72     void loops();
73     void illegalSets();
74     void illegalSets_data();
75     void reset();
76     void reset_data();
77     void resetConvenience();
78     void nullItem();
79     void nullItem_data();
80     void crash1();
81     void centerIn();
82     void centerInRTL();
83     void hvCenter();
84     void hvCenterRTL();
85     void fill();
86     void fillRTL();
87     void margins();
88     void marginsRTL();
89 };
90
91 /*
92    Find an item with the specified id.
93 */
94 template<typename T>
95 T *findItem(QGraphicsObject *parent, const QString &objectName)
96 {
97     const QMetaObject &mo = T::staticMetaObject;
98     QList<QGraphicsItem *> children = parent->childItems();
99     for (int i = 0; i < children.count(); ++i) {
100         QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(children.at(i)->toGraphicsObject());
101         if (item) {
102             if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
103                 return static_cast<T*>(item);
104             }
105             item = findItem<T>(item, objectName);
106             if (item)
107                 return static_cast<T*>(item);
108         }
109     }
110
111     return 0;
112 }
113
114 QGraphicsObject *findObject(QGraphicsObject *parent, const QString &objectName)
115 {
116     QList<QGraphicsItem *> children = parent->childItems();
117     for (int i = 0; i < children.count(); ++i) {
118         QGraphicsObject *item = children.at(i)->toGraphicsObject();
119         if (item) {
120             if (objectName.isEmpty() || item->objectName() == objectName) {
121                 return item;
122             }
123             item = findObject(item, objectName);
124             if (item)
125                 return item;
126         }
127     }
128
129     return 0;
130 }
131
132
133 void tst_qdeclarativeanchors::basicAnchors()
134 {
135     QDeclarativeView *view = new QDeclarativeView;
136     view->setSource(QUrl::fromLocalFile(SRCDIR "/data/anchors.qml"));
137
138     qApp->processEvents();
139
140     //sibling horizontal
141     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect1"))->x(), 26.0);
142     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect2"))->x(), 122.0);
143     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect3"))->x(), 74.0);
144     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect4"))->x(), 16.0);
145     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect5"))->x(), 112.0);
146     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect6"))->x(), 64.0);
147
148     //parent horizontal
149     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect7"))->x(), 0.0);
150     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect8"))->x(), 240.0);
151     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect9"))->x(), 120.0);
152     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect10"))->x(), -10.0);
153     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect11"))->x(), 230.0);
154     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect12"))->x(), 110.0);
155
156     //vertical
157     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect13"))->y(), 20.0);
158     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect14"))->y(), 155.0);
159
160     //stretch
161     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect15"))->x(), 26.0);
162     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect15"))->width(), 96.0);
163     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect16"))->x(), 26.0);
164     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect16"))->width(), 192.0);
165     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect17"))->x(), -70.0);
166     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect17"))->width(), 192.0);
167
168     //vertical stretch
169     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect18"))->y(), 20.0);
170     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect18"))->height(), 40.0);
171
172     //more parent horizontal
173     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect19"))->x(), 115.0);
174     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect20"))->x(), 235.0);
175     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect21"))->x(), -5.0);
176
177     //centerIn
178     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect22"))->x(), 69.0);
179     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect22"))->y(), 5.0);
180
181      //margins
182     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect23"))->x(), 31.0);
183     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect23"))->y(), 5.0);
184     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect23"))->width(), 86.0);
185     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect23"))->height(), 10.0);
186
187     // offsets
188     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect24"))->x(), 26.0);
189     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect25"))->y(), 60.0);
190     QCOMPARE(findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("rect26"))->y(), 5.0);
191
192     //baseline
193     QDeclarativeText *text1 = findItem<QDeclarativeText>(view->rootObject(), QLatin1String("text1"));
194     QDeclarativeText *text2 = findItem<QDeclarativeText>(view->rootObject(), QLatin1String("text2"));
195     QCOMPARE(text1->y(), text2->y());
196
197     delete view;
198 }
199
200 void tst_qdeclarativeanchors::basicAnchorsQGraphicsWidget()
201 {
202     QDeclarativeView *view = new QDeclarativeView;
203     view->setSource(QUrl::fromLocalFile(SRCDIR "/data/anchorsqgraphicswidget.qml"));
204
205     qApp->processEvents();
206
207     //sibling horizontal
208     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect1"))->x(), 26.0);
209     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect2"))->x(), 122.0);
210     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect3"))->x(), 74.0);
211     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect4"))->x(), 16.0);
212     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect5"))->x(), 112.0);
213     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect6"))->x(), 64.0);
214
215     //parent horizontal
216     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect7"))->x(), 0.0);
217     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect8"))->x(), 240.0);
218     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect9"))->x(), 120.0);
219     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect10"))->x(), -10.0);
220     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect11"))->x(), 230.0);
221     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect12"))->x(), 110.0);
222
223     //vertical
224     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect13"))->y(), 20.0);
225     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect14"))->y(), 155.0);
226
227     //stretch
228     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect15"))->x(), 26.0);
229     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect15"))->property("width").toReal(), 96.0);
230     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect16"))->x(), 26.0);
231     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect16"))->property("width").toReal(), 192.0);
232     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect17"))->x(), -70.0);
233     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect17"))->property("width").toReal(), 192.0);
234
235     //vertical stretch
236     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect18"))->y(), 20.0);
237     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect18"))->property("height").toReal(), 40.0);
238
239     //more parent horizontal
240     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect19"))->x(), 115.0);
241     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect20"))->x(), 235.0);
242     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect21"))->x(), -5.0);
243
244     //centerIn
245     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect22"))->x(), 69.0);
246     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect22"))->y(), 5.0);
247
248      //margins
249     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect23"))->x(), 31.0);
250     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect23"))->y(), 5.0);
251     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect23"))->property("width").toReal(), 86.0);
252     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect23"))->property("height").toReal(), 10.0);
253
254     // offsets
255     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect24"))->x(), 26.0);
256     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect25"))->y(), 60.0);
257     QCOMPARE(findObject(view->rootObject(), QLatin1String("rect26"))->y(), 5.0);
258
259     //baseline
260     QDeclarativeText *text1 = findItem<QDeclarativeText>(view->rootObject(), QLatin1String("text1"));
261     QDeclarativeText *text2 = findItem<QDeclarativeText>(view->rootObject(), QLatin1String("text2"));
262     QCOMPARE(text1->y(), text2->y());
263
264     delete view;
265 }
266
267 QDeclarativeItem* childItem(QDeclarativeItem *parentItem, const char * itemString) {
268     return findItem<QDeclarativeItem>(parentItem, QLatin1String(itemString));
269 }
270
271 qreal offsetMasterRTL(QDeclarativeItem *rootItem, const char * itemString) {
272     QDeclarativeItem* masterItem = findItem<QDeclarativeItem>(rootItem,  QLatin1String("masterRect"));
273     return masterItem->width()+2*masterItem->x()-findItem<QDeclarativeItem>(rootItem,  QLatin1String(itemString))->width();
274 }
275
276 qreal offsetParentRTL(QDeclarativeItem *rootItem, const char * itemString) {
277     return rootItem->width()+2*rootItem->x()-findItem<QDeclarativeItem>(rootItem,  QLatin1String(itemString))->width();
278 }
279
280 void mirrorAnchors(QDeclarativeItem *item) {
281     QDeclarativeItemPrivate *itemPrivate = QDeclarativeItemPrivate::get(item);
282     itemPrivate->setLayoutMirror(true);
283 }
284
285 void tst_qdeclarativeanchors::basicAnchorsRTL()
286 {
287     QDeclarativeView *view = new QDeclarativeView;
288     view->setSource(QUrl::fromLocalFile(SRCDIR "/data/anchors.qml"));
289
290     qApp->processEvents();
291
292     QDeclarativeItem* rootItem = qobject_cast<QDeclarativeItem*>(view->rootObject());
293     foreach(QObject *child, rootItem->children()) {
294         bool mirrored = QDeclarativeItemPrivate::get(qobject_cast<QDeclarativeItem*>(child))->anchors()->property("mirrored").toBool();
295         QCOMPARE(mirrored, false);
296     }
297
298     foreach(QObject *child, rootItem->children())
299         mirrorAnchors(qobject_cast<QDeclarativeItem*>(child));
300
301     foreach(QObject *child, rootItem->children()) {
302         bool mirrored = QDeclarativeItemPrivate::get(qobject_cast<QDeclarativeItem*>(child))->anchors()->property("mirrored").toBool();
303         QCOMPARE(mirrored, true);
304     }
305
306     //sibling horizontal
307     QCOMPARE(childItem(rootItem, "rect1")->x(), offsetMasterRTL(rootItem, "rect1")-26.0);
308     QCOMPARE(childItem(rootItem, "rect2")->x(), offsetMasterRTL(rootItem, "rect2")-122.0);
309     QCOMPARE(childItem(rootItem, "rect3")->x(), offsetMasterRTL(rootItem, "rect3")-74.0);
310     QCOMPARE(childItem(rootItem, "rect4")->x(), offsetMasterRTL(rootItem, "rect4")-16.0);
311     QCOMPARE(childItem(rootItem, "rect5")->x(), offsetMasterRTL(rootItem, "rect5")-112.0);
312     QCOMPARE(childItem(rootItem, "rect6")->x(), offsetMasterRTL(rootItem, "rect6")-64.0);
313
314     //parent horizontal
315     QCOMPARE(childItem(rootItem, "rect7")->x(), offsetParentRTL(rootItem, "rect7")-0.0);
316     QCOMPARE(childItem(rootItem, "rect8")->x(), offsetParentRTL(rootItem, "rect8")-240.0);
317     QCOMPARE(childItem(rootItem, "rect9")->x(), offsetParentRTL(rootItem, "rect9")-120.0);
318     QCOMPARE(childItem(rootItem, "rect10")->x(), offsetParentRTL(rootItem, "rect10")+10.0);
319     QCOMPARE(childItem(rootItem, "rect11")->x(), offsetParentRTL(rootItem, "rect11")-230.0);
320     QCOMPARE(childItem(rootItem, "rect12")->x(), offsetParentRTL(rootItem, "rect12")-110.0);
321
322     //vertical
323     QCOMPARE(childItem(rootItem, "rect13")->y(), 20.0);
324     QCOMPARE(childItem(rootItem, "rect14")->y(), 155.0);
325
326     //stretch
327     QCOMPARE(childItem(rootItem, "rect15")->x(), offsetMasterRTL(rootItem, "rect15")-26.0);
328     QCOMPARE(childItem(rootItem, "rect15")->width(), 96.0);
329     QCOMPARE(childItem(rootItem, "rect16")->x(), offsetMasterRTL(rootItem, "rect16")-26.0);
330     QCOMPARE(childItem(rootItem, "rect16")->width(), 192.0);
331     QCOMPARE(childItem(rootItem, "rect17")->x(), offsetMasterRTL(rootItem, "rect17")+70.0);
332     QCOMPARE(childItem(rootItem, "rect17")->width(), 192.0);
333
334     //vertical stretch
335     QCOMPARE(childItem(rootItem, "rect18")->y(), 20.0);
336     QCOMPARE(childItem(rootItem, "rect18")->height(), 40.0);
337
338     //more parent horizontal
339     QCOMPARE(childItem(rootItem, "rect19")->x(), offsetParentRTL(rootItem, "rect19")-115.0);
340     QCOMPARE(childItem(rootItem, "rect20")->x(), offsetParentRTL(rootItem, "rect20")-235.0);
341     QCOMPARE(childItem(rootItem, "rect21")->x(), offsetParentRTL(rootItem, "rect21")+5.0);
342
343     //centerIn
344     QCOMPARE(childItem(rootItem, "rect22")->x(), offsetMasterRTL(rootItem, "rect22")-69.0);
345     QCOMPARE(childItem(rootItem, "rect22")->y(), 5.0);
346
347      //margins
348     QCOMPARE(childItem(rootItem, "rect23")->x(), offsetMasterRTL(rootItem, "rect23")-31.0);
349     QCOMPARE(childItem(rootItem, "rect23")->y(), 5.0);
350     QCOMPARE(childItem(rootItem, "rect23")->width(), 86.0);
351     QCOMPARE(childItem(rootItem, "rect23")->height(), 10.0);
352
353     // offsets
354     QCOMPARE(childItem(rootItem, "rect24")->x(), offsetMasterRTL(rootItem, "rect24")-26.0);
355     QCOMPARE(childItem(rootItem, "rect25")->y(), 60.0);
356     QCOMPARE(childItem(rootItem, "rect26")->y(), 5.0);
357
358     //baseline
359     QDeclarativeText *text1 = findItem<QDeclarativeText>(rootItem, QLatin1String("text1"));
360     QDeclarativeText *text2 = findItem<QDeclarativeText>(rootItem, QLatin1String("text2"));
361     QCOMPARE(text1->y(), text2->y());
362
363     delete view;
364 }
365
366 // mostly testing that we don't crash
367 void tst_qdeclarativeanchors::loops()
368 {
369     {
370         QUrl source(QUrl::fromLocalFile(SRCDIR "/data/loop1.qml"));
371
372         QString expect = source.toString() + ":6:5: QML Text: Possible anchor loop detected on horizontal anchor.";
373         QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
374         QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
375         QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
376
377         QDeclarativeView *view = new QDeclarativeView;
378         view->setSource(source);
379         qApp->processEvents();
380
381         delete view;
382     }
383
384     {
385         QSKIP("This causes a lockup due to Bearer management stuff", SkipSingle);
386         QUrl source(QUrl::fromLocalFile(SRCDIR "/data/loop2.qml"));
387
388         QString expect = source.toString() + ":8:3: QML Image: Possible anchor loop detected on horizontal anchor.";
389         QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
390
391         QDeclarativeView *view = new QDeclarativeView;
392         view->setSource(source);
393         qApp->processEvents();
394
395         delete view;
396     }
397 }
398
399 void tst_qdeclarativeanchors::illegalSets()
400 {
401     QFETCH(QString, qml);
402     QFETCH(QString, warning);
403
404     QTest::ignoreMessage(QtWarningMsg, warning.toLatin1());
405
406     QDeclarativeEngine engine;
407     QDeclarativeComponent component(&engine);
408     component.setData(QByteArray("import QtQuick 1.0\n" + qml.toUtf8()), QUrl::fromLocalFile(""));
409     if (!component.isReady())
410         qWarning() << "Test errors:" << component.errors();
411     QVERIFY(component.isReady());
412     QObject *o = component.create();
413     delete o;
414 }
415
416 void tst_qdeclarativeanchors::illegalSets_data()
417 {
418     QTest::addColumn<QString>("qml");
419     QTest::addColumn<QString>("warning");
420
421     QTest::newRow("H - too many anchors")
422         << "Rectangle { id: rect; Rectangle { anchors.left: rect.left; anchors.right: rect.right; anchors.horizontalCenter: rect.horizontalCenter } }"
423         << "file::2:23: QML Rectangle: Cannot specify left, right, and hcenter anchors.";
424
425     foreach (const QString &side, QStringList() << "left" << "right") {
426         QTest::newRow("H - anchor to V")
427             << QString("Rectangle { Rectangle { anchors.%1: parent.top } }").arg(side)
428             << "file::2:13: QML Rectangle: Cannot anchor a horizontal edge to a vertical edge.";
429
430         QTest::newRow("H - anchor to non parent/sibling")
431             << QString("Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.%1: rect.%1 } }").arg(side)
432             << "file::2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
433
434         QTest::newRow("H - anchor to self")
435             << QString("Rectangle { id: rect; anchors.%1: rect.%1 }").arg(side)
436             << "file::2:1: QML Rectangle: Cannot anchor item to self.";
437     }
438
439
440     QTest::newRow("V - too many anchors")
441         << "Rectangle { id: rect; Rectangle { anchors.top: rect.top; anchors.bottom: rect.bottom; anchors.verticalCenter: rect.verticalCenter } }"
442         << "file::2:23: QML Rectangle: Cannot specify top, bottom, and vcenter anchors.";
443
444     QTest::newRow("V - too many anchors with baseline")
445         << "Rectangle { Text { id: text1; text: \"Hello\" } Text { anchors.baseline: text1.baseline; anchors.top: text1.top; } }"
446         << "file::2:47: QML Text: Baseline anchor cannot be used in conjunction with top, bottom, or vcenter anchors.";
447
448     foreach (const QString &side, QStringList() << "top" << "bottom" << "baseline") {
449
450         QTest::newRow("V - anchor to H")
451             << QString("Rectangle { Rectangle { anchors.%1: parent.left } }").arg(side)
452             << "file::2:13: QML Rectangle: Cannot anchor a vertical edge to a horizontal edge.";
453
454         QTest::newRow("V - anchor to non parent/sibling")
455             << QString("Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.%1: rect.%1 } }").arg(side)
456             << "file::2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
457
458         QTest::newRow("V - anchor to self")
459             << QString("Rectangle { id: rect; anchors.%1: rect.%1 }").arg(side)
460             << "file::2:1: QML Rectangle: Cannot anchor item to self.";
461     }
462
463
464     QTest::newRow("centerIn - anchor to non parent/sibling")
465         << "Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.centerIn: rect} }"
466         << "file::2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
467
468
469     QTest::newRow("fill - anchor to non parent/sibling")
470         << "Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.fill: rect} }"
471         << "file::2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
472 }
473
474 void tst_qdeclarativeanchors::reset()
475 {
476     QFETCH(QString, side);
477     QFETCH(QDeclarativeAnchorLine::AnchorLine, anchorLine);
478     QFETCH(QDeclarativeAnchors::Anchor, usedAnchor);
479
480     QDeclarativeItem *baseItem = new QDeclarativeItem;
481
482     QDeclarativeAnchorLine anchor;
483     anchor.item = baseItem;
484     anchor.anchorLine = anchorLine;
485
486     QDeclarativeItem *item = new QDeclarativeItem;
487     QDeclarativeItemPrivate *itemPrivate = QDeclarativeItemPrivate::get(item);
488
489     const QMetaObject *meta = itemPrivate->anchors()->metaObject();
490     QMetaProperty p = meta->property(meta->indexOfProperty(side.toUtf8().constData()));
491
492     QVERIFY(p.write(itemPrivate->anchors(), qVariantFromValue(anchor)));
493     QCOMPARE(itemPrivate->anchors()->usedAnchors().testFlag(usedAnchor), true);
494
495     QVERIFY(p.reset(itemPrivate->anchors()));
496     QCOMPARE(itemPrivate->anchors()->usedAnchors().testFlag(usedAnchor), false);
497
498     delete item;
499     delete baseItem;
500 }
501
502 void tst_qdeclarativeanchors::reset_data()
503 {
504     QTest::addColumn<QString>("side");
505     QTest::addColumn<QDeclarativeAnchorLine::AnchorLine>("anchorLine");
506     QTest::addColumn<QDeclarativeAnchors::Anchor>("usedAnchor");
507
508     QTest::newRow("left") << "left" << QDeclarativeAnchorLine::Left << QDeclarativeAnchors::LeftAnchor;
509     QTest::newRow("top") << "top" << QDeclarativeAnchorLine::Top << QDeclarativeAnchors::TopAnchor;
510     QTest::newRow("right") << "right" << QDeclarativeAnchorLine::Right << QDeclarativeAnchors::RightAnchor;
511     QTest::newRow("bottom") << "bottom" << QDeclarativeAnchorLine::Bottom << QDeclarativeAnchors::BottomAnchor;
512
513     QTest::newRow("hcenter") << "horizontalCenter" << QDeclarativeAnchorLine::HCenter << QDeclarativeAnchors::HCenterAnchor;
514     QTest::newRow("vcenter") << "verticalCenter" << QDeclarativeAnchorLine::VCenter << QDeclarativeAnchors::VCenterAnchor;
515     QTest::newRow("baseline") << "baseline" << QDeclarativeAnchorLine::Baseline << QDeclarativeAnchors::BaselineAnchor;
516 }
517
518 void tst_qdeclarativeanchors::resetConvenience()
519 {
520     QDeclarativeItem *baseItem = new QDeclarativeItem;
521     QDeclarativeItem *item = new QDeclarativeItem;
522     QDeclarativeItemPrivate *itemPrivate = QDeclarativeItemPrivate::get(item);
523
524     //fill
525     itemPrivate->anchors()->setFill(baseItem);
526     QVERIFY(itemPrivate->anchors()->fill() == baseItem);
527     itemPrivate->anchors()->resetFill();
528     QVERIFY(itemPrivate->anchors()->fill() == 0);
529
530     //centerIn
531     itemPrivate->anchors()->setCenterIn(baseItem);
532     QVERIFY(itemPrivate->anchors()->centerIn() == baseItem);
533     itemPrivate->anchors()->resetCenterIn();
534     QVERIFY(itemPrivate->anchors()->centerIn() == 0);
535
536     delete item;
537     delete baseItem;
538 }
539
540 void tst_qdeclarativeanchors::nullItem()
541 {
542     QFETCH(QString, side);
543
544     QDeclarativeAnchorLine anchor;
545     QDeclarativeItem *item = new QDeclarativeItem;
546     QDeclarativeItemPrivate *itemPrivate = QDeclarativeItemPrivate::get(item);
547
548     const QMetaObject *meta = itemPrivate->anchors()->metaObject();
549     QMetaProperty p = meta->property(meta->indexOfProperty(side.toUtf8().constData()));
550
551     QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML Item: Cannot anchor to a null item.");
552     QVERIFY(p.write(itemPrivate->anchors(), qVariantFromValue(anchor)));
553
554     delete item;
555 }
556
557 void tst_qdeclarativeanchors::nullItem_data()
558 {
559     QTest::addColumn<QString>("side");
560
561     QTest::newRow("left") << "left";
562     QTest::newRow("top") << "top";
563     QTest::newRow("right") << "right";
564     QTest::newRow("bottom") << "bottom";
565
566     QTest::newRow("hcenter") << "horizontalCenter";
567     QTest::newRow("vcenter") << "verticalCenter";
568     QTest::newRow("baseline") << "baseline";
569 }
570
571 void tst_qdeclarativeanchors::crash1()
572 {
573     QUrl source(QUrl::fromLocalFile(SRCDIR "/data/crash1.qml"));
574
575     QString expect = source.toString() + ":4:5: QML Text: Possible anchor loop detected on fill.";
576
577     QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
578
579     // QT-3245 ... anchor loop detection needs improving.
580     QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
581     QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
582     QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
583     QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
584     QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
585     QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
586     QTest::ignoreMessage(QtWarningMsg, expect.toLatin1());
587
588     QDeclarativeView *view = new QDeclarativeView(source);
589     qApp->processEvents();
590
591     delete view;
592 }
593
594 void tst_qdeclarativeanchors::fill()
595 {
596     QDeclarativeView *view = new QDeclarativeView(QUrl::fromLocalFile(SRCDIR "/data/fill.qml"));
597
598     qApp->processEvents();
599     QDeclarativeRectangle* rect = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("filler"));
600     QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
601     QCOMPARE(rect->x(), 0.0 + 10.0);
602     QCOMPARE(rect->y(), 0.0 + 30.0);
603     QCOMPARE(rect->width(), 200.0 - 10.0 - 20.0);
604     QCOMPARE(rect->height(), 200.0 - 30.0 - 40.0);
605     //Alter Offsets (tests QTBUG-6631)
606     rectPrivate->anchors()->setLeftMargin(20.0);
607     rectPrivate->anchors()->setRightMargin(0.0);
608     rectPrivate->anchors()->setBottomMargin(0.0);
609     rectPrivate->anchors()->setTopMargin(10.0);
610     QCOMPARE(rect->x(), 0.0 + 20.0);
611     QCOMPARE(rect->y(), 0.0 + 10.0);
612     QCOMPARE(rect->width(), 200.0 - 20.0);
613     QCOMPARE(rect->height(), 200.0 - 10.0);
614
615     delete view;
616 }
617
618 void tst_qdeclarativeanchors::fillRTL()
619 {
620     QDeclarativeView *view = new QDeclarativeView(QUrl::fromLocalFile(SRCDIR "/data/fill.qml"));
621
622     qApp->processEvents();
623     QDeclarativeRectangle* rect = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("filler"));
624     QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
625     mirrorAnchors(rect);
626
627     QCOMPARE(rect->x(), 0.0 + 20.0);
628     QCOMPARE(rect->y(), 0.0 + 30.0);
629     QCOMPARE(rect->width(), 200.0 - 10.0 - 20.0);
630     QCOMPARE(rect->height(), 200.0 - 30.0 - 40.0);
631     //Alter Offsets (tests QTBUG-6631)
632     rectPrivate->anchors()->setLeftMargin(20.0);
633     rectPrivate->anchors()->setRightMargin(0.0);
634     rectPrivate->anchors()->setBottomMargin(0.0);
635     rectPrivate->anchors()->setTopMargin(10.0);
636     QCOMPARE(rect->x(), 0.0 + 0.0);
637     QCOMPARE(rect->y(), 0.0 + 10.0);
638     QCOMPARE(rect->width(), 200.0 - 20.0);
639     QCOMPARE(rect->height(), 200.0 - 10.0);
640
641     delete view;
642 }
643 void tst_qdeclarativeanchors::centerIn()
644 {
645     QDeclarativeView *view = new QDeclarativeView(QUrl::fromLocalFile(SRCDIR "/data/centerin.qml"));
646
647     qApp->processEvents();
648     QDeclarativeRectangle* rect = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("centered"));
649     QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
650
651     QCOMPARE(rect->x(), 75.0 + 10);
652     QCOMPARE(rect->y(), 75.0 + 30);
653     //Alter Offsets (tests QTBUG-6631)
654     rectPrivate->anchors()->setHorizontalCenterOffset(-20.0);
655     rectPrivate->anchors()->setVerticalCenterOffset(-10.0);
656     QCOMPARE(rect->x(), 75.0 - 20.0);
657     QCOMPARE(rect->y(), 75.0 - 10.0);
658
659     delete view;
660 }
661
662
663 void tst_qdeclarativeanchors::centerInRTL()
664 {
665     QDeclarativeView *view = new QDeclarativeView(QUrl::fromLocalFile(SRCDIR "/data/centerin.qml"));
666
667     qApp->processEvents();
668     QDeclarativeRectangle* rect = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("centered"));
669     QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
670     mirrorAnchors(rect);
671
672     QCOMPARE(rect->x(), 75.0 - 10);
673     QCOMPARE(rect->y(), 75.0 + 30);
674     //Alter Offsets (tests QTBUG-6631)
675     rectPrivate->anchors()->setHorizontalCenterOffset(-20.0);
676     rectPrivate->anchors()->setVerticalCenterOffset(-10.0);
677     QCOMPARE(rect->x(), 75.0 + 20.0);
678     QCOMPARE(rect->y(), 75.0 - 10.0);
679
680     delete view;
681 }
682
683 void tst_qdeclarativeanchors::hvCenter()
684 {
685     QDeclarativeView *view = new QDeclarativeView(QUrl::fromLocalFile(SRCDIR "/data/hvCenter.qml"));
686
687     qApp->processEvents();
688     QDeclarativeRectangle* rect = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("centered"));
689     QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
690
691     // test QTBUG-10999
692     QCOMPARE(rect->x(), 10.0);
693     QCOMPARE(rect->y(), 19.0);
694
695     rectPrivate->anchors()->setHorizontalCenterOffset(-5.0);
696     rectPrivate->anchors()->setVerticalCenterOffset(5.0);
697     QCOMPARE(rect->x(), 10.0 - 5.0);
698     QCOMPARE(rect->y(), 19.0 + 5.0);
699
700     delete view;
701 }
702
703 void tst_qdeclarativeanchors::hvCenterRTL()
704 {
705     QDeclarativeView *view = new QDeclarativeView(QUrl::fromLocalFile(SRCDIR "/data/hvCenter.qml"));
706
707     qApp->processEvents();
708     QDeclarativeRectangle* rect = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("centered"));
709     QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
710     mirrorAnchors(rect);
711
712     // test QTBUG-10999
713     QCOMPARE(rect->x(), 10.0);
714     QCOMPARE(rect->y(), 19.0);
715
716     rectPrivate->anchors()->setHorizontalCenterOffset(-5.0);
717     rectPrivate->anchors()->setVerticalCenterOffset(5.0);
718     QCOMPARE(rect->x(), 10.0 + 5.0);
719     QCOMPARE(rect->y(), 19.0 + 5.0);
720
721     delete view;
722 }
723 void tst_qdeclarativeanchors::margins()
724 {
725     QDeclarativeView *view = new QDeclarativeView(QUrl::fromLocalFile(SRCDIR "/data/margins.qml"));
726
727     qApp->processEvents();
728     QDeclarativeRectangle* rect = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("filler"));
729     QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
730     QCOMPARE(rect->x(), 5.0);
731     QCOMPARE(rect->y(), 6.0);
732     QCOMPARE(rect->width(), 200.0 - 5.0 - 10.0);
733     QCOMPARE(rect->height(), 200.0 - 6.0 - 10.0);
734
735     rectPrivate->anchors()->setTopMargin(0.0);
736     rectPrivate->anchors()->setMargins(20.0);
737
738     QCOMPARE(rect->x(), 5.0);
739     QCOMPARE(rect->y(), 20.0);
740     QCOMPARE(rect->width(), 200.0 - 5.0 - 20.0);
741     QCOMPARE(rect->height(), 200.0 - 20.0 - 20.0);
742
743     delete view;
744 }
745
746 void tst_qdeclarativeanchors::marginsRTL()
747 {
748     QDeclarativeView *view = new QDeclarativeView(QUrl::fromLocalFile(SRCDIR "/data/margins.qml"));
749
750     QDeclarativeRectangle* rect = findItem<QDeclarativeRectangle>(view->rootObject(), QLatin1String("filler"));
751     QDeclarativeItemPrivate *rectPrivate = QDeclarativeItemPrivate::get(rect);
752     mirrorAnchors(rect);
753
754     QCOMPARE(rect->x(), 10.0);
755     QCOMPARE(rect->y(), 6.0);
756     QCOMPARE(rect->width(), 200.0 - 5.0 - 10.0);
757     QCOMPARE(rect->height(), 200.0 - 6.0 - 10.0);
758
759     rectPrivate->anchors()->setTopMargin(0.0);
760     rectPrivate->anchors()->setMargins(20.0);
761
762     QCOMPARE(rect->x(), 20.0);
763     QCOMPARE(rect->y(), 20.0);
764     QCOMPARE(rect->width(), 200.0 - 5.0 - 20.0);
765     QCOMPARE(rect->height(), 200.0 - 20.0 - 20.0);
766
767     delete view;
768 }
769
770
771 QTEST_MAIN(tst_qdeclarativeanchors)
772
773 #include "tst_qdeclarativeanchors.moc"