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