1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
42 #include <QtTest/QSignalSpy>
43 #include <QtQml/qqmlengine.h>
44 #include <QtQml/qqmlcomponent.h>
45 #include <QtQml/qqmlcontext.h>
46 #include <QtQuick/qquickview.h>
47 #include <QtGui/private/qinputmethod_p.h>
48 #include <QtQuick/private/qquickrectangle_p.h>
49 #include <QtQuick/private/qquicktextinput_p.h>
50 #include <private/qquickitem_p.h>
51 #include "../../shared/util.h"
52 #include "../shared/visualtestutil.h"
53 #include "../../shared/platforminputcontext.h"
55 using namespace QQuickVisualTestUtil;
57 class tst_QQuickItem : public QQmlDataTest
68 void keysProcessingOrder();
71 void keyNavigation_RightToLeft();
72 void keyNavigation_skipNotVisible();
73 void keyNavigation_implicitSetting();
74 void layoutMirroring();
75 void layoutMirroringIllegalParent();
79 void mapCoordinates();
80 void mapCoordinates_data();
81 void mapCoordinatesRect();
82 void mapCoordinatesRect_data();
83 void propertyChanges();
85 void transforms_data();
87 void childrenRectBug();
88 void childrenRectBug2();
89 void childrenRectBug3();
91 void childrenProperty();
92 void resourcesProperty();
94 void transformCrash();
97 void visibleChildren();
107 class KeysTestObject : public QObject
111 Q_PROPERTY(bool processLast READ processLast NOTIFY processLastChanged)
114 KeysTestObject() : mKey(0), mModifiers(0), mForwardedKey(0), mLast(false), mNativeScanCode(0) {}
124 bool processLast() const { return mLast; }
125 void setProcessLast(bool b) {
128 emit processLastChanged();
133 void keyPress(int key, QString text, int modifiers) {
136 mModifiers = modifiers;
138 void keyRelease(int key, QString text, int modifiers) {
141 mModifiers = modifiers;
143 void forwardedKey(int key) {
146 void specialKey(int key, QString text, quint32 nativeScanCode) {
149 mNativeScanCode = nativeScanCode;
153 void processLastChanged();
161 quint32 mNativeScanCode;
166 class KeyTestItem : public QQuickItem
170 KeyTestItem(QQuickItem *parent=0) : QQuickItem(parent), mKey(0) {}
173 void keyPressEvent(QKeyEvent *e) {
176 if (e->key() == Qt::Key_A)
182 void keyReleaseEvent(QKeyEvent *e) {
183 if (e->key() == Qt::Key_B)
193 QML_DECLARE_TYPE(KeyTestItem);
195 class HollowTestItem : public QQuickItem
198 Q_PROPERTY(bool circle READ isCircle WRITE setCircle)
199 Q_PROPERTY(qreal holeRadius READ holeRadius WRITE setHoleRadius)
202 HollowTestItem(QQuickItem *parent = 0)
203 : QQuickItem(parent),
209 setAcceptHoverEvents(true);
210 setAcceptedMouseButtons(Qt::LeftButton);
213 bool isPressed() const { return m_isPressed; }
214 bool isHovered() const { return m_isHovered; }
216 bool isCircle() const { return m_isCircle; }
217 void setCircle(bool circle) { m_isCircle = circle; }
219 qreal holeRadius() const { return m_holeRadius; }
220 void setHoleRadius(qreal radius) { m_holeRadius = radius; }
222 bool contains(const QPointF &point) const {
223 const qreal w = width();
224 const qreal h = height();
225 const qreal r = m_holeRadius;
228 if (!QRectF(0, 0, w, h).contains(point))
233 return !QRectF(w / 2 - r, h / 2 - r, r * 2, r * 2).contains(point);
236 const qreal dx = point.x() - (w / 2);
237 const qreal dy = point.y() - (h / 2);
238 const qreal dd = (dx * dx) + (dy * dy);
239 const qreal outerRadius = qMin<qreal>(w / 2, h / 2);
240 return dd > (r * r) && dd <= outerRadius * outerRadius;
244 void hoverEnterEvent(QHoverEvent *) { m_isHovered = true; }
245 void hoverLeaveEvent(QHoverEvent *) { m_isHovered = false; }
246 void mousePressEvent(QMouseEvent *) { m_isPressed = true; }
247 void mouseReleaseEvent(QMouseEvent *) { m_isPressed = false; }
256 QML_DECLARE_TYPE(HollowTestItem);
259 tst_QQuickItem::tst_QQuickItem()
263 void tst_QQuickItem::initTestCase()
265 QQmlDataTest::initTestCase();
266 qmlRegisterType<KeyTestItem>("Test",1,0,"KeyTestItem");
267 qmlRegisterType<HollowTestItem>("Test", 1, 0, "HollowTestItem");
270 void tst_QQuickItem::cleanup()
272 QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
273 inputMethodPrivate->testContext = 0;
276 void tst_QQuickItem::keys()
278 QQuickView *window = new QQuickView(0);
279 window->setBaseSize(QSize(240,320));
281 KeysTestObject *testObject = new KeysTestObject;
282 window->rootContext()->setContextProperty("keysTestObject", testObject);
284 window->rootContext()->setContextProperty("enableKeyHanding", QVariant(true));
285 window->rootContext()->setContextProperty("forwardeeVisible", QVariant(true));
287 window->setSource(testFileUrl("keystest.qml"));
289 window->requestActivateWindow();
290 QVERIFY(QTest::qWaitForWindowActive(window));
291 QVERIFY(QGuiApplication::focusWindow() == window);
293 QVERIFY(window->rootObject());
294 QCOMPARE(window->rootObject()->property("isEnabled").toBool(), true);
296 QKeyEvent key(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "A", false, 1);
297 QGuiApplication::sendEvent(window, &key);
298 QCOMPARE(testObject->mKey, int(Qt::Key_A));
299 QCOMPARE(testObject->mForwardedKey, int(Qt::Key_A));
300 QCOMPARE(testObject->mText, QLatin1String("A"));
301 QVERIFY(testObject->mModifiers == Qt::NoModifier);
302 QVERIFY(!key.isAccepted());
306 key = QKeyEvent(QEvent::KeyRelease, Qt::Key_A, Qt::ShiftModifier, "A", false, 1);
307 QGuiApplication::sendEvent(window, &key);
308 QCOMPARE(testObject->mKey, int(Qt::Key_A));
309 QCOMPARE(testObject->mForwardedKey, int(Qt::Key_A));
310 QCOMPARE(testObject->mText, QLatin1String("A"));
311 QVERIFY(testObject->mModifiers == Qt::ShiftModifier);
312 QVERIFY(key.isAccepted());
316 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier, "", false, 1);
317 QGuiApplication::sendEvent(window, &key);
318 QCOMPARE(testObject->mKey, int(Qt::Key_Return));
319 QCOMPARE(testObject->mForwardedKey, int(Qt::Key_Return));
320 QCOMPARE(testObject->mText, QLatin1String("Return"));
321 QVERIFY(testObject->mModifiers == Qt::NoModifier);
322 QVERIFY(key.isAccepted());
326 key = QKeyEvent(QEvent::KeyPress, Qt::Key_0, Qt::NoModifier, "0", false, 1);
327 QGuiApplication::sendEvent(window, &key);
328 QCOMPARE(testObject->mKey, int(Qt::Key_0));
329 QCOMPARE(testObject->mForwardedKey, int(Qt::Key_0));
330 QCOMPARE(testObject->mText, QLatin1String("0"));
331 QVERIFY(testObject->mModifiers == Qt::NoModifier);
332 QVERIFY(key.isAccepted());
336 key = QKeyEvent(QEvent::KeyPress, Qt::Key_9, Qt::NoModifier, "9", false, 1);
337 QGuiApplication::sendEvent(window, &key);
338 QCOMPARE(testObject->mKey, int(Qt::Key_9));
339 QCOMPARE(testObject->mForwardedKey, int(Qt::Key_9));
340 QCOMPARE(testObject->mText, QLatin1String("9"));
341 QVERIFY(testObject->mModifiers == Qt::NoModifier);
342 QVERIFY(!key.isAccepted());
346 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
347 QGuiApplication::sendEvent(window, &key);
348 QCOMPARE(testObject->mKey, int(Qt::Key_Tab));
349 QCOMPARE(testObject->mForwardedKey, int(Qt::Key_Tab));
350 QCOMPARE(testObject->mText, QLatin1String("Tab"));
351 QVERIFY(testObject->mModifiers == Qt::NoModifier);
352 QVERIFY(key.isAccepted());
356 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
357 QGuiApplication::sendEvent(window, &key);
358 QCOMPARE(testObject->mKey, int(Qt::Key_Backtab));
359 QCOMPARE(testObject->mForwardedKey, int(Qt::Key_Backtab));
360 QCOMPARE(testObject->mText, QLatin1String("Backtab"));
361 QVERIFY(testObject->mModifiers == Qt::NoModifier);
362 QVERIFY(key.isAccepted());
366 key = QKeyEvent(QEvent::KeyPress, Qt::Key_VolumeUp, Qt::NoModifier, 1234, 0, 0);
367 QGuiApplication::sendEvent(window, &key);
368 QCOMPARE(testObject->mKey, int(Qt::Key_VolumeUp));
369 QCOMPARE(testObject->mForwardedKey, int(Qt::Key_VolumeUp));
370 QVERIFY(testObject->mModifiers == Qt::NoModifier);
371 QVERIFY(testObject->mNativeScanCode == 1234);
372 QVERIFY(key.isAccepted());
376 window->rootContext()->setContextProperty("forwardeeVisible", QVariant(false));
377 key = QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "A", false, 1);
378 QGuiApplication::sendEvent(window, &key);
379 QCOMPARE(testObject->mKey, int(Qt::Key_A));
380 QCOMPARE(testObject->mForwardedKey, 0);
381 QCOMPARE(testObject->mText, QLatin1String("A"));
382 QVERIFY(testObject->mModifiers == Qt::NoModifier);
383 QVERIFY(!key.isAccepted());
387 window->rootContext()->setContextProperty("enableKeyHanding", QVariant(false));
388 QCOMPARE(window->rootObject()->property("isEnabled").toBool(), false);
390 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier, "", false, 1);
391 QGuiApplication::sendEvent(window, &key);
392 QCOMPARE(testObject->mKey, 0);
393 QVERIFY(!key.isAccepted());
395 window->rootContext()->setContextProperty("enableKeyHanding", QVariant(true));
396 QCOMPARE(window->rootObject()->property("isEnabled").toBool(), true);
398 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier, "", false, 1);
399 QGuiApplication::sendEvent(window, &key);
400 QCOMPARE(testObject->mKey, int(Qt::Key_Return));
401 QVERIFY(key.isAccepted());
407 void tst_QQuickItem::keysProcessingOrder()
409 QQuickView *window = new QQuickView(0);
410 window->setBaseSize(QSize(240,320));
412 KeysTestObject *testObject = new KeysTestObject;
413 window->rootContext()->setContextProperty("keysTestObject", testObject);
415 window->setSource(testFileUrl("keyspriority.qml"));
417 window->requestActivateWindow();
418 QVERIFY(QTest::qWaitForWindowActive(window));
419 QVERIFY(QGuiApplication::focusWindow() == window);
421 KeyTestItem *testItem = qobject_cast<KeyTestItem*>(window->rootObject());
424 QCOMPARE(testItem->property("priorityTest").toInt(), 0);
426 QKeyEvent key(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "A", false, 1);
427 QGuiApplication::sendEvent(window, &key);
428 QCOMPARE(testObject->mKey, int(Qt::Key_A));
429 QCOMPARE(testObject->mText, QLatin1String("A"));
430 QVERIFY(testObject->mModifiers == Qt::NoModifier);
431 QVERIFY(key.isAccepted());
435 testObject->setProcessLast(true);
437 QCOMPARE(testItem->property("priorityTest").toInt(), 1);
439 key = QKeyEvent(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "A", false, 1);
440 QGuiApplication::sendEvent(window, &key);
441 QCOMPARE(testObject->mKey, 0);
442 QVERIFY(key.isAccepted());
446 key = QKeyEvent(QEvent::KeyPress, Qt::Key_B, Qt::NoModifier, "B", false, 1);
447 QGuiApplication::sendEvent(window, &key);
448 QCOMPARE(testObject->mKey, int(Qt::Key_B));
449 QCOMPARE(testObject->mText, QLatin1String("B"));
450 QVERIFY(testObject->mModifiers == Qt::NoModifier);
451 QVERIFY(!key.isAccepted());
455 key = QKeyEvent(QEvent::KeyRelease, Qt::Key_B, Qt::NoModifier, "B", false, 1);
456 QGuiApplication::sendEvent(window, &key);
457 QCOMPARE(testObject->mKey, 0);
458 QVERIFY(key.isAccepted());
464 void tst_QQuickItem::keysim()
466 PlatformInputContext platformInputContext;
467 QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
468 inputMethodPrivate->testContext = &platformInputContext;
470 QQuickView *window = new QQuickView(0);
471 window->setBaseSize(QSize(240,320));
473 window->setSource(testFileUrl("keysim.qml"));
475 window->requestActivateWindow();
476 QVERIFY(QTest::qWaitForWindowActive(window));
477 QVERIFY(QGuiApplication::focusWindow() == window);
479 QVERIFY(window->rootObject());
480 QVERIFY(window->rootObject()->hasFocus() && window->rootObject()->hasActiveFocus());
482 QQuickTextInput *input = window->rootObject()->findChild<QQuickTextInput*>();
485 QInputMethodEvent ev("Hello world!", QList<QInputMethodEvent::Attribute>());
486 QGuiApplication::sendEvent(qGuiApp->focusObject(), &ev);
488 QEXPECT_FAIL("", "QTBUG-24280", Continue);
489 QCOMPARE(input->text(), QLatin1String("Hello world!"));
494 QQuickItemPrivate *childPrivate(QQuickItem *rootItem, const char * itemString)
496 QQuickItem *item = findItem<QQuickItem>(rootItem, QString(QLatin1String(itemString)));
497 QQuickItemPrivate* itemPrivate = QQuickItemPrivate::get(item);
501 QVariant childProperty(QQuickItem *rootItem, const char * itemString, const char * property)
503 QQuickItem *item = findItem<QQuickItem>(rootItem, QString(QLatin1String(itemString)));
504 return item->property(property);
507 bool anchorsMirrored(QQuickItem *rootItem, const char * itemString)
509 QQuickItem *item = findItem<QQuickItem>(rootItem, QString(QLatin1String(itemString)));
510 QQuickItemPrivate* itemPrivate = QQuickItemPrivate::get(item);
511 return itemPrivate->anchors()->mirrored();
514 void tst_QQuickItem::layoutMirroring()
516 QQuickView *window = new QQuickView(0);
517 window->setSource(testFileUrl("layoutmirroring.qml"));
520 QQuickItem *rootItem = qobject_cast<QQuickItem*>(window->rootObject());
522 QQuickItemPrivate *rootPrivate = QQuickItemPrivate::get(rootItem);
523 QVERIFY(rootPrivate);
525 QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true);
526 QCOMPARE(childPrivate(rootItem, "mirrored2")->effectiveLayoutMirror, true);
527 QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false);
528 QCOMPARE(childPrivate(rootItem, "notMirrored2")->effectiveLayoutMirror, false);
529 QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, true);
530 QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, true);
532 QCOMPARE(anchorsMirrored(rootItem, "mirrored1"), true);
533 QCOMPARE(anchorsMirrored(rootItem, "mirrored2"), true);
534 QCOMPARE(anchorsMirrored(rootItem, "notMirrored1"), false);
535 QCOMPARE(anchorsMirrored(rootItem, "notMirrored2"), false);
536 QCOMPARE(anchorsMirrored(rootItem, "inheritedMirror1"), true);
537 QCOMPARE(anchorsMirrored(rootItem, "inheritedMirror2"), true);
539 QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, true);
540 QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritedLayoutMirror, false);
541 QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, true);
542 QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritedLayoutMirror, false);
543 QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, true);
544 QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, true);
546 QCOMPARE(childPrivate(rootItem, "mirrored1")->isMirrorImplicit, false);
547 QCOMPARE(childPrivate(rootItem, "mirrored2")->isMirrorImplicit, false);
548 QCOMPARE(childPrivate(rootItem, "notMirrored1")->isMirrorImplicit, false);
549 QCOMPARE(childPrivate(rootItem, "notMirrored2")->isMirrorImplicit, true);
550 QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->isMirrorImplicit, true);
551 QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->isMirrorImplicit, true);
553 QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritMirrorFromParent, true);
554 QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritMirrorFromParent, false);
555 QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritMirrorFromParent, true);
556 QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritMirrorFromParent, false);
557 QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritMirrorFromParent, true);
558 QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritMirrorFromParent, true);
560 QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritMirrorFromItem, true);
561 QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritMirrorFromItem, false);
562 QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritMirrorFromItem, false);
563 QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritMirrorFromItem, false);
564 QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritMirrorFromItem, false);
565 QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritMirrorFromItem, false);
567 // load dynamic content using Loader that needs to inherit mirroring
568 rootItem->setProperty("state", "newContent");
569 QCOMPARE(childPrivate(rootItem, "notMirrored3")->effectiveLayoutMirror, false);
570 QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->effectiveLayoutMirror, true);
572 QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritedLayoutMirror, true);
573 QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->inheritedLayoutMirror, true);
575 QCOMPARE(childPrivate(rootItem, "notMirrored3")->isMirrorImplicit, false);
576 QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->isMirrorImplicit, true);
578 QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromParent, true);
579 QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->inheritMirrorFromParent, true);
581 QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromItem, false);
582 QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromItem, false);
584 // disable inheritance
585 rootItem->setProperty("childrenInherit", false);
587 QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, false);
588 QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, false);
589 QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true);
590 QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false);
592 QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, false);
593 QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, false);
594 QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, false);
595 QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, false);
597 // re-enable inheritance
598 rootItem->setProperty("childrenInherit", true);
600 QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, true);
601 QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, true);
602 QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true);
603 QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false);
605 QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, true);
606 QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, true);
607 QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, true);
608 QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, true);
613 QQuickItem *parentItem1 = new QQuickItem();
614 QQuickItemPrivate::get(parentItem1)->effectiveLayoutMirror = true; // LayoutMirroring.enabled: true
615 QQuickItemPrivate::get(parentItem1)->isMirrorImplicit = false;
616 QQuickItemPrivate::get(parentItem1)->inheritMirrorFromItem = true; // LayoutMirroring.childrenInherit: true
617 QQuickItemPrivate::get(parentItem1)->resolveLayoutMirror();
619 // inherit in constructor
620 QQuickItem *childItem1 = new QQuickItem(parentItem1);
621 QCOMPARE(QQuickItemPrivate::get(childItem1)->effectiveLayoutMirror, true);
622 QCOMPARE(QQuickItemPrivate::get(childItem1)->inheritMirrorFromParent, true);
624 // inherit through a parent change
625 QQuickItem *childItem2 = new QQuickItem();
626 QCOMPARE(QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror, false);
627 QCOMPARE(QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent, false);
628 childItem2->setParentItem(parentItem1);
629 QCOMPARE(QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror, true);
630 QCOMPARE(QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent, true);
632 // stop inherting through a parent change
633 QQuickItem *parentItem2 = new QQuickItem();
634 QQuickItemPrivate::get(parentItem2)->effectiveLayoutMirror = true; // LayoutMirroring.enabled: true
635 QQuickItemPrivate::get(parentItem2)->resolveLayoutMirror();
636 childItem2->setParentItem(parentItem2);
637 QCOMPARE(QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror, false);
638 QCOMPARE(QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent, false);
644 void tst_QQuickItem::layoutMirroringIllegalParent()
646 QQmlComponent component(&engine);
647 component.setData("import QtQuick 2.0; QtObject { LayoutMirroring.enabled: true; LayoutMirroring.childrenInherit: true }", QUrl::fromLocalFile(""));
648 QTest::ignoreMessage(QtWarningMsg, "file::1:21: QML QtObject: LayoutDirection attached property only works with Items");
649 QObject *object = component.create();
650 QVERIFY(object != 0);
653 void tst_QQuickItem::keyNavigation()
655 QQuickView *window = new QQuickView(0);
656 window->setBaseSize(QSize(240,320));
658 window->setSource(testFileUrl("keynavigationtest.qml"));
660 window->requestActivateWindow();
661 QVERIFY(QTest::qWaitForWindowActive(window));
662 QVERIFY(QGuiApplication::focusWindow() == window);
664 QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "item1");
666 QVERIFY(item->hasActiveFocus());
669 QVERIFY(QMetaObject::invokeMethod(window->rootObject(), "verify",
670 Q_RETURN_ARG(QVariant, result)));
671 QVERIFY(result.toBool());
674 QKeyEvent key(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
675 QGuiApplication::sendEvent(window, &key);
676 QVERIFY(key.isAccepted());
678 item = findItem<QQuickItem>(window->rootObject(), "item2");
680 QVERIFY(item->hasActiveFocus());
683 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier, "", false, 1);
684 QGuiApplication::sendEvent(window, &key);
685 QVERIFY(key.isAccepted());
687 item = findItem<QQuickItem>(window->rootObject(), "item4");
689 QVERIFY(item->hasActiveFocus());
692 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier, "", false, 1);
693 QGuiApplication::sendEvent(window, &key);
694 QVERIFY(key.isAccepted());
696 item = findItem<QQuickItem>(window->rootObject(), "item3");
698 QVERIFY(item->hasActiveFocus());
701 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier, "", false, 1);
702 QGuiApplication::sendEvent(window, &key);
703 QVERIFY(key.isAccepted());
705 item = findItem<QQuickItem>(window->rootObject(), "item1");
707 QVERIFY(item->hasActiveFocus());
710 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
711 QGuiApplication::sendEvent(window, &key);
712 QVERIFY(key.isAccepted());
714 item = findItem<QQuickItem>(window->rootObject(), "item2");
716 QVERIFY(item->hasActiveFocus());
719 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
720 QGuiApplication::sendEvent(window, &key);
721 QVERIFY(key.isAccepted());
723 item = findItem<QQuickItem>(window->rootObject(), "item1");
725 QVERIFY(item->hasActiveFocus());
730 void tst_QQuickItem::keyNavigation_RightToLeft()
732 QQuickView *window = new QQuickView(0);
733 window->setBaseSize(QSize(240,320));
735 window->setSource(testFileUrl("keynavigationtest.qml"));
737 window->requestActivateWindow();
738 QVERIFY(QTest::qWaitForWindowActive(window));
739 QVERIFY(QGuiApplication::focusWindow() == window);
741 QQuickItem *rootItem = qobject_cast<QQuickItem*>(window->rootObject());
743 QQuickItemPrivate* rootItemPrivate = QQuickItemPrivate::get(rootItem);
745 rootItemPrivate->effectiveLayoutMirror = true; // LayoutMirroring.mirror: true
746 rootItemPrivate->isMirrorImplicit = false;
747 rootItemPrivate->inheritMirrorFromItem = true; // LayoutMirroring.inherit: true
748 rootItemPrivate->resolveLayoutMirror();
750 QEvent wa(QEvent::WindowActivate);
751 QGuiApplication::sendEvent(window, &wa);
752 QFocusEvent fe(QEvent::FocusIn);
753 QGuiApplication::sendEvent(window, &fe);
755 QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "item1");
757 QVERIFY(item->hasActiveFocus());
760 QVERIFY(QMetaObject::invokeMethod(window->rootObject(), "verify",
761 Q_RETURN_ARG(QVariant, result)));
762 QVERIFY(result.toBool());
765 QKeyEvent key(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier, "", false, 1);
766 QGuiApplication::sendEvent(window, &key);
767 QVERIFY(key.isAccepted());
769 item = findItem<QQuickItem>(window->rootObject(), "item2");
771 QVERIFY(item->hasActiveFocus());
774 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
775 QGuiApplication::sendEvent(window, &key);
776 QVERIFY(key.isAccepted());
778 item = findItem<QQuickItem>(window->rootObject(), "item1");
780 QVERIFY(item->hasActiveFocus());
785 void tst_QQuickItem::keyNavigation_skipNotVisible()
787 QQuickView *window = new QQuickView(0);
788 window->setBaseSize(QSize(240,320));
790 window->setSource(testFileUrl("keynavigationtest.qml"));
792 window->requestActivateWindow();
793 QVERIFY(QTest::qWaitForWindowActive(window));
794 QVERIFY(QGuiApplication::focusWindow() == window);
796 QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "item1");
798 QVERIFY(item->hasActiveFocus());
800 // Set item 2 to not visible
801 item = findItem<QQuickItem>(window->rootObject(), "item2");
803 item->setVisible(false);
804 QVERIFY(!item->isVisible());
807 QKeyEvent key(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
808 QGuiApplication::sendEvent(window, &key);
809 QVERIFY(key.isAccepted());
811 item = findItem<QQuickItem>(window->rootObject(), "item1");
813 QVERIFY(item->hasActiveFocus());
816 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
817 QGuiApplication::sendEvent(window, &key);
818 QVERIFY(key.isAccepted());
820 item = findItem<QQuickItem>(window->rootObject(), "item3");
822 QVERIFY(item->hasActiveFocus());
825 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
826 QGuiApplication::sendEvent(window, &key);
827 QVERIFY(key.isAccepted());
829 item = findItem<QQuickItem>(window->rootObject(), "item1");
831 QVERIFY(item->hasActiveFocus());
833 //Set item 3 to not visible
834 item = findItem<QQuickItem>(window->rootObject(), "item3");
836 item->setVisible(false);
837 QVERIFY(!item->isVisible());
840 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
841 QGuiApplication::sendEvent(window, &key);
842 QVERIFY(key.isAccepted());
844 item = findItem<QQuickItem>(window->rootObject(), "item4");
846 QVERIFY(item->hasActiveFocus());
849 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
850 QGuiApplication::sendEvent(window, &key);
851 QVERIFY(key.isAccepted());
853 item = findItem<QQuickItem>(window->rootObject(), "item1");
855 QVERIFY(item->hasActiveFocus());
860 void tst_QQuickItem::keyNavigation_implicitSetting()
862 QQuickView *window = new QQuickView(0);
863 window->setBaseSize(QSize(240,320));
865 window->setSource(testFileUrl("keynavigationtest_implicit.qml"));
867 window->requestActivateWindow();
868 QVERIFY(QTest::qWaitForWindowActive(window));
869 QVERIFY(QGuiApplication::focusWindow() == window);
871 QEvent wa(QEvent::WindowActivate);
872 QGuiApplication::sendEvent(window, &wa);
873 QFocusEvent fe(QEvent::FocusIn);
874 QGuiApplication::sendEvent(window, &fe);
876 QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "item1");
878 QVERIFY(item->hasActiveFocus());
881 QVERIFY(QMetaObject::invokeMethod(window->rootObject(), "verify",
882 Q_RETURN_ARG(QVariant, result)));
883 QVERIFY(result.toBool());
886 QKeyEvent key(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
887 QGuiApplication::sendEvent(window, &key);
888 QVERIFY(key.isAccepted());
890 item = findItem<QQuickItem>(window->rootObject(), "item2");
892 QVERIFY(item->hasActiveFocus());
895 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier, "", false, 1);
896 QGuiApplication::sendEvent(window, &key);
897 QVERIFY(key.isAccepted());
899 item = findItem<QQuickItem>(window->rootObject(), "item1");
901 QVERIFY(item->hasActiveFocus());
904 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier, "", false, 1);
905 QGuiApplication::sendEvent(window, &key);
906 QVERIFY(key.isAccepted());
908 item = findItem<QQuickItem>(window->rootObject(), "item3");
910 QVERIFY(item->hasActiveFocus());
913 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
914 QGuiApplication::sendEvent(window, &key);
915 QVERIFY(key.isAccepted());
917 item = findItem<QQuickItem>(window->rootObject(), "item4");
919 QVERIFY(item->hasActiveFocus());
922 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier, "", false, 1);
923 QGuiApplication::sendEvent(window, &key);
924 QVERIFY(key.isAccepted());
926 item = findItem<QQuickItem>(window->rootObject(), "item3");
928 QVERIFY(item->hasActiveFocus());
931 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier, "", false, 1);
932 QGuiApplication::sendEvent(window, &key);
933 QVERIFY(key.isAccepted());
935 item = findItem<QQuickItem>(window->rootObject(), "item4");
937 QVERIFY(item->hasActiveFocus());
940 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier, "", false, 1);
941 QGuiApplication::sendEvent(window, &key);
942 QVERIFY(key.isAccepted());
944 item = findItem<QQuickItem>(window->rootObject(), "item2");
946 QVERIFY(item->hasActiveFocus());
949 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier, "", false, 1);
950 QGuiApplication::sendEvent(window, &key);
951 QVERIFY(key.isAccepted());
953 item = findItem<QQuickItem>(window->rootObject(), "item4");
955 QVERIFY(item->hasActiveFocus());
958 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Tab, Qt::NoModifier, "", false, 1);
959 QGuiApplication::sendEvent(window, &key);
960 QVERIFY(key.isAccepted());
962 item = findItem<QQuickItem>(window->rootObject(), "item1");
964 QVERIFY(item->hasActiveFocus());
967 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
968 QGuiApplication::sendEvent(window, &key);
969 QVERIFY(key.isAccepted());
971 item = findItem<QQuickItem>(window->rootObject(), "item4");
973 QVERIFY(item->hasActiveFocus());
976 key = QKeyEvent(QEvent::KeyPress, Qt::Key_Backtab, Qt::NoModifier, "", false, 1);
977 QGuiApplication::sendEvent(window, &key);
978 QVERIFY(key.isAccepted());
980 item = findItem<QQuickItem>(window->rootObject(), "item3");
982 QVERIFY(item->hasActiveFocus());
987 void tst_QQuickItem::smooth()
989 QQmlComponent component(&engine);
990 component.setData("import QtQuick 2.0; Item { smooth: false; }", QUrl::fromLocalFile(""));
991 QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
992 QSignalSpy spy(item, SIGNAL(smoothChanged(bool)));
995 QVERIFY(!item->smooth());
997 item->setSmooth(true);
998 QVERIFY(item->smooth());
999 QCOMPARE(spy.count(),1);
1000 QList<QVariant> arguments = spy.first();
1001 QVERIFY(arguments.count() == 1);
1002 QVERIFY(arguments.at(0).toBool() == true);
1004 item->setSmooth(true);
1005 QCOMPARE(spy.count(),1);
1007 item->setSmooth(false);
1008 QVERIFY(!item->smooth());
1009 QCOMPARE(spy.count(),2);
1010 item->setSmooth(false);
1011 QCOMPARE(spy.count(),2);
1016 void tst_QQuickItem::antialiasing()
1018 QQmlComponent component(&engine);
1019 component.setData("import QtQuick 2.0; Item { antialiasing: false; }", QUrl::fromLocalFile(""));
1020 QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
1021 QSignalSpy spy(item, SIGNAL(antialiasingChanged(bool)));
1024 QVERIFY(!item->antialiasing());
1026 item->setAntialiasing(true);
1027 QVERIFY(item->antialiasing());
1028 QCOMPARE(spy.count(),1);
1029 QList<QVariant> arguments = spy.first();
1030 QVERIFY(arguments.count() == 1);
1031 QVERIFY(arguments.at(0).toBool() == true);
1033 item->setAntialiasing(true);
1034 QCOMPARE(spy.count(),1);
1036 item->setAntialiasing(false);
1037 QVERIFY(!item->antialiasing());
1038 QCOMPARE(spy.count(),2);
1039 item->setAntialiasing(false);
1040 QCOMPARE(spy.count(),2);
1045 void tst_QQuickItem::clip()
1047 QQmlComponent component(&engine);
1048 component.setData("import QtQuick 2.0\nItem { clip: false\n }", QUrl::fromLocalFile(""));
1049 QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
1050 QSignalSpy spy(item, SIGNAL(clipChanged(bool)));
1053 QVERIFY(!item->clip());
1055 item->setClip(true);
1056 QVERIFY(item->clip());
1058 QList<QVariant> arguments = spy.first();
1059 QVERIFY(arguments.count() == 1);
1060 QVERIFY(arguments.at(0).toBool() == true);
1062 QCOMPARE(spy.count(),1);
1063 item->setClip(true);
1064 QCOMPARE(spy.count(),1);
1066 item->setClip(false);
1067 QVERIFY(!item->clip());
1068 QCOMPARE(spy.count(),2);
1069 item->setClip(false);
1070 QCOMPARE(spy.count(),2);
1075 void tst_QQuickItem::mapCoordinates()
1080 QQuickView *window = new QQuickView(0);
1081 window->setBaseSize(QSize(300, 300));
1082 window->setSource(testFileUrl("mapCoordinates.qml"));
1084 qApp->processEvents();
1086 QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
1088 QQuickItem *a = findItem<QQuickItem>(window->rootObject(), "itemA");
1090 QQuickItem *b = findItem<QQuickItem>(window->rootObject(), "itemB");
1095 QVERIFY(QMetaObject::invokeMethod(root, "mapAToB",
1096 Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
1097 QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapToItem(b, QPointF(x, y)));
1099 QVERIFY(QMetaObject::invokeMethod(root, "mapAFromB",
1100 Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
1101 QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapFromItem(b, QPointF(x, y)));
1103 QVERIFY(QMetaObject::invokeMethod(root, "mapAToNull",
1104 Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
1105 QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapToScene(QPointF(x, y)));
1107 QVERIFY(QMetaObject::invokeMethod(root, "mapAFromNull",
1108 Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
1109 QCOMPARE(result.value<QPointF>(), qobject_cast<QQuickItem*>(a)->mapFromScene(QPointF(x, y)));
1111 QString warning1 = testFileUrl("mapCoordinates.qml").toString() + ":48:5: QML Item: mapToItem() given argument \"1122\" which is neither null nor an Item";
1112 QString warning2 = testFileUrl("mapCoordinates.qml").toString() + ":48:5: QML Item: mapFromItem() given argument \"1122\" which is neither null nor an Item";
1114 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
1115 QVERIFY(QMetaObject::invokeMethod(root, "checkMapAToInvalid",
1116 Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
1117 QVERIFY(result.toBool());
1119 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
1120 QVERIFY(QMetaObject::invokeMethod(root, "checkMapAFromInvalid",
1121 Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y)));
1122 QVERIFY(result.toBool());
1127 void tst_QQuickItem::mapCoordinates_data()
1129 QTest::addColumn<int>("x");
1130 QTest::addColumn<int>("y");
1132 for (int i=-20; i<=20; i+=10)
1133 QTest::newRow(QTest::toString(i)) << i << i;
1136 void tst_QQuickItem::mapCoordinatesRect()
1141 QFETCH(int, height);
1143 QQuickView *window = new QQuickView(0);
1144 window->setBaseSize(QSize(300, 300));
1145 window->setSource(testFileUrl("mapCoordinatesRect.qml"));
1147 qApp->processEvents();
1149 QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
1151 QQuickItem *a = findItem<QQuickItem>(window->rootObject(), "itemA");
1153 QQuickItem *b = findItem<QQuickItem>(window->rootObject(), "itemB");
1158 QVERIFY(QMetaObject::invokeMethod(root, "mapAToB",
1159 Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y), Q_ARG(QVariant, width), Q_ARG(QVariant, height)));
1160 QCOMPARE(result.value<QRectF>(), qobject_cast<QQuickItem*>(a)->mapRectToItem(b, QRectF(x, y, width, height)));
1162 QVERIFY(QMetaObject::invokeMethod(root, "mapAFromB",
1163 Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y), Q_ARG(QVariant, width), Q_ARG(QVariant, height)));
1164 QCOMPARE(result.value<QRectF>(), qobject_cast<QQuickItem*>(a)->mapRectFromItem(b, QRectF(x, y, width, height)));
1166 QVERIFY(QMetaObject::invokeMethod(root, "mapAToNull",
1167 Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y), Q_ARG(QVariant, width), Q_ARG(QVariant, height)));
1168 QCOMPARE(result.value<QRectF>(), qobject_cast<QQuickItem*>(a)->mapRectToScene(QRectF(x, y, width, height)));
1170 QVERIFY(QMetaObject::invokeMethod(root, "mapAFromNull",
1171 Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y), Q_ARG(QVariant, width), Q_ARG(QVariant, height)));
1172 QCOMPARE(result.value<QRectF>(), qobject_cast<QQuickItem*>(a)->mapRectFromScene(QRectF(x, y, width, height)));
1174 QString warning1 = testFileUrl("mapCoordinatesRect.qml").toString() + ":48:5: QML Item: mapToItem() given argument \"1122\" which is neither null nor an Item";
1175 QString warning2 = testFileUrl("mapCoordinatesRect.qml").toString() + ":48:5: QML Item: mapFromItem() given argument \"1122\" which is neither null nor an Item";
1177 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
1178 QVERIFY(QMetaObject::invokeMethod(root, "checkMapAToInvalid",
1179 Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y), Q_ARG(QVariant, width), Q_ARG(QVariant, height)));
1180 QVERIFY(result.toBool());
1182 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
1183 QVERIFY(QMetaObject::invokeMethod(root, "checkMapAFromInvalid",
1184 Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, x), Q_ARG(QVariant, y), Q_ARG(QVariant, width), Q_ARG(QVariant, height)));
1185 QVERIFY(result.toBool());
1190 void tst_QQuickItem::mapCoordinatesRect_data()
1192 QTest::addColumn<int>("x");
1193 QTest::addColumn<int>("y");
1194 QTest::addColumn<int>("width");
1195 QTest::addColumn<int>("height");
1197 for (int i=-20; i<=20; i+=5)
1198 QTest::newRow(QTest::toString(i)) << i << i << i << i;
1201 void tst_QQuickItem::transforms_data()
1203 QTest::addColumn<QByteArray>("qml");
1204 QTest::addColumn<QTransform>("transform");
1205 QTest::newRow("translate") << QByteArray("Translate { x: 10; y: 20 }")
1206 << QTransform(1,0,0,0,1,0,10,20,1);
1207 QTest::newRow("rotation") << QByteArray("Rotation { angle: 90 }")
1208 << QTransform(0,1,0,-1,0,0,0,0,1);
1209 QTest::newRow("scale") << QByteArray("Scale { xScale: 1.5; yScale: -2 }")
1210 << QTransform(1.5,0,0,0,-2,0,0,0,1);
1211 QTest::newRow("sequence") << QByteArray("[ Translate { x: 10; y: 20 }, Scale { xScale: 1.5; yScale: -2 } ]")
1212 << QTransform(1,0,0,0,1,0,10,20,1) * QTransform(1.5,0,0,0,-2,0,0,0,1);
1215 void tst_QQuickItem::transforms()
1217 QFETCH(QByteArray, qml);
1218 QFETCH(QTransform, transform);
1219 QQmlComponent component(&engine);
1220 component.setData("import QtQuick 2.0\nItem { transform: "+qml+"}", QUrl::fromLocalFile(""));
1221 QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
1223 QCOMPARE(item->itemTransform(0,0), transform);
1226 void tst_QQuickItem::childrenProperty()
1228 QQmlComponent component(&engine, testFileUrl("childrenProperty.qml"));
1230 QObject *o = component.create();
1233 QCOMPARE(o->property("test1").toBool(), true);
1234 QCOMPARE(o->property("test2").toBool(), true);
1235 QCOMPARE(o->property("test3").toBool(), true);
1236 QCOMPARE(o->property("test4").toBool(), true);
1237 QCOMPARE(o->property("test5").toBool(), true);
1241 void tst_QQuickItem::resourcesProperty()
1243 QQmlComponent component(&engine, testFileUrl("resourcesProperty.qml"));
1245 QObject *o = component.create();
1248 QCOMPARE(o->property("test1").toBool(), true);
1249 QCOMPARE(o->property("test2").toBool(), true);
1250 QCOMPARE(o->property("test3").toBool(), true);
1251 QCOMPARE(o->property("test4").toBool(), true);
1252 QCOMPARE(o->property("test5").toBool(), true);
1256 void tst_QQuickItem::propertyChanges()
1258 QQuickView *window = new QQuickView(0);
1259 window->setBaseSize(QSize(300, 300));
1260 window->setSource(testFileUrl("propertychanges.qml"));
1262 window->requestActivateWindow();
1263 QVERIFY(QTest::qWaitForWindowActive(window));
1264 QVERIFY(QGuiApplication::focusWindow() == window);
1266 QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "item");
1267 QQuickItem *parentItem = findItem<QQuickItem>(window->rootObject(), "parentItem");
1270 QVERIFY(parentItem);
1272 QSignalSpy parentSpy(item, SIGNAL(parentChanged(QQuickItem *)));
1273 QSignalSpy widthSpy(item, SIGNAL(widthChanged()));
1274 QSignalSpy heightSpy(item, SIGNAL(heightChanged()));
1275 QSignalSpy baselineOffsetSpy(item, SIGNAL(baselineOffsetChanged(qreal)));
1276 QSignalSpy childrenRectSpy(parentItem, SIGNAL(childrenRectChanged(QRectF)));
1277 QSignalSpy focusSpy(item, SIGNAL(focusChanged(bool)));
1278 QSignalSpy wantsFocusSpy(parentItem, SIGNAL(activeFocusChanged(bool)));
1279 QSignalSpy childrenChangedSpy(parentItem, SIGNAL(childrenChanged()));
1280 QSignalSpy xSpy(item, SIGNAL(xChanged()));
1281 QSignalSpy ySpy(item, SIGNAL(yChanged()));
1283 item->setParentItem(parentItem);
1284 item->setWidth(100.0);
1285 item->setHeight(200.0);
1286 item->setFocus(true);
1287 item->setBaselineOffset(10.0);
1289 QCOMPARE(item->parentItem(), parentItem);
1290 QCOMPARE(parentSpy.count(),1);
1291 QList<QVariant> parentArguments = parentSpy.first();
1292 QVERIFY(parentArguments.count() == 1);
1293 QCOMPARE(item->parentItem(), qvariant_cast<QQuickItem *>(parentArguments.at(0)));
1294 QCOMPARE(childrenChangedSpy.count(),1);
1296 item->setParentItem(parentItem);
1297 QCOMPARE(childrenChangedSpy.count(),1);
1299 QCOMPARE(item->width(), 100.0);
1300 QCOMPARE(widthSpy.count(),1);
1302 QCOMPARE(item->height(), 200.0);
1303 QCOMPARE(heightSpy.count(),1);
1305 QCOMPARE(item->baselineOffset(), 10.0);
1306 QCOMPARE(baselineOffsetSpy.count(),1);
1307 QList<QVariant> baselineOffsetArguments = baselineOffsetSpy.first();
1308 QVERIFY(baselineOffsetArguments.count() == 1);
1309 QCOMPARE(item->baselineOffset(), baselineOffsetArguments.at(0).toReal());
1311 QCOMPARE(parentItem->childrenRect(), QRectF(0.0,0.0,100.0,200.0));
1312 QCOMPARE(childrenRectSpy.count(),1);
1313 QList<QVariant> childrenRectArguments = childrenRectSpy.at(0);
1314 QVERIFY(childrenRectArguments.count() == 1);
1315 QCOMPARE(parentItem->childrenRect(), childrenRectArguments.at(0).toRectF());
1317 QCOMPARE(item->hasActiveFocus(), true);
1318 QCOMPARE(focusSpy.count(),1);
1319 QList<QVariant> focusArguments = focusSpy.first();
1320 QVERIFY(focusArguments.count() == 1);
1321 QCOMPARE(focusArguments.at(0).toBool(), true);
1323 QCOMPARE(parentItem->hasActiveFocus(), false);
1324 QCOMPARE(parentItem->hasFocus(), false);
1325 QCOMPARE(wantsFocusSpy.count(),0);
1328 QCOMPARE(item->x(), 10.0);
1329 QCOMPARE(xSpy.count(), 1);
1332 QCOMPARE(item->y(), 10.0);
1333 QCOMPARE(ySpy.count(), 1);
1338 void tst_QQuickItem::childrenRect()
1340 QQuickView *window = new QQuickView(0);
1341 window->setSource(testFileUrl("childrenRect.qml"));
1342 window->setBaseSize(QSize(240,320));
1345 QQuickItem *o = window->rootObject();
1346 QQuickItem *item = o->findChild<QQuickItem*>("testItem");
1347 QCOMPARE(item->width(), qreal(0));
1348 QCOMPARE(item->height(), qreal(0));
1350 o->setProperty("childCount", 1);
1351 QCOMPARE(item->width(), qreal(10));
1352 QCOMPARE(item->height(), qreal(20));
1354 o->setProperty("childCount", 5);
1355 QCOMPARE(item->width(), qreal(50));
1356 QCOMPARE(item->height(), qreal(100));
1358 o->setProperty("childCount", 0);
1359 QCOMPARE(item->width(), qreal(0));
1360 QCOMPARE(item->height(), qreal(0));
1367 void tst_QQuickItem::childrenRectBug()
1369 QQuickView *window = new QQuickView(0);
1371 QString warning = testFileUrl("childrenRectBug.qml").toString() + ":7:5: QML Item: Binding loop detected for property \"height\"";
1372 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
1373 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning));
1375 window->setSource(testFileUrl("childrenRectBug.qml"));
1378 QQuickItem *o = window->rootObject();
1379 QQuickItem *item = o->findChild<QQuickItem*>("theItem");
1380 QCOMPARE(item->width(), qreal(200));
1381 QCOMPARE(item->height(), qreal(100));
1382 QCOMPARE(item->x(), qreal(100));
1388 void tst_QQuickItem::childrenRectBug2()
1390 QQuickView *window = new QQuickView(0);
1392 QString warning1 = testFileUrl("childrenRectBug2.qml").toString() + ":7:5: QML Item: Binding loop detected for property \"width\"";
1393 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
1394 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
1396 QString warning2 = testFileUrl("childrenRectBug2.qml").toString() + ":7:5: QML Item: Binding loop detected for property \"height\"";
1397 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
1398 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
1399 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
1400 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning2));
1402 window->setSource(testFileUrl("childrenRectBug2.qml"));
1405 QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(window->rootObject());
1407 QQuickItem *item = rect->findChild<QQuickItem*>("theItem");
1408 QCOMPARE(item->width(), qreal(100));
1409 QCOMPARE(item->height(), qreal(110));
1410 QCOMPARE(item->x(), qreal(130));
1412 QQuickItemPrivate *rectPrivate = QQuickItemPrivate::get(rect);
1413 rectPrivate->setState("row");
1414 QCOMPARE(item->width(), qreal(210));
1415 QCOMPARE(item->height(), qreal(50));
1416 QCOMPARE(item->x(), qreal(75));
1422 void tst_QQuickItem::childrenRectBug3()
1424 QQuickView *window = new QQuickView(0);
1425 window->setSource(testFileUrl("childrenRectBug3.qml"));
1428 //don't crash on delete
1433 void tst_QQuickItem::transformCrash()
1435 QQuickView *window = new QQuickView(0);
1436 window->setSource(testFileUrl("transformCrash.qml"));
1442 void tst_QQuickItem::implicitSize()
1444 QQuickView *window = new QQuickView(0);
1445 window->setSource(testFileUrl("implicitsize.qml"));
1448 QQuickItem *item = qobject_cast<QQuickItem*>(window->rootObject());
1450 QCOMPARE(item->width(), qreal(80));
1451 QCOMPARE(item->height(), qreal(60));
1453 QCOMPARE(item->implicitWidth(), qreal(200));
1454 QCOMPARE(item->implicitHeight(), qreal(100));
1456 QMetaObject::invokeMethod(item, "resetSize");
1458 QCOMPARE(item->width(), qreal(200));
1459 QCOMPARE(item->height(), qreal(100));
1461 QMetaObject::invokeMethod(item, "changeImplicit");
1463 QCOMPARE(item->implicitWidth(), qreal(150));
1464 QCOMPARE(item->implicitHeight(), qreal(80));
1465 QCOMPARE(item->width(), qreal(150));
1466 QCOMPARE(item->height(), qreal(80));
1468 QMetaObject::invokeMethod(item, "assignImplicitBinding");
1470 QCOMPARE(item->implicitWidth(), qreal(150));
1471 QCOMPARE(item->implicitHeight(), qreal(80));
1472 QCOMPARE(item->width(), qreal(150));
1473 QCOMPARE(item->height(), qreal(80));
1475 QMetaObject::invokeMethod(item, "increaseImplicit");
1477 QCOMPARE(item->implicitWidth(), qreal(200));
1478 QCOMPARE(item->implicitHeight(), qreal(100));
1479 QCOMPARE(item->width(), qreal(175));
1480 QCOMPARE(item->height(), qreal(90));
1482 QMetaObject::invokeMethod(item, "changeImplicit");
1484 QCOMPARE(item->implicitWidth(), qreal(150));
1485 QCOMPARE(item->implicitHeight(), qreal(80));
1486 QCOMPARE(item->width(), qreal(150));
1487 QCOMPARE(item->height(), qreal(80));
1489 QMetaObject::invokeMethod(item, "assignUndefinedBinding");
1491 QCOMPARE(item->implicitWidth(), qreal(150));
1492 QCOMPARE(item->implicitHeight(), qreal(80));
1493 QCOMPARE(item->width(), qreal(150));
1494 QCOMPARE(item->height(), qreal(80));
1496 QMetaObject::invokeMethod(item, "increaseImplicit");
1498 QCOMPARE(item->implicitWidth(), qreal(200));
1499 QCOMPARE(item->implicitHeight(), qreal(100));
1500 QCOMPARE(item->width(), qreal(175));
1501 QCOMPARE(item->height(), qreal(90));
1503 QMetaObject::invokeMethod(item, "changeImplicit");
1505 QCOMPARE(item->implicitWidth(), qreal(150));
1506 QCOMPARE(item->implicitHeight(), qreal(80));
1507 QCOMPARE(item->width(), qreal(150));
1508 QCOMPARE(item->height(), qreal(80));
1513 void tst_QQuickItem::qtbug_16871()
1515 QQmlComponent component(&engine, testFileUrl("qtbug_16871.qml"));
1516 QObject *o = component.create();
1522 void tst_QQuickItem::visibleChildren()
1524 QQuickView *window = new QQuickView(0);
1525 window->setSource(testFileUrl("visiblechildren.qml"));
1528 QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
1531 QCOMPARE(root->property("test1_1").toBool(), true);
1532 QCOMPARE(root->property("test1_2").toBool(), true);
1533 QCOMPARE(root->property("test1_3").toBool(), true);
1534 QCOMPARE(root->property("test1_4").toBool(), true);
1536 QMetaObject::invokeMethod(root, "hideFirstAndLastRowChild");
1537 QCOMPARE(root->property("test2_1").toBool(), true);
1538 QCOMPARE(root->property("test2_2").toBool(), true);
1539 QCOMPARE(root->property("test2_3").toBool(), true);
1540 QCOMPARE(root->property("test2_4").toBool(), true);
1542 QMetaObject::invokeMethod(root, "showLastRowChildsLastChild");
1543 QCOMPARE(root->property("test3_1").toBool(), true);
1544 QCOMPARE(root->property("test3_2").toBool(), true);
1545 QCOMPARE(root->property("test3_3").toBool(), true);
1546 QCOMPARE(root->property("test3_4").toBool(), true);
1548 QMetaObject::invokeMethod(root, "showLastRowChild");
1549 QCOMPARE(root->property("test4_1").toBool(), true);
1550 QCOMPARE(root->property("test4_2").toBool(), true);
1551 QCOMPARE(root->property("test4_3").toBool(), true);
1552 QCOMPARE(root->property("test4_4").toBool(), true);
1554 QString warning1 = testFileUrl("visiblechildren.qml").toString() + ":87: TypeError: Cannot read property 'visibleChildren' of null";
1555 QTest::ignoreMessage(QtWarningMsg, qPrintable(warning1));
1556 QMetaObject::invokeMethod(root, "tryWriteToReadonlyVisibleChildren");
1558 QMetaObject::invokeMethod(root, "reparentVisibleItem3");
1559 QCOMPARE(root->property("test6_1").toBool(), true);
1560 QCOMPARE(root->property("test6_2").toBool(), true);
1561 QCOMPARE(root->property("test6_3").toBool(), true);
1562 QCOMPARE(root->property("test6_4").toBool(), true);
1564 QMetaObject::invokeMethod(root, "reparentImlicitlyInvisibleItem4_1");
1565 QCOMPARE(root->property("test7_1").toBool(), true);
1566 QCOMPARE(root->property("test7_2").toBool(), true);
1567 QCOMPARE(root->property("test7_3").toBool(), true);
1568 QCOMPARE(root->property("test7_4").toBool(), true);
1570 // FINALLY TEST THAT EVERYTHING IS AS EXPECTED
1571 QCOMPARE(root->property("test8_1").toBool(), true);
1572 QCOMPARE(root->property("test8_2").toBool(), true);
1573 QCOMPARE(root->property("test8_3").toBool(), true);
1574 QCOMPARE(root->property("test8_4").toBool(), true);
1575 QCOMPARE(root->property("test8_5").toBool(), true);
1580 void tst_QQuickItem::parentLoop()
1582 QQuickView *window = new QQuickView(0);
1584 QTest::ignoreMessage(QtWarningMsg, "QQuickItem::setParentItem: Parent is already part of this items subtree.");
1585 window->setSource(testFileUrl("parentLoop.qml"));
1587 QQuickItem *root = qobject_cast<QQuickItem*>(window->rootObject());
1590 QQuickItem *item1 = root->findChild<QQuickItem*>("item1");
1592 QCOMPARE(item1->parentItem(), root);
1594 QQuickItem *item2 = root->findChild<QQuickItem*>("item2");
1596 QCOMPARE(item2->parentItem(), item1);
1601 void tst_QQuickItem::contains_data()
1603 QTest::addColumn<bool>("circleTest");
1604 QTest::addColumn<bool>("insideTarget");
1605 QTest::addColumn<QList<QPoint> >("points");
1607 QList<QPoint> points;
1609 points << QPoint(176, 176)
1616 << QPoint(250, 200);
1617 QTest::newRow("hollow square: testing points inside") << false << true << points;
1620 points << QPoint(162, 162)
1632 << QPoint(280, 200);
1633 QTest::newRow("hollow square: testing points outside") << false << false << points;
1636 points << QPoint(174, 174)
1643 << QPoint(235, 200);
1644 QTest::newRow("hollow circle: testing points inside") << true << true << points;
1647 points << QPoint(160, 160)
1659 << QPoint(200, 255);
1660 QTest::newRow("hollow circle: testing points outside") << true << false << points;
1663 void tst_QQuickItem::contains()
1665 QFETCH(bool, circleTest);
1666 QFETCH(bool, insideTarget);
1667 QFETCH(QList<QPoint>, points);
1669 QQuickView *window = new QQuickView(0);
1670 window->rootContext()->setContextProperty("circleShapeTest", circleTest);
1671 window->setBaseSize(QSize(400, 400));
1672 window->setSource(testFileUrl("hollowTestItem.qml"));
1674 window->requestActivateWindow();
1675 QVERIFY(QTest::qWaitForWindowActive(window));
1676 QVERIFY(QGuiApplication::focusWindow() == window);
1678 QQuickItem *root = qobject_cast<QQuickItem *>(window->rootObject());
1681 HollowTestItem *hollowItem = root->findChild<HollowTestItem *>("hollowItem");
1682 QVERIFY(hollowItem);
1684 foreach (const QPoint &point, points) {
1685 // check mouse hover
1686 QTest::mouseMove(window, point);
1688 QCOMPARE(hollowItem->isHovered(), insideTarget);
1690 // check mouse press
1691 QTest::mousePress(window, Qt::LeftButton, 0, point);
1693 QCOMPARE(hollowItem->isPressed(), insideTarget);
1695 // check mouse release
1696 QTest::mouseRelease(window, Qt::LeftButton, 0, point);
1698 QCOMPARE(hollowItem->isPressed(), false);
1704 void tst_QQuickItem::childAt()
1711 child1.setWidth(100);
1712 child1.setHeight(100);
1713 child1.setParentItem(&parent);
1718 child2.setWidth(100);
1719 child2.setHeight(100);
1720 child2.setParentItem(&parent);
1725 child3.setWidth(50);
1726 child3.setHeight(50);
1727 child3.setParentItem(&parent);
1729 QCOMPARE(parent.childAt(0, 0), &child1);
1730 QCOMPARE(parent.childAt(0, 100), &child1);
1731 QCOMPARE(parent.childAt(25, 25), &child1);
1732 QCOMPARE(parent.childAt(25, 75), &child1);
1733 QCOMPARE(parent.childAt(75, 25), &child1);
1734 QCOMPARE(parent.childAt(75, 75), &child2);
1735 QCOMPARE(parent.childAt(150, 150), &child2);
1736 QCOMPARE(parent.childAt(25, 200), &child3);
1737 QCOMPARE(parent.childAt(0, 150), static_cast<QQuickItem *>(0));
1738 QCOMPARE(parent.childAt(300, 300), static_cast<QQuickItem *>(0));
1742 QTEST_MAIN(tst_QQuickItem)
1744 #include "tst_qquickitem.moc"