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