summaryrefslogtreecommitdiffstats
path: root/tests/auto/qgraphicsitem
diff options
context:
space:
mode:
authorAlexis Menard <alexis.menard@nokia.com>2009-04-17 14:06:06 (GMT)
committerAlexis Menard <alexis.menard@nokia.com>2009-04-17 14:06:06 (GMT)
commitf15b8a83e2e51955776a3f07cb85ebfc342dd8ef (patch)
treec5dc684986051654898db11ce73e03b9fec8db99 /tests/auto/qgraphicsitem
downloadQt-f15b8a83e2e51955776a3f07cb85ebfc342dd8ef.zip
Qt-f15b8a83e2e51955776a3f07cb85ebfc342dd8ef.tar.gz
Qt-f15b8a83e2e51955776a3f07cb85ebfc342dd8ef.tar.bz2
Initial import of statemachine branch from the old kinetic repository
Diffstat (limited to 'tests/auto/qgraphicsitem')
-rw-r--r--tests/auto/qgraphicsitem/.gitignore1
-rw-r--r--tests/auto/qgraphicsitem/nestedClipping_reference.pngbin0 -> 638 bytes
-rw-r--r--tests/auto/qgraphicsitem/qgraphicsitem.pro7
-rw-r--r--tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp5884
4 files changed, 5892 insertions, 0 deletions
diff --git a/tests/auto/qgraphicsitem/.gitignore b/tests/auto/qgraphicsitem/.gitignore
new file mode 100644
index 0000000..b766388
--- /dev/null
+++ b/tests/auto/qgraphicsitem/.gitignore
@@ -0,0 +1 @@
+tst_qgraphicsitem
diff --git a/tests/auto/qgraphicsitem/nestedClipping_reference.png b/tests/auto/qgraphicsitem/nestedClipping_reference.png
new file mode 100644
index 0000000..3bd4fe7
--- /dev/null
+++ b/tests/auto/qgraphicsitem/nestedClipping_reference.png
Binary files differ
diff --git a/tests/auto/qgraphicsitem/qgraphicsitem.pro b/tests/auto/qgraphicsitem/qgraphicsitem.pro
new file mode 100644
index 0000000..20acf35
--- /dev/null
+++ b/tests/auto/qgraphicsitem/qgraphicsitem.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+SOURCES += tst_qgraphicsitem.cpp
+DEFINES += QT_NO_CAST_TO_ASCII
+
+win32:!wince*: LIBS += -lUser32
+
+
diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
new file mode 100644
index 0000000..cce76ff
--- /dev/null
+++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
@@ -0,0 +1,5884 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#if QT_VERSION < 0x040200
+QTEST_NOOP_MAIN
+#else
+
+#include <private/qtextcontrol_p.h>
+#include <private/qgraphicsitem_p.h>
+#include <QAbstractTextDocumentLayout>
+#include <QBitmap>
+#include <QCursor>
+#include <QDial>
+#include <QGraphicsItem>
+#include <QGraphicsScene>
+#include <QGraphicsSceneEvent>
+#include <QGraphicsView>
+#include <QGraphicsWidget>
+#include <QPainter>
+#include <QScrollBar>
+#include <QVBoxLayout>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+Q_DECLARE_METATYPE(QList<int>)
+Q_DECLARE_METATYPE(QList<QRectF>)
+Q_DECLARE_METATYPE(QPainterPath)
+Q_DECLARE_METATYPE(QPointF)
+Q_DECLARE_METATYPE(QRectF)
+
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+#include <windows.h>
+#define Q_CHECK_PAINTEVENTS \
+ if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \
+ QSKIP("The Graphics View doesn't get the paint events", SkipSingle);
+#else
+#define Q_CHECK_PAINTEVENTS
+#endif
+
+class EventTester : public QGraphicsItem
+{
+public:
+ EventTester()
+ : repaints(0)
+ { br = QRectF(-10, -10, 20, 20); }
+
+ void setGeometry(const QRectF &rect)
+ {
+ prepareGeometryChange();
+ br = rect;
+ update();
+ }
+
+ QRectF boundingRect() const
+ { return br; }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ {
+ hints = painter->renderHints();
+ painter->drawRect(boundingRect());
+ ++repaints;
+ }
+
+ bool sceneEvent(QEvent *event)
+ {
+ events << event->type();
+ return QGraphicsItem::sceneEvent(event);
+ }
+
+ QList<QEvent::Type> events;
+ QPainter::RenderHints hints;
+ int repaints;
+ QRectF br;
+};
+
+class tst_QGraphicsItem : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void init();
+
+private slots:
+ void construction();
+ void constructionWithParent();
+ void destruction();
+ void scene();
+ void parentItem();
+ void setParentItem();
+ void children();
+ void flags();
+ void toolTip();
+ void visible();
+ void explicitlyVisible();
+ void enabled();
+ void explicitlyEnabled();
+ void selected();
+ void selected2();
+ void selected_group();
+ void selected_textItem();
+ void selected_multi();
+ void acceptedMouseButtons();
+ void acceptsHoverEvents();
+ void childAcceptsHoverEvents();
+ void hasFocus();
+ void pos();
+ void scenePos();
+ void matrix();
+ void sceneMatrix();
+ void setMatrix();
+ void zValue();
+ void shape();
+ void contains();
+ void collidesWith_item();
+ void collidesWith_path_data();
+ void collidesWith_path();
+ void collidesWithItemWithClip();
+ void isObscuredBy();
+ void isObscured();
+ void mapFromToParent();
+ void mapFromToScene();
+ void mapFromToItem();
+ void isAncestorOf();
+ void commonAncestorItem();
+ void data();
+ void type();
+ void graphicsitem_cast();
+ void hoverEventsGenerateRepaints();
+ void boundingRects_data();
+ void boundingRects();
+ void boundingRects2();
+ void sceneBoundingRect();
+ void childrenBoundingRect();
+ void group();
+ void setGroup();
+ void nestedGroups();
+ void warpChildrenIntoGroup();
+ void removeFromGroup();
+ void handlesChildEvents();
+ void handlesChildEvents2();
+ void handlesChildEvents3();
+ void ensureVisible();
+ void cursor();
+ //void textControlGetterSetter();
+ void defaultItemTest_QGraphicsLineItem();
+ void defaultItemTest_QGraphicsPixmapItem();
+ void defaultItemTest_QGraphicsTextItem();
+ void defaultItemTest_QGraphicsEllipseItem();
+ void itemChange();
+ void sceneEventFilter();
+ void prepareGeometryChange();
+ void paint();
+ void deleteItemInEventHandlers();
+ void itemClipsToShape();
+ void itemClipsChildrenToShape();
+ void itemClipsChildrenToShape2();
+ void itemClipsTextChildToShape();
+ void itemClippingDiscovery();
+ void ancestorFlags();
+ void untransformable();
+ void contextMenuEventPropagation();
+ void itemIsMovable();
+ void boundingRegion_data();
+ void boundingRegion();
+ void itemTransform_parentChild();
+ void itemTransform_siblings();
+ void itemTransform_unrelated();
+ void opacity_data();
+ void opacity();
+ void itemStacksBehindParent();
+ void nestedClipping();
+ void nestedClippingTransforms();
+ void sceneTransformCache();
+ void tabChangesFocus();
+ void tabChangesFocus_data();
+ void cacheMode();
+
+ // task specific tests below me
+ void task141694_textItemEnsureVisible();
+ void task128696_textItemEnsureMovable();
+ void task177918_lineItemUndetected();
+ void task240400_clickOnTextItem_data();
+ void task240400_clickOnTextItem();
+ void task243707_addChildBeforeParent();
+};
+
+void tst_QGraphicsItem::init()
+{
+#ifdef Q_OS_WINCE //disable magic for WindowsCE
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+}
+
+void tst_QGraphicsItem::construction()
+{
+ for (int i = 0; i < 7; ++i) {
+ QGraphicsItem *item;
+ switch (i) {
+ case 0:
+ item = new QGraphicsEllipseItem;
+ QCOMPARE(int(item->type()), int(QGraphicsEllipseItem::Type));
+ QCOMPARE(qgraphicsitem_cast<QGraphicsEllipseItem *>(item), (QGraphicsEllipseItem *)item);
+ QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
+ break;
+ case 1:
+ item = new QGraphicsLineItem;
+ QCOMPARE(int(item->type()), int(QGraphicsLineItem::Type));
+ QCOMPARE(qgraphicsitem_cast<QGraphicsLineItem *>(item), (QGraphicsLineItem *)item);
+ QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
+ break;
+ case 2:
+ item = new QGraphicsPathItem;
+ QCOMPARE(int(item->type()), int(QGraphicsPathItem::Type));
+ QCOMPARE(qgraphicsitem_cast<QGraphicsPathItem *>(item), (QGraphicsPathItem *)item);
+ QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
+ break;
+ case 3:
+ item = new QGraphicsPixmapItem;
+ QCOMPARE(int(item->type()), int(QGraphicsPixmapItem::Type));
+ QCOMPARE(qgraphicsitem_cast<QGraphicsPixmapItem *>(item), (QGraphicsPixmapItem *)item);
+ QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
+ break;
+ case 4:
+ item = new QGraphicsPolygonItem;
+ QCOMPARE(int(item->type()), int(QGraphicsPolygonItem::Type));
+ QCOMPARE(qgraphicsitem_cast<QGraphicsPolygonItem *>(item), (QGraphicsPolygonItem *)item);
+ QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
+ break;
+ case 5:
+ item = new QGraphicsRectItem;
+ QCOMPARE(int(item->type()), int(QGraphicsRectItem::Type));
+ QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)item);
+ QCOMPARE(qgraphicsitem_cast<QGraphicsLineItem *>(item), (QGraphicsLineItem *)0);
+ break;
+ case 6:
+ default:
+ item = new QGraphicsTextItem;
+ QCOMPARE(int(item->type()), int(QGraphicsTextItem::Type));
+ QCOMPARE(qgraphicsitem_cast<QGraphicsTextItem *>(item), (QGraphicsTextItem *)item);
+ QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
+ break;
+ }
+
+ QCOMPARE(item->scene(), (QGraphicsScene *)0);
+ QCOMPARE(item->parentItem(), (QGraphicsItem *)0);
+ QVERIFY(item->children().isEmpty());
+ QCOMPARE(item->flags(), 0);
+ QVERIFY(item->isVisible());
+ QVERIFY(item->isEnabled());
+ QVERIFY(!item->isSelected());
+ QCOMPARE(item->acceptedMouseButtons(), Qt::MouseButtons(0x1f));
+ if (item->type() == QGraphicsTextItem::Type)
+ QVERIFY(item->acceptsHoverEvents());
+ else
+ QVERIFY(!item->acceptsHoverEvents());
+ QVERIFY(!item->hasFocus());
+ QCOMPARE(item->pos(), QPointF());
+ QCOMPARE(item->matrix(), QMatrix());
+ QCOMPARE(item->sceneMatrix(), QMatrix());
+ QCOMPARE(item->zValue(), qreal(0));
+ QCOMPARE(item->sceneBoundingRect(), QRectF());
+ QCOMPARE(item->shape(), QPainterPath());
+ QVERIFY(!item->contains(QPointF(0, 0)));
+ QVERIFY(!item->collidesWithItem(0));
+ QVERIFY(item->collidesWithItem(item));
+ QVERIFY(!item->collidesWithPath(QPainterPath()));
+ QVERIFY(!item->isAncestorOf(0));
+ QVERIFY(!item->isAncestorOf(item));
+ QCOMPARE(item->data(0), QVariant());
+ delete item;
+ }
+}
+
+class BoundingRectItem : public QGraphicsRectItem
+{
+public:
+ BoundingRectItem(QGraphicsItem *parent = 0)
+ : QGraphicsRectItem(0, 0, parent ? 200 : 100, parent ? 200 : 100,
+ parent)
+ {}
+
+ QRectF boundingRect() const
+ {
+ QRectF tmp = QGraphicsRectItem::boundingRect();
+ foreach (QGraphicsItem *child, children())
+ tmp |= child->boundingRect(); // <- might be pure virtual
+ return tmp;
+ }
+};
+
+void tst_QGraphicsItem::constructionWithParent()
+{
+ // This test causes a crash if item1 calls item2's pure virtuals before the
+ // object has been constructed.
+ QGraphicsItem *item0 = new BoundingRectItem;
+ QGraphicsItem *item1 = new BoundingRectItem;
+ QGraphicsScene scene;
+ scene.addItem(item0);
+ scene.addItem(item1);
+ QGraphicsItem *item2 = new BoundingRectItem(item1);
+ QCOMPARE(item1->children(), QList<QGraphicsItem *>() << item2);
+ QCOMPARE(item1->boundingRect(), QRectF(0, 0, 200, 200));
+
+ item2->setParentItem(item0);
+ QCOMPARE(item0->children(), QList<QGraphicsItem *>() << item2);
+ QCOMPARE(item0->boundingRect(), QRectF(0, 0, 200, 200));
+}
+
+static int itemDeleted = 0;
+class Item : public QGraphicsRectItem
+{
+public:
+ ~Item()
+ { ++itemDeleted; }
+};
+
+void tst_QGraphicsItem::destruction()
+{
+ QCOMPARE(itemDeleted, 0);
+ {
+ QGraphicsItem *parent = new QGraphicsRectItem;
+ Item *child = new Item;
+ child->setParentItem(parent);
+ QCOMPARE(child->parentItem(), parent);
+ delete parent;
+ QCOMPARE(itemDeleted, 1);
+ }
+ {
+ QGraphicsItem *parent = new QGraphicsRectItem;
+ Item *child = new Item;
+ child->setParentItem(parent);
+ QCOMPARE(parent->children().size(), 1);
+ delete child;
+ QCOMPARE(parent->children().size(), 0);
+ delete parent;
+ QCOMPARE(itemDeleted, 2);
+ }
+ {
+ QGraphicsScene scene;
+ QGraphicsItem *parent = new QGraphicsRectItem;
+ Item *child = new Item;
+ QCOMPARE(child->parentItem(), (QGraphicsItem *)0);
+ child->setParentItem(parent);
+ QCOMPARE(child->parentItem(), parent);
+ scene.addItem(parent);
+ QCOMPARE(child->parentItem(), parent);
+ delete parent;
+ QCOMPARE(itemDeleted, 3);
+ }
+ {
+ QGraphicsScene scene;
+ QGraphicsItem *parent = new QGraphicsRectItem;
+ Item *child = new Item;
+ child->setParentItem(parent);
+ scene.addItem(parent);
+ QCOMPARE(child->scene(), &scene);
+ QCOMPARE(parent->children().size(), 1);
+ delete child;
+ QCOMPARE(parent->children().size(), 0);
+ delete parent;
+ QCOMPARE(itemDeleted, 4);
+ }
+ {
+ QGraphicsScene scene;
+ QGraphicsItem *parent = new QGraphicsRectItem;
+ Item *child = new Item;
+ child->setParentItem(parent);
+ scene.addItem(parent);
+ QCOMPARE(child->scene(), &scene);
+ scene.removeItem(parent);
+ QCOMPARE(child->scene(), (QGraphicsScene *)0);
+ delete parent;
+ QCOMPARE(itemDeleted, 5);
+ }
+ {
+ QGraphicsScene scene;
+ QGraphicsItem *parent = new QGraphicsRectItem;
+ Item *child = new Item;
+ child->setParentItem(parent);
+ QCOMPARE(child->scene(), (QGraphicsScene *)0);
+ QCOMPARE(parent->scene(), (QGraphicsScene *)0);
+ scene.addItem(parent);
+ QCOMPARE(child->scene(), &scene);
+ scene.removeItem(child);
+ QCOMPARE(child->scene(), (QGraphicsScene *)0);
+ QCOMPARE(parent->scene(), &scene);
+ QCOMPARE(child->parentItem(), (QGraphicsItem *)0);
+ QVERIFY(parent->children().isEmpty());
+ delete parent;
+ QCOMPARE(itemDeleted, 5);
+ delete child;
+ QCOMPARE(itemDeleted, 6);
+ }
+ {
+ QGraphicsScene scene;
+ QGraphicsItem *parent = new QGraphicsRectItem;
+ Item *child = new Item;
+ child->setParentItem(parent);
+ scene.addItem(parent);
+ scene.removeItem(child);
+ scene.removeItem(parent);
+ delete child;
+ delete parent;
+ QCOMPARE(itemDeleted, 7);
+ }
+ {
+ QGraphicsScene scene;
+ QGraphicsItem *parent = new QGraphicsRectItem;
+ Item *child = new Item;
+ child->setParentItem(parent);
+ scene.addItem(parent);
+ QGraphicsScene scene2;
+ scene2.addItem(parent);
+ delete parent;
+ QCOMPARE(itemDeleted, 8);
+ }
+ {
+ QGraphicsScene scene;
+ QGraphicsItem *parent = new QGraphicsRectItem;
+ Item *child = new Item;
+ child->setParentItem(parent);
+ scene.addItem(parent);
+ QCOMPARE(child->scene(), &scene);
+ QGraphicsScene scene2;
+ scene2.addItem(parent);
+ QCOMPARE(child->scene(), &scene2);
+ scene.addItem(parent);
+ QCOMPARE(child->scene(), &scene);
+ scene2.addItem(parent);
+ QCOMPARE(child->scene(), &scene2);
+ delete parent;
+ QCOMPARE(itemDeleted, 9);
+ }
+ {
+ QGraphicsScene scene;
+ QGraphicsItem *parent = new QGraphicsRectItem;
+ Item *child = new Item;
+ child->setParentItem(parent);
+ scene.addItem(parent);
+ QCOMPARE(child->scene(), &scene);
+ QGraphicsScene scene2;
+ scene2.addItem(child);
+ QCOMPARE(child->scene(), &scene2);
+ delete parent;
+ QCOMPARE(itemDeleted, 9);
+ delete child;
+ QCOMPARE(itemDeleted, 10);
+ }
+ {
+ QGraphicsScene scene;
+ QGraphicsItem *root = new QGraphicsRectItem;
+ QGraphicsItem *parent = root;
+ QGraphicsItem *middleItem = 0;
+ for (int i = 0; i < 99; ++i) {
+ Item *child = new Item;
+ child->setParentItem(parent);
+ parent = child;
+ if (i == 50)
+ middleItem = parent;
+ }
+ scene.addItem(root);
+
+ QCOMPARE(scene.items().size(), 100);
+
+ QGraphicsScene scene2;
+ scene2.addItem(middleItem);
+
+ delete middleItem;
+ QCOMPARE(itemDeleted, 59);
+ }
+ QCOMPARE(itemDeleted, 109);
+}
+
+void tst_QGraphicsItem::scene()
+{
+ QGraphicsRectItem *item = new QGraphicsRectItem;
+ QCOMPARE(item->scene(), (QGraphicsScene *)0);
+
+ QGraphicsScene scene;
+ scene.addItem(item);
+ QCOMPARE(item->scene(), (QGraphicsScene *)&scene);
+
+ QGraphicsScene scene2;
+ scene2.addItem(item);
+ QCOMPARE(item->scene(), (QGraphicsScene *)&scene2);
+
+ scene2.removeItem(item);
+ QCOMPARE(item->scene(), (QGraphicsScene *)0);
+
+ delete item;
+}
+
+void tst_QGraphicsItem::parentItem()
+{
+ QGraphicsRectItem item;
+ QCOMPARE(item.parentItem(), (QGraphicsItem *)0);
+
+ QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(), &item);
+ QCOMPARE(item2->parentItem(), (QGraphicsItem *)&item);
+ item2->setParentItem(&item);
+ QCOMPARE(item2->parentItem(), (QGraphicsItem *)&item);
+ item2->setParentItem(0);
+ QCOMPARE(item2->parentItem(), (QGraphicsItem *)0);
+
+ delete item2;
+}
+
+void tst_QGraphicsItem::setParentItem()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *item = scene.addRect(QRectF(0, 0, 10, 10));
+ QCOMPARE(item->scene(), &scene);
+
+ QGraphicsRectItem *child = new QGraphicsRectItem;
+ QCOMPARE(child->scene(), (QGraphicsScene *)0);
+
+ // This implicitly adds the item to the parent's scene
+ child->setParentItem(item);
+ QCOMPARE(child->scene(), &scene);
+
+ // This just makes it a toplevel
+ child->setParentItem(0);
+ QCOMPARE(child->scene(), &scene);
+
+ // Add the child back to the parent, then remove the parent from the scene
+ child->setParentItem(item);
+ scene.removeItem(item);
+ QCOMPARE(child->scene(), (QGraphicsScene *)0);
+}
+
+void tst_QGraphicsItem::children()
+{
+ QGraphicsRectItem item;
+ QVERIFY(item.children().isEmpty());
+
+ QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(), &item);
+ QCOMPARE(item.children().size(), 1);
+ QCOMPARE(item.children().first(), (QGraphicsItem *)item2);
+ QVERIFY(item2->children().isEmpty());
+
+ delete item2;
+ QVERIFY(item.children().isEmpty());
+}
+
+void tst_QGraphicsItem::flags()
+{
+ QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(-10, -10, 20, 20));
+ QCOMPARE(item->flags(), 0);
+
+ QGraphicsScene scene;
+ scene.addItem(item);
+
+ {
+ // Focus
+ item->setFlag(QGraphicsItem::ItemIsFocusable, false);
+ QVERIFY(!item->hasFocus());
+ item->setFocus();
+ QVERIFY(!item->hasFocus());
+
+ item->setFlag(QGraphicsItem::ItemIsFocusable, true);
+ QVERIFY(!item->hasFocus());
+ item->setFocus();
+ QVERIFY(item->hasFocus());
+ QVERIFY(scene.hasFocus());
+
+ item->setFlag(QGraphicsItem::ItemIsFocusable, false);
+ QVERIFY(!item->hasFocus());
+ QVERIFY(scene.hasFocus());
+ }
+ {
+ // Selectable
+ item->setFlag(QGraphicsItem::ItemIsSelectable, false);
+ QVERIFY(!item->isSelected());
+ item->setSelected(true);
+ QVERIFY(!item->isSelected());
+
+ item->setFlag(QGraphicsItem::ItemIsSelectable, true);
+ QVERIFY(!item->isSelected());
+ item->setSelected(true);
+ QVERIFY(item->isSelected());
+ item->setFlag(QGraphicsItem::ItemIsSelectable, false);
+ QVERIFY(!item->isSelected());
+ }
+ {
+ // Movable
+ item->setFlag(QGraphicsItem::ItemIsMovable, false);
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setScenePos(QPointF(0, 0));
+ event.setButton(Qt::LeftButton);
+ event.setButtons(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &event);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0); // mouse grabber is reset
+
+ QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove);
+ event2.setScenePos(QPointF(10, 10));
+ event2.setButton(Qt::LeftButton);
+ event2.setButtons(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &event2);
+ QCOMPARE(item->pos(), QPointF());
+
+ QGraphicsSceneMouseEvent event3(QEvent::GraphicsSceneMouseRelease);
+ event3.setScenePos(QPointF(10, 10));
+ event3.setButtons(0);
+ QApplication::sendEvent(&scene, &event3);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+
+ item->setFlag(QGraphicsItem::ItemIsMovable, true);
+ QGraphicsSceneMouseEvent event4(QEvent::GraphicsSceneMousePress);
+ event4.setScenePos(QPointF(0, 0));
+ event4.setButton(Qt::LeftButton);
+ event4.setButtons(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &event4);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
+ QGraphicsSceneMouseEvent event5(QEvent::GraphicsSceneMouseMove);
+ event5.setScenePos(QPointF(10, 10));
+ event5.setButton(Qt::LeftButton);
+ event5.setButtons(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &event5);
+ QCOMPARE(item->pos(), QPointF(10, 10));
+ }
+}
+
+void tst_QGraphicsItem::toolTip()
+{
+ QString toolTip = "Qt rocks!";
+
+ QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
+ item->setPen(QPen(Qt::red, 1));
+ item->setBrush(QBrush(Qt::blue));
+ QVERIFY(item->toolTip().isEmpty());
+ item->setToolTip(toolTip);
+ QCOMPARE(item->toolTip(), toolTip);
+
+ QGraphicsScene scene;
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(200, 200);
+ view.show();
+ QTest::qWait(250);
+ {
+ QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().topLeft(),
+ view.viewport()->mapToGlobal(view.viewport()->rect().topLeft()));
+ QApplication::sendEvent(view.viewport(), &helpEvent);
+ QTest::qWait(250);
+
+ bool foundView = false;
+ bool foundTipLabel = false;
+ foreach (QWidget *widget, QApplication::topLevelWidgets()) {
+ if (widget == &view)
+ foundView = true;
+ if (widget->inherits("QTipLabel"))
+ foundTipLabel = true;
+ }
+ QVERIFY(foundView);
+ QVERIFY(!foundTipLabel);
+ }
+
+ {
+ QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().center(),
+ view.viewport()->mapToGlobal(view.viewport()->rect().center()));
+ QApplication::sendEvent(view.viewport(), &helpEvent);
+ QTest::qWait(250);
+
+ bool foundView = false;
+ bool foundTipLabel = false;
+ foreach (QWidget *widget, QApplication::topLevelWidgets()) {
+ if (widget == &view)
+ foundView = true;
+ if (widget->inherits("QTipLabel"))
+ foundTipLabel = true;
+ }
+ QVERIFY(foundView);
+ QVERIFY(foundTipLabel);
+ }
+
+ {
+ QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().topLeft(),
+ view.viewport()->mapToGlobal(view.viewport()->rect().topLeft()));
+ QApplication::sendEvent(view.viewport(), &helpEvent);
+ QTest::qWait(1000);
+
+ bool foundView = false;
+ bool foundTipLabel = false;
+ foreach (QWidget *widget, QApplication::topLevelWidgets()) {
+ if (widget == &view)
+ foundView = true;
+ if (widget->inherits("QTipLabel") && widget->isVisible())
+ foundTipLabel = true;
+ }
+ QVERIFY(foundView);
+ QVERIFY(!foundTipLabel);
+ }
+}
+
+void tst_QGraphicsItem::visible()
+{
+ QGraphicsItem *item = new QGraphicsRectItem(QRectF(-10, -10, 20, 20));
+ item->setFlag(QGraphicsItem::ItemIsMovable);
+ QVERIFY(item->isVisible());
+ item->setVisible(false);
+ QVERIFY(!item->isVisible());
+ item->setVisible(true);
+ QVERIFY(item->isVisible());
+
+ QGraphicsScene scene;
+ scene.addItem(item);
+ QVERIFY(item->isVisible());
+ QCOMPARE(scene.itemAt(0, 0), item);
+ item->setVisible(false);
+ QCOMPARE(scene.itemAt(0, 0), (QGraphicsItem *)0);
+ item->setVisible(true);
+ QCOMPARE(scene.itemAt(0, 0), item);
+
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(0, 0));
+ QApplication::sendEvent(&scene, &event);
+ QCOMPARE(scene.mouseGrabberItem(), item);
+ item->setVisible(false);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ item->setVisible(true);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+
+ item->setFlag(QGraphicsItem::ItemIsFocusable);
+ item->setFocus();
+ QVERIFY(item->hasFocus());
+ item->setVisible(false);
+ QVERIFY(!item->hasFocus());
+ item->setVisible(true);
+ QVERIFY(!item->hasFocus());
+}
+
+void tst_QGraphicsItem::explicitlyVisible()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *parent = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsItem *child = scene.addRect(QRectF(25, 25, 50, 50));
+ child->setParentItem(parent);
+
+ QVERIFY(parent->isVisible());
+ QVERIFY(child->isVisible());
+
+ parent->hide();
+
+ QVERIFY(!parent->isVisible());
+ QVERIFY(!child->isVisible());
+
+ parent->show();
+ child->hide();
+
+ QVERIFY(parent->isVisible());
+ QVERIFY(!child->isVisible());
+
+ parent->hide();
+
+ QVERIFY(!parent->isVisible());
+ QVERIFY(!child->isVisible());
+
+ parent->show();
+
+ QVERIFY(parent->isVisible());
+ QVERIFY(!child->isVisible()); // <- explicitly hidden
+
+ child->show();
+
+ QVERIFY(child->isVisible());
+
+ parent->hide();
+
+ QVERIFY(!parent->isVisible());
+ QVERIFY(!child->isVisible()); // <- explicit show doesn't work
+
+ parent->show();
+
+ QVERIFY(parent->isVisible());
+ QVERIFY(child->isVisible()); // <- no longer explicitly hidden
+
+ // ------------------- Reparenting ------------------------------
+
+ QGraphicsItem *parent2 = scene.addRect(-50, -50, 200, 200);
+ QVERIFY(parent2->isVisible());
+
+ // Reparent implicitly hidden item to a visible parent.
+ parent->hide();
+ QVERIFY(!parent->isVisible());
+ QVERIFY(!child->isVisible());
+ child->setParentItem(parent2);
+ QVERIFY(parent2->isVisible());
+ QVERIFY(child->isVisible());
+
+ // Reparent implicitly hidden item to a hidden parent.
+ child->setParentItem(parent);
+ parent2->hide();
+ child->setParentItem(parent2);
+ QVERIFY(!parent2->isVisible());
+ QVERIFY(!child->isVisible());
+
+ // Reparent explicitly hidden item to a visible parent.
+ child->hide();
+ parent->show();
+ child->setParentItem(parent);
+ QVERIFY(parent->isVisible());
+ QVERIFY(!child->isVisible());
+
+ // Reparent explicitly hidden item to a hidden parent.
+ child->setParentItem(parent2);
+ QVERIFY(!parent2->isVisible());
+ QVERIFY(!child->isVisible());
+
+ // Reparent explicitly hidden item to a visible parent.
+ parent->show();
+ child->setParentItem(parent);
+ QVERIFY(parent->isVisible());
+ QVERIFY(!child->isVisible());
+
+ // Reparent visible item to a hidden parent.
+ child->show();
+ parent2->hide();
+ child->setParentItem(parent2);
+ QVERIFY(!parent2->isVisible());
+ QVERIFY(!child->isVisible());
+ parent2->show();
+ QVERIFY(parent2->isVisible());
+ QVERIFY(child->isVisible());
+
+ // Reparent implicitly hidden child to root.
+ parent2->hide();
+ QVERIFY(!child->isVisible());
+ child->setParentItem(0);
+ QVERIFY(child->isVisible());
+
+ // Reparent an explicitly hidden child to root.
+ child->hide();
+ child->setParentItem(parent2);
+ parent2->show();
+ QVERIFY(!child->isVisible());
+ child->setParentItem(0);
+ QVERIFY(!child->isVisible());
+}
+
+void tst_QGraphicsItem::enabled()
+{
+ QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(-10, -10, 20, 20));
+ item->setFlag(QGraphicsItem::ItemIsMovable);
+ QVERIFY(item->isEnabled());
+ item->setEnabled(false);
+ QVERIFY(!item->isEnabled());
+ item->setEnabled(true);
+ QVERIFY(item->isEnabled());
+ item->setEnabled(false);
+ item->setFlag(QGraphicsItem::ItemIsFocusable);
+ QGraphicsScene scene;
+ scene.addItem(item);
+ item->setFocus();
+ QVERIFY(!item->hasFocus());
+ item->setEnabled(true);
+ item->setFocus();
+ QVERIFY(item->hasFocus());
+ item->setEnabled(false);
+ QVERIFY(!item->hasFocus());
+
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(0, 0));
+ QApplication::sendEvent(&scene, &event);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ item->setEnabled(true);
+ QApplication::sendEvent(&scene, &event);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
+ item->setEnabled(false);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+}
+
+void tst_QGraphicsItem::explicitlyEnabled()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *parent = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsItem *child = scene.addRect(QRectF(25, 25, 50, 50));
+ child->setParentItem(parent);
+
+ QVERIFY(parent->isEnabled());
+ QVERIFY(child->isEnabled());
+
+ parent->setEnabled(false);
+
+ QVERIFY(!parent->isEnabled());
+ QVERIFY(!child->isEnabled());
+
+ parent->setEnabled(true);
+ child->setEnabled(false);
+
+ QVERIFY(parent->isEnabled());
+ QVERIFY(!child->isEnabled());
+
+ parent->setEnabled(false);
+
+ QVERIFY(!parent->isEnabled());
+ QVERIFY(!child->isEnabled());
+
+ parent->setEnabled(true);
+
+ QVERIFY(parent->isEnabled());
+ QVERIFY(!child->isEnabled()); // <- explicitly disabled
+
+ child->setEnabled(true);
+
+ QVERIFY(child->isEnabled());
+
+ parent->setEnabled(false);
+
+ QVERIFY(!parent->isEnabled());
+ QVERIFY(!child->isEnabled()); // <- explicit enabled doesn't work
+
+ parent->setEnabled(true);
+
+ QVERIFY(parent->isEnabled());
+ QVERIFY(child->isEnabled()); // <- no longer explicitly disabled
+
+ // ------------------- Reparenting ------------------------------
+
+ QGraphicsItem *parent2 = scene.addRect(-50, -50, 200, 200);
+ QVERIFY(parent2->isEnabled());
+
+ // Reparent implicitly hidden item to a enabled parent.
+ parent->setEnabled(false);
+ QVERIFY(!parent->isEnabled());
+ QVERIFY(!child->isEnabled());
+ child->setParentItem(parent2);
+ QVERIFY(parent2->isEnabled());
+ QVERIFY(child->isEnabled());
+
+ // Reparent implicitly hidden item to a hidden parent.
+ child->setParentItem(parent);
+ parent2->setEnabled(false);
+ child->setParentItem(parent2);
+ QVERIFY(!parent2->isEnabled());
+ QVERIFY(!child->isEnabled());
+
+ // Reparent explicitly hidden item to a enabled parent.
+ child->setEnabled(false);
+ parent->setEnabled(true);
+ child->setParentItem(parent);
+ QVERIFY(parent->isEnabled());
+ QVERIFY(!child->isEnabled());
+
+ // Reparent explicitly hidden item to a hidden parent.
+ child->setParentItem(parent2);
+ QVERIFY(!parent2->isEnabled());
+ QVERIFY(!child->isEnabled());
+
+ // Reparent explicitly hidden item to a enabled parent.
+ parent->setEnabled(true);
+ child->setParentItem(parent);
+ QVERIFY(parent->isEnabled());
+ QVERIFY(!child->isEnabled());
+
+ // Reparent enabled item to a hidden parent.
+ child->setEnabled(true);
+ parent2->setEnabled(false);
+ child->setParentItem(parent2);
+ QVERIFY(!parent2->isEnabled());
+ QVERIFY(!child->isEnabled());
+ parent2->setEnabled(true);
+ QVERIFY(parent2->isEnabled());
+ QVERIFY(child->isEnabled());
+
+ // Reparent implicitly hidden child to root.
+ parent2->setEnabled(false);
+ QVERIFY(!child->isEnabled());
+ child->setParentItem(0);
+ QVERIFY(child->isEnabled());
+
+ // Reparent an explicitly hidden child to root.
+ child->setEnabled(false);
+ child->setParentItem(parent2);
+ parent2->setEnabled(true);
+ QVERIFY(!child->isEnabled());
+ child->setParentItem(0);
+ QVERIFY(!child->isEnabled());
+}
+
+class SelectChangeItem : public QGraphicsRectItem
+{
+public:
+ SelectChangeItem() : QGraphicsRectItem(-50, -50, 100, 100) { setBrush(Qt::blue); }
+ QList<bool> values;
+
+protected:
+ QVariant itemChange(GraphicsItemChange change, const QVariant &value)
+ {
+ if (change == ItemSelectedChange)
+ values << value.toBool();
+ return QGraphicsRectItem::itemChange(change, value);
+ }
+};
+
+void tst_QGraphicsItem::selected()
+{
+ SelectChangeItem *item = new SelectChangeItem;
+ item->setFlag(QGraphicsItem::ItemIsSelectable);
+ QVERIFY(!item->isSelected());
+ QVERIFY(item->values.isEmpty());
+ item->setSelected(true);
+ QCOMPARE(item->values.size(), 1);
+ QCOMPARE(item->values.last(), true);
+ QVERIFY(item->isSelected());
+ item->setSelected(false);
+ QCOMPARE(item->values.size(), 2);
+ QCOMPARE(item->values.last(), false);
+ QVERIFY(!item->isSelected());
+ item->setSelected(true);
+ QCOMPARE(item->values.size(), 3);
+ item->setEnabled(false);
+ QCOMPARE(item->values.size(), 4);
+ QCOMPARE(item->values.last(), false);
+ QVERIFY(!item->isSelected());
+ item->setEnabled(true);
+ QCOMPARE(item->values.size(), 4);
+ item->setSelected(true);
+ QCOMPARE(item->values.size(), 5);
+ QCOMPARE(item->values.last(), true);
+ QVERIFY(item->isSelected());
+ item->setVisible(false);
+ QCOMPARE(item->values.size(), 6);
+ QCOMPARE(item->values.last(), false);
+ QVERIFY(!item->isSelected());
+ item->setVisible(true);
+ QCOMPARE(item->values.size(), 6);
+ item->setSelected(true);
+ QCOMPARE(item->values.size(), 7);
+ QCOMPARE(item->values.last(), true);
+ QVERIFY(item->isSelected());
+
+ QGraphicsScene scene(-100, -100, 200, 200);
+ scene.addItem(item);
+ QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>() << item);
+ item->setSelected(false);
+ QVERIFY(scene.selectedItems().isEmpty());
+ item->setSelected(true);
+ QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>() << item);
+ item->setSelected(false);
+ QVERIFY(scene.selectedItems().isEmpty());
+
+ // Interactive selection
+ QGraphicsView view(&scene);
+ view.setFixedSize(250, 250);
+ view.show();
+
+ qApp->processEvents();
+ qApp->processEvents();
+
+ scene.clearSelection();
+ QCOMPARE(item->values.size(), 10);
+ QCOMPARE(item->values.last(), false);
+ QVERIFY(!item->isSelected());
+
+ // Click inside and check that it's selected
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos()));
+ QCOMPARE(item->values.size(), 11);
+ QCOMPARE(item->values.last(), true);
+ QVERIFY(item->isSelected());
+
+ // Click outside and check that it's not selected
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos() + QPointF(item->boundingRect().width(), item->boundingRect().height())));
+
+ QCOMPARE(item->values.size(), 12);
+ QCOMPARE(item->values.last(), false);
+ QVERIFY(!item->isSelected());
+
+ SelectChangeItem *item2 = new SelectChangeItem;
+ item2->setFlag(QGraphicsItem::ItemIsSelectable);
+ item2->setPos(100, 0);
+ scene.addItem(item2);
+
+ // Click inside and check that it's selected
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos()));
+ QCOMPARE(item->values.size(), 13);
+ QCOMPARE(item->values.last(), true);
+ QVERIFY(item->isSelected());
+
+ // Click inside item2 and check that it's selected, and item is not
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
+ QCOMPARE(item->values.size(), 14);
+ QCOMPARE(item->values.last(), false);
+ QVERIFY(!item->isSelected());
+ QCOMPARE(item2->values.size(), 1);
+ QCOMPARE(item2->values.last(), true);
+ QVERIFY(item2->isSelected());
+}
+
+void tst_QGraphicsItem::selected2()
+{
+ // Selecting an item, then moving another previously caused a crash.
+ QGraphicsScene scene;
+ QGraphicsItem *line1 = scene.addRect(QRectF(0, 0, 100, 100));
+ line1->setPos(-105, 0);
+ line1->setFlag(QGraphicsItem::ItemIsSelectable);
+
+ QGraphicsItem *line2 = scene.addRect(QRectF(0, 0, 100, 100));
+ line2->setFlag(QGraphicsItem::ItemIsMovable);
+
+ line1->setSelected(true);
+
+ {
+ QGraphicsSceneMouseEvent mousePress(QEvent::GraphicsSceneMousePress);
+ mousePress.setScenePos(QPointF(50, 50));
+ mousePress.setButton(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &mousePress);
+ QVERIFY(mousePress.isAccepted());
+ }
+ {
+ QGraphicsSceneMouseEvent mouseMove(QEvent::GraphicsSceneMouseMove);
+ mouseMove.setScenePos(QPointF(60, 60));
+ mouseMove.setButton(Qt::LeftButton);
+ mouseMove.setButtons(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &mouseMove);
+ QVERIFY(mouseMove.isAccepted());
+ }
+}
+
+void tst_QGraphicsItem::selected_group()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *item1 = scene.addRect(QRectF());
+ QGraphicsItem *item2 = scene.addRect(QRectF());
+ item1->setFlag(QGraphicsItem::ItemIsSelectable);
+ item2->setFlag(QGraphicsItem::ItemIsSelectable);
+ scene.addRect(QRectF())->setParentItem(item1);
+ QGraphicsItem *leaf = scene.addRect(QRectF());
+ leaf->setFlag(QGraphicsItem::ItemIsSelectable);
+ leaf->setParentItem(item2);
+
+ QGraphicsItemGroup *group = scene.createItemGroup(QList<QGraphicsItem *>() << item1 << item2);
+ QCOMPARE(group->scene(), &scene);
+ group->setFlag(QGraphicsItem::ItemIsSelectable);
+ foreach (QGraphicsItem *item, scene.items()) {
+ if (item == group)
+ QVERIFY(!item->group());
+ else
+ QCOMPARE(item->group(), group);
+ }
+
+ QVERIFY(group->handlesChildEvents());
+ QVERIFY(!group->isSelected());
+ group->setSelected(false);
+ QVERIFY(!group->isSelected());
+ group->setSelected(true);
+ QVERIFY(group->isSelected());
+ foreach (QGraphicsItem *item, scene.items())
+ QVERIFY(item->isSelected());
+ group->setSelected(false);
+ QVERIFY(!group->isSelected());
+ foreach (QGraphicsItem *item, scene.items())
+ QVERIFY(!item->isSelected());
+ leaf->setSelected(true);
+ foreach (QGraphicsItem *item, scene.items())
+ QVERIFY(item->isSelected());
+ leaf->setSelected(false);
+ foreach (QGraphicsItem *item, scene.items())
+ QVERIFY(!item->isSelected());
+
+ leaf->setSelected(true);
+ QGraphicsScene scene2;
+ scene2.addItem(item1);
+ QVERIFY(!item1->isSelected());
+ QVERIFY(item2->isSelected());
+}
+
+void tst_QGraphicsItem::selected_textItem()
+{
+ QGraphicsScene scene;
+ QGraphicsTextItem *text = scene.addText(QLatin1String("Text"));
+ text->setFlag(QGraphicsItem::ItemIsSelectable);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWait(1000);
+
+ QVERIFY(!text->isSelected());
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0,
+ view.mapFromScene(text->mapToScene(0, 0)));
+ QVERIFY(text->isSelected());
+
+ text->setSelected(false);
+ text->setTextInteractionFlags(Qt::TextEditorInteraction);
+
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0,
+ view.mapFromScene(text->mapToScene(0, 0)));
+ QVERIFY(text->isSelected());
+}
+
+void tst_QGraphicsItem::selected_multi()
+{
+ // Test multiselection behavior
+ QGraphicsScene scene;
+
+ // Create two disjoint items
+ QGraphicsItem *item1 = scene.addRect(QRectF(-10, -10, 20, 20));
+ QGraphicsItem *item2 = scene.addRect(QRectF(-10, -10, 20, 20));
+ item1->setPos(-15, 0);
+ item2->setPos(15, 20);
+
+ // Make both items selectable
+ item1->setFlag(QGraphicsItem::ItemIsSelectable);
+ item2->setFlag(QGraphicsItem::ItemIsSelectable);
+
+ // Create and show a view
+ QGraphicsView view(&scene);
+ view.show();
+ view.fitInView(scene.sceneRect());
+ qApp->processEvents();
+
+ QVERIFY(!item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Start clicking
+ QTest::qWait(200);
+
+ // Click on item1
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(200);
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Click on item2
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
+ QTest::qWait(200);
+ QVERIFY(item2->isSelected());
+ QVERIFY(!item1->isSelected());
+
+ // Ctrl-click on item1
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(200);
+ QVERIFY(item2->isSelected());
+ QVERIFY(item1->isSelected());
+
+ // Ctrl-click on item1 again
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(200);
+ QVERIFY(item2->isSelected());
+ QVERIFY(!item1->isSelected());
+
+ // Ctrl-click on item2
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item2->scenePos()));
+ QTest::qWait(200);
+ QVERIFY(!item2->isSelected());
+ QVERIFY(!item1->isSelected());
+
+ // Click on item1
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(200);
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Click on scene
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(0, 0));
+ QTest::qWait(200);
+ QVERIFY(!item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Click on item1
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(200);
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Ctrl-click on scene
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(0, 0));
+ QTest::qWait(200);
+ QVERIFY(!item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Click on item1
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(200);
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Press on item2
+ QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
+ QTest::qWait(200);
+ QVERIFY(!item1->isSelected());
+ QVERIFY(item2->isSelected());
+
+ // Release on item2
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
+ QTest::qWait(200);
+ QVERIFY(!item1->isSelected());
+ QVERIFY(item2->isSelected());
+
+ // Click on item1
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(200);
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Ctrl-click on item1
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(200);
+ QVERIFY(!item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Ctrl-press on item1
+ QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(200);
+ QVERIFY(!item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ {
+ // Ctrl-move on item1
+ QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item1->scenePos()) + QPoint(1, 0), Qt::LeftButton, Qt::LeftButton, Qt::ControlModifier);
+ QApplication::sendEvent(view.viewport(), &event);
+ QTest::qWait(200);
+ QVERIFY(!item1->isSelected());
+ QVERIFY(!item2->isSelected());
+ }
+
+ // Release on item1
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(200);
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ item1->setFlag(QGraphicsItem::ItemIsMovable);
+ item1->setSelected(false);
+
+ // Ctrl-press on item1
+ QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(200);
+ QVERIFY(!item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ {
+ // Ctrl-move on item1
+ QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item1->scenePos()) + QPoint(1, 0), Qt::LeftButton, Qt::LeftButton, Qt::ControlModifier);
+ QApplication::sendEvent(view.viewport(), &event);
+ QTest::qWait(200);
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+ }
+
+ // Release on item1
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(200);
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+}
+
+void tst_QGraphicsItem::acceptedMouseButtons()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *item1 = scene.addRect(QRectF(-10, -10, 20, 20));
+ QGraphicsRectItem *item2 = scene.addRect(QRectF(-10, -10, 20, 20));
+ item2->setZValue(1);
+
+ item1->setFlag(QGraphicsItem::ItemIsMovable);
+ item2->setFlag(QGraphicsItem::ItemIsMovable);
+
+ QCOMPARE(item1->acceptedMouseButtons(), Qt::MouseButtons(0x1f));
+ QCOMPARE(item2->acceptedMouseButtons(), Qt::MouseButtons(0x1f));
+
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(0, 0));
+ QApplication::sendEvent(&scene, &event);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item2);
+ item2->setAcceptedMouseButtons(0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ QApplication::sendEvent(&scene, &event);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item1);
+}
+
+class HoverItem : public QGraphicsRectItem
+{
+public:
+ HoverItem(const QRectF &rect)
+ : QGraphicsRectItem(rect), hoverInCount(0),
+ hoverMoveCount(0), hoverOutCount(0)
+ { }
+
+ int hoverInCount;
+ int hoverMoveCount;
+ int hoverOutCount;
+protected:
+ void hoverEnterEvent(QGraphicsSceneHoverEvent *)
+ { ++hoverInCount; }
+
+ void hoverMoveEvent(QGraphicsSceneHoverEvent *)
+ { ++hoverMoveCount; }
+
+ void hoverLeaveEvent(QGraphicsSceneHoverEvent *)
+ { ++hoverOutCount; }
+};
+
+void tst_QGraphicsItem::acceptsHoverEvents()
+{
+ QGraphicsScene scene;
+ HoverItem *item1 = new HoverItem(QRectF(-10, -10, 20, 20));
+ HoverItem *item2 = new HoverItem(QRectF(-5, -5, 10, 10));
+ scene.addItem(item1);
+ scene.addItem(item2);
+ item2->setZValue(1);
+
+ QVERIFY(!item1->acceptsHoverEvents());
+ QVERIFY(!item2->acceptsHoverEvents());
+ item1->setAcceptsHoverEvents(true);
+ item2->setAcceptsHoverEvents(true);
+
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
+ event.setScenePos(QPointF(-100, -100));
+ QApplication::sendEvent(&scene, &event);
+ event.setScenePos(QPointF(-2.5, -2.5));
+ QApplication::sendEvent(&scene, &event);
+
+ QCOMPARE(item1->hoverInCount, 0);
+ QCOMPARE(item2->hoverInCount, 1);
+
+ item1->setAcceptsHoverEvents(false);
+ item2->setAcceptsHoverEvents(false);
+
+ event.setScenePos(QPointF(-100, -100));
+ QApplication::sendEvent(&scene, &event);
+ event.setScenePos(QPointF(-2.5, -2.5));
+ QApplication::sendEvent(&scene, &event);
+
+ QCOMPARE(item1->hoverInCount, 0);
+ QCOMPARE(item2->hoverInCount, 1);
+
+ item1->setAcceptsHoverEvents(true);
+ item2->setAcceptsHoverEvents(false);
+
+ event.setScenePos(QPointF(-100, -100));
+ QApplication::sendEvent(&scene, &event);
+ event.setScenePos(QPointF(-2.5, -2.5));
+ QApplication::sendEvent(&scene, &event);
+
+ QCOMPARE(item1->hoverInCount, 1);
+ QCOMPARE(item2->hoverInCount, 1);
+}
+
+void tst_QGraphicsItem::childAcceptsHoverEvents()
+{
+ QGraphicsScene scene;
+ HoverItem *item1 = new HoverItem(QRectF(-10, -10, 20, 20));
+ HoverItem *item2 = new HoverItem(QRectF(-5, -5, 10, 10));
+
+ scene.addItem(item1);
+ scene.addItem(item2);
+ item2->setParentItem(item1);
+ item2->setAcceptHoverEvents(true);
+
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
+ event.setScenePos(QPointF(-100, -100));
+ QApplication::sendEvent(&scene, &event);
+ QCOMPARE(item2->hoverInCount, 0);
+ QCOMPARE(item2->hoverMoveCount, 0);
+ QCOMPARE(item2->hoverOutCount, 0);
+ QCOMPARE(item1->hoverInCount, 0);
+ QCOMPARE(item1->hoverMoveCount, 0);
+ QCOMPARE(item1->hoverOutCount, 0);
+
+ event.setScenePos(QPointF(-2.5, -2.5));
+ QApplication::sendEvent(&scene, &event);
+
+ QCOMPARE(item2->hoverInCount, 1);
+ QCOMPARE(item2->hoverMoveCount, 1);
+ QCOMPARE(item2->hoverOutCount, 0);
+ QCOMPARE(item1->hoverInCount, 0);
+ QCOMPARE(item1->hoverMoveCount, 0);
+ QCOMPARE(item1->hoverOutCount, 0);
+
+ event.setScenePos(QPointF(0, 0));
+ QApplication::sendEvent(&scene, &event);
+
+ QCOMPARE(item2->hoverInCount, 1);
+ QCOMPARE(item2->hoverMoveCount, 2);
+ QCOMPARE(item2->hoverOutCount, 0);
+ QCOMPARE(item1->hoverInCount, 0);
+ QCOMPARE(item1->hoverMoveCount, 0);
+ QCOMPARE(item1->hoverOutCount, 0);
+
+ event.setScenePos(QPointF(-7, -7));
+ QApplication::sendEvent(&scene, &event);
+
+ QCOMPARE(item2->hoverInCount, 1);
+ QCOMPARE(item2->hoverMoveCount, 2);
+ QCOMPARE(item2->hoverOutCount, 1);
+ QCOMPARE(item1->hoverInCount, 0);
+ QCOMPARE(item1->hoverMoveCount, 0);
+ QCOMPARE(item1->hoverOutCount, 0);
+
+ event.setScenePos(QPointF(0, 0));
+ QApplication::sendEvent(&scene, &event);
+
+ QCOMPARE(item2->hoverInCount, 2);
+ QCOMPARE(item2->hoverMoveCount, 3);
+ QCOMPARE(item2->hoverOutCount, 1);
+ QCOMPARE(item1->hoverInCount, 0);
+ QCOMPARE(item1->hoverMoveCount, 0);
+ QCOMPARE(item1->hoverOutCount, 0);
+
+ HoverItem *item0 = new HoverItem(QRectF(-20, -20, 20, 20));
+ scene.addItem(item0);
+ item1->setParentItem(item0);
+ item0->setAcceptHoverEvents(true);
+
+ event.setScenePos(QPointF(-100, -100));
+ QApplication::sendEvent(&scene, &event);
+
+ event.setScenePos(QPointF(-15, -15));
+ QApplication::sendEvent(&scene, &event);
+
+ QCOMPARE(item2->hoverInCount, 2);
+ QCOMPARE(item2->hoverMoveCount, 3);
+ QCOMPARE(item2->hoverOutCount, 2);
+ QCOMPARE(item1->hoverInCount, 0);
+ QCOMPARE(item1->hoverMoveCount, 0);
+ QCOMPARE(item1->hoverOutCount, 0);
+ QCOMPARE(item0->hoverInCount, 1);
+ QCOMPARE(item0->hoverMoveCount, 1);
+ QCOMPARE(item0->hoverOutCount, 0);
+}
+
+void tst_QGraphicsItem::hasFocus()
+{
+ QGraphicsLineItem *line = new QGraphicsLineItem;
+ QVERIFY(!line->hasFocus());
+ line->setFocus();
+ QVERIFY(!line->hasFocus());
+
+ QGraphicsScene scene;
+ scene.addItem(line);
+
+ line->setFocus();
+ QVERIFY(!line->hasFocus());
+ line->setFlag(QGraphicsItem::ItemIsFocusable);
+ line->setFocus();
+ QVERIFY(line->hasFocus());
+
+ QGraphicsScene scene2;
+ scene2.addItem(line);
+ QVERIFY(!line->hasFocus());
+
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *)0);
+ QCOMPARE(scene2.focusItem(), (QGraphicsItem *)0);
+
+ line->setFocus();
+ QVERIFY(line->hasFocus());
+ line->clearFocus();
+ QVERIFY(!line->hasFocus());
+
+ QGraphicsLineItem *line2 = new QGraphicsLineItem;
+ line2->setFlag(QGraphicsItem::ItemIsFocusable);
+ scene2.addItem(line2);
+
+ line2->setFocus();
+ QVERIFY(!line->hasFocus());
+ QVERIFY(line2->hasFocus());
+ line->setFocus();
+ QVERIFY(line->hasFocus());
+ QVERIFY(!line2->hasFocus());
+}
+
+void tst_QGraphicsItem::pos()
+{
+ QGraphicsItem *child = new QGraphicsLineItem;
+ QGraphicsItem *parent = new QGraphicsLineItem;
+
+ QCOMPARE(child->pos(), QPointF());
+ QCOMPARE(parent->pos(), QPointF());
+
+ child->setParentItem(parent);
+ child->setPos(10, 10);
+
+ QCOMPARE(child->pos(), QPointF(10, 10));
+
+ parent->setPos(10, 10);
+
+ QCOMPARE(parent->pos(), QPointF(10, 10));
+ QCOMPARE(child->pos(), QPointF(10, 10));
+
+ delete child;
+ delete parent;
+}
+
+void tst_QGraphicsItem::scenePos()
+{
+ QGraphicsItem *child = new QGraphicsLineItem;
+ QGraphicsItem *parent = new QGraphicsLineItem;
+
+ QCOMPARE(child->scenePos(), QPointF());
+ QCOMPARE(parent->scenePos(), QPointF());
+
+ child->setParentItem(parent);
+ child->setPos(10, 10);
+
+ QCOMPARE(child->scenePos(), QPointF(10, 10));
+
+ parent->setPos(10, 10);
+
+ QCOMPARE(parent->scenePos(), QPointF(10, 10));
+ QCOMPARE(child->scenePos(), QPointF(20, 20));
+
+ parent->setPos(20, 20);
+
+ QCOMPARE(parent->scenePos(), QPointF(20, 20));
+ QCOMPARE(child->scenePos(), QPointF(30, 30));
+
+ delete child;
+ delete parent;
+}
+
+void tst_QGraphicsItem::matrix()
+{
+ QGraphicsLineItem line;
+ QCOMPARE(line.matrix(), QMatrix());
+ line.setMatrix(QMatrix().rotate(90));
+ QCOMPARE(line.matrix(), QMatrix().rotate(90));
+ line.setMatrix(QMatrix().rotate(90));
+ QCOMPARE(line.matrix(), QMatrix().rotate(90));
+ line.setMatrix(QMatrix().rotate(90), true);
+ QCOMPARE(line.matrix(), QMatrix().rotate(180));
+ line.setMatrix(QMatrix().rotate(-90), true);
+ QCOMPARE(line.matrix(), QMatrix().rotate(90));
+ line.resetMatrix();
+ QCOMPARE(line.matrix(), QMatrix());
+
+ line.rotate(90);
+ QCOMPARE(line.matrix(), QMatrix().rotate(90));
+ line.rotate(90);
+ QCOMPARE(line.matrix(), QMatrix().rotate(90).rotate(90));
+ line.resetMatrix();
+
+ line.scale(2, 4);
+ QCOMPARE(line.matrix(), QMatrix().scale(2, 4));
+ line.scale(2, 4);
+ QCOMPARE(line.matrix(), QMatrix().scale(2, 4).scale(2, 4));
+ line.resetMatrix();
+
+ line.shear(2, 4);
+ QCOMPARE(line.matrix(), QMatrix().shear(2, 4));
+ line.shear(2, 4);
+ QCOMPARE(line.matrix(), QMatrix().shear(2, 4).shear(2, 4));
+ line.resetMatrix();
+
+ line.translate(10, 10);
+ QCOMPARE(line.matrix(), QMatrix().translate(10, 10));
+ line.translate(10, 10);
+ QCOMPARE(line.matrix(), QMatrix().translate(10, 10).translate(10, 10));
+ line.resetMatrix();
+}
+
+void tst_QGraphicsItem::sceneMatrix()
+{
+ QGraphicsLineItem *parent = new QGraphicsLineItem;
+ QGraphicsLineItem *child = new QGraphicsLineItem(QLineF(), parent);
+
+ QCOMPARE(parent->sceneMatrix(), QMatrix());
+ QCOMPARE(child->sceneMatrix(), QMatrix());
+
+ parent->translate(10, 10);
+ QCOMPARE(parent->sceneMatrix(), QMatrix().translate(10, 10));
+ QCOMPARE(child->sceneMatrix(), QMatrix().translate(10, 10));
+
+ child->translate(10, 10);
+ QCOMPARE(parent->sceneMatrix(), QMatrix().translate(10, 10));
+ QCOMPARE(child->sceneMatrix(), QMatrix().translate(20, 20));
+
+ parent->rotate(90);
+ QCOMPARE(parent->sceneMatrix(), QMatrix().translate(10, 10).rotate(90));
+ QCOMPARE(child->sceneMatrix(), QMatrix().translate(10, 10).rotate(90).translate(10, 10));
+
+ delete child;
+ delete parent;
+}
+
+void tst_QGraphicsItem::setMatrix()
+{
+ QGraphicsScene scene;
+ qRegisterMetaType<QList<QRectF> >("QList<QRectF>");
+ QSignalSpy spy(&scene, SIGNAL(changed(QList<QRectF>)));
+ QRectF unrotatedRect(-12, -34, 56, 78);
+ QGraphicsRectItem item(unrotatedRect, 0, &scene);
+ scene.update(scene.sceneRect());
+ QApplication::instance()->processEvents();
+
+ QCOMPARE(spy.count(), 1);
+
+ item.setMatrix(QMatrix().rotate(qreal(12.34)));
+ QRectF rotatedRect = scene.sceneRect();
+ QVERIFY(unrotatedRect != rotatedRect);
+ scene.update(scene.sceneRect());
+ QApplication::instance()->processEvents();
+
+ QCOMPARE(spy.count(), 2);
+
+ item.setMatrix(QMatrix());
+
+ scene.update(scene.sceneRect());
+ QApplication::instance()->processEvents();
+
+ QCOMPARE(spy.count(), 3);
+ QList<QRectF> rlist = qVariantValue<QList<QRectF> >(spy.last().at(0));
+
+ QCOMPARE(rlist.size(), 3);
+ QCOMPARE(rlist.at(0), rotatedRect); // From item.setMatrix() (clearing rotated rect)
+ QCOMPARE(rlist.at(1), rotatedRect); // From scene.update() (updating scene rect)
+ QCOMPARE(rlist.at(2), unrotatedRect); // From post-update (update current state)
+}
+
+static QList<QGraphicsItem *> paintedItems;
+class PainterItem : public QGraphicsItem
+{
+protected:
+ QRectF boundingRect() const
+ { return QRectF(-10, -10, 20, 20); }
+
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *)
+ { paintedItems << this; }
+};
+
+void tst_QGraphicsItem::zValue()
+{
+ Q_CHECK_PAINTEVENTS
+
+ QGraphicsScene scene;
+
+ QGraphicsItem *item1 = new PainterItem;
+ QGraphicsItem *item2 = new PainterItem;
+ QGraphicsItem *item3 = new PainterItem;
+ QGraphicsItem *item4 = new PainterItem;
+ scene.addItem(item1);
+ scene.addItem(item2);
+ scene.addItem(item3);
+ scene.addItem(item4);
+ item2->setZValue(-3);
+ item4->setZValue(-2);
+ item1->setZValue(-1);
+ item3->setZValue(0);
+
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QApplication::processEvents();
+#ifdef Q_WS_QWS
+ QApplication::sendPostedEvents(); //glib workaround
+#endif
+
+ QVERIFY(!paintedItems.isEmpty());
+ QVERIFY((paintedItems.size() % 4) == 0);
+ for (int i = 0; i < 3; ++i)
+ QVERIFY(paintedItems.at(i)->zValue() < paintedItems.at(i + 1)->zValue());
+}
+
+void tst_QGraphicsItem::shape()
+{
+ QGraphicsLineItem line(QLineF(-10, -10, 20, 20));
+
+ // We unfortunately need this hack as QPainterPathStroker will set a width of 1.0
+ // if we pass a value of 0.0 to QPainterPathStroker::setWidth()
+ const qreal penWidthZero = qreal(0.00000001);
+
+ QPainterPathStroker ps;
+ ps.setWidth(penWidthZero);
+
+ QPainterPath path(line.line().p1());
+ path.lineTo(line.line().p2());
+ QPainterPath p = ps.createStroke(path);
+ p.addPath(path);
+ QCOMPARE(line.shape(), p);
+
+ QPen linePen;
+ linePen.setWidthF(5.0);
+ linePen.setCapStyle(Qt::RoundCap);
+ line.setPen(linePen);
+
+ ps.setCapStyle(line.pen().capStyle());
+ ps.setWidth(line.pen().widthF());
+ p = ps.createStroke(path);
+ p.addPath(path);
+ QCOMPARE(line.shape(), p);
+
+ linePen.setCapStyle(Qt::FlatCap);
+ line.setPen(linePen);
+ ps.setCapStyle(line.pen().capStyle());
+ p = ps.createStroke(path);
+ p.addPath(path);
+ QCOMPARE(line.shape(), p);
+
+ linePen.setCapStyle(Qt::SquareCap);
+ line.setPen(linePen);
+ ps.setCapStyle(line.pen().capStyle());
+ p = ps.createStroke(path);
+ p.addPath(path);
+ QCOMPARE(line.shape(), p);
+
+ QGraphicsRectItem rect(QRectF(-10, -10, 20, 20));
+ QPainterPathStroker ps1;
+ ps1.setWidth(penWidthZero);
+ path = QPainterPath();
+ path.addRect(rect.rect());
+ p = ps1.createStroke(path);
+ p.addPath(path);
+ QCOMPARE(rect.shape(), p);
+
+ QGraphicsEllipseItem ellipse(QRectF(-10, -10, 20, 20));
+ QPainterPathStroker ps2;
+ ps2.setWidth(ellipse.pen().widthF() <= 0.0 ? penWidthZero : ellipse.pen().widthF());
+ path = QPainterPath();
+ path.addEllipse(ellipse.rect());
+ p = ps2.createStroke(path);
+ p.addPath(path);
+ QCOMPARE(ellipse.shape(), p);
+
+ QPainterPathStroker ps3;
+ ps3.setWidth(penWidthZero);
+ p = ps3.createStroke(path);
+ p.addPath(path);
+ QGraphicsPathItem pathItem(path);
+ QCOMPARE(pathItem.shape(), p);
+
+ QRegion region(QRect(0, 0, 300, 200));
+ region = region.subtracted(QRect(50, 50, 200, 100));
+
+ QImage image(300, 200, QImage::Format_ARGB32_Premultiplied);
+ image.fill(0);
+ QPainter painter(&image);
+ painter.setClipRegion(region);
+ painter.fillRect(0, 0, 300, 200, Qt::green);
+ painter.end();
+ QPixmap pixmap = QPixmap::fromImage(image);
+
+ QGraphicsPixmapItem pixmapItem(pixmap);
+ path = QPainterPath();
+ path.addRegion(region);
+
+ {
+ QBitmap bitmap(300, 200);
+ bitmap.clear();
+ QPainter painter(&bitmap);
+ painter.setClipRegion(region);
+ painter.fillRect(0, 0, 300, 200, Qt::color1);
+ painter.end();
+
+ QBitmap bitmap2(300, 200);
+ bitmap2.clear();
+ painter.begin(&bitmap2);
+ painter.setClipPath(pixmapItem.shape());
+ painter.fillRect(0, 0, 300, 200, Qt::color1);
+ painter.end();
+
+ QCOMPARE(bitmap.toImage(), bitmap2.toImage());
+ }
+
+ QPolygonF poly;
+ poly << QPointF(0, 0) << QPointF(10, 0) << QPointF(0, 10);
+ QGraphicsPolygonItem polygon(poly);
+ path = QPainterPath();
+ path.addPolygon(poly);
+
+ QPainterPathStroker ps4;
+ ps4.setWidth(penWidthZero);
+ p = ps4.createStroke(path);
+ p.addPath(path);
+ QCOMPARE(polygon.shape(), p);
+}
+
+void tst_QGraphicsItem::contains()
+{
+ if (sizeof(qreal) != sizeof(double)) {
+ QSKIP("Skipped due to rounding errors", SkipAll);
+ }
+
+ // Rect
+ QGraphicsRectItem rect(QRectF(-10, -10, 20, 20));
+ QVERIFY(!rect.contains(QPointF(-11, -10)));
+ QVERIFY(rect.contains(QPointF(-10, -10)));
+ QVERIFY(!rect.contains(QPointF(-11, 0)));
+ QVERIFY(rect.contains(QPointF(-10, 0)));
+ QVERIFY(rect.contains(QPointF(0, -10)));
+ QVERIFY(rect.contains(QPointF(0, 0)));
+ QVERIFY(rect.contains(QPointF(9, 9)));
+
+ // Ellipse
+ QGraphicsEllipseItem ellipse(QRectF(-10, -10, 20, 20));
+ QVERIFY(!ellipse.contains(QPointF(-10, -10)));
+ QVERIFY(ellipse.contains(QPointF(-9, 0)));
+ QVERIFY(ellipse.contains(QPointF(0, -9)));
+ QVERIFY(ellipse.contains(QPointF(0, 0)));
+ QVERIFY(!ellipse.contains(QPointF(9, 9)));
+
+ // Line
+ QGraphicsLineItem line(QLineF(-10, -10, 20, 20));
+ QVERIFY(!line.contains(QPointF(-10, 0)));
+ QVERIFY(!line.contains(QPointF(0, -10)));
+ QVERIFY(!line.contains(QPointF(10, 0)));
+ QVERIFY(!line.contains(QPointF(0, 10)));
+ QVERIFY(line.contains(QPointF(0, 0)));
+ QVERIFY(line.contains(QPointF(-9, -9)));
+ QVERIFY(line.contains(QPointF(9, 9)));
+
+ // Polygon
+ QGraphicsPolygonItem polygon(QPolygonF()
+ << QPointF(0, 0)
+ << QPointF(10, 0)
+ << QPointF(0, 10));
+ QVERIFY(polygon.contains(QPointF(1, 1)));
+ QVERIFY(polygon.contains(QPointF(4, 4)));
+ QVERIFY(polygon.contains(QPointF(1, 4)));
+ QVERIFY(polygon.contains(QPointF(4, 1)));
+ QVERIFY(!polygon.contains(QPointF(8, 8)));
+ QVERIFY(polygon.contains(QPointF(1, 8)));
+ QVERIFY(polygon.contains(QPointF(8, 1)));
+}
+
+void tst_QGraphicsItem::collidesWith_item()
+{
+ // Rectangle
+ QGraphicsRectItem rect(QRectF(-10, -10, 20, 20));
+ QGraphicsRectItem rect2(QRectF(-10, -10, 20, 20));
+ QVERIFY(rect.collidesWithItem(&rect2));
+ QVERIFY(rect2.collidesWithItem(&rect));
+ rect2.setPos(21, 21);
+ QVERIFY(!rect.collidesWithItem(&rect2));
+ QVERIFY(!rect2.collidesWithItem(&rect));
+ rect2.setPos(-21, -21);
+ QVERIFY(!rect.collidesWithItem(&rect2));
+ QVERIFY(!rect2.collidesWithItem(&rect));
+ rect2.setPos(-17, -17);
+ QVERIFY(rect.collidesWithItem(&rect2));
+ QVERIFY(rect2.collidesWithItem(&rect));
+
+ QGraphicsEllipseItem ellipse(QRectF(-10, -10, 20, 20));
+ QGraphicsEllipseItem ellipse2(QRectF(-10, -10, 20, 20));
+ QVERIFY(ellipse.collidesWithItem(&ellipse2));
+ QVERIFY(ellipse2.collidesWithItem(&ellipse));
+ ellipse2.setPos(21, 21);
+ QVERIFY(!ellipse.collidesWithItem(&ellipse2));
+ QVERIFY(!ellipse2.collidesWithItem(&ellipse));
+ ellipse2.setPos(-21, -21);
+ QVERIFY(!ellipse.collidesWithItem(&ellipse2));
+ QVERIFY(!ellipse2.collidesWithItem(&ellipse));
+
+ ellipse2.setPos(-17, -17);
+ QVERIFY(!ellipse.collidesWithItem(&ellipse2));
+ QVERIFY(!ellipse2.collidesWithItem(&ellipse));
+
+ {
+ QGraphicsScene scene;
+ QGraphicsRectItem rect(20, 20, 100, 100, 0, &scene);
+ QGraphicsRectItem rect2(40, 40, 50, 50, 0, &scene);
+ rect2.setZValue(1);
+ QGraphicsLineItem line(0, 0, 200, 200, 0, &scene);
+ line.setZValue(2);
+
+ QCOMPARE(scene.items().size(), 3);
+
+ QList<QGraphicsItem *> col1 = rect.collidingItems();
+ QCOMPARE(col1.size(), 2);
+ QCOMPARE(col1.first(), static_cast<QGraphicsItem *>(&line));
+ QCOMPARE(col1.last(), static_cast<QGraphicsItem *>(&rect2));
+
+ QList<QGraphicsItem *> col2 = rect2.collidingItems();
+ QCOMPARE(col2.size(), 2);
+ QCOMPARE(col2.first(), static_cast<QGraphicsItem *>(&line));
+ QCOMPARE(col2.last(), static_cast<QGraphicsItem *>(&rect));
+
+ QList<QGraphicsItem *> col3 = line.collidingItems();
+ QCOMPARE(col3.size(), 2);
+ QCOMPARE(col3.first(), static_cast<QGraphicsItem *>(&rect2));
+ QCOMPARE(col3.last(), static_cast<QGraphicsItem *>(&rect));
+ }
+}
+
+void tst_QGraphicsItem::collidesWith_path_data()
+{
+ QTest::addColumn<QPointF>("pos");
+ QTest::addColumn<QMatrix>("matrix");
+ QTest::addColumn<QPainterPath>("shape");
+ QTest::addColumn<bool>("rectCollides");
+ QTest::addColumn<bool>("ellipseCollides");
+
+ QTest::newRow("nothing") << QPointF(0, 0) << QMatrix() << QPainterPath() << false << false;
+
+ QPainterPath rect;
+ rect.addRect(0, 0, 20, 20);
+
+ QTest::newRow("rect1") << QPointF(0, 0) << QMatrix() << rect << true << true;
+ QTest::newRow("rect2") << QPointF(0, 0) << QMatrix().translate(21, 21) << rect << false << false;
+ QTest::newRow("rect3") << QPointF(21, 21) << QMatrix() << rect << false << false;
+}
+
+void tst_QGraphicsItem::collidesWith_path()
+{
+ QFETCH(QPointF, pos);
+ QFETCH(QMatrix, matrix);
+ QFETCH(QPainterPath, shape);
+ QFETCH(bool, rectCollides);
+ QFETCH(bool, ellipseCollides);
+
+ QGraphicsRectItem rect(QRectF(0, 0, 20, 20));
+ QGraphicsEllipseItem ellipse(QRectF(0, 0, 20, 20));
+
+ rect.setPos(pos);
+ rect.setMatrix(matrix);
+
+ ellipse.setPos(pos);
+ ellipse.setMatrix(matrix);
+
+ QPainterPath mappedShape = rect.sceneMatrix().inverted().map(shape);
+
+ if (rectCollides)
+ QVERIFY(rect.collidesWithPath(mappedShape));
+ else
+ QVERIFY(!rect.collidesWithPath(mappedShape));
+
+ if (ellipseCollides)
+ QVERIFY(ellipse.collidesWithPath(mappedShape));
+ else
+ QVERIFY(!ellipse.collidesWithPath(mappedShape));
+}
+
+void tst_QGraphicsItem::collidesWithItemWithClip()
+{
+ QGraphicsScene scene;
+
+ QGraphicsEllipseItem *ellipse = scene.addEllipse(0, 0, 100, 100);
+ ellipse->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ QGraphicsEllipseItem *ellipse2 = scene.addEllipse(0, 0, 10, 10);
+ ellipse2->setParentItem(ellipse);
+ QGraphicsEllipseItem *ellipse3 = scene.addEllipse(0, 0, 10, 10);
+ ellipse3->setParentItem(ellipse);
+ QGraphicsEllipseItem *ellipse5 = scene.addEllipse(50, 50, 10, 10);
+ ellipse5->setParentItem(ellipse);
+ QGraphicsEllipseItem *ellipse4 = scene.addEllipse(0, 0, 10, 10);
+
+ QVERIFY(ellipse2->collidesWithItem(ellipse3));
+ QVERIFY(ellipse3->collidesWithItem(ellipse2));
+ QVERIFY(!ellipse2->collidesWithItem(ellipse));
+ QVERIFY(!ellipse->collidesWithItem(ellipse2));
+ QVERIFY(!ellipse4->collidesWithItem(ellipse));
+ QVERIFY(!ellipse4->collidesWithItem(ellipse2));
+ QVERIFY(!ellipse4->collidesWithItem(ellipse3));
+ QVERIFY(!ellipse->collidesWithItem(ellipse4));
+ QVERIFY(!ellipse2->collidesWithItem(ellipse4));
+ QVERIFY(!ellipse3->collidesWithItem(ellipse4));
+ QVERIFY(ellipse->collidesWithItem(ellipse5));
+ QVERIFY(ellipse5->collidesWithItem(ellipse));
+}
+
+class MyItem : public QGraphicsEllipseItem
+{
+public:
+ bool isObscuredBy(const QGraphicsItem *item) const
+ {
+ const MyItem *myItem = qgraphicsitem_cast<const MyItem *>(item);
+ if (myItem) {
+ if (item->zValue() > zValue()) {
+ QRectF r = rect();
+ QPointF topMid = (r.topRight()+r.topLeft())/2;
+ QPointF botMid = (r.bottomRight()+r.bottomLeft())/2;
+ QPointF leftMid = (r.topLeft()+r.bottomLeft())/2;
+ QPointF rightMid = (r.topRight()+r.bottomRight())/2;
+
+ QPainterPath mappedShape = item->mapToItem(this, item->opaqueArea());
+
+ if (mappedShape.contains(topMid) &&
+ mappedShape.contains(botMid) &&
+ mappedShape.contains(leftMid) &&
+ mappedShape.contains(rightMid))
+ return true;
+ else
+ return false;
+ }
+ else return false;
+ }
+ else
+ return QGraphicsItem::isObscuredBy(item);
+ }
+
+ QPainterPath opaqueArea() const
+ {
+ return shape();
+ }
+
+ enum {
+ Type = UserType+1
+ };
+ int type() const { return Type; }
+};
+
+void tst_QGraphicsItem::isObscuredBy()
+{
+ QGraphicsScene scene;
+
+ MyItem myitem1, myitem2;
+
+ myitem1.setRect(QRectF(50, 50, 40, 200));
+ myitem1.rotate(67);
+
+ myitem2.setRect(QRectF(25, 25, 20, 20));
+ myitem2.setZValue(-1.0);
+ scene.addItem(&myitem1);
+ scene.addItem(&myitem2);
+
+ QVERIFY(!myitem2.isObscuredBy(&myitem1));
+ QVERIFY(!myitem1.isObscuredBy(&myitem2));
+
+ myitem2.setRect(QRectF(-50, 85, 20, 20));
+ QVERIFY(myitem2.isObscuredBy(&myitem1));
+ QVERIFY(!myitem1.isObscuredBy(&myitem2));
+
+ myitem2.setRect(QRectF(-30, 70, 20, 20));
+ QVERIFY(!myitem2.isObscuredBy(&myitem1));
+ QVERIFY(!myitem1.isObscuredBy(&myitem2));
+
+ QGraphicsRectItem rect1, rect2;
+
+ rect1.setRect(QRectF(-40, -40, 50, 50));
+ rect1.setBrush(QBrush(Qt::red));
+ rect2.setRect(QRectF(-30, -20, 20, 20));
+ rect2.setZValue(-1.0);
+ rect2.setBrush(QBrush(Qt::blue));
+
+ QVERIFY(rect2.isObscuredBy(&rect1));
+ QVERIFY(!rect1.isObscuredBy(&rect2));
+
+ rect2.setPos(QPointF(-20, -25));
+
+ QVERIFY(!rect2.isObscuredBy(&rect1));
+ QVERIFY(!rect1.isObscuredBy(&rect2));
+
+ rect2.setPos(QPointF(-100, -100));
+
+ QVERIFY(!rect2.isObscuredBy(&rect1));
+ QVERIFY(!rect1.isObscuredBy(&rect2));
+}
+
+class OpaqueItem : public QGraphicsRectItem
+{
+protected:
+ QPainterPath opaqueArea() const
+ {
+ return shape();
+ }
+};
+
+void tst_QGraphicsItem::isObscured()
+{
+ if (sizeof(qreal) != sizeof(double)) {
+ QSKIP("Skipped due to rounding errors", SkipAll);
+ }
+
+ OpaqueItem *item1 = new OpaqueItem;
+ item1->setRect(0, 0, 100, 100);
+ item1->setZValue(0);
+
+ OpaqueItem *item2 = new OpaqueItem;
+ item2->setZValue(1);
+ item2->setRect(0, 0, 100, 100);
+
+ QGraphicsScene scene;
+ scene.addItem(item1);
+ scene.addItem(item2);
+
+ QVERIFY(item1->isObscured());
+ QVERIFY(item1->isObscuredBy(item2));
+ QVERIFY(item1->isObscured(QRectF(0, 0, 50, 50)));
+ QVERIFY(item1->isObscured(QRectF(50, 0, 50, 50)));
+ QVERIFY(item1->isObscured(QRectF(50, 50, 50, 50)));
+ QVERIFY(item1->isObscured(QRectF(0, 50, 50, 50)));
+ QVERIFY(item1->isObscured(0, 0, 50, 50));
+ QVERIFY(item1->isObscured(50, 0, 50, 50));
+ QVERIFY(item1->isObscured(50, 50, 50, 50));
+ QVERIFY(item1->isObscured(0, 50, 50, 50));
+ QVERIFY(!item2->isObscured());
+ QVERIFY(!item2->isObscuredBy(item1));
+ QVERIFY(!item2->isObscured(QRectF(0, 0, 50, 50)));
+ QVERIFY(!item2->isObscured(QRectF(50, 0, 50, 50)));
+ QVERIFY(!item2->isObscured(QRectF(50, 50, 50, 50)));
+ QVERIFY(!item2->isObscured(QRectF(0, 50, 50, 50)));
+ QVERIFY(!item2->isObscured(0, 0, 50, 50));
+ QVERIFY(!item2->isObscured(50, 0, 50, 50));
+ QVERIFY(!item2->isObscured(50, 50, 50, 50));
+ QVERIFY(!item2->isObscured(0, 50, 50, 50));
+
+ item2->moveBy(50, 0);
+
+ QVERIFY(!item1->isObscured());
+ QVERIFY(!item1->isObscuredBy(item2));
+ QVERIFY(!item1->isObscured(QRectF(0, 0, 50, 50)));
+ QVERIFY(item1->isObscured(QRectF(50, 0, 50, 50)));
+ QVERIFY(item1->isObscured(QRectF(50, 50, 50, 50)));
+ QVERIFY(!item1->isObscured(QRectF(0, 50, 50, 50)));
+ QVERIFY(!item1->isObscured(0, 0, 50, 50));
+ QVERIFY(item1->isObscured(50, 0, 50, 50));
+ QVERIFY(item1->isObscured(50, 50, 50, 50));
+ QVERIFY(!item1->isObscured(0, 50, 50, 50));
+ QVERIFY(!item2->isObscured());
+ QVERIFY(!item2->isObscuredBy(item1));
+ QVERIFY(!item2->isObscured(QRectF(0, 0, 50, 50)));
+ QVERIFY(!item2->isObscured(QRectF(50, 0, 50, 50)));
+ QVERIFY(!item2->isObscured(QRectF(50, 50, 50, 50)));
+ QVERIFY(!item2->isObscured(QRectF(0, 50, 50, 50)));
+ QVERIFY(!item2->isObscured(0, 0, 50, 50));
+ QVERIFY(!item2->isObscured(50, 0, 50, 50));
+ QVERIFY(!item2->isObscured(50, 50, 50, 50));
+ QVERIFY(!item2->isObscured(0, 50, 50, 50));
+}
+
+void tst_QGraphicsItem::mapFromToParent()
+{
+ QPainterPath path1;
+ path1.addRect(0, 0, 200, 200);
+
+ QPainterPath path2;
+ path2.addRect(0, 0, 100, 100);
+
+ QPainterPath path3;
+ path3.addRect(0, 0, 50, 50);
+
+ QPainterPath path4;
+ path4.addRect(0, 0, 25, 25);
+
+ QGraphicsItem *item1 = new QGraphicsPathItem(path1);
+ QGraphicsItem *item2 = new QGraphicsPathItem(path2, item1);
+ QGraphicsItem *item3 = new QGraphicsPathItem(path3, item2);
+ QGraphicsItem *item4 = new QGraphicsPathItem(path4, item3);
+
+ item1->setPos(10, 10);
+ item2->setPos(10, 10);
+ item3->setPos(10, 10);
+ item4->setPos(10, 10);
+
+ for (int i = 0; i < 4; ++i) {
+ QMatrix matrix;
+ matrix.rotate(i * 90);
+ matrix.translate(i * 100, -i * 100);
+ matrix.scale(2, 4);
+ item1->setMatrix(matrix);
+
+ QCOMPARE(item1->mapToParent(QPointF(0, 0)), item1->pos() + matrix.map(QPointF(0, 0)));
+ QCOMPARE(item2->mapToParent(QPointF(0, 0)), item2->pos());
+ QCOMPARE(item3->mapToParent(QPointF(0, 0)), item3->pos());
+ QCOMPARE(item4->mapToParent(QPointF(0, 0)), item4->pos());
+ QCOMPARE(item1->mapToParent(QPointF(10, -10)), item1->pos() + matrix.map(QPointF(10, -10)));
+ QCOMPARE(item2->mapToParent(QPointF(10, -10)), item2->pos() + QPointF(10, -10));
+ QCOMPARE(item3->mapToParent(QPointF(10, -10)), item3->pos() + QPointF(10, -10));
+ QCOMPARE(item4->mapToParent(QPointF(10, -10)), item4->pos() + QPointF(10, -10));
+ QCOMPARE(item1->mapToParent(QPointF(-10, 10)), item1->pos() + matrix.map(QPointF(-10, 10)));
+ QCOMPARE(item2->mapToParent(QPointF(-10, 10)), item2->pos() + QPointF(-10, 10));
+ QCOMPARE(item3->mapToParent(QPointF(-10, 10)), item3->pos() + QPointF(-10, 10));
+ QCOMPARE(item4->mapToParent(QPointF(-10, 10)), item4->pos() + QPointF(-10, 10));
+ QCOMPARE(item1->mapFromParent(item1->pos()), matrix.inverted().map(QPointF(0, 0)));
+ QCOMPARE(item2->mapFromParent(item2->pos()), QPointF(0, 0));
+ QCOMPARE(item3->mapFromParent(item3->pos()), QPointF(0, 0));
+ QCOMPARE(item4->mapFromParent(item4->pos()), QPointF(0, 0));
+ QCOMPARE(item1->mapFromParent(item1->pos() + QPointF(10, -10)),
+ matrix.inverted().map(QPointF(10, -10)));
+ QCOMPARE(item2->mapFromParent(item2->pos() + QPointF(10, -10)), QPointF(10, -10));
+ QCOMPARE(item3->mapFromParent(item3->pos() + QPointF(10, -10)), QPointF(10, -10));
+ QCOMPARE(item4->mapFromParent(item4->pos() + QPointF(10, -10)), QPointF(10, -10));
+ QCOMPARE(item1->mapFromParent(item1->pos() + QPointF(-10, 10)),
+ matrix.inverted().map(QPointF(-10, 10)));
+ QCOMPARE(item2->mapFromParent(item2->pos() + QPointF(-10, 10)), QPointF(-10, 10));
+ QCOMPARE(item3->mapFromParent(item3->pos() + QPointF(-10, 10)), QPointF(-10, 10));
+ QCOMPARE(item4->mapFromParent(item4->pos() + QPointF(-10, 10)), QPointF(-10, 10));
+ }
+
+ delete item1;
+}
+
+void tst_QGraphicsItem::mapFromToScene()
+{
+ QGraphicsItem *item1 = new QGraphicsPathItem(QPainterPath());
+ QGraphicsItem *item2 = new QGraphicsPathItem(QPainterPath(), item1);
+ QGraphicsItem *item3 = new QGraphicsPathItem(QPainterPath(), item2);
+ QGraphicsItem *item4 = new QGraphicsPathItem(QPainterPath(), item3);
+
+ item1->setPos(100, 100);
+ item2->setPos(100, 100);
+ item3->setPos(100, 100);
+ item4->setPos(100, 100);
+ QCOMPARE(item1->pos(), QPointF(100, 100));
+ QCOMPARE(item2->pos(), QPointF(100, 100));
+ QCOMPARE(item3->pos(), QPointF(100, 100));
+ QCOMPARE(item4->pos(), QPointF(100, 100));
+ QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
+ QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
+ QCOMPARE(item3->pos(), item3->mapToParent(0, 0));
+ QCOMPARE(item4->pos(), item4->mapToParent(0, 0));
+ QCOMPARE(item1->mapToParent(10, 10), QPointF(110, 110));
+ QCOMPARE(item2->mapToParent(10, 10), QPointF(110, 110));
+ QCOMPARE(item3->mapToParent(10, 10), QPointF(110, 110));
+ QCOMPARE(item4->mapToParent(10, 10), QPointF(110, 110));
+ QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100));
+ QCOMPARE(item2->mapToScene(0, 0), QPointF(200, 200));
+ QCOMPARE(item3->mapToScene(0, 0), QPointF(300, 300));
+ QCOMPARE(item4->mapToScene(0, 0), QPointF(400, 400));
+ QCOMPARE(item1->mapToScene(10, 0), QPointF(110, 100));
+ QCOMPARE(item2->mapToScene(10, 0), QPointF(210, 200));
+ QCOMPARE(item3->mapToScene(10, 0), QPointF(310, 300));
+ QCOMPARE(item4->mapToScene(10, 0), QPointF(410, 400));
+ QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0));
+ QCOMPARE(item2->mapFromScene(200, 200), QPointF(0, 0));
+ QCOMPARE(item3->mapFromScene(300, 300), QPointF(0, 0));
+ QCOMPARE(item4->mapFromScene(400, 400), QPointF(0, 0));
+ QCOMPARE(item1->mapFromScene(110, 100), QPointF(10, 0));
+ QCOMPARE(item2->mapFromScene(210, 200), QPointF(10, 0));
+ QCOMPARE(item3->mapFromScene(310, 300), QPointF(10, 0));
+ QCOMPARE(item4->mapFromScene(410, 400), QPointF(10, 0));
+
+ // Rotate item1 90 degrees clockwise
+ QMatrix matrix; matrix.rotate(90);
+ item1->setMatrix(matrix);
+ QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
+ QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
+ QCOMPARE(item3->pos(), item3->mapToParent(0, 0));
+ QCOMPARE(item4->pos(), item4->mapToParent(0, 0));
+ QCOMPARE(item1->mapToParent(10, 0), QPointF(100, 110));
+ QCOMPARE(item2->mapToParent(10, 0), QPointF(110, 100));
+ QCOMPARE(item3->mapToParent(10, 0), QPointF(110, 100));
+ QCOMPARE(item4->mapToParent(10, 0), QPointF(110, 100));
+ QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100));
+ QCOMPARE(item2->mapToScene(0, 0), QPointF(0, 200));
+ QCOMPARE(item3->mapToScene(0, 0), QPointF(-100, 300));
+ QCOMPARE(item4->mapToScene(0, 0), QPointF(-200, 400));
+ QCOMPARE(item1->mapToScene(10, 0), QPointF(100, 110));
+ QCOMPARE(item2->mapToScene(10, 0), QPointF(0, 210));
+ QCOMPARE(item3->mapToScene(10, 0), QPointF(-100, 310));
+ QCOMPARE(item4->mapToScene(10, 0), QPointF(-200, 410));
+ QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0));
+ QCOMPARE(item2->mapFromScene(0, 200), QPointF(0, 0));
+ QCOMPARE(item3->mapFromScene(-100, 300), QPointF(0, 0));
+ QCOMPARE(item4->mapFromScene(-200, 400), QPointF(0, 0));
+ QCOMPARE(item1->mapFromScene(100, 110), QPointF(10, 0));
+ QCOMPARE(item2->mapFromScene(0, 210), QPointF(10, 0));
+ QCOMPARE(item3->mapFromScene(-100, 310), QPointF(10, 0));
+ QCOMPARE(item4->mapFromScene(-200, 410), QPointF(10, 0));
+
+ // Rotate item2 90 degrees clockwise
+ item2->setMatrix(matrix);
+ QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
+ QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
+ QCOMPARE(item3->pos(), item3->mapToParent(0, 0));
+ QCOMPARE(item4->pos(), item4->mapToParent(0, 0));
+ QCOMPARE(item1->mapToParent(10, 0), QPointF(100, 110));
+ QCOMPARE(item2->mapToParent(10, 0), QPointF(100, 110));
+ QCOMPARE(item3->mapToParent(10, 0), QPointF(110, 100));
+ QCOMPARE(item4->mapToParent(10, 0), QPointF(110, 100));
+ QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100));
+ QCOMPARE(item2->mapToScene(0, 0), QPointF(0, 200));
+ QCOMPARE(item3->mapToScene(0, 0), QPointF(-100, 100));
+ QCOMPARE(item4->mapToScene(0, 0), QPointF(-200, 0));
+ QCOMPARE(item1->mapToScene(10, 0), QPointF(100, 110));
+ QCOMPARE(item2->mapToScene(10, 0), QPointF(-10, 200));
+ QCOMPARE(item3->mapToScene(10, 0), QPointF(-110, 100));
+ QCOMPARE(item4->mapToScene(10, 0), QPointF(-210, 0));
+ QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0));
+ QCOMPARE(item2->mapFromScene(0, 200), QPointF(0, 0));
+ QCOMPARE(item3->mapFromScene(-100, 100), QPointF(0, 0));
+ QCOMPARE(item4->mapFromScene(-200, 0), QPointF(0, 0));
+ QCOMPARE(item1->mapFromScene(100, 110), QPointF(10, 0));
+ QCOMPARE(item2->mapFromScene(-10, 200), QPointF(10, 0));
+ QCOMPARE(item3->mapFromScene(-110, 100), QPointF(10, 0));
+ QCOMPARE(item4->mapFromScene(-210, 0), QPointF(10, 0));
+
+ // Translate item3 50 points, then rotate 90 degrees counterclockwise
+ QMatrix matrix2;
+ matrix2.translate(50, 0);
+ matrix2.rotate(-90);
+ item3->setMatrix(matrix2);
+ QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
+ QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
+ QCOMPARE(item3->pos(), item3->mapToParent(0, 0) - QPointF(50, 0));
+ QCOMPARE(item4->pos(), item4->mapToParent(0, 0));
+ QCOMPARE(item1->mapToParent(10, 0), QPointF(100, 110));
+ QCOMPARE(item2->mapToParent(10, 0), QPointF(100, 110));
+ QCOMPARE(item3->mapToParent(10, 0), QPointF(150, 90));
+ QCOMPARE(item4->mapToParent(10, 0), QPointF(110, 100));
+ QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100));
+ QCOMPARE(item2->mapToScene(0, 0), QPointF(0, 200));
+ QCOMPARE(item3->mapToScene(0, 0), QPointF(-150, 100));
+ QCOMPARE(item4->mapToScene(0, 0), QPointF(-250, 200));
+ QCOMPARE(item1->mapToScene(10, 0), QPointF(100, 110));
+ QCOMPARE(item2->mapToScene(10, 0), QPointF(-10, 200));
+ QCOMPARE(item3->mapToScene(10, 0), QPointF(-150, 110));
+ QCOMPARE(item4->mapToScene(10, 0), QPointF(-250, 210));
+ QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0));
+ QCOMPARE(item2->mapFromScene(0, 200), QPointF(0, 0));
+ QCOMPARE(item3->mapFromScene(-150, 100), QPointF(0, 0));
+ QCOMPARE(item4->mapFromScene(-250, 200), QPointF(0, 0));
+ QCOMPARE(item1->mapFromScene(100, 110), QPointF(10, 0));
+ QCOMPARE(item2->mapFromScene(-10, 200), QPointF(10, 0));
+ QCOMPARE(item3->mapFromScene(-150, 110), QPointF(10, 0));
+ QCOMPARE(item4->mapFromScene(-250, 210), QPointF(10, 0));
+
+ delete item1;
+}
+
+void tst_QGraphicsItem::mapFromToItem()
+{
+ QGraphicsItem *item1 = new QGraphicsPathItem;
+ QGraphicsItem *item2 = new QGraphicsPathItem;
+ QGraphicsItem *item3 = new QGraphicsPathItem;
+ QGraphicsItem *item4 = new QGraphicsPathItem;
+
+ item1->setPos(-100, -100);
+ item2->setPos(100, -100);
+ item3->setPos(100, 100);
+ item4->setPos(-100, 100);
+
+ QCOMPARE(item1->mapFromItem(item2, 0, 0), QPointF(200, 0));
+ QCOMPARE(item2->mapFromItem(item3, 0, 0), QPointF(0, 200));
+ QCOMPARE(item3->mapFromItem(item4, 0, 0), QPointF(-200, 0));
+ QCOMPARE(item4->mapFromItem(item1, 0, 0), QPointF(0, -200));
+ QCOMPARE(item1->mapFromItem(item4, 0, 0), QPointF(0, 200));
+ QCOMPARE(item2->mapFromItem(item1, 0, 0), QPointF(-200, 0));
+ QCOMPARE(item3->mapFromItem(item2, 0, 0), QPointF(0, -200));
+ QCOMPARE(item4->mapFromItem(item3, 0, 0), QPointF(200, 0));
+
+ QMatrix matrix;
+ matrix.translate(100, 100);
+ item1->setMatrix(matrix);
+
+ QCOMPARE(item1->mapFromItem(item2, 0, 0), QPointF(100, -100));
+ QCOMPARE(item2->mapFromItem(item3, 0, 0), QPointF(0, 200));
+ QCOMPARE(item3->mapFromItem(item4, 0, 0), QPointF(-200, 0));
+ QCOMPARE(item4->mapFromItem(item1, 0, 0), QPointF(100, -100));
+ QCOMPARE(item1->mapFromItem(item4, 0, 0), QPointF(-100, 100));
+ QCOMPARE(item2->mapFromItem(item1, 0, 0), QPointF(-100, 100));
+ QCOMPARE(item3->mapFromItem(item2, 0, 0), QPointF(0, -200));
+ QCOMPARE(item4->mapFromItem(item3, 0, 0), QPointF(200, 0));
+
+ matrix.rotate(90);
+ item1->setMatrix(matrix);
+ item2->setMatrix(matrix);
+ item3->setMatrix(matrix);
+ item4->setMatrix(matrix);
+
+ QCOMPARE(item1->mapFromItem(item2, 0, 0), QPointF(0, -200));
+ QCOMPARE(item2->mapFromItem(item3, 0, 0), QPointF(200, 0));
+ QCOMPARE(item3->mapFromItem(item4, 0, 0), QPointF(0, 200));
+ QCOMPARE(item4->mapFromItem(item1, 0, 0), QPointF(-200, 0));
+ QCOMPARE(item1->mapFromItem(item4, 0, 0), QPointF(200, 0));
+ QCOMPARE(item2->mapFromItem(item1, 0, 0), QPointF(0, 200));
+ QCOMPARE(item3->mapFromItem(item2, 0, 0), QPointF(-200, 0));
+ QCOMPARE(item4->mapFromItem(item3, 0, 0), QPointF(0, -200));
+ QCOMPARE(item1->mapFromItem(item2, 10, -5), QPointF(10, -205));
+ QCOMPARE(item2->mapFromItem(item3, 10, -5), QPointF(210, -5));
+ QCOMPARE(item3->mapFromItem(item4, 10, -5), QPointF(10, 195));
+ QCOMPARE(item4->mapFromItem(item1, 10, -5), QPointF(-190, -5));
+ QCOMPARE(item1->mapFromItem(item4, 10, -5), QPointF(210, -5));
+ QCOMPARE(item2->mapFromItem(item1, 10, -5), QPointF(10, 195));
+ QCOMPARE(item3->mapFromItem(item2, 10, -5), QPointF(-190, -5));
+ QCOMPARE(item4->mapFromItem(item3, 10, -5), QPointF(10, -205));
+
+ QCOMPARE(item1->mapFromItem(0, 10, -5), item1->mapFromScene(10, -5));
+ QCOMPARE(item2->mapFromItem(0, 10, -5), item2->mapFromScene(10, -5));
+ QCOMPARE(item3->mapFromItem(0, 10, -5), item3->mapFromScene(10, -5));
+ QCOMPARE(item4->mapFromItem(0, 10, -5), item4->mapFromScene(10, -5));
+ QCOMPARE(item1->mapToItem(0, 10, -5), item1->mapToScene(10, -5));
+ QCOMPARE(item2->mapToItem(0, 10, -5), item2->mapToScene(10, -5));
+ QCOMPARE(item3->mapToItem(0, 10, -5), item3->mapToScene(10, -5));
+ QCOMPARE(item4->mapToItem(0, 10, -5), item4->mapToScene(10, -5));
+
+ delete item1;
+ delete item2;
+ delete item3;
+ delete item4;
+}
+
+void tst_QGraphicsItem::isAncestorOf()
+{
+ QGraphicsItem *grandPa = new QGraphicsRectItem;
+ QGraphicsItem *parent = new QGraphicsRectItem;
+ QGraphicsItem *child = new QGraphicsRectItem;
+
+ QVERIFY(!parent->isAncestorOf(0));
+ QVERIFY(!child->isAncestorOf(0));
+ QVERIFY(!parent->isAncestorOf(child));
+ QVERIFY(!child->isAncestorOf(parent));
+ QVERIFY(!parent->isAncestorOf(parent));
+
+ child->setParentItem(parent);
+ parent->setParentItem(grandPa);
+
+ QVERIFY(parent->isAncestorOf(child));
+ QVERIFY(grandPa->isAncestorOf(parent));
+ QVERIFY(grandPa->isAncestorOf(child));
+ QVERIFY(!child->isAncestorOf(parent));
+ QVERIFY(!parent->isAncestorOf(grandPa));
+ QVERIFY(!child->isAncestorOf(grandPa));
+ QVERIFY(!child->isAncestorOf(child));
+ QVERIFY(!parent->isAncestorOf(parent));
+ QVERIFY(!grandPa->isAncestorOf(grandPa));
+
+ parent->setParentItem(0);
+
+ delete child;
+ delete parent;
+ delete grandPa;
+}
+
+void tst_QGraphicsItem::commonAncestorItem()
+{
+ QGraphicsItem *ancestor = new QGraphicsRectItem;
+ QGraphicsItem *grandMa = new QGraphicsRectItem;
+ QGraphicsItem *grandPa = new QGraphicsRectItem;
+ QGraphicsItem *brotherInLaw = new QGraphicsRectItem;
+ QGraphicsItem *cousin = new QGraphicsRectItem;
+ QGraphicsItem *husband = new QGraphicsRectItem;
+ QGraphicsItem *child = new QGraphicsRectItem;
+ QGraphicsItem *wife = new QGraphicsRectItem;
+
+ child->setParentItem(husband);
+ husband->setParentItem(grandPa);
+ brotherInLaw->setParentItem(grandPa);
+ cousin->setParentItem(brotherInLaw);
+ wife->setParentItem(grandMa);
+ grandMa->setParentItem(ancestor);
+ grandPa->setParentItem(ancestor);
+
+ QCOMPARE(grandMa->commonAncestorItem(grandMa), grandMa);
+ QCOMPARE(grandMa->commonAncestorItem(0), (QGraphicsItem *)0);
+ QCOMPARE(grandMa->commonAncestorItem(grandPa), ancestor);
+ QCOMPARE(grandPa->commonAncestorItem(grandMa), ancestor);
+ QCOMPARE(grandPa->commonAncestorItem(husband), grandPa);
+ QCOMPARE(grandPa->commonAncestorItem(wife), ancestor);
+ QCOMPARE(grandMa->commonAncestorItem(husband), ancestor);
+ QCOMPARE(grandMa->commonAncestorItem(wife), grandMa);
+ QCOMPARE(wife->commonAncestorItem(grandMa), grandMa);
+ QCOMPARE(child->commonAncestorItem(cousin), grandPa);
+ QCOMPARE(cousin->commonAncestorItem(child), grandPa);
+ QCOMPARE(wife->commonAncestorItem(child), ancestor);
+ QCOMPARE(child->commonAncestorItem(wife), ancestor);
+}
+
+void tst_QGraphicsItem::data()
+{
+ QGraphicsTextItem text;
+
+ QCOMPARE(text.data(0), QVariant());
+ text.setData(0, "TextItem");
+ QCOMPARE(text.data(0), QVariant(QString("TextItem")));
+ text.setData(0, QVariant());
+ QCOMPARE(text.data(0), QVariant());
+}
+
+void tst_QGraphicsItem::type()
+{
+ QCOMPARE(int(QGraphicsItem::Type), 1);
+ QCOMPARE(int(QGraphicsPathItem::Type), 2);
+ QCOMPARE(int(QGraphicsRectItem::Type), 3);
+ QCOMPARE(int(QGraphicsEllipseItem::Type), 4);
+ QCOMPARE(int(QGraphicsPolygonItem::Type), 5);
+ QCOMPARE(int(QGraphicsLineItem::Type), 6);
+ QCOMPARE(int(QGraphicsPixmapItem::Type), 7);
+ QCOMPARE(int(QGraphicsTextItem::Type), 8);
+
+ QCOMPARE(QGraphicsPathItem().type(), 2);
+ QCOMPARE(QGraphicsRectItem().type(), 3);
+ QCOMPARE(QGraphicsEllipseItem().type(), 4);
+ QCOMPARE(QGraphicsPolygonItem().type(), 5);
+ QCOMPARE(QGraphicsLineItem().type(), 6);
+ QCOMPARE(QGraphicsPixmapItem().type(), 7);
+ QCOMPARE(QGraphicsTextItem().type(), 8);
+}
+
+void tst_QGraphicsItem::graphicsitem_cast()
+{
+ QGraphicsPathItem pathItem;
+ const QGraphicsPathItem *pPathItem = &pathItem;
+ QGraphicsRectItem rectItem;
+ const QGraphicsRectItem *pRectItem = &rectItem;
+ QGraphicsEllipseItem ellipseItem;
+ const QGraphicsEllipseItem *pEllipseItem = &ellipseItem;
+ QGraphicsPolygonItem polygonItem;
+ const QGraphicsPolygonItem *pPolygonItem = &polygonItem;
+ QGraphicsLineItem lineItem;
+ const QGraphicsLineItem *pLineItem = &lineItem;
+ QGraphicsPixmapItem pixmapItem;
+ const QGraphicsPixmapItem *pPixmapItem = &pixmapItem;
+ QGraphicsTextItem textItem;
+ const QGraphicsTextItem *pTextItem = &textItem;
+
+ QVERIFY(qgraphicsitem_cast<QGraphicsPathItem *>(&pathItem));
+ //QVERIFY(qgraphicsitem_cast<QAbstractGraphicsPathItem *>(&pathItem));
+ QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&pathItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pPathItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsPathItem *>(pPathItem));
+
+ QVERIFY(qgraphicsitem_cast<QGraphicsRectItem *>(&rectItem));
+ QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&rectItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pRectItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsRectItem *>(pRectItem));
+
+ QVERIFY(qgraphicsitem_cast<QGraphicsEllipseItem *>(&ellipseItem));
+ QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&ellipseItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pEllipseItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsEllipseItem *>(pEllipseItem));
+
+ QVERIFY(qgraphicsitem_cast<QGraphicsPolygonItem *>(&polygonItem));
+ //QVERIFY(qgraphicsitem_cast<QAbstractGraphicsPathItem *>(&polygonItem));
+ QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&polygonItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pPolygonItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsPolygonItem *>(pPolygonItem));
+
+ QVERIFY(qgraphicsitem_cast<QGraphicsLineItem *>(&lineItem));
+ QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&lineItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pLineItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsLineItem *>(pLineItem));
+
+ QVERIFY(qgraphicsitem_cast<QGraphicsPixmapItem *>(&pixmapItem));
+ QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&pixmapItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pPixmapItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsPixmapItem *>(pPixmapItem));
+
+ QVERIFY(qgraphicsitem_cast<QGraphicsTextItem *>(&textItem));
+ QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&textItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pTextItem));
+ QVERIFY(qgraphicsitem_cast<const QGraphicsTextItem *>(pTextItem));
+
+ // and some casts that _should_ fail:
+ QVERIFY(!qgraphicsitem_cast<QGraphicsEllipseItem *>(&pathItem));
+ QVERIFY(!qgraphicsitem_cast<const QGraphicsTextItem *>(pPolygonItem));
+
+ // and this shouldn't crash
+ QGraphicsItem *ptr = 0;
+ QVERIFY(!qgraphicsitem_cast<QGraphicsTextItem *>(ptr));
+ QVERIFY(!qgraphicsitem_cast<QGraphicsItem *>(ptr));
+}
+
+void tst_QGraphicsItem::hoverEventsGenerateRepaints()
+{
+ Q_CHECK_PAINTEVENTS
+
+ QGraphicsScene scene;
+ EventTester *tester = new EventTester;
+ scene.addItem(tester);
+ tester->setAcceptsHoverEvents(true);
+
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+
+ qApp->processEvents();
+ qApp->processEvents();
+
+
+ // Send a hover enter event
+ QGraphicsSceneHoverEvent hoverEnterEvent(QEvent::GraphicsSceneHoverEnter);
+ hoverEnterEvent.setScenePos(QPointF(0, 0));
+ hoverEnterEvent.setPos(QPointF(0, 0));
+ QApplication::sendEvent(&scene, &hoverEnterEvent);
+
+ // Check that we get a repaint
+ int npaints = tester->repaints;
+ qApp->processEvents();
+ qApp->processEvents();
+ QCOMPARE(tester->events.size(), 2); // enter + move
+ QCOMPARE(tester->repaints, npaints + 1);
+ QCOMPARE(tester->events.last(), QEvent::GraphicsSceneHoverMove);
+
+ // Send a hover move event
+ QGraphicsSceneHoverEvent hoverMoveEvent(QEvent::GraphicsSceneHoverMove);
+ hoverMoveEvent.setScenePos(QPointF(0, 0));
+ hoverMoveEvent.setPos(QPointF(0, 0));
+ QApplication::sendEvent(&scene, &hoverMoveEvent);
+
+ // Check that we don't get a repaint
+ qApp->processEvents();
+ qApp->processEvents();
+
+ QCOMPARE(tester->events.size(), 3);
+ QCOMPARE(tester->repaints, npaints + 1);
+ QCOMPARE(tester->events.last(), QEvent::GraphicsSceneHoverMove);
+
+ // Send a hover leave event
+ QGraphicsSceneHoverEvent hoverLeaveEvent(QEvent::GraphicsSceneHoverLeave);
+ hoverLeaveEvent.setScenePos(QPointF(-100, -100));
+ hoverLeaveEvent.setPos(QPointF(0, 0));
+ QApplication::sendEvent(&scene, &hoverLeaveEvent);
+
+ // Check that we get a repaint
+ qApp->processEvents();
+ qApp->processEvents();
+
+ QCOMPARE(tester->events.size(), 4);
+ QCOMPARE(tester->repaints, npaints + 2);
+ QCOMPARE(tester->events.last(), QEvent::GraphicsSceneHoverLeave);
+}
+
+void tst_QGraphicsItem::boundingRects_data()
+{
+ QTest::addColumn<QGraphicsItem *>("item");
+ QTest::addColumn<QRectF>("boundingRect");
+
+ QRectF rect(0, 0, 100, 100);
+ QPainterPath path;
+ path.addRect(rect);
+
+ QRectF adjustedRect(-0.5, -0.5, 101, 101);
+
+ QTest::newRow("path") << (QGraphicsItem *)new QGraphicsPathItem(path) << adjustedRect;
+ QTest::newRow("rect") << (QGraphicsItem *)new QGraphicsRectItem(rect) << adjustedRect;
+ QTest::newRow("ellipse") << (QGraphicsItem *)new QGraphicsEllipseItem(rect) << adjustedRect;
+ QTest::newRow("polygon") << (QGraphicsItem *)new QGraphicsPolygonItem(rect) << adjustedRect;
+}
+
+void tst_QGraphicsItem::boundingRects()
+{
+ QFETCH(QGraphicsItem *, item);
+ QFETCH(QRectF, boundingRect);
+
+ ((QAbstractGraphicsShapeItem *)item)->setPen(QPen(Qt::black, 1));
+ QCOMPARE(item->boundingRect(), boundingRect);
+}
+
+void tst_QGraphicsItem::boundingRects2()
+{
+ QGraphicsPixmapItem pixmap(QPixmap::fromImage(QImage(100, 100, QImage::Format_ARGB32_Premultiplied)));
+ QCOMPARE(pixmap.boundingRect(), QRectF(-0.5, -0.5, 101, 101));
+
+ QGraphicsLineItem line(0, 0, 100, 0);
+ line.setPen(QPen(Qt::black, 1));
+ QCOMPARE(line.boundingRect(), QRectF(-0.5, -0.5, 101, 1));
+}
+
+void tst_QGraphicsItem::sceneBoundingRect()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *item = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
+ item->setPos(100, 100);
+
+ QCOMPARE(item->boundingRect(), QRectF(0, 0, 100, 100));
+ QCOMPARE(item->sceneBoundingRect(), QRectF(100, 100, 100, 100));
+
+ item->rotate(90);
+
+ QCOMPARE(item->boundingRect(), QRectF(0, 0, 100, 100));
+ QCOMPARE(item->sceneBoundingRect(), QRectF(0, 100, 100, 100));
+}
+
+void tst_QGraphicsItem::childrenBoundingRect()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *parent = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
+ QGraphicsRectItem *child = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
+ child->setParentItem(parent);
+ parent->setPos(100, 100);
+ child->setPos(100, 100);
+
+ QCOMPARE(parent->boundingRect(), QRectF(0, 0, 100, 100));
+ QCOMPARE(child->boundingRect(), QRectF(0, 0, 100, 100));
+ QCOMPARE(child->childrenBoundingRect(), QRectF());
+ QCOMPARE(parent->childrenBoundingRect(), QRectF(100, 100, 100, 100));
+
+ QGraphicsRectItem *child2 = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
+ child2->setParentItem(parent);
+ child2->setPos(-100, -100);
+ QCOMPARE(parent->childrenBoundingRect(), QRectF(-100, -100, 300, 300));
+
+ QGraphicsRectItem *childChild = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
+ childChild->setParentItem(child);
+ childChild->setPos(500, 500);
+ child->rotate(90);
+ QCOMPARE(parent->childrenBoundingRect(), QRectF(-500, -100, 600, 800));
+}
+
+void tst_QGraphicsItem::group()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *parent = scene.addRect(QRectF(0, 0, 50, 50), QPen(Qt::black, 0), QBrush(Qt::green));
+ QGraphicsRectItem *child = scene.addRect(QRectF(0, 0, 50, 50), QPen(Qt::black, 0), QBrush(Qt::blue));
+ QGraphicsRectItem *parent2 = scene.addRect(QRectF(0, 0, 50, 50), QPen(Qt::black, 0), QBrush(Qt::red));
+ parent2->setPos(-50, 50);
+ child->rotate(45);
+ child->setParentItem(parent);
+ parent->setPos(25, 25);
+ child->setPos(25, 25);
+
+ QCOMPARE(parent->group(), (QGraphicsItemGroup *)0);
+ QCOMPARE(parent2->group(), (QGraphicsItemGroup *)0);
+ QCOMPARE(child->group(), (QGraphicsItemGroup *)0);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWait(250);
+
+ QGraphicsItemGroup *group = new QGraphicsItemGroup;
+ group->setSelected(true);
+ scene.addItem(group);
+
+ QRectF parentSceneBoundingRect = parent->sceneBoundingRect();
+ group->addToGroup(parent);
+ QCOMPARE(parent->group(), group);
+ QCOMPARE(parent->sceneBoundingRect(), parentSceneBoundingRect);
+
+ QCOMPARE(parent->parentItem(), (QGraphicsItem *)group);
+ QCOMPARE(group->children().size(), 1);
+ QCOMPARE(scene.items().size(), 4);
+ QCOMPARE(scene.items(group->sceneBoundingRect()).size(), 3);
+
+ QTest::qWait(250);
+
+ QRectF parent2SceneBoundingRect = parent2->sceneBoundingRect();
+ group->addToGroup(parent2);
+ QCOMPARE(parent2->group(), group);
+ QCOMPARE(parent2->sceneBoundingRect(), parent2SceneBoundingRect);
+
+ QCOMPARE(parent2->parentItem(), (QGraphicsItem *)group);
+ QCOMPARE(group->children().size(), 2);
+ QCOMPARE(scene.items().size(), 4);
+ QCOMPARE(scene.items(group->sceneBoundingRect()).size(), 4);
+
+ QTest::qWait(250);
+
+ QList<QGraphicsItem *> newItems;
+ for (int i = 0; i < 100; ++i) {
+ QGraphicsItem *item = scene.addRect(QRectF(-25, -25, 50, 50), QPen(Qt::black, 0),
+ QBrush(QColor(rand() % 255, rand() % 255,
+ rand() % 255, rand() % 255)));
+ newItems << item;
+ item->setPos(-1000 + rand() % 2000,
+ -1000 + rand() % 2000);
+ item->rotate(rand() % 90);
+ }
+
+ view.fitInView(scene.itemsBoundingRect());
+
+ int n = 0;
+ foreach (QGraphicsItem *item, newItems) {
+ group->addToGroup(item);
+ QCOMPARE(item->group(), group);
+ if ((n++ % 100) == 0)
+ QTest::qWait(10);
+ }
+}
+
+void tst_QGraphicsItem::setGroup()
+{
+ QGraphicsItemGroup group1;
+ QGraphicsItemGroup group2;
+
+ QGraphicsRectItem *rect = new QGraphicsRectItem;
+ QCOMPARE(rect->group(), (QGraphicsItemGroup *)0);
+ QCOMPARE(rect->parentItem(), (QGraphicsItem *)0);
+ rect->setGroup(&group1);
+ QCOMPARE(rect->group(), &group1);
+ QCOMPARE(rect->parentItem(), (QGraphicsItem *)&group1);
+ rect->setGroup(&group2);
+ QCOMPARE(rect->group(), &group2);
+ QCOMPARE(rect->parentItem(), (QGraphicsItem *)&group2);
+ rect->setGroup(0);
+ QCOMPARE(rect->group(), (QGraphicsItemGroup *)0);
+ QCOMPARE(rect->parentItem(), (QGraphicsItem *)0);
+}
+
+void tst_QGraphicsItem::nestedGroups()
+{
+ QGraphicsItemGroup *group1 = new QGraphicsItemGroup;
+ QGraphicsItemGroup *group2 = new QGraphicsItemGroup;
+
+ QGraphicsRectItem *rect = new QGraphicsRectItem;
+ QGraphicsRectItem *rect2 = new QGraphicsRectItem;
+ rect2->setParentItem(rect);
+
+ group1->addToGroup(rect);
+ QCOMPARE(rect->group(), group1);
+ QCOMPARE(rect2->group(), group1);
+
+ group2->addToGroup(group1);
+ QCOMPARE(rect->group(), group1);
+ QCOMPARE(rect2->group(), group1);
+ QCOMPARE(group1->group(), group2);
+ QCOMPARE(group2->group(), (QGraphicsItemGroup *)0);
+
+ QGraphicsScene scene;
+ scene.addItem(group1);
+
+ QCOMPARE(rect->group(), group1);
+ QCOMPARE(rect2->group(), group1);
+ QCOMPARE(group1->group(), (QGraphicsItemGroup *)0);
+ QVERIFY(group2->children().isEmpty());
+
+ delete group2;
+}
+
+void tst_QGraphicsItem::warpChildrenIntoGroup()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *parentRectItem = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *childRectItem = scene.addRect(QRectF(0, 0, 100, 100));
+ parentRectItem->rotate(90);
+ childRectItem->setPos(-50, -25);
+ childRectItem->setParentItem(parentRectItem);
+
+ QCOMPARE(childRectItem->mapToScene(50, 0), QPointF(25, 0));
+ QCOMPARE(childRectItem->scenePos(), QPointF(25, -50));
+
+ QGraphicsRectItem *parentOfGroup = scene.addRect(QRectF(0, 0, 100, 100));
+ parentOfGroup->setPos(-200, -200);
+ parentOfGroup->scale(2, 2);
+
+ QGraphicsItemGroup *group = new QGraphicsItemGroup;
+ group->setPos(50, 50);
+ group->setParentItem(parentOfGroup);
+
+ QCOMPARE(group->scenePos(), QPointF(-100, -100));
+
+ group->addToGroup(childRectItem);
+
+ QCOMPARE(childRectItem->mapToScene(50, 0), QPointF(25, 0));
+ QCOMPARE(childRectItem->scenePos(), QPointF(25, -50));
+}
+
+void tst_QGraphicsItem::removeFromGroup()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect1 = scene.addRect(QRectF(-100, -100, 200, 200));
+ QGraphicsRectItem *rect2 = scene.addRect(QRectF(100, 100, 200, 200));
+ rect1->setFlag(QGraphicsItem::ItemIsSelectable);
+ rect2->setFlag(QGraphicsItem::ItemIsSelectable);
+ rect1->setSelected(true);
+ rect2->setSelected(true);
+
+ QGraphicsView view(&scene);
+ view.show();
+
+ qApp->processEvents(); // index items
+ qApp->processEvents(); // emit changed
+
+ QGraphicsItemGroup *group = scene.createItemGroup(scene.selectedItems());
+ QVERIFY(group);
+ QCOMPARE(group->children().size(), 2);
+ qApp->processEvents(); // index items
+ qApp->processEvents(); // emit changed
+
+ scene.destroyItemGroup(group); // calls removeFromGroup.
+
+ qApp->processEvents(); // index items
+ qApp->processEvents(); // emit changed
+
+ QCOMPARE(scene.items().size(), 2);
+ QVERIFY(!rect1->group());
+ QVERIFY(!rect2->group());
+}
+
+class ChildEventTester : public QGraphicsRectItem
+{
+public:
+ ChildEventTester(const QRectF &rect, QGraphicsItem *parent = 0)
+ : QGraphicsRectItem(rect, parent), counter(0)
+ { }
+
+ int counter;
+
+protected:
+ void focusInEvent(QFocusEvent *event)
+ { ++counter; QGraphicsRectItem::focusInEvent(event); }
+ void mousePressEvent(QGraphicsSceneMouseEvent *)
+ { ++counter; }
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *)
+ { ++counter; }
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *)
+ { ++counter; }
+};
+void tst_QGraphicsItem::handlesChildEvents()
+{
+ ChildEventTester *item2_level2 = new ChildEventTester(QRectF(0, 0, 25, 25));
+ ChildEventTester *item1_level1 = new ChildEventTester(QRectF(0, 0, 50, 50));
+ ChildEventTester *item_level0 = new ChildEventTester(QRectF(0, 0, 100, 100));
+ ChildEventTester *item1_level2 = new ChildEventTester(QRectF(0, 0, 25, 25));
+ ChildEventTester *item2_level1 = new ChildEventTester(QRectF(0, 0, 50, 50));
+
+ item_level0->setBrush(QBrush(Qt::blue));
+ item1_level1->setBrush(QBrush(Qt::red));
+ item2_level1->setBrush(QBrush(Qt::yellow));
+ item1_level2->setBrush(QBrush(Qt::green));
+ item2_level2->setBrush(QBrush(Qt::gray));
+ item1_level1->setPos(50, 0);
+ item2_level1->setPos(50, 50);
+ item1_level2->setPos(25, 0);
+ item2_level2->setPos(25, 25);
+ item1_level1->setParentItem(item_level0);
+ item2_level1->setParentItem(item_level0);
+ item1_level2->setParentItem(item1_level1);
+ item2_level2->setParentItem(item1_level1);
+
+ QGraphicsScene scene;
+ scene.addItem(item_level0);
+
+ // Pull out the items, closest item first
+ QList<QGraphicsItem *> items = scene.items(scene.itemsBoundingRect());
+ QCOMPARE(items.at(4), (QGraphicsItem *)item_level0);
+ if (item1_level1 < item2_level1) {
+ QCOMPARE(items.at(3), (QGraphicsItem *)item1_level1);
+ if (item1_level2 < item2_level2) {
+ QCOMPARE(items.at(2), (QGraphicsItem *)item1_level2);
+ QCOMPARE(items.at(1), (QGraphicsItem *)item2_level2);
+ } else {
+ QCOMPARE(items.at(2), (QGraphicsItem *)item2_level2);
+ QCOMPARE(items.at(1), (QGraphicsItem *)item1_level2);
+ }
+ QCOMPARE(items.at(0), (QGraphicsItem *)item2_level1);
+ } else {
+ QCOMPARE(items.at(3), (QGraphicsItem *)item2_level1);
+ QCOMPARE(items.at(2), (QGraphicsItem *)item1_level1);
+ if (item1_level2 < item2_level2) {
+ QCOMPARE(items.at(1), (QGraphicsItem *)item1_level2);
+ QCOMPARE(items.at(0), (QGraphicsItem *)item2_level2);
+ } else {
+ QCOMPARE(items.at(1), (QGraphicsItem *)item2_level2);
+ QCOMPARE(items.at(0), (QGraphicsItem *)item1_level2);
+ }
+ }
+
+ QGraphicsView view(&scene);
+ view.show();
+
+ QTest::qWait(1000);
+
+ QCOMPARE(item_level0->counter, 0);
+
+ // Send events to the toplevel item
+ QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
+ QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
+
+ pressEvent.setButton(Qt::LeftButton);
+ pressEvent.setScenePos(item_level0->mapToScene(5, 5));
+ pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ releaseEvent.setButton(Qt::LeftButton);
+ releaseEvent.setScenePos(item_level0->mapToScene(5, 5));
+ releaseEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(item_level0->counter, 2);
+
+ // Send events to a level1 item
+ pressEvent.setScenePos(item1_level1->mapToScene(5, 5));
+ pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ releaseEvent.setScenePos(item1_level1->mapToScene(5, 5));
+ releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(item_level0->counter, 2);
+ QCOMPARE(item1_level1->counter, 2);
+
+ // Send events to a level2 item
+ pressEvent.setScenePos(item1_level2->mapToScene(5, 5));
+ pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ releaseEvent.setScenePos(item1_level2->mapToScene(5, 5));
+ releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(item_level0->counter, 2);
+ QCOMPARE(item1_level1->counter, 2);
+ QCOMPARE(item1_level2->counter, 2);
+
+ item_level0->setHandlesChildEvents(true);
+
+ // Send events to a level1 item
+ pressEvent.setScenePos(item1_level1->mapToScene(5, 5));
+ pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ releaseEvent.setScenePos(item1_level1->mapToScene(5, 5));
+ releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(item_level0->counter, 4);
+ QCOMPARE(item1_level1->counter, 2);
+
+ // Send events to a level2 item
+ pressEvent.setScenePos(item1_level2->mapToScene(5, 5));
+ pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ releaseEvent.setScenePos(item1_level2->mapToScene(5, 5));
+ releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(item_level0->counter, 6);
+ QCOMPARE(item1_level1->counter, 2);
+ QCOMPARE(item1_level2->counter, 2);
+
+ item_level0->setHandlesChildEvents(false);
+
+ // Send events to a level1 item
+ pressEvent.setScenePos(item1_level1->mapToScene(5, 5));
+ pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ releaseEvent.setScenePos(item1_level1->mapToScene(5, 5));
+ releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(item_level0->counter, 6);
+ QCOMPARE(item1_level1->counter, 4);
+
+ // Send events to a level2 item
+ pressEvent.setScenePos(item1_level2->mapToScene(5, 5));
+ pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ releaseEvent.setScenePos(item1_level2->mapToScene(5, 5));
+ releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(item_level0->counter, 6);
+ QCOMPARE(item1_level1->counter, 4);
+ QCOMPARE(item1_level2->counter, 4);
+}
+
+void tst_QGraphicsItem::handlesChildEvents2()
+{
+ ChildEventTester *root = new ChildEventTester(QRectF(0, 0, 10, 10));
+ root->setHandlesChildEvents(true);
+ QVERIFY(root->handlesChildEvents());
+
+ ChildEventTester *child = new ChildEventTester(QRectF(0, 0, 10, 10), root);
+ QVERIFY(!child->handlesChildEvents());
+
+ ChildEventTester *child2 = new ChildEventTester(QRectF(0, 0, 10, 10));
+ ChildEventTester *child3 = new ChildEventTester(QRectF(0, 0, 10, 10), child2);
+ ChildEventTester *child4 = new ChildEventTester(QRectF(0, 0, 10, 10), child3);
+ child2->setParentItem(root);
+ QVERIFY(!child2->handlesChildEvents());
+ QVERIFY(!child3->handlesChildEvents());
+ QVERIFY(!child4->handlesChildEvents());
+
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ QGraphicsView view(&scene);
+ view.show();
+
+ QTestEventLoop::instance().enterLoop(1);
+
+ QMouseEvent event(QEvent::MouseButtonPress, view.mapFromScene(5, 5),
+ view.viewport()->mapToGlobal(view.mapFromScene(5, 5)), Qt::LeftButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &event);
+
+ QCOMPARE(root->counter, 1);
+}
+
+void tst_QGraphicsItem::handlesChildEvents3()
+{
+ QGraphicsScene scene;
+ ChildEventTester *group2 = new ChildEventTester(QRectF(), 0);
+ ChildEventTester *group1 = new ChildEventTester(QRectF(), group2);
+ ChildEventTester *leaf = new ChildEventTester(QRectF(), group1);
+ scene.addItem(group2);
+
+ leaf->setFlag(QGraphicsItem::ItemIsFocusable);
+ group1->setFlag(QGraphicsItem::ItemIsFocusable);
+ group1->setHandlesChildEvents(true);
+ group2->setFlag(QGraphicsItem::ItemIsFocusable);
+ group2->setHandlesChildEvents(true);
+
+ leaf->setFocus();
+ QVERIFY(leaf->hasFocus()); // group2 stole the event, but leaf still got focus
+ QVERIFY(!group1->hasFocus());
+ QVERIFY(!group2->hasFocus());
+ QCOMPARE(leaf->counter, 0);
+ QCOMPARE(group1->counter, 0);
+ QCOMPARE(group2->counter, 1);
+
+ group1->setFocus();
+ QVERIFY(group1->hasFocus()); // group2 stole the event, but group1 still got focus
+ QVERIFY(!leaf->hasFocus());
+ QVERIFY(!group2->hasFocus());
+ QCOMPARE(leaf->counter, 0);
+ QCOMPARE(group1->counter, 0);
+ QCOMPARE(group2->counter, 2);
+
+ group2->setFocus();
+ QVERIFY(group2->hasFocus()); // group2 stole the event, and now group2 also has focus
+ QVERIFY(!leaf->hasFocus());
+ QVERIFY(!group1->hasFocus());
+ QCOMPARE(leaf->counter, 0);
+ QCOMPARE(group1->counter, 0);
+ QCOMPARE(group2->counter, 3);
+}
+
+class CustomItem : public QGraphicsItem
+{
+public:
+ QRectF boundingRect() const
+ { return QRectF(-110, -110, 220, 220); }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ {
+ for (int x = -100; x <= 100; x += 25)
+ painter->drawLine(x, -100, x, 100);
+ for (int y = -100; y <= 100; y += 25)
+ painter->drawLine(-100, y, 100, y);
+
+ QFont font = painter->font();
+ font.setPointSize(4);
+ painter->setFont(font);
+ for (int x = -100; x < 100; x += 25) {
+ for (int y = -100; y < 100; y += 25) {
+ painter->drawText(QRectF(x, y, 25, 25), Qt::AlignCenter, QString("%1x%2").arg(x).arg(y));
+ }
+ }
+ }
+};
+
+void tst_QGraphicsItem::ensureVisible()
+{
+ QGraphicsScene scene;
+ scene.setSceneRect(-200, -200, 400, 400);
+ QGraphicsItem *item = new CustomItem;
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(300, 300);
+ view.show();
+
+ for (int i = 0; i < 25; ++i) {
+ view.scale(qreal(1.06), qreal(1.06));
+ QTest::qWait(25);
+ }
+
+ item->ensureVisible(-100, -100, 25, 25);
+ QTest::qWait(250);
+
+ for (int x = -100; x < 100; x += 25) {
+ for (int y = -100; y < 100; y += 25) {
+ int xmargin = rand() % 75;
+ int ymargin = rand() % 75;
+ item->ensureVisible(x, y, 25, 25, xmargin, ymargin);
+ QTest::qWait(25);
+
+ QPolygonF viewScenePoly;
+ viewScenePoly << view.mapToScene(view.rect().topLeft())
+ << view.mapToScene(view.rect().topRight())
+ << view.mapToScene(view.rect().bottomRight())
+ << view.mapToScene(view.rect().bottomLeft());
+
+ QVERIFY(scene.items(viewScenePoly).contains(item));
+
+ QPainterPath path;
+ path.addPolygon(viewScenePoly);
+ QVERIFY(path.contains(item->mapToScene(x + 12, y + 12)));
+
+ QPolygonF viewScenePolyMinusMargins;
+ viewScenePolyMinusMargins << view.mapToScene(view.rect().topLeft() + QPoint(xmargin, ymargin))
+ << view.mapToScene(view.rect().topRight() + QPoint(-xmargin, ymargin))
+ << view.mapToScene(view.rect().bottomRight() + QPoint(-xmargin, -ymargin))
+ << view.mapToScene(view.rect().bottomLeft() + QPoint(xmargin, -ymargin));
+
+ QPainterPath path2;
+ path2.addPolygon(viewScenePolyMinusMargins);
+ QVERIFY(path2.contains(item->mapToScene(x + 12, y + 12)));
+ }
+ }
+
+ item->ensureVisible(100, 100, 25, 25);
+ QTest::qWait(250);
+}
+
+void tst_QGraphicsItem::cursor()
+{
+#ifndef QT_NO_CURSOR
+ QGraphicsScene scene;
+ QGraphicsRectItem *item1 = scene.addRect(QRectF(0, 0, 50, 50));
+ QGraphicsRectItem *item2 = scene.addRect(QRectF(0, 0, 50, 50));
+ item1->setPos(-100, 0);
+ item2->setPos(50, 0);
+
+ QVERIFY(!item1->hasCursor());
+ QVERIFY(!item2->hasCursor());
+
+ item1->setCursor(Qt::IBeamCursor);
+ item2->setCursor(Qt::PointingHandCursor);
+
+ QVERIFY(item1->hasCursor());
+ QVERIFY(item2->hasCursor());
+
+ item1->setCursor(QCursor());
+ item2->setCursor(QCursor());
+
+ QVERIFY(item1->hasCursor());
+ QVERIFY(item2->hasCursor());
+
+ item1->unsetCursor();
+ item2->unsetCursor();
+
+ QVERIFY(!item1->hasCursor());
+ QVERIFY(!item2->hasCursor());
+
+ item1->setCursor(Qt::IBeamCursor);
+ item2->setCursor(Qt::PointingHandCursor);
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(200, 100);
+ view.show();
+ QTest::mouseMove(&view, view.rect().center());
+
+ QTest::qWait(250);
+
+ QCursor cursor = view.viewport()->cursor();
+
+ {
+ QMouseEvent event(QEvent::MouseMove, QPoint(100, 50), Qt::NoButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &event);
+ }
+
+ QTest::qWait(250);
+
+ QCOMPARE(view.viewport()->cursor().shape(), cursor.shape());
+
+ {
+ QTest::mouseMove(view.viewport(), view.mapFromScene(item1->sceneBoundingRect().center()));
+ QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item1->sceneBoundingRect().center()), Qt::NoButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &event);
+ }
+
+#if !defined(Q_OS_WINCE)
+ QTest::qWait(250);
+#else
+ // Test environment does not have any cursor, therefore no shape
+ return;
+#endif
+
+ QCOMPARE(view.viewport()->cursor().shape(), item1->cursor().shape());
+
+ {
+ QTest::mouseMove(view.viewport(), view.mapFromScene(item2->sceneBoundingRect().center()));
+ QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item2->sceneBoundingRect().center()), Qt::NoButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &event);
+ }
+
+ QTest::qWait(250);
+
+ QCOMPARE(view.viewport()->cursor().shape(), item2->cursor().shape());
+
+ {
+ QTest::mouseMove(view.viewport(), view.rect().center());
+ QMouseEvent event(QEvent::MouseMove, QPoint(100, 25), Qt::NoButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &event);
+ }
+
+ QTest::qWait(250);
+
+ QCOMPARE(view.viewport()->cursor().shape(), cursor.shape());
+#endif
+}
+/*
+void tst_QGraphicsItem::textControlGetterSetter()
+{
+ QGraphicsTextItem *item = new QGraphicsTextItem;
+ QVERIFY(item->textControl()->parent() == item);
+ QPointer<QTextControl> control = item->textControl();
+ delete item;
+ QVERIFY(!control);
+
+ item = new QGraphicsTextItem;
+
+ QPointer<QTextControl> oldControl = control;
+ control = new QTextControl;
+
+ item->setTextControl(control);
+ QVERIFY(item->textControl() == control);
+ QVERIFY(!control->parent());
+ QVERIFY(!oldControl);
+
+ // set some text to give it a size, to test that
+ // setTextControl (re)connects signals
+ const QRectF oldBoundingRect = item->boundingRect();
+ QVERIFY(oldBoundingRect.isValid());
+ item->setPlainText("Some text");
+ item->adjustSize();
+ QVERIFY(item->boundingRect().isValid());
+ QVERIFY(item->boundingRect() != oldBoundingRect);
+
+ // test that on setting a control the item size
+ // is adjusted
+ oldControl = control;
+ control = new QTextControl;
+ control->setPlainText("foo!");
+ item->setTextControl(control);
+ QCOMPARE(item->boundingRect().size(), control->document()->documentLayout()->documentSize());
+
+ QVERIFY(oldControl);
+ delete oldControl;
+
+ delete item;
+ QVERIFY(control);
+ delete control;
+}
+*/
+
+void tst_QGraphicsItem::defaultItemTest_QGraphicsLineItem()
+{
+ QGraphicsLineItem item;
+ QCOMPARE(item.line(), QLineF());
+ QCOMPARE(item.pen(), QPen());
+ QCOMPARE(item.shape(), QPainterPath());
+
+ item.setPen(QPen(Qt::black, 1));
+ QCOMPARE(item.pen(), QPen(Qt::black, 1));
+ item.setLine(QLineF(0, 0, 10, 0));
+ QCOMPARE(item.line(), QLineF(0, 0, 10, 0));
+ QCOMPARE(item.boundingRect(), QRectF(-0.5, -0.5, 11, 1));
+ QCOMPARE(item.shape().elementCount(), 11);
+
+ QPainterPath path;
+ path.moveTo(0, -0.5);
+ path.lineTo(10, -0.5);
+ path.lineTo(10.5, -0.5);
+ path.lineTo(10.5, 0.5);
+ path.lineTo(10, 0.5);
+ path.lineTo(0, 0.5);
+ path.lineTo(-0.5, 0.5);
+ path.lineTo(-0.5, -0.5);
+ path.lineTo(0, -0.5);
+ path.lineTo(0, 0);
+ path.lineTo(10, 0);
+ path.closeSubpath();
+
+ for (int i = 0; i < 11; ++i)
+ QCOMPARE(QPointF(item.shape().elementAt(i)), QPointF(path.elementAt(i)));
+}
+
+void tst_QGraphicsItem::defaultItemTest_QGraphicsPixmapItem()
+{
+ QGraphicsPixmapItem item;
+ QVERIFY(item.pixmap().isNull());
+ QCOMPARE(item.offset(), QPointF());
+ QCOMPARE(item.transformationMode(), Qt::FastTransformation);
+
+ QPixmap pixmap(300, 200);
+ pixmap.fill(Qt::red);
+ item.setPixmap(pixmap);
+ QCOMPARE(item.pixmap(), pixmap);
+
+ item.setTransformationMode(Qt::FastTransformation);
+ QCOMPARE(item.transformationMode(), Qt::FastTransformation);
+ item.setTransformationMode(Qt::SmoothTransformation);
+ QCOMPARE(item.transformationMode(), Qt::SmoothTransformation);
+
+ item.setOffset(-15, -15);
+ QCOMPARE(item.offset(), QPointF(-15, -15));
+ item.setOffset(QPointF(-10, -10));
+ QCOMPARE(item.offset(), QPointF(-10, -10));
+
+ QCOMPARE(item.boundingRect(), QRectF(-10.5, -10.5, 301, 201));
+}
+
+void tst_QGraphicsItem::defaultItemTest_QGraphicsTextItem()
+{
+ QGraphicsTextItem *text = new QGraphicsTextItem;
+ QVERIFY(!text->openExternalLinks());
+ QVERIFY(text->textCursor().isNull());
+ QCOMPARE(text->defaultTextColor(), QPalette().color(QPalette::Text));
+ QVERIFY(text->document() != 0);
+ QCOMPARE(text->font(), QApplication::font());
+ QCOMPARE(text->textInteractionFlags(), Qt::TextInteractionFlags(Qt::NoTextInteraction));
+ QCOMPARE(text->textWidth(), -1.0);
+ QCOMPARE(text->toPlainText(), QString(""));
+
+ QGraphicsScene scene;
+ scene.addItem(text);
+ text->setPlainText("Hello world");
+ text->setFlag(QGraphicsItem::ItemIsMovable);
+
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setScenePos(QPointF(1, 1));
+ event.setButton(Qt::LeftButton);
+ event.setButtons(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &event);
+ QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove);
+ event2.setScenePos(QPointF(11, 11));
+ event2.setButton(Qt::LeftButton);
+ event2.setButtons(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &event2);
+ }
+
+ QCOMPARE(text->pos(), QPointF(10, 10));
+
+ text->setTextInteractionFlags(Qt::TextEditorInteraction);
+ QCOMPARE(text->textInteractionFlags(), Qt::TextInteractionFlags(Qt::TextEditorInteraction));
+
+ {
+ QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove);
+ event2.setScenePos(QPointF(21, 21));
+ event2.setButton(Qt::LeftButton);
+ event2.setButtons(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &event2);
+ }
+
+ QCOMPARE(text->pos(), QPointF(20, 20)); // clicked on edge, item moved
+}
+
+void tst_QGraphicsItem::defaultItemTest_QGraphicsEllipseItem()
+{
+ QGraphicsEllipseItem item;
+ QVERIFY(item.rect().isNull());
+ QVERIFY(item.boundingRect().isNull());
+ QVERIFY(item.shape().isEmpty());
+ QCOMPARE(item.spanAngle(), 360 * 16);
+ QCOMPARE(item.startAngle(), 0);
+
+ item.setRect(0, 0, 100, 100);
+ QCOMPARE(item.boundingRect(), QRectF(0, 0, 100, 100));
+
+ item.setSpanAngle(90 * 16);
+ qFuzzyCompare(item.boundingRect().left(), qreal(50.0));
+ qFuzzyCompare(item.boundingRect().top(), qreal(0.0));
+ qFuzzyCompare(item.boundingRect().width(), qreal(50.0));
+ qFuzzyCompare(item.boundingRect().height(), qreal(50.0));
+
+ item.setPen(QPen(Qt::black, 1));
+ QCOMPARE(item.boundingRect(), QRectF(49.5, -0.5, 51, 51));
+
+ item.setSpanAngle(180 * 16);
+ QCOMPARE(item.boundingRect(), QRectF(-0.5, -0.5, 101, 51));
+
+ item.setSpanAngle(360 * 16);
+ QCOMPARE(item.boundingRect(), QRectF(-0.5, -0.5, 101, 101));
+}
+
+class ItemChangeTester : public QGraphicsRectItem
+{
+public:
+ QVariant itemChangeReturnValue;
+ QGraphicsScene *itemSceneChangeTargetScene;
+
+ QList<GraphicsItemChange> changes;
+ QList<QVariant> values;
+ QList<QVariant> oldValues;
+protected:
+ QVariant itemChange(GraphicsItemChange change, const QVariant &value)
+ {
+ changes << change;
+ values << value;
+ switch (change) {
+ case QGraphicsItem::ItemPositionChange:
+ oldValues << pos();
+ break;
+ case QGraphicsItem::ItemPositionHasChanged:
+ break;
+ case QGraphicsItem::ItemMatrixChange: {
+ QVariant variant;
+ qVariantSetValue<QMatrix>(variant, matrix());
+ oldValues << variant;
+ }
+ break;
+ case QGraphicsItem::ItemTransformChange: {
+ QVariant variant;
+ qVariantSetValue<QTransform>(variant, transform());
+ oldValues << variant;
+ }
+ break;
+ case QGraphicsItem::ItemTransformHasChanged:
+ break;
+ case QGraphicsItem::ItemVisibleChange:
+ oldValues << isVisible();
+ break;
+ case QGraphicsItem::ItemVisibleHasChanged:
+ break;
+ case QGraphicsItem::ItemEnabledChange:
+ oldValues << isEnabled();
+ break;
+ case QGraphicsItem::ItemEnabledHasChanged:
+ break;
+ case QGraphicsItem::ItemSelectedChange:
+ oldValues << isSelected();
+ break;
+ case QGraphicsItem::ItemSelectedHasChanged:
+ break;
+ case QGraphicsItem::ItemParentChange:
+ oldValues << qVariantFromValue<void *>(parentItem());
+ break;
+ case QGraphicsItem::ItemParentHasChanged:
+ break;
+ case QGraphicsItem::ItemChildAddedChange:
+ oldValues << children().size();
+ break;
+ case QGraphicsItem::ItemChildRemovedChange:
+ oldValues << children().size();
+ break;
+ case QGraphicsItem::ItemSceneChange:
+ oldValues << qVariantFromValue<QGraphicsScene *>(scene());
+ if (itemSceneChangeTargetScene
+ && qVariantValue<QGraphicsScene *>(value)
+ && itemSceneChangeTargetScene != qVariantValue<QGraphicsScene *>(value)) {
+ return qVariantFromValue<QGraphicsScene *>(itemSceneChangeTargetScene);
+ }
+ return value;
+ case QGraphicsItem::ItemSceneHasChanged:
+ break;
+ case QGraphicsItem::ItemCursorChange:
+#ifndef QT_NO_CURSOR
+ oldValues << cursor();
+#endif
+ break;
+ case QGraphicsItem::ItemCursorHasChanged:
+ break;
+ case QGraphicsItem::ItemToolTipChange:
+ oldValues << toolTip();
+ break;
+ case QGraphicsItem::ItemToolTipHasChanged:
+ break;
+ case QGraphicsItem::ItemFlagsChange:
+ oldValues << quint32(flags());
+ break;
+ case QGraphicsItem::ItemFlagsHaveChanged:
+ break;
+ case QGraphicsItem::ItemZValueChange:
+ oldValues << zValue();
+ break;
+ case QGraphicsItem::ItemZValueHasChanged:
+ break;
+ case QGraphicsItem::ItemOpacityChange:
+ oldValues << opacity();
+ break;
+ case QGraphicsItem::ItemOpacityHasChanged:
+ break;
+ }
+ return itemChangeReturnValue.isValid() ? itemChangeReturnValue : value;
+ }
+};
+
+void tst_QGraphicsItem::itemChange()
+{
+ ItemChangeTester tester;
+ tester.itemSceneChangeTargetScene = 0;
+
+ ItemChangeTester testerHelper;
+ QVERIFY(tester.changes.isEmpty());
+ QVERIFY(tester.values.isEmpty());
+
+ int changeCount = 0;
+ {
+ // ItemEnabledChange
+ tester.itemChangeReturnValue = true;
+ tester.setEnabled(false);
+ ++changeCount;
+ ++changeCount; // HasChanged
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemEnabledChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemEnabledHasChanged);
+ QCOMPARE(tester.values.at(tester.values.size() - 2), QVariant(false));
+ QCOMPARE(tester.values.at(tester.values.size() - 1), QVariant(true));
+ QCOMPARE(tester.oldValues.last(), QVariant(true));
+ QCOMPARE(tester.isEnabled(), true);
+ }
+ {
+ // ItemMatrixChange / ItemTransformHasChanged
+ qVariantSetValue<QMatrix>(tester.itemChangeReturnValue, QMatrix().rotate(90));
+ tester.setMatrix(QMatrix().translate(50, 0), true);
+ ++changeCount; // notification sent too
+ QCOMPARE(tester.changes.size(), ++changeCount);
+ QCOMPARE(int(tester.changes.at(tester.changes.size() - 2)), int(QGraphicsItem::ItemMatrixChange));
+ QCOMPARE(int(tester.changes.last()), int(QGraphicsItem::ItemTransformHasChanged));
+ QCOMPARE(qVariantValue<QMatrix>(tester.values.at(tester.values.size() - 2)),
+ QMatrix().translate(50, 0));
+ QCOMPARE(tester.values.last(), QVariant(QTransform(QMatrix().rotate(90))));
+ QVariant variant;
+ qVariantSetValue<QMatrix>(variant, QMatrix());
+ QCOMPARE(tester.oldValues.last(), variant);
+ QCOMPARE(tester.matrix(), QMatrix().rotate(90));
+ }
+ {
+ tester.resetTransform();
+ ++changeCount;
+ ++changeCount; // notification sent too
+
+ // ItemTransformChange / ItemTransformHasChanged
+ qVariantSetValue<QTransform>(tester.itemChangeReturnValue, QTransform().rotate(90));
+ tester.translate(50, 0);
+ ++changeCount; // notification sent too
+ ++changeCount;
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemTransformChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemTransformHasChanged);
+ QCOMPARE(qVariantValue<QTransform>(tester.values.at(tester.values.size() - 2)),
+ QTransform().translate(50, 0));
+ QCOMPARE(qVariantValue<QTransform>(tester.values.at(tester.values.size() - 1)),
+ QTransform().rotate(90));
+ QVariant variant;
+ qVariantSetValue<QTransform>(variant, QTransform());
+ QCOMPARE(tester.oldValues.last(), variant);
+ QCOMPARE(tester.transform(), QTransform().rotate(90));
+ }
+ {
+ // ItemPositionChange / ItemPositionHasChanged
+ tester.itemChangeReturnValue = QPointF(42, 0);
+ tester.setPos(0, 42);
+ ++changeCount; // notification sent too
+ ++changeCount;
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemPositionChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemPositionHasChanged);
+ QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(QPointF(0, 42)));
+ QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(QPointF(42, 0)));
+ QCOMPARE(tester.oldValues.last(), QVariant(QPointF()));
+ QCOMPARE(tester.pos(), QPointF(42, 0));
+ }
+ {
+ // ItemFlagsChange
+ tester.itemChangeReturnValue = QGraphicsItem::ItemIsSelectable;
+ tester.setFlag(QGraphicsItem::ItemIsSelectable, false);
+ QCOMPARE(tester.changes.size(), changeCount); // No change
+ tester.setFlag(QGraphicsItem::ItemIsSelectable, true);
+ ++changeCount;
+ ++changeCount; // ItemFlagsHasChanged
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemFlagsChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemFlagsHaveChanged);
+ QCOMPARE(tester.values.at(tester.values.size() - 2), qVariantFromValue<quint32>(QGraphicsItem::ItemIsSelectable));
+ QCOMPARE(tester.values.at(tester.values.size() - 1), qVariantFromValue<quint32>(QGraphicsItem::ItemIsSelectable));
+ }
+ {
+ // ItemSelectedChange
+ tester.setSelected(false);
+ QCOMPARE(tester.changes.size(), changeCount); // No change :-)
+ tester.itemChangeReturnValue = true;
+ tester.setSelected(true);
+ ++changeCount;
+ ++changeCount; // ItemSelectedHasChanged
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSelectedChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSelectedHasChanged);
+ QCOMPARE(tester.values.at(tester.values.size() - 2), QVariant(true));
+ QCOMPARE(tester.values.at(tester.values.size() - 1), QVariant(true));
+ QCOMPARE(tester.oldValues.last(), QVariant(false));
+ QCOMPARE(tester.isSelected(), true);
+
+ tester.itemChangeReturnValue = false;
+ tester.setSelected(true);
+
+ // the value hasn't changed to the itemChange return value
+ // bacause itemChange is never called (true -> true is a noop).
+ QCOMPARE(tester.isSelected(), true);
+ }
+ {
+ // ItemVisibleChange
+ tester.itemChangeReturnValue = false;
+ QVERIFY(tester.isVisible());
+ tester.setVisible(false);
+ ++changeCount; // ItemVisibleChange
+ ++changeCount; // ItemSelectedChange
+ ++changeCount; // ItemSelectedHasChanged
+ ++changeCount; // ItemVisibleHasChanged
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 4), QGraphicsItem::ItemVisibleChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 3), QGraphicsItem::ItemSelectedChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSelectedHasChanged);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemVisibleHasChanged);
+ QCOMPARE(tester.values.at(tester.values.size() - 4), QVariant(false));
+ QCOMPARE(tester.values.at(tester.values.size() - 3), QVariant(false));
+ QCOMPARE(tester.values.at(tester.values.size() - 2), QVariant(false));
+ QCOMPARE(tester.values.at(tester.values.size() - 1), QVariant(false));
+ QCOMPARE(tester.isVisible(), false);
+ }
+ {
+ // ItemParentChange
+ qVariantSetValue<QGraphicsItem *>(tester.itemChangeReturnValue, 0);
+ tester.setParentItem(&testerHelper);
+ QCOMPARE(tester.changes.size(), ++changeCount);
+ QCOMPARE(tester.changes.last(), QGraphicsItem::ItemParentChange);
+ QCOMPARE(qVariantValue<QGraphicsItem *>(tester.values.last()), (QGraphicsItem *)&testerHelper);
+ QCOMPARE(qVariantValue<QGraphicsItem *>(tester.oldValues.last()), (QGraphicsItem *)0);
+ QCOMPARE(tester.parentItem(), (QGraphicsItem *)0);
+ }
+ {
+ // ItemOpacityChange
+ tester.itemChangeReturnValue = 1.0;
+ tester.setOpacity(0.7);
+ QCOMPARE(tester.changes.size(), ++changeCount);
+ QCOMPARE(tester.changes.last(), QGraphicsItem::ItemOpacityChange);
+ QVERIFY(qFuzzyCompare(qreal(tester.values.last().toDouble()), qreal(0.7)));
+ QCOMPARE(tester.oldValues.last().toDouble(), double(1.0));
+ QCOMPARE(tester.opacity(), qreal(1.0));
+ tester.itemChangeReturnValue = 0.7;
+ tester.setOpacity(0.7);
+ ++changeCount; // ItemOpacityChange
+ ++changeCount; // ItemOpacityHasChanged
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemOpacityChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemOpacityHasChanged);
+ QCOMPARE(tester.opacity(), qreal(0.7));
+ }
+ {
+ // ItemChildAddedChange
+ tester.itemChangeReturnValue.clear();
+ testerHelper.setParentItem(&tester);
+ QCOMPARE(tester.changes.size(), ++changeCount);
+ QCOMPARE(tester.changes.last(), QGraphicsItem::ItemChildAddedChange);
+ QCOMPARE(qVariantValue<QGraphicsItem *>(tester.values.last()), (QGraphicsItem *)&testerHelper);
+ }
+ {
+ // ItemChildRemovedChange 1
+ testerHelper.setParentItem(0);
+ QCOMPARE(tester.changes.size(), ++changeCount);
+ QCOMPARE(tester.changes.last(), QGraphicsItem::ItemChildRemovedChange);
+ QCOMPARE(qVariantValue<QGraphicsItem *>(tester.values.last()), (QGraphicsItem *)&testerHelper);
+ }
+ {
+ // ItemChildRemovedChange 2
+ ItemChangeTester parent;
+ ItemChangeTester *child = new ItemChangeTester;
+ child->setParentItem(&parent);
+ QCOMPARE(parent.changes.last(), QGraphicsItem::ItemChildAddedChange);
+ QCOMPARE(qVariantValue<QGraphicsItem *>(parent.values.last()), (QGraphicsItem *)child);
+ delete child;
+ QCOMPARE(parent.changes.last(), QGraphicsItem::ItemChildRemovedChange);
+ QCOMPARE(qVariantValue<QGraphicsItem *>(parent.values.last()), (QGraphicsItem *)child);
+ }
+ {
+ // !!! Note: If this test crashes because of double-deletion, there's
+ // a bug somewhere in QGraphicsScene or QGraphicsItem.
+
+ // ItemSceneChange
+ QGraphicsScene scene;
+ QGraphicsScene scene2;
+ scene.addItem(&tester);
+ ++changeCount; // ItemSceneChange (scene)
+ ++changeCount; // ItemSceneHasChanged (scene)
+ QCOMPARE(tester.changes.size(), changeCount);
+
+ QCOMPARE(tester.scene(), &scene);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSceneChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSceneHasChanged);
+ // Item's old value was 0
+ // Item's current value is scene
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.oldValues.last()), (QGraphicsScene *)0);
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.last()), (QGraphicsScene *)&scene);
+ scene2.addItem(&tester);
+ ++changeCount; // ItemSceneChange (0) was: (scene)
+ ++changeCount; // ItemSceneHasChanged (0)
+ ++changeCount; // ItemSceneChange (scene2) was: (0)
+ ++changeCount; // ItemSceneHasChanged (scene2)
+ QCOMPARE(tester.changes.size(), changeCount);
+
+ QCOMPARE(tester.scene(), &scene2);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 4), QGraphicsItem::ItemSceneChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 3), QGraphicsItem::ItemSceneHasChanged);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSceneChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSceneHasChanged);
+ // Item's last old value was scene
+ // Item's last current value is 0
+
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.oldValues.at(tester.oldValues.size() - 2)), (QGraphicsScene *)&scene);
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.oldValues.at(tester.oldValues.size() - 1)), (QGraphicsScene *)0);
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 4)), (QGraphicsScene *)0);
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 3)), (QGraphicsScene *)0);
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)&scene2);
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 1)), (QGraphicsScene *)&scene2);
+ // Item's last old value was 0
+ // Item's last current value is scene2
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.oldValues.last()), (QGraphicsScene *)0);
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.last()), (QGraphicsScene *)&scene2);
+
+ scene2.removeItem(&tester);
+ ++changeCount; // ItemSceneChange (0) was: (scene2)
+ ++changeCount; // ItemSceneHasChanged (0)
+ QCOMPARE(tester.changes.size(), changeCount);
+
+ QCOMPARE(tester.scene(), (QGraphicsScene *)0);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSceneChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSceneHasChanged);
+ // Item's last old value was scene2
+ // Item's last current value is 0
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.oldValues.last()), (QGraphicsScene *)&scene2);
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)0);
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 1)), (QGraphicsScene *)0);
+
+ tester.itemSceneChangeTargetScene = &scene;
+ scene2.addItem(&tester);
+ ++changeCount; // ItemSceneChange (scene2) was: (0)
+ ++changeCount; // ItemSceneChange (scene) was: (0)
+ ++changeCount; // ItemSceneHasChanged (scene)
+ QCOMPARE(tester.values.size(), changeCount);
+
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 3)), (QGraphicsScene *)&scene2);
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)&scene);
+ QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 1)), (QGraphicsScene *)&scene);
+
+ QCOMPARE(tester.scene(), &scene);
+ tester.itemSceneChangeTargetScene = 0;
+ tester.itemChangeReturnValue = QVariant();
+ scene.removeItem(&tester);
+ QCOMPARE(tester.scene(), (QGraphicsScene *)0);
+ }
+}
+
+class EventFilterTesterItem : public QGraphicsLineItem
+{
+public:
+ QList<QEvent::Type> filteredEvents;
+ QList<QGraphicsItem *> filteredEventReceivers;
+ bool handlesSceneEvents;
+
+ QList<QEvent::Type> receivedEvents;
+
+ EventFilterTesterItem() : handlesSceneEvents(false) {}
+
+protected:
+ bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
+ {
+ filteredEvents << event->type();
+ filteredEventReceivers << watched;
+ return handlesSceneEvents;
+ }
+
+ bool sceneEvent(QEvent *event)
+ {
+ return QGraphicsLineItem::sceneEvent(event);
+ }
+};
+
+void tst_QGraphicsItem::sceneEventFilter()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+
+ QGraphicsTextItem *text1 = scene.addText(QLatin1String("Text1"));
+ QGraphicsTextItem *text2 = scene.addText(QLatin1String("Text2"));
+ QGraphicsTextItem *text3 = scene.addText(QLatin1String("Text3"));
+ text1->setFlag(QGraphicsItem::ItemIsFocusable);
+ text2->setFlag(QGraphicsItem::ItemIsFocusable);
+ text3->setFlag(QGraphicsItem::ItemIsFocusable);
+
+ EventFilterTesterItem *tester = new EventFilterTesterItem;
+ scene.addItem(tester);
+
+ QVERIFY(!text1->hasFocus());
+ text1->installSceneEventFilter(tester);
+ text1->setFocus();
+ QVERIFY(text1->hasFocus());
+
+ QCOMPARE(tester->filteredEvents.size(), 1);
+ QCOMPARE(tester->filteredEvents.at(0), QEvent::FocusIn);
+ QCOMPARE(tester->filteredEventReceivers.at(0), static_cast<QGraphicsItem *>(text1));
+
+ text2->installSceneEventFilter(tester);
+ text3->installSceneEventFilter(tester);
+
+ text2->setFocus();
+ text3->setFocus();
+
+ QCOMPARE(tester->filteredEvents.size(), 5);
+ QCOMPARE(tester->filteredEvents.at(1), QEvent::FocusOut);
+ QCOMPARE(tester->filteredEventReceivers.at(1), static_cast<QGraphicsItem *>(text1));
+ QCOMPARE(tester->filteredEvents.at(2), QEvent::FocusIn);
+ QCOMPARE(tester->filteredEventReceivers.at(2), static_cast<QGraphicsItem *>(text2));
+ QCOMPARE(tester->filteredEvents.at(3), QEvent::FocusOut);
+ QCOMPARE(tester->filteredEventReceivers.at(3), static_cast<QGraphicsItem *>(text2));
+ QCOMPARE(tester->filteredEvents.at(4), QEvent::FocusIn);
+ QCOMPARE(tester->filteredEventReceivers.at(4), static_cast<QGraphicsItem *>(text3));
+
+ text1->removeSceneEventFilter(tester);
+ text1->setFocus();
+
+ QCOMPARE(tester->filteredEvents.size(), 6);
+ QCOMPARE(tester->filteredEvents.at(5), QEvent::FocusOut);
+ QCOMPARE(tester->filteredEventReceivers.at(5), static_cast<QGraphicsItem *>(text3));
+
+ tester->handlesSceneEvents = true;
+ text2->setFocus();
+
+ QCOMPARE(tester->filteredEvents.size(), 7);
+ QCOMPARE(tester->filteredEvents.at(6), QEvent::FocusIn);
+ QCOMPARE(tester->filteredEventReceivers.at(6), static_cast<QGraphicsItem *>(text2));
+
+ QVERIFY(text2->hasFocus());
+}
+
+class GeometryChanger : public QGraphicsItem
+{
+public:
+ void changeGeometry()
+ { prepareGeometryChange(); }
+};
+
+void tst_QGraphicsItem::prepareGeometryChange()
+{
+ {
+ QGraphicsScene scene;
+ QGraphicsItem *item = scene.addRect(QRectF(0, 0, 100, 100));
+ QVERIFY(scene.items(QRectF(0, 0, 100, 100)).contains(item));
+ ((GeometryChanger *)item)->changeGeometry();
+ QVERIFY(scene.items(QRectF(0, 0, 100, 100)).contains(item));
+ }
+}
+
+
+class PaintTester : public QGraphicsRectItem
+{
+public:
+ PaintTester() : widget(NULL), painted(0) { setRect(QRectF(10, 10, 20, 20));}
+
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *w)
+ {
+ widget = w;
+ painted++;
+ }
+
+ QWidget* widget;
+ int painted;
+};
+
+void tst_QGraphicsItem::paint()
+{
+ QGraphicsScene scene;
+
+ PaintTester paintTester;
+ scene.addItem(&paintTester);
+
+ QGraphicsView view(&scene);
+
+ view.show();
+ QTest::qWait(250);
+
+#ifdef Q_OS_WIN32
+ //we try to switch the desktop: if it fails, we skip the test
+ if (::SwitchDesktop( ::GetThreadDesktop( ::GetCurrentThreadId() ) ) == 0) {
+ QSKIP("The Graphics View doesn't get the paint events", SkipSingle);
+ }
+#endif
+
+ QVERIFY(paintTester.widget == view.viewport());
+
+
+ view.hide();
+
+ QGraphicsScene scene2;
+
+ PaintTester tester2;
+ scene2.addItem(&tester2);
+
+ QGraphicsView view2(&scene2);
+ view2.show();
+ qApp->processEvents();
+ QTest::qWait(250);
+
+ //First show one paint
+ QVERIFY(tester2.painted == 1);
+
+ //nominal case, update call paint
+ tester2.update();
+ qApp->processEvents();
+ QTest::qWait(250);
+ QVERIFY(tester2.painted == 2);
+
+ //we remove the item from the scene, number of updates is still the same
+ tester2.update();
+ scene2.removeItem(&tester2);
+ qApp->processEvents();
+ QTest::qWait(250);
+ QVERIFY(tester2.painted == 2);
+
+ //We re-add the item, the number of paint should increase
+ scene2.addItem(&tester2);
+ tester2.update();
+ qApp->processEvents();
+ QTest::qWait(250);
+ QVERIFY(tester2.painted == 3);
+}
+
+class HarakiriItem : public QGraphicsRectItem
+{
+public:
+ HarakiriItem(int harakiriPoint)
+ : QGraphicsRectItem(QRectF(0, 0, 100, 100)), harakiri(harakiriPoint)
+ { dead = 0; }
+
+ static int dead;
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ QGraphicsRectItem::paint(painter, option, widget);
+ if (harakiri == 0) {
+ // delete unsupported since 4.5
+ /*
+ dead = 1;
+ delete this;
+ */
+ }
+ }
+
+ void advance(int n)
+ {
+ if (harakiri == 1 && n == 0) {
+ // delete unsupported
+ /*
+ dead = 1;
+ delete this;
+ */
+ }
+ if (harakiri == 2 && n == 1) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+protected:
+ void contextMenuEvent(QGraphicsSceneContextMenuEvent *)
+ {
+ if (harakiri == 3) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+ void dragEnterEvent(QGraphicsSceneDragDropEvent *event)
+ {
+ // ??
+ QGraphicsRectItem::dragEnterEvent(event);
+ }
+
+ void dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
+ {
+ // ??
+ QGraphicsRectItem::dragLeaveEvent(event);
+ }
+
+ void dragMoveEvent(QGraphicsSceneDragDropEvent *event)
+ {
+ // ??
+ QGraphicsRectItem::dragMoveEvent(event);
+ }
+
+ void dropEvent(QGraphicsSceneDragDropEvent *event)
+ {
+ // ??
+ QGraphicsRectItem::dropEvent(event);
+ }
+
+ void focusInEvent(QFocusEvent *)
+ {
+ if (harakiri == 4) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+ void focusOutEvent(QFocusEvent *)
+ {
+ if (harakiri == 5) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+ void hoverEnterEvent(QGraphicsSceneHoverEvent *)
+ {
+ if (harakiri == 6) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+ void hoverLeaveEvent(QGraphicsSceneHoverEvent *)
+ {
+ if (harakiri == 7) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+ void hoverMoveEvent(QGraphicsSceneHoverEvent *)
+ {
+ if (harakiri == 8) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+ void inputMethodEvent(QInputMethodEvent *event)
+ {
+ // ??
+ QGraphicsRectItem::inputMethodEvent(event);
+ }
+
+ QVariant inputMethodQuery(Qt::InputMethodQuery query) const
+ {
+ // ??
+ return QGraphicsRectItem::inputMethodQuery(query);
+ }
+
+ QVariant itemChange(GraphicsItemChange change, const QVariant &value)
+ {
+ // deletion not supported
+ return QGraphicsRectItem::itemChange(change, value);
+ }
+
+ void keyPressEvent(QKeyEvent *)
+ {
+ if (harakiri == 9) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+ void keyReleaseEvent(QKeyEvent *)
+ {
+ if (harakiri == 10) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+ void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *)
+ {
+ if (harakiri == 11) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *)
+ {
+ if (harakiri == 12) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+ void mousePressEvent(QGraphicsSceneMouseEvent *)
+ {
+ if (harakiri == 13) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *)
+ {
+ if (harakiri == 14) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+ bool sceneEvent(QEvent *event)
+ {
+ // deletion not supported
+ return QGraphicsRectItem::sceneEvent(event);
+ }
+
+ bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
+ {
+ // deletion not supported
+ return QGraphicsRectItem::sceneEventFilter(watched, event);
+ }
+
+ void wheelEvent(QGraphicsSceneWheelEvent *)
+ {
+ if (harakiri == 16) {
+ dead = 1;
+ delete this;
+ }
+ }
+
+private:
+ int harakiri;
+};
+
+int HarakiriItem::dead;
+
+void tst_QGraphicsItem::deleteItemInEventHandlers()
+{
+ for (int i = 0; i < 17; ++i) {
+ QGraphicsScene scene;
+ HarakiriItem *item = new HarakiriItem(i);
+ item->setAcceptsHoverEvents(true);
+ item->setFlag(QGraphicsItem::ItemIsFocusable);
+
+ scene.addItem(item);
+
+ item->installSceneEventFilter(item); // <- ehey!
+
+ QGraphicsView view(&scene);
+ view.show();
+
+ qApp->processEvents();
+ qApp->processEvents();
+
+ if (!item->dead)
+ scene.advance();
+
+ if (!item->dead) {
+ QContextMenuEvent event(QContextMenuEvent::Other,
+ view.mapFromScene(item->scenePos()));
+ QCoreApplication::sendEvent(view.viewport(), &event);
+ }
+ if (!item->dead)
+ QTest::mouseMove(view.viewport(), view.mapFromScene(item->scenePos()));
+ if (!item->dead)
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos()));
+ if (!item->dead)
+ QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos()));
+ if (!item->dead)
+ QTest::mouseClick(view.viewport(), Qt::RightButton, 0, view.mapFromScene(item->scenePos()));
+ if (!item->dead)
+ QTest::mouseMove(view.viewport(), view.mapFromScene(item->scenePos() + QPointF(20, -20)));
+ if (!item->dead)
+ item->setFocus();
+ if (!item->dead)
+ item->clearFocus();
+ if (!item->dead)
+ item->setFocus();
+ if (!item->dead)
+ QTest::keyPress(view.viewport(), Qt::Key_A);
+ if (!item->dead)
+ QTest::keyRelease(view.viewport(), Qt::Key_A);
+ if (!item->dead)
+ QTest::keyPress(view.viewport(), Qt::Key_A);
+ if (!item->dead)
+ QTest::keyRelease(view.viewport(), Qt::Key_A);
+ }
+}
+
+class ItemPaintsOutsideShape : public QGraphicsItem
+{
+public:
+ QRectF boundingRect() const
+ {
+ return QRectF(0, 0, 100, 100);
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ {
+ painter->fillRect(-50, -50, 200, 200, Qt::red);
+ painter->fillRect(0, 0, 100, 100, Qt::blue);
+ }
+};
+
+void tst_QGraphicsItem::itemClipsToShape()
+{
+ QGraphicsItem *clippedItem = new ItemPaintsOutsideShape;
+ clippedItem->setFlag(QGraphicsItem::ItemClipsToShape);
+
+ QGraphicsItem *unclippedItem = new ItemPaintsOutsideShape;
+ unclippedItem->setPos(200, 0);
+
+ QGraphicsScene scene(-50, -50, 400, 200);
+ scene.addItem(clippedItem);
+ scene.addItem(unclippedItem);
+
+ QImage image(400, 200, QImage::Format_ARGB32_Premultiplied);
+ image.fill(0);
+ QPainter painter(&image);
+ painter.setRenderHint(QPainter::Antialiasing);
+ scene.render(&painter);
+ painter.end();
+
+ QCOMPARE(image.pixel(45, 100), QRgb(0));
+ QCOMPARE(image.pixel(100, 45), QRgb(0));
+ QCOMPARE(image.pixel(155, 100), QRgb(0));
+ QCOMPARE(image.pixel(45, 155), QRgb(0));
+ QCOMPARE(image.pixel(55, 100), QColor(Qt::blue).rgba());
+ QCOMPARE(image.pixel(100, 55), QColor(Qt::blue).rgba());
+ QCOMPARE(image.pixel(145, 100), QColor(Qt::blue).rgba());
+ QCOMPARE(image.pixel(55, 145), QColor(Qt::blue).rgba());
+ QCOMPARE(image.pixel(245, 100), QColor(Qt::red).rgba());
+ QCOMPARE(image.pixel(300, 45), QColor(Qt::red).rgba());
+ QCOMPARE(image.pixel(355, 100), QColor(Qt::red).rgba());
+ QCOMPARE(image.pixel(245, 155), QColor(Qt::red).rgba());
+ QCOMPARE(image.pixel(255, 100), QColor(Qt::blue).rgba());
+ QCOMPARE(image.pixel(300, 55), QColor(Qt::blue).rgba());
+ QCOMPARE(image.pixel(345, 100), QColor(Qt::blue).rgba());
+ QCOMPARE(image.pixel(255, 145), QColor(Qt::blue).rgba());
+}
+
+void tst_QGraphicsItem::itemClipsChildrenToShape()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *rect = scene.addRect(0, 0, 50, 50, QPen(Qt::NoPen), QBrush(Qt::yellow));
+
+ QGraphicsItem *ellipse = scene.addEllipse(0, 0, 100, 100, QPen(Qt::NoPen), QBrush(Qt::green));
+ ellipse->setParentItem(rect);
+
+ QGraphicsItem *clippedEllipse = scene.addEllipse(0, 0, 50, 50, QPen(Qt::NoPen), QBrush(Qt::blue));
+ clippedEllipse->setParentItem(ellipse);
+
+ QGraphicsItem *clippedEllipse2 = scene.addEllipse(0, 0, 25, 25, QPen(Qt::NoPen), QBrush(Qt::red));
+ clippedEllipse2->setParentItem(clippedEllipse);
+
+ QGraphicsItem *clippedEllipse3 = scene.addEllipse(50, 50, 25, 25, QPen(Qt::NoPen), QBrush(Qt::red));
+ clippedEllipse3->setParentItem(clippedEllipse);
+
+ QVERIFY(!(ellipse->flags() & QGraphicsItem::ItemClipsChildrenToShape));
+ ellipse->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ QVERIFY((ellipse->flags() & QGraphicsItem::ItemClipsChildrenToShape));
+
+ QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
+ image.fill(0);
+ QPainter painter(&image);
+ painter.setRenderHint(QPainter::Antialiasing);
+ scene.render(&painter);
+ painter.end();
+
+ QCOMPARE(image.pixel(16, 16), QColor(255, 0, 0).rgba());
+ QCOMPARE(image.pixel(32, 32), QColor(0, 0, 255).rgba());
+ QCOMPARE(image.pixel(50, 50), QColor(0, 255, 0).rgba());
+ QCOMPARE(image.pixel(12, 12), QColor(255, 255, 0).rgba());
+ QCOMPARE(image.pixel(60, 60), QColor(255, 0, 0).rgba());
+}
+
+void tst_QGraphicsItem::itemClipsChildrenToShape2()
+{
+ QGraphicsRectItem *parent = new QGraphicsRectItem(QRectF(0, 0, 10, 10));
+ QGraphicsEllipseItem *child1 = new QGraphicsEllipseItem(QRectF(50, 50, 100, 100));
+ QGraphicsRectItem *child2 = new QGraphicsRectItem(QRectF(15, 15, 80, 80));
+
+ child1->setParentItem(parent);
+ child1->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ child2->setParentItem(child1);
+
+ parent->setBrush(Qt::blue);
+ child1->setBrush(Qt::green);
+ child2->setBrush(Qt::red);
+
+ QGraphicsScene scene;
+ scene.addItem(parent);
+
+ QCOMPARE(scene.itemAt(5, 5), (QGraphicsItem *)parent);
+ QCOMPARE(scene.itemAt(15, 5), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(5, 15), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(60, 60), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(140, 60), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(60, 140), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(140, 140), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(75, 75), (QGraphicsItem *)child2);
+ QCOMPARE(scene.itemAt(75, 100), (QGraphicsItem *)child1);
+ QCOMPARE(scene.itemAt(100, 75), (QGraphicsItem *)child1);
+
+#if 1
+ QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
+ image.fill(0);
+ QPainter painter(&image);
+ scene.render(&painter);
+ painter.end();
+
+ QCOMPARE(image.pixel(5, 5), QColor(0, 0, 255).rgba());
+ QCOMPARE(image.pixel(5, 10), QRgb(0));
+ QCOMPARE(image.pixel(10, 5), QRgb(0));
+ QCOMPARE(image.pixel(40, 40), QRgb(0));
+ QCOMPARE(image.pixel(90, 40), QRgb(0));
+ QCOMPARE(image.pixel(40, 90), QRgb(0));
+ QCOMPARE(image.pixel(95, 95), QRgb(0));
+ QCOMPARE(image.pixel(50, 70), QColor(0, 255, 0).rgba());
+ QCOMPARE(image.pixel(70, 50), QColor(0, 255, 0).rgba());
+ QCOMPARE(image.pixel(50, 60), QColor(255, 0, 0).rgba());
+ QCOMPARE(image.pixel(60, 50), QColor(255, 0, 0).rgba());
+#else
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWait(5000);
+#endif
+}
+
+void tst_QGraphicsItem::itemClipsTextChildToShape()
+{
+ // Construct a scene with a rect that clips its children, with one text
+ // child that has text that exceeds the size of the rect.
+ QGraphicsScene scene;
+ QGraphicsItem *rect = scene.addRect(0, 0, 50, 50, QPen(Qt::black), Qt::black);
+ rect->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ QGraphicsTextItem *text = new QGraphicsTextItem("This is a long sentence that's wider than 50 pixels.");
+ text->setParentItem(rect);
+
+ // Render this scene to a transparent image.
+ QRectF sr = scene.itemsBoundingRect();
+ QImage image(sr.size().toSize(), QImage::Format_ARGB32_Premultiplied);
+ image.fill(0);
+ QPainter painter(&image);
+ scene.render(&painter);
+
+ // Erase the area immediately underneath the rect.
+ painter.setCompositionMode(QPainter::CompositionMode_Source);
+ painter.fillRect(rect->sceneBoundingRect().translated(-sr.topLeft()).adjusted(-0.5, -0.5, 0.5, 0.5),
+ Qt::transparent);
+ painter.end();
+
+ // Check that you get a truly transparent image back (i.e., the text was
+ // clipped away, so there should be no trails left after erasing only the
+ // rect's area).
+ QImage emptyImage(scene.itemsBoundingRect().size().toSize(), QImage::Format_ARGB32_Premultiplied);
+ emptyImage.fill(0);
+ QCOMPARE(image, emptyImage);
+}
+
+void tst_QGraphicsItem::itemClippingDiscovery()
+{
+ // A simple scene with an ellipse parent and two rect children, one a
+ // child of the other.
+ QGraphicsScene scene;
+ QGraphicsEllipseItem *clipItem = scene.addEllipse(0, 0, 100, 100);
+ QGraphicsRectItem *leftRectItem = scene.addRect(0, 0, 50, 100);
+ QGraphicsRectItem *rightRectItem = scene.addRect(50, 0, 50, 100);
+ leftRectItem->setParentItem(clipItem);
+ rightRectItem->setParentItem(clipItem);
+
+ // The rects item are both visible at these points.
+ QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)leftRectItem);
+ QCOMPARE(scene.itemAt(90, 90), (QGraphicsItem *)rightRectItem);
+
+ // The ellipse clips the rects now.
+ clipItem->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+
+ // The rect items are no longer visible at these points.
+ QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0);
+ if (sizeof(qreal) != sizeof(double))
+ QSKIP("This fails due to internal rounding errors", SkipSingle);
+ QCOMPARE(scene.itemAt(90, 90), (QGraphicsItem *)0);
+}
+
+void tst_QGraphicsItem::ancestorFlags()
+{
+ QGraphicsItem *level1 = new QGraphicsRectItem;
+ QGraphicsItem *level21 = new QGraphicsRectItem;
+ level21->setParentItem(level1);
+ QGraphicsItem *level22 = new QGraphicsRectItem;
+ level22->setParentItem(level1);
+ QGraphicsItem *level31 = new QGraphicsRectItem;
+ level31->setParentItem(level21);
+ QGraphicsItem *level32 = new QGraphicsRectItem;
+ level32->setParentItem(level21);
+
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
+
+ // HandlesChildEvents: 1) Root level sets a flag
+ level1->setHandlesChildEvents(true);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
+
+ // HandlesChildEvents: 2) Root level set it again
+ level1->setHandlesChildEvents(true);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
+
+ // HandlesChildEvents: 3) Root level unsets a flag
+ level1->setHandlesChildEvents(false);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
+
+ // HandlesChildEvents: 4) Child item sets a flag
+ level21->setHandlesChildEvents(true);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
+
+ // HandlesChildEvents: 5) Parent item sets a flag
+ level1->setHandlesChildEvents(true);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
+
+ // HandlesChildEvents: 6) Child item unsets a flag
+ level21->setHandlesChildEvents(false);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
+
+ // HandlesChildEvents: 7) Parent item unsets a flag
+ level21->setHandlesChildEvents(true);
+ level1->setHandlesChildEvents(false);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
+
+ // Reparent the child to root
+ level21->setParentItem(0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
+
+ // Reparent the child to level1 again.
+ level1->setHandlesChildEvents(true);
+ level21->setParentItem(level1);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
+
+ // Reparenting level31 back to level1.
+ level31->setParentItem(level1);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
+
+ // Reparenting level31 back to level21.
+ level31->setParentItem(0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
+ level31->setParentItem(level21);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
+
+ // Level1 doesn't handle child events
+ level1->setHandlesChildEvents(false);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
+
+ // Nobody handles child events
+ level21->setHandlesChildEvents(false);
+
+ for (int i = 0; i < 2; ++i) {
+ QGraphicsItem::GraphicsItemFlag flag = !i ? QGraphicsItem::ItemClipsChildrenToShape
+ : QGraphicsItem::ItemIgnoresTransformations;
+ int ancestorFlag = !i ? QGraphicsItemPrivate::AncestorClipsChildren
+ : QGraphicsItemPrivate::AncestorIgnoresTransformations;
+
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
+
+ // HandlesChildEvents: 1) Root level sets a flag
+ level1->setFlag(flag, true);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
+
+ // HandlesChildEvents: 2) Root level set it again
+ level1->setFlag(flag, true);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
+
+ // HandlesChildEvents: 3) Root level unsets a flag
+ level1->setFlag(flag, false);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
+
+ // HandlesChildEvents: 4) Child item sets a flag
+ level21->setFlag(flag, true);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
+
+ // HandlesChildEvents: 5) Parent item sets a flag
+ level1->setFlag(flag, true);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
+
+ // HandlesChildEvents: 6) Child item unsets a flag
+ level21->setFlag(flag, false);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
+
+ // HandlesChildEvents: 7) Parent item unsets a flag
+ level21->setFlag(flag, true);
+ level1->setFlag(flag, false);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
+
+ // Reparent the child to root
+ level21->setParentItem(0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
+
+ // Reparent the child to level1 again.
+ level1->setFlag(flag, true);
+ level21->setParentItem(level1);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
+
+ // Reparenting level31 back to level1.
+ level31->setParentItem(level1);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
+
+ // Reparenting level31 back to level21.
+ level31->setParentItem(0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
+ level31->setParentItem(level21);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
+
+ // Level1 doesn't handle child events
+ level1->setFlag(flag, false);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
+
+ // Nobody handles child events
+ level21->setFlag(flag, false);
+ QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
+ QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
+ }
+
+ delete level1;
+}
+
+void tst_QGraphicsItem::untransformable()
+{
+ QGraphicsItem *item1 = new QGraphicsEllipseItem(QRectF(-50, -50, 100, 100));
+ item1->setZValue(1);
+ item1->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+ item1->rotate(45);
+ ((QGraphicsEllipseItem *)item1)->setBrush(Qt::red);
+
+ QGraphicsItem *item2 = new QGraphicsEllipseItem(QRectF(-50, -50, 100, 100));
+ item2->setParentItem(item1);
+ item2->rotate(45);
+ item2->setPos(100, 0);
+ ((QGraphicsEllipseItem *)item2)->setBrush(Qt::green);
+
+ QGraphicsItem *item3 = new QGraphicsEllipseItem(QRectF(-50, -50, 100, 100));
+ item3->setParentItem(item2);
+ item3->setPos(100, 0);
+ ((QGraphicsEllipseItem *)item3)->setBrush(Qt::blue);
+
+ QGraphicsScene scene(-500, -500, 1000, 1000);
+ scene.addItem(item1);
+
+ QGraphicsView view(&scene);
+ view.resize(300, 300);
+ view.show();
+ view.scale(8, 8);
+ view.centerOn(0, 0);
+
+// Painting with the DiagCrossPattern is really slow on Mac
+// when zoomed out. (The test times out). Task to fix is 155567.
+#if !defined(Q_WS_MAC) || 1
+ view.setBackgroundBrush(QBrush(Qt::black, Qt::DiagCrossPattern));
+#endif
+
+ for (int i = 0; i < 10; ++i) {
+ QPoint center = view.viewport()->rect().center();
+ QCOMPARE(view.itemAt(center), item1);
+ QCOMPARE(view.itemAt(center - QPoint(40, 0)), item1);
+ QCOMPARE(view.itemAt(center - QPoint(-40, 0)), item1);
+ QCOMPARE(view.itemAt(center - QPoint(0, 40)), item1);
+ QCOMPARE(view.itemAt(center - QPoint(0, -40)), item1);
+
+ center += QPoint(70, 70);
+ QCOMPARE(view.itemAt(center - QPoint(40, 0)), item2);
+ QCOMPARE(view.itemAt(center - QPoint(-40, 0)), item2);
+ QCOMPARE(view.itemAt(center - QPoint(0, 40)), item2);
+ QCOMPARE(view.itemAt(center - QPoint(0, -40)), item2);
+
+ center += QPoint(0, 100);
+ QCOMPARE(view.itemAt(center - QPoint(40, 0)), item3);
+ QCOMPARE(view.itemAt(center - QPoint(-40, 0)), item3);
+ QCOMPARE(view.itemAt(center - QPoint(0, 40)), item3);
+ QCOMPARE(view.itemAt(center - QPoint(0, -40)), item3);
+
+ view.scale(0.5, 0.5);
+ view.rotate(13);
+ view.shear(qreal(0.01), qreal(0.01));
+ view.translate(10, 10);
+ QTest::qWait(250);
+ }
+}
+
+class ContextMenuItem : public QGraphicsRectItem
+{
+public:
+ ContextMenuItem()
+ : ignoreEvent(true), gotEvent(false), eventWasAccepted(false)
+ { }
+ bool ignoreEvent;
+ bool gotEvent;
+ bool eventWasAccepted;
+protected:
+ void contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
+ {
+ gotEvent = true;
+ eventWasAccepted = event->isAccepted();
+ if (ignoreEvent)
+ event->ignore();
+ }
+};
+
+void tst_QGraphicsItem::contextMenuEventPropagation()
+{
+ ContextMenuItem *bottomItem = new ContextMenuItem;
+ bottomItem->setRect(0, 0, 100, 100);
+ ContextMenuItem *topItem = new ContextMenuItem;
+ topItem->setParentItem(bottomItem);
+ topItem->setRect(0, 0, 100, 100);
+
+ QGraphicsScene scene;
+
+ QGraphicsView view(&scene);
+ view.setAlignment(Qt::AlignLeft | Qt::AlignTop);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ view.resize(200, 200);
+
+ QContextMenuEvent event(QContextMenuEvent::Mouse, QPoint(10, 10),
+ view.viewport()->mapToGlobal(QPoint(10, 10)));
+ event.ignore();
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(!event.isAccepted());
+
+ scene.addItem(bottomItem);
+ topItem->ignoreEvent = true;
+ bottomItem->ignoreEvent = true;
+
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(!event.isAccepted());
+ QCOMPARE(topItem->gotEvent, true);
+ QCOMPARE(topItem->eventWasAccepted, true);
+ QCOMPARE(bottomItem->gotEvent, true);
+ QCOMPARE(bottomItem->eventWasAccepted, true);
+
+ topItem->ignoreEvent = false;
+ topItem->gotEvent = false;
+ bottomItem->gotEvent = false;
+
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(event.isAccepted());
+ QCOMPARE(topItem->gotEvent, true);
+ QCOMPARE(bottomItem->gotEvent, false);
+ QCOMPARE(topItem->eventWasAccepted, true);
+}
+
+void tst_QGraphicsItem::itemIsMovable()
+{
+ QGraphicsRectItem *rect = new QGraphicsRectItem(-50, -50, 100, 100);
+ rect->setFlag(QGraphicsItem::ItemIsMovable);
+
+ QGraphicsScene scene;
+ scene.addItem(rect);
+
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setButton(Qt::LeftButton);
+ event.setButtons(Qt::LeftButton);
+ qApp->sendEvent(&scene, &event);
+ }
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
+ event.setButton(Qt::LeftButton);
+ event.setButtons(Qt::LeftButton);
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(rect->pos(), QPointF(0, 0));
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
+ event.setButtons(Qt::LeftButton);
+ event.setScenePos(QPointF(10, 10));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(rect->pos(), QPointF(10, 10));
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
+ event.setButtons(Qt::RightButton);
+ event.setScenePos(QPointF(20, 20));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(rect->pos(), QPointF(10, 10));
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
+ event.setButtons(Qt::LeftButton);
+ event.setScenePos(QPointF(30, 30));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(rect->pos(), QPointF(30, 30));
+}
+
+class ItemAddScene : public QGraphicsScene
+{
+ Q_OBJECT
+public:
+ ItemAddScene()
+ {
+ QTimer::singleShot(500, this, SLOT(newTextItem()));
+ }
+
+public slots:
+ void newTextItem()
+ {
+ // Add a text item
+ QGraphicsItem *item = new QGraphicsTextItem("This item will not ensure that it's visible", 0, this);
+ item->setPos(.0, .0);
+ item->show();
+ }
+};
+
+void tst_QGraphicsItem::task141694_textItemEnsureVisible()
+{
+ ItemAddScene scene;
+ scene.setSceneRect(-1000, -1000, 2000, 2000);
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(200, 200);
+ view.show();
+
+ view.ensureVisible(-1000, -1000, 5, 5);
+ int hscroll = view.horizontalScrollBar()->value();
+ int vscroll = view.verticalScrollBar()->value();
+
+ QTestEventLoop::instance().enterLoop(1);
+
+ // This should not cause the view to scroll
+ QCOMPARE(view.horizontalScrollBar()->value(), hscroll);
+ QCOMPARE(view.verticalScrollBar()->value(), vscroll);
+}
+
+void tst_QGraphicsItem::task128696_textItemEnsureMovable()
+{
+ QGraphicsTextItem *item = new QGraphicsTextItem;
+ item->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
+ item->setTextInteractionFlags(Qt::TextEditorInteraction);
+ item->setPlainText("abc de\nf ghi\n j k l");
+
+ QGraphicsScene scene;
+ scene.setSceneRect(-100, -100, 200, 200);
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(200, 200);
+ view.show();
+
+ QGraphicsSceneMouseEvent event1(QEvent::GraphicsSceneMousePress);
+ event1.setScenePos(QPointF(0, 0));
+ event1.setButton(Qt::LeftButton);
+ event1.setButtons(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &event1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
+
+ QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove);
+ event2.setScenePos(QPointF(10, 10));
+ event2.setButton(Qt::LeftButton);
+ event2.setButtons(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &event2);
+ QCOMPARE(item->pos(), QPointF(10, 10));
+}
+
+void tst_QGraphicsItem::task177918_lineItemUndetected()
+{
+ QGraphicsScene scene;
+ QGraphicsLineItem *line = scene.addLine(10, 10, 10, 10);
+ QCOMPARE(line->boundingRect(), QRectF(10, 10, 0, 0));
+
+ QVERIFY(!scene.items(9, 9, 2, 2, Qt::IntersectsItemShape).isEmpty());
+ QVERIFY(!scene.items(9, 9, 2, 2, Qt::ContainsItemShape).isEmpty());
+ QVERIFY(!scene.items(9, 9, 2, 2, Qt::IntersectsItemBoundingRect).isEmpty());
+ QVERIFY(!scene.items(9, 9, 2, 2, Qt::ContainsItemBoundingRect).isEmpty());
+}
+
+void tst_QGraphicsItem::task240400_clickOnTextItem_data()
+{
+ QTest::addColumn<int>("flags");
+ QTest::addColumn<int>("textFlags");
+ QTest::newRow("editor, noflags") << 0 << int(Qt::TextEditorInteraction);
+ QTest::newRow("editor, movable") << int(QGraphicsItem::ItemIsMovable) << int(Qt::TextEditorInteraction);
+ QTest::newRow("editor, selectable") << int(QGraphicsItem::ItemIsSelectable) << int(Qt::TextEditorInteraction);
+ QTest::newRow("editor, movable | selectable") << int(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable)
+ << int(Qt::TextEditorInteraction);
+ QTest::newRow("noninteractive, noflags") << 0 << int(Qt::NoTextInteraction);
+ QTest::newRow("noninteractive, movable") << int(QGraphicsItem::ItemIsMovable) << int(Qt::NoTextInteraction);
+ QTest::newRow("noninteractive, selectable") << int(QGraphicsItem::ItemIsSelectable) << int(Qt::NoTextInteraction);
+ QTest::newRow("noninteractive, movable | selectable") << int(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable)
+ << int(Qt::NoTextInteraction);
+}
+
+void tst_QGraphicsItem::task240400_clickOnTextItem()
+{
+ QFETCH(int, flags);
+ QFETCH(int, textFlags);
+
+ QGraphicsScene scene;
+ QGraphicsTextItem *item = scene.addText("Hello");
+ item->setFlags(QGraphicsItem::GraphicsItemFlags(flags));
+ item->setTextInteractionFlags(Qt::TextInteractionFlags(textFlags));
+ bool focusable = (item->flags() & QGraphicsItem::ItemIsFocusable);
+ QVERIFY(textFlags ? focusable : !focusable);
+
+ int column = item->textCursor().columnNumber();
+ QCOMPARE(column, 0);
+
+ QVERIFY(!item->hasFocus());
+
+ // Click in the top-left corner of the item
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setScenePos(item->sceneBoundingRect().topLeft() + QPointF(0.1, 0.1));
+ event.setButton(Qt::LeftButton);
+ event.setButtons(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &event);
+ }
+ if (flags || textFlags)
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
+ else
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.setScenePos(item->sceneBoundingRect().topLeft() + QPointF(0.1, 0.1));
+ event.setButton(Qt::LeftButton);
+ event.setButtons(0);
+ QApplication::sendEvent(&scene, &event);
+ }
+ if (textFlags)
+ QVERIFY(item->hasFocus());
+ else
+ QVERIFY(!item->hasFocus());
+ QVERIFY(!scene.mouseGrabberItem());
+ bool selectable = (flags & QGraphicsItem::ItemIsSelectable);
+ QVERIFY(selectable ? item->isSelected() : !item->isSelected());
+
+ // Now click in the middle and check that the cursor moved.
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setScenePos(item->sceneBoundingRect().center());
+ event.setButton(Qt::LeftButton);
+ event.setButtons(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &event);
+ }
+ if (flags || textFlags)
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
+ else
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.setScenePos(item->sceneBoundingRect().center());
+ event.setButton(Qt::LeftButton);
+ event.setButtons(0);
+ QApplication::sendEvent(&scene, &event);
+ }
+ if (textFlags)
+ QVERIFY(item->hasFocus());
+ else
+ QVERIFY(!item->hasFocus());
+ QVERIFY(!scene.mouseGrabberItem());
+
+ QVERIFY(selectable ? item->isSelected() : !item->isSelected());
+
+ //
+ if (textFlags & Qt::TextEditorInteraction)
+ QVERIFY(item->textCursor().columnNumber() > column);
+ else
+ QCOMPARE(item->textCursor().columnNumber(), 0);
+}
+
+void tst_QGraphicsItem::task243707_addChildBeforeParent()
+{
+ // Task reports that adding the child before the parent leads to an
+ // inconsistent internal state that can cause a crash. This test shows
+ // one such crash.
+ QGraphicsScene scene;
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsWidget *widget2 = new QGraphicsWidget(widget);
+ scene.addItem(widget2);
+ QVERIFY(!widget2->parentItem());
+ scene.addItem(widget);
+ QVERIFY(!widget->commonAncestorItem(widget2));
+ QVERIFY(!widget2->commonAncestorItem(widget));
+}
+
+void tst_QGraphicsItem::boundingRegion_data()
+{
+ QTest::addColumn<QLineF>("line");
+ QTest::addColumn<qreal>("granularity");
+ QTest::addColumn<QTransform>("transform");
+ QTest::addColumn<QRegion>("expectedRegion");
+
+ QTest::newRow("(0, 0, 10, 10) | 0.0 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 10, 10) << qreal(0.0) << QTransform()
+ << QRegion(QRect(0, 0, 10, 10));
+ {
+ QRegion r;
+ r += QRect(0, 0, 6, 2);
+ r += QRect(0, 2, 8, 2);
+ r += QRect(0, 4, 10, 2);
+ r += QRect(2, 6, 8, 2);
+ r += QRect(4, 8, 6, 2);
+ QTest::newRow("(0, 0, 10, 10) | 0.5 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 10, 10) << qreal(0.5) << QTransform() << r;
+ }
+ {
+ QRegion r;
+ r += QRect(0, 0, 4, 1); r += QRect(0, 1, 5, 1); r += QRect(0, 2, 6, 1);
+ r += QRect(0, 3, 7, 1); r += QRect(1, 4, 7, 1); r += QRect(2, 5, 7, 1);
+ r += QRect(3, 6, 7, 1); r += QRect(4, 7, 6, 1); r += QRect(5, 8, 5, 1);
+ r += QRect(6, 9, 4, 1);
+ QTest::newRow("(0, 0, 10, 10) | 1.0 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 10, 10) << qreal(1.0) << QTransform() << r;
+ }
+ QTest::newRow("(0, 0, 10, 0) | 0.0 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 10, 0) << qreal(0.0) << QTransform()
+ << QRegion(QRect(0, 0, 10, 1));
+ QTest::newRow("(0, 0, 10, 0) | 0.5 | identity | {(0, 0, 10, 1)}") << QLineF(0, 0, 10, 0) << qreal(0.5) << QTransform()
+ << QRegion(QRect(0, 0, 10, 1));
+ QTest::newRow("(0, 0, 10, 0) | 1.0 | identity | {(0, 0, 10, 1)}") << QLineF(0, 0, 10, 0) << qreal(1.0) << QTransform()
+ << QRegion(QRect(0, 0, 10, 1));
+ QTest::newRow("(0, 0, 0, 10) | 0.0 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 0, 10) << qreal(0.0) << QTransform()
+ << QRegion(QRect(0, 0, 1, 10));
+ QTest::newRow("(0, 0, 0, 10) | 0.5 | identity | {(0, 0, 1, 10)}") << QLineF(0, 0, 0, 10) << qreal(0.5) << QTransform()
+ << QRegion(QRect(0, 0, 1, 10));
+ QTest::newRow("(0, 0, 0, 10) | 1.0 | identity | {(0, 0, 1, 10)}") << QLineF(0, 0, 0, 10) << qreal(1.0) << QTransform()
+ << QRegion(QRect(0, 0, 1, 10));
+}
+
+void tst_QGraphicsItem::boundingRegion()
+{
+ QFETCH(QLineF, line);
+ QFETCH(qreal, granularity);
+ QFETCH(QTransform, transform);
+ QFETCH(QRegion, expectedRegion);
+
+ QGraphicsLineItem item(line);
+ QCOMPARE(item.boundingRegionGranularity(), qreal(0.0));
+ item.setBoundingRegionGranularity(granularity);
+ QCOMPARE(item.boundingRegionGranularity(), granularity);
+ QCOMPARE(item.boundingRegion(transform), expectedRegion);
+}
+
+void tst_QGraphicsItem::itemTransform_parentChild()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *parent = scene.addRect(0, 0, 100, 100);
+ QGraphicsItem *child = scene.addRect(0, 0, 100, 100);
+ child->setParentItem(parent);
+ child->setPos(10, 10);
+ child->scale(2, 2);
+ child->rotate(90);
+
+ QCOMPARE(child->itemTransform(parent).map(QPointF(10, 10)), QPointF(-10, 30));
+ QCOMPARE(parent->itemTransform(child).map(QPointF(-10, 30)), QPointF(10, 10));
+}
+
+void tst_QGraphicsItem::itemTransform_siblings()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *parent = scene.addRect(0, 0, 100, 100);
+ QGraphicsItem *brother = scene.addRect(0, 0, 100, 100);
+ QGraphicsItem *sister = scene.addRect(0, 0, 100, 100);
+ parent->scale(10, 5);
+ parent->rotate(-180);
+ parent->shear(2, 3);
+
+ brother->setParentItem(parent);
+ sister->setParentItem(parent);
+
+ brother->setPos(10, 10);
+ brother->scale(2, 2);
+ brother->rotate(90);
+ sister->setPos(10, 10);
+ sister->scale(2, 2);
+ sister->rotate(90);
+
+ QCOMPARE(brother->itemTransform(sister).map(QPointF(10, 10)), QPointF(10, 10));
+ QCOMPARE(sister->itemTransform(brother).map(QPointF(10, 10)), QPointF(10, 10));
+}
+
+void tst_QGraphicsItem::itemTransform_unrelated()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *stranger1 = scene.addRect(0, 0, 100, 100);
+ QGraphicsItem *stranger2 = scene.addRect(0, 0, 100, 100);
+ stranger1->setPos(10, 10);
+ stranger1->scale(2, 2);
+ stranger1->rotate(90);
+ stranger2->setPos(10, 10);
+ stranger2->scale(2, 2);
+ stranger2->rotate(90);
+
+ QCOMPARE(stranger1->itemTransform(stranger2).map(QPointF(10, 10)), QPointF(10, 10));
+ QCOMPARE(stranger2->itemTransform(stranger1).map(QPointF(10, 10)), QPointF(10, 10));
+}
+
+void tst_QGraphicsItem::opacity_data()
+{
+ QTest::addColumn<qreal>("p_opacity");
+ QTest::addColumn<int>("p_opacityFlags");
+ QTest::addColumn<qreal>("c1_opacity");
+ QTest::addColumn<int>("c1_opacityFlags");
+ QTest::addColumn<qreal>("c2_opacity");
+ QTest::addColumn<int>("c2_opacityFlags");
+ QTest::addColumn<qreal>("p_effectiveOpacity");
+ QTest::addColumn<qreal>("c1_effectiveOpacity");
+ QTest::addColumn<qreal>("c2_effectiveOpacity");
+ QTest::addColumn<qreal>("c3_effectiveOpacity");
+
+ // Modify the opacity and see how it propagates
+ QTest::newRow("A: 1.0 0 1.0 0 1.0 1.0 1.0 1.0 1.0") << qreal(1.0) << 0 << qreal(1.0) << 0 << qreal(1.0) << 0
+ << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
+ QTest::newRow("B: 0.5 0 1.0 0 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 << qreal(1.0) << 0 << qreal(1.0) << 0
+ << qreal(0.5) << qreal(0.5) << qreal(0.5) << qreal(0.5);
+ QTest::newRow("C: 0.5 0 0.1 0 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 << qreal(0.1) << 0 << qreal(1.0) << 0
+ << qreal(0.5) << qreal(0.05) << qreal(0.05) << qreal(0.05);
+ QTest::newRow("D: 0.0 0 1.0 0 1.0 1.0 1.0 1.0 1.0") << qreal(0.0) << 0 << qreal(1.0) << 0 << qreal(1.0) << 0
+ << qreal(0.0) << qreal(0.0) << qreal(0.0) << qreal(0.0);
+
+ // Parent doesn't propagate to children - now modify the opacity and see how it propagates
+ int flags = QGraphicsItem::ItemDoesntPropagateOpacityToChildren;
+ QTest::newRow("E: 1.0 2 1.0 0 1.0 1.0 1.0 1.0 1.0") << qreal(1.0) << flags << qreal(1.0) << 0 << qreal(1.0) << 0
+ << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
+ QTest::newRow("F: 0.5 2 1.0 0 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << flags << qreal(1.0) << 0 << qreal(1.0) << 0
+ << qreal(0.5) << qreal(1.0) << qreal(1.0) << qreal(1.0);
+ QTest::newRow("G: 0.5 2 0.1 0 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << flags << qreal(0.1) << 0 << qreal(1.0) << 0
+ << qreal(0.5) << qreal(0.1) << qreal(0.1) << qreal(0.1);
+ QTest::newRow("H: 0.0 2 1.0 0 1.0 1.0 1.0 1.0 1.0") << qreal(0.0) << flags << qreal(1.0) << 0 << qreal(1.0) << 0
+ << qreal(0.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
+
+ // Child ignores parent - now modify the opacity and see how it propagates
+ flags = QGraphicsItem::ItemIgnoresParentOpacity;
+ QTest::newRow("I: 1.0 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(1.0) << 0 << qreal(1.0) << flags << qreal(1.0) << 0
+ << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
+ QTest::newRow("J: 1.0 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 << qreal(0.5) << flags << qreal(0.5) << 0
+ << qreal(0.5) << qreal(0.5) << qreal(0.25) << qreal(0.25);
+ QTest::newRow("K: 1.0 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.2) << 0 << qreal(0.2) << flags << qreal(0.2) << 0
+ << qreal(0.2) << qreal(0.2) << qreal(0.04) << qreal(0.04);
+ QTest::newRow("L: 1.0 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.0) << 0 << qreal(0.0) << flags << qreal(0.0) << 0
+ << qreal(0.0) << qreal(0.0) << qreal(0.0) << qreal(0.0);
+
+ // Child ignores parent and doesn't propagate - now modify the opacity and see how it propagates
+ flags = QGraphicsItem::ItemIgnoresParentOpacity | QGraphicsItem::ItemDoesntPropagateOpacityToChildren;
+ QTest::newRow("M: 1.0 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(1.0) << 0 // p
+ << qreal(1.0) << flags // c1 (no prop)
+ << qreal(1.0) << 0 // c2
+ << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
+ QTest::newRow("M: 0.5 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 // p
+ << qreal(1.0) << flags // c1 (no prop)
+ << qreal(1.0) << 0 // c2
+ << qreal(0.5) << qreal(1.0) << qreal(1.0) << qreal(1.0);
+ QTest::newRow("M: 0.5 0 0.5 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 // p
+ << qreal(0.5) << flags // c1 (no prop)
+ << qreal(1.0) << 0 // c2
+ << qreal(0.5) << qreal(0.5) << qreal(1.0) << qreal(1.0);
+ QTest::newRow("M: 0.5 0 0.5 1 0.5 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 // p
+ << qreal(0.5) << flags // c1 (no prop)
+ << qreal(0.5) << 0 // c2
+ << qreal(0.5) << qreal(0.5) << qreal(0.5) << qreal(0.5);
+ QTest::newRow("M: 1.0 0 0.5 1 0.5 1.0 1.0 1.0 1.0") << qreal(1.0) << 0 // p
+ << qreal(0.5) << flags // c1 (no prop)
+ << qreal(0.5) << 0 // c2
+ << qreal(1.0) << qreal(0.5) << qreal(0.5) << qreal(0.5);
+}
+
+void tst_QGraphicsItem::opacity()
+{
+ QFETCH(qreal, p_opacity);
+ QFETCH(int, p_opacityFlags);
+ QFETCH(qreal, p_effectiveOpacity);
+ QFETCH(qreal, c1_opacity);
+ QFETCH(int, c1_opacityFlags);
+ QFETCH(qreal, c1_effectiveOpacity);
+ QFETCH(qreal, c2_opacity);
+ QFETCH(int, c2_opacityFlags);
+ QFETCH(qreal, c2_effectiveOpacity);
+ QFETCH(qreal, c3_effectiveOpacity);
+
+ QGraphicsRectItem *p = new QGraphicsRectItem;
+ QGraphicsRectItem *c1 = new QGraphicsRectItem(p);
+ QGraphicsRectItem *c2 = new QGraphicsRectItem(c1);
+ QGraphicsRectItem *c3 = new QGraphicsRectItem(c2);
+
+ QCOMPARE(p->opacity(), qreal(1.0));
+ QCOMPARE(p->effectiveOpacity(), qreal(1.0));
+ int opacityMask = QGraphicsItem::ItemIgnoresParentOpacity | QGraphicsItem::ItemDoesntPropagateOpacityToChildren;
+ QVERIFY(!(p->flags() & opacityMask));
+
+ p->setOpacity(p_opacity);
+ c1->setOpacity(c1_opacity);
+ c2->setOpacity(c2_opacity);
+ p->setFlags(QGraphicsItem::GraphicsItemFlags(p->flags() | p_opacityFlags));
+ c1->setFlags(QGraphicsItem::GraphicsItemFlags(c1->flags() | c1_opacityFlags));
+ c2->setFlags(QGraphicsItem::GraphicsItemFlags(c2->flags() | c2_opacityFlags));
+
+ QCOMPARE(int(p->flags() & opacityMask), p_opacityFlags);
+ QCOMPARE(int(c1->flags() & opacityMask), c1_opacityFlags);
+ QCOMPARE(int(c2->flags() & opacityMask), c2_opacityFlags);
+ QCOMPARE(p->opacity(), p_opacity);
+ QCOMPARE(p->effectiveOpacity(), p_effectiveOpacity);
+ QCOMPARE(c1->effectiveOpacity(), c1_effectiveOpacity);
+ QCOMPARE(c2->effectiveOpacity(), c2_effectiveOpacity);
+ QCOMPARE(c3->effectiveOpacity(), c3_effectiveOpacity);
+}
+
+void tst_QGraphicsItem::itemStacksBehindParent()
+{
+ QGraphicsRectItem *parent1 = new QGraphicsRectItem(QRectF(0, 0, 100, 50));
+ QGraphicsRectItem *child11 = new QGraphicsRectItem(QRectF(-10, 10, 50, 50), parent1);
+ QGraphicsRectItem *grandChild111 = new QGraphicsRectItem(QRectF(-20, 20, 50, 50), child11);
+ QGraphicsRectItem *child12 = new QGraphicsRectItem(QRectF(60, 10, 50, 50), parent1);
+ QGraphicsRectItem *grandChild121 = new QGraphicsRectItem(QRectF(70, 20, 50, 50), child12);
+
+ QGraphicsRectItem *parent2 = new QGraphicsRectItem(QRectF(0, 0, 100, 50));
+ QGraphicsRectItem *child21 = new QGraphicsRectItem(QRectF(-10, 10, 50, 50), parent2);
+ QGraphicsRectItem *grandChild211 = new QGraphicsRectItem(QRectF(-20, 20, 50, 50), child21);
+ QGraphicsRectItem *child22 = new QGraphicsRectItem(QRectF(60, 10, 50, 50), parent2);
+ QGraphicsRectItem *grandChild221 = new QGraphicsRectItem(QRectF(70, 20, 50, 50), child22);
+
+ parent1->setData(0, "parent1");
+ child11->setData(0, "child11");
+ grandChild111->setData(0, "grandChild111");
+ child12->setData(0, "child12");
+ grandChild121->setData(0, "grandChild121");
+ parent2->setData(0, "parent2");
+ child21->setData(0, "child21");
+ grandChild211->setData(0, "grandChild211");
+ child22->setData(0, "child22");
+ grandChild221->setData(0, "grandChild221");
+
+ // Disambiguate siblings
+ parent1->setZValue(1);
+ child11->setZValue(1);
+ child21->setZValue(1);
+
+ QGraphicsScene scene;
+ scene.addItem(parent1);
+ scene.addItem(parent2);
+
+ QCOMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
+ << grandChild111 << child11
+ << grandChild121 << child12 << parent1
+ << grandChild211 << child21
+ << grandChild221 << child22 << parent2));
+
+ child11->setFlag(QGraphicsItem::ItemStacksBehindParent);
+ QCOMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
+ << grandChild121 << child12 << parent1
+ << grandChild111 << child11
+ << grandChild211 << child21
+ << grandChild221 << child22 << parent2));
+
+ child12->setFlag(QGraphicsItem::ItemStacksBehindParent);
+ QCOMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
+ << parent1 << grandChild111 << child11
+ << grandChild121 << child12
+ << grandChild211 << child21
+ << grandChild221 << child22 << parent2));
+}
+
+class ClippingAndTransformsScene : public QGraphicsScene
+{
+public:
+ QList<QGraphicsItem *> drawnItems;
+protected:
+ void drawItems(QPainter *painter, int numItems, QGraphicsItem *items[],
+ const QStyleOptionGraphicsItem options[], QWidget *widget = 0)
+ {
+ drawnItems.clear();
+ for (int i = 0; i < numItems; ++i)
+ drawnItems << items[i];
+ QGraphicsScene::drawItems(painter, numItems, items, options, widget);
+ }
+};
+
+void tst_QGraphicsItem::nestedClipping()
+{
+ ClippingAndTransformsScene scene;
+ scene.setSceneRect(-50, -50, 200, 200);
+
+ QGraphicsRectItem *root = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
+ root->setBrush(QColor(0, 0, 255));
+ root->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ QGraphicsRectItem *l1 = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
+ l1->setParentItem(root);
+ l1->setPos(-50, 0);
+ l1->setBrush(QColor(255, 0, 0));
+ l1->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ QGraphicsEllipseItem *l2 = new QGraphicsEllipseItem(QRectF(0, 0, 100, 100));
+ l2->setParentItem(l1);
+ l2->setPos(50, 50);
+ l2->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ l2->setBrush(QColor(255, 255, 0));
+ QGraphicsRectItem *l3 = new QGraphicsRectItem(QRectF(0, 0, 25, 25));
+ l3->setParentItem(l2);
+ l3->setBrush(QColor(0, 255, 0));
+ l3->setPos(50 - 12, -12);
+
+ scene.addItem(root);
+
+ root->setData(0, "root");
+ l1->setData(0, "l1");
+ l2->setData(0, "l2");
+ l3->setData(0, "l3");
+
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(250);
+
+ QList<QGraphicsItem *> expected;
+ expected << root << l1 << l2 << l3;
+ QCOMPARE(scene.drawnItems, expected);
+
+ QImage image(200, 200, QImage::Format_ARGB32_Premultiplied);
+ image.fill(0);
+
+ QPainter painter(&image);
+ scene.render(&painter);
+ painter.end();
+
+ // Check transparent areas
+ QCOMPARE(image.pixel(100, 25), qRgba(0, 0, 0, 0));
+ QCOMPARE(image.pixel(100, 175), qRgba(0, 0, 0, 0));
+ QCOMPARE(image.pixel(25, 100), qRgba(0, 0, 0, 0));
+ QCOMPARE(image.pixel(175, 100), qRgba(0, 0, 0, 0));
+ QCOMPARE(image.pixel(70, 80), qRgba(255, 0, 0, 255));
+ QCOMPARE(image.pixel(80, 130), qRgba(255, 255, 0, 255));
+ QCOMPARE(image.pixel(92, 105), qRgba(0, 255, 0, 255));
+ QCOMPARE(image.pixel(105, 105), qRgba(0, 0, 255, 255));
+#if 0
+ // Enable this to compare if the test starts failing.
+ image.save("nestedClipping_reference.png");
+#endif
+}
+
+class TransformDebugItem : public QGraphicsRectItem
+{
+public:
+ TransformDebugItem()
+ : QGraphicsRectItem(QRectF(-10, -10, 20, 20))
+ {
+ setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
+ }
+
+ QTransform x;
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
+ QWidget *widget = 0)
+ {
+ x = painter->worldTransform();
+ QGraphicsRectItem::paint(painter, option, widget);
+ }
+};
+
+void tst_QGraphicsItem::nestedClippingTransforms()
+{
+ TransformDebugItem *rootClipper = new TransformDebugItem;
+ rootClipper->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ TransformDebugItem *child = new TransformDebugItem;
+ child->setParentItem(rootClipper);
+ child->setPos(2, 2);
+ TransformDebugItem *grandChildClipper = new TransformDebugItem;
+ grandChildClipper->setParentItem(child);
+ grandChildClipper->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ grandChildClipper->setPos(4, 4);
+ TransformDebugItem *greatGrandChild = new TransformDebugItem;
+ greatGrandChild->setPos(2, 2);
+ greatGrandChild->setParentItem(grandChildClipper);
+ TransformDebugItem *grandChildClipper2 = new TransformDebugItem;
+ grandChildClipper2->setParentItem(child);
+ grandChildClipper2->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ grandChildClipper2->setPos(8, 8);
+ TransformDebugItem *greatGrandChild2 = new TransformDebugItem;
+ greatGrandChild2->setPos(2, 2);
+ greatGrandChild2->setParentItem(grandChildClipper2);
+ TransformDebugItem *grandChildClipper3 = new TransformDebugItem;
+ grandChildClipper3->setParentItem(child);
+ grandChildClipper3->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ grandChildClipper3->setPos(12, 12);
+ TransformDebugItem *greatGrandChild3 = new TransformDebugItem;
+ greatGrandChild3->setPos(2, 2);
+ greatGrandChild3->setParentItem(grandChildClipper3);
+
+ QGraphicsScene scene;
+ scene.addItem(rootClipper);
+
+ QImage image(scene.itemsBoundingRect().size().toSize(), QImage::Format_ARGB32_Premultiplied);
+ image.fill(0);
+ QPainter p(&image);
+ scene.render(&p);
+ p.end();
+
+ QCOMPARE(rootClipper->x, QTransform(1, 0, 0, 0, 1, 0, 10, 10, 1));
+ QCOMPARE(child->x, QTransform(1, 0, 0, 0, 1, 0, 12, 12, 1));
+ QCOMPARE(grandChildClipper->x, QTransform(1, 0, 0, 0, 1, 0, 16, 16, 1));
+ QCOMPARE(greatGrandChild->x, QTransform(1, 0, 0, 0, 1, 0, 18, 18, 1));
+ QCOMPARE(grandChildClipper2->x, QTransform(1, 0, 0, 0, 1, 0, 20, 20, 1));
+ QCOMPARE(greatGrandChild2->x, QTransform(1, 0, 0, 0, 1, 0, 22, 22, 1));
+ QCOMPARE(grandChildClipper3->x, QTransform(1, 0, 0, 0, 1, 0, 24, 24, 1));
+ QCOMPARE(greatGrandChild3->x, QTransform(1, 0, 0, 0, 1, 0, 26, 26, 1));
+}
+
+void tst_QGraphicsItem::sceneTransformCache()
+{
+ // Test that an item's scene transform is updated correctly when the
+ // parent is transformed.
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect = scene.addRect(0, 0, 100, 100);
+ QGraphicsRectItem *rect2 = scene.addRect(0, 0, 100, 100);
+ rect2->setParentItem(rect);
+ rect2->rotate(90);
+ rect->translate(0, 50);
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+
+ rect->translate(0, 100);
+ QTransform x;
+ x.translate(0, 150);
+ x.rotate(90);
+ QCOMPARE(rect2->sceneTransform(), x);
+
+ scene.removeItem(rect);
+
+ //Crazy use case : rect4 child of rect3 so the transformation of rect4 will be cached.Good!
+ //We remove rect4 from the scene, then the validTransform bit flag is set to 0 and the index of the cache
+ //add to the freeTransformSlots. The problem was that sceneTransformIndex was not set to -1 so if a new item arrive
+ //with a child (rect6) that will be cached then it will take the freeSlot (ex rect4) and put it his transform. But if rect4 is
+ //added back to the scene then it will set the transform to his old sceneTransformIndex value that will erase the new
+ //value of rect6 so rect6 transform will be wrong.
+ QGraphicsRectItem *rect3 = scene.addRect(0, 0, 100, 100);
+ QGraphicsRectItem *rect4 = scene.addRect(0, 0, 100, 100);
+ rect3->setPos(QPointF(10,10));
+
+ rect4->setParentItem(rect3);
+ rect4->setPos(QPointF(10,10));
+
+ QCOMPARE(rect4->mapToScene(rect4->boundingRect().topLeft()), QPointF(20,20));
+
+ scene.removeItem(rect4);
+ //rect4 transform is local only
+ QCOMPARE(rect4->mapToScene(rect4->boundingRect().topLeft()), QPointF(10,10));
+
+ QGraphicsRectItem *rect5 = scene.addRect(0, 0, 100, 100);
+ QGraphicsRectItem *rect6 = scene.addRect(0, 0, 100, 100);
+ rect5->setPos(QPointF(20,20));
+
+ rect6->setParentItem(rect5);
+ rect6->setPos(QPointF(10,10));
+ //test if rect6 transform is ok
+ QCOMPARE(rect6->mapToScene(rect6->boundingRect().topLeft()), QPointF(30,30));
+
+ scene.addItem(rect4);
+
+ QCOMPARE(rect4->mapToScene(rect4->boundingRect().topLeft()), QPointF(10,10));
+ //test if rect6 transform is still correct
+ QCOMPARE(rect6->mapToScene(rect6->boundingRect().topLeft()), QPointF(30,30));
+}
+
+void tst_QGraphicsItem::tabChangesFocus_data()
+{
+ QTest::addColumn<bool>("tabChangesFocus");
+ QTest::newRow("tab changes focus") << true;
+ QTest::newRow("tab doesn't change focus") << false;
+}
+
+void tst_QGraphicsItem::tabChangesFocus()
+{
+ QFETCH(bool, tabChangesFocus);
+
+ QGraphicsScene scene;
+ QGraphicsTextItem *item = scene.addText("Hello");
+ item->setTabChangesFocus(tabChangesFocus);
+ item->setTextInteractionFlags(Qt::TextEditorInteraction);
+ item->setFocus();
+
+ QDial *dial1 = new QDial;
+ QGraphicsView *view = new QGraphicsView(&scene);
+ QDial *dial2 = new QDial;
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(dial1);
+ layout->addWidget(view);
+ layout->addWidget(dial2);
+
+ QWidget widget;
+ widget.setLayout(layout);
+ widget.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&widget);
+#endif
+
+ dial1->setFocus();
+ QTest::qWait(125);
+ QVERIFY(dial1->hasFocus());
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QTest::qWait(125);
+ QVERIFY(view->hasFocus());
+ QVERIFY(item->hasFocus());
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QTest::qWait(125);
+
+ if (tabChangesFocus) {
+ QVERIFY(!view->hasFocus());
+ QVERIFY(!item->hasFocus());
+ QVERIFY(dial2->hasFocus());
+ } else {
+ QVERIFY(view->hasFocus());
+ QVERIFY(item->hasFocus());
+ QCOMPARE(item->toPlainText(), QString("\tHello"));
+ }
+}
+
+void tst_QGraphicsItem::cacheMode()
+{
+ QGraphicsScene scene(0, 0, 100, 100);
+ QGraphicsView view(&scene);
+ view.resize(150, 150);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+
+ EventTester *tester = new EventTester;
+ EventTester *testerChild = new EventTester;
+ testerChild->setParentItem(tester);
+ EventTester *testerChild2 = new EventTester;
+ testerChild2->setParentItem(testerChild);
+ testerChild2->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+
+ scene.addItem(tester);
+ QTest::qWait(250);
+
+ for (int i = 0; i < 2; ++i) {
+ // No visual change.
+ QCOMPARE(tester->repaints, 1);
+ QCOMPARE(testerChild->repaints, 1);
+ QCOMPARE(testerChild2->repaints, 1);
+ tester->setCacheMode(QGraphicsItem::NoCache);
+ testerChild->setCacheMode(QGraphicsItem::NoCache);
+ testerChild2->setCacheMode(QGraphicsItem::NoCache);
+ QTest::qWait(250);
+ QCOMPARE(tester->repaints, 1);
+ QCOMPARE(testerChild->repaints, 1);
+ QCOMPARE(testerChild2->repaints, 1);
+ tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ testerChild->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ testerChild2->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ QTest::qWait(250);
+ }
+
+ // The first move causes a repaint as the item is painted into its pixmap.
+ // (Only occurs if the item has previously been painted without cache).
+ tester->setPos(10, 10);
+ testerChild->setPos(10, 10);
+ testerChild2->setPos(10, 10);
+ QTest::qWait(250);
+ QCOMPARE(tester->repaints, 2);
+ QCOMPARE(testerChild->repaints, 2);
+ QCOMPARE(testerChild2->repaints, 2);
+
+ // Consecutive moves should not repaint.
+ tester->setPos(20, 20);
+ testerChild->setPos(20, 20);
+ testerChild2->setPos(20, 20);
+ QTest::qWait(250);
+ QCOMPARE(tester->repaints, 2);
+ QCOMPARE(testerChild->repaints, 2);
+ QCOMPARE(testerChild2->repaints, 2);
+
+ // Translating does not result in a repaint.
+ tester->translate(10, 10);
+ QTest::qWait(250);
+ QCOMPARE(tester->repaints, 2);
+ QCOMPARE(testerChild->repaints, 2);
+ QCOMPARE(testerChild2->repaints, 2);
+
+ // Rotating results in a repaint.
+ tester->rotate(45);
+ QTest::qWait(250);
+ QCOMPARE(tester->repaints, 3);
+ QCOMPARE(testerChild->repaints, 3);
+ QCOMPARE(testerChild2->repaints, 2);
+
+ // Change to ItemCoordinateCache (triggers repaint).
+ tester->setCacheMode(QGraphicsItem::ItemCoordinateCache); // autosize
+ testerChild->setCacheMode(QGraphicsItem::ItemCoordinateCache); // autosize
+ testerChild2->setCacheMode(QGraphicsItem::ItemCoordinateCache); // autosize
+ QTest::qWait(250);
+ QCOMPARE(tester->repaints, 4);
+ QCOMPARE(testerChild->repaints, 4);
+ QCOMPARE(testerChild2->repaints, 3);
+
+ // Rotating items with ItemCoordinateCache doesn't cause a repaint.
+ tester->rotate(22);
+ testerChild->rotate(22);
+ testerChild2->rotate(22);
+ QTest::qWait(250);
+ QCOMPARE(tester->repaints, 4);
+ QCOMPARE(testerChild->repaints, 4);
+ QCOMPARE(testerChild2->repaints, 3);
+
+ // Explicit update causes a repaint.
+ tester->update(0, 0, 5, 5);
+ QTest::qWait(250);
+ QCOMPARE(tester->repaints, 5);
+ QCOMPARE(testerChild->repaints, 4);
+ QCOMPARE(testerChild2->repaints, 3);
+
+ // Updating outside the item's bounds does not cause a repaint.
+ tester->update(10, 10, 5, 5);
+ QTest::qWait(250);
+ QCOMPARE(tester->repaints, 5);
+ QCOMPARE(testerChild->repaints, 4);
+ QCOMPARE(testerChild2->repaints, 3);
+
+ // Resizing an item should cause a repaint of that item. (because of
+ // autosize).
+ tester->setGeometry(QRectF(-15, -15, 30, 30));
+ QTest::qWait(250);
+ QCOMPARE(tester->repaints, 6);
+ QCOMPARE(testerChild->repaints, 4);
+ QCOMPARE(testerChild2->repaints, 3);
+
+ // Set fixed size.
+ tester->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(30, 30));
+ testerChild->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(30, 30));
+ testerChild2->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(30, 30));
+ QTest::qWait(250);
+ QCOMPARE(tester->repaints, 7);
+ QCOMPARE(testerChild->repaints, 5);
+ QCOMPARE(testerChild2->repaints, 4);
+
+ // Resizing the item should cause a repaint.
+ testerChild->setGeometry(QRectF(-15, -15, 30, 30));
+ QTest::qWait(250);
+ QCOMPARE(tester->repaints, 7);
+ QCOMPARE(testerChild->repaints, 6);
+ QCOMPARE(testerChild2->repaints, 4);
+
+ // Scaling the view does not cause a repaint.
+ view.scale(0.7, 0.7);
+ QTest::qWait(250);
+ QCOMPARE(tester->repaints, 7);
+ QCOMPARE(testerChild->repaints, 6);
+ QCOMPARE(testerChild2->repaints, 4);
+
+ // Switch to device coordinate cache.
+ tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ testerChild->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ testerChild2->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ QTest::qWait(250);
+ QCOMPARE(tester->repaints, 8);
+ QCOMPARE(testerChild->repaints, 7);
+ QCOMPARE(testerChild2->repaints, 5);
+
+ // Scaling the view back should cause repaints for two of the items.
+ view.setTransform(QTransform());
+ QTest::qWait(250);
+ QCOMPARE(tester->repaints, 9);
+ QCOMPARE(testerChild->repaints, 8);
+ QCOMPARE(testerChild2->repaints, 5);
+
+ // Rotating the base item (perspective) should repaint two items.
+ tester->setTransform(QTransform().rotate(10, Qt::XAxis));
+ QTest::qWait(250);
+ QCOMPARE(tester->repaints, 10);
+ QCOMPARE(testerChild->repaints, 9);
+ QCOMPARE(testerChild2->repaints, 5);
+
+ // Moving the middle item should case a repaint even if it's a move,
+ // because the parent is rotated with a perspective.
+ testerChild->setPos(1, 1);
+ QTest::qWait(250);
+ QCOMPARE(tester->repaints, 10);
+ QCOMPARE(testerChild->repaints, 10);
+ QCOMPARE(testerChild2->repaints, 5);
+
+ // Make a huge item
+ tester->setGeometry(QRectF(-4000, -4000, 8000, 8000));
+ QTest::qWait(250);
+ QCOMPARE(tester->repaints, 11);
+ QCOMPARE(testerChild->repaints, 10);
+ QCOMPARE(testerChild2->repaints, 5);
+
+ // Move the large item - will cause a repaint as the
+ // cache is clipped.
+ tester->setPos(5, 0);
+ QTest::qWait(250);
+ QCOMPARE(tester->repaints, 12);
+ QCOMPARE(testerChild->repaints, 10);
+ QCOMPARE(testerChild2->repaints, 5);
+}
+
+QTEST_MAIN(tst_QGraphicsItem)
+#include "tst_qgraphicsitem.moc"
+#endif