1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28#include <qtest.h>
29#include <QSignalSpy>
30#include <private/qquickitem_p.h>
31#include <QtQml/qqmlengine.h>
32#include <QtQml/qqmlcomponent.h>
33#include <QtQuick/qquickview.h>
34#include <QtQuick/private/qquickrectangle_p.h>
35#include <QtQuick/private/qquicktext_p.h>
36#include <QtQuick/private/qquickanchors_p_p.h>
37#include <QtQuick/private/qquickitem_p.h>
38#include "../../shared/util.h"
39#include "../shared/visualtestutil.h"
40
41Q_DECLARE_METATYPE(QQuickAnchors::Anchor)
42
43using namespace QQuickVisualTestUtil;
44
45class tst_qquickanchors : public QQmlDataTest
46{
47 Q_OBJECT
48public:
49 tst_qquickanchors() {}
50
51private slots:
52 void basicAnchors();
53 void basicAnchorsRTL();
54 void loops();
55 void illegalSets();
56 void illegalSets_data();
57 void reset();
58 void reset_data();
59 void resetConvenience();
60 void nullItem();
61 void nullItem_data();
62 void crash1();
63 void centerIn();
64 void centerInRTL();
65 void centerInRotation();
66 void hvCenter();
67 void hvCenterRTL();
68 void fill();
69 void fillRTL();
70 void margins_data();
71 void margins();
72 void marginsRTL_data() { margins_data(); }
73 void marginsRTL();
74 void stretch();
75 void baselineOffset();
76};
77
78void tst_qquickanchors::basicAnchors()
79{
80 QQuickView *view = new QQuickView;
81 view->setSource(testFileUrl(fileName: "anchors.qml"));
82
83 qApp->processEvents();
84
85 //sibling horizontal
86 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect1"))->x(), 26.0);
87 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect2"))->x(), 122.0);
88 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect3"))->x(), 74.0);
89 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect4"))->x(), 16.0);
90 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect5"))->x(), 112.0);
91 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect6"))->x(), 64.0);
92
93 //parent horizontal
94 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect7"))->x(), 0.0);
95 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect8"))->x(), 240.0);
96 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect9"))->x(), 120.0);
97 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect10"))->x(), -10.0);
98 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect11"))->x(), 230.0);
99 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect12"))->x(), 110.0);
100
101 //vertical
102 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect13"))->y(), 20.0);
103 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect14"))->y(), 155.0);
104
105 //stretch
106 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect15"))->x(), 26.0);
107 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect15"))->width(), 96.0);
108 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect16"))->x(), 26.0);
109 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect16"))->width(), 192.0);
110 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect17"))->x(), -70.0);
111 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect17"))->width(), 192.0);
112
113 //vertical stretch
114 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect18"))->y(), 20.0);
115 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect18"))->height(), 40.0);
116
117 //more parent horizontal
118 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect19"))->x(), 115.0);
119 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect20"))->x(), 235.0);
120 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect21"))->x(), -5.0);
121
122 //centerIn
123 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect22"))->x(), 69.0);
124 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect22"))->y(), 5.0);
125
126 //margins
127 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect23"))->x(), 31.0);
128 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect23"))->y(), 5.0);
129 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect23"))->width(), 86.0);
130 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect23"))->height(), 10.0);
131
132 // offsets
133 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect24"))->x(), 26.0);
134 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect25"))->y(), 60.0);
135 QCOMPARE(findItem<QQuickRectangle>(view->rootObject(), QLatin1String("rect26"))->y(), 5.0);
136
137 //baseline
138 QQuickText *text1 = findItem<QQuickText>(parent: view->rootObject(), objectName: QLatin1String("text1"));
139 QQuickText *text2 = findItem<QQuickText>(parent: view->rootObject(), objectName: QLatin1String("text2"));
140 QCOMPARE(text1->y(), text2->y());
141
142 delete view;
143}
144
145QQuickItem* childItem(QQuickItem *parentItem, const char * itemString) {
146 return findItem<QQuickItem>(parent: parentItem, objectName: QLatin1String(itemString));
147}
148
149qreal offsetMasterRTL(QQuickItem *rootItem, const char * itemString) {
150 QQuickItem* masterItem = findItem<QQuickItem>(parent: rootItem, objectName: QLatin1String("masterRect"));
151 return masterItem->width()+2*masterItem->x()-findItem<QQuickItem>(parent: rootItem, objectName: QLatin1String(itemString))->width();
152}
153
154qreal offsetParentRTL(QQuickItem *rootItem, const char * itemString) {
155 return rootItem->width()+2*rootItem->x()-findItem<QQuickItem>(parent: rootItem, objectName: QLatin1String(itemString))->width();
156}
157
158void mirrorAnchors(QQuickItem *item) {
159 QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
160 itemPrivate->setLayoutMirror(true);
161}
162
163void tst_qquickanchors::basicAnchorsRTL()
164{
165 QQuickView *view = new QQuickView;
166 view->setSource(testFileUrl(fileName: "anchors.qml"));
167
168 qApp->processEvents();
169
170 QQuickItem* rootItem = qobject_cast<QQuickItem*>(object: view->rootObject());
171 foreach (QObject *child, rootItem->children()) {
172 bool mirrored = QQuickItemPrivate::get(item: qobject_cast<QQuickItem*>(object: child))->anchors()->mirrored();
173 QCOMPARE(mirrored, false);
174 }
175
176 foreach (QObject *child, rootItem->children())
177 mirrorAnchors(item: qobject_cast<QQuickItem*>(object: child));
178
179 foreach (QObject *child, rootItem->children()) {
180 bool mirrored = QQuickItemPrivate::get(item: qobject_cast<QQuickItem*>(object: child))->anchors()->mirrored();
181 QCOMPARE(mirrored, true);
182 }
183
184 //sibling horizontal
185 QCOMPARE(childItem(rootItem, "rect1")->x(), offsetMasterRTL(rootItem, "rect1")-26.0);
186 QCOMPARE(childItem(rootItem, "rect2")->x(), offsetMasterRTL(rootItem, "rect2")-122.0);
187 QCOMPARE(childItem(rootItem, "rect3")->x(), offsetMasterRTL(rootItem, "rect3")-74.0);
188 QCOMPARE(childItem(rootItem, "rect4")->x(), offsetMasterRTL(rootItem, "rect4")-16.0);
189 QCOMPARE(childItem(rootItem, "rect5")->x(), offsetMasterRTL(rootItem, "rect5")-112.0);
190 QCOMPARE(childItem(rootItem, "rect6")->x(), offsetMasterRTL(rootItem, "rect6")-64.0);
191
192 //parent horizontal
193 QCOMPARE(childItem(rootItem, "rect7")->x(), offsetParentRTL(rootItem, "rect7")-0.0);
194 QCOMPARE(childItem(rootItem, "rect8")->x(), offsetParentRTL(rootItem, "rect8")-240.0);
195 QCOMPARE(childItem(rootItem, "rect9")->x(), offsetParentRTL(rootItem, "rect9")-120.0);
196 QCOMPARE(childItem(rootItem, "rect10")->x(), offsetParentRTL(rootItem, "rect10")+10.0);
197 QCOMPARE(childItem(rootItem, "rect11")->x(), offsetParentRTL(rootItem, "rect11")-230.0);
198 QCOMPARE(childItem(rootItem, "rect12")->x(), offsetParentRTL(rootItem, "rect12")-110.0);
199
200 //vertical
201 QCOMPARE(childItem(rootItem, "rect13")->y(), 20.0);
202 QCOMPARE(childItem(rootItem, "rect14")->y(), 155.0);
203
204 //stretch
205 QCOMPARE(childItem(rootItem, "rect15")->x(), offsetMasterRTL(rootItem, "rect15")-26.0);
206 QCOMPARE(childItem(rootItem, "rect15")->width(), 96.0);
207 QCOMPARE(childItem(rootItem, "rect16")->x(), offsetMasterRTL(rootItem, "rect16")-26.0);
208 QCOMPARE(childItem(rootItem, "rect16")->width(), 192.0);
209 QCOMPARE(childItem(rootItem, "rect17")->x(), offsetMasterRTL(rootItem, "rect17")+70.0);
210 QCOMPARE(childItem(rootItem, "rect17")->width(), 192.0);
211
212 //vertical stretch
213 QCOMPARE(childItem(rootItem, "rect18")->y(), 20.0);
214 QCOMPARE(childItem(rootItem, "rect18")->height(), 40.0);
215
216 //more parent horizontal
217 QCOMPARE(childItem(rootItem, "rect19")->x(), offsetParentRTL(rootItem, "rect19")-115.0);
218 QCOMPARE(childItem(rootItem, "rect20")->x(), offsetParentRTL(rootItem, "rect20")-235.0);
219 QCOMPARE(childItem(rootItem, "rect21")->x(), offsetParentRTL(rootItem, "rect21")+5.0);
220
221 //centerIn
222 QCOMPARE(childItem(rootItem, "rect22")->x(), offsetMasterRTL(rootItem, "rect22")-69.0);
223 QCOMPARE(childItem(rootItem, "rect22")->y(), 5.0);
224
225 //margins
226 QCOMPARE(childItem(rootItem, "rect23")->x(), offsetMasterRTL(rootItem, "rect23")-31.0);
227 QCOMPARE(childItem(rootItem, "rect23")->y(), 5.0);
228 QCOMPARE(childItem(rootItem, "rect23")->width(), 86.0);
229 QCOMPARE(childItem(rootItem, "rect23")->height(), 10.0);
230
231 // offsets
232 QCOMPARE(childItem(rootItem, "rect24")->x(), offsetMasterRTL(rootItem, "rect24")-26.0);
233 QCOMPARE(childItem(rootItem, "rect25")->y(), 60.0);
234 QCOMPARE(childItem(rootItem, "rect26")->y(), 5.0);
235
236 //baseline
237 QQuickText *text1 = findItem<QQuickText>(parent: rootItem, objectName: QLatin1String("text1"));
238 QQuickText *text2 = findItem<QQuickText>(parent: rootItem, objectName: QLatin1String("text2"));
239 QCOMPARE(text1->y(), text2->y());
240
241 delete view;
242}
243
244// mostly testing that we don't crash
245void tst_qquickanchors::loops()
246{
247 {
248 QUrl source(testFileUrl(fileName: "loop1.qml"));
249
250 QString expect = source.toString() + ":6:5: QML Text: Possible anchor loop detected on horizontal anchor.";
251 QTest::ignoreMessage(type: QtWarningMsg, message: expect.toLatin1());
252 QTest::ignoreMessage(type: QtWarningMsg, message: expect.toLatin1());
253
254 QQuickView *view = new QQuickView;
255 view->setSource(source);
256 qApp->processEvents();
257
258 delete view;
259 }
260
261 {
262 QUrl source(testFileUrl(fileName: "loop2.qml"));
263
264 QString expect = source.toString() + ":8:3: QML Image: Possible anchor loop detected on horizontal anchor.";
265 QTest::ignoreMessage(type: QtWarningMsg, message: expect.toLatin1());
266
267 QQuickView *view = new QQuickView;
268 view->setSource(source);
269 qApp->processEvents();
270
271 delete view;
272 }
273}
274
275void tst_qquickanchors::illegalSets()
276{
277 QFETCH(QString, qml);
278 QFETCH(QString, warning);
279
280 QTest::ignoreMessage(type: QtWarningMsg, message: warning.toLatin1());
281
282 QQmlEngine engine;
283 QQmlComponent component(&engine);
284 component.setData(QByteArray("import QtQuick 2.0\n" + qml.toUtf8()), baseUrl: QUrl::fromLocalFile(localfile: ""));
285 if (!component.isReady())
286 qWarning() << "Test errors:" << component.errors();
287 QVERIFY(component.isReady());
288 QObject *o = component.create();
289 delete o;
290}
291
292void tst_qquickanchors::illegalSets_data()
293{
294 QTest::addColumn<QString>(name: "qml");
295 QTest::addColumn<QString>(name: "warning");
296
297 QTest::newRow(dataTag: "H - too many anchors")
298 << "Rectangle { id: rect; Rectangle { anchors.left: rect.left; anchors.right: rect.right; anchors.horizontalCenter: rect.horizontalCenter } }"
299 << "<Unknown File>:2:23: QML Rectangle: Cannot specify left, right, and horizontalCenter anchors at the same time.";
300
301 foreach (const QString &side, QStringList() << "left" << "right") {
302 QTest::newRow(dataTag: "H - anchor to V")
303 << QString("Rectangle { Rectangle { anchors.%1: parent.top } }").arg(a: side)
304 << "<Unknown File>:2:13: QML Rectangle: Cannot anchor a horizontal edge to a vertical edge.";
305
306 QTest::newRow(dataTag: "H - anchor to non parent/sibling")
307 << QString("Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.%1: rect.%1 } }").arg(a: side)
308 << "<Unknown File>:2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
309
310 QTest::newRow(dataTag: "H - anchor to self")
311 << QString("Rectangle { id: rect; anchors.%1: rect.%1 }").arg(a: side)
312 << "<Unknown File>:2:1: QML Rectangle: Cannot anchor item to self.";
313 }
314
315
316 QTest::newRow(dataTag: "V - too many anchors")
317 << "Rectangle { id: rect; Rectangle { anchors.top: rect.top; anchors.bottom: rect.bottom; anchors.verticalCenter: rect.verticalCenter } }"
318 << "<Unknown File>:2:23: QML Rectangle: Cannot specify top, bottom, and verticalCenter anchors at the same time.";
319
320 QTest::newRow(dataTag: "V - too many anchors with baseline")
321 << "Rectangle { Text { id: text1; text: \"Hello\" } Text { anchors.baseline: text1.baseline; anchors.top: text1.top; } }"
322 << "<Unknown File>:2:47: QML Text: Baseline anchor cannot be used in conjunction with top, bottom, or verticalCenter anchors.";
323
324 foreach (const QString &side, QStringList() << "top" << "bottom" << "baseline") {
325
326 QTest::newRow(dataTag: "V - anchor to H")
327 << QString("Rectangle { Rectangle { anchors.%1: parent.left } }").arg(a: side)
328 << "<Unknown File>:2:13: QML Rectangle: Cannot anchor a vertical edge to a horizontal edge.";
329
330 QTest::newRow(dataTag: "V - anchor to non parent/sibling")
331 << QString("Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.%1: rect.%1 } }").arg(a: side)
332 << "<Unknown File>:2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
333
334 QTest::newRow(dataTag: "V - anchor to self")
335 << QString("Rectangle { id: rect; anchors.%1: rect.%1 }").arg(a: side)
336 << "<Unknown File>:2:1: QML Rectangle: Cannot anchor item to self.";
337 }
338
339
340 QTest::newRow(dataTag: "centerIn - anchor to non parent/sibling")
341 << "Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.centerIn: rect} }"
342 << "<Unknown File>:2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
343
344
345 QTest::newRow(dataTag: "fill - anchor to non parent/sibling")
346 << "Rectangle { Item { Rectangle { id: rect } } Rectangle { anchors.fill: rect} }"
347 << "<Unknown File>:2:45: QML Rectangle: Cannot anchor to an item that isn't a parent or sibling.";
348}
349
350void tst_qquickanchors::reset()
351{
352 QFETCH(QString, side);
353 QFETCH(QQuickAnchors::Anchor, anchor);
354
355 QQuickItem *baseItem = new QQuickItem;
356
357 QQuickAnchorLine anchorLine;
358 anchorLine.item = baseItem;
359 anchorLine.anchorLine = anchor;
360
361 QQuickItem *item = new QQuickItem;
362 QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
363
364 const QMetaObject *meta = itemPrivate->anchors()->metaObject();
365 QMetaProperty p = meta->property(index: meta->indexOfProperty(name: side.toUtf8().constData()));
366
367 QVERIFY(p.write(itemPrivate->anchors(), QVariant::fromValue(anchorLine)));
368 QCOMPARE(itemPrivate->anchors()->usedAnchors().testFlag(anchor), true);
369
370 QVERIFY(p.reset(itemPrivate->anchors()));
371 QCOMPARE(itemPrivate->anchors()->usedAnchors().testFlag(anchor), false);
372
373 delete item;
374 delete baseItem;
375}
376
377void tst_qquickanchors::reset_data()
378{
379 QTest::addColumn<QString>(name: "side");
380 QTest::addColumn<QQuickAnchors::Anchor>(name: "anchor");
381
382 QTest::newRow(dataTag: "left") << "left" << QQuickAnchors::LeftAnchor;
383 QTest::newRow(dataTag: "top") << "top" << QQuickAnchors::TopAnchor;
384 QTest::newRow(dataTag: "right") << "right" << QQuickAnchors::RightAnchor;
385 QTest::newRow(dataTag: "bottom") << "bottom" << QQuickAnchors::BottomAnchor;
386
387 QTest::newRow(dataTag: "hcenter") << "horizontalCenter" << QQuickAnchors::HCenterAnchor;
388 QTest::newRow(dataTag: "vcenter") << "verticalCenter" << QQuickAnchors::VCenterAnchor;
389 QTest::newRow(dataTag: "baseline") << "baseline" << QQuickAnchors::BaselineAnchor;
390}
391
392void tst_qquickanchors::resetConvenience()
393{
394 QQuickItem *baseItem = new QQuickItem;
395 QQuickItem *item = new QQuickItem;
396 QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
397
398 //fill
399 itemPrivate->anchors()->setFill(baseItem);
400 QCOMPARE(itemPrivate->anchors()->fill(), baseItem);
401 itemPrivate->anchors()->resetFill();
402 QVERIFY(!itemPrivate->anchors()->fill());
403
404 //centerIn
405 itemPrivate->anchors()->setCenterIn(baseItem);
406 QCOMPARE(itemPrivate->anchors()->centerIn(), baseItem);
407 itemPrivate->anchors()->resetCenterIn();
408 QVERIFY(!itemPrivate->anchors()->centerIn());
409
410 delete item;
411 delete baseItem;
412}
413
414void tst_qquickanchors::nullItem()
415{
416 QFETCH(QString, side);
417
418 QQuickAnchorLine anchor;
419 QQuickItem *item = new QQuickItem;
420 QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
421
422 const QMetaObject *meta = itemPrivate->anchors()->metaObject();
423 QMetaProperty p = meta->property(index: meta->indexOfProperty(name: side.toUtf8().constData()));
424
425 QTest::ignoreMessage(type: QtWarningMsg, message: "<Unknown File>: QML Item: Cannot anchor to a null item.");
426 QVERIFY(p.write(itemPrivate->anchors(), QVariant::fromValue(anchor)));
427
428 delete item;
429}
430
431void tst_qquickanchors::nullItem_data()
432{
433 QTest::addColumn<QString>(name: "side");
434
435 QTest::newRow(dataTag: "left") << "left";
436 QTest::newRow(dataTag: "top") << "top";
437 QTest::newRow(dataTag: "right") << "right";
438 QTest::newRow(dataTag: "bottom") << "bottom";
439
440 QTest::newRow(dataTag: "hcenter") << "horizontalCenter";
441 QTest::newRow(dataTag: "vcenter") << "verticalCenter";
442 QTest::newRow(dataTag: "baseline") << "baseline";
443}
444
445//QTBUG-5428
446void tst_qquickanchors::crash1()
447{
448 QUrl source(testFileUrl(fileName: "crash1.qml"));
449
450 QQuickView *view = new QQuickView(source);
451 qApp->processEvents();
452
453 delete view;
454}
455
456void tst_qquickanchors::fill()
457{
458 QQuickView *view = new QQuickView(testFileUrl(fileName: "fill.qml"));
459
460 qApp->processEvents();
461 QQuickRectangle* rect = findItem<QQuickRectangle>(parent: view->rootObject(), objectName: QLatin1String("filler"));
462 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(item: rect);
463 QCOMPARE(rectPrivate->anchors()->leftMargin(), 10.0);
464 QCOMPARE(rectPrivate->anchors()->topMargin(), 30.0);
465 QCOMPARE(rectPrivate->anchors()->rightMargin(), 20.0);
466 QCOMPARE(rectPrivate->anchors()->bottomMargin(), 40.0);
467 QCOMPARE(rect->x(), 0.0 + 10.0);
468 QCOMPARE(rect->y(), 0.0 + 30.0);
469 QCOMPARE(rect->width(), 200.0 - 10.0 - 20.0);
470 QCOMPARE(rect->height(), 200.0 - 30.0 - 40.0);
471 //Alter Offsets (tests QTBUG-6631)
472 rectPrivate->anchors()->setLeftMargin(20.0);
473 rectPrivate->anchors()->setRightMargin(0.0);
474 rectPrivate->anchors()->setBottomMargin(0.0);
475 rectPrivate->anchors()->setTopMargin(10.0);
476 QCOMPARE(rectPrivate->anchors()->leftMargin(), 20.0);
477 QCOMPARE(rectPrivate->anchors()->topMargin(), 10.0);
478 QCOMPARE(rectPrivate->anchors()->rightMargin(), 0.0);
479 QCOMPARE(rectPrivate->anchors()->bottomMargin(), 0.0);
480 QCOMPARE(rect->x(), 0.0 + 20.0);
481 QCOMPARE(rect->y(), 0.0 + 10.0);
482 QCOMPARE(rect->width(), 200.0 - 20.0);
483 QCOMPARE(rect->height(), 200.0 - 10.0);
484
485 delete view;
486}
487
488void tst_qquickanchors::fillRTL()
489{
490 QQuickView *view = new QQuickView(testFileUrl(fileName: "fill.qml"));
491
492 qApp->processEvents();
493 QQuickRectangle* rect = findItem<QQuickRectangle>(parent: view->rootObject(), objectName: QLatin1String("filler"));
494 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(item: rect);
495 mirrorAnchors(item: rect);
496
497 QCOMPARE(rect->x(), 0.0 + 20.0);
498 QCOMPARE(rect->y(), 0.0 + 30.0);
499 QCOMPARE(rect->width(), 200.0 - 10.0 - 20.0);
500 QCOMPARE(rect->height(), 200.0 - 30.0 - 40.0);
501 //Alter Offsets (tests QTBUG-6631)
502 rectPrivate->anchors()->setLeftMargin(20.0);
503 rectPrivate->anchors()->setRightMargin(0.0);
504 rectPrivate->anchors()->setBottomMargin(0.0);
505 rectPrivate->anchors()->setTopMargin(10.0);
506 QCOMPARE(rect->x(), 0.0 + 0.0);
507 QCOMPARE(rect->y(), 0.0 + 10.0);
508 QCOMPARE(rect->width(), 200.0 - 20.0);
509 QCOMPARE(rect->height(), 200.0 - 10.0);
510
511 delete view;
512}
513
514void tst_qquickanchors::centerIn()
515{
516 QQuickView *view = new QQuickView(testFileUrl(fileName: "centerin.qml"));
517
518 qApp->processEvents();
519 QQuickRectangle* rect = findItem<QQuickRectangle>(parent: view->rootObject(), objectName: QLatin1String("centered"));
520 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(item: rect);
521
522 QCOMPARE(rectPrivate->anchors()->horizontalCenterOffset(), 10.0);
523 QCOMPARE(rectPrivate->anchors()->verticalCenterOffset(), 30.0);
524 QCOMPARE(rect->x(), 75.0 + 10);
525 QCOMPARE(rect->y(), 75.0 + 30);
526 //Alter Offsets (tests QTBUG-6631)
527 rectPrivate->anchors()->setHorizontalCenterOffset(-20.0);
528 rectPrivate->anchors()->setVerticalCenterOffset(-10.0);
529 QCOMPARE(rectPrivate->anchors()->horizontalCenterOffset(), -20.0);
530 QCOMPARE(rectPrivate->anchors()->verticalCenterOffset(), -10.0);
531 QCOMPARE(rect->x(), 75.0 - 20.0);
532 QCOMPARE(rect->y(), 75.0 - 10.0);
533
534 // By default center aligned to pixel
535 QQuickRectangle* rect2 = findItem<QQuickRectangle>(parent: view->rootObject(), objectName: QLatin1String("centered2"));
536 QCOMPARE(rect2->x(), 94.0);
537 QCOMPARE(rect2->y(), 94.0);
538
539 //QTBUG-21730 (use actual center to prevent animation jitter)
540 QQuickRectangle* rect3 = findItem<QQuickRectangle>(parent: view->rootObject(), objectName: QLatin1String("centered3"));
541 QCOMPARE(rect3->x(), 94.5);
542 QCOMPARE(rect3->y(), 94.5);
543
544 delete view;
545}
546
547void tst_qquickanchors::centerInRTL()
548{
549 QQuickView *view = new QQuickView(testFileUrl(fileName: "centerin.qml"));
550
551 qApp->processEvents();
552 QQuickRectangle* rect = findItem<QQuickRectangle>(parent: view->rootObject(), objectName: QLatin1String("centered"));
553 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(item: rect);
554 mirrorAnchors(item: rect);
555
556 QCOMPARE(rect->x(), 75.0 - 10);
557 QCOMPARE(rect->y(), 75.0 + 30);
558 //Alter Offsets (tests QTBUG-6631)
559 rectPrivate->anchors()->setHorizontalCenterOffset(-20.0);
560 rectPrivate->anchors()->setVerticalCenterOffset(-10.0);
561 QCOMPARE(rect->x(), 75.0 + 20.0);
562 QCOMPARE(rect->y(), 75.0 - 10.0);
563
564 delete view;
565}
566
567//QTBUG-12441
568void tst_qquickanchors::centerInRotation()
569{
570 QQuickView *view = new QQuickView(testFileUrl(fileName: "centerinRotation.qml"));
571
572 qApp->processEvents();
573 QQuickRectangle* outer = findItem<QQuickRectangle>(parent: view->rootObject(), objectName: QLatin1String("outer"));
574 QQuickRectangle* inner = findItem<QQuickRectangle>(parent: view->rootObject(), objectName: QLatin1String("inner"));
575
576 QCOMPARE(outer->x(), qreal(49.5));
577 QCOMPARE(outer->y(), qreal(49.5));
578 QCOMPARE(inner->x(), qreal(25.5));
579 QCOMPARE(inner->y(), qreal(25.5));
580
581 delete view;
582}
583
584void tst_qquickanchors::hvCenter()
585{
586 QQuickView *view = new QQuickView(testFileUrl(fileName: "hvCenter.qml"));
587
588 qApp->processEvents();
589 QQuickRectangle* rect = findItem<QQuickRectangle>(parent: view->rootObject(), objectName: QLatin1String("centered"));
590 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(item: rect);
591
592 // test QTBUG-10999
593 QCOMPARE(rect->x(), 10.0);
594 QCOMPARE(rect->y(), 19.0);
595
596 rectPrivate->anchors()->setHorizontalCenterOffset(-5.0);
597 rectPrivate->anchors()->setVerticalCenterOffset(5.0);
598 QCOMPARE(rect->x(), 10.0 - 5.0);
599 QCOMPARE(rect->y(), 19.0 + 5.0);
600
601 delete view;
602}
603
604void tst_qquickanchors::hvCenterRTL()
605{
606 QQuickView *view = new QQuickView(testFileUrl(fileName: "hvCenter.qml"));
607
608 qApp->processEvents();
609 QQuickRectangle* rect = findItem<QQuickRectangle>(parent: view->rootObject(), objectName: QLatin1String("centered"));
610 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(item: rect);
611 mirrorAnchors(item: rect);
612
613 // test QTBUG-10999
614 QCOMPARE(rect->x(), 10.0);
615 QCOMPARE(rect->y(), 19.0);
616
617 rectPrivate->anchors()->setHorizontalCenterOffset(-5.0);
618 rectPrivate->anchors()->setVerticalCenterOffset(5.0);
619 QCOMPARE(rect->x(), 10.0 + 5.0);
620 QCOMPARE(rect->y(), 19.0 + 5.0);
621
622 delete view;
623}
624
625void tst_qquickanchors::margins_data()
626{
627 QTest::addColumn<QUrl>(name: "source");
628
629 QTest::newRow(dataTag: "fill") << testFileUrl(fileName: "margins.qml");
630 QTest::newRow(dataTag: "individual") << testFileUrl(fileName: "individualMargins.qml");
631}
632
633void tst_qquickanchors::margins()
634{
635 QFETCH(QUrl, source);
636 QQuickView *view = new QQuickView(source);
637
638 qApp->processEvents();
639 QQuickRectangle* rect = findItem<QQuickRectangle>(parent: view->rootObject(), objectName: QLatin1String("filler"));
640 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(item: rect);
641 QCOMPARE(rectPrivate->anchors()->margins(), 10.0);
642 QCOMPARE(rectPrivate->anchors()->topMargin(), 6.0);
643 QCOMPARE(rectPrivate->anchors()->leftMargin(), 5.0);
644 QCOMPARE(rectPrivate->anchors()->bottomMargin(), 10.0);
645 QCOMPARE(rectPrivate->anchors()->rightMargin(), 10.0);
646 QCOMPARE(rect->x(), 5.0);
647 QCOMPARE(rect->y(), 6.0);
648 QCOMPARE(rect->width(), 200.0 - 5.0 - 10.0);
649 QCOMPARE(rect->height(), 200.0 - 6.0 - 10.0);
650
651 rectPrivate->anchors()->setTopMargin(0.0);
652 rectPrivate->anchors()->setMargins(20.0);
653
654 QCOMPARE(rectPrivate->anchors()->margins(), 20.0);
655 QCOMPARE(rectPrivate->anchors()->topMargin(), 0.0);
656 QCOMPARE(rectPrivate->anchors()->leftMargin(), 5.0);
657 QCOMPARE(rectPrivate->anchors()->bottomMargin(), 20.0);
658 QCOMPARE(rectPrivate->anchors()->rightMargin(), 20.0);
659 QCOMPARE(rect->x(), 5.0);
660 QCOMPARE(rect->y(), 0.0);
661 QCOMPARE(rect->width(), 200.0 - 5.0 - 20.0);
662 QCOMPARE(rect->height(), 200.0 - 0.0 - 20.0);
663
664 rectPrivate->anchors()->setRightMargin(0.0);
665 rectPrivate->anchors()->setBottomMargin(0.0);
666 QCOMPARE(rectPrivate->anchors()->margins(), 20.0);
667 QCOMPARE(rectPrivate->anchors()->topMargin(), 0.0);
668 QCOMPARE(rectPrivate->anchors()->leftMargin(), 5.0);
669 QCOMPARE(rectPrivate->anchors()->bottomMargin(), 0.0);
670 QCOMPARE(rectPrivate->anchors()->rightMargin(), 0.0);
671 QCOMPARE(rect->x(), 5.0);
672 QCOMPARE(rect->y(), 0.0);
673 QCOMPARE(rect->width(), 200.0 - 5.0 - 0.0);
674 QCOMPARE(rect->height(), 200.0 - 0.0 - 0.0);
675
676 // Test setting margins doesn't have any effect on individual margins with explicit values.
677 rectPrivate->anchors()->setMargins(50.0);
678 QCOMPARE(rectPrivate->anchors()->margins(), 50.0);
679 QCOMPARE(rectPrivate->anchors()->leftMargin(), 5.0);
680 QCOMPARE(rectPrivate->anchors()->topMargin(), 0.0);
681 QCOMPARE(rectPrivate->anchors()->rightMargin(), 0.0);
682 QCOMPARE(rectPrivate->anchors()->bottomMargin(), 0.0);
683 QCOMPARE(rect->x(), 0.0 + 5.0);
684 QCOMPARE(rect->y(), 0.0 + 0.0);
685 QCOMPARE(rect->width(), 200.0 - 5.0 - 0.0);
686 QCOMPARE(rect->height(), 200.0 - 0.0 - 0.0);
687
688 // Test that individual margins that are reset have the same value as margins.
689 rectPrivate->anchors()->resetLeftMargin();
690 rectPrivate->anchors()->resetBottomMargin();
691 QCOMPARE(rectPrivate->anchors()->leftMargin(), 50.0);
692 QCOMPARE(rectPrivate->anchors()->topMargin(), 0.0);
693 QCOMPARE(rectPrivate->anchors()->rightMargin(), 0.0);
694 QCOMPARE(rectPrivate->anchors()->bottomMargin(), 50.0);
695 QCOMPARE(rect->x(), 0.0 + 50.0);
696 QCOMPARE(rect->y(), 0.0 + 0.0);
697 QCOMPARE(rect->width(), 200.0 - 50.0 - 0.0);
698 QCOMPARE(rect->height(), 200.0 - 0.0 - 50.0);
699
700 rectPrivate->anchors()->setMargins(30.0);
701 QCOMPARE(rectPrivate->anchors()->margins(), 30.0);
702 QCOMPARE(rectPrivate->anchors()->leftMargin(), 30.0);
703 QCOMPARE(rectPrivate->anchors()->topMargin(), 0.0);
704 QCOMPARE(rectPrivate->anchors()->rightMargin(), 0.0);
705 QCOMPARE(rectPrivate->anchors()->bottomMargin(), 30.0);
706 QCOMPARE(rect->x(), 0.0 + 30.0);
707 QCOMPARE(rect->y(), 0.0 + 0.0);
708 QCOMPARE(rect->width(), 200.0 - 30.0 - 0.0);
709 QCOMPARE(rect->height(), 200.0 - 0.0 - 30.0);
710
711 rectPrivate->anchors()->resetTopMargin();
712 rectPrivate->anchors()->resetRightMargin();
713 QCOMPARE(rectPrivate->anchors()->leftMargin(), 30.0);
714 QCOMPARE(rectPrivate->anchors()->topMargin(), 30.0);
715 QCOMPARE(rectPrivate->anchors()->rightMargin(), 30.0);
716 QCOMPARE(rectPrivate->anchors()->bottomMargin(), 30.0);
717 QCOMPARE(rect->x(), 0.0 + 30.0);
718 QCOMPARE(rect->y(), 0.0 + 30.0);
719 QCOMPARE(rect->width(), 200.0 - 30.0 - 30.0);
720 QCOMPARE(rect->height(), 200.0 - 30.0 - 30.0);
721
722 rectPrivate->anchors()->setMargins(25.0);
723 QCOMPARE(rectPrivate->anchors()->margins(), 25.0);
724 QCOMPARE(rectPrivate->anchors()->leftMargin(), 25.0);
725 QCOMPARE(rectPrivate->anchors()->topMargin(), 25.0);
726 QCOMPARE(rectPrivate->anchors()->rightMargin(), 25.0);
727 QCOMPARE(rectPrivate->anchors()->bottomMargin(), 25.0);
728 QCOMPARE(rect->x(), 0.0 + 25.0);
729 QCOMPARE(rect->y(), 0.0 + 25.0);
730 QCOMPARE(rect->width(), 200.0 - 25.0 - 25.0);
731 QCOMPARE(rect->height(), 200.0 - 25.0 - 25.0);
732
733 delete view;
734}
735
736void tst_qquickanchors::marginsRTL()
737{
738 QFETCH(QUrl, source);
739 QQuickView *view = new QQuickView(source);
740
741 QQuickRectangle* rect = findItem<QQuickRectangle>(parent: view->rootObject(), objectName: QLatin1String("filler"));
742 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(item: rect);
743 mirrorAnchors(item: rect);
744
745 QCOMPARE(rect->x(), 10.0);
746 QCOMPARE(rect->y(), 6.0);
747 QCOMPARE(rect->width(), 200.0 - 5.0 - 10.0);
748 QCOMPARE(rect->height(), 200.0 - 6.0 - 10.0);
749
750 rectPrivate->anchors()->setTopMargin(0.0);
751 rectPrivate->anchors()->setMargins(20.0);
752
753 QCOMPARE(rect->x(), 20.0);
754 QCOMPARE(rect->y(), 0.0);
755 QCOMPARE(rect->width(), 200.0 - 5.0 - 20.0);
756 QCOMPARE(rect->height(), 200.0 - 0.0 - 20.0);
757
758 delete view;
759}
760
761void tst_qquickanchors::stretch()
762{
763 QQuickView *view = new QQuickView(testFileUrl(fileName: "stretch.qml"));
764
765 qApp->processEvents();
766 QQuickRectangle* rect = findItem<QQuickRectangle>(parent: view->rootObject(), objectName: QLatin1String("stretcher"));
767 QCOMPARE(rect->x(), 160.0);
768 QCOMPARE(rect->y(), 130.0);
769 QCOMPARE(rect->width(), 40.0);
770 QCOMPARE(rect->height(), 100.0);
771
772 QQuickRectangle* rect2 = findItem<QQuickRectangle>(parent: view->rootObject(), objectName: QLatin1String("stretcher2"));
773 QCOMPARE(rect2->y(), 130.0);
774 QCOMPARE(rect2->height(), 100.0);
775
776 delete view;
777}
778
779void tst_qquickanchors::baselineOffset()
780{
781 QQmlEngine engine;
782 QQmlComponent component(&engine, testFileUrl(fileName: "baselineOffset.qml"));
783 QScopedPointer<QObject> object(component.create());
784
785 QQuickItem *item = qobject_cast<QQuickItem *>(object: object.data());
786 QVERIFY(item);
787
788 QQuickItem *anchoredItem = findItem<QQuickItem>(parent: item, objectName: QLatin1String("baselineAnchored"));
789
790 QCOMPARE(anchoredItem->baselineOffset(), 0.0);
791 QCOMPARE(anchoredItem->y(), 100.0);
792
793 anchoredItem->setBaselineOffset(5);
794 QCOMPARE(anchoredItem->baselineOffset(), 5.0);
795 QCOMPARE(anchoredItem->y(), 95.0);
796
797 anchoredItem->setBaselineOffset(10);
798 QCOMPARE(anchoredItem->baselineOffset(), 10.0);
799 QCOMPARE(anchoredItem->y(), 90.0);
800}
801
802QTEST_MAIN(tst_qquickanchors)
803
804#include "tst_qquickanchors.moc"
805

source code of qtdeclarative/tests/auto/quick/qquickanchors/tst_qquickanchors.cpp