summaryrefslogtreecommitdiff
path: root/tests/auto/widgets/graphicsview
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/widgets/graphicsview')
-rw-r--r--tests/auto/widgets/graphicsview/graphicsview.pro32
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsanchorlayout/qgraphicsanchorlayout.pro5
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp2091
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/qgraphicsanchorlayout1.pro5
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp3111
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicseffectsource/qgraphicseffectsource.pro7
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicseffectsource/tst_qgraphicseffectsource.cpp422
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsgridlayout/.gitignore1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsgridlayout/qgraphicsgridlayout.pro6
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp3465
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsitem/.gitignore1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro9
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp11402
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsitemanimation/.gitignore1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsitemanimation/qgraphicsitemanimation.pro6
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp192
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicslayout/.gitignore1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicslayout/qgraphicslayout.pro9
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp992
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicslayoutitem/.gitignore1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicslayoutitem/qgraphicslayoutitem.pro5
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicslayoutitem/tst_qgraphicslayoutitem.cpp376
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicslinearlayout/.gitignore1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicslinearlayout/qgraphicslinearlayout.pro5
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp1650
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsobject/qgraphicsobject.pro7
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsobject/tst_qgraphicsobject.cpp297
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicspixmapitem/.gitignore1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicspixmapitem/qgraphicspixmapitem.pro5
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp427
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicspolygonitem/.gitignore1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicspolygonitem/qgraphicspolygonitem.pro5
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicspolygonitem/tst_qgraphicspolygonitem.cpp349
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsproxywidget/.gitignore1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsproxywidget/qgraphicsproxywidget.pro8
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp3649
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/.gitignore1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/Ash_European.jpgbin0 -> 4751 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/graphicsScene_selection.databin0 -> 854488 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/images.qrc5
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro20
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-45-deg-left.pngbin0 -> 2181 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-45-deg-right.pngbin0 -> 1953 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-scale-2x.pngbin0 -> 2399 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-translate-0-50.pngbin0 -> 1872 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-translate-50-0.pngbin0 -> 1884 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed-clip-ellipse.pngbin0 -> 1819 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed-clip-rect.pngbin0 -> 1255 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed.pngbin0 -> 1896 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-bottomleft-untransformed.pngbin0 -> 1560 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-bottomright-untransformed.pngbin0 -> 1550 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-topleft-untransformed.pngbin0 -> 1566 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-topright-untransformed.pngbin0 -> 1547 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottom-bottomright-untransformed.pngbin0 -> 1172 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottom-topleft-untransformed.pngbin0 -> 1690 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomleft-all-untransformed.pngbin0 -> 1736 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomleft-topleft-untransformed.pngbin0 -> 1642 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomright-all-untransformed.pngbin0 -> 1093 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomright-topleft-untransformed.pngbin0 -> 1661 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/left-bottomright-untransformed.pngbin0 -> 1289 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/left-topleft-untransformed.pngbin0 -> 1823 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/right-bottomright-untransformed.pngbin0 -> 1236 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/right-topleft-untransformed.pngbin0 -> 1839 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/top-bottomright-untransformed.pngbin0 -> 1174 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/top-topleft-untransformed.pngbin0 -> 1703 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topleft-all-untransformed.pngbin0 -> 1973 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topleft-topleft-untransformed.pngbin0 -> 1650 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topright-all-untransformed.pngbin0 -> 2018 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topright-topleft-untransformed.pngbin0 -> 1669 bytes
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp4710
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicssceneindex/qgraphicssceneindex.pro6
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp366
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicstransform/qgraphicstransform.pro6
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicstransform/tst_qgraphicstransform.cpp408
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsview/.gitignore1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsview/qgraphicsview.pro9
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp4558
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview_2.cpp976
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicswidget/.gitignore1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicswidget/qgraphicswidget.pro10
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp3361
81 files changed, 42984 insertions, 0 deletions
diff --git a/tests/auto/widgets/graphicsview/graphicsview.pro b/tests/auto/widgets/graphicsview/graphicsview.pro
new file mode 100644
index 0000000000..9955e45b64
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/graphicsview.pro
@@ -0,0 +1,32 @@
+TEMPLATE=subdirs
+SUBDIRS=\
+ qgraphicsanchorlayout \
+ qgraphicsanchorlayout1 \
+ qgraphicseffectsource \
+ qgraphicsgridlayout \
+ qgraphicsitem \
+ qgraphicsitemanimation \
+ qgraphicslayout \
+ qgraphicslayoutitem \
+ qgraphicslinearlayout \
+ qgraphicsobject \
+ qgraphicspixmapitem \
+ qgraphicspolygonitem \
+ qgraphicsproxywidget \
+ qgraphicsscene \
+ qgraphicssceneindex \
+ qgraphicstransform \
+ qgraphicsview \
+ qgraphicswidget \
+
+!contains(QT_CONFIG, private_tests): SUBDIRS -= \
+ qgraphicsanchorlayout \
+ qgraphicsanchorlayout1 \
+ qgraphicsitem \
+ qgraphicsscene \
+ qgraphicssceneindex \
+
+# These tests require the cleanlooks style
+!contains(styles, cleanlooks):SUBDIRS -= \
+ qgraphicsproxywidget \
+ qgraphicswidget \
diff --git a/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/qgraphicsanchorlayout.pro b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/qgraphicsanchorlayout.pro
new file mode 100644
index 0000000000..5aa2936e3e
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/qgraphicsanchorlayout.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets widgets-private
+QT += core-private gui-private
+SOURCES += tst_qgraphicsanchorlayout.cpp
+CONFIG += parallel_test
diff --git a/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp
new file mode 100644
index 0000000000..5dbe501ea8
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp
@@ -0,0 +1,2091 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.1, 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtWidgets/qgraphicsanchorlayout.h>
+#include <private/qgraphicsanchorlayout_p.h>
+#include <QtWidgets/qgraphicswidget.h>
+#include <QtWidgets/qgraphicsproxywidget.h>
+#include <QtWidgets/qgraphicsview.h>
+#include <QtWidgets/qwindowsstyle.h>
+
+
+class tst_QGraphicsAnchorLayout : public QObject {
+ Q_OBJECT
+
+public:
+ tst_QGraphicsAnchorLayout() : QObject() {
+ hasSimplification = qgetenv("QT_ANCHORLAYOUT_NO_SIMPLIFICATION").isEmpty();
+ }
+
+private:
+ bool hasSimplification;
+
+private slots:
+ void simple();
+ void simple_center();
+ void simple_semifloat();
+ void layoutDirection();
+ void diagonal();
+ void parallel();
+ void parallel2();
+ void snake();
+ void snakeOppositeDirections();
+ void fairDistribution();
+ void fairDistributionOppositeDirections();
+ void proportionalPreferred();
+ void example();
+ void setSpacing();
+ void styleDefaults();
+ void hardComplexS60();
+ void stability();
+ void delete_anchor();
+ void conflicts();
+ void sizePolicy();
+ void floatConflict();
+ void infiniteMaxSizes();
+ void simplifiableUnfeasible();
+ void simplificationVsOrder();
+ void parallelSimplificationOfCenter();
+ void simplificationVsRedundance();
+ void spacingPersistency();
+ void snakeParallelWithLayout();
+ void parallelToHalfLayout();
+ void globalSpacing();
+ void graphicsAnchorHandling();
+ void invalidHierarchyCheck();
+};
+
+class RectWidget : public QGraphicsWidget
+{
+public:
+ RectWidget(QGraphicsItem *parent = 0) : QGraphicsWidget(parent){}
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+ painter->drawRoundRect(rect());
+ painter->drawLine(rect().topLeft(), rect().bottomRight());
+ painter->drawLine(rect().bottomLeft(), rect().topRight());
+ }
+};
+
+static QGraphicsWidget *createItem(const QSizeF &minimum = QSizeF(100.0, 100.0),
+ const QSizeF &preferred = QSize(150.0, 100.0),
+ const QSizeF &maximum = QSizeF(200.0, 100.0),
+ const QString &name = QString())
+{
+ QGraphicsWidget *w = new RectWidget;
+ w->setMinimumSize(minimum);
+ w->setPreferredSize(preferred);
+ w->setMaximumSize(maximum);
+ w->setData(0, name);
+ return w;
+}
+
+static void setAnchor(QGraphicsAnchorLayout *l,
+ QGraphicsLayoutItem *firstItem,
+ Qt::AnchorPoint firstEdge,
+ QGraphicsLayoutItem *secondItem,
+ Qt::AnchorPoint secondEdge,
+ qreal spacing = 0)
+{
+ QGraphicsAnchor *anchor = l->addAnchor(firstItem, firstEdge, secondItem, secondEdge);
+ anchor->setSpacing(spacing);
+}
+
+static bool checkReverseDirection(QGraphicsWidget *widget)
+{
+ QGraphicsLayout *layout = widget->layout();
+ qreal left, top, right, bottom;
+ layout->getContentsMargins(&left, &top, &right, &bottom);
+ widget->setLayoutDirection(Qt::LeftToRight);
+ QApplication::processEvents();
+ const QRectF layoutGeometry = layout->geometry();
+ QMap<QGraphicsLayoutItem *, QRectF> geometries;
+ for (int i = 0; i < layout->count(); ++i) {
+ QGraphicsLayoutItem *item = layout->itemAt(i);
+ geometries.insert(item, item->geometry());
+ }
+ widget->setLayoutDirection(Qt::RightToLeft);
+ QApplication::processEvents();
+ layoutGeometry.adjusted(+right, +top, -left, -bottom);
+ for (int i = 0; i < layout->count(); ++i) {
+ QGraphicsLayoutItem *item = layout->itemAt(i);
+ const QRectF rightToLeftGeometry = item->geometry();
+ const QRectF leftToRightGeometry = geometries.value(item);
+ QRectF expectedGeometry = leftToRightGeometry;
+ expectedGeometry.moveRight(layoutGeometry.right() - leftToRightGeometry.left());
+ if (expectedGeometry != rightToLeftGeometry) {
+ qDebug() << "layout->geometry():" << layoutGeometry
+ << "expected:" << expectedGeometry
+ << "actual:" << rightToLeftGeometry;
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool layoutHasConflict(QGraphicsAnchorLayout *l)
+{
+ return QGraphicsAnchorLayoutPrivate::get(l)->hasConflicts();
+}
+
+static bool usedSimplex(QGraphicsAnchorLayout *l, Qt::Orientation o)
+{
+ QGraphicsAnchorLayoutPrivate::Orientation oo = (o == Qt::Horizontal) ?
+ QGraphicsAnchorLayoutPrivate::Horizontal :
+ QGraphicsAnchorLayoutPrivate::Vertical;
+
+ return QGraphicsAnchorLayoutPrivate::get(l)->lastCalculationUsedSimplex[oo];
+}
+
+void tst_QGraphicsAnchorLayout::simple()
+{
+ QGraphicsWidget *w1 = createItem();
+ QGraphicsWidget *w2 = createItem();
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+
+ // Horizontal
+ l->addAnchor(l, Qt::AnchorLeft, w1, Qt::AnchorLeft);
+ l->addAnchor(w1, Qt::AnchorRight, w2, Qt::AnchorLeft);
+ l->addAnchor(w2, Qt::AnchorRight, l, Qt::AnchorRight);
+
+ // Vertical
+ l->addAnchors(l, w1, Qt::Vertical);
+ l->addAnchors(l, w2, Qt::Vertical);
+
+ QCOMPARE(l->count(), 2);
+
+ QGraphicsWidget p;
+ p.setLayout(l);
+ p.adjustSize();
+
+ if (hasSimplification) {
+ QVERIFY(!usedSimplex(l, Qt::Horizontal));
+ QVERIFY(!usedSimplex(l, Qt::Vertical));
+ }
+}
+
+void tst_QGraphicsAnchorLayout::simple_center()
+{
+ QSizeF minSize(10, 10);
+ QSizeF pref(50, 10);
+ QSizeF maxSize(100, 10);
+
+ QGraphicsWidget *a = createItem(minSize, pref, maxSize, "a");
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize, "b");
+ QGraphicsWidget *c = createItem(minSize, pref, maxSize, "c");
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ // horizontal
+ setAnchor(l, l, Qt::AnchorLeft, a, Qt::AnchorLeft, 0);
+ setAnchor(l, a, Qt::AnchorRight, b, Qt::AnchorLeft, 0);
+ setAnchor(l, b, Qt::AnchorRight, l, Qt::AnchorRight, 0);
+ setAnchor(l, a, Qt::AnchorHorizontalCenter, c, Qt::AnchorLeft, 0);
+ setAnchor(l, c, Qt::AnchorRight, b, Qt::AnchorHorizontalCenter, 0);
+
+ // vertical
+ setAnchor(l, l, Qt::AnchorTop, a, Qt::AnchorTop, 0);
+ setAnchor(l, l, Qt::AnchorTop, b, Qt::AnchorTop, 0);
+ setAnchor(l, a, Qt::AnchorBottom, c, Qt::AnchorTop, 0);
+ setAnchor(l, b, Qt::AnchorBottom, c, Qt::AnchorTop, 0);
+ setAnchor(l, c, Qt::AnchorBottom, l, Qt::AnchorBottom, 0);
+
+ QCOMPARE(l->count(), 3);
+
+ QGraphicsWidget *p = new QGraphicsWidget(0, Qt::Window);
+ p->setLayout(l);
+
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QCOMPARE(layoutMinimumSize, QSizeF(20, 20));
+
+ QSizeF layoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+ QCOMPARE(layoutMaximumSize, QSizeF(200, 20));
+
+ if (hasSimplification) {
+ QVERIFY(usedSimplex(l, Qt::Horizontal));
+ QVERIFY(!usedSimplex(l, Qt::Vertical));
+ }
+
+ delete p;
+}
+
+void tst_QGraphicsAnchorLayout::simple_semifloat()
+{
+ // Useful for testing simplification between A_left and B_left.
+ // Unfortunately the only way to really test that now is to manually inspect the
+ // simplified graph.
+ QSizeF minSize(10, 10);
+ QSizeF pref(50, 10);
+ QSizeF maxSize(100, 10);
+
+ QGraphicsWidget *A = createItem(minSize, pref, maxSize, "A");
+ QGraphicsWidget *B = createItem(minSize, pref, maxSize, "B");
+ QGraphicsWidget *a = createItem(minSize, pref, maxSize, "a");
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize, "b");
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+
+ // horizontal
+ setAnchor(l, l, Qt::AnchorLeft, A, Qt::AnchorLeft, 0);
+ setAnchor(l, A, Qt::AnchorRight, B, Qt::AnchorLeft, 0);
+ setAnchor(l, B, Qt::AnchorRight, l, Qt::AnchorRight, 0);
+
+ setAnchor(l, A, Qt::AnchorLeft, a, Qt::AnchorLeft, 0);
+ setAnchor(l, B, Qt::AnchorLeft, b, Qt::AnchorLeft, 0);
+
+ // vertical
+ setAnchor(l, l, Qt::AnchorTop, A, Qt::AnchorTop, 0);
+ setAnchor(l, l, Qt::AnchorTop, B, Qt::AnchorTop, 0);
+ setAnchor(l, A, Qt::AnchorBottom, a, Qt::AnchorTop, 0);
+ setAnchor(l, B, Qt::AnchorBottom, b, Qt::AnchorTop, 0);
+ setAnchor(l, a, Qt::AnchorBottom, l, Qt::AnchorBottom, 0);
+ setAnchor(l, b, Qt::AnchorBottom, l, Qt::AnchorBottom, 0);
+
+ QCOMPARE(l->count(), 4);
+
+ QGraphicsWidget *p = new QGraphicsWidget(0, Qt::Window);
+ p->setLayout(l);
+
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QCOMPARE(layoutMinimumSize, QSizeF(20, 20));
+
+ QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize), QSizeF(100, 20));
+
+ QSizeF layoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+ QCOMPARE(layoutMaximumSize, QSizeF(200, 20));
+
+ delete p;
+}
+
+void tst_QGraphicsAnchorLayout::layoutDirection()
+{
+ QSizeF minSize(10, 10);
+ QSizeF pref(50, 10);
+ QSizeF maxSize(100, 10);
+
+ QGraphicsWidget *a = createItem(minSize, pref, maxSize, "a");
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize, "b");
+ QGraphicsWidget *c = createItem(minSize, pref, QSizeF(100, 20), "c");
+
+ a->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ b->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ c->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 5, 10, 15);
+ // horizontal
+ setAnchor(l, l, Qt::AnchorLeft, a, Qt::AnchorLeft, 0);
+ setAnchor(l, a, Qt::AnchorRight, b, Qt::AnchorLeft, 0);
+ setAnchor(l, b, Qt::AnchorRight, l, Qt::AnchorRight, 0);
+ setAnchor(l, a, Qt::AnchorHorizontalCenter, c, Qt::AnchorLeft, 0);
+ setAnchor(l, c, Qt::AnchorRight, b, Qt::AnchorHorizontalCenter, 0);
+
+ // vertical
+ setAnchor(l, l, Qt::AnchorTop, a, Qt::AnchorTop, 0);
+ setAnchor(l, l, Qt::AnchorTop, b, Qt::AnchorTop, 0);
+ setAnchor(l, a, Qt::AnchorBottom, c, Qt::AnchorTop, 0);
+ setAnchor(l, b, Qt::AnchorBottom, c, Qt::AnchorTop, 0);
+ setAnchor(l, c, Qt::AnchorBottom, l, Qt::AnchorBottom, 0);
+
+ QCOMPARE(l->count(), 3);
+
+ QGraphicsWidget *p = new QGraphicsWidget(0, Qt::Window);
+ p->setLayoutDirection(Qt::LeftToRight);
+ p->setLayout(l);
+
+ QGraphicsScene scene;
+ QGraphicsView *view = new QGraphicsView(&scene);
+ scene.addItem(p);
+ p->show();
+ view->show();
+
+ QVERIFY(p->layout());
+ QCOMPARE(checkReverseDirection(p), true);
+
+ if (hasSimplification) {
+ QVERIFY(usedSimplex(l, Qt::Horizontal));
+ QVERIFY(!usedSimplex(l, Qt::Vertical));
+ }
+
+ delete p;
+ delete view;
+}
+
+void tst_QGraphicsAnchorLayout::diagonal()
+{
+ QSizeF minSize(10, 100);
+ QSizeF pref(70, 100);
+ QSizeF maxSize(100, 100);
+
+ QGraphicsWidget *a = createItem(minSize, pref, maxSize, "A");
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize, "B");
+ QGraphicsWidget *c = createItem(minSize, pref, maxSize, "C");
+ QGraphicsWidget *d = createItem(minSize, pref, maxSize, "D");
+ QGraphicsWidget *e = createItem(minSize, pref, maxSize, "E");
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ // vertical
+ l->addAnchor(a, Qt::AnchorTop, l, Qt::AnchorTop);
+ l->addAnchor(b, Qt::AnchorTop, l, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorTop, a, Qt::AnchorBottom);
+ l->addAnchor(c, Qt::AnchorTop, b, Qt::AnchorBottom);
+ l->addAnchor(c, Qt::AnchorBottom, d, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorBottom, e, Qt::AnchorTop);
+ l->addAnchor(d, Qt::AnchorBottom, l, Qt::AnchorBottom);
+ l->addAnchor(e, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ // horizontal
+ l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+ l->addAnchor(l, Qt::AnchorLeft, d, Qt::AnchorLeft);
+ l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorLeft);
+
+ l->addAnchor(a, Qt::AnchorRight, c, Qt::AnchorLeft);
+ l->addAnchor(c, Qt::AnchorRight, e, Qt::AnchorLeft);
+
+ l->addAnchor(b, Qt::AnchorRight, l, Qt::AnchorRight);
+ l->addAnchor(e, Qt::AnchorRight, l, Qt::AnchorRight);
+ l->addAnchor(d, Qt::AnchorRight, e, Qt::AnchorLeft);
+
+ QCOMPARE(l->count(), 5);
+
+ QGraphicsWidget p;
+ p.setLayout(l);
+
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QSizeF layoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+ QSizeF layoutPreferredSize = l->effectiveSizeHint(Qt::PreferredSize);
+
+ QCOMPARE(layoutMinimumSize, QSizeF(30.0, 300.0));
+ QCOMPARE(layoutPreferredSize, QSizeF(170.0, 300.0));
+ QCOMPARE(layoutMaximumSize, QSizeF(190.0, 300.0));
+
+ p.resize(layoutMinimumSize);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 10.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(10.0, 0.0, 20.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(10.0, 100.0, 10.0, 100.0));
+ QCOMPARE(d->geometry(), QRectF(0.0, 200.0, 20.0, 100.0));
+ QCOMPARE(e->geometry(), QRectF(20.0, 200.0, 10.0, 100.0));
+ QCOMPARE(p.size(), layoutMinimumSize);
+
+ p.resize(layoutPreferredSize);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 70.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(70.0, 0.0, 100.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(70.0, 100.0, 30.0, 100.0));
+ QCOMPARE(d->geometry(), QRectF(0.0, 200.0, 100.0, 100.0));
+ QCOMPARE(e->geometry(), QRectF(100.0, 200.0, 70.0, 100.0));
+ QCOMPARE(p.size(), layoutPreferredSize);
+
+ p.resize(layoutMaximumSize);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 90.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(90.0, 0.0, 100.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(90.0, 100.0, 10.0, 100.0));
+ QCOMPARE(d->geometry(), QRectF(0.0, 200.0, 100.0, 100.0));
+ QCOMPARE(e->geometry(), QRectF(100.0, 200.0, 90.0, 100.0));
+ QCOMPARE(p.size(), layoutMaximumSize);
+
+ QSizeF testA(175.0, 300.0);
+ p.resize(testA);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 75.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(75.0, 0.0, 100.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(75.0, 100.0, 25.0, 100.0));
+ QCOMPARE(d->geometry(), QRectF(0.0, 200.0, 100.0, 100.0));
+ QCOMPARE(e->geometry(), QRectF(100.0, 200.0, 75.0, 100.0));
+ QCOMPARE(p.size(), testA);
+
+ if (hasSimplification) {
+ QVERIFY(usedSimplex(l, Qt::Horizontal));
+ QVERIFY(!usedSimplex(l, Qt::Vertical));
+ }
+
+ QVERIFY(p.layout());
+ QCOMPARE(checkReverseDirection(&p), true);
+
+ c->setMinimumWidth(300);
+ QVERIFY(layoutHasConflict(l));
+}
+
+void tst_QGraphicsAnchorLayout::parallel()
+{
+ QGraphicsWidget *a = createItem(QSizeF(100, 100),
+ QSizeF(150, 100),
+ QSizeF(200, 100), "A");
+
+ QGraphicsWidget *b = createItem(QSizeF(100, 100),
+ QSizeF(150, 100),
+ QSizeF(300, 100), "B");
+
+ QGraphicsWidget *c = createItem(QSizeF(100, 100),
+ QSizeF(200, 100),
+ QSizeF(350, 100), "C");
+
+ QGraphicsWidget *d = createItem(QSizeF(100, 100),
+ QSizeF(170, 100),
+ QSizeF(200, 100), "D");
+
+ QGraphicsWidget *e = createItem(QSizeF(150, 100),
+ QSizeF(150, 100),
+ QSizeF(200, 100), "E");
+
+ QGraphicsWidget *f = createItem(QSizeF(100, 100),
+ QSizeF(150, 100),
+ QSizeF(200, 100), "F");
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ l->addAnchor(l, Qt::AnchorTop, a, Qt::AnchorTop);
+ l->addAnchor(a, Qt::AnchorBottom, b, Qt::AnchorTop);
+ l->addAnchor(b, Qt::AnchorBottom, c, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorBottom, d, Qt::AnchorTop);
+ l->addAnchor(d, Qt::AnchorBottom, e, Qt::AnchorTop);
+ l->addAnchor(e, Qt::AnchorBottom, f, Qt::AnchorTop);
+ l->addAnchor(f, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+ l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorLeft);
+ l->addAnchor(a, Qt::AnchorRight, c, Qt::AnchorLeft);
+ l->addAnchor(b, Qt::AnchorRight, d, Qt::AnchorLeft);
+ l->addAnchor(b, Qt::AnchorRight, e, Qt::AnchorLeft);
+ l->addAnchor(c, Qt::AnchorRight, f, Qt::AnchorLeft);
+ l->addAnchor(d, Qt::AnchorRight, f, Qt::AnchorLeft);
+ l->addAnchor(e, Qt::AnchorRight, f, Qt::AnchorLeft);
+ l->addAnchor(f, Qt::AnchorRight, l, Qt::AnchorRight);
+
+ QCOMPARE(l->count(), 6);
+
+ QGraphicsWidget p;
+ p.setLayout(l);
+
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QSizeF layoutPreferredSize = l->effectiveSizeHint(Qt::PreferredSize);
+ QSizeF layoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+
+ QCOMPARE(layoutMinimumSize, QSizeF(450, 600));
+ QCOMPARE(layoutPreferredSize, QSizeF(620, 600));
+ QCOMPARE(layoutMaximumSize, QSizeF(750, 600));
+
+ p.resize(layoutMinimumSize);
+ QCOMPARE(a->geometry(), QRectF(0, 0, 100, 100));
+ QCOMPARE(b->geometry(), QRectF(100, 100, 100, 100));
+ QCOMPARE(c->geometry(), QRectF(100, 200, 250, 100));
+ QCOMPARE(d->geometry(), QRectF(200, 300, 150, 100));
+ QCOMPARE(e->geometry(), QRectF(200, 400, 150, 100));
+ QCOMPARE(f->geometry(), QRectF(350, 500, 100, 100));
+ QCOMPARE(p.size(), layoutMinimumSize);
+
+ if (!hasSimplification)
+ return;
+
+ p.resize(layoutPreferredSize);
+ QCOMPARE(a->geometry(), QRectF(0, 0, 150, 100));
+ QCOMPARE(b->geometry(), QRectF(150, 100, 150, 100));
+ QCOMPARE(c->geometry(), QRectF(150, 200, 320, 100));
+ QCOMPARE(d->geometry(), QRectF(300, 300, 170, 100));
+ QCOMPARE(e->geometry(), QRectF(300, 400, 170, 100));
+ QCOMPARE(f->geometry(), QRectF(470, 500, 150, 100));
+ QCOMPARE(p.size(), layoutPreferredSize);
+
+ // Maximum size depends on simplification / fair distribution
+ // Without that, test may or may not pass, depending on the
+ // solution found by the solver at runtime.
+ p.resize(layoutMaximumSize);
+ QCOMPARE(a->geometry(), QRectF(0, 0, 200, 100));
+ QCOMPARE(b->geometry(), QRectF(200, 100, 175, 100));
+ QCOMPARE(c->geometry(), QRectF(200, 200, 350, 100));
+ QCOMPARE(d->geometry(), QRectF(375, 300, 175, 100));
+ QCOMPARE(e->geometry(), QRectF(375, 400, 175, 100));
+ QCOMPARE(f->geometry(), QRectF(550, 500, 200, 100));
+ QCOMPARE(p.size(), layoutMaximumSize);
+
+ QVERIFY(!usedSimplex(l, Qt::Horizontal));
+ QVERIFY(!usedSimplex(l, Qt::Vertical));
+}
+
+void tst_QGraphicsAnchorLayout::parallel2()
+{
+ QGraphicsWidget *a = createItem(QSizeF(70.0, 100.0),
+ QSizeF(100.0, 100.0),
+ QSizeF(200.0, 100.0), "A");
+
+ QGraphicsWidget *b = createItem(QSizeF(100.0, 100.0),
+ QSizeF(150.0, 100.0),
+ QSizeF(190.0, 100.0), "B");
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ l->addAnchor(l, Qt::AnchorTop, a, Qt::AnchorTop);
+ l->addAnchor(a, Qt::AnchorBottom, b, Qt::AnchorTop);
+ l->addAnchor(b, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ l->addAnchors(l, a, Qt::Horizontal);
+ l->addAnchor(l, Qt::AnchorLeft, b, Qt::AnchorLeft);
+ l->addAnchor(b, Qt::AnchorRight, a, Qt::AnchorRight);
+
+ QCOMPARE(l->count(), 2);
+
+ QGraphicsWidget p;
+ p.setLayout(l);
+
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QSizeF layoutPreferredSize = l->effectiveSizeHint(Qt::PreferredSize);
+ QSizeF layoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+
+ QCOMPARE(layoutMinimumSize, QSizeF(100.0, 200.0));
+ QCOMPARE(layoutPreferredSize, QSizeF(150.0, 200.0));
+ QCOMPARE(layoutMaximumSize, QSizeF(190.0, 200.0));
+
+ p.resize(layoutMinimumSize);
+ QCOMPARE(p.size(), layoutMinimumSize);
+
+ p.resize(layoutPreferredSize);
+ QCOMPARE(p.size(), layoutPreferredSize);
+
+ p.resize(layoutMaximumSize);
+ QCOMPARE(p.size(), layoutMaximumSize);
+
+ if (hasSimplification) {
+ QVERIFY(!usedSimplex(l, Qt::Horizontal));
+ QVERIFY(!usedSimplex(l, Qt::Vertical));
+ }
+}
+
+void tst_QGraphicsAnchorLayout::snake()
+{
+ QGraphicsWidget *a = createItem(QSizeF(50.0, 100.0),
+ QSizeF(70.0, 100.0),
+ QSizeF(100.0, 100.0), "A");
+
+ QGraphicsWidget *b = createItem(QSizeF(10.0, 100.0),
+ QSizeF(20.0, 100.0),
+ QSizeF(40.0, 100.0), "B");
+
+ QGraphicsWidget *c = createItem(QSizeF(50.0, 100.0),
+ QSizeF(70.0, 100.0),
+ QSizeF(100.0, 100.0), "C");
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ l->addAnchor(l, Qt::AnchorTop, a, Qt::AnchorTop);
+ l->addAnchor(a, Qt::AnchorBottom, b, Qt::AnchorTop);
+ l->addAnchor(b, Qt::AnchorBottom, c, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+ l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorRight);
+ l->addAnchor(b, Qt::AnchorLeft, c, Qt::AnchorLeft);
+ l->addAnchor(c, Qt::AnchorRight, l, Qt::AnchorRight);
+
+ QCOMPARE(l->count(), 3);
+
+ QGraphicsWidget p;
+ p.setLayout(l);
+
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QSizeF layoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+ QSizeF layoutPreferredSize = l->effectiveSizeHint(Qt::PreferredSize);
+
+ QCOMPARE(layoutMinimumSize, QSizeF(60.0, 300.0));
+ QCOMPARE(layoutPreferredSize, QSizeF(120.0, 300.0));
+ QCOMPARE(layoutMaximumSize, QSizeF(190.0, 300.0));
+
+ p.resize(layoutMinimumSize);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 50.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(10.0, 100.0, 40.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(10.0, 200.0, 50.0, 100.0));
+ QCOMPARE(p.size(), layoutMinimumSize);
+
+ p.resize(layoutPreferredSize);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 70.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(50.0, 100.0, 20.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(50.0, 200.0, 70.0, 100.0));
+ QCOMPARE(p.size(), layoutPreferredSize);
+
+ p.resize(layoutMaximumSize);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 100.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(90.0, 100.0, 10.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(90.0, 200.0, 100.0, 100.0));
+ QCOMPARE(p.size(), layoutMaximumSize);
+
+ QVERIFY(layoutHasConflict(l) == false);
+
+ // Test QSizePolicy::ExpandFlag, it shouldn't change the extreme
+ // points of the layout...
+ b->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
+
+ QSizeF newLayoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QSizeF newLayoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+ QSizeF newLayoutPreferredSize = l->effectiveSizeHint(Qt::PreferredSize);
+
+ QCOMPARE(layoutMinimumSize, newLayoutMinimumSize);
+ QCOMPARE(layoutMaximumSize, newLayoutMaximumSize);
+ QCOMPARE(layoutPreferredSize, newLayoutPreferredSize);
+}
+
+void tst_QGraphicsAnchorLayout::snakeOppositeDirections()
+{
+ QGraphicsWidget *a = createItem(QSizeF(50.0, 100.0),
+ QSizeF(70.0, 100.0),
+ QSizeF(100.0, 100.0), "A");
+
+ QGraphicsWidget *b = createItem(QSizeF(10.0, 100.0),
+ QSizeF(20.0, 100.0),
+ QSizeF(40.0, 100.0), "B");
+
+ QGraphicsWidget *c = createItem(QSizeF(50.0, 100.0),
+ QSizeF(70.0, 100.0),
+ QSizeF(100.0, 100.0), "C");
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ l->addAnchor(l, Qt::AnchorTop, a, Qt::AnchorTop);
+ l->addAnchor(a, Qt::AnchorBottom, b, Qt::AnchorTop);
+ l->addAnchor(b, Qt::AnchorBottom, c, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+
+ // Both a and c are 'pointing' to b
+ l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorRight);
+ l->addAnchor(c, Qt::AnchorLeft, b, Qt::AnchorLeft);
+
+ l->addAnchor(c, Qt::AnchorRight, l, Qt::AnchorRight);
+
+ QCOMPARE(l->count(), 3);
+
+ QGraphicsWidget p;
+ p.setLayout(l);
+
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QSizeF layoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+ QSizeF layoutPreferredSize = l->effectiveSizeHint(Qt::PreferredSize);
+
+ QCOMPARE(layoutMinimumSize, QSizeF(60.0, 300.0));
+ QCOMPARE(layoutPreferredSize, QSizeF(120.0, 300.0));
+ QCOMPARE(layoutMaximumSize, QSizeF(190.0, 300.0));
+
+ p.resize(layoutMinimumSize);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 50.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(10.0, 100.0, 40.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(10.0, 200.0, 50.0, 100.0));
+ QCOMPARE(p.size(), layoutMinimumSize);
+
+ p.resize(layoutPreferredSize);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 70.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(50.0, 100.0, 20.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(50.0, 200.0, 70.0, 100.0));
+ QCOMPARE(p.size(), layoutPreferredSize);
+
+ p.resize(layoutMaximumSize);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 100.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(90.0, 100.0, 10.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(90.0, 200.0, 100.0, 100.0));
+ QCOMPARE(p.size(), layoutMaximumSize);
+
+ QVERIFY(p.layout());
+ QCOMPARE(checkReverseDirection(&p), true);
+}
+
+void tst_QGraphicsAnchorLayout::fairDistribution()
+{
+ QGraphicsWidget *a = createItem(QSizeF(10.0, 100.0),
+ QSizeF(50.0, 100.0),
+ QSizeF(100.0, 100.0), "A");
+
+ QGraphicsWidget *b = createItem(QSizeF(10.0, 100.0),
+ QSizeF(50.0, 100.0),
+ QSizeF(100.0, 100.0), "B");
+
+ QGraphicsWidget *c = createItem(QSizeF(10.0, 100.0),
+ QSizeF(50.0, 100.0),
+ QSizeF(100.0, 100.0), "C");
+
+ QGraphicsWidget *d = createItem(QSizeF(60.0, 100.0),
+ QSizeF(165.0, 100.0),
+ QSizeF(600.0, 100.0), "D");
+
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ l->addAnchor(l, Qt::AnchorTop, a, Qt::AnchorTop);
+ l->addAnchor(a, Qt::AnchorBottom, b, Qt::AnchorTop);
+ l->addAnchor(b, Qt::AnchorBottom, c, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorBottom, d, Qt::AnchorTop);
+ l->addAnchor(d, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+ l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorLeft);
+ l->addAnchor(b, Qt::AnchorRight, c, Qt::AnchorLeft);
+ l->addAnchor(c, Qt::AnchorRight, l, Qt::AnchorRight);
+ l->addAnchor(l, Qt::AnchorLeft, d, Qt::AnchorLeft);
+ l->addAnchor(d, Qt::AnchorRight, l, Qt::AnchorRight);
+
+ QCOMPARE(l->count(), 4);
+
+ QGraphicsWidget p;
+ p.setLayout(l);
+
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QSizeF layoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+ QSizeF layoutPreferredSize = l->effectiveSizeHint(Qt::PreferredSize);
+
+ QCOMPARE(layoutMinimumSize, QSizeF(60.0, 400.0));
+ QCOMPARE(layoutPreferredSize, QSizeF(165.0, 400.0));
+ QCOMPARE(layoutMaximumSize, QSizeF(300.0, 400.0));
+
+ p.resize(layoutMinimumSize);
+ if (!hasSimplification)
+ QEXPECT_FAIL("", "Without simplification there is no fair distribution.", Abort);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 20.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(20.0, 100.0, 20.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(40.0, 200.0, 20.0, 100.0));
+ QCOMPARE(d->geometry(), QRectF(0.0, 300.0, 60.0, 100.0));
+ QCOMPARE(p.size(), layoutMinimumSize);
+
+ p.resize(layoutPreferredSize);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 55.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(55.0, 100.0, 55.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(110.0, 200.0, 55.0, 100.0));
+ QCOMPARE(d->geometry(), QRectF(0.0, 300.0, 165.0, 100.0));
+ QCOMPARE(p.size(), layoutPreferredSize);
+
+ p.resize(layoutMaximumSize);
+ QCOMPARE(a->geometry(), QRectF(0.0, 0.0, 100.0, 100.0));
+ QCOMPARE(b->geometry(), QRectF(100.0, 100.0, 100.0, 100.0));
+ QCOMPARE(c->geometry(), QRectF(200.0, 200.0, 100.0, 100.0));
+ QCOMPARE(d->geometry(), QRectF(0.0, 300.0, 300.0, 100.0));
+ QCOMPARE(p.size(), layoutMaximumSize);
+
+ if (hasSimplification) {
+ QVERIFY(!usedSimplex(l, Qt::Horizontal));
+ QVERIFY(!usedSimplex(l, Qt::Vertical));
+ }
+}
+
+void tst_QGraphicsAnchorLayout::fairDistributionOppositeDirections()
+{
+ QGraphicsWidget *a = createItem(QSizeF(10.0, 100.0),
+ QSizeF(50.0, 100.0),
+ QSizeF(100.0, 100.0), "A");
+
+ QGraphicsWidget *b = createItem(QSizeF(10.0, 100.0),
+ QSizeF(50.0, 100.0),
+ QSizeF(100.0, 100.0), "B");
+
+ QGraphicsWidget *c = createItem(QSizeF(10.0, 100.0),
+ QSizeF(50.0, 100.0),
+ QSizeF(100.0, 100.0), "C");
+
+ QGraphicsWidget *d = createItem(QSizeF(10.0, 100.0),
+ QSizeF(50.0, 100.0),
+ QSizeF(100.0, 100.0), "D");
+
+ QGraphicsWidget *e = createItem(QSizeF(60.0, 100.0),
+ QSizeF(220.0, 100.0),
+ QSizeF(600.0, 100.0), "E");
+
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ l->addAnchor(l, Qt::AnchorTop, a, Qt::AnchorTop);
+ l->addAnchor(a, Qt::AnchorBottom, b, Qt::AnchorTop);
+ l->addAnchor(b, Qt::AnchorBottom, c, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorBottom, d, Qt::AnchorTop);
+ l->addAnchor(d, Qt::AnchorBottom, e, Qt::AnchorTop);
+ l->addAnchor(e, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ l->addAnchor(a, Qt::AnchorLeft, l, Qt::AnchorLeft);
+ l->addAnchor(b, Qt::AnchorLeft, a, Qt::AnchorRight);
+ l->addAnchor(c, Qt::AnchorLeft, b, Qt::AnchorRight);
+ l->addAnchor(d, Qt::AnchorLeft, c, Qt::AnchorRight);
+ l->addAnchor(d, Qt::AnchorRight, l, Qt::AnchorRight);
+ l->addAnchors(l, e, Qt::Horizontal);
+
+ QCOMPARE(l->count(), 5);
+
+ QGraphicsWidget p;
+ p.setLayout(l);
+
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QSizeF layoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+ QSizeF layoutPreferredSize = l->effectiveSizeHint(Qt::PreferredSize);
+
+ QCOMPARE(layoutMinimumSize, QSizeF(60.0, 500.0));
+ QCOMPARE(layoutPreferredSize, QSizeF(220.0, 500.0));
+ QCOMPARE(layoutMaximumSize, QSizeF(400.0, 500.0));
+
+ if (!hasSimplification)
+ return;
+
+ p.resize(layoutMinimumSize);
+ QCOMPARE(a->size(), b->size());
+ QCOMPARE(a->size(), c->size());
+ QCOMPARE(a->size(), d->size());
+ QCOMPARE(e->size().width(), 4 * a->size().width());
+ QCOMPARE(p.size(), layoutMinimumSize);
+
+ p.resize(layoutPreferredSize);
+ QCOMPARE(a->size(), b->size());
+ QCOMPARE(a->size(), c->size());
+ QCOMPARE(a->size(), d->size());
+ QCOMPARE(e->size().width(), 4 * a->size().width());
+ QCOMPARE(p.size(), layoutPreferredSize);
+
+ p.resize(layoutMaximumSize);
+ QCOMPARE(a->size(), b->size());
+ QCOMPARE(a->size(), c->size());
+ QCOMPARE(a->size(), d->size());
+ QCOMPARE(e->size().width(), 4 * a->size().width());
+ QCOMPARE(p.size(), layoutMaximumSize);
+
+ QVERIFY(!usedSimplex(l, Qt::Horizontal));
+ QVERIFY(!usedSimplex(l, Qt::Vertical));
+}
+
+void tst_QGraphicsAnchorLayout::proportionalPreferred()
+{
+ QSizeF minSize(0, 100);
+
+ QGraphicsWidget *a = createItem(minSize, QSizeF(10, 100), QSizeF(20, 100), "A");
+ QGraphicsWidget *b = createItem(minSize, QSizeF(20, 100), QSizeF(30, 100), "B");
+ QGraphicsWidget *c = createItem(minSize, QSizeF(14, 100), QSizeF(20, 100), "C");
+ QGraphicsWidget *d = createItem(minSize, QSizeF(10, 100), QSizeF(20, 100), "D");
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ l->addAnchor(l, Qt::AnchorTop, a, Qt::AnchorTop);
+ l->addAnchor(a, Qt::AnchorBottom, b, Qt::AnchorTop);
+ l->addAnchor(b, Qt::AnchorBottom, c, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorBottom, d, Qt::AnchorTop);
+ l->addAnchor(d, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+ l->addAnchor(l, Qt::AnchorLeft, b, Qt::AnchorLeft);
+ l->addAnchor(a, Qt::AnchorRight, c, Qt::AnchorLeft);
+ l->addAnchor(a, Qt::AnchorRight, d, Qt::AnchorLeft);
+ l->addAnchor(b, Qt::AnchorRight, l, Qt::AnchorRight);
+ l->addAnchor(c, Qt::AnchorRight, l, Qt::AnchorRight);
+ l->addAnchor(d, Qt::AnchorRight, l, Qt::AnchorRight);
+
+ QCOMPARE(l->count(), 4);
+
+ QGraphicsWidget p;
+ p.setLayout(l);
+
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QSizeF layoutPreferredSize = l->effectiveSizeHint(Qt::PreferredSize);
+ QSizeF layoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+
+ QCOMPARE(layoutMinimumSize, QSizeF(0, 400));
+ QCOMPARE(layoutPreferredSize, QSizeF(24, 400));
+ QCOMPARE(layoutMaximumSize, QSizeF(30, 400));
+
+ p.resize(layoutMinimumSize);
+ QCOMPARE(p.size(), layoutMinimumSize);
+
+ p.resize(layoutPreferredSize);
+ QCOMPARE(c->size().width(), d->size().width());
+ QCOMPARE(p.size(), layoutPreferredSize);
+
+ p.resize(layoutMaximumSize);
+ QCOMPARE(p.size(), layoutMaximumSize);
+
+ p.resize(QSizeF(12, 400));
+
+ // Proportionality between size given and preferred size, this
+ // should be respected in this graph for (a) and (b)|(c).
+ qreal factor = 12.0 / 24.0;
+
+ QCOMPARE(c->size().width(), d->size().width());
+ QCOMPARE(a->size().width(), 10 * factor);
+ QCOMPARE(c->size().width(), 14 * factor);
+ QCOMPARE(p.size(), QSizeF(12, 400));
+
+ if (hasSimplification) {
+ QVERIFY(!usedSimplex(l, Qt::Horizontal));
+ QVERIFY(!usedSimplex(l, Qt::Vertical));
+ }
+}
+
+void tst_QGraphicsAnchorLayout::example()
+{
+ QSizeF minSize(30, 100);
+ QSizeF pref(210, 100);
+ QSizeF maxSize(300, 100);
+
+ QGraphicsWidget *a = createItem(minSize, pref, maxSize, "A");
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize, "B");
+ QGraphicsWidget *c = createItem(minSize, pref, maxSize, "C");
+ QGraphicsWidget *d = createItem(minSize, pref, maxSize, "D");
+ QGraphicsWidget *e = createItem(minSize, pref, maxSize, "E");
+ QGraphicsWidget *f = createItem(QSizeF(30, 50), QSizeF(150, 50), maxSize, "F");
+ QGraphicsWidget *g = createItem(QSizeF(30, 50), QSizeF(30, 100), maxSize, "G");
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ // vertical
+ l->addAnchor(a, Qt::AnchorTop, l, Qt::AnchorTop);
+ l->addAnchor(b, Qt::AnchorTop, l, Qt::AnchorTop);
+
+ l->addAnchor(c, Qt::AnchorTop, a, Qt::AnchorBottom);
+ l->addAnchor(c, Qt::AnchorTop, b, Qt::AnchorBottom);
+ l->addAnchor(c, Qt::AnchorBottom, d, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorBottom, e, Qt::AnchorTop);
+
+ l->addAnchor(d, Qt::AnchorBottom, l, Qt::AnchorBottom);
+ l->addAnchor(e, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ l->addAnchor(c, Qt::AnchorTop, f, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorVerticalCenter, f, Qt::AnchorBottom);
+ l->addAnchor(f, Qt::AnchorBottom, g, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorBottom, g, Qt::AnchorBottom);
+
+ // horizontal
+ l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+ l->addAnchor(l, Qt::AnchorLeft, d, Qt::AnchorLeft);
+ l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorLeft);
+
+ l->addAnchor(a, Qt::AnchorRight, c, Qt::AnchorLeft);
+ l->addAnchor(c, Qt::AnchorRight, e, Qt::AnchorLeft);
+
+ l->addAnchor(b, Qt::AnchorRight, l, Qt::AnchorRight);
+ l->addAnchor(e, Qt::AnchorRight, l, Qt::AnchorRight);
+ l->addAnchor(d, Qt::AnchorRight, e, Qt::AnchorLeft);
+
+ l->addAnchor(l, Qt::AnchorLeft, f, Qt::AnchorLeft);
+ l->addAnchor(l, Qt::AnchorLeft, g, Qt::AnchorLeft);
+ l->addAnchor(f, Qt::AnchorRight, g, Qt::AnchorRight);
+
+ QCOMPARE(l->count(), 7);
+
+ QGraphicsWidget p;
+ p.setLayout(l);
+
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QSizeF layoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+ QSizeF layoutPreferredSize = l->effectiveSizeHint(Qt::PreferredSize);
+
+ QCOMPARE(layoutMinimumSize, QSizeF(90.0, 300.0));
+ QCOMPARE(layoutPreferredSize, QSizeF(510.0, 300.0));
+ QCOMPARE(layoutMaximumSize, QSizeF(570.0, 300.0));
+
+ p.resize(layoutMinimumSize);
+ QCOMPARE(p.size(), layoutMinimumSize);
+ QCOMPARE(a->size(), e->size());
+ QCOMPARE(b->size(), d->size());
+ QCOMPARE(f->size(), g->size());
+
+ p.resize(layoutPreferredSize);
+ QCOMPARE(p.size(), layoutPreferredSize);
+ QCOMPARE(a->size(), e->size());
+ QCOMPARE(b->size(), d->size());
+ QCOMPARE(f->size(), g->size());
+
+ p.resize(layoutMaximumSize);
+ QCOMPARE(p.size(), layoutMaximumSize);
+ QCOMPARE(a->size(), e->size());
+ QCOMPARE(b->size(), d->size());
+ QCOMPARE(f->size(), g->size());
+
+ if (hasSimplification) {
+ QVERIFY(usedSimplex(l, Qt::Horizontal));
+ QVERIFY(usedSimplex(l, Qt::Vertical));
+ }
+}
+
+void tst_QGraphicsAnchorLayout::setSpacing()
+{
+ QSizeF minSize(10, 10);
+ QSizeF pref(20, 20);
+ QSizeF maxSize(50, 50);
+
+ QGraphicsWidget *a = createItem(minSize, pref, maxSize);
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize);
+ QGraphicsWidget *c = createItem(minSize, pref, maxSize);
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->addCornerAnchors(l, Qt::TopLeftCorner, a, Qt::TopLeftCorner);
+ l->addCornerAnchors(b, Qt::TopRightCorner, l, Qt::TopRightCorner);
+ l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorLeft);
+
+ l->addAnchors(l, c, Qt::Horizontal);
+
+ l->addAnchor(a, Qt::AnchorBottom, c, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ QGraphicsWidget *p = new QGraphicsWidget(0, Qt::Window);
+
+ p->setLayout(l);
+ l->setSpacing(1);
+
+ // don't let the style influence the test.
+ l->setContentsMargins(0, 0, 0, 0);
+
+ QGraphicsScene scene;
+ scene.addItem(p);
+ QGraphicsView *view = new QGraphicsView(&scene);
+ view->show();
+ p->show();
+
+ QApplication::processEvents();
+#ifdef Q_WS_MAC
+ QTest::qWait(200);
+#endif
+
+ // 21x21
+ QCOMPARE(p->size(), QSizeF(41, 41));
+ QCOMPARE(a->geometry(), QRectF(0, 0, 20, 20));
+ QCOMPARE(b->geometry(), QRectF(21, 0, 20, 20));
+ QCOMPARE(c->geometry(), QRectF(0, 21, 41, 20));
+
+ l->setHorizontalSpacing(4);
+ QApplication::processEvents();
+ p->adjustSize();
+ QCOMPARE(a->geometry(), QRectF(0, 0, 20, 20));
+ QCOMPARE(b->geometry(), QRectF(24, 0, 20, 20));
+ QCOMPARE(c->geometry(), QRectF(0, 21, 44, 20));
+
+ l->setVerticalSpacing(0);
+ QApplication::processEvents();
+ p->adjustSize();
+ QCOMPARE(a->geometry(), QRectF(0, 0, 20, 20));
+ QCOMPARE(b->geometry(), QRectF(24, 0, 20, 20));
+ QCOMPARE(c->geometry(), QRectF(0, 20, 44, 20));
+
+ delete p;
+ delete view;
+}
+
+class CustomLayoutStyle : public QWindowsStyle
+{
+ Q_OBJECT
+public:
+ CustomLayoutStyle() : QWindowsStyle()
+ {
+ hspacing = 5;
+ vspacing = 10;
+ }
+
+ virtual int pixelMetric(PixelMetric metric, const QStyleOption * option = 0,
+ const QWidget * widget = 0 ) const;
+
+ int hspacing;
+ int vspacing;
+
+protected slots:
+ int layoutSpacingImplementation(QSizePolicy::ControlType control1,
+ QSizePolicy::ControlType control2,
+ Qt::Orientation orientation,
+ const QStyleOption *option = 0,
+ const QWidget *widget = 0) const;
+
+};
+
+#define CT1(c) CT2(c, c)
+#define CT2(c1, c2) ((uint)c1 << 16) | (uint)c2
+
+int CustomLayoutStyle::layoutSpacingImplementation(QSizePolicy::ControlType control1,
+ QSizePolicy::ControlType control2,
+ Qt::Orientation orientation,
+ const QStyleOption * /*option = 0*/,
+ const QWidget * /*widget = 0*/) const
+{
+ if (orientation == Qt::Horizontal) {
+ switch (CT2(control1, control2)) {
+ case CT1(QSizePolicy::PushButton):
+ return 2;
+ break;
+ }
+ return 5;
+ } else {
+ switch (CT2(control1, control2)) {
+ case CT1(QSizePolicy::RadioButton):
+ return 2;
+ break;
+
+ }
+ return 10;
+ }
+}
+
+int CustomLayoutStyle::pixelMetric(PixelMetric metric, const QStyleOption * option /*= 0*/,
+ const QWidget * widget /*= 0*/ ) const
+{
+ switch (metric) {
+ case PM_LayoutLeftMargin:
+ return 0;
+ break;
+ case PM_LayoutTopMargin:
+ return 3;
+ break;
+ case PM_LayoutRightMargin:
+ return 6;
+ break;
+ case PM_LayoutBottomMargin:
+ return 9;
+ break;
+ case PM_LayoutHorizontalSpacing:
+ return hspacing;
+ case PM_LayoutVerticalSpacing:
+ return vspacing;
+ break;
+ default:
+ break;
+ }
+ return QWindowsStyle::pixelMetric(metric, option, widget);
+}
+
+void tst_QGraphicsAnchorLayout::styleDefaults()
+{
+ QSizeF minSize (10, 10);
+ QSizeF pref(20, 20);
+ QSizeF maxSize (50, 50);
+
+ /*
+ create this layout, where a,b have controlType QSizePolicy::RadioButton
+ c,d have controlType QSizePolicy::PushButton:
+ +-------+
+ |a |
+ | b |
+ | c |
+ | d|
+ +-------+
+ */
+ QGraphicsScene scene;
+ QGraphicsWidget *a = createItem(minSize, pref, maxSize);
+ QSizePolicy spRadioButton = a->sizePolicy();
+ spRadioButton.setControlType(QSizePolicy::RadioButton);
+ a->setSizePolicy(spRadioButton);
+
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize);
+ b->setSizePolicy(spRadioButton);
+
+ QGraphicsWidget *c = createItem(minSize, pref, maxSize);
+ QSizePolicy spPushButton = c->sizePolicy();
+ spPushButton.setControlType(QSizePolicy::PushButton);
+ c->setSizePolicy(spPushButton);
+
+ QGraphicsWidget *d = createItem(minSize, pref, maxSize);
+ d->setSizePolicy(spPushButton);
+
+ QGraphicsWidget *window = new QGraphicsWidget(0, Qt::Window);
+
+ // Test layoutSpacingImplementation
+ CustomLayoutStyle *style = new CustomLayoutStyle;
+ style->hspacing = -1;
+ style->vspacing = -1;
+ window->setStyle(style);
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+
+ l->addCornerAnchors(l, Qt::TopLeftCorner, a, Qt::TopLeftCorner);
+ l->addCornerAnchors(a, Qt::BottomRightCorner, b, Qt::TopLeftCorner);
+ l->addCornerAnchors(b, Qt::BottomRightCorner, c, Qt::TopLeftCorner);
+ l->addCornerAnchors(c, Qt::BottomRightCorner, d, Qt::TopLeftCorner);
+ l->addCornerAnchors(d, Qt::BottomRightCorner, l, Qt::BottomRightCorner);
+
+ window->setLayout(l);
+
+ scene.addItem(window);
+
+ window->show();
+ QGraphicsView view(&scene);
+ view.resize(200, 200);
+ view.show();
+
+ window->adjustSize();
+ QCOMPARE(a->geometry(), QRectF(0, 3, 20, 20)); //radio
+ QCOMPARE(b->geometry(), QRectF(25, 25, 20, 20)); //radio
+ QCOMPARE(c->geometry(), QRectF(50, 55, 20, 20)); //push
+ QCOMPARE(d->geometry(), QRectF(72, 85, 20, 20)); //push
+ QCOMPARE(l->geometry(), QRectF(0, 0, 98, 114));
+
+
+ // Test pixelMetric(PM_Layout{Horizontal|Vertical}Spacing
+ window->setStyle(0);
+
+ style->hspacing = 1;
+ style->vspacing = 2;
+
+ window->setStyle(style);
+ window->adjustSize();
+ QCOMPARE(a->geometry(), QRectF(0, 3, 20, 20));
+ QCOMPARE(b->geometry(), QRectF(21, 25, 20, 20));
+ QCOMPARE(c->geometry(), QRectF(42, 47, 20, 20));
+ QCOMPARE(d->geometry(), QRectF(63, 69, 20, 20));
+ QCOMPARE(l->geometry(), QRectF(0, 0, 89, 98));
+
+ window->setStyle(0);
+ delete style;
+}
+
+
+/*!
+ Taken from "hard" complex case, found at
+ https://cwiki.nokia.com/S60QTUI/AnchorLayoutComplexCases
+
+ This layout has a special property, since it has two possible solutions for its minimum size.
+
+ For instance, when it is in its minimum size - the layout have two possible solutions:
+ 1. c.width == 10, e.width == 10 and g.width == 10
+ (all others have width 0)
+ 2. d.width == 10 and g.width == 10
+ (all others have width 0)
+
+ It also has several solutions for preferred size.
+*/
+static QGraphicsAnchorLayout *createAmbiguousS60Layout()
+{
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ QSizeF minSize(0, 10);
+ QSizeF pref(50, 10);
+ QSizeF maxSize(100, 10);
+
+ QGraphicsWidget *a = createItem(minSize, pref, maxSize, "a");
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize, "b");
+ QGraphicsWidget *c = createItem(minSize, pref, maxSize, "c");
+ QGraphicsWidget *d = createItem(minSize, pref, maxSize, "d");
+ QGraphicsWidget *e = createItem(minSize, pref, maxSize, "e");
+ QGraphicsWidget *f = createItem(minSize, pref, maxSize, "f");
+ QGraphicsWidget *g = createItem(minSize, pref, maxSize, "g");
+
+ //<!-- Trunk -->
+ setAnchor(l, l, Qt::AnchorLeft, a, Qt::AnchorLeft, 10);
+ setAnchor(l, a, Qt::AnchorRight, b, Qt::AnchorLeft, 10);
+ setAnchor(l, b, Qt::AnchorRight, c, Qt::AnchorLeft, 10);
+ setAnchor(l, c, Qt::AnchorRight, d, Qt::AnchorLeft, 10);
+ setAnchor(l, d, Qt::AnchorRight, l, Qt::AnchorRight, 10);
+
+ //<!-- Above trunk -->
+ setAnchor(l, b, Qt::AnchorLeft, e, Qt::AnchorLeft, 10);
+ setAnchor(l, e, Qt::AnchorRight, d, Qt::AnchorLeft, 10);
+
+ //<!-- Below trunk -->
+ setAnchor(l, a, Qt::AnchorHorizontalCenter, g, Qt::AnchorLeft, 10);
+ setAnchor(l, g, Qt::AnchorRight, f, Qt::AnchorHorizontalCenter, 10);
+ setAnchor(l, c, Qt::AnchorLeft, f, Qt::AnchorLeft, 10);
+ setAnchor(l, f, Qt::AnchorRight, d, Qt::AnchorRight, 10);
+
+ //<!-- vertical is simpler -->
+ setAnchor(l, l, Qt::AnchorTop, e, Qt::AnchorTop, 0);
+ setAnchor(l, e, Qt::AnchorBottom, a, Qt::AnchorTop, 0);
+ setAnchor(l, e, Qt::AnchorBottom, b, Qt::AnchorTop, 0);
+ setAnchor(l, e, Qt::AnchorBottom, c, Qt::AnchorTop, 0);
+ setAnchor(l, e, Qt::AnchorBottom, d, Qt::AnchorTop, 0);
+ setAnchor(l, a, Qt::AnchorBottom, f, Qt::AnchorTop, 0);
+ setAnchor(l, a, Qt::AnchorBottom, b, Qt::AnchorBottom, 0);
+ setAnchor(l, a, Qt::AnchorBottom, c, Qt::AnchorBottom, 0);
+ setAnchor(l, a, Qt::AnchorBottom, d, Qt::AnchorBottom, 0);
+ setAnchor(l, f, Qt::AnchorBottom, g, Qt::AnchorTop, 0);
+ setAnchor(l, g, Qt::AnchorBottom, l, Qt::AnchorBottom, 0);
+ return l;
+}
+
+void tst_QGraphicsAnchorLayout::hardComplexS60()
+{
+ QGraphicsAnchorLayout *l = createAmbiguousS60Layout();
+ QCOMPARE(l->count(), 7);
+
+ QGraphicsWidget *p = new QGraphicsWidget(0, Qt::Window);
+ p->setLayout(l);
+
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ QCOMPARE(layoutMinimumSize, QSizeF(60, 40));
+ // expected preferred might be wrong, (haven't manually verified it)
+ QSizeF layoutPreferredSize = l->effectiveSizeHint(Qt::PreferredSize);
+ QCOMPARE(layoutPreferredSize, QSizeF(220, 40));
+ QSizeF layoutMaximumSize = l->effectiveSizeHint(Qt::MaximumSize);
+ QCOMPARE(layoutMaximumSize, QSizeF(240, 40));
+
+ delete p;
+}
+
+void tst_QGraphicsAnchorLayout::stability()
+{
+ QVector<QRectF> geometries;
+ geometries.resize(7);
+ QGraphicsWidget *p = new QGraphicsWidget(0, Qt::Window);
+ bool sameAsPreviousArrangement = true;
+ // it usually fails after 3-4 iterations
+ for (int pass = 0; pass < 20 && sameAsPreviousArrangement; ++pass) {
+ // In case we need to "scramble" the heap allocator to provoke this bug.
+ //static const int primes[] = {2, 3, 5, 13, 89, 233, 1597, 28657, 514229}; // fibo primes
+ //const int primeCount = sizeof(primes)/sizeof(int);
+ //int alloc = primes[pass % primeCount] + pass;
+ //void *mem = qMalloc(alloc);
+ //qFree(mem);
+ QGraphicsAnchorLayout *l = createAmbiguousS60Layout();
+ p->setLayout(l);
+ QSizeF layoutMinimumSize = l->effectiveSizeHint(Qt::MinimumSize);
+ l->setGeometry(QRectF(QPointF(0,0), layoutMinimumSize));
+ QApplication::processEvents();
+ for (int i = l->count() - 1; i >=0 && sameAsPreviousArrangement; --i) {
+ QRectF geom = l->itemAt(i)->geometry();
+ if (pass != 0) {
+ sameAsPreviousArrangement = (geometries[i] == geom);
+ }
+ geometries[i] = geom;
+ }
+ p->setLayout(0); // uninstalls and deletes the layout
+ QApplication::processEvents();
+ }
+ delete p;
+ QEXPECT_FAIL("", "The layout have several solutions, but which solution it picks is not stable", Continue);
+ QCOMPARE(sameAsPreviousArrangement, true);
+}
+
+void tst_QGraphicsAnchorLayout::delete_anchor()
+{
+ QGraphicsScene scene;
+ QSizeF minSize(0, 0);
+ QSizeF prefSize(50, 50);
+ QSizeF maxSize(100, 100);
+ QGraphicsWidget *w1 = createItem(minSize, prefSize, maxSize, "w1");
+ QGraphicsWidget *w2 = createItem(minSize, prefSize, maxSize, "w2");
+ QGraphicsWidget *w3 = createItem(minSize, prefSize, maxSize, "w3");
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setSpacing(0);
+ l->setContentsMargins(0, 0, 0, 0);
+
+ // Horizontal
+ l->addAnchor(l, Qt::AnchorLeft, w1, Qt::AnchorLeft);
+ l->addAnchor(w1, Qt::AnchorRight, w2, Qt::AnchorLeft);
+ l->addAnchor(w2, Qt::AnchorRight, l, Qt::AnchorRight);
+ l->addAnchor(w1, Qt::AnchorRight, w3, Qt::AnchorLeft);
+ l->addAnchor(w3, Qt::AnchorRight, l, Qt::AnchorRight);
+
+ // Vertical
+ l->addAnchors(l, w1, Qt::Vertical);
+ l->addAnchors(l, w2, Qt::Vertical);
+ l->addAnchors(l, w3, Qt::Vertical);
+
+ QGraphicsAnchor *anchor = l->anchor(w3, Qt::AnchorRight, l, Qt::AnchorRight);
+ anchor->setSpacing(10);
+
+ QGraphicsWidget *p = new QGraphicsWidget;
+ p->setLayout(l);
+
+ QCOMPARE(l->count(), 3);
+
+ scene.addItem(p);
+ QGraphicsView *view = new QGraphicsView(&scene);
+ QApplication::processEvents();
+ // Should now be simplified
+ QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize).width(), qreal(110));
+ QGraphicsAnchor *anchor1 = l->anchor(w3, Qt::AnchorRight, l, Qt::AnchorRight);
+ QVERIFY(anchor1);
+ QGraphicsAnchor *anchor2 = l->anchor(w3, Qt::AnchorRight, l, Qt::AnchorRight);
+ QVERIFY(anchor2);
+ QGraphicsAnchor *anchor3 = l->anchor(l, Qt::AnchorRight, w3, Qt::AnchorRight);
+ QVERIFY(anchor3);
+ QGraphicsAnchor *anchor4 = l->anchor(l, Qt::AnchorRight, w3, Qt::AnchorRight);
+ QVERIFY(anchor4);
+
+ // should all be the same object
+ QCOMPARE(anchor1, anchor2);
+ QCOMPARE(anchor2, anchor3);
+ QCOMPARE(anchor3, anchor4);
+
+ // check if removal works
+ delete anchor1;
+
+ QApplication::processEvents();
+
+ // it should also change the preferred size of the layout
+ QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize).width(), qreal(100));
+
+ delete p;
+ delete view;
+}
+
+void tst_QGraphicsAnchorLayout::sizePolicy()
+{
+ QGraphicsScene scene;
+ QSizeF minSize(0, 0);
+ QSizeF prefSize(50, 50);
+ QSizeF maxSize(100, 100);
+ QGraphicsWidget *w1 = createItem(minSize, prefSize, maxSize, "w1");
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setSpacing(0);
+ l->setContentsMargins(0, 0, 0, 0);
+
+ // horizontal and vertical
+ l->addAnchors(l, w1);
+
+ QGraphicsWidget *p = new QGraphicsWidget;
+ p->setLayout(l);
+
+ scene.addItem(p);
+ QGraphicsView *view = new QGraphicsView(&scene);
+
+ // QSizePolicy::Minimum
+ w1->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+ QApplication::processEvents();
+ w1->adjustSize();
+
+ QCOMPARE(l->effectiveSizeHint(Qt::MinimumSize), QSizeF(50, 50));
+ QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize), QSizeF(50, 50));
+ QCOMPARE(l->effectiveSizeHint(Qt::MaximumSize), QSizeF(100, 100));
+
+ // QSizePolicy::Maximum
+ w1->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
+ QApplication::processEvents();
+ w1->adjustSize();
+
+ QCOMPARE(l->effectiveSizeHint(Qt::MinimumSize), QSizeF(0, 0));
+ QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize), QSizeF(50, 50));
+ QCOMPARE(l->effectiveSizeHint(Qt::MaximumSize), QSizeF(50, 50));
+
+ // QSizePolicy::Fixed
+ w1->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ QApplication::processEvents();
+ w1->adjustSize();
+
+ QCOMPARE(l->effectiveSizeHint(Qt::MinimumSize), QSizeF(50, 50));
+ QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize), QSizeF(50, 50));
+ QCOMPARE(l->effectiveSizeHint(Qt::MaximumSize), QSizeF(50, 50));
+
+ // QSizePolicy::Preferred
+ w1->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ QApplication::processEvents();
+ w1->adjustSize();
+
+ QCOMPARE(l->effectiveSizeHint(Qt::MinimumSize), QSizeF(0, 0));
+ QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize), QSizeF(50, 50));
+ QCOMPARE(l->effectiveSizeHint(Qt::MaximumSize), QSizeF(100, 100));
+
+ // QSizePolicy::Ignored
+ w1->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
+ QApplication::processEvents();
+ w1->adjustSize();
+
+ QCOMPARE(l->effectiveSizeHint(Qt::MinimumSize), QSizeF(0, 0));
+ QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize), QSizeF(0, 0));
+ QCOMPARE(l->effectiveSizeHint(Qt::MaximumSize), QSizeF(100, 100));
+
+ // Anchor size policies
+ w1->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ QGraphicsAnchor *anchor = l->anchor(l, Qt::AnchorLeft, w1, Qt::AnchorLeft);
+ anchor->setSpacing(10);
+
+ // QSizePolicy::Minimum
+ anchor->setSizePolicy(QSizePolicy::Minimum);
+ QApplication::processEvents();
+
+ QCOMPARE(l->effectiveSizeHint(Qt::MinimumSize), QSizeF(60, 50));
+ QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize), QSizeF(60, 50));
+ // The layout has a maximum size of QWIDGETSIZE_MAX, so the result won't exceed that value.
+ QCOMPARE(l->effectiveSizeHint(Qt::MaximumSize), QSizeF(QWIDGETSIZE_MAX, 50));
+
+ // QSizePolicy::Preferred
+ anchor->setSizePolicy(QSizePolicy::Preferred);
+ QApplication::processEvents();
+
+ QCOMPARE(l->effectiveSizeHint(Qt::MinimumSize), QSizeF(50, 50));
+ QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize), QSizeF(60, 50));
+ // The layout has a maximum size of QWIDGETSIZE_MAX, so the result won't exceed that value.
+ QCOMPARE(l->effectiveSizeHint(Qt::MaximumSize), QSizeF(QWIDGETSIZE_MAX, 50));
+
+ // QSizePolicy::Maximum
+ anchor->setSizePolicy(QSizePolicy::Maximum);
+ QApplication::processEvents();
+
+ QCOMPARE(l->effectiveSizeHint(Qt::MinimumSize), QSizeF(50, 50));
+ QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize), QSizeF(60, 50));
+ QCOMPARE(l->effectiveSizeHint(Qt::MaximumSize), QSizeF(60, 50));
+
+ // QSizePolicy::Ignored
+ anchor->setSizePolicy(QSizePolicy::Ignored);
+ QApplication::processEvents();
+
+ QCOMPARE(l->effectiveSizeHint(Qt::MinimumSize), QSizeF(50, 50));
+ QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize), QSizeF(50, 50));
+ QCOMPARE(l->effectiveSizeHint(Qt::MaximumSize), QSizeF(QWIDGETSIZE_MAX, 50));
+
+ if (hasSimplification) {
+ QVERIFY(!usedSimplex(l, Qt::Horizontal));
+ QVERIFY(!usedSimplex(l, Qt::Vertical));
+ }
+
+ delete p;
+ delete view;
+}
+
+/*!
+ \internal
+
+ Uses private API. (We have decided to pull hasConflicts() out of the API). However, it also
+ tests some tight conditions (almost-in-conflict) that we really want to test.
+*/
+void tst_QGraphicsAnchorLayout::conflicts()
+{
+ QGraphicsWidget *a = createItem(QSizeF(80,10), QSizeF(90,10), QSizeF(100,10), "a");
+ QGraphicsWidget *b = createItem(QSizeF(10,10), QSizeF(20,10), QSizeF(30,10), "b");
+ QGraphicsWidget *c = createItem(QSizeF(10,10), QSizeF(20,10), QSizeF(30,10), "c");
+
+ QGraphicsAnchorLayout *l;
+ QGraphicsWidget *p = new QGraphicsWidget(0, Qt::Window);
+
+ l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+
+ // with the following setup, 'a' cannot be larger than 30 we will first have a Simplex conflict
+
+ // horizontal
+ setAnchor(l, l, Qt::AnchorLeft, b, Qt::AnchorLeft);
+ setAnchor(l, b, Qt::AnchorRight, c, Qt::AnchorLeft);
+ setAnchor(l, c, Qt::AnchorRight, l, Qt::AnchorRight);
+ setAnchor(l, b, Qt::AnchorHorizontalCenter, a, Qt::AnchorLeft);
+ setAnchor(l, a, Qt::AnchorRight, c, Qt::AnchorHorizontalCenter);
+
+ // vertical
+ setAnchor(l, l, Qt::AnchorTop, a, Qt::AnchorTop);
+ setAnchor(l, a, Qt::AnchorBottom, b, Qt::AnchorTop);
+ setAnchor(l, a, Qt::AnchorBottom, c, Qt::AnchorTop);
+ setAnchor(l, b, Qt::AnchorBottom, l, Qt::AnchorBottom);
+ setAnchor(l, c, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ p->setLayout(l);
+
+ QCOMPARE(layoutHasConflict(l), true);
+
+ a->setMinimumSize(QSizeF(29,10));
+ QCOMPARE(layoutHasConflict(l), false);
+
+ a->setMinimumSize(QSizeF(30,10));
+ QCOMPARE(layoutHasConflict(l), false);
+
+ delete p;
+}
+
+void tst_QGraphicsAnchorLayout::floatConflict()
+{
+ QGraphicsWidget *a = createItem(QSizeF(80,10), QSizeF(90,10), QSizeF(100,10), "a");
+ QGraphicsWidget *b = createItem(QSizeF(80,10), QSizeF(90,10), QSizeF(100,10), "b");
+
+ QGraphicsAnchorLayout *l;
+ QGraphicsWidget *p = new QGraphicsWidget(0, Qt::Window);
+
+ l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+
+ p->setLayout(l);
+
+ // horizontal
+ // with this anchor we have two floating items
+ setAnchor(l, a, Qt::AnchorRight, b, Qt::AnchorLeft);
+
+ // Just checking if the layout is handling well the removal of floating items
+ delete l->anchor(a, Qt::AnchorRight, b, Qt::AnchorLeft);
+ QCOMPARE(l->count(), 0);
+ QCOMPARE(layoutHasConflict(l), false);
+
+ // setting back the same anchor
+ setAnchor(l, a, Qt::AnchorRight, b, Qt::AnchorLeft);
+
+ // We don't support floating items but they should be counted as if they are in the layout
+ QCOMPARE(l->count(), 2);
+ // Although, we have an invalid situation
+ QCOMPARE(layoutHasConflict(l), true);
+
+ // Semi-floats are supported
+ setAnchor(l, a, Qt::AnchorLeft, l, Qt::AnchorLeft);
+ QCOMPARE(l->count(), 2);
+
+ // Vertically the layout has floating items. Therefore, we have a conflict
+ QCOMPARE(layoutHasConflict(l), true);
+
+ // No more floating items
+ setAnchor(l, b, Qt::AnchorRight, l, Qt::AnchorRight);
+ setAnchor(l, a, Qt::AnchorTop, l, Qt::AnchorTop);
+ setAnchor(l, a, Qt::AnchorBottom, l, Qt::AnchorBottom);
+ setAnchor(l, b, Qt::AnchorTop, l, Qt::AnchorTop);
+ setAnchor(l, b, Qt::AnchorBottom, l, Qt::AnchorBottom);
+ QCOMPARE(layoutHasConflict(l), false);
+
+ delete p;
+}
+
+void tst_QGraphicsAnchorLayout::infiniteMaxSizes()
+{
+ if (sizeof(qreal) <= 4) {
+ QSKIP("qreal has too little precision, result will be wrong", SkipAll);
+ }
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ QSizeF minSize(10, 10);
+ QSizeF pref(50, 10);
+ QSizeF maxSize(QWIDGETSIZE_MAX, 10);
+
+ QGraphicsWidget *a = createItem(minSize, pref, maxSize, "a");
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize, "b");
+ QGraphicsWidget *c = createItem(minSize, pref, maxSize, "c");
+ QGraphicsWidget *d = createItem(minSize, pref, maxSize, "d");
+ QGraphicsWidget *e = createItem(minSize, pref, maxSize, "e");
+
+ //<!-- Trunk -->
+ setAnchor(l, l, Qt::AnchorLeft, a, Qt::AnchorLeft, 0);
+ setAnchor(l, a, Qt::AnchorRight, b, Qt::AnchorLeft, 0);
+ setAnchor(l, b, Qt::AnchorRight, c, Qt::AnchorLeft, 0);
+ setAnchor(l, c, Qt::AnchorRight, d, Qt::AnchorLeft, 0);
+ setAnchor(l, d, Qt::AnchorRight, l, Qt::AnchorRight, 0);
+ setAnchor(l, b, Qt::AnchorHorizontalCenter, e, Qt::AnchorLeft, 0);
+ setAnchor(l, e, Qt::AnchorRight, c, Qt::AnchorHorizontalCenter, 0);
+
+ QGraphicsWidget p;
+ p.setLayout(l);
+
+ QCOMPARE(int(p.effectiveSizeHint(Qt::MaximumSize).width()),
+ QWIDGETSIZE_MAX);
+
+ p.resize(200, 10);
+ QCOMPARE(a->geometry(), QRectF(0, 0, 50, 10));
+ QCOMPARE(b->geometry(), QRectF(50, 0, 50, 10));
+ QCOMPARE(c->geometry(), QRectF(100, 0, 50, 10));
+ QCOMPARE(d->geometry(), QRectF(150, 0, 50, 10));
+
+ p.resize(1000, 10);
+ QCOMPARE(a->geometry(), QRectF(0, 0, 250, 10));
+ QCOMPARE(b->geometry(), QRectF(250, 0, 250, 10));
+ QCOMPARE(c->geometry(), QRectF(500, 0, 250, 10));
+ QCOMPARE(d->geometry(), QRectF(750, 0, 250, 10));
+
+ p.resize(40000, 10);
+ QCOMPARE(a->geometry(), QRectF(0, 0, 10000, 10));
+ QCOMPARE(b->geometry(), QRectF(10000, 0, 10000, 10));
+ QCOMPARE(c->geometry(), QRectF(20000, 0, 10000, 10));
+ QCOMPARE(d->geometry(), QRectF(30000, 0, 10000, 10));
+}
+
+void tst_QGraphicsAnchorLayout::simplifiableUnfeasible()
+{
+ QGraphicsWidget *a = createItem(QSizeF(70.0, 100.0),
+ QSizeF(100.0, 100.0),
+ QSizeF(100.0, 100.0), "A");
+
+ QGraphicsWidget *b = createItem(QSizeF(110.0, 100.0),
+ QSizeF(150.0, 100.0),
+ QSizeF(190.0, 100.0), "B");
+
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ l->addAnchor(l, Qt::AnchorTop, a, Qt::AnchorTop);
+ l->addAnchor(a, Qt::AnchorBottom, b, Qt::AnchorTop);
+ l->addAnchor(b, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ l->addAnchors(l, a, Qt::Horizontal);
+ l->addAnchor(l, Qt::AnchorLeft, b, Qt::AnchorLeft);
+ l->addAnchor(b, Qt::AnchorRight, a, Qt::AnchorRight);
+
+ QCOMPARE(l->count(), 2);
+
+ QGraphicsWidget p;
+ p.setLayout(l);
+
+ l->invalidate();
+ QVERIFY(layoutHasConflict(l));
+ if (hasSimplification)
+ QVERIFY(!usedSimplex(l, Qt::Horizontal));
+
+ // Now we make it valid
+ b->setMinimumWidth(100);
+
+ l->invalidate();
+ QVERIFY(!layoutHasConflict(l));
+ if (hasSimplification)
+ QVERIFY(!usedSimplex(l, Qt::Horizontal));
+
+ // And make it invalid again
+ a->setPreferredWidth(70);
+ a->setMaximumWidth(70);
+
+ l->invalidate();
+ QVERIFY(layoutHasConflict(l));
+ if (hasSimplification)
+ QVERIFY(!usedSimplex(l, Qt::Horizontal));
+}
+
+/*
+ Test whether the anchor direction can prevent it from
+ being simplificated
+*/
+void tst_QGraphicsAnchorLayout::simplificationVsOrder()
+{
+ QSizeF minSize(10, 10);
+ QSizeF pref(20, 10);
+ QSizeF maxSize(50, 10);
+
+ QGraphicsWidget *a = createItem(minSize, pref, maxSize, "A");
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize, "B");
+ QGraphicsWidget *c = createItem(minSize, pref, maxSize, "C");
+
+ QGraphicsWidget frame;
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout(&frame);
+
+ // Bulk anchors
+ l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+ l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorLeft);
+ l->addAnchor(b, Qt::AnchorLeft, c, Qt::AnchorLeft);
+ l->addAnchor(c, Qt::AnchorRight, l, Qt::AnchorRight);
+
+ // Problematic anchor, direction b->c
+ QGraphicsAnchor *anchor = l->addAnchor(b, Qt::AnchorRight, c, Qt::AnchorRight);
+ anchor->setSpacing(5);
+
+ l->effectiveSizeHint(Qt::MinimumSize);
+ if (hasSimplification) {
+ QCOMPARE(usedSimplex(l, Qt::Horizontal), false);
+ QCOMPARE(usedSimplex(l, Qt::Vertical), false);
+ }
+
+ // Problematic anchor, direction c->b
+ delete anchor;
+ anchor = l->addAnchor(c, Qt::AnchorRight, b, Qt::AnchorRight);
+ anchor->setSpacing(5);
+
+ l->effectiveSizeHint(Qt::MinimumSize);
+ if (hasSimplification) {
+ QCOMPARE(usedSimplex(l, Qt::Horizontal), false);
+ QCOMPARE(usedSimplex(l, Qt::Vertical), false);
+ }
+}
+
+void tst_QGraphicsAnchorLayout::parallelSimplificationOfCenter()
+{
+ QSizeF minSize(10, 10);
+ QSizeF pref(20, 10);
+ QSizeF maxSize(50, 10);
+
+ QGraphicsWidget *a = createItem(minSize, pref, maxSize, "A");
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize, "B");
+
+ QGraphicsWidget parent;
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout(&parent);
+ l->setContentsMargins(0, 0, 0, 0);
+
+ l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+ l->addAnchor(l, Qt::AnchorRight, a, Qt::AnchorRight);
+
+ l->addAnchor(a, Qt::AnchorHorizontalCenter, b, Qt::AnchorLeft);
+ l->addAnchor(b, Qt::AnchorRight, a, Qt::AnchorRight);
+
+ parent.resize(l->effectiveSizeHint(Qt::PreferredSize));
+
+ QCOMPARE(a->geometry(), QRectF(0, 0, 40, 10));
+ QCOMPARE(b->geometry(), QRectF(20, 0, 20, 10));
+}
+
+/*
+ Test whether redundance of anchors (in this case by using addCornerAnchors), will
+ prevent simplification to take place when it should.
+*/
+void tst_QGraphicsAnchorLayout::simplificationVsRedundance()
+{
+ QSizeF minSize(10, 10);
+ QSizeF pref(20, 10);
+ QSizeF maxSize(50, 30);
+
+ QGraphicsWidget *a = createItem(minSize, pref, maxSize, "A");
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize, "B");
+ QGraphicsWidget *c = createItem(minSize, pref, maxSize, "C");
+
+ QGraphicsWidget frame;
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout(&frame);
+
+ l->addCornerAnchors(a, Qt::TopLeftCorner, l, Qt::TopLeftCorner);
+ l->addCornerAnchors(a, Qt::BottomLeftCorner, l, Qt::BottomLeftCorner);
+
+ l->addCornerAnchors(b, Qt::TopLeftCorner, a, Qt::TopRightCorner);
+ l->addCornerAnchors(b, Qt::TopRightCorner, l, Qt::TopRightCorner);
+
+ l->addCornerAnchors(c, Qt::TopLeftCorner, b, Qt::BottomLeftCorner);
+ l->addCornerAnchors(c, Qt::BottomLeftCorner, a, Qt::BottomRightCorner);
+ l->addCornerAnchors(c, Qt::TopRightCorner, b, Qt::BottomRightCorner);
+ l->addCornerAnchors(c, Qt::BottomRightCorner, l, Qt::BottomRightCorner);
+
+ l->effectiveSizeHint(Qt::MinimumSize);
+
+ QCOMPARE(layoutHasConflict(l), false);
+
+ if (!hasSimplification)
+ QEXPECT_FAIL("", "Test depends on simplification.", Abort);
+
+ QCOMPARE(usedSimplex(l, Qt::Horizontal), false);
+ QCOMPARE(usedSimplex(l, Qt::Vertical), false);
+}
+
+/*
+ Avoid regression where the saved prefSize would be lost. This was
+ solved by saving the original spacing in the QGraphicsAnchorPrivate class
+*/
+void tst_QGraphicsAnchorLayout::spacingPersistency()
+{
+ QGraphicsWidget w;
+ QGraphicsWidget *a = createItem();
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout(&w);
+
+ l->addAnchors(l, a, Qt::Horizontal);
+ QGraphicsAnchor *anchor = l->anchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+
+ anchor->setSpacing(-30);
+ QCOMPARE(anchor->spacing(), -30.0);
+
+ anchor->setSpacing(30);
+ QCOMPARE(anchor->spacing(), 30.0);
+
+ anchor->setSizePolicy(QSizePolicy::Ignored);
+ w.effectiveSizeHint(Qt::PreferredSize);
+
+ QCOMPARE(anchor->spacing(), 30.0);
+}
+
+/*
+ Test whether a correct preferred size is set when a "snake" sequence is in parallel with the
+ layout or half of the layout. The tricky thing here is that all items on the snake should
+ keep their preferred sizes.
+*/
+void tst_QGraphicsAnchorLayout::snakeParallelWithLayout()
+{
+ QSizeF minSize(10, 20);
+ QSizeF pref(50, 20);
+ QSizeF maxSize(100, 20);
+
+ QGraphicsWidget *a = createItem(maxSize, maxSize, maxSize, "A");
+ QGraphicsWidget *b = createItem(minSize, pref, maxSize, "B");
+ QGraphicsWidget *c = createItem(maxSize, maxSize, maxSize, "C");
+
+ QGraphicsWidget parent;
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout(&parent);
+ l->setContentsMargins(0, 0, 0, 0);
+ l->setSpacing(0);
+
+ // First we'll do the case in parallel with the entire layout...
+ l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+ l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorRight);
+ l->addAnchor(b, Qt::AnchorLeft, c, Qt::AnchorLeft);
+ l->addAnchor(c, Qt::AnchorRight, l, Qt::AnchorRight);
+
+ l->addAnchor(l, Qt::AnchorTop, a, Qt::AnchorTop);
+ l->addAnchor(a, Qt::AnchorBottom, b, Qt::AnchorTop);
+ l->addAnchor(b, Qt::AnchorBottom, c, Qt::AnchorTop);
+ l->addAnchor(c, Qt::AnchorBottom, l, Qt::AnchorBottom);
+
+ parent.resize(l->effectiveSizeHint(Qt::PreferredSize));
+
+ // Note that A and C are fixed in the maximum size
+ QCOMPARE(l->geometry(), QRectF(QPointF(0, 0), QSizeF(150, 60)));
+ QCOMPARE(a->geometry(), QRectF(QPointF(0, 0), maxSize));
+ QCOMPARE(b->geometry(), QRectF(QPointF(50, 20), pref));
+ QCOMPARE(c->geometry(), QRectF(QPointF(50, 40), maxSize));
+
+ // Then, we change the "snake" to be in parallel with half of the layout
+ delete l->anchor(c, Qt::AnchorRight, l, Qt::AnchorRight);
+ l->addAnchor(c, Qt::AnchorRight, l, Qt::AnchorHorizontalCenter);
+
+ parent.resize(l->effectiveSizeHint(Qt::PreferredSize));
+
+ QCOMPARE(l->geometry(), QRectF(QPointF(0, 0), QSizeF(300, 60)));
+ QCOMPARE(a->geometry(), QRectF(QPointF(0, 0), maxSize));
+ QCOMPARE(b->geometry(), QRectF(QPointF(50, 20), pref));
+ QCOMPARE(c->geometry(), QRectF(QPointF(50, 40), maxSize));
+}
+
+/*
+ Avoid regression where the sizeHint constraints would not be
+ created for a parallel anchor that included the first layout half
+*/
+void tst_QGraphicsAnchorLayout::parallelToHalfLayout()
+{
+ QGraphicsWidget *a = createItem();
+
+ QGraphicsWidget w;
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout(&w);
+ l->setContentsMargins(10, 10, 10, 10);
+
+ l->addAnchors(l, a, Qt::Vertical);
+
+ QGraphicsAnchor *anchor;
+ anchor = l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+ anchor->setSpacing(5);
+ anchor = l->addAnchor(l, Qt::AnchorHorizontalCenter, a, Qt::AnchorRight);
+ anchor->setSpacing(-5);
+
+ const QSizeF minimumSizeHint = w.effectiveSizeHint(Qt::MinimumSize);
+ const QSizeF preferredSizeHint = w.effectiveSizeHint(Qt::PreferredSize);
+ const QSizeF maximumSizeHint = w.effectiveSizeHint(Qt::MaximumSize);
+
+ const QSizeF overhead = QSizeF(10 + 5 + 5, 10) * 2;
+
+ QCOMPARE(minimumSizeHint, QSizeF(200, 100) + overhead);
+ QCOMPARE(preferredSizeHint, QSizeF(300, 100) + overhead);
+ QCOMPARE(maximumSizeHint, QSizeF(400, 100) + overhead);
+}
+
+void tst_QGraphicsAnchorLayout::globalSpacing()
+{
+ QGraphicsWidget *a = createItem();
+ QGraphicsWidget *b = createItem();
+
+ QGraphicsWidget w;
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout(&w);
+
+ l->addCornerAnchors(l, Qt::TopLeftCorner, a, Qt::TopLeftCorner);
+ l->addCornerAnchors(a, Qt::BottomRightCorner, b, Qt::TopLeftCorner);
+ l->addCornerAnchors(b, Qt::BottomRightCorner, l, Qt::BottomRightCorner);
+
+ w.resize(w.effectiveSizeHint(Qt::PreferredSize));
+ qreal vSpacing = b->geometry().top() - a->geometry().bottom();
+ qreal hSpacing = b->geometry().left() - a->geometry().right();
+
+ // Set spacings manually
+ l->setVerticalSpacing(vSpacing + 10);
+ l->setHorizontalSpacing(hSpacing + 5);
+
+ w.resize(w.effectiveSizeHint(Qt::PreferredSize));
+ qreal newVSpacing = b->geometry().top() - a->geometry().bottom();
+ qreal newHSpacing = b->geometry().left() - a->geometry().right();
+
+ QCOMPARE(newVSpacing, vSpacing + 10);
+ QCOMPARE(newHSpacing, hSpacing + 5);
+
+ // Set a negative spacing. This will unset the previous spacing and
+ // bring back the widget-defined spacing.
+ l->setSpacing(-1);
+
+ w.resize(w.effectiveSizeHint(Qt::PreferredSize));
+ newVSpacing = b->geometry().top() - a->geometry().bottom();
+ newHSpacing = b->geometry().left() - a->geometry().right();
+
+ QCOMPARE(newVSpacing, vSpacing);
+ QCOMPARE(newHSpacing, hSpacing);
+}
+
+void tst_QGraphicsAnchorLayout::graphicsAnchorHandling()
+{
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout();
+ QGraphicsWidget *a = createItem();
+
+ l->addAnchors(l, a);
+
+ QGraphicsAnchor *layoutAnchor = l->anchor(l, Qt::AnchorTop, l, Qt::AnchorBottom);
+ QGraphicsAnchor *itemAnchor = l->anchor(a, Qt::AnchorTop, a, Qt::AnchorBottom);
+ QGraphicsAnchor *invalidAnchor = l->anchor(a, Qt::AnchorTop, l, Qt::AnchorBottom);
+
+ // Ensure none of these anchors are accessible.
+ QVERIFY(layoutAnchor == 0);
+ QVERIFY(itemAnchor == 0);
+ QVERIFY(invalidAnchor == 0);
+
+ // Hook the anchors to a QObject
+ QObject object;
+ QGraphicsAnchor *userAnchor = l->anchor(l, Qt::AnchorTop, a, Qt::AnchorTop);
+ userAnchor->setParent(&object);
+ userAnchor = l->anchor(l, Qt::AnchorBottom, a, Qt::AnchorBottom);
+ userAnchor->setParent(&object);
+ userAnchor = l->anchor(l, Qt::AnchorRight, a, Qt::AnchorRight);
+ userAnchor->setParent(&object);
+ userAnchor = l->anchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft);
+ userAnchor->setParent(&object);
+
+ QCOMPARE(object.children().size(), 4);
+
+ // Delete layout, this will cause all anchors to be deleted internally.
+ // We expect the public QGraphicsAnchor instances to be deleted too.
+ delete l;
+ QCOMPARE(object.children().size(), 0);
+
+ delete a;
+}
+
+void tst_QGraphicsAnchorLayout::invalidHierarchyCheck()
+{
+ QGraphicsWidget window(0, Qt::Window);
+ QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout;
+ window.setLayout(l);
+
+ QCOMPARE(l->count(), 0);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): "
+ "You cannot add the parent of the layout to the layout.");
+ QVERIFY(!l->addAnchor(l, Qt::AnchorLeft, &window, Qt::AnchorLeft));
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): "
+ "You cannot add the parent of the layout to the layout.");
+ l->addAnchors(l, &window);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): "
+ "You cannot add the parent of the layout to the layout.");
+ l->addCornerAnchors(l, Qt::TopLeftCorner, &window, Qt::TopLeftCorner);
+ QCOMPARE(l->count(), 0);
+}
+
+QTEST_MAIN(tst_QGraphicsAnchorLayout)
+#include "tst_qgraphicsanchorlayout.moc"
diff --git a/tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/qgraphicsanchorlayout1.pro b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/qgraphicsanchorlayout1.pro
new file mode 100644
index 0000000000..bcad43fc12
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/qgraphicsanchorlayout1.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets widgets-private
+QT += core-private gui-private
+SOURCES += tst_qgraphicsanchorlayout1.cpp
+CONFIG += parallel_test
diff --git a/tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp
new file mode 100644
index 0000000000..05f08e8719
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp
@@ -0,0 +1,3111 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.1, 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui>
+#include <QtTest/QtTest>
+#include <QTest>
+#include <QMetaType>
+#include <QtWidgets/qgraphicsanchorlayout.h>
+#include <private/qgraphicsanchorlayout_p.h>
+
+#define TEST_COMPLEX_CASES
+
+
+//---------------------- AnchorLayout helper class ----------------------------
+class TheAnchorLayout : public QGraphicsAnchorLayout
+{
+public:
+ TheAnchorLayout() : QGraphicsAnchorLayout()
+ {
+ setContentsMargins( 0,0,0,0 );
+ setSpacing( 0 );
+ }
+
+ bool isValid()
+ {
+ return !QGraphicsAnchorLayoutPrivate::get(this)->hasConflicts();
+ }
+
+ void setAnchor(
+ QGraphicsLayoutItem *startItem,
+ Qt::AnchorPoint startEdge,
+ QGraphicsLayoutItem *endItem,
+ Qt::AnchorPoint endEdge,
+ qreal value)
+ {
+ QGraphicsAnchor *anchor = addAnchor( startItem, startEdge, endItem, endEdge);
+ if (anchor)
+ anchor->setSpacing(value);
+ }
+
+ int indexOf(const QGraphicsLayoutItem* item) const
+ {
+ for ( int i=0; i< count(); i++) {
+ if ( itemAt(i) == item ) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ void removeItem(QGraphicsLayoutItem* item)
+ {
+ removeAt(indexOf(item));
+ }
+
+ void removeAnchor(
+ QGraphicsLayoutItem *startItem,
+ Qt::AnchorPoint startEdge,
+ QGraphicsLayoutItem *endItem,
+ Qt::AnchorPoint endEdge)
+ {
+ delete QGraphicsAnchorLayout::anchor(startItem, startEdge, endItem, endEdge);
+ }
+};
+//-----------------------------------------------------------------------------
+
+
+struct BasicLayoutTestData
+{
+ inline BasicLayoutTestData(
+ int index1, Qt::AnchorPoint edge1,
+ int index2, Qt::AnchorPoint edge2,
+ qreal distance)
+ : firstIndex(index1), firstEdge(edge1),
+ secondIndex(index2), secondEdge(edge2),
+ spacing(distance)
+ {
+ }
+
+ int firstIndex;
+ Qt::AnchorPoint firstEdge;
+ int secondIndex;
+ Qt::AnchorPoint secondEdge;
+ qreal spacing;
+};
+
+struct AnchorItemSizeHint
+{
+ inline AnchorItemSizeHint(
+ qreal hmin, qreal hpref, qreal hmax,
+ qreal vmin, qreal vpref, qreal vmax )
+ : hmin(hmin), hpref(hpref), hmax(hmax), vmin(vmin), vpref(vpref), vmax(vmax)
+ {
+ }
+ qreal hmin, hpref, hmax;
+ qreal vmin, vpref, vmax;
+};
+
+// some test results
+
+struct BasicLayoutTestResult
+{
+ inline BasicLayoutTestResult(
+ int resultIndex, const QRectF& resultRect )
+ : index(resultIndex), rect(resultRect)
+ {
+ }
+
+ int index;
+ QRectF rect;
+};
+
+typedef QList<BasicLayoutTestData> BasicLayoutTestDataList;
+Q_DECLARE_METATYPE(BasicLayoutTestDataList)
+
+typedef QList<BasicLayoutTestResult> BasicLayoutTestResultList;
+Q_DECLARE_METATYPE(BasicLayoutTestResultList)
+
+typedef QList<AnchorItemSizeHint> AnchorItemSizeHintList;
+Q_DECLARE_METATYPE(AnchorItemSizeHintList)
+
+
+//---------------------- Test Widget used on all tests ------------------------
+class TestWidget : public QGraphicsWidget
+{
+public:
+ inline TestWidget(QGraphicsItem *parent = 0, const QString &name = QString())
+ : QGraphicsWidget(parent)
+ {
+ setContentsMargins( 0,0,0,0 );
+ if (name.isEmpty())
+ setData(0, QString::fromAscii("w%1").arg(quintptr(this)));
+ else
+ setData(0, name);
+ }
+ ~TestWidget()
+ {
+ }
+
+protected:
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
+};
+
+QSizeF TestWidget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
+{
+ Q_UNUSED( constraint );
+ if (which == Qt::MinimumSize) {
+ return QSizeF(5,5);
+ }
+
+ if (which == Qt::PreferredSize) {
+ return QSizeF(50,50);
+ }
+
+ return QSizeF(500,500);
+}
+//-----------------------------------------------------------------------------
+
+
+
+//----------------------------- Test class ------------------------------------
+class tst_QGraphicsAnchorLayout1 : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void testCount();
+
+ void testRemoveAt();
+ void testRemoveItem();
+
+ void testItemAt();
+ void testIndexOf();
+
+ void testAddAndRemoveAnchor();
+ void testIsValid();
+ void testSpecialCases();
+
+ void testBasicLayout_data();
+ void testBasicLayout();
+
+ void testNegativeSpacing_data();
+ void testNegativeSpacing();
+
+ void testMixedSpacing_data();
+ void testMixedSpacing();
+
+ void testMulti_data();
+ void testMulti();
+
+ void testCenterAnchors_data();
+ void testCenterAnchors();
+
+ void testRemoveCenterAnchor_data();
+ void testRemoveCenterAnchor();
+
+ void testSingleSizePolicy_data();
+ void testSingleSizePolicy();
+
+ void testDoubleSizePolicy_data();
+ void testDoubleSizePolicy();
+
+ void testSizeDistribution_data();
+ void testSizeDistribution();
+
+ void testSizeHint();
+
+#ifdef TEST_COMPLEX_CASES
+ void testComplexCases_data();
+ void testComplexCases();
+#endif
+};
+
+
+void tst_QGraphicsAnchorLayout1::testCount()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+
+ TheAnchorLayout *layout = new TheAnchorLayout();
+ QVERIFY( layout->count() == 0 );
+
+ TestWidget *widget1 = new TestWidget();
+ layout->setAnchor(layout, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 1);
+ QCOMPARE( layout->count(), 1 );
+
+ // adding one more anchor for already added widget should not increase the count
+ layout->setAnchor(layout, Qt::AnchorRight, widget1, Qt::AnchorRight, 1);
+ QCOMPARE( layout->count(), 1 );
+
+ // create one more widget and attach with anchor layout
+ TestWidget *widget2 = new TestWidget();
+ layout->setAnchor(layout, Qt::AnchorLeft, widget2, Qt::AnchorLeft, 1);
+ QCOMPARE( layout->count(), 2 );
+
+ widget->setLayout(layout);
+ delete widget;
+}
+
+void tst_QGraphicsAnchorLayout1::testRemoveAt()
+{
+ TheAnchorLayout *layout = new TheAnchorLayout();
+ QVERIFY( layout->count() == 0 );
+
+ TestWidget *widget1 = new TestWidget();
+ layout->setAnchor(layout, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 2);
+ QVERIFY( layout->count() == 1 );
+
+ TestWidget *widget2 = new TestWidget();
+ layout->setAnchor(widget2, Qt::AnchorLeft, layout, Qt::AnchorLeft, 0.1);
+ QVERIFY( layout->count() == 2 );
+
+ layout->removeAt(0);
+ QVERIFY( layout->count() == 1 );
+
+ layout->removeAt(-55);
+ layout->removeAt(55);
+ QVERIFY( layout->count() == 1 );
+
+ layout->removeAt(0);
+ QVERIFY( layout->count() == 0 );
+
+ delete layout;
+ delete widget1;
+ delete widget2;
+}
+
+void tst_QGraphicsAnchorLayout1::testRemoveItem()
+{
+ TheAnchorLayout *layout = new TheAnchorLayout();
+ QCOMPARE( layout->count(), 0 );
+
+ TestWidget *widget1 = new TestWidget();
+ layout->setAnchor(layout, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 2);
+ QCOMPARE( layout->count(), 1 );
+
+ TestWidget *widget2 = new TestWidget();
+ layout->setAnchor(layout, Qt::AnchorLeft, widget2, Qt::AnchorLeft, 0.1);
+ QCOMPARE( layout->count(), 2 );
+
+ layout->removeItem(0);
+ QCOMPARE( layout->count(), 2 );
+
+ layout->removeItem(widget1);
+ QCOMPARE( layout->count(), 1 );
+ QCOMPARE( layout->indexOf(widget1), -1 );
+ QCOMPARE( layout->indexOf(widget2), 0 );
+
+ layout->removeItem(widget1);
+ QCOMPARE( layout->count(), 1 );
+
+ layout->removeItem(widget2);
+ QVERIFY( layout->count() == 0 );
+
+ delete layout;
+ delete widget1;
+ delete widget2;
+}
+
+void tst_QGraphicsAnchorLayout1::testItemAt()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+
+ TheAnchorLayout *layout = new TheAnchorLayout();
+
+ TestWidget *widget1 = new TestWidget();
+ TestWidget *widget2 = new TestWidget();
+ TestWidget *widget3 = new TestWidget();
+ TestWidget *widget4 = new TestWidget();
+
+ layout->setAnchor(layout, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 0.1);
+ layout->setAnchor(layout, Qt::AnchorLeft, widget2, Qt::AnchorLeft, 0.1);
+ layout->setAnchor(layout, Qt::AnchorLeft, widget3, Qt::AnchorLeft, 0.1);
+ layout->setAnchor(layout, Qt::AnchorLeft, widget4, Qt::AnchorLeft, 0.1);
+
+ QVERIFY( layout->itemAt(0) == widget1 );
+
+ layout->removeAt(0);
+
+ QVERIFY( layout->itemAt(0) == widget2 );
+
+ delete widget1;
+
+ widget->setLayout(layout);
+ delete widget;
+}
+
+void tst_QGraphicsAnchorLayout1::testIndexOf()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+
+ TheAnchorLayout *layout = new TheAnchorLayout();
+
+ TestWidget *widget1 = new TestWidget();
+ TestWidget *widget2 = new TestWidget();
+ TestWidget *widget3 = new TestWidget();
+ TestWidget *widget4 = new TestWidget();
+
+ QCOMPARE( layout->indexOf(widget1), -1 );
+
+ layout->setAnchor(layout, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 0.1);
+ layout->setAnchor(layout, Qt::AnchorLeft, widget2, Qt::AnchorLeft, 0.1);
+ layout->setAnchor(layout, Qt::AnchorLeft, widget3, Qt::AnchorLeft, 0.1);
+
+ QCOMPARE( layout->indexOf(widget4), -1 );
+ layout->setAnchor(layout, Qt::AnchorLeft, widget4, Qt::AnchorLeft, 0.1);
+
+ QCOMPARE( layout->count(), 4 );
+ for (int i = 0; i < layout->count(); ++i) {
+ QCOMPARE(layout->indexOf(layout->itemAt(i)), i);
+ }
+
+ QCOMPARE( layout->indexOf(0), -1 );
+ widget->setLayout(layout);
+ delete widget;
+}
+
+void tst_QGraphicsAnchorLayout1::testAddAndRemoveAnchor()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+
+ TheAnchorLayout *layout = new TheAnchorLayout();
+
+ TestWidget *widget1 = new TestWidget();
+ TestWidget *widget2 = new TestWidget();
+ TestWidget *widget3 = new TestWidget();
+ TestWidget *widget4 = new TestWidget();
+ TestWidget *widget5 = new TestWidget();
+
+ layout->setAnchor(layout, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 0.1);
+ layout->setAnchor(layout, Qt::AnchorLeft, widget2, Qt::AnchorLeft, 0.5);
+ layout->setAnchor(layout, Qt::AnchorLeft, widget3, Qt::AnchorLeft, 10);
+ layout->setAnchor(layout, Qt::AnchorLeft, widget4, Qt::AnchorLeft, 0.1);
+ QCOMPARE( layout->count(), 4 );
+
+ // test setting invalid anchors
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor NULL items");
+ layout->setAnchor(0, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 1);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor NULL items");
+ layout->setAnchor(layout, Qt::AnchorLeft, 0, Qt::AnchorLeft, 1);
+ QCOMPARE( layout->count(), 4 );
+
+ // test removing invalid anchors
+ layout->removeAnchor(widget4, Qt::AnchorRight, widget1, Qt::AnchorRight);
+
+ // anchor one horizontal edge with vertical edge. it should not add this widget as a child
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor edges of different orientations");
+ layout->setAnchor(layout, Qt::AnchorLeft, widget5, Qt::AnchorTop, 10);
+ QCOMPARE( layout->count(), 4 );
+
+ // anchor two edges of a widget (to define width / height)
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ layout->setAnchor(widget5, Qt::AnchorLeft, widget5, Qt::AnchorRight, 10);
+ // QCOMPARE( layout->count(), 5 );
+ QCOMPARE( layout->count(), 4 );
+
+ // anchor yet new widget properly
+ layout->setAnchor(layout, Qt::AnchorRight, widget5, Qt::AnchorRight, 20 );
+ QCOMPARE( layout->count(), 5 );
+
+ // remove anchor for widget1. widget1 should be removed from layout since the
+ // last anchor was removed.
+ layout->removeAnchor(layout, Qt::AnchorLeft, widget1, Qt::AnchorLeft);
+
+ QCOMPARE( layout->count(), 4 );
+ QVERIFY( !widget1->parentLayoutItem() );
+
+ // test that item is not removed from layout if other anchors remain set
+ layout->setAnchor(widget2, Qt::AnchorLeft, widget3, Qt::AnchorRight, 10);
+ layout->removeAnchor(layout, Qt::AnchorLeft, widget2, Qt::AnchorLeft);
+ QCOMPARE( layout->count(), 4 );
+
+ // remove all the anchors
+ layout->removeAnchor(widget2, Qt::AnchorLeft, widget3, Qt::AnchorRight);
+ layout->removeAnchor(layout, Qt::AnchorLeft, widget3, Qt::AnchorLeft);
+ layout->removeAnchor(layout, Qt::AnchorLeft, widget4, Qt::AnchorLeft);
+ layout->removeAnchor(widget5, Qt::AnchorLeft, widget5, Qt::AnchorRight);
+ layout->removeAnchor(layout, Qt::AnchorRight, widget5, Qt::AnchorRight);
+
+ QCOMPARE( layout->count(), 0 );
+
+ // set one anchor "another way round" to get full coverage for "removeAnchor"
+ layout->setAnchor(widget1, Qt::AnchorLeft, layout, Qt::AnchorLeft, 0.1);
+ layout->removeAnchor(widget1, Qt::AnchorLeft, layout, Qt::AnchorLeft);
+
+ QCOMPARE( layout->count(), 0 );
+
+ delete widget1;
+ delete widget2;
+ delete widget3;
+ delete widget4;
+ delete widget5;
+
+ widget->setLayout(layout);
+ delete widget;
+}
+
+void tst_QGraphicsAnchorLayout1::testIsValid()
+{
+ // Empty, valid
+ {
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ TheAnchorLayout *layout = new TheAnchorLayout();
+ widget->setLayout(layout);
+ widget->setGeometry(QRectF(0,0,100,100));
+
+ QCOMPARE(layout->isValid(), true);
+ delete widget;
+ }
+
+ // One widget, valid
+ {
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ TheAnchorLayout *layout = new TheAnchorLayout();
+
+ TestWidget *widget1 = new TestWidget();
+
+ layout->setAnchor(layout, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 0.1);
+ layout->setAnchor(layout, Qt::AnchorTop, widget1, Qt::AnchorTop, 0.1);
+ layout->setAnchor(widget1, Qt::AnchorRight, layout, Qt::AnchorRight, 0.1);
+ layout->setAnchor(widget1, Qt::AnchorBottom, layout, Qt::AnchorBottom, 0.1);
+
+ widget->setLayout(layout);
+
+ widget->setGeometry(QRectF(0,0,100,100));
+ QCOMPARE(layout->isValid(), true);
+ delete widget;
+ }
+
+ // Overconstrained one widget, invalid
+ // ### Our understanding is that this case is valid. What happens though,
+ // is that the layout minimum and maximum vertical size hints become
+ // the same, 10.1. That means its height is fixed.
+ // What will "fail" then is the "setGeometry(0, 0, 100, 100)" call,
+ // after which the layout geometry will be (0, 0, 100, 10.1).
+
+ {
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ TheAnchorLayout *layout = new TheAnchorLayout();
+
+ TestWidget *widget1 = new TestWidget();
+
+ layout->setAnchor(layout, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 0.1);
+ layout->setAnchor(layout, Qt::AnchorTop, widget1, Qt::AnchorTop, 0.1);
+ layout->setAnchor(widget1, Qt::AnchorRight, layout, Qt::AnchorRight, 0.1);
+ layout->setAnchor(widget1, Qt::AnchorBottom, layout, Qt::AnchorBottom, 0.1);
+
+ layout->setAnchor(widget1, Qt::AnchorTop, layout, Qt::AnchorBottom, 10);
+
+ widget->setLayout(layout);
+
+ widget->setGeometry(QRectF(0,0,100,100));
+ QCOMPARE(layout->isValid(), true);
+ delete widget;
+ }
+
+ // Underconstrained two widgets, valid
+ {
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ TheAnchorLayout *layout = new TheAnchorLayout();
+
+ TestWidget *widget1 = new TestWidget();
+ TestWidget *widget2 = new TestWidget();
+
+ // Vertically the layout has floating items. Therefore, we have a conflict
+ layout->setAnchor(layout, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 0.1);
+ layout->setAnchor(layout, Qt::AnchorRight, widget1, Qt::AnchorRight, -0.1);
+
+ // Horizontally the layout has floating items. Therefore, we have a conflict
+ layout->setAnchor(layout, Qt::AnchorTop, widget2, Qt::AnchorTop, 0.1);
+ layout->setAnchor(layout, Qt::AnchorBottom, widget2, Qt::AnchorBottom, -0.1);
+
+ widget->setLayout(layout);
+
+ widget->setGeometry(QRectF(0,0,100,100));
+ QCOMPARE(layout->isValid(), false);
+ delete widget;
+ }
+}
+
+void tst_QGraphicsAnchorLayout1::testSpecialCases()
+{
+ // One widget, setLayout before defining layouts
+ {
+#ifdef QT_DEBUG
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsLayout::addChildLayoutItem: QGraphicsWidget \"\""
+ " in wrong parent; moved to correct parent");
+#endif
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ TheAnchorLayout *layout = new TheAnchorLayout();
+ widget->setLayout(layout);
+
+ TestWidget *widget1 = new TestWidget();
+
+ layout->setAnchor(layout, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 1);
+ layout->setAnchor(layout, Qt::AnchorTop, widget1, Qt::AnchorTop, 1);
+ layout->setAnchor(widget1, Qt::AnchorRight, layout, Qt::AnchorRight, 1);
+ layout->setAnchor(widget1, Qt::AnchorBottom, layout, Qt::AnchorBottom, 1);
+ widget->setGeometry(QRectF(0,0,100,100));
+ QCOMPARE(widget1->geometry(), QRectF(1,1,98,98));
+ delete widget1;
+ delete widget;
+ }
+
+ // One widget, layout inside layout, layout inside layout inside layout
+ {
+#ifdef QT_DEBUG
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsLayout::addChildLayoutItem: QGraphicsWidget \"\""
+ " in wrong parent; moved to correct parent");
+#endif
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ TheAnchorLayout *layout = new TheAnchorLayout();
+ widget->setLayout(layout);
+
+ TheAnchorLayout *layout1 = new TheAnchorLayout();
+ TestWidget *widget1 = new TestWidget();
+ layout1->setAnchor(layout1, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 1);
+ layout1->setAnchor(layout1, Qt::AnchorTop, widget1, Qt::AnchorTop, 1);
+ layout1->setAnchor(widget1, Qt::AnchorRight, layout1, Qt::AnchorRight, 1);
+ layout1->setAnchor(widget1, Qt::AnchorBottom, layout1, Qt::AnchorBottom, 1);
+
+ TheAnchorLayout *layout2 = new TheAnchorLayout();
+ TestWidget *widget2 = new TestWidget();
+ layout2->setAnchor(layout2, Qt::AnchorLeft, widget2, Qt::AnchorLeft, 1);
+ layout2->setAnchor(layout2, Qt::AnchorTop, widget2, Qt::AnchorTop, 1);
+ layout2->setAnchor(widget2, Qt::AnchorRight, layout2, Qt::AnchorRight, 1);
+ layout2->setAnchor(widget2, Qt::AnchorBottom, layout2, Qt::AnchorBottom, 1);
+
+ layout1->setAnchor(layout1, Qt::AnchorLeft, layout2, Qt::AnchorLeft, 1);
+ layout1->setAnchor(layout1, Qt::AnchorTop, layout2, Qt::AnchorTop, 1);
+ layout1->setAnchor(layout2, Qt::AnchorRight, layout1, Qt::AnchorRight, 1);
+ layout1->setAnchor(layout2, Qt::AnchorBottom, layout1, Qt::AnchorBottom, 1);
+
+ layout->setAnchor(layout, Qt::AnchorLeft, layout1, Qt::AnchorLeft, 1);
+ layout->setAnchor(layout, Qt::AnchorTop, layout1, Qt::AnchorTop, 1);
+ layout->setAnchor(layout1, Qt::AnchorRight, layout, Qt::AnchorRight, 1);
+ layout->setAnchor(layout1, Qt::AnchorBottom, layout, Qt::AnchorBottom, 1);
+
+ // remove and add again to improve test coverage.
+ layout->removeItem(layout1);
+
+ layout->setAnchor(layout, Qt::AnchorLeft, layout1, Qt::AnchorLeft, 1);
+ layout->setAnchor(layout, Qt::AnchorTop, layout1, Qt::AnchorTop, 1);
+ layout->setAnchor(layout1, Qt::AnchorRight, layout, Qt::AnchorRight, 1);
+ layout->setAnchor(layout1, Qt::AnchorBottom, layout, Qt::AnchorBottom, 1);
+
+ widget->setGeometry(QRectF(0,0,100,100));
+ QCOMPARE(widget1->geometry(), QRectF(2,2,96,96));
+ QCOMPARE(widget2->geometry(), QRectF(3,3,94,94));
+ delete widget;
+ }
+
+ // One widget, layout inside layout, setLayout after layout definition
+ {
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ TheAnchorLayout *layout = new TheAnchorLayout();
+
+ TheAnchorLayout *layout1 = new TheAnchorLayout();
+
+ TestWidget *widget1 = new TestWidget();
+ layout1->setAnchor(layout1, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 1);
+ layout1->setAnchor(layout1, Qt::AnchorTop, widget1, Qt::AnchorTop, 1);
+ layout1->setAnchor(widget1, Qt::AnchorRight, layout1, Qt::AnchorRight, 1);
+ layout1->setAnchor(widget1, Qt::AnchorBottom, layout1, Qt::AnchorBottom, 1);
+
+ layout->setAnchor(layout, Qt::AnchorLeft, layout1, Qt::AnchorLeft, 1);
+ layout->setAnchor(layout, Qt::AnchorTop, layout1, Qt::AnchorTop, 1);
+ layout->setAnchor(layout1, Qt::AnchorRight, layout, Qt::AnchorRight, 1);
+ layout->setAnchor(layout1, Qt::AnchorBottom, layout, Qt::AnchorBottom, 1);
+
+ widget->setLayout(layout);
+ widget->setGeometry(QRectF(0,0,100,100));
+ QCOMPARE(widget1->geometry(), QRectF(2,2,96,96));
+ delete widget;
+ }
+
+ // One widget, layout inside layout, setLayout after layout definition, widget transferred from
+ // one layout to another
+ {
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ TheAnchorLayout *layout = new TheAnchorLayout();
+ widget->setLayout(layout);
+
+ TheAnchorLayout *layout1 = new TheAnchorLayout();
+ TestWidget *widget1 = new TestWidget();
+
+ // Additional layout + widget to improve coverage.
+ TheAnchorLayout *layout0 = new TheAnchorLayout();
+ TestWidget *widget0 = new TestWidget();
+
+ // widget0 to layout0
+ layout0->setAnchor(layout0, Qt::AnchorLeft, widget0, Qt::AnchorLeft, 1);
+ layout0->setAnchor(layout0, Qt::AnchorTop, widget0, Qt::AnchorTop, 1);
+ layout0->setAnchor(widget0, Qt::AnchorRight, layout0, Qt::AnchorRight, 1);
+ layout0->setAnchor(widget0, Qt::AnchorBottom, layout0, Qt::AnchorBottom, 1);
+
+ // layout0 to layout
+ layout->setAnchor(layout, Qt::AnchorLeft, layout0, Qt::AnchorLeft, 1);
+ layout->setAnchor(layout, Qt::AnchorTop, layout0, Qt::AnchorTop, 1);
+ layout->setAnchor(layout0, Qt::AnchorRight, layout, Qt::AnchorRight, 50);
+ layout->setAnchor(layout0, Qt::AnchorBottom, layout, Qt::AnchorBottom, 1);
+
+ // widget1 to layout1
+ layout1->setAnchor(layout1, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 1);
+ layout1->setAnchor(layout1, Qt::AnchorTop, widget1, Qt::AnchorTop, 1);
+ layout1->setAnchor(widget1, Qt::AnchorRight, layout1, Qt::AnchorRight, 1);
+ layout1->setAnchor(widget1, Qt::AnchorBottom, layout1, Qt::AnchorBottom, 1);
+
+ // layout1 to layout
+ layout->setAnchor(layout, Qt::AnchorLeft, layout1, Qt::AnchorLeft, 1);
+ layout->setAnchor(layout, Qt::AnchorTop, layout1, Qt::AnchorTop, 1);
+ layout->setAnchor(layout1, Qt::AnchorRight, layout, Qt::AnchorRight, 50);
+ layout->setAnchor(layout1, Qt::AnchorBottom, layout, Qt::AnchorBottom, 1);
+
+ TheAnchorLayout *layout2 = new TheAnchorLayout();
+
+ // layout2 to layout
+ layout->setAnchor(layout, Qt::AnchorLeft, layout2, Qt::AnchorLeft, 50);
+ layout->setAnchor(layout, Qt::AnchorTop, layout2, Qt::AnchorTop, 1);
+ layout->setAnchor(layout2, Qt::AnchorRight, layout, Qt::AnchorRight, 1);
+ layout->setAnchor(layout2, Qt::AnchorBottom, layout, Qt::AnchorBottom, 1);
+
+ // transfer widget1 to layout2
+ layout2->setAnchor(layout2, Qt::AnchorLeft, widget1, Qt::AnchorLeft, 1);
+ layout2->setAnchor(layout2, Qt::AnchorTop, widget1, Qt::AnchorTop, 1);
+ layout2->setAnchor(widget1, Qt::AnchorRight, layout2, Qt::AnchorRight, 1);
+ layout2->setAnchor(widget1, Qt::AnchorBottom, layout2, Qt::AnchorBottom, 1);
+
+ widget->setGeometry(QRectF(0,0,100,100));
+ QCOMPARE(widget1->geometry(), QRectF(51,2,47,96));
+ delete widget;
+ }
+
+ // One widget, set first to one layout then to another. Child reparented.
+ // In addition widget as a direct child of another widget. Child reparented.
+ {
+ QGraphicsWidget *widget1 = new QGraphicsWidget;
+ TheAnchorLayout *layout1 = new TheAnchorLayout();
+ widget1->setLayout(layout1);
+
+ TestWidget *childWidget = new TestWidget();
+
+ // childWidget to layout1
+ layout1->setAnchor(layout1, Qt::AnchorLeft, childWidget, Qt::AnchorLeft, 1);
+ layout1->setAnchor(layout1, Qt::AnchorTop, childWidget, Qt::AnchorTop, 1);
+ layout1->setAnchor(childWidget, Qt::AnchorRight, layout1, Qt::AnchorRight, 1);
+ layout1->setAnchor(childWidget, Qt::AnchorBottom, layout1, Qt::AnchorBottom, 1);
+
+ widget1->setGeometry(QRectF(0,0,100,100));
+ QCOMPARE(childWidget->geometry(), QRectF(1,1,98,98));
+ QVERIFY(childWidget->parentLayoutItem() == layout1);
+ QGraphicsWidget *widget2 = new QGraphicsWidget;
+ TheAnchorLayout *layout2 = new TheAnchorLayout();
+ widget2->setLayout(layout2);
+
+ // childWidget to layout2
+ layout2->setAnchor(layout2, Qt::AnchorLeft, childWidget, Qt::AnchorLeft, 1);
+ layout2->setAnchor(layout2, Qt::AnchorTop, childWidget, Qt::AnchorTop, 1);
+ layout2->setAnchor(childWidget, Qt::AnchorRight, layout2, Qt::AnchorRight, 1);
+ layout2->setAnchor(childWidget, Qt::AnchorBottom, layout2, Qt::AnchorBottom, 1);
+
+ QGraphicsWidget *widget3 = new QGraphicsWidget;
+ QGraphicsWidget *widget4 = new QGraphicsWidget;
+ // widget4 is a direct child of widget3 (i.e. not in any layout)
+ widget4->setParentItem(widget3);
+
+ // widget4 to layout2
+ layout2->setAnchor(layout2, Qt::AnchorLeft, widget4, Qt::AnchorLeft, 1);
+ layout2->setAnchor(layout2, Qt::AnchorTop, widget4, Qt::AnchorTop, 1);
+ layout2->setAnchor(widget4, Qt::AnchorRight, layout2, Qt::AnchorRight, 1);
+ layout2->setAnchor(widget4, Qt::AnchorBottom, layout2, Qt::AnchorBottom, 1);
+
+ widget2->setGeometry(QRectF(0,0,100,100));
+ QCOMPARE(childWidget->geometry(), QRectF(1,1,98,98));
+ QVERIFY(childWidget->parentLayoutItem() == layout2);
+ QCOMPARE(widget4->geometry(), QRectF(1,1,98,98));
+ QVERIFY(widget4->parentLayoutItem() == layout2);
+ QVERIFY(widget4->parentItem() == widget2);
+
+ delete widget4;
+ delete widget3;
+ delete widget1;
+ delete childWidget;
+ delete widget2;
+ }
+}
+
+void tst_QGraphicsAnchorLayout1::testBasicLayout_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::addColumn<BasicLayoutTestDataList>("data");
+ QTest::addColumn<BasicLayoutTestResultList>("result");
+
+ typedef BasicLayoutTestData BasicData;
+ typedef BasicLayoutTestResult BasicResult;
+
+ // One widget, basic
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 20)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 30)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 40)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(20, 10, 150, 50) )
+ ;
+
+ QTest::newRow("One, simple") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // One widget, duplicates
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 20)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 30)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 40)
+
+ << BasicData(0, Qt::AnchorTop, -1, Qt::AnchorTop, 0)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 0)
+ << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorRight, 0)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 0)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(0, 0, 200, 100) )
+ ;
+
+ QTest::newRow("One, duplicates") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // One widget, mixed
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorBottom, 80)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorRight, 150)
+ << BasicData(0, Qt::AnchorLeft, -1, Qt::AnchorRight, 150)
+ << BasicData(0, Qt::AnchorTop, -1, Qt::AnchorBottom, 80)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(50, 20, 100, 60) )
+ ;
+
+ QTest::newRow("One, mixed") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets (same layout), different ordering
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+
+ << BasicData(1, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+ << BasicData(-1, Qt::AnchorLeft, 1, Qt::AnchorLeft, 10)
+ << BasicData(-1, Qt::AnchorTop, 1, Qt::AnchorTop, 10)
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(10, 10, 180, 80) )
+ << BasicResult(1, QRectF(10, 10, 180, 80) )
+ ;
+
+ QTest::newRow("Two, orderings") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets, duplicate anchors
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 30)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 20)
+
+ << BasicData(1, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+ << BasicData(-1, Qt::AnchorLeft, 1, Qt::AnchorLeft, 10)
+ << BasicData(-1, Qt::AnchorTop, 1, Qt::AnchorTop, 10)
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ << BasicData(1, Qt::AnchorTop, -1, Qt::AnchorTop, 0)
+ << BasicData(-1, Qt::AnchorRight, 1, Qt::AnchorRight, 0)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(30, 10, 160, 70) )
+ << BasicResult(1, QRectF(10, 0, 190, 90) )
+ ;
+
+ QTest::newRow("Two, duplicates") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets, mixed
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorBottom, 90)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorRight, 190)
+ << BasicData(0, Qt::AnchorLeft, -1, Qt::AnchorRight, 190)
+ << BasicData(0, Qt::AnchorTop, -1, Qt::AnchorBottom, 90)
+
+ << BasicData(1, Qt::AnchorTop, -1, Qt::AnchorBottom, 20)
+ << BasicData(1, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+ << BasicData(-1, Qt::AnchorLeft, 1, Qt::AnchorLeft, 10)
+ << BasicData(-1, Qt::AnchorLeft, 1, Qt::AnchorRight, 20)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(10, 10, 180, 80) )
+ << BasicResult(1, QRectF(10, 80, 10, 10) )
+ ;
+
+ QTest::newRow("Two, mixed") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets, 1 horizontal connection, first completely defined
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 180)
+
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorLeft, 10)
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ << BasicData(-1, Qt::AnchorTop, 1, Qt::AnchorTop, 10)
+ << BasicData(1, Qt::AnchorBottom, -1, Qt::AnchorBottom, 20)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(10, 10, 10, 80) )
+ << BasicResult(1, QRectF(30, 10, 160, 70) )
+ ;
+
+ QTest::newRow("Two, 1h connected") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets, 2 horizontal connections, first completely defined
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 180)
+
+ // ### QGAL is not sensible to the argument order in this case
+ // To achieve the desired result we must explicitly set a negative
+ // spacing.
+ // << BasicData(0, Qt::AnchorLeft, 1, Qt::AnchorRight, 100)
+ << BasicData(0, Qt::AnchorLeft, 1, Qt::AnchorRight, -100)
+
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorLeft, 30)
+ << BasicData(-1, Qt::AnchorTop, 1, Qt::AnchorTop, 10)
+ << BasicData(1, Qt::AnchorBottom, -1, Qt::AnchorBottom, 20)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(10, 10, 10, 80) )
+ << BasicResult(1, QRectF(50, 10, 60, 70) )
+ ;
+
+ QTest::newRow("Two, 2h connected") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets, 1 vertical connection, first completely defined
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 180)
+
+ << BasicData(-1, Qt::AnchorLeft, 1, Qt::AnchorLeft, 30)
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ << BasicData(0, Qt::AnchorTop, 1, Qt::AnchorTop, 10)
+ << BasicData(1, Qt::AnchorBottom, -1, Qt::AnchorBottom, 20)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(10, 10, 10, 80) )
+ << BasicResult(1, QRectF(30, 20, 160, 60) )
+ ;
+
+ QTest::newRow("Two, 1v connected") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets, 2 vertical connections, first completely defined
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 180)
+
+ << BasicData(-1, Qt::AnchorLeft, 1, Qt::AnchorLeft, 30)
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ << BasicData(0, Qt::AnchorTop, 1, Qt::AnchorTop, 10)
+ << BasicData(1, Qt::AnchorBottom, 0, Qt::AnchorBottom, 20)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(10, 10, 10, 80) )
+ << BasicResult(1, QRectF(30, 20, 160, 50) )
+ ;
+
+ QTest::newRow("Two, 2v connected") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets, 1 horizontal and 1 vertical connection, first completely defined
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 180)
+
+ << BasicData(-1, Qt::AnchorLeft, 1, Qt::AnchorLeft, 80)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorRight, 100)
+ << BasicData(-1, Qt::AnchorTop, 1, Qt::AnchorTop, 10)
+ << BasicData(1, Qt::AnchorBottom, 0, Qt::AnchorBottom, 10)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(10, 10, 10, 80) )
+ << BasicResult(1, QRectF(80, 10, 40, 70) )
+ ;
+
+ QTest::newRow("Two, 1h+1v connected") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets, 2 horizontal and 2 vertical connections, first completely defined
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 180)
+
+ << BasicData(0, Qt::AnchorLeft, 1, Qt::AnchorLeft, 80)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorRight, 100)
+ << BasicData(0, Qt::AnchorTop, 1, Qt::AnchorTop, 10)
+ << BasicData(1, Qt::AnchorBottom, 0, Qt::AnchorBottom, 10)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(10, 10, 10, 80) )
+ << BasicResult(1, QRectF(90, 20, 30, 60) )
+ ;
+
+ QTest::newRow("Two, 2h+2v connected") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets, 2 horizontal and 2 vertical connections, dependent on each other.
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorRight, 150)
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(0, Qt::AnchorBottom, 1, Qt::AnchorBottom, 10)
+
+ << BasicData(0, Qt::AnchorLeft, 1, Qt::AnchorLeft, 90)
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ << BasicData(0, Qt::AnchorTop, 1, Qt::AnchorTop, 10)
+ << BasicData(1, Qt::AnchorBottom, -1, Qt::AnchorBottom, 20)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(10, 10, 30, 60) )
+ << BasicResult(1, QRectF(100, 20, 90, 60) )
+ ;
+
+ QTest::newRow("Two, 2h+2v connected2") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets, connected, overlapping
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ // << BasicData(1, Qt::AnchorLeft, 0, Qt::AnchorRight, 30)
+ // ### QGAL has different semantics and assumes right edges are always
+ // to the left of left edges. Thus we need the minus sign here.
+ << BasicData(1, Qt::AnchorLeft, 0, Qt::AnchorRight, -30)
+ << BasicData(0, Qt::AnchorBottom, 1, Qt::AnchorBottom, 40)
+
+ << BasicData(-1, Qt::AnchorLeft, 1, Qt::AnchorLeft, 40)
+ << BasicData(-1, Qt::AnchorTop, 1, Qt::AnchorTop, 20)
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ << BasicData(1, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(10, 10, 60, 40) )
+ << BasicResult(1, QRectF(40, 20, 150, 70) )
+ ;
+
+ QTest::newRow("Two, connected overlapping") << QSizeF(200, 100) << theData << theResult;
+ }
+}
+
+void tst_QGraphicsAnchorLayout1::testNegativeSpacing_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::addColumn<BasicLayoutTestDataList>("data");
+ QTest::addColumn<BasicLayoutTestResultList>("result");
+
+ typedef BasicLayoutTestData BasicData;
+ typedef BasicLayoutTestResult BasicResult;
+
+ // One widget, negative spacing
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ /// ### QGAL assumes items are always inside the layout.
+ // In this case, the negative spacing would make the item
+ // grow beyond the layout edges, which is OK, but gives a
+ // different result.
+ // Changing the direction of anchors (-1 to 0 or vice-versa)
+ // has no effect in this case.
+
+ theData
+ // << BasicData(0, Qt::AnchorTop, -1, Qt::AnchorTop, -10)
+ // << BasicData(0, Qt::AnchorLeft, -1, Qt::AnchorLeft, -20)
+ // << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorRight, -30)
+ // << BasicData(-1, Qt::AnchorBottom, 0, Qt::AnchorBottom, -40)
+
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, -10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, -20)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, -30)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, -40)
+
+ ;
+
+ theResult
+ // << BasicResult(0, QRectF(20, 10, 150, 50) )
+ << BasicResult(0, QRectF(-20, -10, 250, 150) )
+ ;
+
+ QTest::newRow("One, simple (n)") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // One widget, duplicates, negative spacing
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(0, Qt::AnchorTop, -1, Qt::AnchorTop, -20)
+ << BasicData(0, Qt::AnchorLeft, -1, Qt::AnchorLeft, -20)
+ << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorRight, -30)
+ << BasicData(-1, Qt::AnchorBottom, 0, Qt::AnchorBottom, -40)
+
+ << BasicData(0, Qt::AnchorTop, -1, Qt::AnchorTop, -10)
+ << BasicData(0, Qt::AnchorLeft, -1, Qt::AnchorLeft, -10)
+ << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorRight, -10)
+ << BasicData(-1, Qt::AnchorBottom, 0, Qt::AnchorBottom, -10)
+ ;
+
+ theResult
+ // ### Same as above...
+ // << BasicResult(0, QRectF(10, 10, 180, 80) )
+ << BasicResult(0, QRectF(-10, -10, 220, 120) )
+ ;
+
+ QTest::newRow("One, duplicates (n)") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // One widget, mixed, negative spacing
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ // ### All anchors of negative spacing between the layout and an
+ // item are handled as to make sure the item is _outside_ the
+ // layout.
+ // To keep it inside, one _must_ use positive spacings.
+ // << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorTop, -80)
+ // << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorLeft, -150)
+ // << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorLeft, -150)
+ // << BasicData(-1, Qt::AnchorBottom, 0, Qt::AnchorTop, -80)
+
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorTop, 80)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorLeft, 150)
+ << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorLeft, 150)
+ << BasicData(-1, Qt::AnchorBottom, 0, Qt::AnchorTop, 80)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(50, 20, 100, 60) )
+ ;
+
+ QTest::newRow("One, mixed (n)") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets, 1 horizontal connection, first completely defined, negative spacing
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ // << BasicData(0, Qt::AnchorTop, -1, Qt::AnchorTop, -10)
+ // << BasicData(-1, Qt::AnchorBottom, 0, Qt::AnchorBottom, -10)
+ // << BasicData(0, Qt::AnchorLeft, -1, Qt::AnchorLeft, -10)
+ // << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorRight, -180)
+
+ // << BasicData(1, Qt::AnchorLeft, 0, Qt::AnchorRight, -10)
+ // << BasicData(-1, Qt::AnchorRight, 1, Qt::AnchorRight, -10)
+ // << BasicData(1, Qt::AnchorTop, -1, Qt::AnchorTop, -10)
+ // << BasicData(-1, Qt::AnchorBottom, 1, Qt::AnchorBottom, -20)
+
+ << BasicData(0, Qt::AnchorTop, -1, Qt::AnchorTop, -10)
+ << BasicData(-1, Qt::AnchorBottom, 0, Qt::AnchorBottom, -10)
+ << BasicData(0, Qt::AnchorLeft, -1, Qt::AnchorLeft, -10)
+ << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorRight, 180)
+
+ << BasicData(1, Qt::AnchorLeft, 0, Qt::AnchorRight, -10)
+ << BasicData(-1, Qt::AnchorRight, 1, Qt::AnchorRight, -10)
+ << BasicData(1, Qt::AnchorTop, -1, Qt::AnchorTop, -10)
+ << BasicData(-1, Qt::AnchorBottom, 1, Qt::AnchorBottom, -20)
+
+ ;
+
+ theResult
+ // << BasicResult(0, QRectF(10, 10, 10, 80) )
+ // << BasicResult(1, QRectF(30, 10, 160, 70) )
+
+ << BasicResult(0, QRectF(-10, -10, 30, 120) )
+ << BasicResult(1, QRectF(10, -10, 200, 130) )
+ ;
+
+ QTest::newRow("Two, 1h connected (n)") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Basic case - two widgets, 2 horizontal and 2 vertical connections, dependent on each other, negative spacing
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(0, Qt::AnchorLeft, -1, Qt::AnchorLeft, -10)
+ << BasicData(1, Qt::AnchorRight, 0, Qt::AnchorRight, -150)
+ << BasicData(0, Qt::AnchorTop, -1, Qt::AnchorTop, -10)
+ << BasicData(1, Qt::AnchorBottom, 0, Qt::AnchorBottom, -10)
+
+ << BasicData(1, Qt::AnchorLeft, 0, Qt::AnchorLeft, -90)
+ << BasicData(-1, Qt::AnchorRight, 1, Qt::AnchorRight, -10)
+ << BasicData(1, Qt::AnchorTop, 0, Qt::AnchorTop, -10)
+ << BasicData(-1, Qt::AnchorBottom, 1, Qt::AnchorBottom, -20)
+ ;
+
+ theResult
+ // << BasicResult(0, QRectF(10, 10, 30, 60) )
+ // << BasicResult(1, QRectF(100, 20, 90, 60) )
+ << BasicResult(0, QRectF(-10, -10, 70, 120) )
+ << BasicResult(1, QRectF(80, 0, 130, 120) )
+ ;
+
+ QTest::newRow("Two, 2h+2v connected2 (n)") << QSizeF(200, 100) << theData << theResult;
+ }
+}
+
+void tst_QGraphicsAnchorLayout1::testMixedSpacing_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::addColumn<BasicLayoutTestDataList>("data");
+ QTest::addColumn<BasicLayoutTestResultList>("result");
+
+ typedef BasicLayoutTestData BasicData;
+ typedef BasicLayoutTestResult BasicResult;
+
+ // Two widgets, partial overlapping
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(0, Qt::AnchorLeft, -1, Qt::AnchorLeft, -50)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 50)
+ << BasicData(1, Qt::AnchorRight, 0, Qt::AnchorRight, 15)
+
+ // << BasicData(1, Qt::AnchorTop, 0, Qt::AnchorBottom, 5)
+ << BasicData(1, Qt::AnchorTop, 0, Qt::AnchorBottom, -5)
+ << BasicData(0, Qt::AnchorLeft, 1, Qt::AnchorLeft, -10)
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 20)
+ << BasicData(-1, Qt::AnchorBottom, 1, Qt::AnchorBottom, -5)
+ ;
+
+ theResult
+ // << BasicResult(0, QRectF(50, 10, 45, 40) )
+ // << BasicResult(1, QRectF(40, 45, 40, 50) )
+ << BasicResult(0, QRectF(-50, 10, 145, 40) )
+ << BasicResult(1, QRectF(-60, 45, 140, 60) )
+ ;
+
+ QTest::newRow("Two, partial overlap") << QSizeF(100, 100) << theData << theResult;
+ }
+
+ // Two widgets, complete overlapping
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 5)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorRight, 0)
+ << BasicData(0, Qt::AnchorTop, 1, Qt::AnchorTop, 0)
+ << BasicData(1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 25)
+
+ << BasicData(1, Qt::AnchorBottom, 0, Qt::AnchorBottom, 0)
+ << BasicData(1, Qt::AnchorBottom, -1, Qt::AnchorBottom, 5)
+ << BasicData(1, Qt::AnchorLeft, -1, Qt::AnchorRight, 50)
+ << BasicData(-1, Qt::AnchorRight, 1, Qt::AnchorRight, -10)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(65, 5, 35, 35) )
+ << BasicResult(1, QRectF(40, 5, 60, 35) )
+ ;
+
+ QTest::newRow("Two, complete overlap") << QSizeF(90, 45) << theData << theResult;
+ }
+
+ // Five widgets, v shaped, edges shared
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ // edges shared
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorLeft, 0)
+ << BasicData(1, Qt::AnchorRight, 2, Qt::AnchorLeft, 0)
+ << BasicData(2, Qt::AnchorRight, 3, Qt::AnchorLeft, 0)
+ << BasicData(3, Qt::AnchorRight, 4, Qt::AnchorLeft, 0)
+ << BasicData(1, Qt::AnchorBottom, 2, Qt::AnchorTop, 0)
+ << BasicData(0, Qt::AnchorBottom, 1, Qt::AnchorTop, 0)
+ << BasicData(3, Qt::AnchorBottom, 2, Qt::AnchorTop, 0)
+ << BasicData(4, Qt::AnchorBottom, 3, Qt::AnchorTop, 0)
+ << BasicData(0, Qt::AnchorBottom, 4, Qt::AnchorBottom, 0)
+ << BasicData(1, Qt::AnchorBottom, 3, Qt::AnchorBottom, 0)
+ << BasicData(0, Qt::AnchorTop, 4, Qt::AnchorTop, 0)
+ << BasicData(1, Qt::AnchorTop, 3, Qt::AnchorTop, 0)
+
+ // margins
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 5)
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 5)
+ << BasicData(2, Qt::AnchorBottom, -1, Qt::AnchorBottom, 5)
+ // << BasicData(-1, Qt::AnchorRight, 4, Qt::AnchorRight, -5)
+ << BasicData(-1, Qt::AnchorRight, 4, Qt::AnchorRight, 5)
+
+ // additional details for exact size determination easily
+ << BasicData(-1, Qt::AnchorLeft, 1, Qt::AnchorLeft, 25)
+ << BasicData(-1, Qt::AnchorLeft, 1, Qt::AnchorRight, 50)
+ // << BasicData(-1, Qt::AnchorRight, 3, Qt::AnchorRight, -25)
+ // << BasicData(-1, Qt::AnchorRight, 2, Qt::AnchorRight, -50)
+ << BasicData(-1, Qt::AnchorRight, 3, Qt::AnchorRight, 25)
+ << BasicData(-1, Qt::AnchorRight, 2, Qt::AnchorRight, 50)
+ << BasicData(-1, Qt::AnchorTop, 3, Qt::AnchorBottom, 50)
+ // << BasicData(-1, Qt::AnchorBottom, 3, Qt::AnchorTop, -50)
+ << BasicData(-1, Qt::AnchorBottom, 3, Qt::AnchorTop, 50)
+
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(5,5,20,20))
+ << BasicResult(1, QRectF(25,25,25,25))
+ << BasicResult(2, QRectF(50,50,25,20))
+ << BasicResult(3, QRectF(75,25,25,25))
+ << BasicResult(4, QRectF(100,5,20,20))
+ ;
+
+ QTest::newRow("Five, V shape") << QSizeF(125, 75) << theData << theResult;
+ }
+
+ // ### The behavior is different in QGraphicsAnchorLayout. What happens here is
+ // that when the above anchors are set, the layout size hints are changed.
+ // In the example, the minimum item width is 5, thus the minimum layout width
+ // becomes 105 (50 + 5 + 50). Once that size hint is set, trying to set
+ // the widget size to (10, 10) is not possible because
+ // QGraphicsWidget::setGeometry() will enforce the minimum is respected.
+ if (0)
+ // One widget, unsolvable
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 50)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 50)
+ ;
+ theResult
+ << BasicResult(0, QRectF(0,0,0,0))
+ ;
+
+ QTest::newRow("One widget, unsolvable") << QSizeF(10, 10) << theData << theResult;
+ }
+
+ // Two widgets, one has fixed size
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 50)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 50)
+ // not supported, use sizePolicy instead
+ // << BasicData(0, Qt::AnchorLeft, 0, Qt::AnchorRight, 50)
+
+ << BasicData(-1, Qt::AnchorLeft, 1, Qt::AnchorLeft, 50)
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 50)
+ ;
+ theResult
+ << BasicResult(0, QRectF(50,0,50,50))
+ << BasicResult(1, QRectF(50,0,50,50))
+ ;
+
+ QTest::newRow("Two widgets, one has fixed size") << QSizeF(150, 150) << theData << theResult;
+ }
+}
+
+void tst_QGraphicsAnchorLayout1::testMulti_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::addColumn<BasicLayoutTestDataList>("data");
+ QTest::addColumn<BasicLayoutTestResultList>("result");
+
+ typedef BasicLayoutTestData BasicData;
+ typedef BasicLayoutTestResult BasicResult;
+
+ // Multiple widgets, all overllapping
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ const int n = 30;
+ for ( int i = 0 ; i < n; i++ ) {
+ theData
+ << BasicData(-1, Qt::AnchorTop, i, Qt::AnchorTop, 20)
+ << BasicData(-1, Qt::AnchorLeft, i, Qt::AnchorLeft, 10)
+ // << BasicData(-1, Qt::AnchorBottom, i, Qt::AnchorBottom, -40)
+ // << BasicData(-1, Qt::AnchorRight, i, Qt::AnchorRight, -30);
+ << BasicData(-1, Qt::AnchorBottom, i, Qt::AnchorBottom, 40)
+ << BasicData(-1, Qt::AnchorRight, i, Qt::AnchorRight, 30);
+
+ theResult
+ << BasicResult(i, QRectF(10, 20, 160, 40) );
+ }
+
+
+ QTest::newRow("Overlapping multi") << QSizeF(200, 100) << theData << theResult;
+ }
+
+ // Multiple widgets, linear order
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ const qreal height = 1000.f;
+ const qreal width = 2000.f;
+
+ const int n = 30;
+
+ const qreal verticalStep = height/qreal(n+2);
+ const qreal horizontalStep = width/qreal(n+2);
+
+ for ( int i = 0 ; i < n; i++ ) {
+
+ if ( i == 0 ) {
+ // First item
+ theData
+ << BasicData(-1, Qt::AnchorTop, i, Qt::AnchorTop, verticalStep)
+ << BasicData(-1, Qt::AnchorLeft, i, Qt::AnchorLeft, horizontalStep)
+ << BasicData(i+1, Qt::AnchorBottom, i, Qt::AnchorBottom, -verticalStep)
+ << BasicData(i+1, Qt::AnchorRight, i, Qt::AnchorRight, -horizontalStep);
+
+ } else if ( i == n-1 ) {
+ // Last item
+ theData
+ << BasicData(i-1, Qt::AnchorTop, i, Qt::AnchorTop, verticalStep)
+ << BasicData(i-1, Qt::AnchorLeft, i, Qt::AnchorLeft, horizontalStep)
+ << BasicData(-1, Qt::AnchorBottom, i, Qt::AnchorBottom, verticalStep)
+ << BasicData(-1, Qt::AnchorRight, i, Qt::AnchorRight, horizontalStep);
+ // << BasicData(-1, Qt::AnchorBottom, i, Qt::AnchorBottom, -verticalStep)
+ // << BasicData(-1, Qt::AnchorRight, i, Qt::AnchorRight, -horizontalStep);
+
+ } else {
+ // items in the middle
+ theData
+ << BasicData(i-1, Qt::AnchorTop, i, Qt::AnchorTop, verticalStep)
+ << BasicData(i-1, Qt::AnchorLeft, i, Qt::AnchorLeft, horizontalStep)
+ << BasicData(i+1, Qt::AnchorBottom, i, Qt::AnchorBottom, -verticalStep)
+ << BasicData(i+1, Qt::AnchorRight, i, Qt::AnchorRight, -horizontalStep);
+ // << BasicData(i+1, Qt::AnchorBottom, i, Qt::AnchorBottom, -verticalStep)
+ // << BasicData(i+1, Qt::AnchorRight, i, Qt::AnchorRight, -horizontalStep);
+
+ }
+
+ theResult
+ << BasicResult(i, QRectF((i+1)*horizontalStep, (i+1)*verticalStep, horizontalStep, verticalStep) );
+ }
+
+
+ if (sizeof(qreal) == 4) {
+ qDebug("Linear multi: Skipping! (qreal has too little precision, result will be wrong)");
+ } else {
+ QTest::newRow("Linear multi") << QSizeF(width, height) << theData << theResult;
+ }
+ }
+
+ // Multiple widgets, V shape
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ const qreal height = 100.f;
+ const qreal width = 200.f;
+
+ const int n = 31; // odd number please (3,5,7... )
+
+ const qreal verticalStep = height/(2.f+(n+1)/2.f);
+ const qreal horizontalStep = width/(n+2.f);
+
+ for ( int i = 0 ; i < n; i++ ) {
+
+ if ( i == 0 ) {
+ // First item
+ theData
+ << BasicData(-1, Qt::AnchorTop, i, Qt::AnchorTop, verticalStep)
+ << BasicData(-1, Qt::AnchorLeft, i, Qt::AnchorLeft, horizontalStep)
+ << BasicData(i+1, Qt::AnchorBottom, i, Qt::AnchorBottom, -verticalStep)
+ << BasicData(i, Qt::AnchorRight, i+1, Qt::AnchorRight, horizontalStep);
+
+ } else if ( i == n-1 ) {
+ // Last item
+ theData
+ << BasicData(i-1, Qt::AnchorTop, i, Qt::AnchorTop, -verticalStep)
+ << BasicData(i-1, Qt::AnchorLeft, i, Qt::AnchorLeft, horizontalStep)
+ << BasicData(i-1, Qt::AnchorBottom, i, Qt::AnchorBottom, -verticalStep)
+ << BasicData(i, Qt::AnchorRight, -1, Qt::AnchorRight, horizontalStep);
+ } else if ( i == ((n-1)/2) ) {
+ // midway
+ theData
+ << BasicData(i-1, Qt::AnchorTop, i, Qt::AnchorTop, verticalStep)
+ << BasicData(i-1, Qt::AnchorLeft, i, Qt::AnchorLeft, horizontalStep)
+ // << BasicData(-1, Qt::AnchorBottom, i, Qt::AnchorBottom, -verticalStep)
+ << BasicData(-1, Qt::AnchorBottom, i, Qt::AnchorBottom, verticalStep)
+ << BasicData(i, Qt::AnchorRight, i+1, Qt::AnchorRight, horizontalStep);
+ } else if ( i < ((n-1)/2) ) {
+ // before midway - going down
+ theData
+ << BasicData(i-1, Qt::AnchorTop, i, Qt::AnchorTop, verticalStep)
+ << BasicData(i-1, Qt::AnchorLeft, i, Qt::AnchorLeft, horizontalStep)
+ << BasicData(i+1, Qt::AnchorBottom, i, Qt::AnchorBottom, -verticalStep)
+ << BasicData(i, Qt::AnchorRight, i+1, Qt::AnchorRight, horizontalStep);
+
+ } else {
+ // after midway - going up
+ theData
+ << BasicData(i-1, Qt::AnchorTop, i, Qt::AnchorTop, -verticalStep)
+ << BasicData(i-1, Qt::AnchorLeft, i, Qt::AnchorLeft, horizontalStep)
+ << BasicData(i-1, Qt::AnchorBottom, i, Qt::AnchorBottom, -verticalStep)
+ << BasicData(i, Qt::AnchorRight, i+1, Qt::AnchorRight, horizontalStep);
+
+ }
+
+ if ( i <= ((n-1)/2) ) {
+ // until midway
+ theResult
+ << BasicResult(i, QRectF((i+1)*horizontalStep, (i+1)*verticalStep, horizontalStep, verticalStep) );
+ } else {
+ // after midway
+ theResult
+ << BasicResult(i, QRectF((i+1)*horizontalStep, (n-i)*verticalStep, horizontalStep, verticalStep) );
+ }
+
+ }
+ if (sizeof(qreal) == 4) {
+ qDebug("V multi: Skipping! (qreal has too little precision, result will be wrong)");
+ } else {
+ QTest::newRow("V multi") << QSizeF(width, height) << theData << theResult;
+ }
+ }
+
+ // Multiple widgets, grid
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ const qreal height = 100.f;
+ const qreal width = 200.f;
+
+ const int d = 10; // items per dimension
+ const int n = d*d;
+
+ const qreal verticalStep = height/(d+2.f);
+ const qreal horizontalStep = width/(d+2.f);
+
+ for ( int i = 0 ; i < n; i++ ) {
+ if ( i%d == 0 ) {
+ // left side item
+ theData
+ << BasicData(-1, Qt::AnchorLeft, i, Qt::AnchorLeft, horizontalStep)
+ << BasicData(i+1, Qt::AnchorRight, i, Qt::AnchorRight, -horizontalStep);
+ } else if ( (i+1)%d == 0 ) {
+ // rigth side item
+ theData
+ << BasicData(i-1, Qt::AnchorLeft, i, Qt::AnchorLeft, horizontalStep)
+ // << BasicData(-1, Qt::AnchorRight, i, Qt::AnchorRight, -horizontalStep);
+ << BasicData(-1, Qt::AnchorRight, i, Qt::AnchorRight, horizontalStep);
+ } else {
+ // horizontal middle
+ theData
+ << BasicData(i-1, Qt::AnchorLeft, i, Qt::AnchorLeft, horizontalStep)
+ << BasicData(i+1, Qt::AnchorRight, i, Qt::AnchorRight, -horizontalStep);
+ }
+
+ if ( i < d ) {
+ // top line
+ theData
+ << BasicData(-1, Qt::AnchorTop, i, Qt::AnchorTop, verticalStep)
+ << BasicData(i+d, Qt::AnchorBottom, i, Qt::AnchorBottom, -verticalStep);
+ } else if ( i >= (d-1)*d ){
+ // bottom line
+ theData
+ << BasicData(i-d, Qt::AnchorTop, i, Qt::AnchorTop, verticalStep)
+ // << BasicData(-1, Qt::AnchorBottom, i, Qt::AnchorBottom, -verticalStep)
+ << BasicData(-1, Qt::AnchorBottom, i, Qt::AnchorBottom, verticalStep);
+ } else {
+ // vertical middle
+ theData
+ << BasicData(i-d, Qt::AnchorTop, i, Qt::AnchorTop, verticalStep)
+ << BasicData(i+d, Qt::AnchorBottom, i, Qt::AnchorBottom, -verticalStep);
+ }
+
+ theResult
+ << BasicResult(i, QRectF(((i%d)+1)*horizontalStep, ((i/d)+1)*verticalStep, horizontalStep, verticalStep) );
+ }
+
+ if (sizeof(qreal) == 4) {
+ qDebug("Grid multi: Skipping! (qreal has too little precision, result will be wrong)");
+ } else {
+ QTest::newRow("Grid multi") << QSizeF(200, 100) << theData << theResult;
+ }
+ }
+}
+
+inline QGraphicsLayoutItem *getItem(
+ int index,
+ const QList<QGraphicsWidget *>& widgets,
+ QGraphicsLayoutItem *defaultItem)
+{
+ if (index < 0) {
+ return defaultItem;
+ }
+
+ return widgets[index];
+}
+
+static bool fuzzierCompare(qreal a, qreal b)
+{
+ return qAbs(a - b) <= qreal(0.0001);
+}
+
+static bool fuzzierCompare(const QRectF &r1, const QRectF &r2)
+{
+
+ return fuzzierCompare(r1.x(), r2.x()) && fuzzierCompare(r1.y(), r2.y())
+ && fuzzierCompare(r1.width(), r2.width()) && fuzzierCompare(r1.height(), r2.height());
+}
+
+void tst_QGraphicsAnchorLayout1::testBasicLayout()
+{
+ QFETCH(QSizeF, size);
+ QFETCH(BasicLayoutTestDataList, data);
+ QFETCH(BasicLayoutTestResultList, result);
+
+ QGraphicsWidget *widget = new QGraphicsWidget;
+
+ // Determine amount of widgets to add.
+ int widgetCount = -1;
+ for (int i = 0; i < data.count(); ++i) {
+ const BasicLayoutTestData item = data[i];
+ widgetCount = qMax(widgetCount, item.firstIndex);
+ widgetCount = qMax(widgetCount, item.secondIndex);
+ }
+ ++widgetCount; // widgetCount is max of indices.
+
+ // Create dummy widgets
+ QList<QGraphicsWidget *> widgets;
+ for (int i = 0; i < widgetCount; ++i) {
+ TestWidget *w = new TestWidget(0, QString::fromAscii("W%1").arg(i));
+ widgets << w;
+ }
+
+ // Setup anchor layout
+ TheAnchorLayout *layout = new TheAnchorLayout;
+
+ for (int i = 0; i < data.count(); ++i) {
+ const BasicLayoutTestData item = data[i];
+ layout->setAnchor(
+ getItem(item.firstIndex, widgets, layout),
+ item.firstEdge,
+ getItem(item.secondIndex, widgets, layout),
+ item.secondEdge,
+ item.spacing );
+ }
+
+ widget->setLayout(layout);
+ widget->setContentsMargins(0,0,0,0);
+
+ widget->resize(size);
+ QCOMPARE(widget->size(), size);
+
+ // Validate
+ for (int i = 0; i < result.count(); ++i) {
+ const BasicLayoutTestResult item = result[i];
+ QRectF expected = item.rect;
+ QRectF actual = widgets[item.index]->geometry();
+
+ QVERIFY(fuzzierCompare(actual, expected));
+ }
+
+ // Test mirrored mode
+ widget->setLayoutDirection(Qt::RightToLeft);
+ layout->activate();
+ // Validate
+ for (int j = 0; j < result.count(); ++j) {
+ const BasicLayoutTestResult item = result[j];
+ QRectF mirroredRect(item.rect);
+ // only valid cases are mirrored
+ if (mirroredRect.isValid()){
+ mirroredRect.moveLeft(size.width()-item.rect.width()-item.rect.left());
+ }
+ QRectF expected = mirroredRect;
+ QRectF actual = widgets[item.index]->geometry();
+
+ QVERIFY(fuzzierCompare(actual, expected));
+ }
+
+ qDeleteAll(widgets);
+ delete widget;
+}
+
+void tst_QGraphicsAnchorLayout1::testNegativeSpacing()
+{
+ // use the same frame
+ testBasicLayout();
+}
+
+void tst_QGraphicsAnchorLayout1::testMixedSpacing()
+{
+ // use the same frame
+ testBasicLayout();
+}
+
+void tst_QGraphicsAnchorLayout1::testMulti()
+{
+ // use the same frame
+ testBasicLayout();
+}
+
+void tst_QGraphicsAnchorLayout1::testCenterAnchors_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::addColumn<BasicLayoutTestDataList>("data");
+ QTest::addColumn<BasicLayoutTestResultList>("result");
+
+ typedef BasicLayoutTestData BasicData;
+ typedef BasicLayoutTestResult BasicResult;
+
+ // Basic center case
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ // << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorHorizontalCenter, -10)
+ << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorHorizontalCenter, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorRight, 15)
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorVerticalCenter, 10)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 5);
+
+ theResult
+ << BasicResult(0, QRectF(5, 5, 10, 10) );
+
+ QTest::newRow("center, basic") << QSizeF(20, 20) << theData << theResult;
+ }
+
+ // Basic center case, with invalid (shouldn't affect on result)
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ // << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorHorizontalCenter, -10)
+ << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorHorizontalCenter, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorRight, 15)
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorVerticalCenter, 10)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 5)
+
+ // bogus definitions
+ << BasicData(0, Qt::AnchorHorizontalCenter, -1, Qt::AnchorBottom, 5)
+ << BasicData(0, Qt::AnchorHorizontalCenter, 1, Qt::AnchorVerticalCenter, 5)
+ << BasicData(0, Qt::AnchorVerticalCenter, -1, Qt::AnchorRight, 5)
+ << BasicData(0, Qt::AnchorVerticalCenter, 0, Qt::AnchorVerticalCenter, 666)
+ << BasicData(0, Qt::AnchorHorizontalCenter, 0, Qt::AnchorHorizontalCenter, 999)
+ << BasicData(0, Qt::AnchorLeft, 0, Qt::AnchorLeft, 333)
+ << BasicData(-1, Qt::AnchorRight, -1, Qt::AnchorRight, 222)
+ << BasicData(0, Qt::AnchorTop, 0, Qt::AnchorTop, 111)
+ << BasicData(0, Qt::AnchorBottom, 0, Qt::AnchorBottom, 444);
+
+ theResult
+ << BasicResult(0, QRectF(5, 5, 10, 10) );
+
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor edges of different orientations");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor edges of different orientations");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor edges of different orientations");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ QTest::newRow("center, basic with invalid") << QSizeF(20, 20) << theData << theResult;
+ }
+
+ // Basic center case 2
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorHorizontalCenter, 0)
+ // Not supported << BasicData(0, Qt::AnchorHorizontalCenter, 0, Qt::AnchorRight, 5)
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorRight, 5)
+ << BasicData(-1, Qt::AnchorVerticalCenter, 0, Qt::AnchorVerticalCenter, 0)
+ << BasicData(-1, Qt::AnchorVerticalCenter, 0, Qt::AnchorTop, -5);
+
+ theResult
+ << BasicResult(0, QRectF(5, 5, 10, 10) );
+
+ QTest::newRow("center, basic 2") << QSizeF(20, 20) << theData << theResult;
+ }
+
+ // Basic center case, overrides
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorHorizontalCenter, 10)
+ << BasicData(-1, Qt::AnchorVerticalCenter, 0, Qt::AnchorVerticalCenter, 20)
+ << BasicData(0, Qt::AnchorHorizontalCenter, -1, Qt::AnchorHorizontalCenter, 30)
+ << BasicData(0, Qt::AnchorVerticalCenter, -1, Qt::AnchorVerticalCenter, 40)
+ // actual data:
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorHorizontalCenter, 0)
+ << BasicData(-1, Qt::AnchorVerticalCenter, 0, Qt::AnchorVerticalCenter, 0)
+ // << BasicData(0, Qt::AnchorHorizontalCenter, 0, Qt::AnchorRight, 5)
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorRight, 5)
+ << BasicData(-1, Qt::AnchorVerticalCenter, 0, Qt::AnchorTop, -5);
+
+ theResult
+ << BasicResult(0, QRectF(5, 5, 10, 10) );
+
+ QTest::newRow("center, overrides") << QSizeF(20, 20) << theData << theResult;
+ }
+
+ // Two nested
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorLeft, 0)
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 0)
+ << BasicData(-1, Qt::AnchorBottom, 0, Qt::AnchorBottom, 0)
+ << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorRight, 0)
+ << BasicData(0, Qt::AnchorVerticalCenter, 1, Qt::AnchorTop, 0)
+ << BasicData(0, Qt::AnchorLeft, 1, Qt::AnchorLeft, 0)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorRight, 0)
+ << BasicData(0, Qt::AnchorBottom, 1, Qt::AnchorBottom, 0);
+
+ theResult
+ << BasicResult(0, QRectF(20, 0, 20, 40))
+ << BasicResult(1, QRectF(20, 20, 20, 20));
+
+ QTest::newRow("center, two nested") << QSizeF(40, 40) << theData << theResult;
+ }
+
+ // Two overlap
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ // theData
+ // // horizontal
+ // << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 20)
+ // << BasicData(0, Qt::AnchorHorizontalCenter, 1, Qt::AnchorLeft, 0)
+ // << BasicData(1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorRight, -5)
+ // << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ // << BasicData(0, Qt::AnchorHorizontalCenter, 0, Qt::AnchorRight, 10)
+ // // vertical is pretty much same as horizontal, just roles swapped
+ // << BasicData(-1, Qt::AnchorTop, 1, Qt::AnchorTop, 20)
+ // << BasicData(1, Qt::AnchorVerticalCenter, 0, Qt::AnchorTop, 0)
+ // << BasicData(0, Qt::AnchorVerticalCenter, 1, Qt::AnchorBottom, -5)
+ // << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 10)
+ // << BasicData(1, Qt::AnchorVerticalCenter, 1, Qt::AnchorBottom, 10);
+
+ theData
+ // horizontal
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 20)
+ << BasicData(0, Qt::AnchorHorizontalCenter, 1, Qt::AnchorLeft, 0)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorHorizontalCenter, 5)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorRight, 20)
+ // vertical
+ << BasicData(-1, Qt::AnchorTop, 1, Qt::AnchorTop, 20)
+ << BasicData(1, Qt::AnchorVerticalCenter, 0, Qt::AnchorTop, 0)
+ << BasicData(1, Qt::AnchorBottom, 0, Qt::AnchorVerticalCenter, 5)
+ << BasicData(1, Qt::AnchorBottom, 0, Qt::AnchorBottom, 20);
+
+ theResult
+ << BasicResult(0, QRectF(20, 30, 20, 30))
+ << BasicResult(1, QRectF(30, 20, 30, 20));
+
+ QTest::newRow("center, two overlap") << QSizeF(70, 70) << theData << theResult;
+ }
+
+ // Three
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 0)
+ << BasicData(0, Qt::AnchorHorizontalCenter, 2, Qt::AnchorHorizontalCenter, 75)
+ << BasicData(1, Qt::AnchorRight, 2, Qt::AnchorLeft, 10)
+ << BasicData(1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorHorizontalCenter, -30)
+ << BasicData(2, Qt::AnchorRight, -1, Qt::AnchorRight, 0)
+ << BasicData(1, Qt::AnchorLeft, 1, Qt::AnchorRight, 30)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorLeft, 10)
+
+ << BasicData(1, Qt::AnchorTop, -1, Qt::AnchorTop, 0)
+ << BasicData(1, Qt::AnchorVerticalCenter, 0, Qt::AnchorVerticalCenter, 35)
+ << BasicData(1, Qt::AnchorVerticalCenter, 2, Qt::AnchorVerticalCenter, 15)
+ << BasicData(1, Qt::AnchorBottom, 2, Qt::AnchorTop, 5)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 0)
+ << BasicData(2, Qt::AnchorBottom, 0, Qt::AnchorTop, 5)
+ << BasicData(0, Qt::AnchorTop, 0, Qt::AnchorBottom, 20);
+
+ theResult
+ << BasicResult(0, QRectF(0, 30, 10, 20))
+ << BasicResult(1, QRectF(20, 0, 30, 10))
+ << BasicResult(2, QRectF(60, 15, 40, 10));
+
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+
+ QTest::newRow("center, three") << QSizeF(100, 50) << theData << theResult;
+ }
+
+ // Two, parent center
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ // vertical is pretty much same as horizontal, just roles swapped
+ << BasicData(-1, Qt::AnchorVerticalCenter, 1, Qt::AnchorVerticalCenter, -15)
+ << BasicData(-1, Qt::AnchorVerticalCenter, 0, Qt::AnchorVerticalCenter, 10)
+ << BasicData(-1, Qt::AnchorBottom, 0, Qt::AnchorBottom, 0)
+ << BasicData(1, Qt::AnchorTop, 0, Qt::AnchorTop, 0)
+ // horizontal
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorHorizontalCenter, -15)
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 1, Qt::AnchorHorizontalCenter, 10)
+ << BasicData(-1, Qt::AnchorRight, 1, Qt::AnchorRight, 0)
+ << BasicData(0, Qt::AnchorLeft, 1, Qt::AnchorLeft, 0);
+
+ theResult
+ << BasicResult(0, QRectF(20, 20, 30, 80))
+ << BasicResult(1, QRectF(20, 20, 80, 30));
+
+ QTest::newRow("center, parent") << QSizeF(100, 100) << theData << theResult;
+ }
+
+ // Two, parent center 2
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ // << BasicData(1, Qt::AnchorLeft, -1, Qt::AnchorHorizontalCenter, 15)
+ << BasicData(1, Qt::AnchorLeft, -1, Qt::AnchorHorizontalCenter, -15)
+ << BasicData(1, Qt::AnchorRight, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, -1, Qt::AnchorRight, 5)
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 1, Qt::AnchorRight, -5)
+ // vertical
+ << BasicData(0, Qt::AnchorVerticalCenter, 1, Qt::AnchorVerticalCenter, 20)
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 10)
+ << BasicData(0, Qt::AnchorBottom, 1, Qt::AnchorBottom, 20)
+ << BasicData(0, Qt::AnchorTop, 1, Qt::AnchorTop, 20)
+ << BasicData(0, Qt::AnchorBottom, 1, Qt::AnchorTop, 10);
+
+ theResult
+ << BasicResult(0, QRectF(30, 10, 15, 10))
+ << BasicResult(1, QRectF(10, 30, 10, 10));
+
+ QTest::newRow("center, parent 2") << QSizeF(50, 50) << theData << theResult;
+ }
+
+ // Two, parent center 3
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorRight, -5)
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 1, Qt::AnchorLeft, 5)
+ // << BasicData(0, Qt::AnchorLeft, 1, Qt::AnchorRight, 100)
+ << BasicData(0, Qt::AnchorLeft, 1, Qt::AnchorRight, -100)
+ << BasicData(0, Qt::AnchorLeft, -1, Qt::AnchorLeft, 0)
+
+ // vertical
+ << BasicData(0, Qt::AnchorVerticalCenter, 1, Qt::AnchorVerticalCenter, 55)
+ << BasicData(0, Qt::AnchorTop, -1, Qt::AnchorTop, 0)
+ << BasicData(1, Qt::AnchorBottom, -1, Qt::AnchorBottom, 0)
+ << BasicData(0, Qt::AnchorBottom, 1, Qt::AnchorTop, 10)
+ // << BasicData(0, Qt::AnchorTop, 0, Qt::AnchorBottom, 45)
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorBottom, 45)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(0, 0, 45, 45))
+ << BasicResult(1, QRectF(55, 55, 45, 45));
+
+ QTest::newRow("center, parent 3") << QSizeF(100, 100) << theData << theResult;
+ }
+
+}
+
+void tst_QGraphicsAnchorLayout1::testCenterAnchors()
+{
+ // use the same frame
+ testBasicLayout();
+}
+
+void tst_QGraphicsAnchorLayout1::testRemoveCenterAnchor_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::addColumn<BasicLayoutTestDataList>("data");
+ QTest::addColumn<BasicLayoutTestDataList>("removeData");
+ QTest::addColumn<BasicLayoutTestResultList>("result");
+
+ typedef BasicLayoutTestData BasicData;
+ typedef BasicLayoutTestResult BasicResult;
+
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestDataList theRemoveData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ // << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorHorizontalCenter, -10)
+ << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorHorizontalCenter, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorRight, 15)
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorVerticalCenter, 10)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 5)
+
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 1, Qt::AnchorHorizontalCenter, 66)
+ << BasicData(1, Qt::AnchorVerticalCenter, -1, Qt::AnchorVerticalCenter, 99)
+ << BasicData(0, Qt::AnchorHorizontalCenter, 1, Qt::AnchorHorizontalCenter, 33)
+ ;
+
+ theRemoveData
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 1, Qt::AnchorHorizontalCenter, 0)
+ << BasicData(1, Qt::AnchorVerticalCenter, -1, Qt::AnchorVerticalCenter, 0)
+ << BasicData(0, Qt::AnchorHorizontalCenter, 1, Qt::AnchorHorizontalCenter, 0);
+
+ theResult
+ << BasicResult(0, QRectF(5, 5, 10, 10) );
+
+ QTest::newRow("remove, center, basic") << QSizeF(20, 20) << theData
+ << theRemoveData << theResult;
+ }
+
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestDataList theRemoveData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 0)
+ << BasicData(0, Qt::AnchorHorizontalCenter, 2, Qt::AnchorHorizontalCenter, 75)
+ << BasicData(1, Qt::AnchorRight, 2, Qt::AnchorLeft, 10)
+ << BasicData(1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorHorizontalCenter, -30)
+ << BasicData(2, Qt::AnchorRight, -1, Qt::AnchorRight, 0)
+ << BasicData(1, Qt::AnchorLeft, 1, Qt::AnchorRight, 30)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorLeft, 10)
+
+ // extra:
+ << BasicData(-1, Qt::AnchorVerticalCenter, 0, Qt::AnchorVerticalCenter, 66)
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorHorizontalCenter, 33)
+ << BasicData(0, Qt::AnchorHorizontalCenter, 0, Qt::AnchorHorizontalCenter, 55)
+ << BasicData(1, Qt::AnchorVerticalCenter, 1, Qt::AnchorVerticalCenter, 55)
+
+ << BasicData(1, Qt::AnchorTop, -1, Qt::AnchorTop, 0)
+ << BasicData(1, Qt::AnchorVerticalCenter, 0, Qt::AnchorVerticalCenter, 35)
+ << BasicData(1, Qt::AnchorVerticalCenter, 2, Qt::AnchorVerticalCenter, 15)
+ << BasicData(1, Qt::AnchorBottom, 2, Qt::AnchorTop, 5)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 0)
+ << BasicData(2, Qt::AnchorBottom, 0, Qt::AnchorTop, 5)
+ << BasicData(0, Qt::AnchorTop, 0, Qt::AnchorBottom, 20);
+
+ theRemoveData
+ << BasicData(-1, Qt::AnchorVerticalCenter, 0, Qt::AnchorVerticalCenter, 66)
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorHorizontalCenter, 33)
+ << BasicData(0, Qt::AnchorHorizontalCenter, 0, Qt::AnchorHorizontalCenter, 55)
+ << BasicData(1, Qt::AnchorVerticalCenter, 1, Qt::AnchorVerticalCenter, 55);
+
+ theResult
+ << BasicResult(0, QRectF(0, 30, 10, 20))
+ << BasicResult(1, QRectF(20, 0, 30, 10))
+ << BasicResult(2, QRectF(60, 15, 40, 10));
+
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+
+ QTest::newRow("remove, center, three") << QSizeF(100, 50) << theData << theRemoveData << theResult;
+ }
+
+ // add edge (item0,edge0,item1,edge1), remove (item1,edge1,item0,edge0)
+ {
+ BasicLayoutTestDataList theData;
+ BasicLayoutTestDataList theRemoveData;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ // << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorHorizontalCenter, -10)
+ << BasicData(-1, Qt::AnchorRight, 0, Qt::AnchorHorizontalCenter, 10)
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorRight, 15)
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorVerticalCenter, 10)
+ << BasicData(0, Qt::AnchorBottom, -1, Qt::AnchorBottom, 5)
+
+ << BasicData(-1, Qt::AnchorHorizontalCenter, 1, Qt::AnchorHorizontalCenter, 66)
+ << BasicData(1, Qt::AnchorVerticalCenter, -1, Qt::AnchorVerticalCenter, 99)
+ << BasicData(0, Qt::AnchorHorizontalCenter, 1, Qt::AnchorHorizontalCenter, 33)
+ << BasicData(0, Qt::AnchorLeft, 0, Qt::AnchorRight, 22)
+ << BasicData(0, Qt::AnchorTop, 0, Qt::AnchorBottom, 11)
+ ;
+
+ theRemoveData
+ << BasicData(1, Qt::AnchorHorizontalCenter, -1, Qt::AnchorHorizontalCenter, 0)
+ << BasicData(-1, Qt::AnchorVerticalCenter, 1, Qt::AnchorVerticalCenter, 0)
+ << BasicData(1, Qt::AnchorHorizontalCenter, 0, Qt::AnchorHorizontalCenter, 0)
+ << BasicData(0, Qt::AnchorRight, 0, Qt::AnchorLeft, 0)
+ << BasicData(0, Qt::AnchorBottom, 0, Qt::AnchorTop, 0)
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(5, 5, 10, 10) );
+
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsAnchorLayout::addAnchor(): Cannot anchor the item to itself");
+ QTest::newRow("remove, center, basic 2") << QSizeF(20, 20) << theData
+ << theRemoveData << theResult;
+ }
+
+}
+
+void tst_QGraphicsAnchorLayout1::testRemoveCenterAnchor()
+{
+ QFETCH(QSizeF, size);
+ QFETCH(BasicLayoutTestDataList, data);
+ QFETCH(BasicLayoutTestDataList, removeData);
+ QFETCH(BasicLayoutTestResultList, result);
+
+ QGraphicsWidget *widget = new QGraphicsWidget;
+
+ // Determine amount of widgets to add.
+ int widgetCount = -1;
+ for (int i = 0; i < data.count(); ++i) {
+ const BasicLayoutTestData item = data[i];
+ widgetCount = qMax(widgetCount, item.firstIndex);
+ widgetCount = qMax(widgetCount, item.secondIndex);
+ }
+ ++widgetCount; // widgetCount is max of indices.
+
+ // Create dummy widgets
+ QList<QGraphicsWidget *> widgets;
+ for (int i = 0; i < widgetCount; ++i) {
+ TestWidget *w = new TestWidget;
+ widgets << w;
+ }
+
+ // Setup anchor layout
+ TheAnchorLayout *layout = new TheAnchorLayout;
+
+ for (int i = 0; i < data.count(); ++i) {
+ const BasicLayoutTestData item = data[i];
+ layout->setAnchor(
+ getItem(item.firstIndex, widgets, layout),
+ item.firstEdge,
+ getItem(item.secondIndex, widgets, layout),
+ item.secondEdge,
+ item.spacing );
+ }
+
+ for (int i = 0; i < removeData.count(); ++i) {
+ const BasicLayoutTestData item = removeData[i];
+ layout->removeAnchor(
+ getItem(item.firstIndex, widgets, layout),
+ item.firstEdge,
+ getItem(item.secondIndex, widgets, layout),
+ item.secondEdge);
+ }
+
+ widget->setLayout(layout);
+ widget->setContentsMargins(0,0,0,0);
+
+ widget->resize(size);
+ QCOMPARE(widget->size(), size);
+
+ // Validate
+ for (int i = 0; i < result.count(); ++i) {
+ const BasicLayoutTestResult item = result[i];
+
+ QCOMPARE(widgets[item.index]->geometry(), item.rect);
+ }
+
+ qDeleteAll(widgets);
+ delete widget;
+}
+
+void tst_QGraphicsAnchorLayout1::testSingleSizePolicy_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::addColumn<QSizePolicy>("policy");
+ QTest::addColumn<bool>("valid");
+
+// FIXED
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ QTest::newRow("single size policy: fixed ok") << QSizeF(70, 70) << sizePolicy << true;
+ }
+/*
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ QTest::newRow("single size policy: fixed too big") << QSizeF(100, 100) << sizePolicy << false;
+ }
+
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ QTest::newRow("single size policy: fixed too small") << QSizeF(50, 50) << sizePolicy << false;
+ }
+*/
+// MINIMUM
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
+ QTest::newRow("single size policy: minimum bigger ok") << QSizeF(100, 100) << sizePolicy << true;
+ }
+
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
+ QTest::newRow("single size policy: minimum limit ok") << QSizeF(70, 70) << sizePolicy << true;
+ }
+/*
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
+ QTest::newRow("single size policy: minimum too small") << QSizeF(50, 50) << sizePolicy << false;
+ }
+*/
+// MAXIMUM
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Maximum, QSizePolicy::Maximum );
+ QTest::newRow("single size policy: maximum small ok") << QSizeF(50, 50) << sizePolicy << true;
+ }
+
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Maximum, QSizePolicy::Maximum );
+ QTest::newRow("single size policy: maximum limit ok") << QSizeF(70, 70) << sizePolicy << true;
+ }
+/*
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Maximum, QSizePolicy::Maximum );
+ QTest::newRow("single size policy: maximum bigger fail") << QSizeF(100, 100) << sizePolicy << false;
+ }
+*/
+// PREFERRED
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ QTest::newRow("single size policy: preferred bigger ok") << QSizeF(100, 100) << sizePolicy << true;
+ }
+
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ QTest::newRow("single size policy: preferred smaller ok") << QSizeF(50, 50) << sizePolicy << true;
+ }
+/*
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ QTest::newRow("single size policy: preferred too big") << QSizeF(700, 700) << sizePolicy << false;
+ }
+
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ QTest::newRow("single size policy: preferred too small") << QSizeF(21, 21) << sizePolicy << false;
+ }
+*/
+// MINIMUMEXPANDING
+
+ {
+ QSizePolicy sizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding );
+ QTest::newRow("single size policy: min.expanding bigger ok") << QSizeF(100, 100) << sizePolicy << true;
+ }
+
+ {
+ QSizePolicy sizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding );
+ QTest::newRow("single size policy: min.expanding limit ok") << QSizeF(70, 70) << sizePolicy << true;
+ }
+
+ /*{
+ QSizePolicy sizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding );
+ QTest::newRow("single size policy: min.expanding too small") << QSizeF(50, 50) << sizePolicy << false;
+ }*/
+
+// EXPANDING
+
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
+ QTest::newRow("single size policy: expanding bigger ok") << QSizeF(100, 100) << sizePolicy << true;
+ }
+
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
+ QTest::newRow("single size policy: expanding smaller ok") << QSizeF(50, 50) << sizePolicy << true;
+ }
+
+ // IGNORED
+
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Ignored, QSizePolicy::Ignored );
+ QTest::newRow("single size policy: ignored bigger ok") << QSizeF(100, 100) << sizePolicy << true;
+ }
+
+ {
+ QSizePolicy sizePolicy( QSizePolicy::Ignored, QSizePolicy::Ignored );
+ QTest::newRow("single size policy: ignored smaller ok") << QSizeF(50, 50) << sizePolicy << true;
+ }
+}
+
+void tst_QGraphicsAnchorLayout1::testSingleSizePolicy()
+{
+ QFETCH(QSizeF, size);
+ QFETCH(QSizePolicy, policy);
+ QFETCH(bool, valid);
+
+ // create objects
+ QGraphicsWidget widget;
+ TheAnchorLayout *layout = new TheAnchorLayout;
+ TestWidget *childWidget = new TestWidget;
+
+ // set anchors
+ layout->setAnchor( layout, Qt::AnchorLeft, childWidget, Qt::AnchorLeft, 10 );
+ layout->setAnchor( childWidget, Qt::AnchorRight, layout, Qt::AnchorRight, 10 );
+ layout->setAnchor( layout, Qt::AnchorTop, childWidget, Qt::AnchorTop, 10 );
+ layout->setAnchor( childWidget, Qt::AnchorBottom, layout, Qt::AnchorBottom, 10 );
+
+ widget.setLayout( layout );
+
+ // set test case specific: policy and size
+ childWidget->setSizePolicy( policy );
+ widget.setGeometry( QRectF( QPoint(0,0), size ) );
+
+ QCOMPARE( layout->isValid() , valid );
+
+ const QRectF childRect = childWidget->geometry();
+ Q_UNUSED( childRect );
+}
+
+void tst_QGraphicsAnchorLayout1::testDoubleSizePolicy_data()
+{
+ // tests only horizontal direction
+ QTest::addColumn<QSizePolicy>("policy1");
+ QTest::addColumn<QSizePolicy>("policy2");
+ QTest::addColumn<qreal>("width1");
+ QTest::addColumn<qreal>("width2");
+
+ // layout size always 100x100 and size hints for items are 5<50<500
+ // gabs: 10-item1-10-item2-10
+
+ {
+ QSizePolicy sizePolicy1( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ QSizePolicy sizePolicy2( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ const qreal width1 = 50;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: fixed-preferred") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }
+
+ {
+ QSizePolicy sizePolicy1( QSizePolicy::Minimum, QSizePolicy::Minimum );
+ QSizePolicy sizePolicy2( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ const qreal width1 = 50;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: minimum-preferred") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }
+
+ {
+ QSizePolicy sizePolicy1( QSizePolicy::Maximum, QSizePolicy::Maximum );
+ QSizePolicy sizePolicy2( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ const qreal width1 = 35;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: maximum-preferred") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }
+
+ {
+ QSizePolicy sizePolicy1( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ QSizePolicy sizePolicy2( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ const qreal width1 = 35;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: preferred-preferred") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }
+
+ {
+ QSizePolicy sizePolicy1( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding );
+ QSizePolicy sizePolicy2( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ const qreal width1 = 50;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: min.expanding-preferred") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }
+
+ {
+ QSizePolicy sizePolicy1( QSizePolicy::Expanding, QSizePolicy::Expanding );
+ QSizePolicy sizePolicy2( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ const qreal width1 = 35;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: expanding-preferred") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }
+
+ // QGAL handling of ignored flag is different
+ if (0)
+ {
+ QSizePolicy sizePolicy1( QSizePolicy::Ignored, QSizePolicy::Ignored );
+ QSizePolicy sizePolicy2( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ const qreal width1 = 35;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: ignored-preferred") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }
+
+ /*{
+ QSizePolicy sizePolicy1( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ QSizePolicy sizePolicy2( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ const qreal width1 = -1;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: fixed-fixed invalid") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }*/
+
+ /*{
+ QSizePolicy sizePolicy1( QSizePolicy::Minimum, QSizePolicy::Minimum );
+ QSizePolicy sizePolicy2( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ const qreal width1 = -1;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: minimum-fixed invalid") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }*/
+
+ {
+ QSizePolicy sizePolicy1( QSizePolicy::Maximum, QSizePolicy::Maximum );
+ QSizePolicy sizePolicy2( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ const qreal width1 = 20;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: maximum-fixed") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }
+
+ {
+ QSizePolicy sizePolicy1( QSizePolicy::Preferred, QSizePolicy::Preferred );
+ QSizePolicy sizePolicy2( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ const qreal width1 = 20;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: preferred-fixed") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }
+
+ /*{
+ QSizePolicy sizePolicy1( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding );
+ QSizePolicy sizePolicy2( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ const qreal width1 = -1;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: min.expanding-fixed invalid") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }*/
+
+ {
+ QSizePolicy sizePolicy1( QSizePolicy::Expanding, QSizePolicy::Expanding );
+ QSizePolicy sizePolicy2( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ const qreal width1 = 20;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: expanding-fixed") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }
+
+ {
+ QSizePolicy sizePolicy1( QSizePolicy::Ignored, QSizePolicy::Ignored );
+ QSizePolicy sizePolicy2( QSizePolicy::Fixed, QSizePolicy::Fixed );
+ const qreal width1 = 20;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("double size policy: ignored-fixed") << sizePolicy1 << sizePolicy2 << width1 << width2;
+ }
+}
+
+void tst_QGraphicsAnchorLayout1::testDoubleSizePolicy()
+{
+ QFETCH(QSizePolicy, policy1);
+ QFETCH(QSizePolicy, policy2);
+ QFETCH(qreal, width1);
+ QFETCH(qreal, width2);
+
+ // create objects
+ QGraphicsWidget widget;
+ TheAnchorLayout *layout = new TheAnchorLayout;
+ TestWidget *childWidget1 = new TestWidget;
+ TestWidget *childWidget2 = new TestWidget;
+
+ // set anchors
+ layout->setAnchor( layout, Qt::AnchorLeft, childWidget1, Qt::AnchorLeft, 10 );
+ layout->setAnchor( childWidget1, Qt::AnchorRight, childWidget2, Qt::AnchorLeft, 10 );
+ layout->setAnchor( childWidget2, Qt::AnchorRight, layout, Qt::AnchorRight, 10 );
+
+ widget.setLayout( layout );
+
+ // set test case specific: policy
+ childWidget1->setSizePolicy( policy1 );
+ childWidget2->setSizePolicy( policy2 );
+
+ widget.setGeometry( QRectF( QPoint(0,0), QSize( 100,100 ) ) );
+
+ // check results:
+ if ( width1 == -1.0f ) {
+ // invalid
+ QCOMPARE( layout->isValid() , false );
+ } else {
+ // valid
+ QCOMPARE( childWidget1->geometry().width(), width1 );
+ QCOMPARE( childWidget2->geometry().width(), width2 );
+ }
+}
+
+typedef QMap<int,qreal> SizeHintArray;
+Q_DECLARE_METATYPE(SizeHintArray)
+
+void tst_QGraphicsAnchorLayout1::testSizeDistribution_data()
+{
+ // tests only horizontal direction
+ QTest::addColumn<SizeHintArray>("sizeHints1");
+ QTest::addColumn<SizeHintArray>("sizeHints2");
+ QTest::addColumn<qreal>("width1");
+ QTest::addColumn<qreal>("width2");
+
+ // layout size always 100x100 and size policy for items is preferred-preferred
+ // gabs: 10-item1-10-item2-10
+
+ {
+ SizeHintArray sizeHints1;
+ sizeHints1.insert( Qt::MinimumSize, 30 );
+ sizeHints1.insert( Qt::PreferredSize, 35 );
+ sizeHints1.insert( Qt::MaximumSize, 40 );
+
+ SizeHintArray sizeHints2;
+ sizeHints2.insert( Qt::MinimumSize, 5 );
+ sizeHints2.insert( Qt::PreferredSize, 35 );
+ sizeHints2.insert( Qt::MaximumSize, 300 );
+
+ const qreal width1 = 35;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("size distribution: preferred equal") << sizeHints1 << sizeHints2 << width1 << width2;
+ }
+
+ {
+ SizeHintArray sizeHints1;
+ sizeHints1.insert( Qt::MinimumSize, 0 );
+ sizeHints1.insert( Qt::PreferredSize, 20 );
+ sizeHints1.insert( Qt::MaximumSize, 100 );
+
+ SizeHintArray sizeHints2;
+ sizeHints2.insert( Qt::MinimumSize, 0 );
+ sizeHints2.insert( Qt::PreferredSize, 50 );
+ sizeHints2.insert( Qt::MaximumSize, 100 );
+
+ const qreal width1 = 20;
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("size distribution: preferred non-equal") << sizeHints1 << sizeHints2 << width1 << width2;
+ }
+
+ {
+ SizeHintArray sizeHints1;
+ sizeHints1.insert( Qt::MinimumSize, 0 );
+ sizeHints1.insert( Qt::PreferredSize, 40 );
+ sizeHints1.insert( Qt::MaximumSize, 100 );
+
+ SizeHintArray sizeHints2;
+ sizeHints2.insert( Qt::MinimumSize, 0 );
+ sizeHints2.insert( Qt::PreferredSize, 60 );
+ sizeHints2.insert( Qt::MaximumSize, 100 );
+
+ const qreal width1 = 28; // got from manual calculation
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("size distribution: below preferred") << sizeHints1 << sizeHints2 << width1 << width2;
+ }
+
+ {
+ SizeHintArray sizeHints1;
+ sizeHints1.insert( Qt::MinimumSize, 0 );
+ sizeHints1.insert( Qt::PreferredSize, 10 );
+ sizeHints1.insert( Qt::MaximumSize, 100 );
+
+ SizeHintArray sizeHints2;
+ sizeHints2.insert( Qt::MinimumSize, 0 );
+ sizeHints2.insert( Qt::PreferredSize, 40 );
+ sizeHints2.insert( Qt::MaximumSize, 100 );
+
+ const qreal width1 = 22; // got from manual calculation
+ const qreal width2 = 100-10-10-10-width1;
+ QTest::newRow("size distribution: above preferred") << sizeHints1 << sizeHints2 << width1 << width2;
+ }
+
+}
+
+void tst_QGraphicsAnchorLayout1::testSizeDistribution()
+{
+ QFETCH(SizeHintArray, sizeHints1);
+ QFETCH(SizeHintArray, sizeHints2);
+ QFETCH(qreal, width1);
+ QFETCH(qreal, width2);
+
+ // sanity-check the test data - MinimumSize <= PreferredSize <= MaximumSize
+ QVERIFY( sizeHints1.value( Qt::MinimumSize ) <= sizeHints1.value( Qt::PreferredSize ) );
+ QVERIFY( sizeHints1.value( Qt::PreferredSize ) <= sizeHints1.value( Qt::MaximumSize ) );
+ QVERIFY( sizeHints2.value( Qt::MinimumSize ) <= sizeHints2.value( Qt::PreferredSize ) );
+ QVERIFY( sizeHints2.value( Qt::PreferredSize ) <= sizeHints2.value( Qt::MaximumSize ) );
+
+ // create objects
+ QGraphicsWidget widget;
+ TheAnchorLayout *layout = new TheAnchorLayout;
+ TestWidget *childWidget1 = new TestWidget;
+ TestWidget *childWidget2 = new TestWidget;
+
+ // set anchors
+ layout->setAnchor( layout, Qt::AnchorLeft, childWidget1, Qt::AnchorLeft, 10 );
+ layout->setAnchor( childWidget1, Qt::AnchorRight, childWidget2, Qt::AnchorLeft, 10 );
+ layout->setAnchor( childWidget2, Qt::AnchorRight, layout, Qt::AnchorRight, 10 );
+
+ widget.setLayout( layout );
+
+ // set test case specific: size hints
+ childWidget1->setMinimumWidth( sizeHints1.value( Qt::MinimumSize ) );
+ childWidget1->setPreferredWidth( sizeHints1.value( Qt::PreferredSize ) );
+ childWidget1->setMaximumWidth( sizeHints1.value( Qt::MaximumSize ) );
+
+ childWidget2->setMinimumWidth( sizeHints2.value( Qt::MinimumSize ) );
+ childWidget2->setPreferredWidth( sizeHints2.value( Qt::PreferredSize ) );
+ childWidget2->setMaximumWidth( sizeHints2.value( Qt::MaximumSize ) );
+
+ widget.setGeometry( QRectF( QPoint(0,0), QSize( 100,100 ) ) );
+
+ // check results:
+ if ( width1 == -1.0f ) {
+ // invalid
+ QCOMPARE( layout->isValid() , false );
+ } else {
+ // valid
+ QCOMPARE( float(childWidget1->geometry().width()), float(width1) );
+ QCOMPARE( float(childWidget2->geometry().width()), float(width2) );
+ }
+}
+
+void tst_QGraphicsAnchorLayout1::testSizeHint()
+{
+ QGraphicsWidget *widget[5];
+
+ for( int i = 0; i < 5; i++ ) {
+ widget[i] = new QGraphicsWidget;
+ widget[i]->setMinimumSize( 10, 10 );
+ widget[i]->setPreferredSize( 20, 20 );
+ widget[i]->setMaximumSize( 40, 40 );
+ }
+
+ // one, basic
+ {
+ TheAnchorLayout *layout = new TheAnchorLayout();
+
+
+ layout->setAnchor(layout, Qt::AnchorLeft, widget[0], Qt::AnchorLeft, 0 );
+ layout->setAnchor(layout, Qt::AnchorRight, widget[0], Qt::AnchorRight, 0 );
+
+ layout->setAnchor(layout, Qt::AnchorTop, widget[0], Qt::AnchorTop, 0 );
+ layout->setAnchor(layout, Qt::AnchorBottom, widget[0], Qt::AnchorBottom, 0 );
+
+ QCOMPARE( layout->minimumSize(), widget[0]->minimumSize() );
+ QCOMPARE( layout->preferredSize(), widget[0]->preferredSize() );
+ QCOMPARE( layout->maximumSize(), widget[0]->maximumSize() );
+
+
+ delete layout;
+ }
+
+ // one, basic again
+ {
+ TheAnchorLayout *layout = new TheAnchorLayout();
+
+
+ layout->setAnchor(layout, Qt::AnchorLeft, widget[0], Qt::AnchorLeft, 10 );
+ // layout->setAnchor(layout, Qt::AnchorRight, widget[0], Qt::AnchorRight, -10 );
+ layout->setAnchor(layout, Qt::AnchorRight, widget[0], Qt::AnchorRight, 10 );
+
+ layout->setAnchor(layout, Qt::AnchorTop, widget[0], Qt::AnchorTop, 10 );
+ // layout->setAnchor(layout, Qt::AnchorBottom, widget[0], Qt::AnchorBottom, -10 );
+ layout->setAnchor(layout, Qt::AnchorBottom, widget[0], Qt::AnchorBottom, 10 );
+
+ QCOMPARE( layout->minimumSize(), widget[0]->minimumSize() + QSizeF( 20, 20 ) );
+ QCOMPARE( layout->preferredSize(), widget[0]->preferredSize() + QSizeF( 20, 20 ) );
+ QCOMPARE( layout->maximumSize(), widget[0]->maximumSize() + QSizeF( 20, 20 ) );
+
+ delete layout;
+ }
+
+ // two, serial
+ {
+ TheAnchorLayout *layout = new TheAnchorLayout();
+
+
+ layout->setAnchor(layout, Qt::AnchorLeft, widget[0], Qt::AnchorLeft, 0 );
+ layout->setAnchor(layout, Qt::AnchorTop, widget[0], Qt::AnchorTop, 0 );
+ layout->setAnchor(layout, Qt::AnchorBottom, widget[0], Qt::AnchorBottom, 0 );
+
+ layout->setAnchor(widget[0], Qt::AnchorRight, widget[1], Qt::AnchorLeft, 0 );
+ layout->setAnchor(widget[1], Qt::AnchorRight, layout, Qt::AnchorRight, 0 );
+
+
+ QCOMPARE( layout->minimumSize(), widget[0]->minimumSize() + QSizeF( widget[1]->minimumWidth(), 0 ) );
+ QCOMPARE( layout->preferredSize(), widget[0]->preferredSize() + QSizeF( widget[1]->preferredWidth(), 0 ) );
+ QCOMPARE( layout->maximumSize(), widget[0]->maximumSize() + QSizeF( widget[1]->maximumWidth(), 0 ) );
+
+ delete layout;
+ }
+
+ // two, parallel
+ {
+ TheAnchorLayout *layout = new TheAnchorLayout();
+
+
+ layout->setAnchor(layout, Qt::AnchorLeft, widget[0], Qt::AnchorLeft, 0 );
+ layout->setAnchor(layout, Qt::AnchorTop, widget[0], Qt::AnchorTop, 0 );
+ layout->setAnchor(layout, Qt::AnchorBottom, widget[0], Qt::AnchorBottom, 0 );
+ layout->setAnchor(layout, Qt::AnchorRight, widget[0], Qt::AnchorRight, 0 );
+
+ layout->setAnchor(layout, Qt::AnchorLeft, widget[1], Qt::AnchorLeft, 0 );
+ layout->setAnchor(layout, Qt::AnchorTop, widget[1], Qt::AnchorTop, 0 );
+ layout->setAnchor(layout, Qt::AnchorBottom, widget[1], Qt::AnchorBottom, 0 );
+ layout->setAnchor(layout, Qt::AnchorRight, widget[1], Qt::AnchorRight, 0 );
+
+ QCOMPARE( layout->minimumSize(), widget[0]->minimumSize() );
+ QCOMPARE( layout->preferredSize(), widget[0]->preferredSize() );
+ QCOMPARE( layout->maximumSize(), widget[0]->maximumSize() );
+
+ delete layout;
+ }
+
+ // five, serial
+ {
+ TheAnchorLayout *layout = new TheAnchorLayout();
+
+
+ layout->setAnchor(layout, Qt::AnchorLeft, widget[0], Qt::AnchorLeft, 0 );
+ layout->setAnchor(layout, Qt::AnchorTop, widget[0], Qt::AnchorTop, 0 );
+ layout->setAnchor(layout, Qt::AnchorBottom, widget[0], Qt::AnchorBottom, 0 );
+
+ layout->setAnchor(widget[0], Qt::AnchorRight, widget[1], Qt::AnchorLeft, 0 );
+ layout->setAnchor(widget[1], Qt::AnchorRight, widget[2], Qt::AnchorLeft, 0 );
+ layout->setAnchor(widget[2], Qt::AnchorRight, widget[3], Qt::AnchorLeft, 0 );
+ layout->setAnchor(widget[3], Qt::AnchorRight, widget[4], Qt::AnchorLeft, 0 );
+ layout->setAnchor(widget[4], Qt::AnchorRight, layout, Qt::AnchorRight, 0 );
+
+
+ QCOMPARE( layout->minimumSize(), widget[0]->minimumSize() +
+ QSizeF( widget[1]->minimumWidth() +
+ widget[2]->minimumWidth() +
+ widget[3]->minimumWidth() +
+ widget[4]->minimumWidth(), 0 ) );
+
+ QCOMPARE( layout->preferredSize(), widget[0]->preferredSize() +
+ QSizeF( widget[1]->preferredWidth() +
+ widget[2]->preferredWidth() +
+ widget[3]->preferredWidth() +
+ widget[4]->preferredWidth(), 0 ) );
+
+ QCOMPARE( layout->maximumSize(), widget[0]->maximumSize() +
+ QSizeF( widget[1]->maximumWidth() +
+ widget[2]->maximumWidth() +
+ widget[3]->maximumWidth() +
+ widget[4]->maximumWidth(), 0 ) );
+
+ delete layout;
+ }
+
+
+ for( int i = 0; i < 5; i++ ) {
+ delete widget[i];
+ }
+}
+
+#ifdef TEST_COMPLEX_CASES
+
+void tst_QGraphicsAnchorLayout1::testComplexCases_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::addColumn<BasicLayoutTestDataList>("data");
+ QTest::addColumn<AnchorItemSizeHintList>("sizehint");
+ QTest::addColumn<BasicLayoutTestResultList>("result");
+
+ typedef BasicLayoutTestData BasicData;
+ typedef BasicLayoutTestResult BasicResult;
+
+ // Three widgets, the same sizehint
+ {
+ BasicLayoutTestDataList theData;
+ AnchorItemSizeHintList theSizeHint;
+ BasicLayoutTestResultList theResult1;
+ BasicLayoutTestResultList theResult2;
+
+ theData
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, 2, Qt::AnchorLeft, 10)
+
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ << BasicData(2, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 0)
+ << BasicData(-1, Qt::AnchorTop, 1, Qt::AnchorTop, 0)
+ << BasicData(-1, Qt::AnchorTop, 2, Qt::AnchorTop, 0)
+ ;
+
+ theSizeHint
+ << AnchorItemSizeHint( 0, 50, 100, 0, 50, 100 )
+ << AnchorItemSizeHint( 0, 50, 100, 0, 50, 100 )
+ << AnchorItemSizeHint( 0, 50, 100, 0, 50, 100 )
+ ;
+ theResult1
+ << BasicResult(0, QRectF(10, 0, 30, 50) )
+ << BasicResult(1, QRectF(50, 0, 30, 50) )
+ << BasicResult(2, QRectF(50, 0, 30, 50) )
+ ;
+
+ theResult2
+ << BasicResult(0, QRectF(10, 0, 60, 50) )
+ << BasicResult(1, QRectF(80, 0, 60, 50) )
+ << BasicResult(2, QRectF(80, 0, 60, 50) )
+ ;
+
+ QTest::newRow("Three, the same sizehint(1)") << QSizeF(90, 50) << theData << theSizeHint << theResult1;
+ QTest::newRow("Three, the same sizehint(2)") << QSizeF(150, 50) << theData << theSizeHint << theResult2;
+ }
+
+ // Three widgets, serial is bigger
+ {
+ BasicLayoutTestDataList theData;
+ AnchorItemSizeHintList theSizeHint;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, 2, Qt::AnchorLeft, 10)
+
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ << BasicData(2, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 0)
+ << BasicData(-1, Qt::AnchorTop, 1, Qt::AnchorTop, 0)
+ << BasicData(-1, Qt::AnchorTop, 2, Qt::AnchorTop, 0)
+ ;
+
+ theSizeHint
+ << AnchorItemSizeHint( 0, 100, 200, 0, 50, 100 )
+ << AnchorItemSizeHint( 0, 50, 100, 0, 50, 100 )
+ << AnchorItemSizeHint( 0, 50, 100, 0, 50, 100 )
+ ;
+
+ theResult
+ << BasicResult(0, QRectF(10, 0, 70, 50) )
+ << BasicResult(1, QRectF(90, 0, 35, 50) )
+ << BasicResult(2, QRectF(90, 0, 35, 50) );
+
+ QTest::newRow("Three, serial is bigger") << QSizeF(135, 50) << theData << theSizeHint << theResult;
+
+ // theResult
+ // << BasicResult(0, QRectF(10, 0, 80, 50) )
+ // << BasicResult(1, QRectF(100, 0, 60, 50) )
+ // << BasicResult(2, QRectF(100, 0, 60, 50) )
+ // ;
+
+ // QTest::newRow("Three, serial is bigger") << QSizeF(170, 50) << theData << theSizeHint << theResult;
+ }
+
+
+ // Three widgets, parallel is bigger
+ {
+ BasicLayoutTestDataList theData;
+ AnchorItemSizeHintList theSizeHint;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, 2, Qt::AnchorLeft, 10)
+
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ << BasicData(2, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 0)
+ << BasicData(-1, Qt::AnchorTop, 1, Qt::AnchorTop, 0)
+ << BasicData(-1, Qt::AnchorTop, 2, Qt::AnchorTop, 0)
+ ;
+
+ theSizeHint
+ << AnchorItemSizeHint( 0, 50, 100, 0, 50, 100 )
+ << AnchorItemSizeHint( 0, 100, 200, 0, 50, 100 )
+ << AnchorItemSizeHint( 0, 50, 100, 0, 50, 100 )
+ ;
+
+ // ### QGAL uses a different preferred size calculation algorithm.
+ // This algorithm was discussed with Jan-Arve and tries to grow
+ // items instead of shrinking them.
+ // In this case, the preferred size of each item becomes:
+ // Item 0: 50
+ // Item 1: 100 (grows to avoid shrinking item 2)
+ // Item 2: 100
+ // Therefore, the preferred size of the parent widget becomes
+ // 180 == (10 + 50 + 10 + 100 + 10)
+ // As we set its size to 150, each widget is shrinked in the same
+ // ratio, in order to achieve the width of 150 == (10 + 40 + 10 + 80 + 10)
+
+ theResult
+ << BasicResult(0, QRectF(10, 0, 40, 50) )
+ << BasicResult(1, QRectF(60, 0, 80, 50) )
+ << BasicResult(2, QRectF(60, 0, 80, 50) )
+ ;
+
+ QTest::newRow("Three, parallel is bigger") << QSizeF(150, 50) << theData << theSizeHint << theResult;
+
+ // #ifdef PREFERRED_IS_AVERAGE
+ // theResult
+ // << BasicResult(0, QRectF(10, 0, 50, 50) )
+ // << BasicResult(1, QRectF(70, 0, 75, 50) )
+ // << BasicResult(2, QRectF(70, 0, 75, 50) )
+ // ;
+
+ // QTest::newRow("Three, parallel is bigger") << QSizeF(155, 50) << theData << theSizeHint << theResult;
+ // #else
+ // theResult
+ // << BasicResult(0, QRectF(10, 0, 50, 50) )
+ // << BasicResult(1, QRectF(70, 0, 66.66666666666666, 50) )
+ // << BasicResult(2, QRectF(70, 0, 60.66666666666666, 50) )
+ // ;
+
+ // QTest::newRow("Three, parallel is bigger") << QSizeF(146.66666666666666, 50) << theData << theSizeHint << theResult;
+ // #endif
+ }
+
+ // Three widgets, the same sizehint, one center anchor
+ {
+ BasicLayoutTestDataList theData;
+ AnchorItemSizeHintList theSizeHint;
+ BasicLayoutTestResultList theResult;
+
+ theData
+ << BasicData(-1, Qt::AnchorLeft, 0, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorRight, 1, Qt::AnchorLeft, 10)
+ << BasicData(0, Qt::AnchorHorizontalCenter, 2, Qt::AnchorLeft, 10)
+
+ << BasicData(1, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+ << BasicData(2, Qt::AnchorRight, -1, Qt::AnchorRight, 10)
+
+ << BasicData(-1, Qt::AnchorTop, 0, Qt::AnchorTop, 0)
+ << BasicData(-1, Qt::AnchorTop, 1, Qt::AnchorTop, 0)
+ << BasicData(-1, Qt::AnchorTop, 2, Qt::AnchorTop, 0)
+ ;
+
+ theSizeHint
+ << AnchorItemSizeHint( 0, 50, 100, 0, 50, 100 )
+ << AnchorItemSizeHint( 0, 50, 100, 0, 50, 100 )
+ << AnchorItemSizeHint( 0, 50, 100, 0, 50, 100 )
+ ;
+ theResult
+ << BasicResult(0, QRectF(10, 0, 40, 50) )
+ << BasicResult(1, QRectF(60, 0, 40, 50) )
+ << BasicResult(2, QRectF(40, 0, 60, 50) )
+ ;
+
+ ;
+
+ QTest::newRow("Three, the same sizehint, one center anchor") << QSizeF(110, 50) << theData << theSizeHint << theResult;
+ }
+}
+
+void tst_QGraphicsAnchorLayout1::testComplexCases()
+{
+ QFETCH(QSizeF, size);
+ QFETCH(BasicLayoutTestDataList, data);
+ QFETCH(AnchorItemSizeHintList, sizehint);
+ QFETCH(BasicLayoutTestResultList, result);
+
+ QGraphicsWidget *widget = new QGraphicsWidget;
+
+ // Determine amount of widgets to add.
+ int widgetCount = -1;
+ for (int i = 0; i < data.count(); ++i) {
+ const BasicLayoutTestData item = data[i];
+ widgetCount = qMax(widgetCount, item.firstIndex);
+ widgetCount = qMax(widgetCount, item.secondIndex);
+ }
+ ++widgetCount; // widgetCount is max of indices.
+
+ // Create dummy widgets
+ QList<QGraphicsWidget *> widgets;
+ for (int i = 0; i < widgetCount; ++i) {
+ TestWidget *w = new TestWidget;
+
+ w->setMinimumWidth( sizehint[i].hmin );
+ w->setPreferredWidth( sizehint[i].hpref );
+ w->setMaximumWidth( sizehint[i].hmax );
+
+ w->setMinimumHeight( sizehint[i].vmin );
+ w->setPreferredHeight( sizehint[i].vpref );
+ w->setMaximumHeight( sizehint[i].vmax );
+
+ widgets << w;
+ }
+
+ // Setup anchor layout
+ TheAnchorLayout *layout = new TheAnchorLayout;
+
+ for (int i = 0; i < data.count(); ++i) {
+ const BasicLayoutTestData item = data[i];
+ layout->setAnchor(
+ getItem(item.firstIndex, widgets, layout),
+ item.firstEdge,
+ getItem(item.secondIndex, widgets, layout),
+ item.secondEdge,
+ item.spacing );
+ }
+
+ widget->setLayout(layout);
+ widget->setContentsMargins(0,0,0,0);
+
+ widget->resize(size);
+ QCOMPARE(widget->size(), size);
+
+// QTest::qWait(500); // layouting is asynchronous..
+
+ // Validate
+ for (int i = 0; i < result.count(); ++i) {
+ const BasicLayoutTestResult item = result[i];
+ QCOMPARE(widgets[item.index]->geometry(), item.rect);
+ }
+
+ // Test mirrored mode
+ widget->setLayoutDirection(Qt::RightToLeft);
+ layout->activate();
+ // Validate
+ for (int j = 0; j < result.count(); ++j) {
+ const BasicLayoutTestResult item = result[j];
+ QRectF mirroredRect(item.rect);
+ // only valid cases are mirrored
+ if (mirroredRect.isValid()){
+ mirroredRect.moveLeft(size.width()-item.rect.width()-item.rect.left());
+ }
+ QCOMPARE(widgets[item.index]->geometry(), mirroredRect);
+ delete widgets[item.index];
+ }
+
+ delete widget;
+}
+#endif //TEST_COMPLEX_CASES
+
+
+QTEST_MAIN(tst_QGraphicsAnchorLayout1)
+#include "tst_qgraphicsanchorlayout1.moc"
+//-----------------------------------------------------------------------------
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicseffectsource/qgraphicseffectsource.pro b/tests/auto/widgets/graphicsview/qgraphicseffectsource/qgraphicseffectsource.pro
new file mode 100644
index 0000000000..44ec70eef3
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicseffectsource/qgraphicseffectsource.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+QT += core-private gui-private
+
+SOURCES += tst_qgraphicseffectsource.cpp
+CONFIG += parallel_test
diff --git a/tests/auto/widgets/graphicsview/qgraphicseffectsource/tst_qgraphicseffectsource.cpp b/tests/auto/widgets/graphicsview/qgraphicseffectsource/tst_qgraphicseffectsource.cpp
new file mode 100644
index 0000000000..4f39f991c6
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicseffectsource/tst_qgraphicseffectsource.cpp
@@ -0,0 +1,422 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.1, 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtWidgets/qgraphicseffect.h>
+#include <QtWidgets/qgraphicsview.h>
+#include <QtWidgets/qgraphicsscene.h>
+#include <QtWidgets/qgraphicsitem.h>
+#include <QtWidgets/qstyleoption.h>
+
+#include <private/qgraphicseffect_p.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class CustomItem : public QGraphicsRectItem
+{
+public:
+ CustomItem(qreal x, qreal y, qreal width, qreal height)
+ : QGraphicsRectItem(x, y, width, height), numRepaints(0),
+ m_painter(0)
+ {}
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ m_painter = painter;
+ ++numRepaints;
+ QGraphicsRectItem::paint(painter, option, widget);
+ }
+
+ void reset()
+ {
+ numRepaints = 0;
+ m_painter = 0;
+ }
+
+ int numRepaints;
+ QPainter *m_painter;
+};
+
+class CustomEffect : public QGraphicsEffect
+{
+public:
+ CustomEffect()
+ : QGraphicsEffect(), numRepaints(0), m_margin(10), m_sourceChanged(false),
+ m_sourceBoundingRectChanged(false), doNothingInDraw(false),
+ storeDeviceDependentStuff(false),
+ m_painter(0), m_source(0)
+ {}
+
+ QRectF boundingRectFor(const QRectF &rect) const
+ { return rect.adjusted(-m_margin, -m_margin, m_margin, m_margin); }
+
+ void reset()
+ {
+ numRepaints = 0;
+ m_sourceChanged = false;
+ m_sourceBoundingRectChanged = false;
+ m_painter = 0;
+ m_source = 0;
+ deviceCoordinatesPixmap = QPixmap();
+ deviceRect = QRect();
+ sourceDeviceBoundingRect = QRectF();
+ }
+
+ void setMargin(int margin)
+ {
+ m_margin = margin;
+ updateBoundingRect();
+ }
+
+ int margin() const
+ { return m_margin; }
+
+ void draw(QPainter *painter)
+ {
+ ++numRepaints;
+ if (storeDeviceDependentStuff) {
+ deviceCoordinatesPixmap = source()->pixmap(Qt::DeviceCoordinates);
+ deviceRect = QRect(0, 0, painter->device()->width(), painter->device()->height());
+ sourceDeviceBoundingRect = source()->boundingRect(Qt::DeviceCoordinates);
+ }
+ if (doNothingInDraw)
+ return;
+ m_source = source();
+ m_painter = painter;
+ source()->draw(painter);
+ }
+
+ void sourceChanged()
+ { m_sourceChanged = true; }
+
+ void sourceBoundingRectChanged()
+ { m_sourceBoundingRectChanged = true; }
+
+ int numRepaints;
+ int m_margin;
+ bool m_sourceChanged;
+ bool m_sourceBoundingRectChanged;
+ bool doNothingInDraw;
+ bool storeDeviceDependentStuff;
+ QPainter *m_painter;
+ QGraphicsEffectSource *m_source;
+ QPixmap deviceCoordinatesPixmap;
+ QRect deviceRect;
+ QRectF sourceDeviceBoundingRect;
+};
+
+class tst_QGraphicsEffectSource : public QObject
+{
+ Q_OBJECT
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+
+private slots:
+ void graphicsItem();
+ void styleOption();
+ void isPixmap();
+ void draw();
+ void update();
+ void boundingRect();
+ void clippedBoundingRect();
+ void deviceRect();
+ void pixmap();
+
+ void pixmapPadding_data();
+ void pixmapPadding();
+
+private:
+ QGraphicsView *view;
+ QGraphicsScene *scene;
+ CustomItem *item;
+ CustomEffect *effect;
+};
+
+void tst_QGraphicsEffectSource::initTestCase()
+{
+ scene = new QGraphicsScene;
+ item = new CustomItem(0, 0, 100, 100);
+ effect = new CustomEffect;
+ item->setGraphicsEffect(effect);
+ scene->addItem(item);
+ view = new QGraphicsView(scene);
+ view->show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(view);
+#endif
+ QTest::qWait(200);
+}
+
+void tst_QGraphicsEffectSource::cleanupTestCase()
+{
+ delete view;
+}
+
+void tst_QGraphicsEffectSource::init()
+{
+ QVERIFY(effect);
+ QVERIFY(item);
+ QVERIFY(effect->source());
+ effect->reset();
+ effect->storeDeviceDependentStuff = false;
+ effect->doNothingInDraw = false;
+ item->reset();
+}
+
+void tst_QGraphicsEffectSource::graphicsItem()
+{
+ QVERIFY(effect->source());
+ QCOMPARE(effect->source()->graphicsItem(), (const QGraphicsItem*)item);
+}
+
+void tst_QGraphicsEffectSource::styleOption()
+{
+ // We don't have style options unless the source is drawing.
+ QVERIFY(effect->source());
+ QVERIFY(!effect->source()->styleOption());
+
+ // Trigger an update and check that the style option in QGraphicsEffect::draw
+ // was the same as the one in QGraphicsItem::paint.
+ QCOMPARE(item->numRepaints, 0);
+ QCOMPARE(effect->numRepaints, 0);
+ item->update();
+ QTRY_COMPARE(item->numRepaints, 1);
+ QTRY_COMPARE(effect->numRepaints, 1);
+}
+
+void tst_QGraphicsEffectSource::isPixmap()
+{
+ // Current source is a CustomItem (which is not a pixmap item).
+ QVERIFY(!effect->source()->isPixmap());
+
+ // Make sure isPixmap() returns true for QGraphicsPixmapItem.
+ QGraphicsPixmapItem *pixmapItem = new QGraphicsPixmapItem;
+ CustomEffect *anotherEffect = new CustomEffect;
+ pixmapItem->setGraphicsEffect(anotherEffect);
+ QVERIFY(anotherEffect->source());
+ QCOMPARE(anotherEffect->source()->graphicsItem(), static_cast<const QGraphicsItem *>(pixmapItem));
+ QVERIFY(anotherEffect->source()->isPixmap());
+ delete pixmapItem;
+}
+
+void tst_QGraphicsEffectSource::draw()
+{
+ // The source can only draw as a result of QGraphicsEffect::draw.
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsEffectSource::draw: Can only begin as a result of QGraphicsEffect::draw");
+ QPixmap dummyPixmap(10, 10);
+ QPainter dummyPainter(&dummyPixmap);
+ effect->source()->draw(&dummyPainter);
+}
+
+void tst_QGraphicsEffectSource::update()
+{
+ QCOMPARE(item->numRepaints, 0);
+ QCOMPARE(effect->numRepaints, 0);
+
+ effect->source()->update();
+
+ QTRY_COMPARE(item->numRepaints, 1);
+ QTRY_COMPARE(effect->numRepaints, 1);
+}
+
+void tst_QGraphicsEffectSource::boundingRect()
+{
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context");
+ QCOMPARE(effect->source()->boundingRect(Qt::DeviceCoordinates), QRectF());
+
+ QRectF itemBoundingRect = item->boundingRect();
+ if (!item->children().isEmpty())
+ itemBoundingRect |= item->childrenBoundingRect();
+
+ // We can at least check that the device bounding rect was correct in QGraphicsEffect::draw.
+ effect->storeDeviceDependentStuff = true;
+ effect->source()->update();
+ const QTransform deviceTransform = item->deviceTransform(view->viewportTransform());
+ QTRY_COMPARE(effect->sourceDeviceBoundingRect, deviceTransform.mapRect(itemBoundingRect));
+
+ // Bounding rect in logical coordinates is of course fine.
+ QTRY_COMPARE(effect->source()->boundingRect(Qt::LogicalCoordinates), itemBoundingRect);
+ // Make sure default value is Qt::LogicalCoordinates.
+ QTRY_COMPARE(effect->source()->boundingRect(), itemBoundingRect);
+}
+
+void tst_QGraphicsEffectSource::clippedBoundingRect()
+{
+ QRectF itemBoundingRect = item->boundingRect();
+ item->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+
+ QGraphicsRectItem *child = new QGraphicsRectItem(-1000, -1000, 2000, 2000);
+ child->setBrush(Qt::red);
+ child->setParentItem(item);
+
+ effect->storeDeviceDependentStuff = true;
+ effect->source()->update();
+ QTRY_COMPARE(effect->source()->boundingRect(Qt::LogicalCoordinates), itemBoundingRect);
+}
+
+void tst_QGraphicsEffectSource::deviceRect()
+{
+ effect->storeDeviceDependentStuff = true;
+ effect->source()->update();
+ QTRY_COMPARE(effect->deviceRect, view->viewport()->rect());
+}
+
+void tst_QGraphicsEffectSource::pixmap()
+{
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
+ QCOMPARE(effect->source()->pixmap(Qt::DeviceCoordinates), QPixmap());
+
+ // We can at least verify a valid pixmap from QGraphicsEffect::draw.
+ effect->storeDeviceDependentStuff = true;
+ effect->source()->update();
+ QTRY_VERIFY(!effect->deviceCoordinatesPixmap.isNull());
+
+ // Pixmaps in logical coordinates we can do fine.
+ QPixmap pixmap1 = effect->source()->pixmap(Qt::LogicalCoordinates);
+ QVERIFY(!pixmap1.isNull());
+
+ // Make sure default value is Qt::LogicalCoordinates.
+ QPixmap pixmap2 = effect->source()->pixmap();
+ QCOMPARE(pixmap1, pixmap2);
+}
+
+class PaddingEffect : public QGraphicsEffect
+{
+public:
+ PaddingEffect(QObject *parent) : QGraphicsEffect(parent)
+ {
+ }
+
+ QRectF boundingRectFor(const QRectF &src) const {
+ return src.adjusted(-10, -10, 10, 10);
+ }
+
+ void draw(QPainter *) {
+ pix = source()->pixmap(coordinateMode, &offset, padMode);
+ }
+
+ QPixmap pix;
+ QPoint offset;
+ QGraphicsEffect::PixmapPadMode padMode;
+ Qt::CoordinateSystem coordinateMode;
+};
+
+void tst_QGraphicsEffectSource::pixmapPadding_data()
+{
+ QTest::addColumn<int>("coordinateMode");
+ QTest::addColumn<int>("padMode");
+ QTest::addColumn<QSize>("size");
+ QTest::addColumn<QPoint>("offset");
+ QTest::addColumn<uint>("ulPixel");
+
+ QTest::newRow("log,nopad") << int(Qt::LogicalCoordinates)
+ << int(QGraphicsEffect::NoPad)
+ << QSize(10, 10) << QPoint(0, 0)
+ << 0xffff0000u;
+
+ QTest::newRow("log,transparent") << int(Qt::LogicalCoordinates)
+ << int(QGraphicsEffect::PadToTransparentBorder)
+ << QSize(14, 14) << QPoint(-2, -2)
+ << 0x00000000u;
+
+ QTest::newRow("log,effectrect") << int(Qt::LogicalCoordinates)
+ << int(QGraphicsEffect::PadToEffectiveBoundingRect)
+ << QSize(20, 20) << QPoint(-5, -5)
+ << 0x00000000u;
+
+ QTest::newRow("dev,nopad") << int(Qt::DeviceCoordinates)
+ << int(QGraphicsEffect::NoPad)
+ << QSize(20, 20) << QPoint(40, 40)
+ << 0xffff0000u;
+
+ QTest::newRow("dev,transparent") << int(Qt::DeviceCoordinates)
+ << int(QGraphicsEffect::PadToTransparentBorder)
+ << QSize(24, 24) << QPoint(38, 38)
+ << 0x00000000u;
+
+ QTest::newRow("dev,effectrect") << int(Qt::DeviceCoordinates)
+ << int(QGraphicsEffect::PadToEffectiveBoundingRect)
+ << QSize(40, 40) << QPoint(30, 30)
+ << 0x00000000u;
+
+}
+
+void tst_QGraphicsEffectSource::pixmapPadding()
+{
+ QPixmap dummyTarget(100, 100);
+ QPainter dummyPainter(&dummyTarget);
+ dummyPainter.translate(40, 40);
+ dummyPainter.scale(2, 2);
+
+ QPixmap pm(10, 10);
+ pm.fill(Qt::red);
+
+ QGraphicsScene *scene = new QGraphicsScene();
+ PaddingEffect *effect = new PaddingEffect(scene);
+ QGraphicsPixmapItem *pmItem = new QGraphicsPixmapItem(pm);
+ scene->addItem(pmItem);
+ pmItem->setGraphicsEffect(effect);
+
+ QFETCH(int, coordinateMode);
+ QFETCH(int, padMode);
+ QFETCH(QPoint, offset);
+ QFETCH(QSize, size);
+ QFETCH(uint, ulPixel);
+
+ effect->padMode = (QGraphicsEffect::PixmapPadMode) padMode;
+ effect->coordinateMode = (Qt::CoordinateSystem) coordinateMode;
+
+ scene->render(&dummyPainter, scene->itemsBoundingRect(), scene->itemsBoundingRect());
+
+ QCOMPARE(effect->pix.size(), size);
+ QCOMPARE(effect->offset, offset);
+ QCOMPARE(effect->pix.toImage().pixel(0, 0), ulPixel);
+
+ // ### Fix corruption in scene destruction, then enable...
+ // delete scene;
+}
+
+QTEST_MAIN(tst_QGraphicsEffectSource)
+#include "tst_qgraphicseffectsource.moc"
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicsgridlayout/.gitignore b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/.gitignore
new file mode 100644
index 0000000000..e3a8cc317c
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/.gitignore
@@ -0,0 +1 @@
+tst_qgraphicsgridlayout
diff --git a/tests/auto/widgets/graphicsview/qgraphicsgridlayout/qgraphicsgridlayout.pro b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/qgraphicsgridlayout.pro
new file mode 100644
index 0000000000..7db7c1ae6f
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/qgraphicsgridlayout.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+
+QT += widgets
+SOURCES += tst_qgraphicsgridlayout.cpp
+CONFIG += parallel_test
+contains(QT_CONFIG,xcb):qpa:CONFIG+=insignificant_test # QTBUG-20756 crashes on qpa, xcb
diff --git a/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp
new file mode 100644
index 0000000000..e9d9cb67bb
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp
@@ -0,0 +1,3465 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.1, 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qgraphicsgridlayout.h>
+#include <qgraphicswidget.h>
+#include <qgraphicsscene.h>
+#include <qgraphicsview.h>
+
+class tst_QGraphicsGridLayout : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void qgraphicsgridlayout_data();
+ void qgraphicsgridlayout();
+ void addItem_data();
+ void addItem();
+#ifndef Q_WS_MAC
+ void alignment_data();
+ void alignment();
+#endif
+ void alignment2();
+ void alignment2_data();
+#ifndef Q_WS_MAC
+ void columnAlignment_data();
+ void columnAlignment();
+#endif
+ void columnCount_data();
+ void columnCount();
+ void columnMaximumWidth_data();
+ void columnMaximumWidth();
+ void columnMinimumWidth_data();
+ void columnMinimumWidth();
+ void columnPreferredWidth_data();
+ void columnPreferredWidth();
+ void setColumnFixedWidth();
+ void columnSpacing();
+ void columnStretchFactor();
+ void count();
+ void contentsMargins();
+ void horizontalSpacing_data();
+ void horizontalSpacing();
+ void itemAt();
+ void removeAt();
+ void removeItem();
+ void rowAlignment_data();
+ void rowAlignment();
+ void rowCount_data();
+ void rowCount();
+ void rowMaximumHeight_data();
+ void rowMaximumHeight();
+ void rowMinimumHeight_data();
+ void rowMinimumHeight();
+ void rowPreferredHeight_data();
+ void rowPreferredHeight();
+ void rowSpacing();
+ void rowStretchFactor_data();
+ void rowStretchFactor();
+ void setColumnSpacing_data();
+ void setColumnSpacing();
+ void setGeometry_data();
+ void setGeometry();
+ void setRowFixedHeight();
+ void setRowSpacing_data();
+ void setRowSpacing();
+ void setSpacing_data();
+ void setSpacing();
+ void sizeHint_data();
+ void sizeHint();
+ void verticalSpacing_data();
+ void verticalSpacing();
+ void layoutDirection_data();
+ void layoutDirection();
+ void removeLayout();
+ void defaultStretchFactors_data();
+ void defaultStretchFactors();
+ void geometries_data();
+ void geometries();
+ void avoidRecursionInInsertItem();
+ void styleInfoLeak();
+ void task236367_maxSizeHint();
+ void spanningItem2x2_data();
+ void spanningItem2x2();
+ void spanningItem2x3_data();
+ void spanningItem2x3();
+ void spanningItem();
+ void heightForWidth();
+ void widthForHeight();
+ void heightForWidthWithSpanning();
+ void stretchAndHeightForWidth();
+ void testDefaultAlignment();
+};
+
+class RectWidget : public QGraphicsWidget
+{
+public:
+ RectWidget(QGraphicsItem *parent = 0) : QGraphicsWidget(parent), m_fnConstraint(0) {}
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+ painter->drawRoundRect(rect());
+ painter->drawLine(rect().topLeft(), rect().bottomRight());
+ painter->drawLine(rect().bottomLeft(), rect().topRight());
+ }
+
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const
+ {
+ if (constraint.width() < 0 && constraint.height() < 0 && m_sizeHints[which].isValid()) {
+ return m_sizeHints[which];
+ }
+ if (m_fnConstraint) {
+ return m_fnConstraint(which, constraint);
+ }
+ return QGraphicsWidget::sizeHint(which, constraint);
+ }
+
+ void setSizeHint(Qt::SizeHint which, const QSizeF &size) {
+ m_sizeHints[which] = size;
+ updateGeometry();
+ }
+
+ void setConstraintFunction(QSizeF (*fnConstraint)(Qt::SizeHint, const QSizeF &)) {
+ m_fnConstraint = fnConstraint;
+ }
+
+ QSizeF m_sizeHints[Qt::NSizeHints];
+ QSizeF (*m_fnConstraint)(Qt::SizeHint, const QSizeF &);
+
+};
+
+struct ItemDesc
+{
+ ItemDesc(int row, int col)
+ : m_pos(qMakePair(row, col)),
+ m_rowSpan(1),
+ m_colSpan(1),
+ m_sizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred)),
+ m_align(0),
+ m_fnConstraint(0)
+ {
+ }
+
+ ItemDesc &rowSpan(int span) {
+ m_rowSpan = span;
+ return (*this);
+ }
+
+ ItemDesc &colSpan(int span) {
+ m_colSpan = span;
+ return (*this);
+ }
+
+ ItemDesc &sizePolicy(const QSizePolicy &sp) {
+ m_sizePolicy = sp;
+ return (*this);
+ }
+
+ ItemDesc &sizePolicy(QSizePolicy::Policy horAndVer) {
+ m_sizePolicy = QSizePolicy(horAndVer, horAndVer);
+ return (*this);
+ }
+
+ ItemDesc &sizePolicyH(QSizePolicy::Policy hor) {
+ m_sizePolicy.setHorizontalPolicy(hor);
+ return (*this);
+ }
+
+ ItemDesc &sizePolicyV(QSizePolicy::Policy ver) {
+ m_sizePolicy.setVerticalPolicy(ver);
+ return (*this);
+ }
+
+ ItemDesc &sizePolicy(QSizePolicy::Policy hor, QSizePolicy::Policy ver) {
+ m_sizePolicy = QSizePolicy(hor, ver);
+ return (*this);
+ }
+
+ ItemDesc &sizeHint(Qt::SizeHint which, const QSizeF &sh) {
+ m_sizeHints[which] = sh;
+ return (*this);
+ }
+
+ ItemDesc &preferredSizeHint(const QSizeF &sh) {
+ m_sizeHints[Qt::PreferredSize] = sh;
+ return (*this);
+ }
+
+ ItemDesc &minSize(const QSizeF &sz) {
+ m_sizes[Qt::MinimumSize] = sz;
+ return (*this);
+ }
+ ItemDesc &preferredSize(const QSizeF &sz) {
+ m_sizes[Qt::PreferredSize] = sz;
+ return (*this);
+ }
+ ItemDesc &maxSize(const QSizeF &sz) {
+ m_sizes[Qt::MaximumSize] = sz;
+ return (*this);
+ }
+
+ ItemDesc &alignment(Qt::Alignment alignment) {
+ m_align = alignment;
+ return (*this);
+ }
+
+ ItemDesc &dynamicConstraint(QSizeF (*fnConstraint)(Qt::SizeHint, const QSizeF &),
+ Qt::Orientation orientation) {
+ m_fnConstraint = fnConstraint;
+ m_constraintOrientation = orientation;
+ return (*this);
+ }
+
+ void apply(QGraphicsGridLayout *layout, QGraphicsWidget *item) {
+ QSizePolicy sp = m_sizePolicy;
+ if (m_fnConstraint) {
+ sp.setHeightForWidth(m_constraintOrientation == Qt::Vertical);
+ sp.setWidthForHeight(m_constraintOrientation == Qt::Horizontal);
+ }
+
+ item->setSizePolicy(sp);
+ for (int i = 0; i < Qt::NSizeHints; ++i) {
+ if (!m_sizes[i].isValid())
+ continue;
+ switch ((Qt::SizeHint)i) {
+ case Qt::MinimumSize:
+ item->setMinimumSize(m_sizes[i]);
+ break;
+ case Qt::PreferredSize:
+ item->setPreferredSize(m_sizes[i]);
+ break;
+ case Qt::MaximumSize:
+ item->setMaximumSize(m_sizes[i]);
+ break;
+ default:
+ qWarning("not implemented");
+ break;
+ }
+ }
+
+ layout->addItem(item, m_pos.first, m_pos.second, m_rowSpan, m_colSpan);
+ layout->setAlignment(item, m_align);
+ }
+
+ void apply(QGraphicsGridLayout *layout, RectWidget *item) {
+ for (int i = 0; i < Qt::NSizeHints; ++i)
+ item->setSizeHint((Qt::SizeHint)i, m_sizeHints[i]);
+ item->setConstraintFunction(m_fnConstraint);
+ apply(layout, static_cast<QGraphicsWidget*>(item));
+ }
+
+//private:
+ QPair<int,int> m_pos; // row,col
+ int m_rowSpan;
+ int m_colSpan;
+ QSizePolicy m_sizePolicy;
+ QSizeF m_sizeHints[Qt::NSizeHints];
+ QSizeF m_sizes[Qt::NSizeHints];
+ Qt::Alignment m_align;
+
+ Qt::Orientation m_constraintOrientation;
+ QSizeF (*m_fnConstraint)(Qt::SizeHint, const QSizeF &);
+};
+
+typedef QList<ItemDesc> ItemList;
+Q_DECLARE_METATYPE(ItemList);
+
+typedef QList<QSizeF> SizeList;
+Q_DECLARE_METATYPE(SizeList);
+
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_QGraphicsGridLayout::initTestCase()
+{
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_QGraphicsGridLayout::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_QGraphicsGridLayout::init()
+{
+#ifdef Q_OS_WINCE //disable magic for WindowsCE
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+}
+
+// This will be called after every test function.
+void tst_QGraphicsGridLayout::cleanup()
+{
+}
+
+void tst_QGraphicsGridLayout::qgraphicsgridlayout_data()
+{
+}
+
+void tst_QGraphicsGridLayout::qgraphicsgridlayout()
+{
+ QGraphicsGridLayout layout;
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsGridLayout::addItem: invalid row span/column span: 0");
+ layout.addItem(0, 0, 0, 0, 0);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsGridLayout::addItem: cannot add null item");
+ layout.addItem(0, 0, 0);
+ layout.alignment(0);
+ layout.columnAlignment(0);
+ layout.columnCount();
+ layout.columnMaximumWidth(0);
+ layout.columnMinimumWidth(0);
+ layout.columnPreferredWidth(0);
+ layout.columnSpacing(0);
+ layout.columnStretchFactor(0);
+ layout.count();
+ layout.horizontalSpacing();
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsGridLayout::itemAt: invalid row, column 0, 0");
+ layout.itemAt(0, 0);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsGridLayout::itemAt: invalid index 0");
+ layout.itemAt(0);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsGridLayout::removeAt: invalid index 0");
+ layout.removeAt(0);
+ layout.rowAlignment(0);
+ layout.rowCount();
+ layout.rowMaximumHeight(0);
+ layout.rowMinimumHeight(0);
+ layout.rowPreferredHeight(0);
+ layout.rowSpacing(0);
+ layout.rowStretchFactor(0);
+ layout.setAlignment(0, Qt::AlignRight);
+ layout.setColumnAlignment(0, Qt::AlignRight);
+ layout.setColumnFixedWidth(0, 0);
+ layout.setColumnMaximumWidth(0, 0);
+ layout.setColumnMinimumWidth(0, 0);
+ layout.setColumnPreferredWidth(0, 0);
+ layout.setColumnSpacing(0, 0);
+ layout.setColumnStretchFactor(0, 0);
+ layout.setGeometry(QRectF());
+ layout.setHorizontalSpacing(0);
+ layout.setRowAlignment(0, 0);
+ layout.setRowFixedHeight(0, 0);
+ layout.setRowMaximumHeight(0, 0);
+ layout.setRowMinimumHeight(0, 0);
+ layout.setRowPreferredHeight(0, 0);
+ layout.setRowSpacing(0, 0);
+ layout.setRowStretchFactor(0, 0);
+ layout.setSpacing(0);
+ layout.setVerticalSpacing(0);
+ layout.sizeHint(Qt::MinimumSize);
+ layout.verticalSpacing();
+}
+
+static void populateLayout(QGraphicsGridLayout *gridLayout, int width, int height, bool hasHeightForWidth = false)
+{
+ for (int y = 0; y < height; ++y) {
+ for (int x = 0; x < width; ++x) {
+ QGraphicsWidget *item = new RectWidget();
+ item->setMinimumSize(10, 10);
+ item->setPreferredSize(25, 25);
+ item->setMaximumSize(50, 50);
+ gridLayout->addItem(item, y, x);
+ QSizePolicy policy = item->sizePolicy();
+ policy.setHeightForWidth(hasHeightForWidth);
+ item->setSizePolicy(policy);
+ }
+ }
+}
+
+
+/** populates \a gridLayout with a 3x2 layout:
+ * +----+----+----+
+ * |+---|---+|xxxx|
+ * ||span=2 ||hole|
+ * |+---|---+|xxxx|
+ * +----+----+----+
+ * |xxxx|+---|---+|
+ * |hole||span=2 ||
+ * |xxxx|+---|---+|
+ * +----+----+----+
+ */
+static void populateLayoutWithSpansAndHoles(QGraphicsGridLayout *gridLayout, bool hasHeightForWidth = false)
+{
+ QGraphicsWidget *item = new RectWidget();
+ item->setMinimumSize(10, 10);
+ item->setPreferredSize(25, 25);
+ item->setMaximumSize(50, 50);
+ QSizePolicy sizepolicy = item->sizePolicy();
+ sizepolicy.setHeightForWidth(hasHeightForWidth);
+ item->setSizePolicy(sizepolicy);
+ gridLayout->addItem(item, 0, 0, 1, 2);
+
+ item = new RectWidget();
+ item->setMinimumSize(10, 10);
+ item->setPreferredSize(25, 25);
+ item->setMaximumSize(50, 50);
+ item->setSizePolicy(sizepolicy);
+ gridLayout->addItem(item, 1, 1, 1, 2);
+}
+
+Q_DECLARE_METATYPE(Qt::Alignment)
+void tst_QGraphicsGridLayout::addItem_data()
+{
+ QTest::addColumn<int>("row");
+ QTest::addColumn<int>("column");
+ QTest::addColumn<int>("rowSpan");
+ QTest::addColumn<int>("columnSpan");
+ QTest::addColumn<Qt::Alignment>("alignment");
+
+ for (int a = -1; a < 3; ++a) {
+ for (int b = -1; b < 2; ++b) {
+ for (int c = -1; c < 2; ++c) {
+ for (int d = -1; d < 2; ++d) {
+ for (int e = 0; e < 9; ++e) {
+ int row = a;
+ int column = b;
+ int rowSpan = c;
+ int columnSpan = d;
+ QString name = QString::fromAscii("(%1,%2,%3,%4").arg(a).arg(b).arg(c).arg(d);
+ Qt::Alignment alignment = Qt::AlignLeft;
+ QTest::newRow(name.toLatin1()) << row << column << rowSpan << columnSpan << alignment;
+ }}}}}
+}
+
+// public void addItem(QGraphicsLayoutItem* item, int row, int column, int rowSpan, int columnSpan, Qt::Alignment alignment = 0)
+void tst_QGraphicsGridLayout::addItem()
+{
+ QFETCH(int, row);
+ QFETCH(int, column);
+ QFETCH(int, rowSpan);
+ QFETCH(int, columnSpan);
+ QFETCH(Qt::Alignment, alignment);
+
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+
+ QGraphicsWidget *wid = new QGraphicsWidget;
+ if (row < 0 || column < 0) {
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsGridLayout::addItem: invalid row/column: -1");
+ } else if (rowSpan < 1 || columnSpan < 1) {
+ char buf[1024];
+ ::qsnprintf(buf, sizeof(buf), "QGraphicsGridLayout::addItem: invalid row span/column span: %d",
+ rowSpan < 1 ? rowSpan : columnSpan);
+ QTest::ignoreMessage(QtWarningMsg, buf);
+ }
+ layout->addItem(wid, row, column, rowSpan, columnSpan, alignment);
+
+ delete layout;
+}
+
+// Resizing a QGraphicsWidget to effectiveSizeHint(Qt::MaximumSize) is currently not supported on mac.
+#ifndef Q_WS_MAC
+void tst_QGraphicsGridLayout::alignment_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+
+// public Qt::Alignment alignment(QGraphicsLayoutItem* item) const
+void tst_QGraphicsGridLayout::alignment()
+{
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2, hasHeightForWidth);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ view.show();
+ widget->show();
+ widget->resize(widget->effectiveSizeHint(Qt::PreferredSize));
+ QApplication::processEvents();
+ // no alignment (the default)
+ QCOMPARE(layout->itemAt(0, 0)->geometry().left(), 0.0);
+ QCOMPARE(layout->itemAt(0, 0)->geometry().right(), layout->itemAt(0, 1)->geometry().left());
+ QCOMPARE(layout->itemAt(0, 1)->geometry().left(), 25.0);
+ QCOMPARE(layout->itemAt(0, 1)->geometry().right(), layout->itemAt(0, 2)->geometry().left());
+ QCOMPARE(layout->itemAt(0, 2)->geometry().left(), 50.0);
+ QCOMPARE(layout->itemAt(0, 2)->geometry().right(), 75.0);
+
+ QCOMPARE(layout->itemAt(1, 0)->geometry().left(), 0.0);
+ QCOMPARE(layout->itemAt(1, 0)->geometry().right(), layout->itemAt(1, 1)->geometry().left());
+ QCOMPARE(layout->itemAt(1, 1)->geometry().left(), 25.0);
+ QCOMPARE(layout->itemAt(1, 1)->geometry().right(), layout->itemAt(1, 2)->geometry().left());
+ QCOMPARE(layout->itemAt(1, 2)->geometry().left(), 50.0);
+ QCOMPARE(layout->itemAt(1, 2)->geometry().right(), 75.0);
+
+ QCOMPARE(layout->itemAt(0, 0)->geometry().top(), 0.0);
+ QCOMPARE(layout->itemAt(0, 0)->geometry().bottom(), layout->itemAt(1, 0)->geometry().top());
+ QCOMPARE(layout->itemAt(1, 0)->geometry().top(), 25.0);
+ QCOMPARE(layout->itemAt(1, 0)->geometry().bottom(), 50.0);
+
+ // align first column left, second hcenter, third right
+ layout->setColumnMinimumWidth(0, 100);
+ layout->setAlignment(layout->itemAt(0,0), Qt::AlignLeft);
+ layout->setAlignment(layout->itemAt(1,0), Qt::AlignLeft);
+ layout->setColumnMinimumWidth(1, 100);
+ layout->setAlignment(layout->itemAt(0,1), Qt::AlignHCenter);
+ layout->setAlignment(layout->itemAt(1,1), Qt::AlignHCenter);
+ layout->setColumnMinimumWidth(2, 100);
+ layout->setAlignment(layout->itemAt(0,2), Qt::AlignRight);
+ layout->setAlignment(layout->itemAt(1,2), Qt::AlignRight);
+
+ widget->resize(widget->effectiveSizeHint(Qt::MaximumSize));
+ QApplication::processEvents();
+
+ QCOMPARE(layout->itemAt(0,0)->geometry(), QRectF(0, 0, 50, 50));
+ QCOMPARE(layout->itemAt(1,0)->geometry(), QRectF(0, 50, 50, 50));
+ QCOMPARE(layout->itemAt(0,1)->geometry(), QRectF(125, 0, 50, 50));
+ QCOMPARE(layout->itemAt(1,1)->geometry(), QRectF(125, 50, 50, 50));
+ QCOMPARE(layout->itemAt(0,2)->geometry(), QRectF(250, 0, 50, 50));
+ QCOMPARE(layout->itemAt(1,2)->geometry(), QRectF(250, 50, 50, 50));
+
+ delete widget;
+}
+#endif
+
+// Resizing a QGraphicsWidget to effectiveSizeHint(Qt::MaximumSize) is currently not supported on mac.
+#ifndef Q_WS_MAC
+void tst_QGraphicsGridLayout::columnAlignment_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+
+// public void setColumnAlignment(int column, Qt::Alignment alignment)
+// public Qt::Alignment columnAlignment(int column) const
+void tst_QGraphicsGridLayout::columnAlignment()
+{
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2, hasHeightForWidth);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(1);
+ widget->setContentsMargins(0, 0, 0, 0);
+
+ layout->setColumnMinimumWidth(0, 100);
+ layout->setColumnMinimumWidth(1, 100);
+ layout->setColumnMinimumWidth(2, 100);
+
+ view.resize(450,150);
+ widget->resize(widget->effectiveSizeHint(Qt::MaximumSize));
+ view.show();
+ widget->show();
+ QApplication::sendPostedEvents(0, 0);
+ // Check default
+ QCOMPARE(layout->columnAlignment(0), 0);
+ QCOMPARE(layout->columnAlignment(1), 0);
+ QCOMPARE(layout->columnAlignment(2), 0);
+
+ layout->setColumnAlignment(0, Qt::AlignLeft);
+ layout->setColumnAlignment(1, Qt::AlignHCenter);
+ layout->setColumnAlignment(2, Qt::AlignRight);
+
+ // see if item alignment takes preference over columnAlignment
+ layout->setAlignment(layout->itemAt(1,0), Qt::AlignHCenter);
+ layout->setAlignment(layout->itemAt(1,1), Qt::AlignRight);
+ layout->setAlignment(layout->itemAt(1,2), Qt::AlignLeft);
+
+ QApplication::sendPostedEvents(0, 0); // process LayoutRequest
+ /*
+ +----------+------------+---------+
+ | Left | HCenter | Right |
+ +----------+------------+---------+
+ | HCenter | Right | Left |
+ +---------------------------------+
+ */
+ QCOMPARE(layout->itemAt(0,0)->geometry(), QRectF(0, 0, 50, 50));
+ QCOMPARE(layout->itemAt(1,0)->geometry(), QRectF(25, 51, 50, 50)); // item is king
+ QCOMPARE(layout->itemAt(0,1)->geometry(), QRectF(126, 0, 50, 50));
+ QCOMPARE(layout->itemAt(1,1)->geometry(), QRectF(151, 51, 50, 50)); // item is king
+ QCOMPARE(layout->itemAt(0,2)->geometry(), QRectF(252, 0, 50, 50));
+ QCOMPARE(layout->itemAt(1,2)->geometry(), QRectF(202, 51, 50, 50)); // item is king
+
+ delete widget;
+}
+#endif
+
+void tst_QGraphicsGridLayout::columnCount_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+// public int columnCount() const
+void tst_QGraphicsGridLayout::columnCount()
+{
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+ widget->setContentsMargins(0, 0, 0, 0);
+
+ view.show();
+ widget->show();
+ QApplication::processEvents();
+
+ QCOMPARE(layout->columnCount(), 0);
+ layout->addItem(new RectWidget(widget), 0, 0);
+ QCOMPARE(layout->columnCount(), 1);
+ layout->addItem(new RectWidget(widget), 1, 1);
+ QCOMPARE(layout->columnCount(), 2);
+ layout->addItem(new RectWidget(widget), 0, 2);
+ QCOMPARE(layout->columnCount(), 3);
+ layout->addItem(new RectWidget(widget), 1, 0);
+ QCOMPARE(layout->columnCount(), 3);
+ layout->addItem(new RectWidget(widget), 0, 1);
+ QCOMPARE(layout->columnCount(), 3);
+ layout->addItem(new RectWidget(widget), 1, 2);
+ QCOMPARE(layout->columnCount(), 3);
+
+ // ### Talk with Jasmin. Not sure if removeAt() should adjust columnCount().
+ widget->setLayout(0);
+ layout = new QGraphicsGridLayout();
+ populateLayout(layout, 3, 2, hasHeightForWidth);
+ QCOMPARE(layout->columnCount(), 3);
+ layout->removeAt(5);
+ layout->removeAt(3);
+ QCOMPARE(layout->columnCount(), 3);
+ layout->removeAt(1);
+ QCOMPARE(layout->columnCount(), 3);
+ layout->removeAt(0);
+ QCOMPARE(layout->columnCount(), 3);
+ layout->removeAt(0);
+ QCOMPARE(layout->columnCount(), 2);
+
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::columnMaximumWidth_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+// public qreal columnMaximumWidth(int column) const
+void tst_QGraphicsGridLayout::columnMaximumWidth()
+{
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2, hasHeightForWidth);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ QCOMPARE(layout->minimumSize(), QSizeF(10+10+10, 10+10));
+ QCOMPARE(layout->preferredSize(), QSizeF(25+25+25, 25+25));
+ QCOMPARE(layout->maximumSize(), QSizeF(50+50+50, 50+50));
+
+ // should at least be a very large number
+ QVERIFY(layout->columnMaximumWidth(0) >= 10000);
+ QCOMPARE(layout->columnMaximumWidth(0), layout->columnMaximumWidth(1));
+ QCOMPARE(layout->columnMaximumWidth(1), layout->columnMaximumWidth(2));
+ layout->setColumnMaximumWidth(0, 20);
+ layout->setColumnMaximumWidth(2, 60);
+
+ QCOMPARE(layout->minimumSize(), QSizeF(10+10+10, 10+10));
+ QCOMPARE(layout->preferredSize(), QSizeF(20+25+25, 25+25));
+ QCOMPARE(layout->maximumSize(), QSizeF(20+50+60, 50+50));
+ QCOMPARE(layout->maximumSize(), widget->maximumSize());
+
+ widget->resize(widget->effectiveSizeHint(Qt::PreferredSize));
+ layout->activate();
+
+ QCOMPARE(layout->itemAt(0,0)->geometry(), QRectF(0, 0, 20, 25));
+ QCOMPARE(layout->itemAt(1,0)->geometry(), QRectF(0, 25, 20, 25));
+ QCOMPARE(layout->itemAt(0,1)->geometry(), QRectF(20, 0, 25, 25));
+ QCOMPARE(layout->itemAt(1,1)->geometry(), QRectF(20, 25, 25, 25));
+ QCOMPARE(layout->itemAt(0,2)->geometry(), QRectF(45, 0, 25, 25));
+ QCOMPARE(layout->itemAt(1,2)->geometry(), QRectF(45, 25, 25, 25));
+
+ layout->setColumnAlignment(2, Qt::AlignCenter);
+ widget->resize(widget->effectiveSizeHint(Qt::MaximumSize));
+ layout->activate();
+ QCOMPARE(layout->geometry(), QRectF(0,0,20+50+60, 50+50));
+ QCOMPARE(layout->itemAt(0,0)->geometry(), QRectF(0, 0, 20, 50));
+ QCOMPARE(layout->itemAt(1,0)->geometry(), QRectF(0, 50, 20, 50));
+ QCOMPARE(layout->itemAt(0,1)->geometry(), QRectF(20, 0, 50, 50));
+ QCOMPARE(layout->itemAt(1,1)->geometry(), QRectF(20, 50, 50, 50));
+ QCOMPARE(layout->itemAt(0,2)->geometry(), QRectF(75, 0, 50, 50));
+ QCOMPARE(layout->itemAt(1,2)->geometry(), QRectF(75, 50, 50, 50));
+
+ for (int i = 0; i < layout->count(); i++)
+ layout->setAlignment(layout->itemAt(i), Qt::AlignRight | Qt::AlignBottom);
+ layout->activate();
+ QCOMPARE(layout->itemAt(0,0)->geometry(), QRectF(0, 0, 20, 50));
+ QCOMPARE(layout->itemAt(1,0)->geometry(), QRectF(0, 50, 20, 50));
+ QCOMPARE(layout->itemAt(0,1)->geometry(), QRectF(20, 0, 50, 50));
+ QCOMPARE(layout->itemAt(1,1)->geometry(), QRectF(20, 50, 50, 50));
+ QCOMPARE(layout->itemAt(0,2)->geometry(), QRectF(80, 0, 50, 50));
+ QCOMPARE(layout->itemAt(1,2)->geometry(), QRectF(80, 50, 50, 50));
+ for (int i = 0; i < layout->count(); i++)
+ layout->setAlignment(layout->itemAt(i), Qt::AlignCenter);
+
+ layout->setMaximumSize(layout->maximumSize() + QSizeF(60,60));
+ widget->resize(widget->effectiveSizeHint(Qt::MaximumSize));
+ layout->activate();
+
+ QCOMPARE(layout->itemAt(0,0)->geometry(), QRectF(0, 15, 20, 50));
+ QCOMPARE(layout->itemAt(1,0)->geometry(), QRectF(0, 95, 20, 50));
+ QCOMPARE(layout->itemAt(0,1)->geometry(), QRectF(20+30, 15, 50, 50));
+ QCOMPARE(layout->itemAt(1,1)->geometry(), QRectF(20+30, 95, 50, 50));
+ QCOMPARE(layout->itemAt(0,2)->geometry(), QRectF(20+60+50+5, 15, 50, 50));
+ QCOMPARE(layout->itemAt(1,2)->geometry(), QRectF(20+60+50+5, 95, 50, 50));
+
+ layout->setMaximumSize(layout->preferredSize() + QSizeF(20,20));
+ widget->resize(widget->effectiveSizeHint(Qt::MaximumSize));
+ layout->activate();
+
+ QCOMPARE(layout->itemAt(0,0)->geometry(), QRectF(0, 0, 20, 35));
+ QCOMPARE(layout->itemAt(1,0)->geometry(), QRectF(0, 35, 20, 35));
+ QCOMPARE(layout->itemAt(0,1)->geometry(), QRectF(20, 0, 35, 35));
+ QCOMPARE(layout->itemAt(1,1)->geometry(), QRectF(20, 35, 35, 35));
+ QCOMPARE(layout->itemAt(0,2)->geometry(), QRectF(55, 0, 35, 35));
+ QCOMPARE(layout->itemAt(1,2)->geometry(), QRectF(55, 35, 35, 35));
+
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::columnMinimumWidth_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+// public qreal columnMinimumWidth(int column) const
+void tst_QGraphicsGridLayout::columnMinimumWidth()
+{
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2, hasHeightForWidth);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ // should at least be a very large number
+ QCOMPARE(layout->columnMinimumWidth(0), 0.0);
+ QCOMPARE(layout->columnMinimumWidth(0), layout->columnMinimumWidth(1));
+ QCOMPARE(layout->columnMinimumWidth(1), layout->columnMinimumWidth(2));
+ layout->setColumnMinimumWidth(0, 20);
+ layout->setColumnMinimumWidth(2, 40);
+
+ view.show();
+ widget->show();
+ widget->resize(widget->effectiveSizeHint(Qt::PreferredSize));
+ QApplication::processEvents();
+
+ QCOMPARE(layout->itemAt(0,0)->geometry().width(), 25.0);
+ QCOMPARE(layout->itemAt(1,0)->geometry().width(), 25.0);
+ QCOMPARE(layout->itemAt(0,1)->geometry().width(), 25.0);
+ QCOMPARE(layout->itemAt(1,1)->geometry().width(), 25.0);
+ QCOMPARE(layout->itemAt(0,2)->geometry().width(), 40.0);
+ QCOMPARE(layout->itemAt(1,2)->geometry().width(), 40.0);
+
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::columnPreferredWidth_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+// public qreal columnPreferredWidth(int column) const
+void tst_QGraphicsGridLayout::columnPreferredWidth()
+{
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2, hasHeightForWidth);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ // default preferred width ??
+ QCOMPARE(layout->columnPreferredWidth(0), 0.0);
+ QCOMPARE(layout->columnPreferredWidth(0), layout->columnPreferredWidth(1));
+ QCOMPARE(layout->columnPreferredWidth(1), layout->columnPreferredWidth(2));
+ layout->setColumnPreferredWidth(0, 20);
+ layout->setColumnPreferredWidth(2, 40);
+
+ view.show();
+ widget->show();
+ widget->resize(widget->effectiveSizeHint(Qt::PreferredSize));
+ QApplication::processEvents();
+
+ QCOMPARE(layout->itemAt(0,0)->geometry().width(), 25.0);
+ QCOMPARE(layout->itemAt(1,0)->geometry().width(), 25.0);
+ QCOMPARE(layout->itemAt(0,1)->geometry().width(), 25.0);
+ QCOMPARE(layout->itemAt(1,1)->geometry().width(), 25.0);
+ QCOMPARE(layout->itemAt(0,2)->geometry().width(), 40.0);
+ QCOMPARE(layout->itemAt(1,2)->geometry().width(), 40.0);
+
+ delete widget;
+}
+
+// public void setColumnFixedWidth(int row, qreal height)
+void tst_QGraphicsGridLayout::setColumnFixedWidth()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ layout->setColumnFixedWidth(0, 20);
+ layout->setColumnFixedWidth(2, 40);
+
+ view.show();
+ widget->show();
+ widget->resize(widget->effectiveSizeHint(Qt::PreferredSize));
+ QApplication::processEvents();
+
+ QCOMPARE(layout->itemAt(0,0)->geometry().width(), 20.0);
+ QCOMPARE(layout->itemAt(1,0)->geometry().width(), 20.0);
+ QCOMPARE(layout->itemAt(0,1)->geometry().width(), 25.0);
+ QCOMPARE(layout->itemAt(1,1)->geometry().width(), 25.0);
+ QCOMPARE(layout->itemAt(0,2)->geometry().width(), 40.0);
+ QCOMPARE(layout->itemAt(1,2)->geometry().width(), 40.0);
+
+ delete widget;
+}
+
+// public qreal columnSpacing(int column) const
+void tst_QGraphicsGridLayout::columnSpacing()
+{
+ {
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+ QCOMPARE(layout->columnSpacing(0), 0.0);
+
+ layout->setColumnSpacing(0, 20);
+ view.show();
+ widget->show();
+ widget->resize(widget->effectiveSizeHint(Qt::PreferredSize));
+ QApplication::processEvents();
+
+ QCOMPARE(layout->itemAt(0,0)->geometry().left(), 0.0);
+ QCOMPARE(layout->itemAt(0,0)->geometry().right(), 25.0);
+ QCOMPARE(layout->itemAt(0,1)->geometry().left(), 45.0);
+ QCOMPARE(layout->itemAt(0,1)->geometry().right(), 70.0);
+ QCOMPARE(layout->itemAt(0,2)->geometry().left(), 70.0);
+ QCOMPARE(layout->itemAt(0,2)->geometry().right(), 95.0);
+
+ delete widget;
+ }
+
+ {
+ // don't include items and spacings that was previously part of the layout
+ // (horizontal)
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ populateLayout(layout, 3, 1);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+ layout->setColumnSpacing(0, 10);
+ layout->setColumnSpacing(1, 10);
+ layout->setColumnSpacing(2, 10);
+ layout->setColumnSpacing(3, 10);
+ QCOMPARE(layout->preferredSize(), QSizeF(95, 25));
+ layout->removeAt(2);
+ QCOMPARE(layout->preferredSize(), QSizeF(60, 25));
+ layout->removeAt(1);
+ QCOMPARE(layout->preferredSize(), QSizeF(25, 25));
+ delete layout;
+ }
+ {
+ // don't include items and spacings that was previously part of the layout
+ // (vertical)
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ populateLayout(layout, 2, 2);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+ layout->setColumnSpacing(0, 10);
+ layout->setColumnSpacing(1, 10);
+ layout->setRowSpacing(0, 10);
+ layout->setRowSpacing(1, 10);
+ QCOMPARE(layout->preferredSize(), QSizeF(60, 60));
+ layout->removeAt(3);
+ QCOMPARE(layout->preferredSize(), QSizeF(60, 60));
+ layout->removeAt(2);
+ QCOMPARE(layout->preferredSize(), QSizeF(60, 25));
+ layout->removeAt(1);
+ QCOMPARE(layout->preferredSize(), QSizeF(25, 25));
+ delete layout;
+ }
+
+}
+
+// public int columnStretchFactor(int column) const
+void tst_QGraphicsGridLayout::columnStretchFactor()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ layout->setColumnStretchFactor(0, 1);
+ layout->setColumnStretchFactor(1, 2);
+ layout->setColumnStretchFactor(2, 3);
+ view.show();
+ widget->show();
+ widget->resize(130, 50);
+ QApplication::processEvents();
+
+ QVERIFY(layout->itemAt(0,0)->geometry().width() < layout->itemAt(0,1)->geometry().width());
+ QVERIFY(layout->itemAt(0,1)->geometry().width() < layout->itemAt(0,2)->geometry().width());
+ QVERIFY(layout->itemAt(1,0)->geometry().width() < layout->itemAt(1,1)->geometry().width());
+ QVERIFY(layout->itemAt(1,1)->geometry().width() < layout->itemAt(1,2)->geometry().width());
+
+ delete widget;
+}
+
+
+// public int count() const
+void tst_QGraphicsGridLayout::count()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2);
+ QCOMPARE(layout->count(), 6);
+ layout->removeAt(5);
+ layout->removeAt(3);
+ QCOMPARE(layout->count(), 4);
+ layout->removeAt(1);
+ QCOMPARE(layout->count(), 3);
+ layout->removeAt(0);
+ QCOMPARE(layout->count(), 2);
+ layout->removeAt(0);
+ QCOMPARE(layout->count(), 1);
+ layout->removeAt(0);
+ QCOMPARE(layout->count(), 0);
+
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::horizontalSpacing_data()
+{
+ QTest::addColumn<qreal>("horizontalSpacing");
+ QTest::newRow("zero") << qreal(0.0);
+ QTest::newRow("10") << qreal(10.0);
+}
+
+// public qreal horizontalSpacing() const
+void tst_QGraphicsGridLayout::horizontalSpacing()
+{
+ QFETCH(qreal, horizontalSpacing);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2);
+ layout->setContentsMargins(0, 0, 0, 0);
+ qreal w = layout->sizeHint(Qt::PreferredSize, QSizeF()).width();
+ qreal oldSpacing = layout->horizontalSpacing();
+ if (oldSpacing != -1) {
+ layout->setHorizontalSpacing(horizontalSpacing);
+ QApplication::processEvents();
+ qreal new_w = layout->sizeHint(Qt::PreferredSize, QSizeF()).width();
+ QCOMPARE(new_w, w - (3-1)*(oldSpacing - horizontalSpacing));
+ } else {
+ QSKIP("The current style uses non-uniform layout spacing", SkipAll);
+ }
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::contentsMargins()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ QGraphicsGridLayout *sublayout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ layout->addItem(sublayout,0, 1);
+
+ qreal left, top, right, bottom;
+ // sublayouts have 0 margin
+ sublayout->getContentsMargins(&left, &top, &right, &bottom);
+ QCOMPARE(left, 0.0);
+ QCOMPARE(top, 0.0);
+ QCOMPARE(right, 0.0);
+ QCOMPARE(bottom, 0.0);
+
+ // top level layouts have style dependent margins.
+ // we'll just check if its different from 0. (applies to all our styles)
+ layout->getContentsMargins(&left, &top, &right, &bottom);
+ QVERIFY(left >= 0.0);
+ QVERIFY(top >= 0.0);
+ QVERIFY(right >= 0.0);
+ QVERIFY(bottom >= 0.0);
+
+ delete widget;
+}
+
+// public QGraphicsLayoutItem* itemAt(int index) const
+void tst_QGraphicsGridLayout::itemAt()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayoutWithSpansAndHoles(layout);
+
+ //itemAt(int row, int column)
+ QVERIFY( layout->itemAt(0,0));
+ QVERIFY( layout->itemAt(0,1));
+ QCOMPARE(layout->itemAt(0,2), static_cast<QGraphicsLayoutItem*>(0));
+ QCOMPARE(layout->itemAt(1,0), static_cast<QGraphicsLayoutItem*>(0));
+ QVERIFY( layout->itemAt(1,1));
+ QVERIFY( layout->itemAt(1,2));
+
+
+ //itemAt(int index)
+ for (int i = -2; i < layout->count() + 2; ++i) {
+ if (i >= 0 && i < layout->count()) {
+ QVERIFY(layout->itemAt(i));
+ } else {
+ QTest::ignoreMessage(QtWarningMsg, QString::fromAscii("QGraphicsGridLayout::itemAt: invalid index %1").arg(i).toLatin1().constData());
+ QCOMPARE(layout->itemAt(i), static_cast<QGraphicsLayoutItem*>(0));
+ }
+ }
+ delete widget;
+}
+
+// public void removeAt(int index)
+void tst_QGraphicsGridLayout::removeAt()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2);
+ QCOMPARE(layout->count(), 6);
+ layout->removeAt(5);
+ layout->removeAt(3);
+ QCOMPARE(layout->count(), 4);
+ layout->removeAt(1);
+ QCOMPARE(layout->count(), 3);
+ layout->removeAt(0);
+ QCOMPARE(layout->count(), 2);
+ layout->removeAt(0);
+ QCOMPARE(layout->count(), 1);
+ QGraphicsLayoutItem *item0 = layout->itemAt(0);
+ QCOMPARE(item0->parentLayoutItem(), static_cast<QGraphicsLayoutItem *>(layout));
+ layout->removeAt(0);
+ QCOMPARE(item0->parentLayoutItem(), static_cast<QGraphicsLayoutItem *>(0));
+ QCOMPARE(layout->count(), 0);
+ QTest::ignoreMessage(QtWarningMsg, QString::fromAscii("QGraphicsGridLayout::removeAt: invalid index 0").toLatin1().constData());
+ layout->removeAt(0);
+ QCOMPARE(layout->count(), 0);
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::removeItem()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ scene.addItem(widget);
+ QGraphicsGridLayout *l = new QGraphicsGridLayout();
+ widget->setLayout(l);
+
+ populateLayout(l, 3, 2);
+ QCOMPARE(l->count(), 6);
+ l->removeItem(l->itemAt(5));
+ l->removeItem(l->itemAt(4));
+ QCOMPARE(l->count(), 4);
+
+ // Avoid crashing. Note that the warning message might change in the future.
+ QTest::ignoreMessage(QtWarningMsg, QString::fromAscii("QGraphicsGridLayout::removeAt: invalid index -1").toLatin1().constData());
+ l->removeItem(0);
+ QCOMPARE(l->count(), 4);
+
+ QTest::ignoreMessage(QtWarningMsg, QString::fromAscii("QGraphicsGridLayout::removeAt: invalid index -1").toLatin1().constData());
+ l->removeItem(new QGraphicsWidget);
+ QCOMPARE(l->count(), 4);
+}
+
+void tst_QGraphicsGridLayout::rowAlignment_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+
+// public Qt::Alignment rowAlignment(int row) const
+void tst_QGraphicsGridLayout::rowAlignment()
+{
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 2, 3, hasHeightForWidth);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(1);
+ widget->setContentsMargins(0, 0, 0, 0);
+
+ view.resize(330,450);
+ widget->resize(300, 400);
+ view.show();
+ widget->show();
+ QApplication::sendPostedEvents(0, 0);
+ // Check default
+ QCOMPARE(layout->rowAlignment(0), 0);
+ QCOMPARE(layout->rowAlignment(1), 0);
+ QCOMPARE(layout->rowAlignment(2), 0);
+
+ // make the grids larger than the items, so that alignment kicks in
+ layout->setRowMinimumHeight(0, 100.0);
+ layout->setRowMinimumHeight(1, 100.0);
+ layout->setRowMinimumHeight(2, 100.0);
+ // expand columns also, so we can test combination of horiz and vertical alignment
+ layout->setColumnMinimumWidth(0, 100.0);
+ layout->setColumnMinimumWidth(1, 100.0);
+
+ layout->setRowAlignment(0, Qt::AlignBottom);
+ layout->setRowAlignment(1, Qt::AlignVCenter);
+ layout->setRowAlignment(2, Qt::AlignTop);
+
+ // see if item alignment takes preference over rowAlignment
+ layout->setAlignment(layout->itemAt(0,0), Qt::AlignRight);
+ layout->setAlignment(layout->itemAt(1,0), Qt::AlignTop);
+ layout->setAlignment(layout->itemAt(2,0), Qt::AlignHCenter);
+
+ QApplication::sendPostedEvents(0, 0); // process LayoutRequest
+
+ QCOMPARE(layout->alignment(layout->itemAt(0,0)), Qt::AlignRight); //Qt::AlignRight | Qt::AlignBottom
+ QCOMPARE(layout->itemAt(0,0)->geometry(), QRectF(50, 50, 50, 50));
+ QCOMPARE(layout->rowAlignment(0), Qt::AlignBottom);
+ QCOMPARE(layout->itemAt(0,1)->geometry(), QRectF(101, 50, 50, 50));
+ QCOMPARE(layout->alignment(layout->itemAt(1,0)), Qt::AlignTop);
+ QCOMPARE(layout->itemAt(1,0)->geometry(), QRectF(0, 101, 50, 50));
+ QCOMPARE(layout->rowAlignment(1), Qt::AlignVCenter);
+ QCOMPARE(layout->itemAt(1,1)->geometry(), QRectF(101, 126, 50, 50));
+ QCOMPARE(layout->alignment(layout->itemAt(2,0)), Qt::AlignHCenter);
+ QCOMPARE(layout->itemAt(2,0)->geometry(), QRectF(25, 202, 50, 50));
+ QCOMPARE(layout->rowAlignment(2), Qt::AlignTop);
+ QCOMPARE(layout->itemAt(2,1)->geometry(), QRectF(101,202, 50, 50));
+
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::rowCount_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+
+// public int rowCount() const
+// public int columnCount() const
+void tst_QGraphicsGridLayout::rowCount()
+{
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 2, 3, hasHeightForWidth);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+ widget->setContentsMargins(0, 0, 0, 0);
+ QCOMPARE(layout->rowCount(), 3);
+ QCOMPARE(layout->columnCount(), 2);
+
+ // with spans and holes...
+ widget->setLayout(0);
+ layout = new QGraphicsGridLayout();
+ populateLayoutWithSpansAndHoles(layout, hasHeightForWidth);
+ QCOMPARE(layout->rowCount(), 2);
+ QCOMPARE(layout->columnCount(), 3);
+
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::rowMaximumHeight_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+
+// public qreal rowMaximumHeight(int row) const
+void tst_QGraphicsGridLayout::rowMaximumHeight()
+{
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 2, 3, hasHeightForWidth);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ // should at least be a very large number
+ QVERIFY(layout->rowMaximumHeight(0) >= 10000);
+ QCOMPARE(layout->rowMaximumHeight(0), layout->rowMaximumHeight(1));
+ QCOMPARE(layout->rowMaximumHeight(1), layout->rowMaximumHeight(2));
+ layout->setRowMaximumHeight(0, 20);
+ layout->setRowMaximumHeight(2, 60);
+
+ view.show();
+ widget->show();
+ widget->resize(widget->effectiveSizeHint(Qt::PreferredSize));
+ QApplication::processEvents();
+
+ QCOMPARE(layout->itemAt(0,0)->geometry().height(), 20.0);
+ QCOMPARE(layout->itemAt(0,1)->geometry().height(), 20.0);
+ QCOMPARE(layout->itemAt(1,0)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(1,1)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(2,0)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(2,1)->geometry().height(), 25.0);
+
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::rowMinimumHeight_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+// public qreal rowMinimumHeight(int row) const
+void tst_QGraphicsGridLayout::rowMinimumHeight()
+{
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 2, 3, hasHeightForWidth);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ // should at least be a very large number
+ QCOMPARE(layout->rowMinimumHeight(0), 0.0);
+ QCOMPARE(layout->rowMinimumHeight(0), layout->rowMinimumHeight(1));
+ QCOMPARE(layout->rowMinimumHeight(1), layout->rowMinimumHeight(2));
+ layout->setRowMinimumHeight(0, 20);
+ layout->setRowMinimumHeight(2, 40);
+
+ view.show();
+ widget->show();
+ widget->resize(widget->effectiveSizeHint(Qt::PreferredSize));
+ QApplication::processEvents();
+
+ QCOMPARE(layout->itemAt(0,0)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(0,1)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(1,0)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(1,1)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(2,0)->geometry().height(), 40.0);
+ QCOMPARE(layout->itemAt(2,1)->geometry().height(), 40.0);
+
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::rowPreferredHeight_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+// public qreal rowPreferredHeight(int row) const
+void tst_QGraphicsGridLayout::rowPreferredHeight()
+{
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 2, 3, hasHeightForWidth);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ // default preferred height ??
+ QCOMPARE(layout->rowPreferredHeight(0), 0.0);
+ QCOMPARE(layout->rowPreferredHeight(0), layout->rowPreferredHeight(1));
+ QCOMPARE(layout->rowPreferredHeight(1), layout->rowPreferredHeight(2));
+ layout->setRowPreferredHeight(0, 20);
+ layout->setRowPreferredHeight(2, 40);
+
+ view.show();
+ widget->show();
+ widget->resize(widget->effectiveSizeHint(Qt::PreferredSize));
+ QApplication::processEvents();
+
+ // ### Jasmin: Should rowPreferredHeight have precedence over sizeHint(Qt::PreferredSize) ?
+ QCOMPARE(layout->itemAt(0,0)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(0,1)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(1,0)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(1,1)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(2,0)->geometry().height(), 40.0);
+ QCOMPARE(layout->itemAt(2,1)->geometry().height(), 40.0);
+
+ delete widget;
+}
+
+// public void setRowFixedHeight(int row, qreal height)
+void tst_QGraphicsGridLayout::setRowFixedHeight()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 2, 3);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ layout->setRowFixedHeight(0, 20.);
+ layout->setRowFixedHeight(2, 40.);
+
+ view.show();
+ widget->show();
+ widget->resize(widget->effectiveSizeHint(Qt::PreferredSize));
+ QApplication::processEvents();
+
+ QCOMPARE(layout->itemAt(0,0)->geometry().height(), 20.0);
+ QCOMPARE(layout->itemAt(0,1)->geometry().height(), 20.0);
+ QCOMPARE(layout->itemAt(1,0)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(1,1)->geometry().height(), 25.0);
+ QCOMPARE(layout->itemAt(2,0)->geometry().height(), 40.0);
+ QCOMPARE(layout->itemAt(2,1)->geometry().height(), 40.0);
+
+ delete widget;
+}
+
+// public qreal rowSpacing(int row) const
+void tst_QGraphicsGridLayout::rowSpacing()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+ QCOMPARE(layout->columnSpacing(0), 0.0);
+
+ layout->setColumnSpacing(0, 20);
+ view.show();
+ widget->show();
+ widget->resize(widget->effectiveSizeHint(Qt::PreferredSize));
+ QApplication::processEvents();
+
+ QCOMPARE(layout->itemAt(0,0)->geometry().left(), 0.0);
+ QCOMPARE(layout->itemAt(0,0)->geometry().right(), 25.0);
+ QCOMPARE(layout->itemAt(0,1)->geometry().left(), 45.0);
+ QCOMPARE(layout->itemAt(0,1)->geometry().right(), 70.0);
+ QCOMPARE(layout->itemAt(0,2)->geometry().left(), 70.0);
+ QCOMPARE(layout->itemAt(0,2)->geometry().right(), 95.0);
+
+ delete widget;
+
+}
+
+void tst_QGraphicsGridLayout::rowStretchFactor_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+
+// public int rowStretchFactor(int row) const
+void tst_QGraphicsGridLayout::rowStretchFactor()
+{
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 2, 3, hasHeightForWidth);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ layout->setRowStretchFactor(0, 1);
+ layout->setRowStretchFactor(1, 2);
+ layout->setRowStretchFactor(2, 3);
+ view.show();
+ widget->show();
+ widget->resize(50, 130);
+ QApplication::processEvents();
+
+ QVERIFY(layout->itemAt(0,0)->geometry().height() < layout->itemAt(1,0)->geometry().height());
+ QVERIFY(layout->itemAt(1,0)->geometry().height() < layout->itemAt(2,0)->geometry().height());
+ QVERIFY(layout->itemAt(0,1)->geometry().height() < layout->itemAt(1,1)->geometry().height());
+ QVERIFY(layout->itemAt(1,1)->geometry().height() < layout->itemAt(2,1)->geometry().height());
+
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::setColumnSpacing_data()
+{
+ QTest::addColumn<int>("column");
+ QTest::addColumn<qreal>("spacing");
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("null") << 0 << qreal(0.0) << false;
+ QTest::newRow("10") << 0 << qreal(10.0) << false;
+ QTest::newRow("null, hasHeightForWidth") << 0 << qreal(0.0) << true;
+ QTest::newRow("10, hasHeightForWidth") << 0 << qreal(10.0) << true;
+}
+
+// public void setColumnSpacing(int column, qreal spacing)
+void tst_QGraphicsGridLayout::setColumnSpacing()
+{
+ QFETCH(int, column);
+ QFETCH(qreal, spacing);
+ QFETCH(bool, hasHeightForWidth);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2, hasHeightForWidth);
+ layout->setSpacing(0);
+ layout->setContentsMargins(0, 0, 0, 0);
+ qreal oldSpacing = layout->columnSpacing(column);
+ QCOMPARE(oldSpacing, 0.0);
+ qreal w = layout->sizeHint(Qt::PreferredSize, QSizeF()).width();
+ layout->setColumnSpacing(column, spacing);
+ QApplication::processEvents();
+ QCOMPARE(layout->sizeHint(Qt::PreferredSize, QSizeF()).width(), w + spacing);
+}
+
+void tst_QGraphicsGridLayout::setGeometry_data()
+{
+ QTest::addColumn<QRectF>("rect");
+ QTest::newRow("null") << QRectF();
+ QTest::newRow("normal") << QRectF(0,0, 50, 50);
+}
+
+// public void setGeometry(QRectF const& rect)
+void tst_QGraphicsGridLayout::setGeometry()
+{
+ QFETCH(QRectF, rect);
+
+ QGraphicsWidget *window = new QGraphicsWidget;
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ window->setLayout(layout);
+ QGraphicsGridLayout *layout2 = new QGraphicsGridLayout();
+ layout2->setMaximumSize(100, 100);
+ layout->addItem(layout2, 0, 0);
+ layout2->setGeometry(rect);
+ QCOMPARE(layout2->geometry(), rect);
+}
+
+void tst_QGraphicsGridLayout::setRowSpacing_data()
+{
+ QTest::addColumn<int>("row");
+ QTest::addColumn<qreal>("spacing");
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("null") << 0 << qreal(0.0) << false;
+ QTest::newRow("10") << 0 << qreal(10.0) << false;
+ QTest::newRow("null, hasHeightForWidth") << 0 << qreal(0.0) << true;
+ QTest::newRow("10, hasHeightForWidth") << 0 << qreal(10.0) << true;
+}
+
+// public void setRowSpacing(int row, qreal spacing)
+void tst_QGraphicsGridLayout::setRowSpacing()
+{
+ QFETCH(int, row);
+ QFETCH(qreal, spacing);
+ QFETCH(bool, hasHeightForWidth);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2, hasHeightForWidth);
+ layout->setSpacing(0);
+ layout->setContentsMargins(0, 0, 0, 0);
+ qreal oldSpacing = layout->rowSpacing(row);
+ QCOMPARE(oldSpacing, 0.0);
+ qreal h = layout->sizeHint(Qt::PreferredSize, QSizeF()).height();
+ layout->setRowSpacing(row, spacing);
+ QApplication::processEvents();
+ QCOMPARE(layout->sizeHint(Qt::PreferredSize, QSizeF()).height(), h + spacing);
+}
+
+void tst_QGraphicsGridLayout::setSpacing_data()
+{
+ QTest::addColumn<qreal>("spacing");
+ QTest::addColumn<bool>("hasHeightForWidth");
+ QTest::newRow("zero") << qreal(0.0) << false;
+ QTest::newRow("17") << qreal(17.0) << false;
+ QTest::newRow("zero, hasHeightForWidth") << qreal(0.0) << true;
+ QTest::newRow("17, hasHeightForWidth") << qreal(17.0) << true;
+}
+
+// public void setSpacing(qreal spacing)
+void tst_QGraphicsGridLayout::setSpacing()
+{
+ QFETCH(qreal, spacing);
+ QFETCH(bool, hasHeightForWidth);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2, hasHeightForWidth);
+ layout->setContentsMargins(0, 0, 0, 0);
+ QSizeF sh = layout->sizeHint(Qt::PreferredSize, QSizeF());
+ qreal oldVSpacing = layout->verticalSpacing();
+ qreal oldHSpacing = layout->horizontalSpacing();
+ if (oldVSpacing != -1) {
+ layout->setSpacing(spacing);
+ QApplication::processEvents();
+ QSizeF newSH = layout->sizeHint(Qt::PreferredSize, QSizeF());
+ QCOMPARE(newSH.height(), sh.height() - (2-1)*(oldVSpacing - spacing));
+ QCOMPARE(newSH.width(), sh.width() - (3-1)*(oldHSpacing - spacing));
+ } else {
+ QSKIP("The current style uses non-uniform layout spacing", SkipAll);
+ }
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::sizeHint_data()
+{
+ QTest::addColumn<ItemList>("itemDescriptions");
+ QTest::addColumn<QSizeF>("expectedMinimumSizeHint");
+ QTest::addColumn<QSizeF>("expectedPreferredSizeHint");
+ QTest::addColumn<QSizeF>("expectedMaximumSizeHint");
+
+ QTest::newRow("rowSpan_larger_than_rows") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(50,300))
+ .maxSize(QSizeF(50,300))
+ .rowSpan(2)
+ << ItemDesc(0,1)
+ .minSize(QSizeF(50,0))
+ .preferredSize(QSizeF(50,50))
+ .maxSize(QSize(50, 1000))
+ << ItemDesc(1,1)
+ .minSize(QSizeF(50,0))
+ .preferredSize(QSizeF(50,50))
+ .maxSize(QSize(50, 1000))
+ )
+ << QSizeF(100, 300)
+ << QSizeF(100, 300)
+ << QSizeF(100, 2000);
+
+ QTest::newRow("rowSpan_smaller_than_rows") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(50, 0))
+ .preferredSize(QSizeF(50, 50))
+ .maxSize(QSizeF(50, 300))
+ .rowSpan(2)
+ << ItemDesc(0,1)
+ .minSize(QSizeF(50, 50))
+ .preferredSize(QSizeF(50, 50))
+ .maxSize(QSize(50, 50))
+ << ItemDesc(1,1)
+ .minSize(QSizeF(50, 50))
+ .preferredSize(QSizeF(50, 50))
+ .maxSize(QSize(50, 50))
+ )
+ << QSizeF(100, 100)
+ << QSizeF(100, 100)
+ << QSizeF(100, 100);
+
+}
+
+// public QSizeF sizeHint(Qt::SizeHint which, QSizeF const& constraint = QSizeF()) const
+void tst_QGraphicsGridLayout::sizeHint()
+{
+ QFETCH(ItemList, itemDescriptions);
+ QFETCH(QSizeF, expectedMinimumSizeHint);
+ QFETCH(QSizeF, expectedPreferredSizeHint);
+ QFETCH(QSizeF, expectedMaximumSizeHint);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0.0);
+ widget->setContentsMargins(0, 0, 0, 0);
+
+ int i;
+ for (i = 0; i < itemDescriptions.count(); ++i) {
+ ItemDesc desc = itemDescriptions.at(i);
+ RectWidget *item = new RectWidget(widget);
+ desc.apply(layout, item);
+ }
+
+ QApplication::sendPostedEvents(0, 0);
+
+ widget->show();
+ view.show();
+ view.resize(400,300);
+ QCOMPARE(layout->sizeHint(Qt::MinimumSize), expectedMinimumSizeHint);
+ QCOMPARE(layout->sizeHint(Qt::PreferredSize), expectedPreferredSizeHint);
+ QCOMPARE(layout->sizeHint(Qt::MaximumSize), expectedMaximumSizeHint);
+
+}
+
+void tst_QGraphicsGridLayout::verticalSpacing_data()
+{
+ QTest::addColumn<qreal>("verticalSpacing");
+ QTest::newRow("zero") << qreal(0.0);
+ QTest::newRow("17") << qreal(10.0);
+}
+
+// public qreal verticalSpacing() const
+void tst_QGraphicsGridLayout::verticalSpacing()
+{
+ QFETCH(qreal, verticalSpacing);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout();
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ populateLayout(layout, 3, 2);
+ layout->setContentsMargins(0, 0, 0, 0);
+ qreal h = layout->sizeHint(Qt::PreferredSize, QSizeF()).height();
+ qreal oldSpacing = layout->verticalSpacing();
+ if (oldSpacing != -1) {
+ layout->setVerticalSpacing(verticalSpacing);
+ QApplication::processEvents();
+ qreal new_h = layout->sizeHint(Qt::PreferredSize, QSizeF()).height();
+ QCOMPARE(new_h, h - (2-1)*(oldSpacing - verticalSpacing));
+ } else {
+ QSKIP("The current style uses non-uniform layout spacing", SkipAll);
+ }
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::layoutDirection_data()
+{
+ QTest::addColumn<bool>("hasHeightForWidth");
+
+ QTest::newRow("") << false;
+ QTest::newRow("hasHeightForWidth") << true;
+}
+
+void tst_QGraphicsGridLayout::layoutDirection()
+{
+ QFETCH(bool, hasHeightForWidth);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ QGraphicsWidget *window = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ layout->setContentsMargins(1, 2, 3, 4);
+ layout->setSpacing(6);
+ RectWidget *w1 = new RectWidget;
+ w1->setMinimumSize(30, 20);
+ layout->addItem(w1, 0, 0);
+ RectWidget *w2 = new RectWidget;
+ w2->setMinimumSize(20, 20);
+ w2->setMaximumSize(20, 20);
+ layout->addItem(w2, 0, 1);
+ RectWidget *w3 = new RectWidget;
+ w3->setMinimumSize(20, 20);
+ w3->setMaximumSize(20, 20);
+ layout->addItem(w3, 1, 0);
+ RectWidget *w4 = new RectWidget;
+ w4->setMinimumSize(30, 20);
+ layout->addItem(w4, 1, 1);
+
+ QSizePolicy policy = w1->sizePolicy();
+ policy.setHeightForWidth(hasHeightForWidth);
+ w1->setSizePolicy(policy);
+ w2->setSizePolicy(policy);
+ w4->setSizePolicy(policy);
+
+ layout->setAlignment(w2, Qt::AlignRight);
+ layout->setAlignment(w3, Qt::AlignLeft);
+
+ scene.addItem(window);
+ window->setLayout(layout);
+ view.show();
+ window->resize(70, 52);
+ QApplication::processEvents();
+ QCOMPARE(w1->geometry().left(), 1.0);
+ QCOMPARE(w1->geometry().right(), 31.0);
+ QCOMPARE(w2->geometry().left(), 47.0);
+ QCOMPARE(w2->geometry().right(), 67.0);
+ QCOMPARE(w3->geometry().left(), 1.0);
+ QCOMPARE(w3->geometry().right(), 21.0);
+ QCOMPARE(w4->geometry().left(), 37.0);
+ QCOMPARE(w4->geometry().right(), 67.0);
+
+ window->setLayoutDirection(Qt::RightToLeft);
+ QApplication::processEvents();
+ QCOMPARE(w1->geometry().left(), 39.0);
+ QCOMPARE(w1->geometry().right(), 69.0);
+ QCOMPARE(w2->geometry().left(), 3.0);
+ QCOMPARE(w2->geometry().right(), 23.0);
+ QCOMPARE(w3->geometry().left(), 49.0);
+ QCOMPARE(w3->geometry().right(), 69.0);
+ QCOMPARE(w4->geometry().left(), 3.0);
+ QCOMPARE(w4->geometry().right(), 33.0);
+
+ delete window;
+}
+
+void tst_QGraphicsGridLayout::removeLayout()
+{
+ QGraphicsScene scene;
+ RectWidget *textEdit = new RectWidget;
+ RectWidget *pushButton = new RectWidget;
+ scene.addItem(textEdit);
+ scene.addItem(pushButton);
+
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ layout->addItem(textEdit, 0, 0);
+ layout->addItem(pushButton, 1, 0);
+
+ QGraphicsWidget *form = new QGraphicsWidget;
+ form->setLayout(layout);
+ scene.addItem(form);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWait(20);
+
+ QRectF r1 = textEdit->geometry();
+ QRectF r2 = pushButton->geometry();
+ form->setLayout(0);
+ //documentation of QGraphicsWidget::setLayout:
+ //If layout is 0, the widget is left without a layout. Existing subwidgets' geometries will remain unaffected.
+ QCOMPARE(textEdit->geometry(), r1);
+ QCOMPARE(pushButton->geometry(), r2);
+}
+
+void tst_QGraphicsGridLayout::defaultStretchFactors_data()
+{
+ QTest::addColumn<ItemList>("itemDescriptions");
+ QTest::addColumn<QSizeF>("newSize");
+ QTest::addColumn<SizeList>("expectedSizes");
+
+ QTest::newRow("usepreferredsize") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,2)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,1)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,2)
+ .preferredSizeHint(QSizeF(10,10))
+ )
+ << QSizeF()
+ << (SizeList()
+ << QSizeF(10,10) << QSizeF(10,10) << QSizeF(10,10)
+ << QSizeF(10,10) << QSizeF(10,10) << QSizeF(10,10)
+ );
+
+ QTest::newRow("ignoreitem01") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,2)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,1)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,2)
+ .preferredSizeHint(QSizeF(10,10))
+ )
+ << QSizeF()
+ << (SizeList()
+ << QSizeF(10,10) << QSizeF(10,10) << QSizeF(10,10)
+ << QSizeF(10,10) << QSizeF(10,10) << QSizeF(10,10)
+ );
+
+ QTest::newRow("ignoreitem01_resize120x40") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(20,10))
+ << ItemDesc(0,2)
+ .preferredSizeHint(QSizeF(30,10))
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,1)
+ .preferredSizeHint(QSizeF(20,10))
+ << ItemDesc(1,2)
+ .preferredSizeHint(QSizeF(30,10))
+ )
+ << QSizeF(120, 40)
+ << (SizeList()
+ << QSizeF(20,20) << QSizeF(40,20) << QSizeF(60,20)
+ << QSizeF(20,20) << QSizeF(40,20) << QSizeF(60,20)
+ );
+
+ QTest::newRow("ignoreitem11_resize120x40") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .preferredSizeHint(QSizeF(20,10))
+ << ItemDesc(0,2)
+ .preferredSizeHint(QSizeF(30,10))
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,20))
+ << ItemDesc(1,1)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(20,20))
+ << ItemDesc(1,2)
+ .preferredSizeHint(QSizeF(30,20))
+ )
+ << QSizeF(120, 60)
+ << (SizeList()
+ << QSizeF(20,20) << QSizeF(40,20) << QSizeF(60,20)
+ << QSizeF(20,40) << QSizeF(40,40) << QSizeF(60,40)
+ );
+
+ QTest::newRow("ignoreitem01_span01_resize70x60") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .preferredSizeHint(QSizeF(20,10))
+ .sizePolicy(QSizePolicy::Ignored)
+ .rowSpan(2)
+ << ItemDesc(0,2)
+ .preferredSizeHint(QSizeF(30,10))
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,20))
+ << ItemDesc(1,2)
+ .preferredSizeHint(QSizeF(30,20))
+ )
+ << QSizeF(70, 60)
+ << (SizeList()
+ << QSizeF(20,20) << QSizeF(10,60) << QSizeF(40,20)
+ << QSizeF(20,40) << QSizeF(40,40)
+ );
+
+ QTest::newRow("ignoreitem10_resize40x120") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,0)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,20))
+ << ItemDesc(1,1)
+ .preferredSizeHint(QSizeF(10,20))
+ << ItemDesc(2,0)
+ .preferredSizeHint(QSizeF(10,30))
+ << ItemDesc(2,1)
+ .preferredSizeHint(QSizeF(10,30))
+ )
+ << QSizeF(40, 120)
+ << (SizeList()
+ << QSizeF(20,20) << QSizeF(20,20)
+ << QSizeF(20,40) << QSizeF(20,40)
+ << QSizeF(20,60) << QSizeF(20,60)
+ );
+
+ QTest::newRow("ignoreitem01_span02") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,20))
+ .rowSpan(2)
+ << ItemDesc(0,2)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,2)
+ .preferredSizeHint(QSizeF(10,10))
+ )
+ << QSizeF()
+ << (SizeList()
+ << QSizeF(10,10) << QSizeF(0,20) << QSizeF(10,10)
+ << QSizeF(10,10) << QSizeF(10,10)
+ );
+
+ QTest::newRow("ignoreitem02_span02") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,2)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,20))
+ .rowSpan(2)
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,1)
+ .preferredSizeHint(QSizeF(10,10))
+ )
+ << QSizeF()
+ << (SizeList()
+ << QSizeF(10,10) << QSizeF(10,10) << QSizeF(0,20)
+ << QSizeF(10,10) << QSizeF(10,10)
+ );
+
+ QTest::newRow("ignoreitem02_span00_span02") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,10))
+ .rowSpan(2)
+ << ItemDesc(0,1)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,2)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,20))
+ .rowSpan(2)
+ << ItemDesc(1,1)
+ .preferredSizeHint(QSizeF(10,10))
+ )
+ << QSizeF()
+ << (SizeList()
+ << QSizeF(10,20) << QSizeF(10,10) << QSizeF(0,20)
+ << QSizeF(10,10)
+ );
+
+ QTest::newRow("ignoreitem00_colspan00") << (ItemList()
+ << ItemDesc(0,0)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,20))
+ .colSpan(2)
+ << ItemDesc(0,2)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,1)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,2)
+ .preferredSizeHint(QSizeF(10,10))
+ )
+ << QSizeF()
+ << (SizeList()
+ << QSizeF(20,10) << QSizeF(10,10) << QSizeF(10,10)
+ << QSizeF(10,10) << QSizeF(10,10)
+ );
+
+ QTest::newRow("ignoreitem01_colspan01") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,20))
+ .colSpan(2)
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,1)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,2)
+ .preferredSizeHint(QSizeF(10,10))
+ )
+ << QSizeF()
+ << (SizeList()
+ << QSizeF(10,10) << QSizeF(20,10) << QSizeF(10,10)
+ << QSizeF(10,10) << QSizeF(10,10)
+ );
+
+ QTest::newRow("ignorecolumn1_resize70x60") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(20,10))
+ << ItemDesc(0,2)
+ .preferredSizeHint(QSizeF(30,10))
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,20))
+ << ItemDesc(1,1)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(20,20))
+ << ItemDesc(1,2)
+ .preferredSizeHint(QSizeF(30,20))
+ )
+ << QSizeF(70, 60)
+ << (SizeList()
+ << QSizeF(20,20) << QSizeF(10,20) << QSizeF(40,20)
+ << QSizeF(20,40) << QSizeF(10,40) << QSizeF(40,40)
+ );
+
+ QTest::newRow("ignorerow0") << (ItemList()
+ << ItemDesc(0,0)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,2)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,1)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,2)
+ .preferredSizeHint(QSizeF(10,10))
+ )
+ << QSizeF()
+ << (SizeList()
+ << QSizeF(10,0) << QSizeF(10,0) << QSizeF(10,0)
+ << QSizeF(10,10) << QSizeF(10,10) << QSizeF(10,10)
+ );
+
+ QTest::newRow("ignorerow1") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,2)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,0)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,1)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(1,2)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,10))
+ )
+ << QSizeF()
+ << (SizeList()
+ << QSizeF(10,10) << QSizeF(10,10) << QSizeF(10,10)
+ << QSizeF(10,0) << QSizeF(10,0) << QSizeF(10,0)
+ );
+
+ QTest::newRow("ignorerow0_resize60x50") << (ItemList()
+ << ItemDesc(0,0)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(10,10))
+ << ItemDesc(0,1)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(20,10))
+ << ItemDesc(0,2)
+ .sizePolicy(QSizePolicy::Ignored)
+ .preferredSizeHint(QSizeF(30,10))
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,30))
+ << ItemDesc(1,1)
+ .preferredSizeHint(QSizeF(20,30))
+ << ItemDesc(1,2)
+ .preferredSizeHint(QSizeF(30,30))
+ )
+ << QSizeF(60, 50)
+ << (SizeList()
+ << QSizeF(10,10) << QSizeF(20,10) << QSizeF(30,10)
+ << QSizeF(10,40) << QSizeF(20,40) << QSizeF(30,40)
+ );
+
+}
+
+void tst_QGraphicsGridLayout::defaultStretchFactors()
+{
+ QFETCH(ItemList, itemDescriptions);
+ QFETCH(QSizeF, newSize);
+ QFETCH(SizeList, expectedSizes);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0.0);
+ widget->setContentsMargins(0, 0, 0, 0);
+
+ int i;
+ for (i = 0; i < itemDescriptions.count(); ++i) {
+ ItemDesc desc = itemDescriptions.at(i);
+ RectWidget *item = new RectWidget(widget);
+ desc.apply(layout, item);
+ }
+
+ QApplication::sendPostedEvents(0, 0);
+
+ widget->show();
+ view.show();
+ view.resize(400,300);
+ if (newSize.isValid())
+ widget->resize(newSize);
+
+ QApplication::sendPostedEvents(0, 0);
+ for (i = 0; i < expectedSizes.count(); ++i) {
+ QSizeF itemSize = layout->itemAt(i)->geometry().size();
+ QCOMPARE(itemSize, expectedSizes.at(i));
+ }
+
+ delete widget;
+}
+
+typedef QList<QRectF> RectList;
+Q_DECLARE_METATYPE(RectList);
+
+void tst_QGraphicsGridLayout::alignment2_data()
+{
+ QTest::addColumn<ItemList>("itemDescriptions");
+ QTest::addColumn<QSizeF>("newSize");
+ QTest::addColumn<RectList>("expectedGeometries");
+
+ QTest::newRow("hor_sizepolicy_fixed") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,20))
+ .sizePolicyV(QSizePolicy::Fixed)
+ << ItemDesc(0,1)
+ .preferredSizeHint(QSizeF(10,10))
+ .sizePolicyV(QSizePolicy::Fixed)
+ )
+ << QSizeF()
+ << (RectList()
+ << QRectF(0, 0, 10,20) << QRectF(10, 0, 10,10)
+ );
+
+ QTest::newRow("hor_sizepolicy_fixed_alignvcenter") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,20))
+ .sizePolicyV(QSizePolicy::Fixed)
+ << ItemDesc(0,1)
+ .preferredSizeHint(QSizeF(10,10))
+ .sizePolicyV(QSizePolicy::Fixed)
+ .alignment(Qt::AlignVCenter)
+ )
+ << QSizeF()
+ << (RectList()
+ << QRectF(0, 0, 10,20) << QRectF(10, 5, 10,10)
+ );
+
+ QTest::newRow("hor_sizepolicy_fixed_aligntop") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,20))
+ .sizePolicyV(QSizePolicy::Fixed)
+ << ItemDesc(0,1)
+ .preferredSizeHint(QSizeF(10,10))
+ .sizePolicyV(QSizePolicy::Fixed)
+ .alignment(Qt::AlignTop)
+ )
+ << QSizeF()
+ << (RectList()
+ << QRectF(0, 0, 10,20) << QRectF(10, 0, 10,10)
+ );
+
+ QTest::newRow("hor_sizepolicy_fixed_alignbottom") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(10,20))
+ .sizePolicyV(QSizePolicy::Fixed)
+ << ItemDesc(0,1)
+ .preferredSizeHint(QSizeF(10,10))
+ .sizePolicyV(QSizePolicy::Fixed)
+ .alignment(Qt::AlignBottom)
+ )
+ << QSizeF()
+ << (RectList()
+ << QRectF(0, 0, 10,20) << QRectF(10, 10, 10,10)
+ );
+
+ QTest::newRow("ver_sizepolicy_fixed") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(20,10))
+ .sizePolicyH(QSizePolicy::Fixed)
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,10))
+ .sizePolicyH(QSizePolicy::Fixed)
+ )
+ << QSizeF()
+ << (RectList()
+ << QRectF(0, 0, 20,10) << QRectF(0, 10, 10,10)
+ );
+
+ QTest::newRow("ver_sizepolicy_fixed_alignhcenter") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(20,10))
+ .sizePolicyH(QSizePolicy::Fixed)
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,10))
+ .sizePolicyH(QSizePolicy::Fixed)
+ .alignment(Qt::AlignHCenter)
+ )
+ << QSizeF()
+ << (RectList()
+ << QRectF(0, 0, 20,10) << QRectF(5, 10, 10,10)
+ );
+
+ QTest::newRow("ver_sizepolicy_fixed_alignleft") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(20,10))
+ .sizePolicyH(QSizePolicy::Fixed)
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,10))
+ .sizePolicyH(QSizePolicy::Fixed)
+ .alignment(Qt::AlignLeft)
+ )
+ << QSizeF()
+ << (RectList()
+ << QRectF(0, 0, 20,10) << QRectF(0, 10, 10,10)
+ );
+
+ QTest::newRow("ver_sizepolicy_fixed_alignright") << (ItemList()
+ << ItemDesc(0,0)
+ .preferredSizeHint(QSizeF(20,10))
+ .sizePolicyH(QSizePolicy::Fixed)
+ << ItemDesc(1,0)
+ .preferredSizeHint(QSizeF(10,10))
+ .sizePolicyH(QSizePolicy::Fixed)
+ .alignment(Qt::AlignRight)
+ )
+ << QSizeF()
+ << (RectList()
+ << QRectF(0, 0, 20,10) << QRectF(10, 10, 10,10)
+ );
+}
+
+void tst_QGraphicsGridLayout::alignment2()
+{
+ QFETCH(ItemList, itemDescriptions);
+ QFETCH(QSizeF, newSize);
+ QFETCH(RectList, expectedGeometries);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0.0);
+ widget->setContentsMargins(0, 0, 0, 0);
+
+ int i;
+ for (i = 0; i < itemDescriptions.count(); ++i) {
+ ItemDesc desc = itemDescriptions.at(i);
+ RectWidget *item = new RectWidget(widget);
+ desc.apply(layout, item);
+ }
+
+ QApplication::sendPostedEvents(0, 0);
+
+ widget->show();
+ view.resize(400,300);
+ view.show();
+ if (newSize.isValid())
+ widget->resize(newSize);
+
+ QApplication::sendPostedEvents(0, 0);
+ for (i = 0; i < expectedGeometries.count(); ++i) {
+ QRectF itemRect = layout->itemAt(i)->geometry();
+ QCOMPARE(itemRect, expectedGeometries.at(i));
+ }
+
+ delete widget;
+}
+
+static QSizeF hfw1(Qt::SizeHint, const QSizeF &constraint)
+{
+ QSizeF result(constraint);
+ const qreal ch = constraint.height();
+ const qreal cw = constraint.width();
+ if (cw < 0 && ch < 0) {
+ return QSizeF(50, 400);
+ } else if (cw > 0) {
+ result.setHeight(20000./cw);
+ }
+ return result;
+}
+
+static QSizeF wfh1(Qt::SizeHint, const QSizeF &constraint)
+{
+ QSizeF result(constraint);
+ const qreal ch = constraint.height();
+ const qreal cw = constraint.width();
+ if (cw < 0 && ch < 0) {
+ return QSizeF(400, 50);
+ } else if (ch > 0) {
+ result.setWidth(20000./ch);
+ }
+ return result;
+}
+
+static QSizeF wfh2(Qt::SizeHint, const QSizeF &constraint)
+{
+ QSizeF result(constraint);
+ const qreal ch = constraint.height();
+ const qreal cw = constraint.width();
+ if (ch < 0 && cw < 0)
+ return QSizeF(50, 50);
+ if (ch >= 0)
+ result.setWidth(ch);
+ return result;
+}
+
+static QSizeF hfw3(Qt::SizeHint, const QSizeF &constraint)
+{
+ QSizeF result(constraint);
+ const qreal ch = constraint.height();
+ const qreal cw = constraint.width();
+ if (cw < 0 && ch < 0) {
+ return QSizeF(10, 10);
+ } else if (cw > 0) {
+ result.setHeight(100./cw);
+ }
+ return result;
+}
+
+static QSizeF hfw2(Qt::SizeHint /*which*/, const QSizeF &constraint)
+{
+ return QSizeF(constraint.width(), constraint.width());
+}
+
+void tst_QGraphicsGridLayout::geometries_data()
+{
+
+ QTest::addColumn<ItemList>("itemDescriptions");
+ QTest::addColumn<QSizeF>("newSize");
+ QTest::addColumn<RectList>("expectedGeometries");
+
+ QTest::newRow("combine_max_sizes") << (ItemList()
+ << ItemDesc(0,0)
+ .maxSize(QSizeF(50,10))
+ << ItemDesc(1,0)
+ .maxSize(QSizeF(10,10))
+ )
+ << QSizeF(50, 20)
+ << (RectList()
+ << QRectF(0, 0, 50,10) << QRectF(0, 10, 10,10)
+ );
+
+ QTest::newRow("combine_min_sizes") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(50,10))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(10,10))
+ )
+ << QSizeF(60, 20)
+ << (RectList()
+ << QRectF(0, 0, 60,10) << QRectF(0, 10, 60,10)
+ );
+
+ // change layout height and verify
+ QTest::newRow("hfw-100x401") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .minSize(QSizeF(40,-1))
+ .preferredSize(QSizeF(50,-1))
+ .maxSize(QSizeF(500, -1))
+ .dynamicConstraint(hfw1, Qt::Vertical)
+ )
+ << QSizeF(100, 401)
+ << (RectList()
+ << QRectF(0, 0, 50, 1) << QRectF(50, 0, 50, 1)
+ << QRectF(0, 1, 50,100) << QRectF(50, 1, 50,400)
+ );
+ QTest::newRow("hfw-h408") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(40,40))
+ .sizeHint(Qt::PreferredSize, QSizeF(50,400))
+ .sizeHint(Qt::MaximumSize, QSizeF(500, 500))
+ .dynamicConstraint(hfw1, Qt::Vertical)
+ )
+ << QSizeF(100, 408)
+ << (RectList()
+ << QRectF(0, 0, 50, 8) << QRectF(50, 0, 50, 8)
+ << QRectF(0, 8, 50,100) << QRectF(50, 8, 50,400)
+ );
+ QTest::newRow("hfw-h410") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .minSize(QSizeF(40,40))
+ .preferredSize(QSizeF(50,400))
+ .maxSize(QSizeF(500, 500))
+ .dynamicConstraint(hfw1, Qt::Vertical)
+ )
+ << QSizeF(100, 410)
+ << (RectList()
+ << QRectF(0, 0, 50,10) << QRectF(50, 0, 50,10)
+ << QRectF(0, 10, 50,100) << QRectF(50, 10, 50,400)
+ );
+
+ QTest::newRow("hfw-100x470") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(40,40))
+ .sizeHint(Qt::PreferredSize, QSizeF(50,400))
+ .sizeHint(Qt::MaximumSize, QSizeF(500,500))
+ .dynamicConstraint(hfw1, Qt::Vertical)
+ )
+ << QSizeF(100, 470)
+ << (RectList()
+ << QRectF(0, 0, 50,70) << QRectF(50, 0, 50,70)
+ << QRectF(0, 70, 50,100) << QRectF(50, 70, 50,400)
+ );
+
+ // change layout width and verify
+ QTest::newRow("hfw-100x401") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .minSize(QSizeF(-1,-1))
+ .preferredSize(QSizeF(-1,-1))
+ .maxSize(QSizeF(-1, -1))
+ .dynamicConstraint(hfw1, Qt::Vertical)
+ )
+ << QSizeF(100, 401)
+ << (RectList()
+ << QRectF( 0, 0, 50, 1) << QRectF( 50, 0, 50, 1)
+ << QRectF( 0, 1, 50, 100) << QRectF( 50, 1, 50, 400)
+ );
+
+ QTest::newRow("hfw-160x350") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(40,40))
+ .sizeHint(Qt::PreferredSize, QSizeF(50,400))
+ .sizeHint(Qt::MaximumSize, QSizeF(5000,5000))
+ .dynamicConstraint(hfw1, Qt::Vertical)
+ )
+ << QSizeF(160, 350)
+ << (RectList()
+ << QRectF( 0, 0, 80, 100) << QRectF( 80, 0, 80, 100)
+ << QRectF( 0, 100, 80, 100) << QRectF( 80, 100, 80, 250)
+ );
+
+ QTest::newRow("hfw-160x300") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(40,40))
+ .sizeHint(Qt::PreferredSize, QSizeF(50,400))
+ .sizeHint(Qt::MaximumSize, QSizeF(5000, 5000))
+ .dynamicConstraint(hfw1, Qt::Vertical)
+ )
+ << QSizeF(160, 300)
+ << (RectList()
+ << QRectF( 0, 0, 80, 50) << QRectF( 80, 0, 80, 50)
+ << QRectF( 0, 50, 80, 100) << QRectF( 80, 50, 80, 250)
+ );
+
+ QTest::newRow("hfw-20x40") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,10))
+ .preferredSize(QSizeF(50,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(1, 1))
+ .sizeHint(Qt::PreferredSize, QSizeF(50, 50))
+ .sizeHint(Qt::MaximumSize, QSizeF(100, 100))
+ .dynamicConstraint(hfw3, Qt::Vertical)
+ )
+ << QSizeF(20, 40)
+ << (RectList()
+ << QRectF(0, 0, 10, 20) << QRectF(10, 0, 10, 20)
+ << QRectF(0, 20, 10, 20) << QRectF(10, 20, 10, 10)
+ );
+
+ QTest::newRow("wfh-300x160") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(10,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(10,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(10,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(10,10))
+ .sizeHint(Qt::PreferredSize, QSizeF(400,50))
+ .sizeHint(Qt::MaximumSize, QSizeF(5000, 5000))
+ .dynamicConstraint(wfh1, Qt::Horizontal)
+ )
+ << QSizeF(300, 160)
+ << (RectList()
+ << QRectF( 0, 0, 50, 80) << QRectF( 50, 0, 100, 80)
+ << QRectF( 0, 80, 50, 80) << QRectF( 50, 80, 250, 80)
+ );
+
+ QTest::newRow("wfh-40x20") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ // Note, must be 10 in order to match stretching of wfh item
+ // below (the same stretch makes it easier to test)
+ .minSize(QSizeF(10,1))
+ .preferredSize(QSizeF(50,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(1,1))
+ .sizeHint(Qt::PreferredSize, QSizeF(50,50))
+ .sizeHint(Qt::MaximumSize, QSizeF(100, 100))
+ .dynamicConstraint(wfh2, Qt::Horizontal)
+ )
+ << QSizeF(40, 20)
+ << (RectList()
+ << QRectF(0, 0, 20, 10) << QRectF(20, 0, 20, 10)
+ << QRectF(0, 10, 20, 10) << QRectF(20, 10, 10, 10)
+ );
+
+ QTest::newRow("wfh-400x160") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(1,1))
+ .sizeHint(Qt::PreferredSize, QSizeF(50,50))
+ .sizeHint(Qt::MaximumSize, QSizeF(100, 100))
+ .dynamicConstraint(wfh2, Qt::Horizontal)
+ )
+
+ << QSizeF(400, 160)
+ << (RectList()
+ << QRectF(0, 0, 100, 80) << QRectF(100, 0, 100, 80)
+ << QRectF(0, 80, 100, 80) << QRectF(100, 80, 80, 80)
+ );
+
+ QTest::newRow("wfh-160x100") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ // Note, preferred width must be 50 in order to match
+ // preferred width of wfh item below.
+ // (The same preferred size makes the stretch the same, and
+ // makes it easier to test) (The stretch algorithm is a
+ // blackbox)
+ .preferredSize(QSizeF(50,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(10,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(10,50))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(1,1))
+ .sizeHint(Qt::PreferredSize, QSizeF(10,50))
+ .sizeHint(Qt::MaximumSize, QSizeF(500, 500))
+ .dynamicConstraint(wfh2, Qt::Horizontal)
+ )
+ << QSizeF(160, 100)
+ << (RectList()
+ << QRectF(0, 0, 80, 50) << QRectF( 80, 0, 80, 50)
+ << QRectF(0, 50, 80, 50) << QRectF( 80, 50, 50, 50)
+ );
+
+ QTest::newRow("hfw-h470") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(40,40))
+ .sizeHint(Qt::PreferredSize, QSizeF(50,400))
+ .sizeHint(Qt::MaximumSize, QSizeF(500,500))
+ .dynamicConstraint(hfw1, Qt::Vertical)
+ )
+ << QSizeF(100, 470)
+ << (RectList()
+ << QRectF(0, 0, 50,70) << QRectF(50, 0, 50,70)
+ << QRectF(0, 70, 50,100) << QRectF(50, 70, 50,400)
+ );
+
+ // change layout width and verify
+ QTest::newRow("hfw-w100") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(40,40))
+ .sizeHint(Qt::PreferredSize, QSizeF(50,400))
+ .sizeHint(Qt::MaximumSize, QSizeF(5000,5000))
+ .dynamicConstraint(hfw1, Qt::Vertical)
+ )
+ << QSizeF(100, 401)
+ << (RectList()
+ << QRectF( 0, 0, 50, 1) << QRectF( 50, 0, 50, 1)
+ << QRectF( 0, 1, 50, 100) << QRectF( 50, 1, 50, 400)
+ );
+
+ QTest::newRow("hfw-w160") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(40,40))
+ .sizeHint(Qt::PreferredSize, QSizeF(50,400))
+ .sizeHint(Qt::MaximumSize, QSizeF(5000,5000))
+ .dynamicConstraint(hfw1, Qt::Vertical)
+ )
+ << QSizeF(160, 350)
+ << (RectList()
+ << QRectF( 0, 0, 80, 100) << QRectF( 80, 0, 80, 100)
+ << QRectF( 0, 100, 80, 100) << QRectF( 80, 100, 80, 250)
+ );
+
+ QTest::newRow("hfw-w500") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(0,1)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,0)
+ .minSize(QSizeF(1,1))
+ .preferredSize(QSizeF(50,10))
+ .maxSize(QSizeF(100, 100))
+ << ItemDesc(1,1)
+ .sizeHint(Qt::MinimumSize, QSizeF(40,40))
+ .sizeHint(Qt::PreferredSize, QSizeF(50,400))
+ .sizeHint(Qt::MaximumSize, QSizeF(5000,5000))
+ .dynamicConstraint(hfw1, Qt::Vertical)
+ )
+ << QSizeF(500, 200)
+ << (RectList()
+ << QRectF( 0, 0, 100, 100) << QRectF(100, 0, 100, 100)
+ << QRectF( 0, 100, 100, 100) << QRectF(100, 100, 400, 50)
+ );
+
+ QTest::newRow("hfw-alignment-defaults") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(100, 100))
+ .maxSize(QSizeF(100, 100))
+ .dynamicConstraint(hfw2, Qt::Vertical)
+ << ItemDesc(1,0)
+ .minSize(QSizeF(200, 200))
+ .maxSize(QSizeF(200, 200))
+ .dynamicConstraint(hfw2, Qt::Vertical)
+ << ItemDesc(2,0)
+ .minSize(QSizeF(300, 300))
+ .maxSize(QSizeF(300, 300))
+ )
+ << QSizeF(300, 600)
+ << (RectList()
+ << QRectF(0, 0, 100, 100)
+ << QRectF(0, 100, 200, 200)
+ << QRectF(0, 300, 300, 300)
+ );
+
+ QTest::newRow("hfw-alignment2") << (ItemList()
+ << ItemDesc(0,0)
+ .minSize(QSizeF(100, 100))
+ .maxSize(QSizeF(100, 100))
+ .dynamicConstraint(hfw2, Qt::Vertical)
+ .alignment(Qt::AlignRight)
+ << ItemDesc(1,0)
+ .minSize(QSizeF(200, 200))
+ .maxSize(QSizeF(200, 200))
+ .dynamicConstraint(hfw2, Qt::Vertical)
+ .alignment(Qt::AlignHCenter)
+ << ItemDesc(2,0)
+ .minSize(QSizeF(300, 300))
+ .maxSize(QSizeF(300, 300))
+ )
+ << QSizeF(300, 600)
+ << (RectList()
+ << QRectF(200, 0, 100, 100)
+ << QRectF( 50, 100, 200, 200)
+ << QRectF( 0, 300, 300, 300)
+ );
+
+}
+
+void tst_QGraphicsGridLayout::geometries()
+{
+ QFETCH(ItemList, itemDescriptions);
+ QFETCH(QSizeF, newSize);
+ QFETCH(RectList, expectedGeometries);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0.0);
+ widget->setContentsMargins(0, 0, 0, 0);
+
+ int i;
+ for (i = 0; i < itemDescriptions.count(); ++i) {
+ ItemDesc desc = itemDescriptions.at(i);
+ RectWidget *item = new RectWidget(widget);
+ desc.apply(layout, item);
+ }
+
+ QApplication::processEvents();
+
+ widget->show();
+ view.resize(400,300);
+ view.show();
+ if (newSize.isValid())
+ widget->resize(newSize);
+
+ QApplication::processEvents();
+ for (i = 0; i < expectedGeometries.count(); ++i) {
+ QRectF itemRect = layout->itemAt(i)->geometry();
+ QCOMPARE(itemRect, expectedGeometries.at(i));
+ }
+
+ delete widget;
+}
+
+void tst_QGraphicsGridLayout::avoidRecursionInInsertItem()
+{
+ QGraphicsWidget window(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout(&window);
+ QCOMPARE(layout->count(), 0);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsGridLayout::addItem: cannot insert itself");
+ layout->addItem(layout, 0, 0);
+ QCOMPARE(layout->count(), 0);
+}
+
+void tst_QGraphicsGridLayout::styleInfoLeak()
+{
+ QGraphicsGridLayout grid;
+ grid.horizontalSpacing();
+}
+
+void tst_QGraphicsGridLayout::task236367_maxSizeHint()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ int w = 203;
+ int h = 204;
+ widget->resize(w, h);
+ QCOMPARE(widget->size(), QSizeF(w, h));
+}
+
+static QSizeF hfw(Qt::SizeHint /*which*/, const QSizeF &constraint)
+{
+ QSizeF result(constraint);
+ const qreal cw = constraint.width();
+ const qreal ch = constraint.height();
+ if (cw < 0 && ch < 0) {
+ return QSizeF(200, 100);
+ } else if (cw >= 0) {
+ result.setHeight(20000./cw);
+ } else if (cw == 0) {
+ result.setHeight(20000);
+ } else if (ch >= 0) {
+ result.setWidth(20000./ch);
+ } else if (ch == 0) {
+ result.setWidth(20000);
+ }
+ return result;
+}
+
+static QSizeF wfh(Qt::SizeHint /*which*/, const QSizeF &constraint)
+{
+ QSizeF result(constraint);
+ const qreal ch = constraint.height();
+ if (ch >= 0) {
+ result.setWidth(ch);
+ }
+ return result;
+}
+
+bool qFuzzyCompare(const QSizeF &a, const QSizeF &b)
+{
+ return qFuzzyCompare(a.width(), b.width()) && qFuzzyCompare(a.height(), b.height());
+}
+
+void tst_QGraphicsGridLayout::heightForWidth()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+ RectWidget *w00 = new RectWidget;
+ w00->setSizeHint(Qt::MinimumSize, QSizeF(1,1));
+ w00->setSizeHint(Qt::PreferredSize, QSizeF(10,10));
+ w00->setSizeHint(Qt::MaximumSize, QSizeF(100,100));
+ layout->addItem(w00, 0, 0);
+
+ RectWidget *w01 = new RectWidget;
+ w01->setSizeHint(Qt::MinimumSize, QSizeF(1,1));
+ w01->setSizeHint(Qt::PreferredSize, QSizeF(10,10));
+ w01->setSizeHint(Qt::MaximumSize, QSizeF(100,100));
+ layout->addItem(w01, 0, 1);
+
+ RectWidget *w10 = new RectWidget;
+ w10->setSizeHint(Qt::MinimumSize, QSizeF(1,1));
+ w10->setSizeHint(Qt::PreferredSize, QSizeF(10,10));
+ w10->setSizeHint(Qt::MaximumSize, QSizeF(100,100));
+ layout->addItem(w10, 1, 0);
+
+ RectWidget *w11 = new RectWidget;
+ w11->setSizeHint(Qt::MinimumSize, QSizeF(1,1));
+ w11->setSizeHint(Qt::MaximumSize, QSizeF(30000,30000));
+ w11->setConstraintFunction(hfw);
+ QSizePolicy sp(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ sp.setHeightForWidth(true);
+ w11->setSizePolicy(sp);
+ layout->addItem(w11, 1, 1);
+
+ QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, -1)), QSizeF(2, 2));
+ QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, -1)), QSizeF(210, 110));
+ QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(-1, -1)), QSizeF(30100, 30100));
+
+ QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(2, -1)), QSizeF(2, 20001));
+ QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(2, -1)), QSizeF(2, 20010));
+ QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(2, -1)), QSizeF(2, 20100));
+
+ // Since 20 is somewhere between "minimum width hint" (2) and
+ // "preferred width hint" (210), it will try to do distribution by
+ // stretching them with different factors.
+ // Since column 1 has a "preferred width" of 200 it means that
+ // column 1 will be a bit wider than column 0. Thus it will also be a bit
+ // shorter than 2001, (the expected height if all columns had width=10)
+ QSizeF sh = layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(20, -1));
+ // column 1 cannot be wider than 19, which means that it must be taller than 20000/19~=1052
+ QVERIFY(sh.height() < 2000 + 1 && sh.height() > 1052 + 1);
+
+ sh = layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(20, -1));
+ QVERIFY(sh.height() < 2000 + 10 && sh.height() > 1052 + 10);
+
+ sh = layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(20, -1));
+ QVERIFY(sh.height() < 2000 + 100 && sh.height() > 1052 + 100);
+
+ // the height of the hfw widget is shorter than the one to the left, which is 100, so
+ // the total height of the last row is 100 (which leaves the layout height to be 200)
+ QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(500, -1)), QSizeF(500, 100 + 100));
+
+}
+
+void tst_QGraphicsGridLayout::widthForHeight()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ RectWidget *w00 = new RectWidget;
+ w00->setMinimumSize(1, 1);
+ w00->setPreferredSize(50, 50);
+ w00->setMaximumSize(100, 100);
+
+ layout->addItem(w00, 0, 0);
+
+ RectWidget *w01 = new RectWidget;
+ w01->setMinimumSize(1,1);
+ w01->setPreferredSize(50,50);
+ w01->setMaximumSize(100,100);
+ layout->addItem(w01, 0, 1);
+
+ RectWidget *w10 = new RectWidget;
+ w10->setMinimumSize(1,1);
+ w10->setPreferredSize(50,50);
+ w10->setMaximumSize(100,100);
+ layout->addItem(w10, 1, 0);
+
+ RectWidget *w11 = new RectWidget;
+ w11->setSizeHint(Qt::MinimumSize, QSizeF(1,1));
+ w11->setSizeHint(Qt::PreferredSize, QSizeF(50,50));
+ w11->setSizeHint(Qt::MaximumSize, QSizeF(30000,30000));
+
+ // This will make sure its always square.
+ w11->setConstraintFunction(wfh);
+ QSizePolicy sp(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ sp.setWidthForHeight(true);
+ w11->setSizePolicy(sp);
+ layout->addItem(w11, 1, 1);
+
+ /*
+ | 1, 50, 100 | 1, 50, 100 |
+ -----+--------------+--------------+
+ 1| | |
+ 50| | |
+ 100| | |
+ -----|--------------+--------------+
+ 1| | |
+ 50| | WFH |
+ 100| | |
+ -----------------------------------+
+ */
+
+
+ QSizeF prefSize = layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, -1));
+ QCOMPARE(prefSize, QSizeF(50+50, 50+50));
+
+ // wfh(1): = 1
+ QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, 2)), QSizeF(1 + 1, 2));
+ QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, 2)), QSizeF(50 + 50, 2));
+ QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(-1, 2)), QSizeF(100 + 100, 2));
+
+ // wfh(40) = 40
+ QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, 80)), QSizeF(1 + 40, 80));
+ QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, 80)), QSizeF(50 + 50, 80));
+ QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(-1, 80)), QSizeF(100 + 100, 80));
+
+ // wfh(80) = 80
+ QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, 160)), QSizeF(1 + 80, 160));
+ QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, 160)), QSizeF(50 + 80, 160));
+ QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(-1, 160)), QSizeF(100 + 100, 160));
+
+ // wfh(200) = 200
+ QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, 300)), QSizeF(1 + 200, 300));
+ QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, 300)), QSizeF(50 + 200, 300));
+ QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(-1, 300)), QSizeF(100 + 200, 300));
+}
+
+void tst_QGraphicsGridLayout::heightForWidthWithSpanning()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ RectWidget *w = new RectWidget;
+ w->setSizeHint(Qt::MinimumSize, QSizeF(1,1));
+ w->setSizeHint(Qt::MaximumSize, QSizeF(30000,30000));
+ w->setConstraintFunction(hfw);
+ QSizePolicy sp(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ sp.setHeightForWidth(true);
+ w->setSizePolicy(sp);
+ layout->addItem(w, 0,0,2,2);
+
+ QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, -1)), QSizeF(1, 1));
+ QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(-1, -1)), QSizeF(200, 100));
+ QEXPECT_FAIL("", "Due to an old bug this wrongly returns QWIDGETSIZE_MAX", Continue);
+ QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(-1, -1)), QSizeF(30000, 30000));
+
+ QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(200, -1)), QSizeF(200, 100));
+ QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(200, -1)), QSizeF(200, 100));
+ QEXPECT_FAIL("", "Due to an old bug this wrongly returns QWIDGETSIZE_MAX", Continue);
+ QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(200, -1)), QSizeF(200, 100));
+
+ QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(2, -1)), QSizeF(2, 10000));
+ QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(2, -1)), QSizeF(2, 10000));
+ QEXPECT_FAIL("", "Due to an old bug this wrongly returns QWIDGETSIZE_MAX", Continue);
+ QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(2, -1)), QSizeF(2, 10000));
+
+ QCOMPARE(layout->effectiveSizeHint(Qt::MinimumSize, QSizeF(200, -1)), QSizeF(200, 100));
+ QCOMPARE(layout->effectiveSizeHint(Qt::PreferredSize, QSizeF(200, -1)), QSizeF(200, 100));
+ QEXPECT_FAIL("", "Due to an old bug this wrongly returns QWIDGETSIZE_MAX", Continue);
+ QCOMPARE(layout->effectiveSizeHint(Qt::MaximumSize, QSizeF(200, -1)), QSizeF(200, 10000));
+}
+
+Q_DECLARE_METATYPE(QSizePolicy::Policy)
+void tst_QGraphicsGridLayout::spanningItem2x2_data()
+{
+ QTest::addColumn<QSizePolicy::Policy>("sizePolicy");
+ QTest::addColumn<int>("itemHeight");
+ QTest::addColumn<int>("expectedHeight");
+
+ QTest::newRow("A larger spanning item with 2 widgets with fixed policy") << QSizePolicy::Fixed << 39 << 80;
+ QTest::newRow("A larger spanning item with 2 widgets with preferred policy") << QSizePolicy::Preferred << 39 << 80;
+ QTest::newRow("An equally-sized spanning item with 2 widgets with fixed policy") << QSizePolicy::Fixed << 40 << 80;
+ QTest::newRow("An equally-sized spanning item with 2 widgets with preferred policy") << QSizePolicy::Preferred << 40 << 80;
+ QTest::newRow("A smaller spanning item with 2 widgets with fixed policy") << QSizePolicy::Fixed << 41 << 82;
+ QTest::newRow("A smaller spanning item with 2 widgets with preferred policy") << QSizePolicy::Preferred << 41 << 82;
+}
+
+void tst_QGraphicsGridLayout::spanningItem2x2()
+{
+ QFETCH(QSizePolicy::Policy, sizePolicy);
+ QFETCH(int, itemHeight);
+ QFETCH(int, expectedHeight);
+ QGraphicsWidget *form = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout(form);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ QGraphicsWidget *w1 = new QGraphicsWidget;
+ w1->setMinimumSize(80,80);
+ w1->setMaximumSize(80,80);
+
+ QGraphicsWidget *w2 = new QGraphicsWidget;
+ w2->setMinimumSize(80,itemHeight);
+ w2->setPreferredSize(80,itemHeight);
+ w2->setSizePolicy(QSizePolicy::Fixed, sizePolicy);
+
+ QGraphicsWidget *w3 = new QGraphicsWidget;
+ w3->setMinimumSize(80,itemHeight);
+ w3->setPreferredSize(80,itemHeight);
+ w3->setSizePolicy(QSizePolicy::Fixed, sizePolicy);
+
+ layout->addItem(w1, 0, 0, 2, 1);
+ layout->addItem(w2, 0, 1);
+ layout->addItem(w3, 1, 1);
+
+ QCOMPARE(layout->minimumSize(), QSizeF(160,expectedHeight));
+ if(sizePolicy == QSizePolicy::Fixed)
+ QCOMPARE(layout->maximumSize(), QSizeF(160,expectedHeight));
+ else
+ QCOMPARE(layout->maximumSize(), QSizeF(160,QWIDGETSIZE_MAX));
+}
+
+void tst_QGraphicsGridLayout::spanningItem2x3_data()
+{
+ QTest::addColumn<bool>("w1_fixed");
+ QTest::addColumn<bool>("w2_fixed");
+ QTest::addColumn<bool>("w3_fixed");
+ QTest::addColumn<bool>("w4_fixed");
+ QTest::addColumn<bool>("w5_fixed");
+
+ for(int w1 = 0; w1 < 2; w1++)
+ for(int w2 = 0; w2 < 2; w2++)
+ for(int w3 = 0; w3 < 2; w3++)
+ for(int w4 = 0; w4 < 2; w4++)
+ for(int w5 = 0; w5 < 2; w5++) {
+ QString description = QString("Fixed sizes:") + (w1?" w1":"") + (w2?" w2":"") + (w3?" w3":"") + (w4?" w4":"") + (w5?" w5":"");
+ QTest::newRow(description.toLatin1()) << (bool)w1 << (bool)w2 << (bool)w3 << (bool)w4 << (bool)w5;
+ }
+}
+
+void tst_QGraphicsGridLayout::spanningItem2x3()
+{
+ QFETCH(bool, w1_fixed);
+ QFETCH(bool, w2_fixed);
+ QFETCH(bool, w3_fixed);
+ QFETCH(bool, w4_fixed);
+ QFETCH(bool, w5_fixed);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ QGraphicsWidget *w1 = new QGraphicsWidget;
+ w1->setMinimumSize(80,80);
+ w1->setMaximumSize(80,80);
+ if (w1_fixed)
+ w1->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+
+ QGraphicsWidget *w2 = new QGraphicsWidget;
+ w2->setMinimumSize(80,48);
+ w2->setPreferredSize(80,48);
+ if (w2_fixed)
+ w2->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+
+ QGraphicsWidget *w3 = new QGraphicsWidget;
+ w3->setMinimumSize(80,30);
+ w3->setPreferredSize(80,30);
+ if (w3_fixed)
+ w3->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+
+ QGraphicsWidget *w4 = new QGraphicsWidget;
+ w4->setMinimumSize(80,30);
+ w4->setMaximumSize(80,30);
+ if (w4_fixed)
+ w4->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+
+ QGraphicsWidget *w5 = new QGraphicsWidget;
+ w5->setMinimumSize(40,24);
+ w5->setMaximumSize(40,24);
+ if (w5_fixed)
+ w5->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+
+ layout->addItem(w1, 0, 0, 2, 1);
+ layout->addItem(w2, 0, 1);
+ layout->addItem(w3, 1, 1);
+ layout->addItem(w4, 0, 2);
+ layout->addItem(w5, 1, 2);
+
+ QCOMPARE(layout->minimumSize(), QSizeF(240,80));
+ // Only w2 and w3 grow vertically, so when they have a fixed vertical size policy,
+ // the whole layout cannot grow vertically.
+ if (w2_fixed && w3_fixed)
+ QCOMPARE(layout->maximumSize(), QSizeF(QWIDGETSIZE_MAX,80));
+ else
+ QCOMPARE(layout->maximumSize(), QSizeF(QWIDGETSIZE_MAX,QWIDGETSIZE_MAX));
+}
+
+void tst_QGraphicsGridLayout::spanningItem()
+{
+ QGraphicsWidget *form = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout(form);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ QGraphicsWidget *w1 = new QGraphicsWidget;
+ w1->setMinimumSize(80,80);
+ w1->setMaximumSize(80,80);
+
+ QGraphicsWidget *w2 = new QGraphicsWidget;
+ w2->setMinimumSize(80,38);
+ w2->setPreferredSize(80,38);
+ w2->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+
+ QGraphicsWidget *w3 = new QGraphicsWidget;
+ w3->setMinimumSize(80,38);
+ w3->setPreferredSize(80,38);
+ w3->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+
+ layout->addItem(w1, 0, 0, 2, 1);
+ layout->addItem(w2, 0, 1);
+ layout->addItem(w3, 1, 1);
+
+ QCOMPARE(layout->minimumSize(), QSizeF(160,80));
+ QCOMPARE(layout->maximumSize(), QSizeF(160,80));
+}
+
+void tst_QGraphicsGridLayout::stretchAndHeightForWidth()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout;
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ RectWidget *w1 = new RectWidget;
+ w1->setSizeHint(Qt::MinimumSize, QSizeF(10, 10));
+ w1->setSizeHint(Qt::PreferredSize, QSizeF(100, 100));
+ w1->setSizeHint(Qt::MaximumSize, QSizeF(500, 500));
+ layout->addItem(w1, 0,0,1,1);
+
+ RectWidget *w2 = new RectWidget;
+ w2->setSizeHint(Qt::MinimumSize, QSizeF(10, 10));
+ w2->setSizeHint(Qt::PreferredSize, QSizeF(100, 100));
+ w2->setSizeHint(Qt::MaximumSize, QSizeF(500, 500));
+ layout->addItem(w2, 0,1,1,1);
+ layout->setColumnStretchFactor(1, 2);
+
+ QApplication::sendPostedEvents();
+ QGraphicsScene scene;
+ QGraphicsView *view = new QGraphicsView(&scene);
+
+ scene.addItem(widget);
+
+ view->show();
+
+ widget->resize(500, 100);
+ // w1 should stay at its preferred size
+ QCOMPARE(w1->geometry(), QRectF(0, 0, 100, 100));
+ QCOMPARE(w2->geometry(), QRectF(100, 0, 400, 100));
+
+
+ // only w1 has hfw
+ w1->setConstraintFunction(hfw);
+ QSizePolicy sp(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ sp.setHeightForWidth(true);
+ w1->setSizePolicy(sp);
+ QApplication::sendPostedEvents();
+
+ QCOMPARE(w1->geometry(), QRectF(0, 0, 100, 200));
+ QCOMPARE(w2->geometry(), QRectF(100, 0, 400, 200));
+
+ // only w2 has hfw
+ w2->setConstraintFunction(hfw);
+ w2->setSizePolicy(sp);
+
+ w1->setConstraintFunction(0);
+ sp.setHeightForWidth(false);
+ w1->setSizePolicy(sp);
+ QApplication::sendPostedEvents();
+
+ QCOMPARE(w1->geometry(), QRectF(0, 0, 100, 100));
+ QCOMPARE(w2->geometry(), QRectF(100, 0, 400, 50));
+
+}
+
+void tst_QGraphicsGridLayout::testDefaultAlignment()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsGridLayout *layout = new QGraphicsGridLayout(widget);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ QGraphicsWidget *w = new QGraphicsWidget;
+ w->setMinimumSize(50,50);
+ w->setMaximumSize(50,50);
+ layout->addItem(w,0,0);
+
+ //Default alignment should be to the top-left
+
+ //First, check by forcing the layout to be bigger
+ layout->setMinimumSize(100,100);
+ layout->activate();
+ QCOMPARE(layout->geometry(), QRectF(0,0,100,100));
+ QCOMPARE(w->geometry(), QRectF(0,0,50,50));
+ layout->setMinimumSize(-1,-1);
+
+ //Second, check by forcing the column and row to be bigger instead
+ layout->setColumnMinimumWidth(0, 100);
+ layout->setRowMinimumHeight(0, 100);
+ layout->activate();
+ QCOMPARE(layout->geometry(), QRectF(0,0,100,100));
+ QCOMPARE(w->geometry(), QRectF(0,0,50,50));
+ layout->setMinimumSize(-1,-1);
+ layout->setColumnMinimumWidth(0, 0);
+ layout->setRowMinimumHeight(0, 0);
+
+
+ //Third, check by adding a larger item in the column
+ QGraphicsWidget *w2 = new QGraphicsWidget;
+ w2->setMinimumSize(100,100);
+ w2->setMaximumSize(100,100);
+ layout->addItem(w2,1,0);
+ layout->activate();
+ QCOMPARE(layout->geometry(), QRectF(0,0,100,150));
+ QCOMPARE(w->geometry(), QRectF(0,0,50,50));
+ QCOMPARE(w2->geometry(), QRectF(0,50,100,100));
+}
+QTEST_MAIN(tst_QGraphicsGridLayout)
+#include "tst_qgraphicsgridlayout.moc"
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/.gitignore b/tests/auto/widgets/graphicsview/qgraphicsitem/.gitignore
new file mode 100644
index 0000000000..b766388e3e
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsitem/.gitignore
@@ -0,0 +1 @@
+tst_qgraphicsitem
diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro b/tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro
new file mode 100644
index 0000000000..51a4426680
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsitem/qgraphicsitem.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+QT += widgets widgets-private
+QT += core-private gui-private
+SOURCES += tst_qgraphicsitem.cpp
+DEFINES += QT_NO_CAST_TO_ASCII
+
+win32:!wince*: LIBS += -lUser32
+
+contains(QT_CONFIG,xcb):qpa:CONFIG+=insignificant_test # QTBUG-20756 crashes on qpa, xcb
diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
new file mode 100644
index 0000000000..8ac1f6b5c5
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
@@ -0,0 +1,11402 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.1, 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <private/qgraphicsitem_p.h>
+#include <private/qgraphicsview_p.h>
+#include <private/qgraphicsscene_p.h>
+#include <QStyleOptionGraphicsItem>
+#include <QAbstractTextDocumentLayout>
+#include <QBitmap>
+#include <QCursor>
+#include <QLabel>
+#include <QDial>
+#include <QGraphicsItem>
+#include <QGraphicsScene>
+#include <QGraphicsSceneEvent>
+#include <QGraphicsView>
+#include <QGraphicsWidget>
+#include <QGraphicsProxyWidget>
+#include <QPainter>
+#include <QScrollBar>
+#include <QVBoxLayout>
+#include <QGraphicsEffect>
+#include <QInputContext>
+#include <QPushButton>
+#include <QLineEdit>
+#include <QGraphicsLinearLayout>
+#include <float.h>
+
+//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
+
+#if defined(Q_WS_MAC)
+// On mac (cocoa) we always get full update.
+// So check that the expected region is contained inside the actual
+#define COMPARE_REGIONS(ACTUAL, EXPECTED) QVERIFY((EXPECTED).subtracted(ACTUAL).isEmpty())
+#else
+#define COMPARE_REGIONS QTRY_COMPARE
+#endif
+
+#include "../../../platformquirks.h"
+
+static QGraphicsRectItem staticItem; //QTBUG-7629, we should not crash at exit.
+
+static void sendMousePress(QGraphicsScene *scene, const QPointF &point, Qt::MouseButton button = Qt::LeftButton)
+{
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setScenePos(point);
+ event.setButton(button);
+ event.setButtons(button);
+ QApplication::sendEvent(scene, &event);
+}
+
+static void sendMouseMove(QGraphicsScene *scene, const QPointF &point,
+ Qt::MouseButton button = Qt::NoButton, Qt::MouseButtons /* buttons */ = 0)
+{
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
+ event.setScenePos(point);
+ event.setButton(button);
+ event.setButtons(button);
+ QApplication::sendEvent(scene, &event);
+}
+
+static void sendMouseRelease(QGraphicsScene *scene, const QPointF &point, Qt::MouseButton button = Qt::LeftButton)
+{
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.setScenePos(point);
+ event.setButton(button);
+ QApplication::sendEvent(scene, &event);
+}
+
+static void sendMouseClick(QGraphicsScene *scene, const QPointF &point, Qt::MouseButton button = Qt::LeftButton)
+{
+ sendMousePress(scene, point, button);
+ sendMouseRelease(scene, point, button);
+}
+
+static void sendKeyPress(QGraphicsScene *scene, Qt::Key key)
+{
+ QKeyEvent keyEvent(QEvent::KeyPress, key, Qt::NoModifier);
+ QApplication::sendEvent(scene, &keyEvent);
+}
+
+static void sendKeyRelease(QGraphicsScene *scene, Qt::Key key)
+{
+ QKeyEvent keyEvent(QEvent::KeyRelease, key, Qt::NoModifier);
+ QApplication::sendEvent(scene, &keyEvent);
+}
+
+static void sendKeyClick(QGraphicsScene *scene, Qt::Key key)
+{
+ sendKeyPress(scene, key);
+ sendKeyRelease(scene, key);
+}
+
+class EventSpy : public QGraphicsWidget
+{
+ Q_OBJECT
+public:
+ EventSpy(QObject *watched, QEvent::Type type)
+ : _count(0), spied(type)
+ {
+ watched->installEventFilter(this);
+ }
+
+ EventSpy(QGraphicsScene *scene, QGraphicsItem *watched, QEvent::Type type)
+ : _count(0), spied(type)
+ {
+ scene->addItem(this);
+ watched->installSceneEventFilter(this);
+ }
+
+ int count() const { return _count; }
+
+protected:
+ bool eventFilter(QObject *watched, QEvent *event)
+ {
+ Q_UNUSED(watched);
+ if (event->type() == spied)
+ ++_count;
+ return false;
+ }
+
+ bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
+ {
+ Q_UNUSED(watched);
+ if (event->type() == spied)
+ ++_count;
+ return false;
+ }
+
+ int _count;
+ QEvent::Type spied;
+};
+
+class EventSpy2 : public QGraphicsWidget
+{
+ Q_OBJECT
+public:
+ EventSpy2(QObject *watched)
+ {
+ watched->installEventFilter(this);
+ }
+
+ EventSpy2(QGraphicsScene *scene, QGraphicsItem *watched)
+ {
+ scene->addItem(this);
+ watched->installSceneEventFilter(this);
+ }
+
+ QMap<QEvent::Type, int> counts;
+
+protected:
+ bool eventFilter(QObject *watched, QEvent *event)
+ {
+ Q_UNUSED(watched);
+ ++counts[event->type()];
+ return false;
+ }
+
+ bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
+ {
+ Q_UNUSED(watched);
+ ++counts[event->type()];
+ return false;
+ }
+};
+
+class EventTester : public QGraphicsItem
+{
+public:
+ EventTester(QGraphicsItem *parent = 0) : QGraphicsItem(parent), 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 *o, QWidget *)
+ {
+ hints = painter->renderHints();
+ painter->setBrush(brush);
+ painter->drawRect(boundingRect());
+ lastExposedRect = o->exposedRect;
+ ++repaints;
+ }
+
+ bool sceneEvent(QEvent *event)
+ {
+ events << event->type();
+ return QGraphicsItem::sceneEvent(event);
+ }
+
+ void reset()
+ {
+ events.clear();
+ hints = QPainter::RenderHints(0);
+ repaints = 0;
+ lastExposedRect = QRectF();
+ }
+
+ QList<QEvent::Type> events;
+ QPainter::RenderHints hints;
+ int repaints;
+ QRectF br;
+ QRectF lastExposedRect;
+ QBrush brush;
+};
+
+class MyGraphicsView : public QGraphicsView
+{
+public:
+ int repaints;
+ QRegion paintedRegion;
+ MyGraphicsView(QGraphicsScene *scene, QWidget *parent=0) : QGraphicsView(scene,parent), repaints(0) {}
+ void paintEvent(QPaintEvent *e)
+ {
+ paintedRegion += e->region();
+ ++repaints;
+ QGraphicsView::paintEvent(e);
+ }
+ void reset() { repaints = 0; paintedRegion = QRegion(); }
+};
+
+class tst_QGraphicsItem : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void init();
+
+private slots:
+ void construction();
+ void constructionWithParent();
+ void destruction();
+ void deleteChildItem();
+ void scene();
+ void parentItem();
+ void setParentItem();
+ void children();
+ void flags();
+ void inputMethodHints();
+ void toolTip();
+ void visible();
+ void isVisibleTo();
+ 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 mapRectFromToParent_data();
+ void mapRectFromToParent();
+ 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 childrenBoundingRectTransformed();
+ void childrenBoundingRect2();
+ void childrenBoundingRect3();
+ void childrenBoundingRect4();
+ void childrenBoundingRect5();
+ void group();
+ void setGroup();
+ void setGroup2();
+ void nestedGroups();
+ void warpChildrenIntoGroup();
+ void removeFromGroup();
+ void handlesChildEvents();
+ void handlesChildEvents2();
+ void handlesChildEvents3();
+ void filtersChildEvents();
+ void filtersChildEvents2();
+ 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 itemClipsChildrenToShape3();
+ void itemClipsChildrenToShape4();
+ void itemClipsChildrenToShape5();
+ 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 opacity2();
+ void opacityZeroUpdates();
+ void itemStacksBehindParent();
+ void nestedClipping();
+ void nestedClippingTransforms();
+ void sceneTransformCache();
+ void tabChangesFocus();
+ void tabChangesFocus_data();
+ void cacheMode();
+ void cacheMode2();
+ void updateCachedItemAfterMove();
+ void deviceTransform_data();
+ void deviceTransform();
+ void update();
+ void setTransformProperties_data();
+ void setTransformProperties();
+ void itemUsesExtendedStyleOption();
+ void itemSendsGeometryChanges();
+ void moveItem();
+ void moveLineItem();
+ void sorting_data();
+ void sorting();
+ void itemHasNoContents();
+ void hitTestUntransformableItem();
+ void hitTestGraphicsEffectItem();
+ void focusProxy();
+ void subFocus();
+ void focusProxyDeletion();
+ void negativeZStacksBehindParent();
+ void setGraphicsEffect();
+ void panel();
+ void addPanelToActiveScene();
+ void panelWithFocusItem();
+ void activate();
+ void setActivePanelOnInactiveScene();
+ void activationOnShowHide();
+ void moveWhileDeleting();
+ void ensureDirtySceneTransform();
+ void focusScope();
+ void focusScope2();
+ void stackBefore();
+ void sceneModality();
+ void panelModality();
+ void mixedModality();
+ void modality_hover();
+ void modality_mouseGrabber();
+ void modality_clickFocus();
+ void modality_keyEvents();
+ void itemIsInFront();
+ void scenePosChange();
+ void updateMicroFocus();
+ void textItem_shortcuts();
+ void scroll();
+ void focusHandling_data();
+ void focusHandling();
+ void touchEventPropagation_data();
+ void touchEventPropagation();
+ void deviceCoordinateCache_simpleRotations();
+
+ // task specific tests below me
+ void task141694_textItemEnsureVisible();
+ void task128696_textItemEnsureMovable();
+ void ensureUpdateOnTextItem();
+ void task177918_lineItemUndetected();
+ void task240400_clickOnTextItem_data();
+ void task240400_clickOnTextItem();
+ void task243707_addChildBeforeParent();
+ void task197802_childrenVisibility();
+ void QTBUG_4233_updateCachedWithSceneRect();
+ void QTBUG_5418_textItemSetDefaultColor();
+ void QTBUG_6738_missingUpdateWithSetParent();
+ void QTBUG_7714_fullUpdateDiscardingOpacityUpdate2();
+ void QT_2653_fullUpdateDiscardingOpacityUpdate();
+ void QT_2649_focusScope();
+ void sortItemsWhileAdding();
+ void doNotMarkFullUpdateIfNotInScene();
+ void itemDiesDuringDraggingOperation();
+ void QTBUG_12112_focusItem();
+ void QTBUG_13473_sceneposchange();
+ void QTBUG_16374_crashInDestructor();
+ void QTBUG_20699_focusScopeCrash();
+
+private:
+ QList<QGraphicsItem *> paintedItems;
+};
+
+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);
+ QCOMPARE(item->flags(), 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);
+ QCOMPARE(item->flags(), 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);
+ QCOMPARE(item->flags(), 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);
+ QCOMPARE(item->flags(), 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);
+ QCOMPARE(item->flags(), 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);
+ QCOMPARE(item->flags(), 0);
+ break;
+ case 6:
+ item = new QGraphicsTextItem;
+ QCOMPARE(int(item->type()), int(QGraphicsTextItem::Type));
+ QCOMPARE(qgraphicsitem_cast<QGraphicsTextItem *>(item), (QGraphicsTextItem *)item);
+ QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
+ // This is the only item that uses an extended style option.
+ QCOMPARE(item->flags(), QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemUsesExtendedStyleOption));
+ break;
+ default:
+ qFatal("You broke the logic, please fix!");
+ break;
+ }
+
+ QCOMPARE(item->scene(), (QGraphicsScene *)0);
+ QCOMPARE(item->parentItem(), (QGraphicsItem *)0);
+ QVERIFY(item->children().isEmpty());
+ 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);
+ {
+ QGraphicsScene *scene = new QGraphicsScene;
+ QGraphicsRectItem *parent = new QGraphicsRectItem;
+ Item *child = new Item;
+ child->setParentItem(parent);
+ parent->setVisible(false);
+ scene->addItem(parent);
+ QCOMPARE(child->parentItem(), static_cast<QGraphicsItem*>(parent));
+ delete scene;
+ QCOMPARE(itemDeleted, 110);
+ }
+}
+
+void tst_QGraphicsItem::deleteChildItem()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *rect = scene.addRect(QRectF());
+ QGraphicsItem *child1 = new QGraphicsRectItem(rect);
+ QGraphicsItem *child2 = new QGraphicsRectItem(rect);
+ QGraphicsItem *child3 = new QGraphicsRectItem(rect);
+ Q_UNUSED(child3);
+ delete child1;
+ child2->setParentItem(0);
+ delete child2;
+}
+
+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;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ 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));
+ }
+ {
+ QGraphicsItem* clippingParent = new QGraphicsRectItem;
+ clippingParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
+
+ QGraphicsItem* nonClippingParent = new QGraphicsRectItem;
+ nonClippingParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
+
+ QGraphicsItem* child = new QGraphicsRectItem(nonClippingParent);
+ QVERIFY(!child->isClipped());
+
+ child->setParentItem(clippingParent);
+ QVERIFY(child->isClipped());
+
+ child->setParentItem(nonClippingParent);
+ QVERIFY(!child->isClipped());
+ }
+}
+
+class ImhTester : public QGraphicsItem
+{
+ QRectF boundingRect() const { return QRectF(); }
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) {}
+};
+
+void tst_QGraphicsItem::inputMethodHints()
+{
+ ImhTester *item = new ImhTester;
+ item->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
+ item->setFlag(QGraphicsItem::ItemIsFocusable, true);
+ QCOMPARE(item->inputMethodHints(), Qt::ImhNone);
+ ImhTester *item2 = new ImhTester;
+ item2->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
+ item2->setFlag(QGraphicsItem::ItemIsFocusable, true);
+ Qt::InputMethodHints imHints = item2->inputMethodHints();
+ imHints |= Qt::ImhHiddenText;
+ item2->setInputMethodHints(imHints);
+ QGraphicsScene scene;
+ scene.addItem(item);
+ scene.addItem(item2);
+ QGraphicsView view(&scene);
+ QApplication::setActiveWindow(&view);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ item->setFocus();
+ QTRY_VERIFY(item->hasFocus());
+ QCOMPARE(view.inputMethodHints(), item->inputMethodHints());
+ item2->setFocus();
+ QTRY_VERIFY(item2->hasFocus());
+ QCOMPARE(view.inputMethodHints(), item2->inputMethodHints());
+ item->setFlag(QGraphicsItem::ItemAcceptsInputMethod, false);
+ item->setFocus();
+ QTRY_VERIFY(item->hasFocus());
+ //Focus has changed but the new item doesn't accept input method, no hints.
+ QCOMPARE(view.inputMethodHints(), 0);
+ item2->setFocus();
+ QTRY_VERIFY(item2->hasFocus());
+ QCOMPARE(view.inputMethodHints(), item2->inputMethodHints());
+ imHints = item2->inputMethodHints();
+ imHints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
+ item2->setInputMethodHints(imHints);
+ QCOMPARE(view.inputMethodHints(), item2->inputMethodHints());
+ QGraphicsProxyWidget *widget = new QGraphicsProxyWidget;
+ QLineEdit *edit = new QLineEdit;
+ edit->setEchoMode(QLineEdit::Password);
+ scene.addItem(widget);
+ widget->setFocus();
+ QTRY_VERIFY(widget->hasFocus());
+ //No widget on the proxy, so no hints
+ QCOMPARE(view.inputMethodHints(), 0);
+ widget->setWidget(edit);
+ //View should match with the line edit
+ QCOMPARE(view.inputMethodHints(), edit->inputMethodHints());
+}
+
+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;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ 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::isVisibleTo()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *parent = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsItem *child = scene.addRect(QRectF(25, 25, 50, 50));
+ QGraphicsItem *grandChild = scene.addRect(QRectF(50, 50, 50, 50));
+ QGraphicsItem *stranger = scene.addRect(100, 100, 100, 100);
+
+ child->setParentItem(parent);
+ grandChild->setParentItem(child);
+
+ QVERIFY(grandChild->isVisible());
+ QVERIFY(grandChild->isVisibleTo(grandChild));
+ QVERIFY(grandChild->isVisibleTo(child));
+ QVERIFY(grandChild->isVisibleTo(parent));
+ QVERIFY(grandChild->isVisibleTo(0));
+ QVERIFY(child->isVisible());
+ QVERIFY(child->isVisibleTo(child));
+ QVERIFY(child->isVisibleTo(parent));
+ QVERIFY(child->isVisibleTo(0));
+ QVERIFY(parent->isVisible());
+ QVERIFY(parent->isVisibleTo(parent));
+ QVERIFY(parent->isVisibleTo(0));
+ QVERIFY(!parent->isVisibleTo(child));
+ QVERIFY(!child->isVisibleTo(grandChild));
+ QVERIFY(!grandChild->isVisibleTo(stranger));
+ QVERIFY(!child->isVisibleTo(stranger));
+ QVERIFY(!parent->isVisibleTo(stranger));
+ QVERIFY(!stranger->isVisibleTo(grandChild));
+ QVERIFY(!stranger->isVisibleTo(child));
+ QVERIFY(!stranger->isVisibleTo(parent));
+
+ // Case 1: only parent is explicitly hidden
+ parent->hide();
+
+ QVERIFY(!grandChild->isVisible());
+ QVERIFY(grandChild->isVisibleTo(grandChild));
+ QVERIFY(grandChild->isVisibleTo(child));
+ QVERIFY(grandChild->isVisibleTo(parent));
+ QVERIFY(!grandChild->isVisibleTo(0));
+ QVERIFY(!child->isVisible());
+ QVERIFY(child->isVisibleTo(child));
+ QVERIFY(child->isVisibleTo(parent));
+ QVERIFY(!child->isVisibleTo(0));
+ QVERIFY(!parent->isVisible());
+ QVERIFY(!parent->isVisibleTo(parent));
+ QVERIFY(!parent->isVisibleTo(0));
+ QVERIFY(!parent->isVisibleTo(child));
+ QVERIFY(!child->isVisibleTo(grandChild));
+ QVERIFY(!grandChild->isVisibleTo(stranger));
+ QVERIFY(!child->isVisibleTo(stranger));
+ QVERIFY(!parent->isVisibleTo(stranger));
+ QVERIFY(!stranger->isVisibleTo(grandChild));
+ QVERIFY(!stranger->isVisibleTo(child));
+ QVERIFY(!stranger->isVisibleTo(parent));
+
+ // Case 2: only child is hidden
+ parent->show();
+ child->hide();
+
+ QVERIFY(!grandChild->isVisible());
+ QVERIFY(grandChild->isVisibleTo(grandChild));
+ QVERIFY(grandChild->isVisibleTo(child));
+ QVERIFY(!grandChild->isVisibleTo(parent));
+ QVERIFY(!grandChild->isVisibleTo(0));
+ QVERIFY(!child->isVisible());
+ QVERIFY(!child->isVisibleTo(child));
+ QVERIFY(!child->isVisibleTo(parent));
+ QVERIFY(!child->isVisibleTo(0));
+ QVERIFY(parent->isVisible());
+ QVERIFY(parent->isVisibleTo(parent));
+ QVERIFY(parent->isVisibleTo(0));
+ QVERIFY(!parent->isVisibleTo(child));
+ QVERIFY(!child->isVisibleTo(grandChild));
+ QVERIFY(!grandChild->isVisibleTo(stranger));
+ QVERIFY(!child->isVisibleTo(stranger));
+ QVERIFY(!parent->isVisibleTo(stranger));
+ QVERIFY(!stranger->isVisibleTo(grandChild));
+ QVERIFY(!stranger->isVisibleTo(child));
+ QVERIFY(!stranger->isVisibleTo(parent));
+
+ // Case 3: only grand child is hidden
+ child->show();
+ grandChild->hide();
+
+ QVERIFY(!grandChild->isVisible());
+ QVERIFY(!grandChild->isVisibleTo(grandChild));
+ QVERIFY(!grandChild->isVisibleTo(child));
+ QVERIFY(!grandChild->isVisibleTo(parent));
+ QVERIFY(!grandChild->isVisibleTo(0));
+ QVERIFY(child->isVisible());
+ QVERIFY(child->isVisibleTo(child));
+ QVERIFY(child->isVisibleTo(parent));
+ QVERIFY(child->isVisibleTo(0));
+ QVERIFY(parent->isVisible());
+ QVERIFY(parent->isVisibleTo(parent));
+ QVERIFY(parent->isVisibleTo(0));
+ QVERIFY(!parent->isVisibleTo(child));
+ QVERIFY(!child->isVisibleTo(grandChild));
+ QVERIFY(!grandChild->isVisibleTo(stranger));
+ QVERIFY(!child->isVisibleTo(stranger));
+ QVERIFY(!parent->isVisibleTo(stranger));
+ QVERIFY(!stranger->isVisibleTo(grandChild));
+ QVERIFY(!stranger->isVisibleTo(child));
+ QVERIFY(!stranger->isVisibleTo(parent));
+}
+
+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;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ 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();
+
+ QTest::qWaitForWindowShown(&view);
+ 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::mouseMove(view.viewport());
+ 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::qWaitForWindowShown(&view);
+ QTest::qWait(20);
+
+ QTRY_VERIFY(!text->isSelected());
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0,
+ view.mapFromScene(text->mapToScene(0, 0)));
+ QTRY_VERIFY(text->isSelected());
+
+ text->setSelected(false);
+ text->setTextInteractionFlags(Qt::TextEditorInteraction);
+
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0,
+ view.mapFromScene(text->mapToScene(0, 0)));
+ QTRY_VERIFY(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(20);
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Click on item2
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
+ QTest::qWait(20);
+ QVERIFY(item2->isSelected());
+ QVERIFY(!item1->isSelected());
+
+ // Ctrl-click on item1
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(20);
+ 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(20);
+ QVERIFY(item2->isSelected());
+ QVERIFY(!item1->isSelected());
+
+ // Ctrl-click on item2
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item2->scenePos()));
+ QTest::qWait(20);
+ QVERIFY(!item2->isSelected());
+ QVERIFY(!item1->isSelected());
+
+ // Click on item1
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(20);
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Click on scene
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(0, 0));
+ QTest::qWait(20);
+ QVERIFY(!item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Click on item1
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(20);
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Ctrl-click on scene
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(0, 0));
+ QTest::qWait(20);
+ QVERIFY(!item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Click on item1
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(20);
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Press on item2
+ QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
+ QTest::qWait(20);
+ QVERIFY(!item1->isSelected());
+ QVERIFY(item2->isSelected());
+
+ // Release on item2
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
+ QTest::qWait(20);
+ QVERIFY(!item1->isSelected());
+ QVERIFY(item2->isSelected());
+
+ // Click on item1
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(20);
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Ctrl-click on item1
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(20);
+ QVERIFY(!item1->isSelected());
+ QVERIFY(!item2->isSelected());
+
+ // Ctrl-press on item1
+ QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(20);
+ 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(20);
+ QVERIFY(!item1->isSelected());
+ QVERIFY(!item2->isSelected());
+ }
+
+ // Release on item1
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(20);
+ 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(20);
+ 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(20);
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+ }
+
+ // Release on item1
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
+ QTest::qWait(20);
+ 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;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ scene.addItem(line);
+
+ line->setFocus();
+ QVERIFY(!line->hasFocus());
+ line->setFlag(QGraphicsItem::ItemIsFocusable);
+ line->setFocus();
+ QVERIFY(line->hasFocus());
+
+ QGraphicsScene scene2;
+ QApplication::sendEvent(&scene2, &activate);
+
+ 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 *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ { _paintedItems << this; painter->fillRect(boundingRect(), Qt::red); }
+};
+
+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
+
+ QTRY_VERIFY(!_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::mapRectFromToParent_data()
+{
+ QTest::addColumn<bool>("parent");
+ QTest::addColumn<QPointF>("parentPos");
+ QTest::addColumn<QTransform>("parentTransform");
+ QTest::addColumn<QPointF>("pos");
+ QTest::addColumn<QTransform>("transform");
+ QTest::addColumn<QRectF>("inputRect");
+ QTest::addColumn<QRectF>("outputRect");
+
+ QTest::newRow("nil") << false << QPointF() << QTransform() << QPointF() << QTransform() << QRectF() << QRectF();
+ QTest::newRow("simple") << false << QPointF() << QTransform() << QPointF() << QTransform()
+ << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10);
+ QTest::newRow("simple w/parent") << true
+ << QPointF() << QTransform()
+ << QPointF() << QTransform()
+ << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10);
+ QTest::newRow("simple w/parent parentPos") << true
+ << QPointF(50, 50) << QTransform()
+ << QPointF() << QTransform()
+ << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10);
+ QTest::newRow("simple w/parent parentPos parentRotation") << true
+ << QPointF(50, 50) << QTransform().rotate(45)
+ << QPointF() << QTransform()
+ << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10);
+ QTest::newRow("pos w/parent") << true
+ << QPointF() << QTransform()
+ << QPointF(50, 50) << QTransform()
+ << QRectF(0, 0, 10, 10) << QRectF(50, 50, 10, 10);
+ QTest::newRow("rotation w/parent") << true
+ << QPointF() << QTransform()
+ << QPointF() << QTransform().rotate(90)
+ << QRectF(0, 0, 10, 10) << QRectF(-10, 0, 10, 10);
+ QTest::newRow("pos rotation w/parent") << true
+ << QPointF() << QTransform()
+ << QPointF(50, 50) << QTransform().rotate(90)
+ << QRectF(0, 0, 10, 10) << QRectF(40, 50, 10, 10);
+ QTest::newRow("pos rotation w/parent parentPos parentRotation") << true
+ << QPointF(-170, -190) << QTransform().rotate(90)
+ << QPointF(50, 50) << QTransform().rotate(90)
+ << QRectF(0, 0, 10, 10) << QRectF(40, 50, 10, 10);
+}
+
+void tst_QGraphicsItem::mapRectFromToParent()
+{
+ QFETCH(bool, parent);
+ QFETCH(QPointF, parentPos);
+ QFETCH(QTransform, parentTransform);
+ QFETCH(QPointF, pos);
+ QFETCH(QTransform, transform);
+ QFETCH(QRectF, inputRect);
+ QFETCH(QRectF, outputRect);
+
+ QGraphicsRectItem *rect = new QGraphicsRectItem;
+ rect->setPos(pos);
+ rect->setTransform(transform);
+
+ if (parent) {
+ QGraphicsRectItem *rectParent = new QGraphicsRectItem;
+ rect->setParentItem(rectParent);
+ rectParent->setPos(parentPos);
+ rectParent->setTransform(parentTransform);
+ }
+
+ // Make sure we use non-destructive transform operations (e.g., 90 degree
+ // rotations).
+ QCOMPARE(rect->mapRectToParent(inputRect), outputRect);
+ QCOMPARE(rect->mapRectFromParent(outputRect), inputRect);
+ QCOMPARE(rect->itemTransform(rect->parentItem()).mapRect(inputRect), outputRect);
+ QCOMPARE(rect->mapToParent(inputRect).boundingRect(), outputRect);
+ QCOMPARE(rect->mapToParent(QPolygonF(inputRect)).boundingRect(), outputRect);
+ QCOMPARE(rect->mapFromParent(outputRect).boundingRect(), inputRect);
+ QCOMPARE(rect->mapFromParent(QPolygonF(outputRect)).boundingRect(), inputRect);
+ QPainterPath inputPath;
+ inputPath.addRect(inputRect);
+ QPainterPath outputPath;
+ outputPath.addRect(outputRect);
+ QCOMPARE(rect->mapToParent(inputPath).boundingRect(), outputPath.boundingRect());
+ QCOMPARE(rect->mapFromParent(outputPath).boundingRect(), inputPath.boundingRect());
+}
+
+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;
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(150);
+
+ EventTester *tester = new EventTester;
+ scene.addItem(tester);
+ tester->setAcceptsHoverEvents(true);
+
+ QTRY_COMPARE(tester->repaints, 1);
+
+ // 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, 0, 100, 100));
+
+ 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);
+
+ scene.addPolygon(parent->mapToScene(parent->boundingRect() | parent->childrenBoundingRect()))->setPen(QPen(Qt::red));;
+
+ QGraphicsView view(&scene);
+ view.show();
+
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(30);
+
+ QCOMPARE(parent->childrenBoundingRect(), QRectF(-500, -100, 600, 800));
+}
+
+void tst_QGraphicsItem::childrenBoundingRectTransformed()
+{
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect4 = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect5 = scene.addRect(QRectF(0, 0, 100, 100));
+ rect2->setParentItem(rect);
+ rect3->setParentItem(rect2);
+ rect4->setParentItem(rect3);
+ rect5->setParentItem(rect4);
+
+ rect2->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect2->setPos(25, 25);
+ rect3->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect3->setPos(25, 25);
+ rect4->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect4->setPos(25, 25);
+ rect5->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect5->setPos(25, 25);
+
+ QRectF subTreeRect = rect->childrenBoundingRect();
+ QCOMPARE(subTreeRect.left(), qreal(-206.0660171779821));
+ QCOMPARE(subTreeRect.top(), qreal(75.0));
+ QCOMPARE(subTreeRect.width(), qreal(351.7766952966369));
+ QCOMPARE(subTreeRect.height(), qreal(251.7766952966369));
+
+ rect->rotate(45);
+ rect2->rotate(-45);
+ rect3->rotate(45);
+ rect4->rotate(-45);
+ rect5->rotate(45);
+
+ subTreeRect = rect->childrenBoundingRect();
+ QCOMPARE(rect->childrenBoundingRect(), QRectF(-100, 75, 275, 250));
+}
+
+void tst_QGraphicsItem::childrenBoundingRect2()
+{
+ QGraphicsItemGroup box;
+ QGraphicsLineItem l1(0, 0, 100, 0, &box);
+ QGraphicsLineItem l2(100, 0, 100, 100, &box);
+ QGraphicsLineItem l3(0, 0, 0, 100, &box);
+ // Make sure lines (zero with/height) are included in the childrenBoundingRect.
+ QCOMPARE(box.childrenBoundingRect(), QRectF(0, 0, 100, 100));
+}
+
+void tst_QGraphicsItem::childrenBoundingRect3()
+{
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect4 = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *rect5 = scene.addRect(QRectF(0, 0, 100, 100));
+ rect2->setParentItem(rect);
+ rect3->setParentItem(rect2);
+ rect4->setParentItem(rect3);
+ rect5->setParentItem(rect4);
+
+ rect2->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect2->setPos(25, 25);
+ rect3->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect3->setPos(25, 25);
+ rect4->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect4->setPos(25, 25);
+ rect5->setTransform(QTransform().translate(50, 50).rotate(45));
+ rect5->setPos(25, 25);
+
+ // Try to mess up the cached bounding rect.
+ (void)rect2->childrenBoundingRect();
+
+ QRectF subTreeRect = rect->childrenBoundingRect();
+ QCOMPARE(subTreeRect.left(), qreal(-206.0660171779821));
+ QCOMPARE(subTreeRect.top(), qreal(75.0));
+ QCOMPARE(subTreeRect.width(), qreal(351.7766952966369));
+ QCOMPARE(subTreeRect.height(), qreal(251.7766952966369));
+}
+
+void tst_QGraphicsItem::childrenBoundingRect4()
+{
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 10, 10));
+ QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 20, 20));
+ QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 30, 30));
+ rect2->setParentItem(rect);
+ rect3->setParentItem(rect);
+
+ QGraphicsView view(&scene);
+ view.show();
+
+ QTest::qWaitForWindowShown(&view);
+
+ // Try to mess up the cached bounding rect.
+ rect->childrenBoundingRect();
+ rect2->childrenBoundingRect();
+
+ rect3->setOpacity(0.0);
+ rect3->setParentItem(rect2);
+
+ QCOMPARE(rect->childrenBoundingRect(), rect3->boundingRect());
+ QCOMPARE(rect2->childrenBoundingRect(), rect3->boundingRect());
+}
+
+void tst_QGraphicsItem::childrenBoundingRect5()
+{
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *parent = scene.addRect(QRectF(0, 0, 100, 100));
+ QGraphicsRectItem *child = scene.addRect(QRectF(0, 0, 100, 100));
+ child->setParentItem(parent);
+
+ QGraphicsView view(&scene);
+ view.show();
+
+ QTest::qWaitForWindowShown(&view);
+
+ // Try to mess up the cached bounding rect.
+ QRectF expectedChildrenBoundingRect = parent->boundingRect();
+ QCOMPARE(parent->childrenBoundingRect(), expectedChildrenBoundingRect);
+
+ // Apply some effects.
+ QGraphicsDropShadowEffect *dropShadow = new QGraphicsDropShadowEffect;
+ dropShadow->setOffset(25, 25);
+ child->setGraphicsEffect(dropShadow);
+ parent->setGraphicsEffect(new QGraphicsOpacityEffect);
+
+ QVERIFY(parent->childrenBoundingRect() != expectedChildrenBoundingRect);
+ expectedChildrenBoundingRect |= dropShadow->boundingRect();
+ QCOMPARE(parent->childrenBoundingRect(), expectedChildrenBoundingRect);
+}
+
+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::qWaitForWindowShown(&view);
+ QApplication::processEvents();
+
+ 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(25);
+
+ 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(25);
+
+ 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::setGroup2()
+{
+ QGraphicsScene scene;
+ QGraphicsItemGroup group;
+ scene.addItem(&group);
+
+ QGraphicsRectItem *rect = scene.addRect(50,50,50,50,Qt::NoPen,Qt::black);
+ rect->setTransformOriginPoint(50,50);
+ rect->setRotation(45);
+ rect->setScale(1.5);
+ rect->translate(20,20);
+ group.translate(-30,-40);
+ group.setRotation(180);
+ group.setScale(0.5);
+
+ QTransform oldSceneTransform = rect->sceneTransform();
+ rect->setGroup(&group);
+ QCOMPARE(rect->sceneTransform(), oldSceneTransform);
+
+ group.setRotation(20);
+ group.setScale(2);
+ rect->setRotation(90);
+ rect->setScale(0.8);
+
+ oldSceneTransform = rect->sceneTransform();
+ rect->setGroup(0);
+ QCOMPARE(rect->sceneTransform(), oldSceneTransform);
+}
+
+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 *blue = new ChildEventTester(QRectF(0, 0, 100, 100));
+ ChildEventTester *red = new ChildEventTester(QRectF(0, 0, 50, 50));
+ ChildEventTester *green = new ChildEventTester(QRectF(0, 0, 25, 25));
+ ChildEventTester *gray = new ChildEventTester(QRectF(0, 0, 25, 25));
+ ChildEventTester *yellow = new ChildEventTester(QRectF(0, 0, 50, 50));
+
+ blue->setBrush(QBrush(Qt::blue));
+ red->setBrush(QBrush(Qt::red));
+ yellow->setBrush(QBrush(Qt::yellow));
+ green->setBrush(QBrush(Qt::green));
+ gray->setBrush(QBrush(Qt::gray));
+ red->setPos(50, 0);
+ yellow->setPos(50, 50);
+ green->setPos(25, 0);
+ gray->setPos(25, 25);
+ red->setParentItem(blue);
+ yellow->setParentItem(blue);
+ green->setParentItem(red);
+ gray->setParentItem(red);
+
+ QGraphicsScene scene;
+ scene.addItem(blue);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(20);
+
+ // Pull out the items, closest item first
+ QList<QGraphicsItem *> items = scene.items(scene.itemsBoundingRect());
+ QCOMPARE(items.at(0), (QGraphicsItem *)yellow);
+ QCOMPARE(items.at(1), (QGraphicsItem *)gray);
+ QCOMPARE(items.at(2), (QGraphicsItem *)green);
+ QCOMPARE(items.at(3), (QGraphicsItem *)red);
+ QCOMPARE(items.at(4), (QGraphicsItem *)blue);
+
+ QCOMPARE(blue->counter, 0);
+
+ // Send events to the toplevel item
+ QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
+ QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
+
+ pressEvent.setButton(Qt::LeftButton);
+ pressEvent.setScenePos(blue->mapToScene(5, 5));
+ pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ releaseEvent.setButton(Qt::LeftButton);
+ releaseEvent.setScenePos(blue->mapToScene(5, 5));
+ releaseEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(blue->counter, 2);
+
+ // Send events to a level1 item
+ pressEvent.setScenePos(red->mapToScene(5, 5));
+ pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ releaseEvent.setScenePos(red->mapToScene(5, 5));
+ releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(blue->counter, 2);
+ QCOMPARE(red->counter, 2);
+
+ // Send events to a level2 item
+ pressEvent.setScenePos(green->mapToScene(5, 5));
+ pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ releaseEvent.setScenePos(green->mapToScene(5, 5));
+ releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(blue->counter, 2);
+ QCOMPARE(red->counter, 2);
+ QCOMPARE(green->counter, 2);
+
+ blue->setHandlesChildEvents(true);
+
+ // Send events to a level1 item
+ pressEvent.setScenePos(red->mapToScene(5, 5));
+ pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ releaseEvent.setScenePos(red->mapToScene(5, 5));
+ releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(blue->counter, 4);
+ QCOMPARE(red->counter, 2);
+
+ // Send events to a level2 item
+ pressEvent.setScenePos(green->mapToScene(5, 5));
+ pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ releaseEvent.setScenePos(green->mapToScene(5, 5));
+ releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(blue->counter, 6);
+ QCOMPARE(red->counter, 2);
+ QCOMPARE(green->counter, 2);
+
+ blue->setHandlesChildEvents(false);
+
+ // Send events to a level1 item
+ pressEvent.setScenePos(red->mapToScene(5, 5));
+ pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ releaseEvent.setScenePos(red->mapToScene(5, 5));
+ releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(blue->counter, 6);
+ QCOMPARE(red->counter, 4);
+
+ // Send events to a level2 item
+ pressEvent.setScenePos(green->mapToScene(5, 5));
+ pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ releaseEvent.setScenePos(green->mapToScene(5, 5));
+ releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(blue->counter, 6);
+ QCOMPARE(red->counter, 4);
+ QCOMPARE(green->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();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
+
+ QMouseEvent event(QEvent::MouseButtonPress, view.mapFromScene(5, 5),
+ view.viewport()->mapToGlobal(view.mapFromScene(5, 5)), Qt::LeftButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &event);
+
+ QTRY_COMPARE(root->counter, 1);
+}
+
+void tst_QGraphicsItem::handlesChildEvents3()
+{
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ 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 ChildEventFilterTester : public ChildEventTester
+{
+public:
+ ChildEventFilterTester(const QRectF &rect, QGraphicsItem *parent = 0)
+ : ChildEventTester(rect, parent), filter(QEvent::None)
+ { }
+
+ QEvent::Type filter;
+
+protected:
+ bool sceneEventFilter(QGraphicsItem *item, QEvent *event)
+ {
+ Q_UNUSED(item);
+ if (event->type() == filter) {
+ ++counter;
+ return true;
+ }
+ return false;
+ }
+};
+
+void tst_QGraphicsItem::filtersChildEvents()
+{
+ QGraphicsScene scene;
+ ChildEventFilterTester *root = new ChildEventFilterTester(QRectF(0, 0, 10, 10));
+ ChildEventFilterTester *filter = new ChildEventFilterTester(QRectF(10, 10, 10, 10), root);
+ ChildEventTester *child = new ChildEventTester(QRectF(20, 20, 10, 10), filter);
+
+ // setup filter
+ filter->setFiltersChildEvents(true);
+ filter->filter = QEvent::GraphicsSceneMousePress;
+
+ scene.addItem(root);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(20);
+
+ QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
+ QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
+
+ // send event to child
+ pressEvent.setButton(Qt::LeftButton);
+ pressEvent.setScenePos(QPointF(25, 25));//child->mapToScene(5, 5));
+ pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ releaseEvent.setButton(Qt::LeftButton);
+ releaseEvent.setScenePos(QPointF(25, 25));//child->mapToScene(5, 5));
+ releaseEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QTRY_COMPARE(child->counter, 1); // mouse release is not filtered
+ QCOMPARE(filter->counter, 1); // mouse press is filtered
+ QCOMPARE(root->counter, 0);
+
+ // add another filter
+ root->setFiltersChildEvents(true);
+ root->filter = QEvent::GraphicsSceneMouseRelease;
+
+ // send event to child
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(child->counter, 1);
+ QCOMPARE(filter->counter, 2); // mouse press is filtered
+ QCOMPARE(root->counter, 1); // mouse release is filtered
+
+ // reparent to another sub-graph
+ ChildEventTester *parent = new ChildEventTester(QRectF(10, 10, 10, 10), root);
+ child->setParentItem(parent);
+
+ // send event to child
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &releaseEvent);
+
+ QCOMPARE(child->counter, 2); // mouse press is _not_ filtered
+ QCOMPARE(parent->counter, 0);
+ QCOMPARE(filter->counter, 2);
+ QCOMPARE(root->counter, 2); // mouse release is filtered
+}
+
+void tst_QGraphicsItem::filtersChildEvents2()
+{
+ ChildEventFilterTester *root = new ChildEventFilterTester(QRectF(0, 0, 10, 10));
+ root->setFiltersChildEvents(true);
+ root->filter = QEvent::GraphicsSceneMousePress;
+ QVERIFY(root->filtersChildEvents());
+
+ ChildEventTester *child = new ChildEventTester(QRectF(0, 0, 10, 10), root);
+ QVERIFY(!child->filtersChildEvents());
+
+ 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->filtersChildEvents());
+ QVERIFY(!child3->filtersChildEvents());
+ QVERIFY(!child4->filtersChildEvents());
+
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ QGraphicsView view(&scene);
+ view.show();
+
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
+
+ QMouseEvent event(QEvent::MouseButtonPress, view.mapFromScene(5, 5),
+ view.viewport()->mapToGlobal(view.mapFromScene(5, 5)), Qt::LeftButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &event);
+
+ QTRY_COMPARE(root->counter, 1);
+ QCOMPARE(child->counter, 0);
+ QCOMPARE(child2->counter, 0);
+ QCOMPARE(child3->counter, 0);
+ QCOMPARE(child4->counter, 0);
+}
+
+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();
+ QTest::qWaitForWindowShown(&view);
+
+ for (int i = 0; i < 25; ++i) {
+ view.scale(qreal(1.06), qreal(1.06));
+ QApplication::processEvents();
+ }
+
+ item->ensureVisible(-100, -100, 25, 25);
+ QTest::qWait(25);
+
+ 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);
+ QApplication::processEvents();
+
+ 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(25);
+}
+
+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);
+
+ QWidget topLevel;
+ QGraphicsView view(&scene,&topLevel);
+ view.setFixedSize(200, 100);
+ topLevel.show();
+ QTest::mouseMove(&view, view.rect().center());
+
+ QTest::qWait(25);
+
+ QCursor cursor = view.viewport()->cursor();
+
+ {
+ QMouseEvent event(QEvent::MouseMove, QPoint(100, 50), Qt::NoButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &event);
+ }
+
+ QTest::qWait(25);
+
+ 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 (!PlatformQuirks::haveMouseCursor())
+ return;
+#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(25);
+
+ 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(25);
+
+ 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, -10, 300, 200));
+}
+
+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::NoTextInteraction);
+ QVERIFY(!(text->flags() & QGraphicsItem::ItemAcceptsInputMethod));
+ text->setTextInteractionFlags(Qt::TextEditorInteraction);
+ QCOMPARE(text->textInteractionFlags(), Qt::TextInteractionFlags(Qt::TextEditorInteraction));
+ QVERIFY(text->flags() & QGraphicsItem::ItemAcceptsInputMethod);
+
+ {
+ 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:
+ ItemChangeTester()
+ { setFlag(ItemSendsGeometryChanges); clear(); }
+ ItemChangeTester(QGraphicsItem *parent) : QGraphicsRectItem(parent)
+ { setFlag(ItemSendsGeometryChanges); clear(); }
+
+ void clear()
+ {
+ itemChangeReturnValue = QVariant();
+ itemSceneChangeTargetScene = 0;
+ changes.clear();
+ values.clear();
+ oldValues.clear();
+ }
+
+ 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;
+ case QGraphicsItem::ItemScenePositionHasChanged:
+ break;
+ case QGraphicsItem::ItemRotationChange:
+ oldValues << rotation();
+ break;
+ case QGraphicsItem::ItemRotationHasChanged:
+ break;
+ case QGraphicsItem::ItemScaleChange:
+ oldValues << scale();
+ break;
+ case QGraphicsItem::ItemScaleHasChanged:
+ break;
+ case QGraphicsItem::ItemTransformOriginPointChange:
+ oldValues << transformOriginPoint();
+ break;
+ case QGraphicsItem::ItemTransformOriginPointHasChanged:
+ 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));
+ }
+ {
+ // ItemZValueChange / ItemZValueHasChanged
+ tester.itemChangeReturnValue = qreal(2.0);
+ tester.setZValue(1.0);
+ ++changeCount; // notification sent too
+ ++changeCount;
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemZValueChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemZValueHasChanged);
+ QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(qreal(1.0)));
+ QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(qreal(2.0)));
+ QCOMPARE(tester.oldValues.last(), QVariant(qreal(0.0)));
+ QCOMPARE(tester.zValue(), qreal(2.0));
+ }
+ {
+ // ItemRotationChange / ItemRotationHasChanged
+ tester.itemChangeReturnValue = qreal(15.0);
+ tester.setRotation(10.0);
+ ++changeCount; // notification sent too
+ ++changeCount;
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemRotationChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemRotationHasChanged);
+ QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(qreal(10.0)));
+ QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(qreal(15.0)));
+ QCOMPARE(tester.oldValues.last(), QVariant(qreal(0.0)));
+ QCOMPARE(tester.rotation(), qreal(15.0));
+ }
+ {
+ // ItemScaleChange / ItemScaleHasChanged
+ tester.itemChangeReturnValue = qreal(2.0);
+ tester.setScale(1.5);
+ ++changeCount; // notification sent too
+ ++changeCount;
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemScaleChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemScaleHasChanged);
+ QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(qreal(1.5)));
+ QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(qreal(2.0)));
+ QCOMPARE(tester.oldValues.last(), QVariant(qreal(1.0)));
+ QCOMPARE(tester.scale(), qreal(2.0));
+ }
+ {
+ // ItemTransformOriginPointChange / ItemTransformOriginPointHasChanged
+ tester.itemChangeReturnValue = QPointF(2.0, 2.0);
+ tester.setTransformOriginPoint(1.0, 1.0);
+ ++changeCount; // notification sent too
+ ++changeCount;
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemTransformOriginPointChange);
+ QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemTransformOriginPointHasChanged);
+ QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(QPointF(1.0, 1.0)));
+ QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(QPointF(2.0, 2.0)));
+ QCOMPARE(tester.oldValues.last(), QVariant(QPointF(0.0, 0.0)));
+ QCOMPARE(tester.transformOriginPoint(), QPointF(2.0, 2.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);
+ QVariant expectedFlags = qVariantFromValue<quint32>(QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges));
+ QCOMPARE(tester.values.at(tester.values.size() - 2), expectedFlags);
+ QCOMPARE(tester.values.at(tester.values.size() - 1), qVariantFromValue<quint32>((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 1
+ ItemChangeTester *test = new ItemChangeTester;
+ test->itemSceneChangeTargetScene = 0;
+ int count = 0;
+ QGraphicsScene *scene = new QGraphicsScene;
+ scene->addItem(test);
+ count = test->changes.size();
+ //We test here the fact that when a child is deleted the parent receive only one ItemChildRemovedChange
+ QGraphicsRectItem *child = new QGraphicsRectItem(test);
+ //We received ItemChildAddedChange
+ QCOMPARE(test->changes.size(), ++count);
+ QCOMPARE(test->changes.last(), QGraphicsItem::ItemChildAddedChange);
+ delete child;
+ child = 0;
+ QCOMPARE(test->changes.size(), ++count);
+ QCOMPARE(test->changes.last(), QGraphicsItem::ItemChildRemovedChange);
+
+ ItemChangeTester *childTester = new ItemChangeTester(test);
+ //Changes contains all sceneHasChanged and so on, we don't want to test that
+ int childCount = childTester->changes.size();
+ //We received ItemChildAddedChange
+ QCOMPARE(test->changes.size(), ++count);
+ child = new QGraphicsRectItem(childTester);
+ //We received ItemChildAddedChange
+ QCOMPARE(childTester->changes.size(), ++childCount);
+ QCOMPARE(childTester->changes.last(), QGraphicsItem::ItemChildAddedChange);
+ //Delete the child of the top level with all its children
+ delete childTester;
+ //Only one removal
+ QCOMPARE(test->changes.size(), ++count);
+ QCOMPARE(test->changes.last(), QGraphicsItem::ItemChildRemovedChange);
+ delete scene;
+ }
+ {
+ // 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);
+ ++changeCount; // ItemSceneChange
+ ++changeCount; // ItemSceneHasChanged
+ QCOMPARE(tester.scene(), (QGraphicsScene *)0);
+ }
+ {
+ // ItemToolTipChange/ItemToolTipHasChanged
+ const QString toolTip(QLatin1String("I'm soo cool"));
+ const QString overridenToolTip(QLatin1String("No, you are not soo cool"));
+ tester.itemChangeReturnValue = overridenToolTip;
+ tester.setToolTip(toolTip);
+ ++changeCount; // ItemToolTipChange
+ ++changeCount; // ItemToolTipHasChanged
+ QCOMPARE(tester.changes.size(), changeCount);
+ QCOMPARE(tester.changes.at(changeCount - 2), QGraphicsItem::ItemToolTipChange);
+ QCOMPARE(tester.values.at(changeCount - 2).toString(), toolTip);
+ QCOMPARE(tester.changes.at(changeCount - 1), QGraphicsItem::ItemToolTipHasChanged);
+ QCOMPARE(tester.values.at(changeCount - 1).toString(), overridenToolTip);
+ QCOMPARE(tester.toolTip(), overridenToolTip);
+ tester.itemChangeReturnValue = QVariant();
+ }
+}
+
+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();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(25);
+
+ 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);
+
+ QTRY_VERIFY(!text1->hasFocus());
+ text1->installSceneEventFilter(tester);
+ text1->setFocus();
+ QTRY_VERIFY(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());
+
+ //Let check if the items are correctly removed from the sceneEventFilters array
+ //to avoid stale pointers.
+ QGraphicsView gv;
+ QGraphicsScene *anotherScene = new QGraphicsScene;
+ QGraphicsTextItem *ti = anotherScene->addText("This is a test #1");
+ ti->moveBy(50, 50);
+ QGraphicsTextItem *ti2 = anotherScene->addText("This is a test #2");
+ QGraphicsTextItem *ti3 = anotherScene->addText("This is a test #3");
+ gv.setScene(anotherScene);
+ gv.show();
+ QTest::qWaitForWindowShown(&gv);
+ QTest::qWait(25);
+ ti->installSceneEventFilter(ti2);
+ ti3->installSceneEventFilter(ti);
+ delete ti2;
+ //we souldn't crash
+ QTest::mouseMove(gv.viewport(), gv.mapFromScene(ti->scenePos()));
+ QTest::qWait(30);
+ delete ti;
+}
+
+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);
+
+ if(PlatformQuirks::isAutoMaximizing())
+ view.showFullScreen();
+ else
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
+#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
+
+ QTRY_COMPARE(paintTester.widget, view.viewport());
+
+ view.hide();
+
+ QGraphicsScene scene2;
+ QGraphicsView view2(&scene2);
+ view2.show();
+ QTest::qWaitForWindowShown(&view2);
+ QTest::qWait(25);
+
+ PaintTester tester2;
+ scene2.addItem(&tester2);
+ qApp->processEvents();
+
+ //First show one paint
+ QTRY_COMPARE(tester2.painted, 1);
+
+ //nominal case, update call paint
+ tester2.update();
+ qApp->processEvents();
+ QTRY_VERIFY(tester2.painted == 2);
+
+ //we remove the item from the scene, number of updates is still the same
+ tester2.update();
+ scene2.removeItem(&tester2);
+ qApp->processEvents();
+ QTRY_VERIFY(tester2.painted == 2);
+
+ //We re-add the item, the number of paint should increase
+ scene2.addItem(&tester2);
+ tester2.update();
+ qApp->processEvents();
+ QTRY_VERIFY(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::itemClipsChildrenToShape3()
+{
+ // Construct a scene with nested children, each 50 pixels offset from the elder.
+ // Set a top-level clipping flag
+ QGraphicsScene scene;
+ QGraphicsRectItem *parent = scene.addRect( 0, 0, 150, 150 );
+ QGraphicsRectItem *child = scene.addRect( 0, 0, 150, 150 );
+ QGraphicsRectItem *grandchild = scene.addRect( 0, 0, 150, 150 );
+ child->setParentItem(parent);
+ grandchild->setParentItem(child);
+ child->setPos( 50, 50 );
+ grandchild->setPos( 50, 50 );
+ parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+
+ QCOMPARE(scene.itemAt(25,25), (QGraphicsItem *)parent);
+ QCOMPARE(scene.itemAt(75,75), (QGraphicsItem *)child);
+ QCOMPARE(scene.itemAt(125,125), (QGraphicsItem *)grandchild);
+ QCOMPARE(scene.itemAt(175,175), (QGraphicsItem *)0);
+
+ // Move child to fully overlap the parent. The grandchild should
+ // now occupy two-thirds of the scene
+ child->prepareGeometryChange();
+ child->setPos( 0, 0 );
+
+ QCOMPARE(scene.itemAt(25,25), (QGraphicsItem *)child);
+ QCOMPARE(scene.itemAt(75,75), (QGraphicsItem *)grandchild);
+ QCOMPARE(scene.itemAt(125,125), (QGraphicsItem *)grandchild);
+ QCOMPARE(scene.itemAt(175,175), (QGraphicsItem *)0);
+}
+
+class MyProxyWidget : public QGraphicsProxyWidget
+{
+public:
+ MyProxyWidget(QGraphicsItem *parent) : QGraphicsProxyWidget(parent)
+ {
+ painted = false;
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ QGraphicsProxyWidget::paint(painter, option, widget);
+ painted = true;
+ }
+ bool painted;
+};
+
+void tst_QGraphicsItem::itemClipsChildrenToShape4()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ QGraphicsWidget * outerWidget = new QGraphicsWidget();
+ outerWidget->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
+ MyProxyWidget * innerWidget = new MyProxyWidget(outerWidget);
+ QLabel * label = new QLabel();
+ label->setText("Welcome back my friends to the show that never ends...");
+ innerWidget->setWidget(label);
+ view.resize(300, 300);
+ scene.addItem(outerWidget);
+ outerWidget->resize( 200, 100 );
+ scene.addEllipse( 100, 100, 100, 50 ); // <-- this is important to trigger the right codepath*
+ //now the label is shown
+ outerWidget->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false );
+ QApplication::setActiveWindow(&view);
+ view.show();
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget *)&view);
+ QTRY_COMPARE(innerWidget->painted, true);
+}
+
+//#define DEBUG_ITEM_CLIPS_CHILDREN_TO_SHAPE_5
+static inline void renderSceneToImage(QGraphicsScene *scene, QImage *image, const QString &filename)
+{
+ image->fill(0);
+ QPainter painter(image);
+ scene->render(&painter);
+ painter.end();
+#ifdef DEBUG_ITEM_CLIPS_CHILDREN_TO_SHAPE_5
+ image->save(filename);
+#else
+ Q_UNUSED(filename);
+#endif
+}
+
+void tst_QGraphicsItem::itemClipsChildrenToShape5()
+{
+ class ParentItem : public QGraphicsRectItem
+ {
+ public:
+ ParentItem(qreal x, qreal y, qreal width, qreal height)
+ : QGraphicsRectItem(x, y, width, height) {}
+
+ QPainterPath shape() const
+ {
+ QPainterPath path;
+ path.addRect(50, 50, 200, 200);
+ return path;
+ }
+ };
+
+ ParentItem *parent = new ParentItem(0, 0, 300, 300);
+ parent->setBrush(Qt::blue);
+ parent->setOpacity(0.5);
+
+ const QRegion parentRegion(0, 0, 300, 300);
+ const QRegion clippedParentRegion = parentRegion & QRect(50, 50, 200, 200);
+ QRegion childRegion;
+ QRegion grandChildRegion;
+
+ QGraphicsRectItem *topLeftChild = new QGraphicsRectItem(0, 0, 100, 100);
+ topLeftChild->setBrush(Qt::red);
+ topLeftChild->setParentItem(parent);
+ childRegion += QRect(0, 0, 100, 100);
+
+ QGraphicsRectItem *topRightChild = new QGraphicsRectItem(0, 0, 100, 100);
+ topRightChild->setBrush(Qt::red);
+ topRightChild->setParentItem(parent);
+ topRightChild->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ topRightChild->setPos(200, 0);
+ childRegion += QRect(200, 0, 100, 100);
+
+ QGraphicsRectItem *topRightGrandChild = new QGraphicsRectItem(0, 0, 100, 100);
+ topRightGrandChild->setBrush(Qt::green);
+ topRightGrandChild->setParentItem(topRightChild);
+ topRightGrandChild->setPos(-40, 40);
+ grandChildRegion += QRect(200 - 40, 0 + 40, 100, 100) & QRect(200, 0, 100, 100);
+
+ QGraphicsRectItem *bottomLeftChild = new QGraphicsRectItem(0, 0, 100, 100);
+ bottomLeftChild->setBrush(Qt::red);
+ bottomLeftChild->setParentItem(parent);
+ bottomLeftChild->setFlag(QGraphicsItem::ItemClipsToShape);
+ bottomLeftChild->setPos(0, 200);
+ childRegion += QRect(0, 200, 100, 100);
+
+ QGraphicsRectItem *bottomLeftGrandChild = new QGraphicsRectItem(0, 0, 160, 160);
+ bottomLeftGrandChild->setBrush(Qt::green);
+ bottomLeftGrandChild->setParentItem(bottomLeftChild);
+ bottomLeftGrandChild->setFlag(QGraphicsItem::ItemClipsToShape);
+ bottomLeftGrandChild->setPos(0, -60);
+ grandChildRegion += QRect(0, 200 - 60, 160, 160);
+
+ QGraphicsRectItem *bottomRightChild = new QGraphicsRectItem(0, 0, 100, 100);
+ bottomRightChild->setBrush(Qt::red);
+ bottomRightChild->setParentItem(parent);
+ bottomRightChild->setPos(200, 200);
+ childRegion += QRect(200, 200, 100, 100);
+
+ QPoint controlPoints[17] = {
+ QPoint(5, 5) , QPoint(95, 5) , QPoint(205, 5) , QPoint(295, 5) ,
+ QPoint(5, 95) , QPoint(95, 95) , QPoint(205, 95) , QPoint(295, 95) ,
+ QPoint(150, 150),
+ QPoint(5, 205), QPoint(95, 205), QPoint(205, 205), QPoint(295, 205),
+ QPoint(5, 295), QPoint(95, 295), QPoint(205, 295), QPoint(295, 295),
+ };
+
+ const QRegion clippedChildRegion = childRegion & QRect(50, 50, 200, 200);
+ const QRegion clippedGrandChildRegion = grandChildRegion & QRect(50, 50, 200, 200);
+
+ QGraphicsScene scene;
+ scene.addItem(parent);
+ QImage sceneImage(300, 300, QImage::Format_ARGB32);
+
+#define VERIFY_CONTROL_POINTS(pRegion, cRegion, gRegion) \
+ for (int i = 0; i < 17; ++i) { \
+ QPoint controlPoint = controlPoints[i]; \
+ QRgb pixel = sceneImage.pixel(controlPoint.x(), controlPoint.y()); \
+ if (pRegion.contains(controlPoint)) \
+ QVERIFY(qBlue(pixel) != 0); \
+ else \
+ QVERIFY(qBlue(pixel) == 0); \
+ if (cRegion.contains(controlPoint)) \
+ QVERIFY(qRed(pixel) != 0); \
+ else \
+ QVERIFY(qRed(pixel) == 0); \
+ if (gRegion.contains(controlPoint)) \
+ QVERIFY(qGreen(pixel) != 0); \
+ else \
+ QVERIFY(qGreen(pixel) == 0); \
+ }
+
+ const QList<QGraphicsItem *> children = parent->childItems();
+ const int childrenCount = children.count();
+
+ for (int i = 0; i < 5; ++i) {
+ QString clipString;
+ QString childString;
+ switch (i) {
+ case 0:
+ // All children stacked in front.
+ childString = QLatin1String("ChildrenInFront.png");
+ foreach (QGraphicsItem *child, children)
+ child->setFlag(QGraphicsItem::ItemStacksBehindParent, false);
+ break;
+ case 1:
+ // All children stacked behind.
+ childString = QLatin1String("ChildrenBehind.png");
+ foreach (QGraphicsItem *child, children)
+ child->setFlag(QGraphicsItem::ItemStacksBehindParent, true);
+ break;
+ case 2:
+ // First half of the children behind, second half in front.
+ childString = QLatin1String("FirstHalfBehind_SecondHalfInFront.png");
+ for (int j = 0; j < childrenCount; ++j) {
+ QGraphicsItem *child = children.at(j);
+ child->setFlag(QGraphicsItem::ItemStacksBehindParent, (j < childrenCount / 2));
+ }
+ break;
+ case 3:
+ // First half of the children in front, second half behind.
+ childString = QLatin1String("FirstHalfInFront_SecondHalfBehind.png");
+ for (int j = 0; j < childrenCount; ++j) {
+ QGraphicsItem *child = children.at(j);
+ child->setFlag(QGraphicsItem::ItemStacksBehindParent, (j >= childrenCount / 2));
+ }
+ break;
+ case 4:
+ // Child2 and child4 behind, rest in front.
+ childString = QLatin1String("Child2And4Behind_RestInFront.png");
+ for (int j = 0; j < childrenCount; ++j) {
+ QGraphicsItem *child = children.at(j);
+ if (j == 1 || j == 3)
+ child->setFlag(QGraphicsItem::ItemStacksBehindParent, true);
+ else
+ child->setFlag(QGraphicsItem::ItemStacksBehindParent, false);
+ }
+ break;
+ default:
+ qFatal("internal error");
+ }
+
+ // Nothing is clipped.
+ parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
+ parent->setFlag(QGraphicsItem::ItemClipsToShape, false);
+ clipString = QLatin1String("nothingClipped_");
+ renderSceneToImage(&scene, &sceneImage, clipString + childString);
+ VERIFY_CONTROL_POINTS(parentRegion, childRegion, grandChildRegion);
+
+ // Parent clips children to shape.
+ parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ clipString = QLatin1String("parentClipsChildrenToShape_");
+ renderSceneToImage(&scene, &sceneImage, clipString + childString);
+ VERIFY_CONTROL_POINTS(parentRegion, clippedChildRegion, clippedGrandChildRegion);
+
+ // Parent clips itself and children to shape.
+ parent->setFlag(QGraphicsItem::ItemClipsToShape);
+ clipString = QLatin1String("parentClipsItselfAndChildrenToShape_");
+ renderSceneToImage(&scene, &sceneImage, clipString + childString);
+ VERIFY_CONTROL_POINTS(clippedParentRegion, clippedChildRegion, clippedGrandChildRegion);
+
+ // Parent clips itself to shape.
+ parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
+ clipString = QLatin1String("parentClipsItselfToShape_");
+ renderSceneToImage(&scene, &sceneImage, clipString + childString);
+ VERIFY_CONTROL_POINTS(clippedParentRegion, childRegion, grandChildRegion);
+ }
+}
+
+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);
+
+ QWidget topLevel;
+ QGraphicsView view(&scene,&topLevel);
+ view.resize(300, 300);
+ topLevel.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
+
+ QTest::qWaitForWindowShown(&view);
+
+ 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(25);
+ }
+}
+
+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();
+ view.resize(200, 200);
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(20);
+
+ 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();
+ QTest::qWaitForWindowShown(&view);
+
+ view.ensureVisible(-1000, -1000, 5, 5);
+ int hscroll = view.horizontalScrollBar()->value();
+ int vscroll = view.verticalScrollBar()->value();
+
+ QTest::qWait(10);
+
+ // This should not cause the view to scroll
+ QTRY_COMPARE(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;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ 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);
+}
+
+class TextItem : public QGraphicsSimpleTextItem
+{
+public:
+ TextItem(const QString& text) : QGraphicsSimpleTextItem(text)
+ {
+ updates = 0;
+ }
+
+ void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget)
+ {
+ updates++;
+ QGraphicsSimpleTextItem::paint(painter, option, widget);
+ }
+
+ int updates;
+};
+
+void tst_QGraphicsItem::ensureUpdateOnTextItem()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(25);
+ TextItem *text1 = new TextItem(QLatin1String("123"));
+ scene.addItem(text1);
+ qApp->processEvents();
+ QTRY_COMPARE(text1->updates,1);
+
+ //same bouding rect but we have to update
+ text1->setText(QLatin1String("321"));
+ qApp->processEvents();
+ QTRY_COMPARE(text1->updates,2);
+}
+
+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::task197802_childrenVisibility()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem item(QRectF(0,0,20,20));
+
+ QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(0,0,10,10), &item);
+ scene.addItem(&item);
+
+ //freshly created: both visible
+ QVERIFY(item.isVisible());
+ QVERIFY(item2->isVisible());
+
+ //hide child: parent visible, child not
+ item2->hide();
+ QVERIFY(item.isVisible());
+ QVERIFY(!item2->isVisible());
+
+ //hide parent: parent and child invisible
+ item.hide();
+ QVERIFY(!item.isVisible());
+ QVERIFY(!item2->isVisible());
+
+ //ask to show the child: parent and child invisible anyways
+ item2->show();
+ QVERIFY(!item.isVisible());
+ QVERIFY(!item2->isVisible());
+
+ //show the parent: both parent and child visible
+ item.show();
+ QVERIFY(item.isVisible());
+ QVERIFY(item2->isVisible());
+
+ delete item2;
+}
+
+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));
+#if 0
+ {
+ 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;
+ }
+#endif
+ 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::opacity2()
+{
+ EventTester *parent = new EventTester;
+ EventTester *child = new EventTester(parent);
+ EventTester *grandChild = new EventTester(child);
+
+ QGraphicsScene scene;
+ scene.addItem(parent);
+
+ MyGraphicsView view(&scene);
+ if(PlatformQuirks::isAutoMaximizing())
+ view.showFullScreen();
+ else
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.repaints >= 1);
+
+#define RESET_REPAINT_COUNTERS \
+ parent->repaints = 0; \
+ child->repaints = 0; \
+ grandChild->repaints = 0; \
+ view.repaints = 0;
+
+ RESET_REPAINT_COUNTERS
+
+ child->setOpacity(0.0);
+ QTest::qWait(10);
+ QTRY_COMPARE(view.repaints, 1);
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(child->repaints, 0);
+ QCOMPARE(grandChild->repaints, 0);
+
+ RESET_REPAINT_COUNTERS
+
+ child->setOpacity(1.0);
+ QTest::qWait(10);
+ QTRY_COMPARE(view.repaints, 1);
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(child->repaints, 1);
+ QCOMPARE(grandChild->repaints, 1);
+
+ RESET_REPAINT_COUNTERS
+
+ parent->setOpacity(0.0);
+ QTest::qWait(10);
+ QTRY_COMPARE(view.repaints, 1);
+ QCOMPARE(parent->repaints, 0);
+ QCOMPARE(child->repaints, 0);
+ QCOMPARE(grandChild->repaints, 0);
+
+ RESET_REPAINT_COUNTERS
+
+ parent->setOpacity(1.0);
+ QTest::qWait(10);
+ QTRY_COMPARE(view.repaints, 1);
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(child->repaints, 1);
+ QCOMPARE(grandChild->repaints, 1);
+
+ grandChild->setFlag(QGraphicsItem::ItemIgnoresParentOpacity);
+ RESET_REPAINT_COUNTERS
+
+ child->setOpacity(0.0);
+ QTest::qWait(10);
+ QTRY_COMPARE(view.repaints, 1);
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(child->repaints, 0);
+ QCOMPARE(grandChild->repaints, 1);
+
+ RESET_REPAINT_COUNTERS
+
+ child->setOpacity(0.0); // Already 0.0; no change.
+ QTest::qWait(10);
+ QTRY_COMPARE(view.repaints, 0);
+ QCOMPARE(parent->repaints, 0);
+ QCOMPARE(child->repaints, 0);
+ QCOMPARE(grandChild->repaints, 0);
+}
+
+void tst_QGraphicsItem::opacityZeroUpdates()
+{
+ EventTester *parent = new EventTester;
+ EventTester *child = new EventTester(parent);
+
+ child->setPos(10, 10);
+
+ QGraphicsScene scene;
+ scene.addItem(parent);
+
+ MyGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.repaints > 0);
+
+ view.reset();
+ parent->setOpacity(0.0);
+
+ QTest::qWait(20);
+
+ // transforming items bounding rect to view coordinates
+ const QRect childDeviceBoundingRect = child->deviceTransform(view.viewportTransform())
+ .mapRect(child->boundingRect()).toRect();
+ const QRect parentDeviceBoundingRect = parent->deviceTransform(view.viewportTransform())
+ .mapRect(parent->boundingRect()).toRect();
+
+ QRegion expectedRegion = parentDeviceBoundingRect.adjusted(-2, -2, 2, 2);
+ expectedRegion += childDeviceBoundingRect.adjusted(-2, -2, 2, 2);
+
+ COMPARE_REGIONS(view.paintedRegion, expectedRegion);
+}
+
+class StacksBehindParentHelper : public QGraphicsRectItem
+{
+public:
+ StacksBehindParentHelper(QList<QGraphicsItem *> *paintedItems, const QRectF &rect, QGraphicsItem *parent = 0)
+ : QGraphicsRectItem(rect, parent), paintedItems(paintedItems)
+ { }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ QGraphicsRectItem::paint(painter, option, widget);
+ paintedItems->append(this);
+ }
+
+private:
+ QList<QGraphicsItem *> *paintedItems;
+};
+
+void tst_QGraphicsItem::itemStacksBehindParent()
+{
+ StacksBehindParentHelper *parent1 = new StacksBehindParentHelper(&paintedItems, QRectF(0, 0, 100, 50));
+ StacksBehindParentHelper *child11 = new StacksBehindParentHelper(&paintedItems, QRectF(-10, 10, 50, 50), parent1);
+ StacksBehindParentHelper *grandChild111 = new StacksBehindParentHelper(&paintedItems, QRectF(-20, 20, 50, 50), child11);
+ StacksBehindParentHelper *child12 = new StacksBehindParentHelper(&paintedItems, QRectF(60, 10, 50, 50), parent1);
+ StacksBehindParentHelper *grandChild121 = new StacksBehindParentHelper(&paintedItems, QRectF(70, 20, 50, 50), child12);
+
+ StacksBehindParentHelper *parent2 = new StacksBehindParentHelper(&paintedItems, QRectF(0, 0, 100, 50));
+ StacksBehindParentHelper *child21 = new StacksBehindParentHelper(&paintedItems, QRectF(-10, 10, 50, 50), parent2);
+ StacksBehindParentHelper *grandChild211 = new StacksBehindParentHelper(&paintedItems, QRectF(-20, 20, 50, 50), child21);
+ StacksBehindParentHelper *child22 = new StacksBehindParentHelper(&paintedItems, QRectF(60, 10, 50, 50), parent2);
+ StacksBehindParentHelper *grandChild221 = new StacksBehindParentHelper(&paintedItems, 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);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(!paintedItems.isEmpty());
+ QTest::qWait(100);
+ paintedItems.clear();
+ view.viewport()->update();
+ QApplication::processEvents();
+ QTRY_COMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
+ << grandChild111 << child11
+ << grandChild121 << child12 << parent1
+ << grandChild211 << child21
+ << grandChild221 << child22 << parent2));
+ QTRY_COMPARE(paintedItems, QList<QGraphicsItem *>()
+ << parent2 << child22 << grandChild221
+ << child21 << grandChild211
+ << parent1 << child12 << grandChild121
+ << child11 << grandChild111);
+
+ child11->setFlag(QGraphicsItem::ItemStacksBehindParent);
+ scene.update();
+ paintedItems.clear();
+ QApplication::processEvents();
+
+ QTRY_COMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
+ << grandChild121 << child12 << parent1
+ << grandChild111 << child11
+ << grandChild211 << child21
+ << grandChild221 << child22 << parent2));
+ QCOMPARE(paintedItems, QList<QGraphicsItem *>()
+ << parent2 << child22 << grandChild221
+ << child21 << grandChild211
+ << child11 << grandChild111
+ << parent1 << child12 << grandChild121);
+
+ child12->setFlag(QGraphicsItem::ItemStacksBehindParent);
+ paintedItems.clear();
+ scene.update();
+ QApplication::processEvents();
+
+ QTRY_COMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
+ << parent1 << grandChild111 << child11
+ << grandChild121 << child12
+ << grandChild211 << child21
+ << grandChild221 << child22 << parent2));
+ QCOMPARE(paintedItems, QList<QGraphicsItem *>()
+ << parent2 << child22 << grandChild221
+ << child21 << grandChild211
+ << child12 << grandChild121
+ << child11 << grandChild111 << parent1);
+}
+
+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.setOptimizationFlag(QGraphicsView::IndirectPainting);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(25);
+
+ QList<QGraphicsItem *> expected;
+ expected << root << l1 << l2 << l3;
+ QTRY_COMPARE(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();
+ QTest::qWaitForWindowShown(&widget);
+ QTest::qWait(2000);
+
+ QTRY_VERIFY(scene.isActive());
+
+ dial1->setFocus();
+ QTest::qWait(15);
+ QTRY_VERIFY(dial1->hasFocus());
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QTest::qWait(15);
+ QTRY_VERIFY(view->hasFocus());
+ QTRY_VERIFY(item->hasFocus());
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QTest::qWait(15);
+
+ if (tabChangesFocus) {
+ QTRY_VERIFY(!view->hasFocus());
+ QTRY_VERIFY(!item->hasFocus());
+ QTRY_VERIFY(dial2->hasFocus());
+ } else {
+ QTRY_VERIFY(view->hasFocus());
+ QTRY_VERIFY(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();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+
+ // Increase the probability of window activation
+ // not causing another repaint of test items.
+ QTest::qWait(50);
+
+ 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(10);
+
+ for (int i = 0; i < 2; ++i) {
+ // No visual change.
+ QTRY_COMPARE(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(25);
+ QTRY_COMPARE(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(25);
+ }
+
+ // 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(25);
+ QTRY_COMPARE(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(25);
+ QTRY_COMPARE(tester->repaints, 2);
+ QCOMPARE(testerChild->repaints, 2);
+ QCOMPARE(testerChild2->repaints, 2);
+
+ // Rotating results in a repaint.
+ tester->rotate(45);
+ QTest::qWait(25);
+ QTRY_COMPARE(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(25);
+ QTRY_COMPARE(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(25);
+ QTRY_COMPARE(tester->repaints, 4);
+ QTRY_COMPARE(testerChild->repaints, 4);
+ QTRY_COMPARE(testerChild2->repaints, 3);
+ tester->resetTransform();
+ testerChild->resetTransform();
+ testerChild2->resetTransform();
+
+ // Explicit update causes a repaint.
+ tester->update(0, 0, 5, 5);
+ QTest::qWait(25);
+ QTRY_COMPARE(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(25);
+ QTRY_COMPARE(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(25);
+ QTRY_COMPARE(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(20);
+ QTRY_COMPARE(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(25);
+ QTRY_COMPARE(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(25);
+ QTRY_COMPARE(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(25);
+ QTRY_COMPARE(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(25);
+ QTRY_COMPARE(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(25);
+ QTRY_COMPARE(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(25);
+ QTRY_COMPARE(tester->repaints, 11);
+ QTRY_COMPARE(testerChild->repaints, 10);
+ QTRY_COMPARE(testerChild2->repaints, 5);
+ tester->resetTransform();
+
+ // Make a huge item
+ tester->setGeometry(QRectF(-4000, -4000, 8000, 8000));
+ QTRY_COMPARE(tester->repaints, 12);
+ QTRY_COMPARE(testerChild->repaints, 11);
+ QTRY_COMPARE(testerChild2->repaints, 5);
+
+ // Move the large item - will cause a repaint as the
+ // cache is clipped.
+ tester->setPos(5, 0);
+ QTRY_COMPARE(tester->repaints, 13);
+ QTRY_COMPARE(testerChild->repaints, 11);
+ QTRY_COMPARE(testerChild2->repaints, 5);
+
+ // Hiding and showing should invalidate the cache
+ tester->hide();
+ QTest::qWait(25);
+ tester->show();
+ QTRY_COMPARE(tester->repaints, 14);
+ QTRY_COMPARE(testerChild->repaints, 12);
+ QTRY_COMPARE(testerChild2->repaints, 6);
+}
+
+void tst_QGraphicsItem::cacheMode2()
+{
+ QGraphicsScene scene(0, 0, 100, 100);
+ QGraphicsView view(&scene);
+ view.resize(150, 150);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+
+ // Increase the probability of window activation
+ // not causing another repaint of test items.
+ QTest::qWait(50);
+
+ EventTester *tester = new EventTester;
+ scene.addItem(tester);
+ QTest::qWait(10);
+ QTRY_COMPARE(tester->repaints, 1);
+
+ // Switching from NoCache to NoCache (no repaint)
+ tester->setCacheMode(QGraphicsItem::NoCache);
+ QTest::qWait(50);
+ QTRY_COMPARE(tester->repaints, 1);
+
+ // Switching from NoCache to DeviceCoordinateCache (no repaint)
+ tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ QTest::qWait(50);
+ QTRY_COMPARE(tester->repaints, 1);
+
+ // Switching from DeviceCoordinateCache to DeviceCoordinateCache (no repaint)
+ tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ QTest::qWait(50);
+ QTRY_COMPARE(tester->repaints, 1);
+
+ // Switching from DeviceCoordinateCache to NoCache (no repaint)
+ tester->setCacheMode(QGraphicsItem::NoCache);
+ QTest::qWait(50);
+ QTRY_COMPARE(tester->repaints, 1);
+
+ // Switching from NoCache to ItemCoordinateCache (repaint)
+ tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
+ QTest::qWait(50);
+ QTRY_COMPARE(tester->repaints, 2);
+
+ // Switching from ItemCoordinateCache to ItemCoordinateCache (no repaint)
+ tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
+ QTest::qWait(50);
+ QTRY_COMPARE(tester->repaints, 2);
+
+ // Switching from ItemCoordinateCache to ItemCoordinateCache with different size (repaint)
+ tester->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(100, 100));
+ QTest::qWait(50);
+ QTRY_COMPARE(tester->repaints, 3);
+
+ // Switching from ItemCoordinateCache to NoCache (repaint)
+ tester->setCacheMode(QGraphicsItem::NoCache);
+ QTest::qWait(50);
+ QTRY_COMPARE(tester->repaints, 4);
+
+ // Switching from DeviceCoordinateCache to ItemCoordinateCache (repaint)
+ tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ QTest::qWait(50);
+ QTRY_COMPARE(tester->repaints, 4);
+ tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
+ QTest::qWait(50);
+ QTRY_COMPARE(tester->repaints, 5);
+
+ // Switching from ItemCoordinateCache to DeviceCoordinateCache (repaint)
+ tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ QTest::qWait(50);
+ QTRY_COMPARE(tester->repaints, 6);
+}
+
+void tst_QGraphicsItem::updateCachedItemAfterMove()
+{
+ // A simple item that uses ItemCoordinateCache
+ EventTester *tester = new EventTester;
+ tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
+
+ // Add to a scene, show in a view, ensure it's painted and reset its
+ // repaint counter.
+ QGraphicsScene scene;
+ scene.addItem(tester);
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QTest::qWait(12);
+ QTRY_VERIFY(tester->repaints > 0);
+ tester->repaints = 0;
+
+ // Move the item, should not cause repaints
+ tester->setPos(10, 0);
+ QTest::qWait(12);
+ QCOMPARE(tester->repaints, 0);
+
+ // Move then update, should cause one repaint
+ tester->setPos(20, 0);
+ tester->update();
+ QTest::qWait(12);
+ QCOMPARE(tester->repaints, 1);
+
+ // Hiding the item doesn't cause a repaint
+ tester->hide();
+ QTest::qWait(12);
+ QCOMPARE(tester->repaints, 1);
+
+ // Moving a hidden item doesn't cause a repaint
+ tester->setPos(30, 0);
+ tester->update();
+ QTest::qWait(12);
+ QCOMPARE(tester->repaints, 1);
+}
+
+class Track : public QGraphicsRectItem
+{
+public:
+ Track(const QRectF &rect)
+ : QGraphicsRectItem(rect)
+ {
+ setAcceptHoverEvents(true);
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
+ {
+ QGraphicsRectItem::paint(painter, option, widget);
+ painter->drawText(boundingRect(), Qt::AlignCenter, QString("%1x%2\n%3x%4").arg(p.x()).arg(p.y()).arg(sp.x()).arg(sp.y()));
+ }
+
+protected:
+ void hoverMoveEvent(QGraphicsSceneHoverEvent *event)
+ {
+ p = event->pos();
+ sp = event->widget()->mapFromGlobal(event->screenPos());
+ update();
+ }
+private:
+ QPointF p;
+ QPoint sp;
+};
+
+void tst_QGraphicsItem::deviceTransform_data()
+{
+ QTest::addColumn<bool>("untransformable1");
+ QTest::addColumn<bool>("untransformable2");
+ QTest::addColumn<bool>("untransformable3");
+ QTest::addColumn<qreal>("rotation1");
+ QTest::addColumn<qreal>("rotation2");
+ QTest::addColumn<qreal>("rotation3");
+ QTest::addColumn<QTransform>("deviceX");
+ QTest::addColumn<QPointF>("mapResult1");
+ QTest::addColumn<QPointF>("mapResult2");
+ QTest::addColumn<QPointF>("mapResult3");
+
+ QTest::newRow("nil") << false << false << false
+ << qreal(0.0) << qreal(0.0) << qreal(0.0)
+ << QTransform()
+ << QPointF(150, 150) << QPointF(250, 250) << QPointF(350, 350);
+ QTest::newRow("deviceX rot 90") << false << false << false
+ << qreal(0.0) << qreal(0.0) << qreal(0.0)
+ << QTransform().rotate(90)
+ << QPointF(-150, 150) << QPointF(-250, 250) << QPointF(-350, 350);
+ QTest::newRow("deviceX rot 90 100") << true << false << false
+ << qreal(0.0) << qreal(0.0) << qreal(0.0)
+ << QTransform().rotate(90)
+ << QPointF(-50, 150) << QPointF(50, 250) << QPointF(150, 350);
+ QTest::newRow("deviceX rot 90 010") << false << true << false
+ << qreal(0.0) << qreal(0.0) << qreal(0.0)
+ << QTransform().rotate(90)
+ << QPointF(-150, 150) << QPointF(-150, 250) << QPointF(-50, 350);
+ QTest::newRow("deviceX rot 90 001") << false << false << true
+ << qreal(0.0) << qreal(0.0) << qreal(0.0)
+ << QTransform().rotate(90)
+ << QPointF(-150, 150) << QPointF(-250, 250) << QPointF(-250, 350);
+ QTest::newRow("deviceX rot 90 111") << true << true << true
+ << qreal(0.0) << qreal(0.0) << qreal(0.0)
+ << QTransform().rotate(90)
+ << QPointF(-50, 150) << QPointF(50, 250) << QPointF(150, 350);
+ QTest::newRow("deviceX rot 90 101") << true << false << true
+ << qreal(0.0) << qreal(0.0) << qreal(0.0)
+ << QTransform().rotate(90)
+ << QPointF(-50, 150) << QPointF(50, 250) << QPointF(150, 350);
+}
+
+void tst_QGraphicsItem::deviceTransform()
+{
+ QFETCH(bool, untransformable1);
+ QFETCH(bool, untransformable2);
+ QFETCH(bool, untransformable3);
+ QFETCH(qreal, rotation1);
+ QFETCH(qreal, rotation2);
+ QFETCH(qreal, rotation3);
+ QFETCH(QTransform, deviceX);
+ QFETCH(QPointF, mapResult1);
+ QFETCH(QPointF, mapResult2);
+ QFETCH(QPointF, mapResult3);
+
+ QGraphicsScene scene;
+ Track *rect1 = new Track(QRectF(0, 0, 100, 100));
+ Track *rect2 = new Track(QRectF(0, 0, 100, 100));
+ Track *rect3 = new Track(QRectF(0, 0, 100, 100));
+ rect2->setParentItem(rect1);
+ rect3->setParentItem(rect2);
+ rect1->setPos(100, 100);
+ rect2->setPos(100, 100);
+ rect3->setPos(100, 100);
+ rect1->rotate(rotation1);
+ rect2->rotate(rotation2);
+ rect3->rotate(rotation3);
+ rect1->setFlag(QGraphicsItem::ItemIgnoresTransformations, untransformable1);
+ rect2->setFlag(QGraphicsItem::ItemIgnoresTransformations, untransformable2);
+ rect3->setFlag(QGraphicsItem::ItemIgnoresTransformations, untransformable3);
+ rect1->setBrush(Qt::red);
+ rect2->setBrush(Qt::green);
+ rect3->setBrush(Qt::blue);
+ scene.addItem(rect1);
+
+ QCOMPARE(rect1->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult1);
+ QCOMPARE(rect2->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult2);
+ QCOMPARE(rect3->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult3);
+}
+
+void tst_QGraphicsItem::update()
+{
+ QGraphicsScene scene;
+ scene.setSceneRect(-100, -100, 200, 200);
+ QWidget topLevel;
+ MyGraphicsView view(&scene,&topLevel);
+
+ topLevel.resize(300, 300);
+ topLevel.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(100);
+
+ EventTester *item = new EventTester;
+ scene.addItem(item);
+ QTest::qWait(100); // Make sure all pending updates are processed.
+ item->repaints = 0;
+
+ item->update(); // Item marked as dirty
+ scene.update(); // Entire scene marked as dirty
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 1);
+
+ // Make sure the dirty state from the previous update is reset so that
+ // the item don't think it is already dirty and discards this update.
+ item->update();
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 2);
+
+ // Make sure a partial update doesn't cause a full update to be discarded.
+ view.reset();
+ item->repaints = 0;
+ item->update(QRectF(0, 0, 5, 5));
+ item->update();
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ QRect itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform())
+ .mapRect(item->boundingRect()).toAlignedRect();
+ QRegion expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2);
+ // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
+ QCOMPARE(view.paintedRegion, expectedRegion);
+
+ // Make sure update requests outside the bounding rect are discarded.
+ view.reset();
+ item->repaints = 0;
+ item->update(-15, -15, 5, 5); // Item's brect: (-10, -10, 20, 20)
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 0);
+ QCOMPARE(view.repaints, 0);
+
+ // Make sure the area occupied by an item is repainted when hiding it.
+ view.reset();
+ item->repaints = 0;
+ item->update(); // Full update; all sub-sequent update requests are discarded.
+ item->hide(); // visible set to 0. ignoreVisible must be set to 1; the item won't be processed otherwise.
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 0);
+ QCOMPARE(view.repaints, 1);
+ // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
+ QCOMPARE(view.paintedRegion, expectedRegion);
+
+ // Make sure item is repainted when shown (after being hidden).
+ view.reset();
+ item->repaints = 0;
+ item->show();
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
+ QCOMPARE(view.paintedRegion, expectedRegion);
+
+ item->repaints = 0;
+ item->hide();
+ qApp->processEvents();
+ view.reset();
+ const QPointF originalPos = item->pos();
+ item->setPos(5000, 5000);
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 0);
+ QCOMPARE(view.repaints, 0);
+ qApp->processEvents();
+
+ item->setPos(originalPos);
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 0);
+ QCOMPARE(view.repaints, 0);
+ item->show();
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
+ QCOMPARE(view.paintedRegion, expectedRegion);
+
+ QGraphicsViewPrivate *viewPrivate = static_cast<QGraphicsViewPrivate *>(qt_widget_private(&view));
+ item->setPos(originalPos + QPoint(50, 50));
+ viewPrivate->updateAll();
+ QVERIFY(viewPrivate->fullUpdatePending);
+ QTest::qWait(50);
+ item->repaints = 0;
+ view.reset();
+ item->setPos(originalPos);
+ QTest::qWait(50);
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ COMPARE_REGIONS(view.paintedRegion, expectedRegion + expectedRegion.translated(50, 50));
+
+ // Make sure moving a parent item triggers an update on the children
+ // (even though the parent itself is outside the viewport).
+ QGraphicsRectItem *parent = new QGraphicsRectItem(0, 0, 10, 10);
+ parent->setPos(-400, 0);
+ item->setParentItem(parent);
+ item->setPos(400, 0);
+ scene.addItem(parent);
+ QTest::qWait(50);
+ itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform())
+ .mapRect(item->boundingRect()).toAlignedRect();
+ expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2);
+ view.reset();
+ item->repaints = 0;
+ parent->translate(-400, 0);
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 0);
+ QCOMPARE(view.repaints, 1);
+ QCOMPARE(view.paintedRegion, expectedRegion);
+ view.reset();
+ item->repaints = 0;
+ parent->translate(400, 0);
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ QCOMPARE(view.paintedRegion, expectedRegion);
+ QCOMPARE(view.paintedRegion, expectedRegion);
+}
+
+void tst_QGraphicsItem::setTransformProperties_data()
+{
+ QTest::addColumn<QPointF>("origin");
+ QTest::addColumn<qreal>("rotation");
+ QTest::addColumn<qreal>("scale");
+
+ QTest::newRow("nothing") << QPointF() << qreal(0.0) << qreal(1.0);
+
+ QTest::newRow("rotation") << QPointF() << qreal(42.2) << qreal(1.0);
+
+ QTest::newRow("rotation dicentred") << QPointF(qreal(22.3), qreal(-56.2))
+ << qreal(-2578.2)
+ << qreal(1.0);
+
+ QTest::newRow("Scale") << QPointF() << qreal(0.0)
+ << qreal(6);
+
+ QTest::newRow("Everything dicentred") << QPointF(qreal(22.3), qreal(-56.2)) << qreal(-175) << qreal(196);
+}
+
+/**
+ * the normal QCOMPARE doesn't work because it doesn't use qFuzzyCompare
+ */
+#define QCOMPARE_TRANSFORM(X1, X2) QVERIFY(((X1)*(X2).inverted()).isIdentity())
+
+void tst_QGraphicsItem::setTransformProperties()
+{
+ QFETCH(QPointF,origin);
+ QFETCH(qreal,rotation);
+ QFETCH(qreal,scale);
+
+ QTransform result;
+ result.translate(origin.x(), origin.y());
+ result.rotate(rotation, Qt::ZAxis);
+ result.scale(scale, scale);
+ result.translate(-origin.x(), -origin.y());
+
+ QGraphicsScene scene;
+ QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
+ scene.addItem(item);
+
+ item->setRotation(rotation);
+ item->setScale(scale);
+ item->setTransformOriginPoint(origin);
+
+ QCOMPARE(item->rotation(), rotation);
+ QCOMPARE(item->scale(), scale);
+ QCOMPARE(item->transformOriginPoint(), origin);
+
+ QCOMPARE(QTransform(), item->transform());
+ QCOMPARE(result, item->sceneTransform());
+
+ //-----------------------------------------------------------------
+ //Change the rotation Z
+ item->setRotation(45);
+ QTransform result2;
+ result2.translate(origin.x(), origin.y());
+ result2.rotate(45);
+ result2.scale(scale, scale);
+ result2.translate(-origin.x(), -origin.y());
+
+ QCOMPARE(item->rotation(), 45.);
+ QCOMPARE(item->scale(), scale);
+ QCOMPARE(item->transformOriginPoint(), origin);
+
+ QCOMPARE(QTransform(), item->transform());
+ QCOMPARE(result2, item->sceneTransform());
+
+ //-----------------------------------------------------------------
+ // calling setTransform() and setPos should change the sceneTransform
+ item->setTransform(result);
+ item->setPos(100, -150.5);
+
+ QCOMPARE(item->rotation(), 45.);
+ QCOMPARE(item->scale(), scale);
+ QCOMPARE(item->transformOriginPoint(), origin);
+ QCOMPARE(result, item->transform());
+
+ QTransform result3(result);
+
+ result3.translate(origin.x(), origin.y());
+ result3.rotate(45);
+ result3.scale(scale, scale);
+ result3.translate(-origin.x(), -origin.y());
+
+ result3 *= QTransform::fromTranslate(100, -150.5); //the pos;
+
+ QCOMPARE(result3, item->sceneTransform());
+
+ //-----------------------------------------------------
+ // setting the propertiees should be the same as setting a transform
+ {//with center origin on the matrix
+ QGraphicsRectItem *item1 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119));
+ scene.addItem(item1);
+ QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119));
+ scene.addItem(item2);
+
+ item1->setPos(12.3, -5);
+ item2->setPos(12.3, -5);
+ item1->setRotation(rotation);
+ item1->setScale(scale);
+ item1->setTransformOriginPoint(origin);
+
+ item2->setTransform(result);
+
+ QCOMPARE_TRANSFORM(item1->sceneTransform(), item2->sceneTransform());
+
+ QCOMPARE_TRANSFORM(item1->itemTransform(item2), QTransform());
+ QCOMPARE_TRANSFORM(item2->itemTransform(item1), QTransform());
+ }
+}
+
+class MyStyleOptionTester : public QGraphicsRectItem
+{
+public:
+ MyStyleOptionTester(const QRectF &rect)
+ : QGraphicsRectItem(rect), startTrack(false)
+ {}
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
+ {
+ if (startTrack) {
+ //Doesn't use the extended style option so the exposed rect is the boundingRect
+ if (!(flags() & QGraphicsItem::ItemUsesExtendedStyleOption)) {
+ QCOMPARE(option->exposedRect, boundingRect());
+ QCOMPARE(option->matrix, QMatrix());
+ } else {
+ QVERIFY(option->exposedRect != QRect());
+ QVERIFY(option->exposedRect != boundingRect());
+ QCOMPARE(option->matrix, sceneTransform().toAffine());
+ }
+ }
+ QGraphicsRectItem::paint(painter, option, widget);
+ }
+ bool startTrack;
+};
+
+void tst_QGraphicsItem::itemUsesExtendedStyleOption()
+{
+ QGraphicsScene scene(0, 0, 300, 300);
+ QGraphicsPixmapItem item;
+ item.setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
+ QCOMPARE(item.flags(), QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemUsesExtendedStyleOption));
+ item.setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, false);
+ QCOMPARE(item.flags(), 0);
+
+ //We now test the content of the style option
+ MyStyleOptionTester *rect = new MyStyleOptionTester(QRect(0, 0, 100, 100));
+ scene.addItem(rect);
+ rect->setPos(200, 200);
+ QWidget topLevel;
+ QGraphicsView view(&scene, &topLevel);
+ topLevel.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ rect->startTrack = false;
+ topLevel.show();
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(60);
+ rect->startTrack = true;
+ rect->update(10, 10, 10, 10);
+ QTest::qWait(60);
+ rect->startTrack = false;
+ rect->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
+ QVERIFY((rect->flags() & QGraphicsItem::ItemUsesExtendedStyleOption));
+ QTest::qWait(60);
+ rect->startTrack = true;
+ rect->update(10, 10, 10, 10);
+ QTest::qWait(60);
+}
+
+void tst_QGraphicsItem::itemSendsGeometryChanges()
+{
+ ItemChangeTester item;
+ item.setFlags(0);
+ item.clear();
+
+ QTransform x = QTransform().rotate(45);
+ QPointF pos(10, 10);
+ qreal o(0.5);
+ qreal r(10.0);
+ qreal s(1.5);
+ QPointF origin(1.0, 1.0);
+ item.setTransform(x);
+ item.setPos(pos);
+ item.setRotation(r);
+ item.setScale(s);
+ item.setTransformOriginPoint(origin);
+ QCOMPARE(item.transform(), x);
+ QCOMPARE(item.pos(), pos);
+ QCOMPARE(item.rotation(), r);
+ QCOMPARE(item.scale(), s);
+ QCOMPARE(item.transformOriginPoint(), origin);
+ QCOMPARE(item.changes.size(), 0);
+
+ item.setOpacity(o);
+ QCOMPARE(item.changes.size(), 2); // opacity
+
+ item.setFlag(QGraphicsItem::ItemSendsGeometryChanges);
+ QCOMPARE(item.changes.size(), 4); // flags
+ item.setTransform(QTransform());
+ item.setPos(QPointF());
+ QCOMPARE(item.changes.size(), 8); // transform + pos
+ QCOMPARE(item.transform(), QTransform());
+ QCOMPARE(item.pos(), QPointF());
+ QCOMPARE(item.opacity(), o);
+ item.setRotation(0.0);
+ item.setScale(1.0);
+ item.setTransformOriginPoint(0.0, 0.0);
+ QCOMPARE(item.changes.size(), 14); // rotation + scale + origin
+ QCOMPARE(item.rotation(), qreal(0.0));
+ QCOMPARE(item.scale(), qreal(1.0));
+ QCOMPARE(item.transformOriginPoint(), QPointF(0.0, 0.0));
+
+ QCOMPARE(item.changes, QList<QGraphicsItem::GraphicsItemChange>()
+ << QGraphicsItem::ItemOpacityChange
+ << QGraphicsItem::ItemOpacityHasChanged
+ << QGraphicsItem::ItemFlagsChange
+ << QGraphicsItem::ItemFlagsHaveChanged
+ << QGraphicsItem::ItemTransformChange
+ << QGraphicsItem::ItemTransformHasChanged
+ << QGraphicsItem::ItemPositionChange
+ << QGraphicsItem::ItemPositionHasChanged
+ << QGraphicsItem::ItemRotationChange
+ << QGraphicsItem::ItemRotationHasChanged
+ << QGraphicsItem::ItemScaleChange
+ << QGraphicsItem::ItemScaleHasChanged
+ << QGraphicsItem::ItemTransformOriginPointChange
+ << QGraphicsItem::ItemTransformOriginPointHasChanged);
+}
+
+// Make sure we update moved items correctly.
+void tst_QGraphicsItem::moveItem()
+{
+ QGraphicsScene scene;
+ scene.setSceneRect(-50, -50, 200, 200);
+
+ MyGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(100);
+
+ EventTester *parent = new EventTester;
+ EventTester *child = new EventTester(parent);
+ EventTester *grandChild = new EventTester(child);
+
+#define RESET_COUNTERS \
+ parent->repaints = 0; \
+ child->repaints = 0; \
+ grandChild->repaints = 0; \
+ view.reset();
+
+ scene.addItem(parent);
+ QTest::qWait(100);
+
+ RESET_COUNTERS
+
+ // Item's boundingRect: (-10, -10, 20, 20).
+ QRect parentDeviceBoundingRect = parent->deviceTransform(view.viewportTransform())
+ .mapRect(parent->boundingRect()).toAlignedRect()
+ .adjusted(-2, -2, 2, 2); // Adjusted for antialiasing.
+
+ parent->setPos(20, 20);
+ qApp->processEvents();
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ QRegion expectedParentRegion = parentDeviceBoundingRect; // old position
+ parentDeviceBoundingRect.translate(20, 20);
+ expectedParentRegion += parentDeviceBoundingRect; // new position
+ COMPARE_REGIONS(view.paintedRegion, expectedParentRegion);
+
+ RESET_COUNTERS
+
+ child->setPos(20, 20);
+ qApp->processEvents();
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(child->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ const QRegion expectedChildRegion = expectedParentRegion.translated(20, 20);
+ COMPARE_REGIONS(view.paintedRegion, expectedChildRegion);
+
+ RESET_COUNTERS
+
+ grandChild->setPos(20, 20);
+ qApp->processEvents();
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(child->repaints, 1);
+ QCOMPARE(grandChild->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ const QRegion expectedGrandChildRegion = expectedParentRegion.translated(40, 40);
+ COMPARE_REGIONS(view.paintedRegion, expectedGrandChildRegion);
+
+ RESET_COUNTERS
+
+ parent->translate(20, 20);
+ qApp->processEvents();
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(child->repaints, 1);
+ QCOMPARE(grandChild->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ expectedParentRegion.translate(20, 20);
+ expectedParentRegion += expectedChildRegion.translated(20, 20);
+ expectedParentRegion += expectedGrandChildRegion.translated(20, 20);
+ COMPARE_REGIONS(view.paintedRegion, expectedParentRegion);
+}
+
+void tst_QGraphicsItem::moveLineItem()
+{
+ QGraphicsScene scene;
+ scene.setSceneRect(0, 0, 200, 200);
+ QGraphicsLineItem *item = new QGraphicsLineItem(0, 0, 100, 0);
+ item->setPos(50, 50);
+ scene.addItem(item);
+
+ MyGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(200);
+ view.reset();
+
+ QRectF brect = item->boundingRect();
+ // Do same adjustments as in qgraphicsscene.cpp
+ if (!brect.width())
+ brect.adjust(qreal(-0.00001), 0, qreal(0.00001), 0);
+ if (!brect.height())
+ brect.adjust(0, qreal(-0.00001), 0, qreal(0.00001));
+ const QRect itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform())
+ .mapRect(brect).toAlignedRect();
+ QRegion expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2); // antialiasing
+
+ // Make sure the calculated region is correct.
+ item->update();
+ QTest::qWait(10);
+ QTRY_COMPARE(view.paintedRegion, expectedRegion);
+ view.reset();
+
+ // Old position: (50, 50)
+ item->setPos(50, 100);
+ expectedRegion += expectedRegion.translated(0, 50);
+ QTest::qWait(10);
+ QCOMPARE(view.paintedRegion, expectedRegion);
+}
+
+void tst_QGraphicsItem::sorting_data()
+{
+ QTest::addColumn<int>("index");
+
+ QTest::newRow("NoIndex") << int(QGraphicsScene::NoIndex);
+ QTest::newRow("BspTreeIndex") << int(QGraphicsScene::BspTreeIndex);
+}
+
+void tst_QGraphicsItem::sorting()
+{
+ if (PlatformQuirks::isAutoMaximizing())
+ QSKIP("Skipped because Platform is auto maximizing", SkipAll);
+
+ _paintedItems.clear();
+
+ QGraphicsScene scene;
+ QGraphicsItem *grid[100][100];
+ for (int x = 0; x < 100; ++x) {
+ for (int y = 0; y < 100; ++y) {
+ PainterItem *item = new PainterItem;
+ item->setPos(x * 25, y * 25);
+ item->setData(0, QString("%1x%2").arg(x).arg(y));
+ grid[x][y] = item;
+ scene.addItem(item);
+ }
+ }
+
+ PainterItem *item1 = new PainterItem;
+ PainterItem *item2 = new PainterItem;
+ item1->setData(0, "item1");
+ item2->setData(0, "item2");
+ scene.addItem(item1);
+ scene.addItem(item2);
+
+ QGraphicsView view(&scene);
+ view.setResizeAnchor(QGraphicsView::NoAnchor);
+ view.setTransformationAnchor(QGraphicsView::NoAnchor);
+ view.resize(120, 100);
+ view.setFrameStyle(0);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(100);
+
+ _paintedItems.clear();
+
+ view.viewport()->repaint();
+#if defined(Q_WS_MAC)
+ // There's no difference between repaint and update on the Mac,
+ // so we have to process events here to make sure we get the event.
+ QTest::qWait(100);
+#endif
+
+ QCOMPARE(_paintedItems, QList<QGraphicsItem *>()
+ << grid[0][0] << grid[0][1] << grid[0][2] << grid[0][3]
+ << grid[1][0] << grid[1][1] << grid[1][2] << grid[1][3]
+ << grid[2][0] << grid[2][1] << grid[2][2] << grid[2][3]
+ << grid[3][0] << grid[3][1] << grid[3][2] << grid[3][3]
+ << grid[4][0] << grid[4][1] << grid[4][2] << grid[4][3]
+ << item1 << item2);
+}
+
+void tst_QGraphicsItem::itemHasNoContents()
+{
+ PainterItem *item1 = new PainterItem;
+ PainterItem *item2 = new PainterItem;
+ item2->setParentItem(item1);
+ item2->setPos(50, 50);
+ item1->setFlag(QGraphicsItem::ItemHasNoContents);
+ item1->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+
+ QGraphicsScene scene;
+ scene.addItem(item1);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(!_paintedItems.isEmpty());
+
+ _paintedItems.clear();
+
+ view.viewport()->repaint();
+#ifdef Q_WS_MAC
+ // There's no difference between update() and repaint() on the Mac,
+ // so we have to process events here to make sure we get the event.
+ QTest::qWait(10);
+#endif
+
+ QTRY_COMPARE(_paintedItems, QList<QGraphicsItem *>() << item2);
+}
+
+void tst_QGraphicsItem::hitTestUntransformableItem()
+{
+ QGraphicsScene scene;
+ scene.setSceneRect(-100, -100, 200, 200);
+
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(100);
+
+ // Confuse the BSP with dummy items.
+ QGraphicsRectItem *dummy = new QGraphicsRectItem(0, 0, 20, 20);
+ dummy->setPos(-100, -100);
+ scene.addItem(dummy);
+ for (int i = 0; i < 100; ++i) {
+ QGraphicsItem *parent = dummy;
+ dummy = new QGraphicsRectItem(0, 0, 20, 20);
+ dummy->setPos(-100 + i, -100 + i);
+ dummy->setParentItem(parent);
+ }
+
+ QGraphicsRectItem *item1 = new QGraphicsRectItem(0, 0, 20, 20);
+ item1->setPos(-200, -200);
+
+ QGraphicsRectItem *item2 = new QGraphicsRectItem(0, 0, 20, 20);
+ item2->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+ item2->setParentItem(item1);
+ item2->setPos(200, 200);
+
+ QGraphicsRectItem *item3 = new QGraphicsRectItem(0, 0, 20, 20);
+ item3->setParentItem(item2);
+ item3->setPos(80, 80);
+
+ scene.addItem(item1);
+ QTest::qWait(100);
+
+ QList<QGraphicsItem *> items = scene.items(QPointF(80, 80));
+ QCOMPARE(items.size(), 1);
+ QCOMPARE(items.at(0), static_cast<QGraphicsItem*>(item3));
+
+ scene.setItemIndexMethod(QGraphicsScene::NoIndex);
+ QTest::qWait(100);
+
+ items = scene.items(QPointF(80, 80));
+ QCOMPARE(items.size(), 1);
+ QCOMPARE(items.at(0), static_cast<QGraphicsItem*>(item3));
+}
+
+void tst_QGraphicsItem::hitTestGraphicsEffectItem()
+{
+ QGraphicsScene scene;
+ scene.setSceneRect(-100, -100, 200, 200);
+
+ QWidget toplevel;
+
+ QGraphicsView view(&scene, &toplevel);
+ toplevel.resize(300, 300);
+ toplevel.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&toplevel);
+#endif
+ QTest::qWait(100);
+
+ // Confuse the BSP with dummy items.
+ QGraphicsRectItem *dummy = new QGraphicsRectItem(0, 0, 20, 20);
+ dummy->setPos(-100, -100);
+ scene.addItem(dummy);
+ for (int i = 0; i < 100; ++i) {
+ QGraphicsItem *parent = dummy;
+ dummy = new QGraphicsRectItem(0, 0, 20, 20);
+ dummy->setPos(-100 + i, -100 + i);
+ dummy->setParentItem(parent);
+ }
+
+ const QRectF itemBoundingRect(0, 0, 20, 20);
+ EventTester *item1 = new EventTester;
+ item1->br = itemBoundingRect;
+ item1->setPos(-200, -200);
+ item1->brush = Qt::red;
+
+ EventTester *item2 = new EventTester;
+ item2->br = itemBoundingRect;
+ item2->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+ item2->setParentItem(item1);
+ item2->setPos(200, 200);
+ item2->brush = Qt::green;
+
+ EventTester *item3 = new EventTester;
+ item3->br = itemBoundingRect;
+ item3->setParentItem(item2);
+ item3->setPos(80, 80);
+ item3->brush = Qt::blue;
+
+ scene.addItem(item1);
+ QTest::qWait(100);
+
+ item1->repaints = 0;
+ item2->repaints = 0;
+ item3->repaints = 0;
+
+ // Apply shadow effect to the entire sub-tree.
+ QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect;
+ shadow->setOffset(-20, -20);
+ item1->setGraphicsEffect(shadow);
+ QTest::qWait(50);
+
+ // Make sure all visible items are repainted.
+ QCOMPARE(item1->repaints, 1);
+ QCOMPARE(item2->repaints, 1);
+ QCOMPARE(item3->repaints, 1);
+
+ // Make sure an item doesn't respond to a click on its shadow.
+ QList<QGraphicsItem *> items = scene.items(QPointF(75, 75));
+ QVERIFY(items.isEmpty());
+ items = scene.items(QPointF(80, 80));
+ QCOMPARE(items.size(), 1);
+ QCOMPARE(items.at(0), static_cast<QGraphicsItem *>(item3));
+
+ scene.setItemIndexMethod(QGraphicsScene::NoIndex);
+ QTest::qWait(100);
+
+ items = scene.items(QPointF(75, 75));
+ QVERIFY(items.isEmpty());
+ items = scene.items(QPointF(80, 80));
+ QCOMPARE(items.size(), 1);
+ QCOMPARE(items.at(0), static_cast<QGraphicsItem *>(item3));
+}
+
+void tst_QGraphicsItem::focusProxy()
+{
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ QGraphicsItem *item = scene.addRect(0, 0, 10, 10);
+ item->setFlag(QGraphicsItem::ItemIsFocusable);
+ QVERIFY(!item->focusProxy());
+
+ QGraphicsItem *item2 = scene.addRect(0, 0, 10, 10);
+ item2->setFlag(QGraphicsItem::ItemIsFocusable);
+ item->setFocusProxy(item2);
+ QCOMPARE(item->focusProxy(), item2);
+
+ item->setFocus();
+ QVERIFY(item->hasFocus());
+ QVERIFY(item2->hasFocus());
+
+ // Try to make a focus chain loop
+ QString err;
+ QTextStream stream(&err);
+ stream << "QGraphicsItem::setFocusProxy: "
+ << (void*)item << " is already in the focus proxy chain" << flush;
+ QTest::ignoreMessage(QtWarningMsg, err.toLatin1().constData());
+ item2->setFocusProxy(item); // fails
+ QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2);
+ QCOMPARE(item2->focusProxy(), (QGraphicsItem *)0);
+
+ // Try to assign self as focus proxy
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::setFocusProxy: cannot assign self as focus proxy");
+ item->setFocusProxy(item); // fails
+ QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2);
+ QCOMPARE(item2->focusProxy(), (QGraphicsItem *)0);
+
+ // Reset the focus proxy
+ item->setFocusProxy(0);
+ QCOMPARE(item->focusProxy(), (QGraphicsItem *)0);
+ QVERIFY(!item->hasFocus());
+ QVERIFY(item2->hasFocus());
+
+ // Test deletion
+ item->setFocusProxy(item2);
+ QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2);
+ delete item2;
+ QCOMPARE(item->focusProxy(), (QGraphicsItem *)0);
+
+ // Test event delivery
+ item2 = scene.addRect(0, 0, 10, 10);
+ item2->setFlag(QGraphicsItem::ItemIsFocusable);
+ item->setFocusProxy(item2);
+ item->clearFocus();
+
+ EventSpy focusInSpy(&scene, item, QEvent::FocusIn);
+ EventSpy focusOutSpy(&scene, item, QEvent::FocusOut);
+ EventSpy focusInSpy2(&scene, item2, QEvent::FocusIn);
+ EventSpy focusOutSpy2(&scene, item2, QEvent::FocusOut);
+ QCOMPARE(focusInSpy.count(), 0);
+ QCOMPARE(focusOutSpy.count(), 0);
+ QCOMPARE(focusInSpy2.count(), 0);
+ QCOMPARE(focusOutSpy2.count(), 0);
+
+ item->setFocus();
+ QCOMPARE(focusInSpy.count(), 0);
+ QCOMPARE(focusInSpy2.count(), 1);
+ item->clearFocus();
+ QCOMPARE(focusOutSpy.count(), 0);
+ QCOMPARE(focusOutSpy2.count(), 1);
+
+ // Test two items proxying one item.
+ QGraphicsItem *item3 = scene.addRect(0, 0, 10, 10);
+ item3->setFlag(QGraphicsItem::ItemIsFocusable);
+ item3->setFocusProxy(item2); // item and item3 use item2 as proxy
+
+ QCOMPARE(item->focusProxy(), item2);
+ QCOMPARE(item2->focusProxy(), (QGraphicsItem *)0);
+ QCOMPARE(item3->focusProxy(), item2);
+ delete item2;
+ QCOMPARE(item->focusProxy(), (QGraphicsItem *)0);
+ QCOMPARE(item3->focusProxy(), (QGraphicsItem *)0);
+}
+
+void tst_QGraphicsItem::subFocus()
+{
+ // Construct a text item that's not part of a scene (yet)
+ // and has no parent. Setting focus on it will not make
+ // the item gain input focus; that requires a scene. But
+ // it does set subfocus, indicating that the item wishes
+ // to gain focus later.
+ QGraphicsTextItem *text = new QGraphicsTextItem("Hello");
+ text->setTextInteractionFlags(Qt::TextEditorInteraction);
+ QVERIFY(!text->hasFocus());
+ text->setFocus();
+ QVERIFY(!text->hasFocus());
+ QCOMPARE(text->focusItem(), (QGraphicsItem *)text);
+
+ // Add a sibling.
+ QGraphicsTextItem *text2 = new QGraphicsTextItem("Hi");
+ text2->setTextInteractionFlags(Qt::TextEditorInteraction);
+ text2->setPos(30, 30);
+
+ // Add both items to a scene and check that it's text that
+ // got input focus.
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ scene.addItem(text);
+ scene.addItem(text2);
+ QVERIFY(text->hasFocus());
+
+ text->setData(0, "text");
+ text2->setData(0, "text2");
+
+ // Remove text2 and set subfocus on it. Then readd. Reparent it onto the
+ // other item and see that it gains input focus.
+ scene.removeItem(text2);
+ text2->setFocus();
+ scene.addItem(text2);
+ QCOMPARE(text2->focusItem(), (QGraphicsItem *)text2);
+ text2->setParentItem(text);
+ QCOMPARE(text->focusItem(), (QGraphicsItem *)text2);
+ QCOMPARE(text2->focusItem(), (QGraphicsItem *)text2);
+ QVERIFY(!text->hasFocus());
+ QVERIFY(text2->hasFocus());
+
+ // Remove both items from the scene, restore subfocus and
+ // readd them. Now the subfocus should kick in and give
+ // text2 focus.
+ scene.removeItem(text);
+ QCOMPARE(text->focusItem(), (QGraphicsItem *)0);
+ QCOMPARE(text2->focusItem(), (QGraphicsItem *)0);
+ text2->setFocus();
+ QCOMPARE(text->focusItem(), (QGraphicsItem *)text2);
+ QCOMPARE(text2->focusItem(), (QGraphicsItem *)text2);
+ scene.addItem(text);
+
+ // Hiding and showing text should pass focus to text2.
+ QCOMPARE(text->focusItem(), (QGraphicsItem *)text2);
+ QVERIFY(text2->hasFocus());
+
+ // Subfocus should repropagate to root when reparenting.
+ QGraphicsRectItem *rect = new QGraphicsRectItem;
+ QGraphicsRectItem *rect2 = new QGraphicsRectItem(rect);
+ QGraphicsRectItem *rect3 = new QGraphicsRectItem(rect2);
+ rect3->setFlag(QGraphicsItem::ItemIsFocusable);
+
+ text->setData(0, "text");
+ text2->setData(0, "text2");
+ rect->setData(0, "rect");
+ rect2->setData(0, "rect2");
+ rect3->setData(0, "rect3");
+
+ rect3->setFocus();
+ QVERIFY(!rect3->hasFocus());
+ QCOMPARE(rect->focusItem(), (QGraphicsItem *)rect3);
+ QCOMPARE(rect2->focusItem(), (QGraphicsItem *)rect3);
+ QCOMPARE(rect3->focusItem(), (QGraphicsItem *)rect3);
+ rect->setParentItem(text2);
+ QCOMPARE(text->focusItem(), (QGraphicsItem *)rect3);
+ QCOMPARE(text2->focusItem(), (QGraphicsItem *)rect3);
+ QCOMPARE(rect->focusItem(), (QGraphicsItem *)rect3);
+ QCOMPARE(rect2->focusItem(), (QGraphicsItem *)rect3);
+ QCOMPARE(rect3->focusItem(), (QGraphicsItem *)rect3);
+ QVERIFY(!rect->hasFocus());
+ QVERIFY(!rect2->hasFocus());
+ QVERIFY(rect3->hasFocus());
+
+ delete rect2;
+ QCOMPARE(text->focusItem(), (QGraphicsItem *)0);
+ QCOMPARE(text2->focusItem(), (QGraphicsItem *)0);
+ QCOMPARE(rect->focusItem(), (QGraphicsItem *)0);
+}
+
+void tst_QGraphicsItem::focusProxyDeletion()
+{
+ QGraphicsRectItem *rect = new QGraphicsRectItem;
+ QGraphicsRectItem *rect2 = new QGraphicsRectItem;
+ rect->setFocusProxy(rect2);
+ QCOMPARE(rect->focusProxy(), (QGraphicsItem *)rect2);
+
+ delete rect2;
+ QCOMPARE(rect->focusProxy(), (QGraphicsItem *)0);
+
+ rect2 = new QGraphicsRectItem;
+ rect->setFocusProxy(rect2);
+ delete rect; // don't crash
+
+ rect = new QGraphicsRectItem;
+ rect->setFocusProxy(rect2);
+ QGraphicsScene *scene = new QGraphicsScene;
+ scene->addItem(rect);
+ scene->addItem(rect2);
+ delete rect2;
+ QCOMPARE(rect->focusProxy(), (QGraphicsItem *)0);
+
+ rect2 = new QGraphicsRectItem;
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::setFocusProxy: focus proxy must be in same scene");
+ rect->setFocusProxy(rect2);
+ QCOMPARE(rect->focusProxy(), (QGraphicsItem *)0);
+ scene->addItem(rect2);
+ rect->setFocusProxy(rect2);
+ QCOMPARE(rect->focusProxy(), (QGraphicsItem *)rect2);
+ delete rect; // don't crash
+
+ rect = new QGraphicsRectItem;
+ rect2 = new QGraphicsRectItem;
+ rect->setFocusProxy(rect2);
+ QCOMPARE(rect->focusProxy(), (QGraphicsItem *)rect2);
+ scene->addItem(rect);
+ scene->addItem(rect2);
+ rect->setFocusProxy(rect2);
+ delete scene; // don't crash
+}
+
+void tst_QGraphicsItem::negativeZStacksBehindParent()
+{
+ QGraphicsRectItem rect;
+ QCOMPARE(rect.zValue(), qreal(0.0));
+ QVERIFY(!(rect.flags() & QGraphicsItem::ItemNegativeZStacksBehindParent));
+ QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
+ rect.setZValue(-1);
+ QCOMPARE(rect.zValue(), qreal(-1.0));
+ QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
+ rect.setZValue(0);
+ rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent);
+ QVERIFY(rect.flags() & QGraphicsItem::ItemNegativeZStacksBehindParent);
+ QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
+ rect.setZValue(-1);
+ QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent);
+ rect.setZValue(0);
+ QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
+ rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, false);
+ rect.setZValue(-1);
+ rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, true);
+ QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent);
+ rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, false);
+ QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent);
+}
+
+void tst_QGraphicsItem::setGraphicsEffect()
+{
+ // Check that we don't have any effect by default.
+ QGraphicsItem *item = new QGraphicsRectItem(0, 0, 10, 10);
+ QVERIFY(!item->graphicsEffect());
+
+ // SetGet check.
+ QPointer<QGraphicsEffect> blurEffect = new QGraphicsBlurEffect;
+ item->setGraphicsEffect(blurEffect);
+ QCOMPARE(item->graphicsEffect(), static_cast<QGraphicsEffect *>(blurEffect));
+
+ // Ensure the existing effect is deleted when setting a new one.
+ QPointer<QGraphicsEffect> shadowEffect = new QGraphicsDropShadowEffect;
+ item->setGraphicsEffect(shadowEffect);
+ QVERIFY(!blurEffect);
+ QCOMPARE(item->graphicsEffect(), static_cast<QGraphicsEffect *>(shadowEffect));
+ blurEffect = new QGraphicsBlurEffect;
+
+ // Ensure the effect is uninstalled when setting it on a new target.
+ QGraphicsItem *anotherItem = new QGraphicsRectItem(0, 0, 10, 10);
+ anotherItem->setGraphicsEffect(blurEffect);
+ item->setGraphicsEffect(blurEffect);
+ QVERIFY(!anotherItem->graphicsEffect());
+ QVERIFY(!shadowEffect);
+
+ // Ensure the existing effect is deleted when deleting the item.
+ delete item;
+ QVERIFY(!blurEffect);
+ delete anotherItem;
+
+ // Ensure the effect is uninstalled when deleting it
+ item = new QGraphicsRectItem(0, 0, 10, 10);
+ blurEffect = new QGraphicsBlurEffect;
+ item->setGraphicsEffect(blurEffect);
+ delete blurEffect;
+ QVERIFY(!item->graphicsEffect());
+
+ // Ensure the existing effect is uninstalled and deleted when setting a null effect
+ blurEffect = new QGraphicsBlurEffect;
+ item->setGraphicsEffect(blurEffect);
+ item->setGraphicsEffect(0);
+ QVERIFY(!item->graphicsEffect());
+ QVERIFY(!blurEffect);
+
+ delete item;
+}
+
+void tst_QGraphicsItem::panel()
+{
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *panel1 = new QGraphicsRectItem;
+ QGraphicsRectItem *panel2 = new QGraphicsRectItem;
+ QGraphicsRectItem *panel3 = new QGraphicsRectItem;
+ QGraphicsRectItem *panel4 = new QGraphicsRectItem;
+ QGraphicsRectItem *notPanel1 = new QGraphicsRectItem;
+ QGraphicsRectItem *notPanel2 = new QGraphicsRectItem;
+ panel1->setFlag(QGraphicsItem::ItemIsPanel);
+ panel2->setFlag(QGraphicsItem::ItemIsPanel);
+ panel3->setFlag(QGraphicsItem::ItemIsPanel);
+ panel4->setFlag(QGraphicsItem::ItemIsPanel);
+ scene.addItem(panel1);
+ scene.addItem(panel2);
+ scene.addItem(panel3);
+ scene.addItem(panel4);
+ scene.addItem(notPanel1);
+ scene.addItem(notPanel2);
+
+ EventSpy spy_activate_panel1(&scene, panel1, QEvent::WindowActivate);
+ EventSpy spy_deactivate_panel1(&scene, panel1, QEvent::WindowDeactivate);
+ EventSpy spy_activate_panel2(&scene, panel2, QEvent::WindowActivate);
+ EventSpy spy_deactivate_panel2(&scene, panel2, QEvent::WindowDeactivate);
+ EventSpy spy_activate_panel3(&scene, panel3, QEvent::WindowActivate);
+ EventSpy spy_deactivate_panel3(&scene, panel3, QEvent::WindowDeactivate);
+ EventSpy spy_activate_panel4(&scene, panel4, QEvent::WindowActivate);
+ EventSpy spy_deactivate_panel4(&scene, panel4, QEvent::WindowDeactivate);
+ EventSpy spy_activate_notPanel1(&scene, notPanel1, QEvent::WindowActivate);
+ EventSpy spy_deactivate_notPanel1(&scene, notPanel1, QEvent::WindowDeactivate);
+ EventSpy spy_activate_notPanel2(&scene, notPanel1, QEvent::WindowActivate);
+ EventSpy spy_deactivate_notPanel2(&scene, notPanel1, QEvent::WindowDeactivate);
+
+ QCOMPARE(spy_activate_panel1.count(), 0);
+ QCOMPARE(spy_deactivate_panel1.count(), 0);
+ QCOMPARE(spy_activate_panel2.count(), 0);
+ QCOMPARE(spy_deactivate_panel2.count(), 0);
+ QCOMPARE(spy_activate_panel3.count(), 0);
+ QCOMPARE(spy_deactivate_panel3.count(), 0);
+ QCOMPARE(spy_activate_panel4.count(), 0);
+ QCOMPARE(spy_deactivate_panel4.count(), 0);
+ QCOMPARE(spy_activate_notPanel1.count(), 0);
+ QCOMPARE(spy_deactivate_notPanel1.count(), 0);
+ QCOMPARE(spy_activate_notPanel2.count(), 0);
+ QCOMPARE(spy_deactivate_notPanel2.count(), 0);
+
+ QVERIFY(!scene.activePanel());
+ QVERIFY(!scene.isActive());
+
+ QEvent activate(QEvent::WindowActivate);
+ QEvent deactivate(QEvent::WindowDeactivate);
+
+ QApplication::sendEvent(&scene, &activate);
+
+ // No previous activation, so the scene is active.
+ QVERIFY(scene.isActive());
+ QCOMPARE(scene.activePanel(), (QGraphicsItem *)panel1);
+ QVERIFY(panel1->isActive());
+ QVERIFY(!panel2->isActive());
+ QVERIFY(!panel3->isActive());
+ QVERIFY(!panel4->isActive());
+ QVERIFY(!notPanel1->isActive());
+ QVERIFY(!notPanel2->isActive());
+ QCOMPARE(spy_deactivate_notPanel1.count(), 0);
+ QCOMPARE(spy_deactivate_notPanel2.count(), 0);
+ QCOMPARE(spy_activate_panel1.count(), 1);
+ QCOMPARE(spy_activate_panel2.count(), 0);
+ QCOMPARE(spy_activate_panel3.count(), 0);
+ QCOMPARE(spy_activate_panel4.count(), 0);
+
+ // Switch back to scene.
+ scene.setActivePanel(0);
+ QVERIFY(!scene.activePanel());
+ QVERIFY(!panel1->isActive());
+ QVERIFY(!panel2->isActive());
+ QVERIFY(!panel3->isActive());
+ QVERIFY(!panel4->isActive());
+ QVERIFY(notPanel1->isActive());
+ QVERIFY(notPanel2->isActive());
+ QCOMPARE(spy_activate_notPanel1.count(), 1);
+ QCOMPARE(spy_activate_notPanel2.count(), 1);
+
+ // Deactivate the scene
+ QApplication::sendEvent(&scene, &deactivate);
+ QVERIFY(!scene.activePanel());
+ QVERIFY(!panel1->isActive());
+ QVERIFY(!panel2->isActive());
+ QVERIFY(!panel3->isActive());
+ QVERIFY(!panel4->isActive());
+ QVERIFY(!notPanel1->isActive());
+ QVERIFY(!notPanel2->isActive());
+ QCOMPARE(spy_deactivate_notPanel1.count(), 1);
+ QCOMPARE(spy_deactivate_notPanel2.count(), 1);
+
+ // Reactivate the scene
+ QApplication::sendEvent(&scene, &activate);
+ QVERIFY(!scene.activePanel());
+ QVERIFY(!panel1->isActive());
+ QVERIFY(!panel2->isActive());
+ QVERIFY(!panel3->isActive());
+ QVERIFY(!panel4->isActive());
+ QVERIFY(notPanel1->isActive());
+ QVERIFY(notPanel2->isActive());
+ QCOMPARE(spy_activate_notPanel1.count(), 2);
+ QCOMPARE(spy_activate_notPanel2.count(), 2);
+
+ // Switch to panel1
+ scene.setActivePanel(panel1);
+ QVERIFY(panel1->isActive());
+ QCOMPARE(spy_deactivate_notPanel1.count(), 2);
+ QCOMPARE(spy_deactivate_notPanel2.count(), 2);
+ QCOMPARE(spy_activate_panel1.count(), 2);
+
+ // Deactivate the scene
+ QApplication::sendEvent(&scene, &deactivate);
+ QVERIFY(!panel1->isActive());
+ QCOMPARE(spy_deactivate_panel1.count(), 2);
+
+ // Reactivate the scene
+ QApplication::sendEvent(&scene, &activate);
+ QVERIFY(panel1->isActive());
+ QCOMPARE(spy_activate_panel1.count(), 3);
+
+ // Deactivate the scene
+ QApplication::sendEvent(&scene, &deactivate);
+ QVERIFY(!panel1->isActive());
+ QVERIFY(!scene.activePanel());
+ scene.setActivePanel(0);
+
+ // Reactivate the scene
+ QApplication::sendEvent(&scene, &activate);
+ QVERIFY(!panel1->isActive());
+}
+
+void tst_QGraphicsItem::panelWithFocusItem()
+{
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ QGraphicsRectItem *parentPanel = new QGraphicsRectItem;
+ QGraphicsRectItem *parentPanelFocusItem = new QGraphicsRectItem(parentPanel);
+ parentPanel->setFlag(QGraphicsItem::ItemIsPanel);
+ parentPanelFocusItem->setFlag(QGraphicsItem::ItemIsFocusable);
+ parentPanelFocusItem->setFocus();
+ scene.addItem(parentPanel);
+
+ QVERIFY(parentPanel->isActive());
+ QVERIFY(parentPanelFocusItem->hasFocus());
+ QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
+ QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
+
+ QGraphicsRectItem *childPanel = new QGraphicsRectItem;
+ QGraphicsRectItem *childPanelFocusItem = new QGraphicsRectItem(childPanel);
+ childPanel->setFlag(QGraphicsItem::ItemIsPanel);
+ childPanelFocusItem->setFlag(QGraphicsItem::ItemIsFocusable);
+ childPanelFocusItem->setFocus();
+
+ QVERIFY(!childPanelFocusItem->hasFocus());
+ QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)childPanelFocusItem);
+ QCOMPARE(childPanelFocusItem->focusItem(), (QGraphicsItem *)childPanelFocusItem);
+
+ childPanel->setParentItem(parentPanel);
+
+ QVERIFY(!parentPanel->isActive());
+ QVERIFY(!parentPanelFocusItem->hasFocus());
+ QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
+ QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
+
+ QVERIFY(childPanel->isActive());
+ QVERIFY(childPanelFocusItem->hasFocus());
+ QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)childPanelFocusItem);
+ QCOMPARE(childPanelFocusItem->focusItem(), (QGraphicsItem *)childPanelFocusItem);
+
+ childPanel->hide();
+
+ QVERIFY(parentPanel->isActive());
+ QVERIFY(parentPanelFocusItem->hasFocus());
+ QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
+ QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
+}
+
+void tst_QGraphicsItem::addPanelToActiveScene()
+{
+ QGraphicsScene scene;
+ QVERIFY(!scene.isActive());
+
+ QGraphicsRectItem *rect = new QGraphicsRectItem;
+ scene.addItem(rect);
+ QVERIFY(!rect->isActive());
+ scene.removeItem(rect);
+
+ QEvent activate(QEvent::WindowActivate);
+ QEvent deactivate(QEvent::WindowDeactivate);
+
+ QApplication::sendEvent(&scene, &activate);
+ QVERIFY(scene.isActive());
+ scene.addItem(rect);
+ QVERIFY(rect->isActive());
+ scene.removeItem(rect);
+
+ rect->setFlag(QGraphicsItem::ItemIsPanel);
+ scene.addItem(rect);
+ QVERIFY(rect->isActive());
+ QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect);
+
+ QGraphicsRectItem *rect2 = new QGraphicsRectItem;
+ scene.addItem(rect2);
+ QVERIFY(rect->isActive());
+ QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect);
+}
+
+void tst_QGraphicsItem::activate()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect = scene.addRect(-10, -10, 20, 20);
+ QVERIFY(!rect->isActive());
+
+ QEvent activate(QEvent::WindowActivate);
+ QEvent deactivate(QEvent::WindowDeactivate);
+
+ QApplication::sendEvent(&scene, &activate);
+
+ // Non-panel item (active when scene is active).
+ QVERIFY(rect->isActive());
+
+ QGraphicsRectItem *rect2 = new QGraphicsRectItem;
+ rect2->setFlag(QGraphicsItem::ItemIsPanel);
+ QGraphicsRectItem *rect3 = new QGraphicsRectItem;
+ rect3->setFlag(QGraphicsItem::ItemIsPanel);
+
+ // Test normal activation.
+ QVERIFY(!rect2->isActive());
+ scene.addItem(rect2);
+ QVERIFY(rect2->isActive()); // first panel item is activated
+ scene.addItem(rect3);
+ QVERIFY(!rect3->isActive()); // second panel item is _not_ activated
+ rect3->setActive(true);
+ QVERIFY(rect3->isActive());
+ scene.removeItem(rect3);
+ QVERIFY(!rect3->isActive()); // no panel is active anymore
+ QCOMPARE(scene.activePanel(), (QGraphicsItem *)0);
+ scene.addItem(rect3);
+ QVERIFY(rect3->isActive()); // second panel item is activated
+
+ // Test pending activation.
+ scene.removeItem(rect3);
+ rect2->setActive(true);
+ QVERIFY(rect2->isActive()); // first panel item is activated
+ rect3->setActive(true);
+ QVERIFY(!rect3->isActive()); // not active (yet)
+ scene.addItem(rect3);
+ QVERIFY(rect3->isActive()); // now becomes active
+
+ // Test pending deactivation.
+ scene.removeItem(rect3);
+ rect3->setActive(false);
+ scene.addItem(rect3);
+ QVERIFY(!rect3->isActive()); // doesn't become active
+
+ // Child of panel activation.
+ rect3->setActive(true);
+ QGraphicsRectItem *rect4 = new QGraphicsRectItem;
+ rect4->setFlag(QGraphicsItem::ItemIsPanel);
+ QGraphicsRectItem *rect5 = new QGraphicsRectItem(rect4);
+ QGraphicsRectItem *rect6 = new QGraphicsRectItem(rect5);
+ scene.addItem(rect4);
+ QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect3);
+ scene.removeItem(rect4);
+ rect6->setActive(true);
+ scene.addItem(rect4);
+ QVERIFY(rect4->isActive());
+ QVERIFY(rect5->isActive());
+ QVERIFY(rect6->isActive());
+ QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect4);
+ scene.removeItem(rect4); // no active panel
+ rect6->setActive(false);
+ scene.addItem(rect4);
+ QVERIFY(!rect4->isActive());
+ QVERIFY(!rect5->isActive());
+ QVERIFY(!rect6->isActive());
+ QCOMPARE(scene.activePanel(), (QGraphicsItem *)0);
+
+ // Controlling auto-activation when the scene changes activation.
+ rect4->setActive(true);
+ QApplication::sendEvent(&scene, &deactivate);
+ QVERIFY(!scene.isActive());
+ QVERIFY(!rect4->isActive());
+ rect4->setActive(false);
+ QApplication::sendEvent(&scene, &activate);
+ QVERIFY(scene.isActive());
+ QVERIFY(!scene.activePanel());
+ QVERIFY(!rect4->isActive());
+}
+
+void tst_QGraphicsItem::setActivePanelOnInactiveScene()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *item = scene.addRect(QRectF());
+ QGraphicsRectItem *panel = scene.addRect(QRectF());
+ panel->setFlag(QGraphicsItem::ItemIsPanel);
+
+ EventSpy itemActivateSpy(&scene, item, QEvent::WindowActivate);
+ EventSpy itemDeactivateSpy(&scene, item, QEvent::WindowDeactivate);
+ EventSpy panelActivateSpy(&scene, panel, QEvent::WindowActivate);
+ EventSpy panelDeactivateSpy(&scene, panel, QEvent::WindowDeactivate);
+ EventSpy sceneActivationChangeSpy(&scene, QEvent::ActivationChange);
+
+ scene.setActivePanel(panel);
+ QCOMPARE(scene.activePanel(), (QGraphicsItem *)0);
+ QCOMPARE(itemActivateSpy.count(), 0);
+ QCOMPARE(itemDeactivateSpy.count(), 0);
+ QCOMPARE(panelActivateSpy.count(), 0);
+ QCOMPARE(panelDeactivateSpy.count(), 0);
+ QCOMPARE(sceneActivationChangeSpy.count(), 0);
+}
+
+void tst_QGraphicsItem::activationOnShowHide()
+{
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ QGraphicsRectItem *rootPanel = scene.addRect(QRectF());
+ rootPanel->setFlag(QGraphicsItem::ItemIsPanel);
+ rootPanel->setActive(true);
+
+ QGraphicsRectItem *subPanel = new QGraphicsRectItem;
+ subPanel->setFlag(QGraphicsItem::ItemIsPanel);
+
+ // Reparenting onto an active panel auto-activates the child panel.
+ subPanel->setParentItem(rootPanel);
+ QVERIFY(subPanel->isActive());
+ QVERIFY(!rootPanel->isActive());
+
+ // Hiding an active child panel will reactivate the parent panel.
+ subPanel->hide();
+ QVERIFY(rootPanel->isActive());
+
+ // Showing a child panel will auto-activate it.
+ subPanel->show();
+ QVERIFY(subPanel->isActive());
+ QVERIFY(!rootPanel->isActive());
+
+ // Adding an unrelated panel doesn't affect activation.
+ QGraphicsRectItem *otherPanel = new QGraphicsRectItem;
+ otherPanel->setFlag(QGraphicsItem::ItemIsPanel);
+ scene.addItem(otherPanel);
+ QVERIFY(subPanel->isActive());
+
+ // Showing an unrelated panel doesn't affect activation.
+ otherPanel->hide();
+ otherPanel->show();
+ QVERIFY(subPanel->isActive());
+
+ // Add a non-panel item.
+ QGraphicsRectItem *otherItem = new QGraphicsRectItem;
+ scene.addItem(otherItem);
+ otherItem->setActive(true);
+ QVERIFY(otherItem->isActive());
+
+ // Reparent a panel onto an active non-panel item.
+ subPanel->setParentItem(otherItem);
+ QVERIFY(subPanel->isActive());
+
+ // Showing a child panel of a non-panel item will activate it.
+ subPanel->hide();
+ QVERIFY(!subPanel->isActive());
+ QVERIFY(otherItem->isActive());
+ subPanel->show();
+ QVERIFY(subPanel->isActive());
+
+ // Hiding a toplevel active panel will pass activation back
+ // to the non-panel items.
+ rootPanel->setActive(true);
+ rootPanel->hide();
+ QVERIFY(!rootPanel->isActive());
+ QVERIFY(otherItem->isActive());
+}
+
+class MoveWhileDying : public QGraphicsRectItem
+{
+public:
+ MoveWhileDying(QGraphicsItem *parent = 0)
+ : QGraphicsRectItem(parent)
+ { }
+ ~MoveWhileDying()
+ {
+ foreach (QGraphicsItem *c, childItems()) {
+ foreach (QGraphicsItem *cc, c->childItems()) {
+ cc->moveBy(10, 10);
+ }
+ c->moveBy(10, 10);
+ }
+ if (QGraphicsItem *p = parentItem()) { p->moveBy(10, 10); }
+ }
+};
+
+void tst_QGraphicsItem::moveWhileDeleting()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect = new QGraphicsRectItem;
+ MoveWhileDying *silly = new MoveWhileDying(rect);
+ QGraphicsRectItem *child = new QGraphicsRectItem(silly);
+ scene.addItem(rect);
+ delete rect; // don't crash!
+
+ rect = new QGraphicsRectItem;
+ silly = new MoveWhileDying(rect);
+ child = new QGraphicsRectItem(silly);
+
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(125);
+
+ delete rect;
+
+ rect = new QGraphicsRectItem;
+ rect->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ silly = new MoveWhileDying(rect);
+ child = new QGraphicsRectItem(silly);
+
+ QTest::qWait(125);
+
+ delete rect;
+
+ rect = new MoveWhileDying;
+ rect->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ child = new QGraphicsRectItem(rect);
+ silly = new MoveWhileDying(child);
+
+ QTest::qWait(125);
+
+ delete rect;
+}
+
+class MyRectItem : public QGraphicsWidget
+{
+ Q_OBJECT
+public:
+ MyRectItem(QGraphicsItem *parent = 0) : QGraphicsWidget(parent)
+ {
+
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ {
+ painter->setBrush(brush);
+ painter->drawRect(boundingRect());
+ }
+ void move()
+ {
+ setPos(-100,-100);
+ topLevel->collidingItems(Qt::IntersectsItemBoundingRect);
+ }
+public:
+ QGraphicsItem *topLevel;
+ QBrush brush;
+};
+
+
+void tst_QGraphicsItem::ensureDirtySceneTransform()
+{
+ QGraphicsScene scene;
+
+ MyRectItem *topLevel = new MyRectItem;
+ topLevel->setGeometry(0, 0, 100, 100);
+ topLevel->setPos(-50, -50);
+ topLevel->brush = QBrush(QColor(Qt::black));
+ scene.addItem(topLevel);
+
+ MyRectItem *parent = new MyRectItem;
+ parent->topLevel = topLevel;
+ parent->setGeometry(0, 0, 100, 100);
+ parent->setPos(0, 0);
+ parent->brush = QBrush(QColor(Qt::magenta));
+ parent->setObjectName("parent");
+ scene.addItem(parent);
+
+ MyRectItem *child = new MyRectItem(parent);
+ child->setGeometry(0, 0, 80, 80);
+ child->setPos(10, 10);
+ child->setObjectName("child");
+ child->brush = QBrush(QColor(Qt::blue));
+
+ MyRectItem *child2 = new MyRectItem(parent);
+ child2->setGeometry(0, 0, 80, 80);
+ child2->setPos(15, 15);
+ child2->setObjectName("child2");
+ child2->brush = QBrush(QColor(Qt::green));
+
+ MyRectItem *child3 = new MyRectItem(parent);
+ child3->setGeometry(0, 0, 80, 80);
+ child3->setPos(20, 20);
+ child3->setObjectName("child3");
+ child3->brush = QBrush(QColor(Qt::gray));
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
+
+ //We move the parent
+ parent->move();
+ QApplication::processEvents();
+
+ //We check if all items moved
+ QCOMPARE(child->pos(), QPointF(10, 10));
+ QCOMPARE(child2->pos(), QPointF(15, 15));
+ QCOMPARE(child3->pos(), QPointF(20, 20));
+
+ QCOMPARE(child->sceneBoundingRect(), QRectF(-90, -90, 80, 80));
+ QCOMPARE(child2->sceneBoundingRect(), QRectF(-85, -85, 80, 80));
+ QCOMPARE(child3->sceneBoundingRect(), QRectF(-80, -80, 80, 80));
+
+ QCOMPARE(child->sceneTransform(), QTransform::fromTranslate(-90, -90));
+ QCOMPARE(child2->sceneTransform(), QTransform::fromTranslate(-85, -85));
+ QCOMPARE(child3->sceneTransform(), QTransform::fromTranslate(-80, -80));
+}
+
+void tst_QGraphicsItem::focusScope()
+{
+ // ItemIsFocusScope is an internal feature (for now).
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *scope3 = new QGraphicsRectItem;
+ scope3->setData(0, "scope3");
+ scope3->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
+ scope3->setFocus();
+ QVERIFY(!scope3->focusScopeItem());
+ QCOMPARE(scope3->focusItem(), (QGraphicsItem *)scope3);
+
+ QGraphicsRectItem *scope2 = new QGraphicsRectItem;
+ scope2->setData(0, "scope2");
+ scope2->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
+ scope2->setFocus();
+ QVERIFY(!scope2->focusScopeItem());
+ scope3->setParentItem(scope2);
+ QCOMPARE(scope2->focusScopeItem(), (QGraphicsItem *)scope3);
+ QCOMPARE(scope2->focusItem(), (QGraphicsItem *)scope3);
+
+ QGraphicsRectItem *scope1 = new QGraphicsRectItem;
+ scope1->setData(0, "scope1");
+ scope1->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
+ scope1->setFocus();
+ QVERIFY(!scope1->focusScopeItem());
+ scope2->setParentItem(scope1);
+
+ QCOMPARE(scope1->focusItem(), (QGraphicsItem *)scope3);
+ QCOMPARE(scope2->focusItem(), (QGraphicsItem *)scope3);
+ QCOMPARE(scope3->focusItem(), (QGraphicsItem *)scope3);
+ QCOMPARE(scope1->focusScopeItem(), (QGraphicsItem *)scope2);
+ QCOMPARE(scope2->focusScopeItem(), (QGraphicsItem *)scope3);
+ QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)0);
+
+ scene.addItem(scope1);
+
+ QEvent windowActivate(QEvent::WindowActivate);
+ qApp->sendEvent(&scene, &windowActivate);
+ scene.setFocus();
+
+ QCOMPARE(scope1->focusItem(), (QGraphicsItem *)scope3);
+ QCOMPARE(scope2->focusItem(), (QGraphicsItem *)scope3);
+ QCOMPARE(scope3->focusItem(), (QGraphicsItem *)scope3);
+ QCOMPARE(scope1->focusScopeItem(), (QGraphicsItem *)scope2);
+ QCOMPARE(scope2->focusScopeItem(), (QGraphicsItem *)scope3);
+ QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)0);
+
+ QVERIFY(scope3->hasFocus());
+
+ scope3->hide();
+ QVERIFY(scope2->hasFocus());
+ scope2->hide();
+ QVERIFY(scope1->hasFocus());
+ scope2->show();
+ QVERIFY(scope2->hasFocus());
+ scope3->show();
+ QVERIFY(scope3->hasFocus());
+ scope1->hide();
+ QVERIFY(!scope3->hasFocus());
+ scope1->show();
+ QVERIFY(scope3->hasFocus());
+ scope3->clearFocus();
+ QVERIFY(scope2->hasFocus());
+ scope2->clearFocus();
+ QVERIFY(scope1->hasFocus());
+ scope2->hide();
+ scope2->show();
+ QVERIFY(!scope2->hasFocus());
+ QVERIFY(scope1->hasFocus());
+ scope2->setFocus();
+ QVERIFY(scope2->hasFocus());
+ scope3->setFocus();
+ QVERIFY(scope3->hasFocus());
+
+ QGraphicsRectItem *rect4 = new QGraphicsRectItem;
+ rect4->setData(0, "rect4");
+ rect4->setParentItem(scope3);
+
+ QGraphicsRectItem *rect5 = new QGraphicsRectItem;
+ rect5->setData(0, "rect5");
+ rect5->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
+ rect5->setFocus();
+ rect5->setParentItem(rect4);
+ QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)rect5);
+ QVERIFY(rect5->hasFocus());
+
+ rect4->setParentItem(0);
+ QVERIFY(rect5->hasFocus());
+ QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)0);
+ QCOMPARE(scope3->focusItem(), (QGraphicsItem *)0);
+ QVERIFY(!scope3->hasFocus());
+
+ QGraphicsRectItem *rectA = new QGraphicsRectItem;
+ QGraphicsRectItem *scopeA = new QGraphicsRectItem(rectA);
+ scopeA->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
+ scopeA->setFocus();
+ QGraphicsRectItem *scopeB = new QGraphicsRectItem(scopeA);
+ scopeB->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
+ scopeB->setFocus();
+
+ scene.addItem(rectA);
+ QVERIFY(rect5->hasFocus());
+ QVERIFY(!scopeB->hasFocus());
+
+ scopeA->setFocus();
+ QVERIFY(scopeB->hasFocus());
+ QCOMPARE(scopeB->focusItem(), (QGraphicsItem *)scopeB);
+}
+
+void tst_QGraphicsItem::focusScope2()
+{
+ QGraphicsRectItem *child1 = new QGraphicsRectItem;
+ child1->setFlags(QGraphicsItem::ItemIsFocusable);
+ child1->setFocus();
+ QCOMPARE(child1->focusItem(), (QGraphicsItem *)child1);
+
+ QGraphicsRectItem *child2 = new QGraphicsRectItem;
+ child2->setFlags(QGraphicsItem::ItemIsFocusable);
+
+ QGraphicsRectItem *rootFocusScope = new QGraphicsRectItem;
+ rootFocusScope->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
+ rootFocusScope->setFocus();
+ QCOMPARE(rootFocusScope->focusItem(), (QGraphicsItem *)rootFocusScope);
+
+ child1->setParentItem(rootFocusScope);
+ child2->setParentItem(rootFocusScope);
+
+ QCOMPARE(rootFocusScope->focusScopeItem(), (QGraphicsItem *)child1);
+ QCOMPARE(rootFocusScope->focusItem(), (QGraphicsItem *)child1);
+
+ QGraphicsRectItem *siblingChild1 = new QGraphicsRectItem;
+ siblingChild1->setFlags(QGraphicsItem::ItemIsFocusable);
+ siblingChild1->setFocus();
+
+ QGraphicsRectItem *siblingChild2 = new QGraphicsRectItem;
+ siblingChild2->setFlags(QGraphicsItem::ItemIsFocusable);
+
+ QGraphicsRectItem *siblingFocusScope = new QGraphicsRectItem;
+ siblingFocusScope->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
+
+ siblingChild1->setParentItem(siblingFocusScope);
+ siblingChild2->setParentItem(siblingFocusScope);
+
+ QCOMPARE(siblingFocusScope->focusScopeItem(), (QGraphicsItem *)siblingChild1);
+ QCOMPARE(siblingFocusScope->focusItem(), (QGraphicsItem *)0);
+
+ QGraphicsItem *root = new QGraphicsRectItem;
+ rootFocusScope->setParentItem(root);
+ siblingFocusScope->setParentItem(root);
+
+ QCOMPARE(root->focusItem(), (QGraphicsItem *)child1);
+
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ QEvent activate(QEvent::WindowActivate);
+ qApp->sendEvent(&scene, &activate);
+ scene.setFocus();
+
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *)child1);
+
+ // You cannot set focus on a descendant of a focus scope directly;
+ // this will only change the scope's focus scope item pointer. If
+ // you want to give true input focus, you must set it directly on
+ // the scope itself
+ siblingChild2->setFocus();
+ QVERIFY(!siblingChild2->hasFocus());
+ QVERIFY(!siblingChild2->focusItem());
+ QCOMPARE(siblingFocusScope->focusScopeItem(), (QGraphicsItem *)siblingChild2);
+ QCOMPARE(siblingFocusScope->focusItem(), (QGraphicsItem *)0);
+
+ // Set focus on the scope; focus is forwarded to the focus scope item.
+ siblingFocusScope->setFocus();
+ QVERIFY(siblingChild2->hasFocus());
+ QVERIFY(siblingChild2->focusItem());
+ QCOMPARE(siblingFocusScope->focusScopeItem(), (QGraphicsItem *)siblingChild2);
+ QCOMPARE(siblingFocusScope->focusItem(), (QGraphicsItem *)siblingChild2);
+}
+
+void tst_QGraphicsItem::stackBefore()
+{
+ QGraphicsRectItem parent;
+ QGraphicsRectItem *child1 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
+ QGraphicsRectItem *child2 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
+ QGraphicsRectItem *child3 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
+ QGraphicsRectItem *child4 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
+ child1->setData(0, "child1");
+ child2->setData(0, "child2");
+ child3->setData(0, "child3");
+ child4->setData(0, "child4");
+
+ // Remove and append
+ child2->setParentItem(0);
+ child2->setParentItem(&parent);
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child3 << child4 << child2));
+
+ // Move child2 before child1
+ child2->stackBefore(child1); // 2134
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
+ child2->stackBefore(child2); // 2134
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
+ child1->setZValue(1); // 2341
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
+ child1->stackBefore(child2); // 2341
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
+ child1->setZValue(0); // 1234
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
+ child4->stackBefore(child1); // 4123
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child4 << child1 << child2 << child3));
+ child4->setZValue(1); // 1234 (4123)
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
+ child3->stackBefore(child1); // 3124 (4312)
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child3 << child1 << child2 << child4));
+ child4->setZValue(0); // 4312
+ QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child4 << child3 << child1 << child2));
+
+ // Make them all toplevels
+ child1->setParentItem(0);
+ child2->setParentItem(0);
+ child3->setParentItem(0);
+ child4->setParentItem(0);
+
+ QGraphicsScene scene;
+ scene.addItem(child1);
+ scene.addItem(child2);
+ scene.addItem(child3);
+ scene.addItem(child4);
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder),
+ (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
+
+ // Remove and append
+ scene.removeItem(child2);
+ scene.addItem(child2);
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child1 << child3 << child4 << child2));
+
+ // Move child2 before child1
+ child2->stackBefore(child1); // 2134
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
+ child2->stackBefore(child2); // 2134
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
+ child1->setZValue(1); // 2341
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
+ child1->stackBefore(child2); // 2341
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
+ child1->setZValue(0); // 1234
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
+ child4->stackBefore(child1); // 4123
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child4 << child1 << child2 << child3));
+ child4->setZValue(1); // 1234 (4123)
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
+ child3->stackBefore(child1); // 3124 (4312)
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child3 << child1 << child2 << child4));
+ child4->setZValue(0); // 4312
+ QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child4 << child3 << child1 << child2));
+}
+
+void tst_QGraphicsItem::QTBUG_4233_updateCachedWithSceneRect()
+{
+ EventTester *tester = new EventTester;
+ tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
+
+ QGraphicsScene scene;
+ scene.addItem(tester);
+ scene.setSceneRect(-100, -100, 200, 200); // contains the tester item
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget *)&view);
+
+ QTRY_COMPARE(tester->repaints, 1);
+
+ scene.update(); // triggers "updateAll" optimization
+ qApp->processEvents();
+ qApp->processEvents(); // in 4.6 only one processEvents is necessary
+
+ QCOMPARE(tester->repaints, 1);
+
+ scene.update(); // triggers "updateAll" optimization
+ tester->update();
+ qApp->processEvents();
+ qApp->processEvents(); // in 4.6 only one processEvents is necessary
+
+ QCOMPARE(tester->repaints, 2);
+}
+
+void tst_QGraphicsItem::sceneModality()
+{
+ // 1) Test mouse events (delivery/propagation/redirection)
+ // 2) Test hover events (incl. leave on block, enter on unblock)
+ // 3) Test cursor stuff (incl. unset on block, set on unblock)
+ // 4) Test clickfocus
+ // 5) Test grab/ungrab events (possibly ungrab on block, regrab on unblock)
+ // 6) ### modality for non-panels is unsupported for now
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *bottomItem = scene.addRect(-150, -100, 300, 200);
+ bottomItem->setFlag(QGraphicsItem::ItemIsFocusable);
+ bottomItem->setBrush(Qt::yellow);
+
+ QGraphicsRectItem *leftParent = scene.addRect(-50, -50, 100, 100);
+ leftParent->setFlag(QGraphicsItem::ItemIsPanel);
+ leftParent->setBrush(Qt::blue);
+
+ QGraphicsRectItem *leftChild = scene.addRect(-25, -25, 50, 50);
+ leftChild->setFlag(QGraphicsItem::ItemIsPanel);
+ leftChild->setBrush(Qt::green);
+ leftChild->setParentItem(leftParent);
+
+ QGraphicsRectItem *rightParent = scene.addRect(-50, -50, 100, 100);
+ rightParent->setFlag(QGraphicsItem::ItemIsPanel);
+ rightParent->setBrush(Qt::red);
+ QGraphicsRectItem *rightChild = scene.addRect(-25, -25, 50, 50);
+ rightChild->setFlag(QGraphicsItem::ItemIsPanel);
+ rightChild->setBrush(Qt::gray);
+ rightChild->setParentItem(rightParent);
+
+ leftParent->setPos(-75, 0);
+ rightParent->setPos(75, 0);
+
+ bottomItem->setData(0, "bottomItem");
+ leftParent->setData(0, "leftParent");
+ leftChild->setData(0, "leftChild");
+ rightParent->setData(0, "rightParent");
+ rightChild->setData(0, "rightChild");
+
+ scene.setSceneRect(scene.itemsBoundingRect().adjusted(-50, -50, 50, 50));
+
+ EventSpy2 leftParentSpy(&scene, leftParent);
+ EventSpy2 leftChildSpy(&scene, leftChild);
+ EventSpy2 rightParentSpy(&scene, rightParent);
+ EventSpy2 rightChildSpy(&scene, rightChild);
+ EventSpy2 bottomItemSpy(&scene, bottomItem);
+
+ // Scene modality, also test multiple scene modal items
+ leftChild->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0); // not a panel
+
+ // Click inside left child
+ sendMouseClick(&scene, leftChild->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+
+ // Click on left parent, event goes to modal child
+ sendMouseClick(&scene, leftParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 2);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+
+ // Click on all other items and outside the items
+ sendMouseClick(&scene, rightParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 3);
+ sendMouseClick(&scene, rightChild->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 4);
+ sendMouseClick(&scene, bottomItem->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 5);
+ sendMouseClick(&scene, QPointF(10000, 10000), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 6);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+
+ leftChildSpy.counts.clear();
+ rightChildSpy.counts.clear();
+ leftParentSpy.counts.clear();
+ rightParentSpy.counts.clear();
+ bottomItemSpy.counts.clear();
+
+ leftChild->setPanelModality(QGraphicsItem::NonModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 1);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowUnblocked], 0);
+
+ // Left parent enters scene modality.
+ leftParent->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
+
+ // Click inside left child.
+ sendMouseClick(&scene, leftChild->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // panel stops propagation
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+
+ // Click on left parent.
+ sendMouseClick(&scene, leftParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0);
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0);
+
+ // Click on all other items and outside the items
+ sendMouseClick(&scene, rightParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 2);
+ sendMouseClick(&scene, rightChild->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 3);
+ sendMouseClick(&scene, bottomItem->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 4);
+ sendMouseClick(&scene, QPointF(10000, 10000), Qt::LeftButton);
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 5);
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0);
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0);
+
+ leftChildSpy.counts.clear();
+ rightChildSpy.counts.clear();
+ leftParentSpy.counts.clear();
+ rightParentSpy.counts.clear();
+ bottomItemSpy.counts.clear();
+
+ // Now both left parent and child are scene modal. Left parent is blocked.
+ leftChild->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
+
+ // Click inside left child
+ sendMouseClick(&scene, leftChild->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+
+ // Click on left parent, event goes to modal child
+ sendMouseClick(&scene, leftParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 2);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+
+ // Click on all other items and outside the items
+ sendMouseClick(&scene, rightParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 3);
+ sendMouseClick(&scene, rightChild->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 4);
+ sendMouseClick(&scene, bottomItem->scenePos(), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 5);
+ sendMouseClick(&scene, QPointF(10000, 10000), Qt::LeftButton);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 6);
+ QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
+ QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+ QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
+
+ leftChildSpy.counts.clear();
+ rightChildSpy.counts.clear();
+ leftParentSpy.counts.clear();
+ rightParentSpy.counts.clear();
+ bottomItemSpy.counts.clear();
+
+ // Right child enters scene modality, only left child is blocked.
+ rightChild->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
+}
+
+void tst_QGraphicsItem::panelModality()
+{
+ // 1) Test mouse events (delivery/propagation/redirection)
+ // 2) Test hover events (incl. leave on block, enter on unblock)
+ // 3) Test cursor stuff (incl. unset on block, set on unblock)
+ // 4) Test clickfocus
+ // 5) Test grab/ungrab events (possibly ungrab on block, regrab on unblock)
+ // 6) ### modality for non-panels is unsupported for now
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *bottomItem = scene.addRect(-150, -100, 300, 200);
+ bottomItem->setFlag(QGraphicsItem::ItemIsFocusable);
+ bottomItem->setBrush(Qt::yellow);
+
+ QGraphicsRectItem *leftParent = scene.addRect(-50, -50, 100, 100);
+ leftParent->setFlag(QGraphicsItem::ItemIsPanel);
+ leftParent->setBrush(Qt::blue);
+
+ QGraphicsRectItem *leftChild = scene.addRect(-25, -25, 50, 50);
+ leftChild->setFlag(QGraphicsItem::ItemIsPanel);
+ leftChild->setBrush(Qt::green);
+ leftChild->setParentItem(leftParent);
+
+ QGraphicsRectItem *rightParent = scene.addRect(-50, -50, 100, 100);
+ rightParent->setFlag(QGraphicsItem::ItemIsPanel);
+ rightParent->setBrush(Qt::red);
+ QGraphicsRectItem *rightChild = scene.addRect(-25, -25, 50, 50);
+ rightChild->setFlag(QGraphicsItem::ItemIsPanel);
+ rightChild->setBrush(Qt::gray);
+ rightChild->setParentItem(rightParent);
+
+ leftParent->setPos(-75, 0);
+ rightParent->setPos(75, 0);
+
+ bottomItem->setData(0, "bottomItem");
+ leftParent->setData(0, "leftParent");
+ leftChild->setData(0, "leftChild");
+ rightParent->setData(0, "rightParent");
+ rightChild->setData(0, "rightChild");
+
+ scene.setSceneRect(scene.itemsBoundingRect().adjusted(-50, -50, 50, 50));
+
+ EventSpy2 leftParentSpy(&scene, leftParent);
+ EventSpy2 leftChildSpy(&scene, leftChild);
+ EventSpy2 rightParentSpy(&scene, rightParent);
+ EventSpy2 rightChildSpy(&scene, rightChild);
+ EventSpy2 bottomItemSpy(&scene, bottomItem);
+
+ // Left Child enters panel modality, only left parent is blocked.
+ leftChild->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
+
+ leftChild->setPanelModality(QGraphicsItem::NonModal);
+ leftChildSpy.counts.clear();
+ rightChildSpy.counts.clear();
+ leftParentSpy.counts.clear();
+ rightParentSpy.counts.clear();
+ bottomItemSpy.counts.clear();
+
+ // Left parent enter panel modality, nothing is blocked.
+ leftParent->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
+
+ // Left child enters panel modality, left parent is blocked again.
+ leftChild->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
+
+ leftChildSpy.counts.clear();
+ rightChildSpy.counts.clear();
+ leftParentSpy.counts.clear();
+ rightParentSpy.counts.clear();
+ bottomItemSpy.counts.clear();
+
+ leftChild->setPanelModality(QGraphicsItem::NonModal);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 1);
+ leftParent->setPanelModality(QGraphicsItem::NonModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(bottomItemSpy.counts[QEvent::WindowUnblocked], 0);
+
+ leftChildSpy.counts.clear();
+ rightChildSpy.counts.clear();
+ leftParentSpy.counts.clear();
+ rightParentSpy.counts.clear();
+ bottomItemSpy.counts.clear();
+
+ // Left and right child enter panel modality, both parents are blocked.
+ rightChild->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+ leftChild->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+}
+
+void tst_QGraphicsItem::mixedModality()
+{
+ // 1) Test mouse events (delivery/propagation/redirection)
+ // 2) Test hover events (incl. leave on block, enter on unblock)
+ // 3) Test cursor stuff (incl. unset on block, set on unblock)
+ // 4) Test clickfocus
+ // 5) Test grab/ungrab events (possibly ungrab on block, regrab on unblock)
+ // 6) ### modality for non-panels is unsupported for now
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *bottomItem = scene.addRect(-150, -100, 300, 200);
+ bottomItem->setFlag(QGraphicsItem::ItemIsFocusable);
+ bottomItem->setBrush(Qt::yellow);
+
+ QGraphicsRectItem *leftParent = scene.addRect(-50, -50, 100, 100);
+ leftParent->setFlag(QGraphicsItem::ItemIsPanel);
+ leftParent->setBrush(Qt::blue);
+
+ QGraphicsRectItem *leftChild = scene.addRect(-25, -25, 50, 50);
+ leftChild->setFlag(QGraphicsItem::ItemIsPanel);
+ leftChild->setBrush(Qt::green);
+ leftChild->setParentItem(leftParent);
+
+ QGraphicsRectItem *rightParent = scene.addRect(-50, -50, 100, 100);
+ rightParent->setFlag(QGraphicsItem::ItemIsPanel);
+ rightParent->setBrush(Qt::red);
+ QGraphicsRectItem *rightChild = scene.addRect(-25, -25, 50, 50);
+ rightChild->setFlag(QGraphicsItem::ItemIsPanel);
+ rightChild->setBrush(Qt::gray);
+ rightChild->setParentItem(rightParent);
+
+ leftParent->setPos(-75, 0);
+ rightParent->setPos(75, 0);
+
+ bottomItem->setData(0, "bottomItem");
+ leftParent->setData(0, "leftParent");
+ leftChild->setData(0, "leftChild");
+ rightParent->setData(0, "rightParent");
+ rightChild->setData(0, "rightChild");
+
+ scene.setSceneRect(scene.itemsBoundingRect().adjusted(-50, -50, 50, 50));
+
+ EventSpy2 leftParentSpy(&scene, leftParent);
+ EventSpy2 leftChildSpy(&scene, leftChild);
+ EventSpy2 rightParentSpy(&scene, rightParent);
+ EventSpy2 rightChildSpy(&scene, rightChild);
+ EventSpy2 bottomItemSpy(&scene, bottomItem);
+
+ // Left Child enters panel modality, only left parent is blocked.
+ leftChild->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
+
+ // Left parent enters scene modality, which blocks everything except the child.
+ leftParent->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
+
+ // Right child enters panel modality (changes nothing).
+ rightChild->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
+
+ // Left parent leaves modality. Right child is unblocked.
+ leftParent->setPanelModality(QGraphicsItem::NonModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
+
+ // Right child "upgrades" its modality to scene modal. Left child is blocked.
+ // Right parent is unaffected.
+ rightChild->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
+
+ // "downgrade" right child back to panel modal, left child is unblocked
+ rightChild->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 1);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
+ QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
+}
+
+void tst_QGraphicsItem::modality_hover()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
+ rect1->setFlag(QGraphicsItem::ItemIsPanel);
+ rect1->setAcceptHoverEvents(true);
+ rect1->setData(0, "rect1");
+
+ QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
+ rect2->setParentItem(rect1);
+ rect2->setFlag(QGraphicsItem::ItemIsPanel);
+ rect2->setAcceptHoverEvents(true);
+ rect2->setPos(50, 50);
+ rect2->setPanelModality(QGraphicsItem::SceneModal);
+ rect2->setData(0, "rect2");
+
+ EventSpy2 rect1Spy(&scene, rect1);
+ EventSpy2 rect2Spy(&scene, rect2);
+
+ sendMouseMove(&scene, QPointF(-25, -25));
+
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
+
+ sendMouseMove(&scene, QPointF(75, 75));
+
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
+
+ sendMouseMove(&scene, QPointF(-25, -25));
+
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
+
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
+
+ sendMouseMove(&scene, QPointF(75, 75));
+
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 2);
+
+ rect2->setPanelModality(QGraphicsItem::SceneModal);
+
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
+ // changing modality causes a spurious GraphicsSceneHoveMove, even though the mouse didn't
+ // actually move
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 3);
+
+ sendMouseMove(&scene, QPointF(-25, -25));
+
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
+
+ rect2->setPanelModality(QGraphicsItem::PanelModal);
+
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 3);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 2);
+
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 3);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 2);
+}
+
+void tst_QGraphicsItem::modality_mouseGrabber()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
+ rect1->setFlag(QGraphicsItem::ItemIsPanel);
+ rect1->setFlag(QGraphicsItem::ItemIsMovable);
+ rect1->setData(0, "rect1");
+
+ QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
+ rect2->setParentItem(rect1);
+ rect2->setFlag(QGraphicsItem::ItemIsPanel);
+ rect2->setFlag(QGraphicsItem::ItemIsMovable);
+ rect2->setPos(50, 50);
+ rect2->setData(0, "rect2");
+
+ EventSpy2 rect1Spy(&scene, rect1);
+ EventSpy2 rect2Spy(&scene, rect2);
+
+ {
+ // pressing mouse on rect1 starts implicit grab
+ sendMousePress(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
+
+ // grab lost when rect1 is modally shadowed
+ rect2->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ // releasing goes nowhere
+ sendMouseRelease(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ // pressing mouse on rect1 starts implicit grab on rect2 (since it is modal)
+ sendMouseClick(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+
+ // pressing mouse on rect1 starts implicit grab
+ sendMousePress(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
+
+ // grab lost to rect2 when rect1 is modally shadowed
+ rect2->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ // rect1 does *not* re-grab when rect2 is no longer modal
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ // release goes nowhere
+ sendMouseRelease(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+ }
+ {
+ // repeat the test using PanelModal
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+ rect1Spy.counts.clear();
+ rect2Spy.counts.clear();
+
+ // pressing mouse on rect1 starts implicit grab
+ sendMousePress(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
+
+ // grab lost when rect1 is modally shadowed
+ rect2->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ // releasing goes nowhere
+ sendMouseRelease(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ // pressing mouse on rect1 starts implicit grab on rect2 (since it is modal)
+ sendMouseClick(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+
+ // pressing mouse on rect1 starts implicit grab
+ sendMousePress(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
+
+ // grab lost to rect2 when rect1 is modally shadowed
+ rect2->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ // rect1 does *not* re-grab when rect2 is no longer modal
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ // release goes nowhere
+ sendMouseRelease(&scene, QPoint(-25, -25));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+ }
+
+ {
+ // repeat the PanelModal tests, but this time the mouse events will be on a non-modal item,
+ // meaning normal grabbing should work
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+ rect1Spy.counts.clear();
+ rect2Spy.counts.clear();
+
+ QGraphicsRectItem *rect3 = scene.addRect(-50, -50, 100, 100);
+ rect3->setFlag(QGraphicsItem::ItemIsPanel);
+ rect3->setFlag(QGraphicsItem::ItemIsMovable);
+ rect3->setPos(150, 50);
+ rect3->setData(0, "rect3");
+
+ EventSpy2 rect3Spy(&scene, rect3);
+
+ // pressing mouse on rect3 starts implicit grab
+ sendMousePress(&scene, QPoint(150, 50));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect3Spy.counts[QEvent::GraphicsSceneMousePress], 1);
+ QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
+
+ // grab is *not* lost when rect1 is modally shadowed by rect2
+ rect2->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
+
+ // releasing goes to rect3
+ sendMouseRelease(&scene, QPoint(150, 50));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 1);
+ QCOMPARE(rect3Spy.counts[QEvent::GraphicsSceneMouseRelease], 1);
+ QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+
+ // pressing mouse on rect3 starts implicit grab
+ sendMousePress(&scene, QPoint(150, 50));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
+
+ // grab is not lost
+ rect2->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
+
+ // grab stays on rect3
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
+
+ // release goes to rect3
+ sendMouseRelease(&scene, QPoint(150, 50));
+ QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
+ QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
+ QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 2);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
+ }
+}
+
+void tst_QGraphicsItem::modality_clickFocus()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
+ rect1->setFlag(QGraphicsItem::ItemIsPanel);
+ rect1->setFlag(QGraphicsItem::ItemIsFocusable);
+ rect1->setData(0, "rect1");
+
+ QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
+ rect2->setParentItem(rect1);
+ rect2->setFlag(QGraphicsItem::ItemIsPanel);
+ rect2->setFlag(QGraphicsItem::ItemIsFocusable);
+ rect2->setPos(50, 50);
+ rect2->setData(0, "rect2");
+
+ QEvent windowActivateEvent(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &windowActivateEvent);
+
+ EventSpy2 rect1Spy(&scene, rect1);
+ EventSpy2 rect2Spy(&scene, rect2);
+
+ // activate rect1, it should not get focus
+ rect1->setActive(true);
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
+
+ // focus stays unset when rect2 becomes modal
+ rect2->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0);
+
+ // clicking on rect1 should not set it's focus item
+ sendMouseClick(&scene, QPointF(-25, -25));
+ QCOMPARE(rect1->focusItem(), (QGraphicsItem *) 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0);
+
+ // clicking on rect2 gives it focus
+ rect2->setActive(true);
+ sendMouseClick(&scene, QPointF(75, 75));
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect2);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0);
+
+ // clicking on rect1 does *not* give it focus
+ rect1->setActive(true);
+ sendMouseClick(&scene, QPointF(-25, -25));
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1);
+
+ // focus doesn't change when leaving modality either
+ rect2->setPanelModality(QGraphicsItem::NonModal);
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1);
+
+ // click on rect1, it should get focus now
+ sendMouseClick(&scene, QPointF(-25, -25));
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1);
+}
+
+void tst_QGraphicsItem::modality_keyEvents()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
+ rect1->setFlag(QGraphicsItem::ItemIsPanel);
+ rect1->setFlag(QGraphicsItem::ItemIsFocusable);
+ rect1->setData(0, "rect1");
+
+ QGraphicsRectItem *rect1child = scene.addRect(-10, -10, 20, 20);
+ rect1child->setParentItem(rect1);
+ rect1child->setFlag(QGraphicsItem::ItemIsFocusable);
+ rect1child->setData(0, "rect1child1");
+
+ QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
+ rect2->setParentItem(rect1);
+ rect2->setFlag(QGraphicsItem::ItemIsPanel);
+ rect2->setFlag(QGraphicsItem::ItemIsFocusable);
+ rect2->setPos(50, 50);
+ rect2->setData(0, "rect2");
+
+ QGraphicsRectItem *rect2child = scene.addRect(-10, -10, 20, 20);
+ rect2child->setParentItem(rect2);
+ rect2child->setFlag(QGraphicsItem::ItemIsFocusable);
+ rect2child->setData(0, "rect2child1");
+
+ QEvent windowActivateEvent(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &windowActivateEvent);
+
+ EventSpy2 rect1Spy(&scene, rect1);
+ EventSpy2 rect1childSpy(&scene, rect1child);
+ EventSpy2 rect2Spy(&scene, rect2);
+ EventSpy2 rect2childSpy(&scene, rect2child);
+
+ // activate rect1 and give it rect1child focus
+ rect1->setActive(true);
+ rect1child->setFocus();
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1child);
+
+ // focus stays on rect1child when rect2 becomes modal
+ rect2->setPanelModality(QGraphicsItem::SceneModal);
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1child);
+
+ // but key events to rect1child should be neither delivered nor propagated
+ sendKeyClick(&scene, Qt::Key_A);
+ sendKeyClick(&scene, Qt::Key_S);
+ sendKeyClick(&scene, Qt::Key_D);
+ sendKeyClick(&scene, Qt::Key_F);
+ QCOMPARE(rect1childSpy.counts[QEvent::KeyPress], 0);
+ QCOMPARE(rect1childSpy.counts[QEvent::KeyRelease], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::KeyPress], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::KeyRelease], 0);
+
+ // change to panel modality, rect1child1 keeps focus
+ rect2->setPanelModality(QGraphicsItem::PanelModal);
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1child);
+
+ // still no key events
+ sendKeyClick(&scene, Qt::Key_J);
+ sendKeyClick(&scene, Qt::Key_K);
+ sendKeyClick(&scene, Qt::Key_L);
+ sendKeyClick(&scene, Qt::Key_Semicolon);
+ QCOMPARE(rect1childSpy.counts[QEvent::KeyPress], 0);
+ QCOMPARE(rect1childSpy.counts[QEvent::KeyRelease], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::KeyPress], 0);
+ QCOMPARE(rect1Spy.counts[QEvent::KeyRelease], 0);
+}
+
+void tst_QGraphicsItem::itemIsInFront()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect1 = new QGraphicsRectItem;
+ rect1->setData(0, "rect1");
+ scene.addItem(rect1);
+
+ QGraphicsRectItem *rect1child1 = new QGraphicsRectItem(rect1);
+ rect1child1->setZValue(1);
+ rect1child1->setData(0, "rect1child1");
+
+ QGraphicsRectItem *rect1child2 = new QGraphicsRectItem(rect1);
+ rect1child2->setParentItem(rect1);
+ rect1child2->setData(0, "rect1child2");
+
+ QGraphicsRectItem *rect1child1_1 = new QGraphicsRectItem(rect1child1);
+ rect1child1_1->setData(0, "rect1child1_1");
+
+ QGraphicsRectItem *rect1child1_2 = new QGraphicsRectItem(rect1child1);
+ rect1child1_2->setFlag(QGraphicsItem::ItemStacksBehindParent);
+ rect1child1_2->setData(0, "rect1child1_2");
+
+ QGraphicsRectItem *rect2 = new QGraphicsRectItem;
+ rect2->setData(0, "rect2");
+ scene.addItem(rect2);
+
+ QGraphicsRectItem *rect2child1 = new QGraphicsRectItem(rect2);
+ rect2child1->setData(0, "rect2child1");
+
+ QCOMPARE(qt_closestItemFirst(rect1, rect1), false);
+ QCOMPARE(qt_closestItemFirst(rect1, rect2), false);
+ QCOMPARE(qt_closestItemFirst(rect1child1, rect2child1), false);
+ QCOMPARE(qt_closestItemFirst(rect1child1, rect1child2), true);
+ QCOMPARE(qt_closestItemFirst(rect1child1_1, rect1child2), true);
+ QCOMPARE(qt_closestItemFirst(rect1child1_1, rect1child1), true);
+ QCOMPARE(qt_closestItemFirst(rect1child1_2, rect1child2), true);
+ QCOMPARE(qt_closestItemFirst(rect1child1_2, rect1child1), false);
+ QCOMPARE(qt_closestItemFirst(rect1child1_2, rect1), true);
+ QCOMPARE(qt_closestItemFirst(rect1child1_2, rect2), false);
+ QCOMPARE(qt_closestItemFirst(rect1child1_2, rect2child1), false);
+}
+
+class ScenePosChangeTester : public ItemChangeTester
+{
+public:
+ ScenePosChangeTester()
+ { }
+ ScenePosChangeTester(QGraphicsItem *parent) : ItemChangeTester(parent)
+ { }
+};
+
+void tst_QGraphicsItem::scenePosChange()
+{
+ ScenePosChangeTester* root = new ScenePosChangeTester;
+ ScenePosChangeTester* child1 = new ScenePosChangeTester(root);
+ ScenePosChangeTester* grandChild1 = new ScenePosChangeTester(child1);
+ ScenePosChangeTester* child2 = new ScenePosChangeTester(root);
+ ScenePosChangeTester* grandChild2 = new ScenePosChangeTester(child2);
+
+ child1->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
+ grandChild2->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
+
+ QVERIFY(child1->flags() & QGraphicsItem::ItemSendsScenePositionChanges);
+ QVERIFY(grandChild2->flags() & QGraphicsItem::ItemSendsScenePositionChanges);
+
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ // ignore uninteresting changes
+ child1->clear();
+ child2->clear();
+ grandChild1->clear();
+ grandChild2->clear();
+
+ // move whole tree
+ root->moveBy(1.0, 1.0);
+ QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
+ QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
+ QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
+ QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
+
+ // move subtree
+ child2->moveBy(1.0, 1.0);
+ QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
+ QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
+ QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
+ QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 2);
+
+ // reparent
+ grandChild2->setParentItem(child1);
+ child1->moveBy(1.0, 1.0);
+ QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 2);
+ QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
+ QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
+ QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 3);
+
+ // change flags
+ grandChild1->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
+ grandChild2->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, false);
+ QCoreApplication::processEvents(); // QGraphicsScenePrivate::_q_updateScenePosDescendants()
+ child1->moveBy(1.0, 1.0);
+ QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 3);
+ QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
+ QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
+ QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 3);
+
+ // remove
+ scene.removeItem(grandChild1);
+ delete grandChild2; grandChild2 = 0;
+ QCoreApplication::processEvents(); // QGraphicsScenePrivate::_q_updateScenePosDescendants()
+ root->moveBy(1.0, 1.0);
+ QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 4);
+ QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
+ QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
+
+ root->setX(1);
+ QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 5);
+ QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
+ QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
+
+ root->setY(1);
+ QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 6);
+ QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
+ QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
+}
+
+class MyInputContext : public QInputContext
+{
+public:
+ MyInputContext() : nbUpdates(0) {}
+ ~MyInputContext() {}
+
+ QString identifierName() { return QString(); }
+ QString language() { return QString(); }
+
+ void reset() {}
+
+ bool isComposing() const { return false; }
+
+ void update() { nbUpdates++; }
+
+ bool nbUpdates;
+};
+
+class MyInputWidget : public QGraphicsWidget
+{
+public:
+ MyInputWidget()
+ {
+ setFlag(QGraphicsItem::ItemIsFocusable, true);
+ setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
+ }
+ void mousePressEvent(QGraphicsSceneMouseEvent *event)
+ {
+ event->accept();
+ }
+
+ void doUpdateMicroFocus()
+ {
+ if (QWidget *fw = QApplication::focusWidget()) {
+ if (scene()) {
+ for (int i = 0 ; i < scene()->views().count() ; ++i) {
+ if (scene()->views().at(i) == fw) {
+ if (QInputContext *inputContext = fw->inputContext()) {
+ inputContext->update();
+ }
+ }
+ }
+ }
+ }
+ }
+};
+
+void tst_QGraphicsItem::updateMicroFocus()
+{
+#if defined Q_OS_WIN || defined Q_OS_MAC
+ QSKIP("QTBUG-9578", SkipAll);
+#endif
+ QGraphicsScene scene;
+ QWidget parent;
+ QGridLayout layout;
+ parent.setLayout(&layout);
+ QGraphicsView view(&scene);
+ QGraphicsView view2(&scene);
+ layout.addWidget(&view, 0, 0);
+ layout.addWidget(&view2, 0, 1);
+ MyInputContext *ic = new MyInputContext;
+ qApp->setInputContext(ic);
+ MyInputWidget input;
+ input.setPos(0, 0);
+ input.resize(150, 150);
+ scene.addItem(&input);
+ input.setFocus();
+ parent.show();
+ view.setFocus();
+ qApp->setAutoSipEnabled(true);
+ QApplication::setActiveWindow(&parent);
+ QTest::qWaitForWindowShown(&parent);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&parent));
+ //We reset the number of updates that happened previously (initialisation)
+ ic->nbUpdates = 0;
+ input.doUpdateMicroFocus();
+ QApplication::processEvents();
+ QTRY_COMPARE(ic->nbUpdates, 1);
+}
+
+void tst_QGraphicsItem::textItem_shortcuts()
+{
+ QWidget w;
+ QVBoxLayout l;
+ w.setLayout(&l);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ l.addWidget(&view);
+ QPushButton b("Push Me");
+ l.addWidget(&b);
+
+ QGraphicsTextItem *item = scene.addText("Troll Text");
+ item->setFlag(QGraphicsItem::ItemIsFocusable);
+ item->setTextInteractionFlags(Qt::TextEditorInteraction);
+ w.show();
+ QTest::qWaitForWindowShown(&w);
+
+ item->setFocus();
+ QTRY_VERIFY(item->hasFocus());
+ QVERIFY(item->textCursor().selectedText().isEmpty());
+
+ // Shortcut should work (select all)
+ QTest::keyClick(&view, Qt::Key_A, Qt::ControlModifier);
+ QTRY_COMPARE(item->textCursor().selectedText(), item->toPlainText());
+ QTextCursor tc = item->textCursor();
+ tc.clearSelection();
+ item->setTextCursor(tc);
+ QVERIFY(item->textCursor().selectedText().isEmpty());
+
+ // Shortcut should also work if the text item has the focus and another widget
+ // has the same shortcut.
+ b.setShortcut(QKeySequence("CTRL+A"));
+ QTest::keyClick(&view, Qt::Key_A, Qt::ControlModifier);
+ QTRY_COMPARE(item->textCursor().selectedText(), item->toPlainText());
+}
+
+void tst_QGraphicsItem::scroll()
+{
+ // Create two overlapping rectangles in the scene:
+ // +-------+
+ // | | <- item1
+ // | +-------+
+ // | | |
+ // +---| | <- item2
+ // | |
+ // +-------+
+
+ EventTester *item1 = new EventTester;
+ item1->br = QRectF(0, 0, 200, 200);
+ item1->brush = Qt::red;
+ item1->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption);
+
+ EventTester *item2 = new EventTester;
+ item2->br = QRectF(0, 0, 200, 200);
+ item2->brush = Qt::blue;
+ item2->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption);
+ item2->setPos(100, 100);
+
+ QGraphicsScene scene(0, 0, 300, 300);
+ scene.addItem(item1);
+ scene.addItem(item2);
+
+ MyGraphicsView view(&scene);
+ view.setFrameStyle(0);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.repaints > 0);
+
+ view.reset();
+ item1->reset();
+ item2->reset();
+
+ const QRectF item1BoundingRect = item1->boundingRect();
+ const QRectF item2BoundingRect = item2->boundingRect();
+
+ // Scroll item1:
+ // Item1 should get full exposure
+ // Item2 should get exposure for the part that overlaps item1.
+ item1->scroll(0, -10);
+ QTRY_VERIFY(view.repaints > 0);
+ QCOMPARE(item1->lastExposedRect, item1BoundingRect);
+
+ QRectF expectedItem2Expose = item2BoundingRect;
+ // NB! Adjusted by 2 pixels for antialiasing
+ expectedItem2Expose &= item1->mapRectToItem(item2, item1BoundingRect.adjusted(-2, -2, 2, 2));
+ QCOMPARE(item2->lastExposedRect, expectedItem2Expose);
+
+ // Enable ItemCoordinateCache on item1.
+ view.reset();
+ item1->setCacheMode(QGraphicsItem::ItemCoordinateCache);
+ QTRY_VERIFY(view.repaints > 0);
+ view.reset();
+ item1->reset();
+ item2->reset();
+
+ // Scroll item1:
+ // Item1 should only get expose for the newly exposed area (accelerated scroll).
+ // Item2 should get exposure for the part that overlaps item1.
+ item1->scroll(0, -10, QRectF(50, 50, 100, 100));
+ QTRY_VERIFY(view.repaints > 0);
+ QCOMPARE(item1->lastExposedRect, QRectF(50, 140, 100, 10));
+
+ expectedItem2Expose = item2BoundingRect;
+ // NB! Adjusted by 2 pixels for antialiasing
+ expectedItem2Expose &= item1->mapRectToItem(item2, QRectF(50, 50, 100, 100).adjusted(-2, -2, 2, 2));
+ QCOMPARE(item2->lastExposedRect, expectedItem2Expose);
+}
+
+Q_DECLARE_METATYPE(QGraphicsItem::GraphicsItemFlag);
+
+void tst_QGraphicsItem::focusHandling_data()
+{
+ QTest::addColumn<QGraphicsItem::GraphicsItemFlag>("focusFlag");
+ QTest::addColumn<bool>("useStickyFocus");
+ QTest::addColumn<int>("expectedFocusItem"); // 0: none, 1: focusableUnder, 2: itemWithFocus
+
+ QTest::newRow("Focus goes through.")
+ << static_cast<QGraphicsItem::GraphicsItemFlag>(0x0) << false << 1;
+
+ QTest::newRow("Focus goes through, even with sticky scene.")
+ << static_cast<QGraphicsItem::GraphicsItemFlag>(0x0) << true << 1;
+
+ QTest::newRow("With ItemStopsClickFocusPropagation, we cannot focus the item beneath the flagged one (but can still focus-out).")
+ << QGraphicsItem::ItemStopsClickFocusPropagation << false << 0;
+
+ QTest::newRow("With ItemStopsClickFocusPropagation, we cannot focus the item beneath the flagged one (and cannot focus-out if scene is sticky).")
+ << QGraphicsItem::ItemStopsClickFocusPropagation << true << 2;
+
+ QTest::newRow("With ItemStopsFocusHandling, focus cannot be changed by presses.")
+ << QGraphicsItem::ItemStopsFocusHandling << false << 2;
+
+ QTest::newRow("With ItemStopsFocusHandling, focus cannot be changed by presses (even if scene is sticky).")
+ << QGraphicsItem::ItemStopsFocusHandling << true << 2;
+}
+
+void tst_QGraphicsItem::focusHandling()
+{
+ QFETCH(QGraphicsItem::GraphicsItemFlag, focusFlag);
+ QFETCH(bool, useStickyFocus);
+ QFETCH(int, expectedFocusItem);
+
+ class MyItem : public QGraphicsRectItem
+ {
+ public:
+ MyItem() : QGraphicsRectItem(0, 0, 100, 100) {}
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ {
+ painter->fillRect(boundingRect(), hasFocus() ? QBrush(Qt::red) : brush());
+ }
+ };
+
+ QGraphicsRectItem *noFocusOnTop = new MyItem;
+ noFocusOnTop->setFlag(QGraphicsItem::ItemIsFocusable, false);
+ noFocusOnTop->setBrush(Qt::yellow);
+
+ QGraphicsRectItem *focusableUnder = new MyItem;
+ focusableUnder->setBrush(Qt::blue);
+ focusableUnder->setFlag(QGraphicsItem::ItemIsFocusable);
+ focusableUnder->setPos(50, 50);
+
+ QGraphicsRectItem *itemWithFocus = new MyItem;
+ itemWithFocus->setBrush(Qt::black);
+ itemWithFocus->setFlag(QGraphicsItem::ItemIsFocusable);
+ itemWithFocus->setPos(250, 10);
+
+ QGraphicsScene scene(-50, -50, 400, 400);
+ scene.addItem(noFocusOnTop);
+ scene.addItem(focusableUnder);
+ scene.addItem(itemWithFocus);
+ scene.setStickyFocus(useStickyFocus);
+
+ noFocusOnTop->setFlag(focusFlag);
+ focusableUnder->stackBefore(noFocusOnTop);
+ itemWithFocus->setFocus();
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QApplication::setActiveWindow(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
+ QVERIFY(itemWithFocus->hasFocus());
+
+ const QPointF mousePressPoint = noFocusOnTop->mapToScene(noFocusOnTop->boundingRect().center());
+ const QList<QGraphicsItem *> itemsAtMousePressPosition = scene.items(mousePressPoint);
+ QVERIFY(itemsAtMousePressPosition.contains(noFocusOnTop));
+
+ sendMousePress(&scene, mousePressPoint);
+
+ switch (expectedFocusItem) {
+ case 0:
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsRectItem *>(0));
+ break;
+ case 1:
+ QCOMPARE(scene.focusItem(), focusableUnder);
+ break;
+ case 2:
+ QCOMPARE(scene.focusItem(), itemWithFocus);
+ break;
+ }
+
+ // Sanity check - manually setting the focus must work regardless of our
+ // focus handling flags:
+ focusableUnder->setFocus();
+ QCOMPARE(scene.focusItem(), focusableUnder);
+}
+
+void tst_QGraphicsItem::touchEventPropagation_data()
+{
+ QTest::addColumn<QGraphicsItem::GraphicsItemFlag>("flag");
+ QTest::addColumn<int>("expectedCount");
+
+ QTest::newRow("ItemIsPanel")
+ << QGraphicsItem::ItemIsPanel << 0;
+ QTest::newRow("ItemStopsClickFocusPropagation")
+ << QGraphicsItem::ItemStopsClickFocusPropagation << 1;
+ QTest::newRow("ItemStopsFocusHandling")
+ << QGraphicsItem::ItemStopsFocusHandling << 1;
+}
+
+void tst_QGraphicsItem::touchEventPropagation()
+{
+ QFETCH(QGraphicsItem::GraphicsItemFlag, flag);
+ QFETCH(int, expectedCount);
+
+ class Testee : public QGraphicsRectItem
+ {
+ public:
+ int touchBeginEventCount;
+
+ Testee()
+ : QGraphicsRectItem(0, 0, 100, 100)
+ , touchBeginEventCount(0)
+ {
+ setAcceptTouchEvents(true);
+ setFlag(QGraphicsItem::ItemIsFocusable, false);
+ }
+
+ bool sceneEvent(QEvent *ev)
+ {
+ if (ev->type() == QEvent::TouchBegin)
+ ++touchBeginEventCount;
+
+ return QGraphicsRectItem::sceneEvent(ev);
+ }
+ };
+
+ Testee *touchEventReceiver = new Testee;
+ QGraphicsItem *topMost = new QGraphicsRectItem(touchEventReceiver->boundingRect());
+
+ QGraphicsScene scene;
+ scene.addItem(topMost);
+ scene.addItem(touchEventReceiver);
+
+ topMost->setAcceptTouchEvents(true);
+ topMost->setZValue(FLT_MAX);
+ topMost->setFlag(QGraphicsItem::ItemIsFocusable, false);
+ topMost->setFlag(flag, true);
+
+ QGraphicsView view(&scene);
+ view.setSceneRect(touchEventReceiver->boundingRect());
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QCOMPARE(touchEventReceiver->touchBeginEventCount, 0);
+
+ QTouchEvent::TouchPoint tp(0);
+ tp.setState(Qt::TouchPointPressed);
+ tp.setScenePos(view.sceneRect().center());
+ tp.setLastScenePos(view.sceneRect().center());
+
+ QList<QTouchEvent::TouchPoint> touchPoints;
+ touchPoints << tp;
+
+ sendMousePress(&scene, tp.scenePos());
+ QTouchEvent touchBegin(QEvent::TouchBegin, QTouchEvent::TouchScreen, Qt::NoModifier, Qt::TouchPointPressed, touchPoints);
+
+ qApp->sendEvent(&scene, &touchBegin);
+ QCOMPARE(touchEventReceiver->touchBeginEventCount, expectedCount);
+}
+
+void tst_QGraphicsItem::deviceCoordinateCache_simpleRotations()
+{
+ // Make sure we don't invalidate the cache when applying simple
+ // (90, 180, 270, 360) rotation transforms to the item.
+ QGraphicsRectItem *item = new QGraphicsRectItem(0, 0, 300, 200);
+ item->setBrush(Qt::red);
+ item->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+
+ QGraphicsScene scene;
+ scene.setSceneRect(0, 0, 300, 200);
+ scene.addItem(item);
+
+ MyGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.repaints > 0);
+
+ QGraphicsItemCache *itemCache = QGraphicsItemPrivate::get(item)->extraItemCache();
+ QVERIFY(itemCache);
+ QPixmapCache::Key currentKey = itemCache->deviceData.value(view.viewport()).key;
+
+ // Trigger an update and verify that the cache is unchanged.
+ QPixmapCache::Key oldKey = currentKey;
+ view.reset();
+ view.viewport()->update();
+ QTRY_VERIFY(view.repaints > 0);
+ currentKey = itemCache->deviceData.value(view.viewport()).key;
+ QCOMPARE(currentKey, oldKey);
+
+ // Check 90, 180, 270 and 360 degree rotations.
+ for (int angle = 90; angle <= 360; angle += 90) {
+ // Rotate item and verify that the cache was invalidated.
+ oldKey = currentKey;
+ view.reset();
+ QTransform transform;
+ transform.translate(150, 100);
+ transform.rotate(angle);
+ transform.translate(-150, -100);
+ item->setTransform(transform);
+ QTRY_VERIFY(view.repaints > 0);
+ currentKey = itemCache->deviceData.value(view.viewport()).key;
+ QVERIFY(currentKey != oldKey);
+
+ // IMPORTANT PART:
+ // Trigger an update and verify that the cache is unchanged.
+ oldKey = currentKey;
+ view.reset();
+ view.viewport()->update();
+ QTRY_VERIFY(view.repaints > 0);
+ currentKey = itemCache->deviceData.value(view.viewport()).key;
+ QCOMPARE(currentKey, oldKey);
+ }
+
+ // 45 degree rotation.
+ oldKey = currentKey;
+ view.reset();
+ QTransform transform;
+ transform.translate(150, 100);
+ transform.rotate(45);
+ transform.translate(-150, -100);
+ item->setTransform(transform);
+ QTRY_VERIFY(view.repaints > 0);
+ currentKey = itemCache->deviceData.value(view.viewport()).key;
+ QVERIFY(currentKey != oldKey);
+
+ // Trigger an update and verify that the cache was invalidated.
+ // We should always invalidate the cache for non-trivial transforms.
+ oldKey = currentKey;
+ view.reset();
+ view.viewport()->update();
+ QTRY_VERIFY(view.repaints > 0);
+ currentKey = itemCache->deviceData.value(view.viewport()).key;
+ QVERIFY(currentKey != oldKey);
+}
+
+void tst_QGraphicsItem::QTBUG_5418_textItemSetDefaultColor()
+{
+ struct Item : public QGraphicsTextItem
+ {
+ int painted;
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *opt, QWidget *wid)
+ {
+ painted++;
+ QGraphicsTextItem::paint(painter, opt, wid);
+ }
+ };
+
+ Item *i = new Item;
+ i->painted = 0;
+ i->setPlainText("I AM A TROLL");
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ scene.addItem(i);
+ QApplication::processEvents();
+ QTRY_VERIFY(i->painted);
+ QApplication::processEvents();
+
+ i->painted = 0;
+ QColor col(Qt::red);
+ i->setDefaultTextColor(col);
+ QApplication::processEvents();
+ QTRY_COMPARE(i->painted, 1); //check that changing the color force an update
+
+ i->painted = false;
+ QImage image(400, 200, QImage::Format_RGB32);
+ image.fill(0);
+ QPainter painter(&image);
+ scene.render(&painter);
+ painter.end();
+ QCOMPARE(i->painted, 1);
+
+ int numRedPixel = 0;
+ QRgb rgb = col.rgb();
+ for (int y = 0; y < image.height(); ++y) {
+ for (int x = 0; x < image.width(); ++x) {
+ // Because of antialiasing we allow a certain range of errors here.
+ QRgb pixel = image.pixel(x, y);
+ if (qAbs((int)(pixel & 0xff) - (int)(rgb & 0xff)) +
+ qAbs((int)((pixel & 0xff00) >> 8) - (int)((rgb & 0xff00) >> 8)) +
+ qAbs((int)((pixel & 0xff0000) >> 16) - (int)((rgb & 0xff0000) >> 16)) <= 50) {
+ if (++numRedPixel >= 10) {
+ return;
+ }
+ }
+ }
+ }
+ QCOMPARE(numRedPixel, -1); //color not found, FAIL!
+
+ i->painted = 0;
+ i->setDefaultTextColor(col);
+ QApplication::processEvents();
+ QCOMPARE(i->painted, 0); //same color as before should not trigger an update (QTBUG-6242)
+}
+
+void tst_QGraphicsItem::QTBUG_6738_missingUpdateWithSetParent()
+{
+ // In all 3 test cases below the reparented item should disappear
+ EventTester *parent = new EventTester;
+ EventTester *child = new EventTester(parent);
+ EventTester *child2 = new EventTester(parent);
+ EventTester *child3 = new EventTester(parent);
+ EventTester *child4 = new EventTester(parent);
+
+ child->setPos(10, 10);
+ child2->setPos(20, 20);
+ child3->setPos(30, 30);
+ child4->setPos(40, 40);
+
+ QGraphicsScene scene;
+ scene.addItem(parent);
+
+ MyGraphicsView view(&scene);
+ if(PlatformQuirks::isAutoMaximizing())
+ view.showFullScreen();
+ else
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.repaints > 0);
+
+ // test case #1
+ view.reset();
+ child2->setVisible(false);
+ child2->setParentItem(child);
+
+ QTRY_VERIFY(view.repaints == 1);
+
+ // test case #2
+ view.reset();
+ child3->setOpacity(0.0);
+ child3->setParentItem(child);
+
+ QTRY_VERIFY(view.repaints == 1);
+
+ // test case #3
+ view.reset();
+ child4->setParentItem(child);
+ child4->setVisible(false);
+
+ QTRY_VERIFY(view.repaints == 1);
+}
+
+void tst_QGraphicsItem::QT_2653_fullUpdateDiscardingOpacityUpdate()
+{
+ QGraphicsScene scene(0, 0, 200, 200);
+ MyGraphicsView view(&scene);
+
+ EventTester *parentGreen = new EventTester();
+ parentGreen->setGeometry(QRectF(20, 20, 100, 100));
+ parentGreen->brush = Qt::green;
+
+ EventTester *childYellow = new EventTester(parentGreen);
+ childYellow->setGeometry(QRectF(10, 10, 50, 50));
+ childYellow->brush = Qt::yellow;
+
+ scene.addItem(parentGreen);
+
+ childYellow->setOpacity(0.0);
+ parentGreen->setOpacity(0.0);
+
+ // set any of the flags below to trigger a fullUpdate to reproduce the bug:
+ // ItemIgnoresTransformations, ItemClipsChildrenToShape, ItemIsSelectable
+ parentGreen->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+
+ if (PlatformQuirks::isAutoMaximizing())
+ view.showFullScreen();
+ else
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ view.reset();
+
+ parentGreen->setOpacity(1.0);
+
+ QTRY_COMPARE(view.repaints, 1);
+
+ view.reset();
+ childYellow->repaints = 0;
+
+ childYellow->setOpacity(1.0);
+
+ QTRY_COMPARE(view.repaints, 1);
+ QTRY_COMPARE(childYellow->repaints, 1);
+}
+
+void tst_QGraphicsItem::QTBUG_7714_fullUpdateDiscardingOpacityUpdate2()
+{
+ QGraphicsScene scene(0, 0, 200, 200);
+ MyGraphicsView view(&scene);
+ MyGraphicsView origView(&scene);
+
+ EventTester *parentGreen = new EventTester();
+ parentGreen->setGeometry(QRectF(20, 20, 100, 100));
+ parentGreen->brush = Qt::green;
+
+ EventTester *childYellow = new EventTester(parentGreen);
+ childYellow->setGeometry(QRectF(10, 10, 50, 50));
+ childYellow->brush = Qt::yellow;
+
+ scene.addItem(parentGreen);
+
+ origView.show();
+ QTest::qWaitForWindowShown(&origView);
+ origView.setGeometry(origView.width() + 20, 20,
+ origView.width(), origView.height());
+
+ parentGreen->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+
+ origView.reset();
+ childYellow->setOpacity(0.0);
+
+ QTRY_COMPARE(origView.repaints, 1);
+
+ view.show();
+
+ QTest::qWaitForWindowShown(&view);
+ view.reset();
+ origView.reset();
+
+ childYellow->setOpacity(1.0);
+
+ QTRY_COMPARE(origView.repaints, 1);
+ QTRY_COMPARE(view.repaints, 1);
+}
+
+void tst_QGraphicsItem::QT_2649_focusScope()
+{
+ QGraphicsScene *scene = new QGraphicsScene;
+
+ QGraphicsRectItem *subFocusItem = new QGraphicsRectItem;
+ subFocusItem->setFlags(QGraphicsItem::ItemIsFocusable);
+ subFocusItem->setFocus();
+ QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
+
+ QGraphicsRectItem *scope = new QGraphicsRectItem;
+ scope->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
+ scope->setFocus();
+ subFocusItem->setParentItem(scope);
+ QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
+ QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
+
+ QGraphicsRectItem *rootItem = new QGraphicsRectItem;
+ rootItem->setFlags(QGraphicsItem::ItemIsFocusable);
+ scope->setParentItem(rootItem);
+ QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
+ QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
+ QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
+
+ scene->addItem(rootItem);
+
+ QEvent windowActivate(QEvent::WindowActivate);
+ qApp->sendEvent(scene, &windowActivate);
+ scene->setFocus();
+
+ QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
+ QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
+ QVERIFY(subFocusItem->hasFocus());
+
+ scope->hide();
+
+ QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)0);
+ QCOMPARE(scope->focusItem(), (QGraphicsItem *)0);
+ QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)0);
+ QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
+ QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
+ QVERIFY(!subFocusItem->hasFocus());
+
+ scope->show();
+
+ QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
+ QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
+ QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
+ QVERIFY(subFocusItem->hasFocus());
+
+ // This should not crash
+ scope->hide();
+ delete scene;
+}
+
+class MyGraphicsItemWithItemChange : public QGraphicsWidget
+{
+public:
+ MyGraphicsItemWithItemChange(QGraphicsItem *parent = 0) : QGraphicsWidget(parent)
+ {}
+
+ QVariant itemChange(GraphicsItemChange change, const QVariant &value)
+ {
+ if (change == QGraphicsItem::ItemSceneHasChanged) {
+ foreach (QGraphicsView *view, scene()->views()) {
+ //We trigger a sort of unindexed items in the BSP
+ view->sceneRect();
+ }
+ }
+ return QGraphicsWidget::itemChange(change, value);
+ }
+};
+
+void tst_QGraphicsItem::sortItemsWhileAdding()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget grandGrandParent;
+ grandGrandParent.resize(200, 200);
+ scene.addItem(&grandGrandParent);
+ QGraphicsWidget grandParent;
+ grandParent.resize(200, 200);
+ QGraphicsWidget parent(&grandParent);
+ parent.resize(200, 200);
+ MyGraphicsItemWithItemChange item(&parent);
+ grandParent.setParentItem(&grandGrandParent);
+}
+
+void tst_QGraphicsItem::doNotMarkFullUpdateIfNotInScene()
+{
+ struct Item : public QGraphicsTextItem
+ {
+ int painted;
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *opt, QWidget *wid)
+ {
+ painted++;
+ QGraphicsTextItem::paint(painter, opt, wid);
+ }
+ };
+ QGraphicsScene scene;
+ MyGraphicsView view(&scene);
+ Item *item = new Item;
+ item->painted = 0;
+ item->setPlainText("Grandparent");
+ Item *item2 = new Item;
+ item2->setPlainText("parent");
+ item2->painted = 0;
+ Item *item3 = new Item;
+ item3->setPlainText("child");
+ item3->painted = 0;
+ QGraphicsOpacityEffect *effect = new QGraphicsOpacityEffect;
+ effect->setOpacity(0.5);
+ item2->setGraphicsEffect(effect);
+ item3->setParentItem(item2);
+ item2->setParentItem(item);
+ scene.addItem(item);
+ if(PlatformQuirks::isAutoMaximizing())
+ view.showFullScreen();
+ else
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(view.repaints, 1);
+ QTRY_COMPARE(item->painted, 1);
+ QTRY_COMPARE(item2->painted, 1);
+ QTRY_COMPARE(item3->painted, 1);
+ item2->update();
+ QApplication::processEvents();
+ QTRY_COMPARE(item->painted, 2);
+ QTRY_COMPARE(item2->painted, 2);
+ QTRY_COMPARE(item3->painted, 2);
+ item2->update();
+ QApplication::processEvents();
+ QTRY_COMPARE(item->painted, 3);
+ QTRY_COMPARE(item2->painted, 3);
+ QTRY_COMPARE(item3->painted, 3);
+}
+
+void tst_QGraphicsItem::itemDiesDuringDraggingOperation()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
+ item->setFlag(QGraphicsItem::ItemIsMovable);
+ item->setAcceptDrops(true);
+ scene.addItem(item);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget *)&view);
+ QGraphicsSceneDragDropEvent dragEnter(QEvent::GraphicsSceneDragEnter);
+ dragEnter.setScenePos(item->boundingRect().center());
+ QApplication::sendEvent(&scene, &dragEnter);
+ QGraphicsSceneDragDropEvent event(QEvent::GraphicsSceneDragMove);
+ event.setScenePos(item->boundingRect().center());
+ QApplication::sendEvent(&scene, &event);
+ QVERIFY(QGraphicsScenePrivate::get(&scene)->dragDropItem == item);
+ delete item;
+ QVERIFY(QGraphicsScenePrivate::get(&scene)->dragDropItem == 0);
+}
+
+void tst_QGraphicsItem::QTBUG_12112_focusItem()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsRectItem *item1 = new QGraphicsRectItem(0, 0, 20, 20);
+ item1->setFlag(QGraphicsItem::ItemIsFocusable);
+ QGraphicsRectItem *item2 = new QGraphicsRectItem(20, 20, 20, 20);
+ item2->setFlag(QGraphicsItem::ItemIsFocusable);
+ item1->setFocus();
+ scene.addItem(item2);
+ scene.addItem(item1);
+
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget *)&view);
+
+ QVERIFY(item1->focusItem());
+ QVERIFY(!item2->focusItem());
+
+ item2->setFocus();
+ QVERIFY(!item1->focusItem());
+ QVERIFY(item2->focusItem());
+}
+
+void tst_QGraphicsItem::QTBUG_13473_sceneposchange()
+{
+ ScenePosChangeTester* parent = new ScenePosChangeTester;
+ ScenePosChangeTester* child = new ScenePosChangeTester(parent);
+
+ // parent's disabled ItemSendsGeometryChanges flag must not affect
+ // child's scene pos change notifications
+ parent->setFlag(QGraphicsItem::ItemSendsGeometryChanges, false);
+ child->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
+
+ QGraphicsScene scene;
+ scene.addItem(parent);
+
+ // ignore uninteresting changes
+ parent->clear();
+ child->clear();
+
+ // move
+ parent->moveBy(1.0, 1.0);
+ QCOMPARE(child->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
+
+ // transform
+ parent->setTransform(QTransform::fromScale(0.5, 0.5));
+ QCOMPARE(child->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 2);
+}
+
+class MyGraphicsWidget : public QGraphicsWidget {
+Q_OBJECT
+public:
+ MyGraphicsWidget()
+ : QGraphicsWidget(0)
+ {
+ QGraphicsLinearLayout *lay = new QGraphicsLinearLayout(Qt::Vertical);
+ QLatin1String wiseWords("AZ BUKI VEDI");
+ QString sentence(wiseWords);
+ QStringList words = sentence.split(QLatin1Char(' '), QString::SkipEmptyParts);
+ for (int i = 0; i < words.count(); ++i) {
+ QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(this);
+ QLabel *label = new QLabel(words.at(i));
+ proxy->setWidget(label);
+ proxy->setFocusPolicy(Qt::StrongFocus);
+ proxy->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
+ if (i%2 == 0)
+ proxy->setVisible(false);
+ proxy->setFocus();
+ lay->addItem(proxy);
+ }
+ setLayout(lay);
+ }
+
+};
+
+class MyWidgetWindow : public QGraphicsWidget
+{
+public:
+ MyWidgetWindow()
+ : QGraphicsWidget(0, Qt::Window)
+ {
+ QGraphicsLinearLayout *lay = new QGraphicsLinearLayout(Qt::Vertical);
+ MyGraphicsWidget *widget = new MyGraphicsWidget();
+ lay->addItem(widget);
+ setLayout(lay);
+ }
+};
+
+void tst_QGraphicsItem::QTBUG_16374_crashInDestructor()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ MyWidgetWindow win;
+ scene.addItem(&win);
+
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+}
+
+void tst_QGraphicsItem::QTBUG_20699_focusScopeCrash()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsPixmapItem fs;
+ fs.setFlags(QGraphicsItem::ItemIsFocusScope | QGraphicsItem::ItemIsFocusable);
+ scene.addItem(&fs);
+ QGraphicsPixmapItem* fs2 = new QGraphicsPixmapItem(&fs);
+ fs2->setFlags(QGraphicsItem::ItemIsFocusScope | QGraphicsItem::ItemIsFocusable);
+ QGraphicsPixmapItem* fi2 = new QGraphicsPixmapItem(&fs);
+ fi2->setFlags(QGraphicsItem::ItemIsFocusable);
+ QGraphicsPixmapItem* fi = new QGraphicsPixmapItem(fs2);
+ fi->setFlags(QGraphicsItem::ItemIsFocusable);
+ fs.setFocus();
+ fi->setFocus();
+
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ fi->setParentItem(fi2);
+ fi->setFocus();
+ fs.setFocus();
+ fi->setParentItem(fs2);
+ fi->setFocus();
+ fs2->setFocus();
+ fs.setFocus();
+ fi->setParentItem(fi2);
+ fi->setFocus();
+ fs.setFocus();
+}
+
+QTEST_MAIN(tst_QGraphicsItem)
+#include "tst_qgraphicsitem.moc"
diff --git a/tests/auto/widgets/graphicsview/qgraphicsitemanimation/.gitignore b/tests/auto/widgets/graphicsview/qgraphicsitemanimation/.gitignore
new file mode 100644
index 0000000000..fe9fe0b8ec
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsitemanimation/.gitignore
@@ -0,0 +1 @@
+tst_qgraphicsitemanimation
diff --git a/tests/auto/widgets/graphicsview/qgraphicsitemanimation/qgraphicsitemanimation.pro b/tests/auto/widgets/graphicsview/qgraphicsitemanimation/qgraphicsitemanimation.pro
new file mode 100644
index 0000000000..5d723da32e
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsitemanimation/qgraphicsitemanimation.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qgraphicsitemanimation.cpp
+DEFINES += QT_NO_CAST_TO_ASCII
+CONFIG += parallel_test
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp b/tests/auto/widgets/graphicsview/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp
new file mode 100644
index 0000000000..f7cf393253
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsitemanimation/tst_qgraphicsitemanimation.cpp
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.1, 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qgraphicsitemanimation.h>
+#include <QtCore/qtimeline.h>
+#include <QtGui/qmatrix.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QGraphicsItemAnimation : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void construction();
+ void linearMove();
+ void linearRotation();
+ void checkReturnedLists();
+ void overwriteValueForStep();
+ void setTimeLine();
+};
+
+void tst_QGraphicsItemAnimation::construction()
+{
+ QGraphicsItemAnimation animation;
+ QVERIFY(!animation.item());
+ QVERIFY(!animation.timeLine());
+ QCOMPARE(animation.posAt(0), QPointF());
+ QCOMPARE(animation.posAt(0.5), QPointF());
+ QCOMPARE(animation.posAt(1), QPointF());
+ QCOMPARE(animation.matrixAt(0), QMatrix());
+ QCOMPARE(animation.matrixAt(0.5), QMatrix());
+ QCOMPARE(animation.matrixAt(1), QMatrix());
+ QCOMPARE(animation.rotationAt(0), qreal(0.0));
+ QCOMPARE(animation.rotationAt(0.5), qreal(0.0));
+ QCOMPARE(animation.rotationAt(1), qreal(0.0));
+ QCOMPARE(animation.xTranslationAt(0), qreal(0.0));
+ QCOMPARE(animation.xTranslationAt(0.5), qreal(0.0));
+ QCOMPARE(animation.xTranslationAt(1), qreal(0.0));
+ QCOMPARE(animation.yTranslationAt(0), qreal(0.0));
+ QCOMPARE(animation.yTranslationAt(0.5), qreal(0.0));
+ QCOMPARE(animation.yTranslationAt(1), qreal(0.0));
+ QCOMPARE(animation.verticalScaleAt(0), qreal(1.0));
+ QCOMPARE(animation.horizontalScaleAt(0), qreal(1.0));
+ QCOMPARE(animation.verticalShearAt(0), qreal(0.0));
+ QCOMPARE(animation.horizontalShearAt(0), qreal(0.0));
+ animation.clear(); // don't crash
+}
+
+void tst_QGraphicsItemAnimation::linearMove()
+{
+ QGraphicsItemAnimation animation;
+
+ for (int i = 0; i <= 10; ++i) {
+ QCOMPARE(animation.posAt(i / 10.0).x(), qreal(0));
+ QCOMPARE(animation.posAt(i / 10.0).y(), qreal(0));
+ }
+
+ animation.setPosAt(1, QPointF(10, -10));
+
+ for (int i = 0; i <= 10; ++i) {
+ QCOMPARE(animation.posAt(i / 10.0).x(), qreal(i));
+ QCOMPARE(animation.posAt(i / 10.0).y(), qreal(-i));
+ }
+
+ animation.setPosAt(2, QPointF(10, -10));
+
+ QCOMPARE(animation.posAt(11).x(), qreal(10));
+}
+
+void tst_QGraphicsItemAnimation::linearRotation()
+{
+ QGraphicsItemAnimation animation;
+ animation.setRotationAt(1, 1);
+
+ for (int i = 0; i <= 10; ++i)
+ QCOMPARE(animation.rotationAt(i / 10.0), qreal(i / 10.0));
+}
+
+void tst_QGraphicsItemAnimation::checkReturnedLists()
+{
+ QGraphicsItemAnimation animation;
+
+ animation.setPosAt(1.0, QPointF(10, -10));
+ animation.setPosAt(0.5, QPointF(5, -5));
+
+ animation.setRotationAt(0.3, 2.3);
+ animation.setTranslationAt(0.3, 15, 15);
+ animation.setScaleAt(0.3, 2.5, 1.8);
+ animation.setShearAt(0.3, 5, 5);
+
+ QCOMPARE(animation.posList().at(0), (QPair<qreal, QPointF>(0.5, QPointF(5, -5))));
+ QCOMPARE(animation.posList().at(1), (QPair<qreal, QPointF>(1.0, QPointF(10, -10))));
+ QCOMPARE(animation.rotationList().at(0), (QPair<qreal, qreal>(0.3, 2.3)));
+ QCOMPARE(animation.translationList().at(0), (QPair<qreal, QPointF>(0.3, QPointF(15, 15))));
+ QCOMPARE(animation.scaleList().at(0), (QPair<qreal, QPointF>(0.3, QPointF(2.5, 1.8))));
+ QCOMPARE(animation.shearList().at(0), (QPair<qreal, QPointF>(0.3, QPointF(5, 5))));
+
+ QCOMPARE(animation.posList().size(), 2);
+ QCOMPARE(animation.rotationList().size(), 1);
+ QCOMPARE(animation.translationList().size(), 1);
+ QCOMPARE(animation.scaleList().size(), 1);
+ QCOMPARE(animation.shearList().size(), 1);
+}
+
+void tst_QGraphicsItemAnimation::overwriteValueForStep()
+{
+ QGraphicsItemAnimation animation;
+
+ for (int i=0; i<3; i++){
+ animation.setPosAt(0.3, QPointF(3, -3.1));
+ animation.setRotationAt(0.3, 2.3);
+ animation.setTranslationAt(0.3, 15, 15);
+ animation.setScaleAt(0.3, 2.5, 1.8);
+ animation.setShearAt(0.3, 5, 5);
+
+ QCOMPARE(animation.posList().size(), 1);
+ QCOMPARE(animation.rotationList().size(), 1);
+ QCOMPARE(animation.translationList().size(), 1);
+ QCOMPARE(animation.scaleList().size(), 1);
+ QCOMPARE(animation.shearList().size(), 1);
+ }
+}
+
+void tst_QGraphicsItemAnimation::setTimeLine()
+{
+ QGraphicsItemAnimation animation;
+ QCOMPARE(animation.timeLine(), (QTimeLine *)0);
+
+ QPointer<QTimeLine> line1 = new QTimeLine;
+ animation.setTimeLine(line1);
+ QCOMPARE(animation.timeLine(), (QTimeLine *)line1);
+ animation.setTimeLine(line1);
+ QVERIFY(line1);
+ QCOMPARE(animation.timeLine(), (QTimeLine *)line1);
+
+ animation.setTimeLine(0);
+ QCOMPARE(animation.timeLine(), (QTimeLine *)0);
+ QVERIFY(!line1);
+
+ QTimeLine *line2 = new QTimeLine;
+ animation.setTimeLine(line2);
+ QCOMPARE(animation.timeLine(), (QTimeLine *)line2);
+
+ delete line2;
+ QCOMPARE(animation.timeLine(), (QTimeLine *)0);
+}
+
+QTEST_MAIN(tst_QGraphicsItemAnimation)
+#include "tst_qgraphicsitemanimation.moc"
diff --git a/tests/auto/widgets/graphicsview/qgraphicslayout/.gitignore b/tests/auto/widgets/graphicsview/qgraphicslayout/.gitignore
new file mode 100644
index 0000000000..b3b27f68a1
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicslayout/.gitignore
@@ -0,0 +1 @@
+tst_qgraphicslayout
diff --git a/tests/auto/widgets/graphicsview/qgraphicslayout/qgraphicslayout.pro b/tests/auto/widgets/graphicsview/qgraphicslayout/qgraphicslayout.pro
new file mode 100644
index 0000000000..ea176c98fe
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicslayout/qgraphicslayout.pro
@@ -0,0 +1,9 @@
+############################################################
+# Project file for autotest for file qlayout.h
+############################################################
+
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qgraphicslayout.cpp
+DEFINES += QT_USE_USING_NAMESPACE
+CONFIG += parallel_test
diff --git a/tests/auto/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp b/tests/auto/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp
new file mode 100644
index 0000000000..3eac04e4e5
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicslayout/tst_qgraphicslayout.cpp
@@ -0,0 +1,992 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.1, 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtGui>
+#include <QtWidgets>
+#include <math.h>
+
+//TESTED_CLASS=QGraphicsLayout
+//TESTED_FILES=
+
+class tst_QGraphicsLayout : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_QGraphicsLayout();
+ virtual ~tst_QGraphicsLayout();
+
+private slots:
+ void sizeHints();
+ void compressLayoutRequest();
+ void automaticReparenting();
+ void verifyActivate();
+ void invalidate();
+ void constructors();
+ void alternativeLayoutItems();
+ void ownership();
+};
+
+tst_QGraphicsLayout::tst_QGraphicsLayout()
+{
+}
+
+tst_QGraphicsLayout::~tst_QGraphicsLayout()
+{
+}
+
+void tst_QGraphicsLayout::sizeHints()
+{
+
+ QGraphicsView view;
+ QGraphicsScene scene;
+ QGraphicsWidget *window = new QGraphicsWidget();
+ scene.addItem(window);
+ QGraphicsLinearLayout *lout = new QGraphicsLinearLayout(window);
+ lout->setContentsMargins(0,0,0,0);
+ QGraphicsWidget *gw = new QGraphicsWidget(window);
+ gw->setMinimumSize(QSizeF(10,10));
+ gw->setPreferredSize(QSizeF(100,100));
+ gw->setMaximumSize(QSizeF(500,500));
+ lout->addItem(gw);
+ QCOMPARE(lout->effectiveSizeHint(Qt::MinimumSize), gw->effectiveSizeHint(Qt::MinimumSize));
+ QCOMPARE(lout->effectiveSizeHint(Qt::PreferredSize), gw->effectiveSizeHint(Qt::PreferredSize));
+ QCOMPARE(lout->effectiveSizeHint(Qt::MaximumSize), gw->effectiveSizeHint(Qt::MaximumSize));
+
+}
+
+enum FunctionType {
+ SetGeometry = 0,
+ Invalidate,
+ NumFunctionTypes
+};
+
+
+
+class TestGraphicsWidget : public QGraphicsWidget {
+public:
+ TestGraphicsWidget(QGraphicsWidget *parent = 0) : QGraphicsWidget(parent)
+ { }
+
+ bool event(QEvent *e) {
+ ++(m_eventCount[int(e->type())]);
+ return QGraphicsWidget::event(e);
+ }
+
+ int eventCount(QEvent::Type type) {
+ return m_eventCount.value(int(type));
+ }
+
+ void clearEventCount() {
+ m_eventCount.clear();
+ }
+
+ void clearCounters() {
+ m_eventCount.clear();
+ functionCount.clear();
+ }
+
+ void setGeometry(const QRectF &rect)
+ {
+ QGraphicsWidget::setGeometry(rect);
+ ++(functionCount[SetGeometry]);
+ }
+
+ void callUpdateGeometry()
+ {
+ // updateGeometry() is protected
+ QGraphicsWidget::updateGeometry();
+ }
+ QMap<FunctionType, int> functionCount;
+private:
+ QMap<int, int> m_eventCount;
+};
+
+void tst_QGraphicsLayout::compressLayoutRequest()
+{
+ QGraphicsView view;
+ QGraphicsScene scene;
+ TestGraphicsWidget *tw = new TestGraphicsWidget();
+ scene.addItem(tw);
+ view.show();
+
+ QTest::qWaitForWindowShown(&view);
+ QGraphicsLinearLayout *lout = new QGraphicsLinearLayout(tw);
+ for (int i = 0; i < 4; ++i) {
+ QGraphicsWidget *gw = new QGraphicsWidget(tw);
+ gw->setPreferredSize(QSizeF(50, 50));
+ lout->addItem(gw);
+ }
+ QApplication::processEvents();
+ QCOMPARE(tw->eventCount(QEvent::LayoutRequest), 1);
+}
+
+void tst_QGraphicsLayout::automaticReparenting()
+{
+ QGraphicsView view;
+ QGraphicsScene scene;
+ {
+ QGraphicsWidget *w = new QGraphicsWidget();
+ QGraphicsLinearLayout *l = new QGraphicsLinearLayout(w);
+ QGraphicsWidget *w1 = new QGraphicsWidget;
+ l->addItem(w1);
+ scene.addItem(w);
+ QCOMPARE(w1->parentWidget(), w);
+ delete w;
+ }
+ {
+ QGraphicsWidget *w = new QGraphicsWidget();
+ QGraphicsLinearLayout *l = new QGraphicsLinearLayout(w);
+ QGraphicsWidget *w1 = new QGraphicsWidget;
+ l->addItem(w1);
+ scene.addItem(w);
+ QCOMPARE(w1->parentWidget(), w);
+
+ QGraphicsWidget *ww = new QGraphicsWidget();
+ QGraphicsLinearLayout *l1 = new QGraphicsLinearLayout(ww);
+#if !defined(Q_OS_MAC) && defined(QT_DEBUG)
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsLayout::addChildLayoutItem: QGraphicsWidget \"\""
+ " in wrong parent; moved to correct parent");
+#endif
+ l1->addItem(w1);
+ QCOMPARE(w1->parentWidget(), ww);
+ delete w;
+ }
+
+ QGraphicsWidget *window = new QGraphicsWidget();
+ scene.addItem(window);
+ view.show();
+ QGraphicsLinearLayout *l1 = new QGraphicsLinearLayout();
+ QGraphicsWidget *w1 = new QGraphicsWidget();
+ l1->addItem(w1);
+ QGraphicsWidget *w2 = new QGraphicsWidget();
+ l1->addItem(w2);
+ QCOMPARE(w1->parentItem(), static_cast<QGraphicsItem*>(0));
+ QCOMPARE(w2->parentItem(), static_cast<QGraphicsItem*>(0));
+ scene.addItem(w1);
+ QCOMPARE(w1->parentItem(), static_cast<QGraphicsItem*>(0));
+ window->setLayout(l1);
+ QCOMPARE(w1->parentItem(), static_cast<QGraphicsItem*>(window));
+ QCOMPARE(w2->parentItem(), static_cast<QGraphicsItem*>(window));
+
+ // Sublayouts
+ QGraphicsLinearLayout *l2 = new QGraphicsLinearLayout();
+ QGraphicsWidget *w3 = new QGraphicsWidget();
+ l2->addItem(w3);
+ QGraphicsWidget *w4 = new QGraphicsWidget();
+ l2->addItem(w4);
+ QGraphicsLinearLayout *l3 = new QGraphicsLinearLayout();
+ l2->addItem(l3);
+ QGraphicsWidget *window2 = new QGraphicsWidget();
+ scene.addItem(window2);
+ window2->setLayout(l2);
+
+ QCOMPARE(w3->parentItem(), static_cast<QGraphicsItem*>(window2));
+ QCOMPARE(w4->parentItem(), static_cast<QGraphicsItem*>(window2));
+
+ // graphics item with another parent
+ QGraphicsLinearLayout *l5 = new QGraphicsLinearLayout();
+ l5->addItem(w1);
+ l5->addItem(w2);
+ QCOMPARE(w1->parentItem(), static_cast<QGraphicsItem*>(window));
+ QCOMPARE(w2->parentItem(), static_cast<QGraphicsItem*>(window));
+ QGraphicsLinearLayout *l4 = new QGraphicsLinearLayout();
+ l4->addItem(l5);
+ QGraphicsWidget *window3 = new QGraphicsWidget();
+ scene.addItem(window3);
+ window3->setLayout(l4);
+
+ QCOMPARE(w1->parentItem(), static_cast<QGraphicsItem*>(window3));
+ QCOMPARE(w2->parentItem(), static_cast<QGraphicsItem*>(window3));
+}
+
+class TestLayout : public QGraphicsLinearLayout
+{
+ public:
+ TestLayout(QGraphicsLayoutItem *parent = 0)
+ : QGraphicsLinearLayout(parent)
+ {
+ setContentsMargins(0,0,0,0);
+ setSpacing(0);
+ }
+
+ void setGeometry(const QRectF &rect)
+ {
+ ++(functionCount[SetGeometry]);
+ QGraphicsLinearLayout::setGeometry(rect);
+ }
+
+ void invalidate()
+ {
+ ++(functionCount[Invalidate]);
+ QGraphicsLinearLayout::invalidate();
+ }
+
+ void clearCounters() {
+ functionCount.clear();
+ }
+
+ QMap<FunctionType, int> functionCount;
+};
+
+void tst_QGraphicsLayout::verifyActivate()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ QGraphicsWidget *window = new QGraphicsWidget();
+ scene.addItem(window);
+ TestLayout *lout = new TestLayout(window);
+ QGraphicsWidget *w = new QGraphicsWidget();
+ lout->addItem(w);
+ window->setLayout(lout);
+
+ QCOMPARE(lout->functionCount[SetGeometry], 0);
+ window->setVisible(false);
+ QCOMPARE(lout->functionCount[SetGeometry], 0);
+ window->setVisible(true);
+ // on polish or the first time a widget is shown, the widget is resized.
+ QCOMPARE(lout->functionCount[SetGeometry], 1);
+
+}
+
+static void clearAllCounters(TestGraphicsWidget *widget)
+{
+ if (!widget)
+ return;
+ widget->clearCounters();
+ TestLayout *layout = static_cast<TestLayout *>(widget->layout());
+ if (layout) {
+ layout->clearCounters();
+ for (int i = layout->count() - 1; i >=0; --i) {
+ QGraphicsLayoutItem *item = layout->itemAt(i);
+ if (item->isLayout()) {
+ // ### Not used ATM
+ //TestLayout *lay = static_cast<TestLayout*>(static_cast<QGraphicsLayout*>(item));
+ //clearAllCounters(lay);
+ } else {
+ TestGraphicsWidget *wid = static_cast<TestGraphicsWidget *>(item);
+ clearAllCounters(wid);
+ }
+ }
+ }
+}
+
+static void activateAndReset(TestGraphicsWidget *widget)
+{
+ QApplication::sendPostedEvents();
+ QApplication::processEvents();
+ if (widget->layout())
+ widget->layout()->activate();
+ clearAllCounters(widget);
+}
+
+
+void tst_QGraphicsLayout::invalidate()
+{
+ QGraphicsLayout::setInstantInvalidatePropagation(true);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ TestGraphicsWidget *a = new TestGraphicsWidget;
+ a->setData(0, QString("a"));
+ scene.addItem(a);
+ TestLayout *alay = new TestLayout(a);
+ TestGraphicsWidget *b = new TestGraphicsWidget;
+ b->setData(0, QString("b"));
+ alay->addItem(b);
+ TestLayout *blay = new TestLayout(b);
+ TestGraphicsWidget *e = new TestGraphicsWidget;
+ e->setData(0, QString("e"));
+ blay->addItem(e);
+
+
+ TestGraphicsWidget *c = new TestGraphicsWidget;
+ c->setData(0, QString("c"));
+ alay->addItem(c);
+ TestLayout *clay = new TestLayout(c);
+ TestGraphicsWidget *f = new TestGraphicsWidget;
+ f->setData(0, QString("f"));
+ clay->addItem(f);
+
+ TestGraphicsWidget *d = new TestGraphicsWidget;
+ d->setData(0, QString("d"));
+ alay->addItem(d);
+ TestLayout *dlay = new TestLayout(d);
+ TestGraphicsWidget *g = new TestGraphicsWidget;
+ g->setData(0, QString("g"));
+ dlay->addItem(g);
+
+ view.show();
+
+ {
+ clearAllCounters(a);
+
+ QCoreApplication::sendPostedEvents();
+ QCoreApplication::processEvents();
+
+ alay->activate();
+ QCOMPARE(alay->isActivated(), true);
+ QCOMPARE(blay->isActivated(), true);
+ QCOMPARE(clay->isActivated(), true);
+ QCOMPARE(dlay->isActivated(), true);
+ }
+
+ {
+ clearAllCounters(a);
+ e->callUpdateGeometry();
+ QCOMPARE(alay->isActivated(), false);
+ QCOMPARE(blay->isActivated(), false);
+ QCOMPARE(clay->isActivated(), true);
+ QCOMPARE(dlay->isActivated(), true);
+ QCOMPARE(a->eventCount(QEvent::LayoutRequest), 0);
+ QCOMPARE(b->eventCount(QEvent::LayoutRequest), 0);
+ QCOMPARE(c->eventCount(QEvent::LayoutRequest), 0);
+ QCOMPARE(d->eventCount(QEvent::LayoutRequest), 0);
+
+ // should only invalidate ascendants of e
+ QCOMPARE(blay->functionCount[Invalidate], 1);
+ QCOMPARE(alay->functionCount[Invalidate], 1);
+ // not siblings
+ QCOMPARE(clay->functionCount[Invalidate], 0);
+ QCOMPARE(dlay->functionCount[Invalidate], 0);
+
+ QApplication::sendPostedEvents();
+ QCOMPARE(a->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(b->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(c->eventCount(QEvent::LayoutRequest), 0);
+ QCOMPARE(d->eventCount(QEvent::LayoutRequest), 0);
+ }
+
+
+ {
+ activateAndReset(a);
+ f->callUpdateGeometry();
+ QCOMPARE(alay->isActivated(), false);
+ QCOMPARE(blay->isActivated(), true);
+ QCOMPARE(clay->isActivated(), false);
+ QCOMPARE(dlay->isActivated(), true);
+
+ QCoreApplication::sendPostedEvents();
+ QCOMPARE(a->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(b->eventCount(QEvent::LayoutRequest), 0);
+ QCOMPARE(c->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(d->eventCount(QEvent::LayoutRequest), 0);
+
+ QCOMPARE(a->functionCount[SetGeometry], 1);
+ QCOMPARE(alay->functionCount[SetGeometry], 1);
+
+ QCOMPARE(b->functionCount[SetGeometry], 1);
+ QCOMPARE(c->functionCount[SetGeometry], 1);
+ QCOMPARE(d->functionCount[SetGeometry], 1);
+ // Since nothing really changed, blay and dlay don't need
+ // to be resized.
+ QCOMPARE(blay->functionCount[SetGeometry], 0);
+ QCOMPARE(clay->functionCount[SetGeometry], 1);
+ QCOMPARE(dlay->functionCount[SetGeometry], 0);
+
+ QCOMPARE(f->functionCount[SetGeometry], 1);
+
+ QCOMPARE(a->size(), QSizeF(150, 50));
+ }
+
+ {
+ activateAndReset(a);
+ f->setPreferredSize(QSizeF(60,50));
+ QCOMPARE(alay->isActivated(), false);
+ QCOMPARE(blay->isActivated(), true);
+ QCOMPARE(clay->isActivated(), false);
+ QCOMPARE(dlay->isActivated(), true);
+
+ QCOMPARE(c->eventCount(QEvent::LayoutRequest), 0);
+ QCoreApplication::sendPostedEvents();
+ QCOMPARE(a->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(b->eventCount(QEvent::LayoutRequest), 0);
+ QCOMPARE(c->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(d->eventCount(QEvent::LayoutRequest), 0);
+
+ QCOMPARE(a->functionCount[SetGeometry], 1);
+ QCOMPARE(alay->functionCount[SetGeometry], 1);
+
+ QCOMPARE(b->functionCount[SetGeometry], 1);
+ QCOMPARE(c->functionCount[SetGeometry], 1);
+ QCOMPARE(d->functionCount[SetGeometry], 1);
+ // f actually got wider, need to rearrange its siblings
+ QCOMPARE(blay->functionCount[SetGeometry], 1);
+ QCOMPARE(clay->functionCount[SetGeometry], 1);
+ QCOMPARE(dlay->functionCount[SetGeometry], 1);
+
+ QCOMPARE(e->functionCount[SetGeometry], 1);
+ QCOMPARE(f->functionCount[SetGeometry], 1);
+ QCOMPARE(g->functionCount[SetGeometry], 1);
+
+ QVERIFY(e->size().width() < f->size().width());
+ QVERIFY(g->size().width() < f->size().width());
+ }
+
+ {
+ // resize f so much that it'll force a resize of the top widget
+ // this will currently generate two setGeometry() calls on the child layout
+ // of the top widget.
+ activateAndReset(a);
+ f->setPreferredSize(QSizeF());
+ f->setMinimumSize(QSizeF(200,50));
+ QCOMPARE(alay->isActivated(), false);
+ QCOMPARE(blay->isActivated(), true);
+ QCOMPARE(clay->isActivated(), false);
+ QCOMPARE(dlay->isActivated(), true);
+
+ QCOMPARE(c->eventCount(QEvent::LayoutRequest), 0);
+ QCoreApplication::sendPostedEvents();
+ QCOMPARE(a->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(b->eventCount(QEvent::LayoutRequest), 0);
+ QCOMPARE(c->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(d->eventCount(QEvent::LayoutRequest), 0);
+
+ QCOMPARE(a->functionCount[SetGeometry], 1);
+
+ /* well, ideally one call to setGeometry(), but it will currently
+ * get two calls to setGeometry():
+ * 1. The first LayoutRequest will call activate() - that will call
+ * setGeometry() on the layout. This geometry will be based on
+ * the widget geometry which is not correct at this moment.
+ * (it is still 150 wide)
+ * 2. Next, we check if the widget is top level, and then we call
+ * parentWidget->resize(parentWidget->size());
+ * This will be adjusted to be minimum 200 pixels wide.
+ * The new size will then be propagated down to the layout
+ *
+ */
+ QCOMPARE(alay->functionCount[SetGeometry], 2);
+
+ QCOMPARE(b->functionCount[SetGeometry], 2);
+ QCOMPARE(c->functionCount[SetGeometry], 2);
+ QCOMPARE(d->functionCount[SetGeometry], 2);
+ // f actually got wider, need to rearrange its siblings
+ QCOMPARE(blay->functionCount[SetGeometry], 1);
+ QCOMPARE(clay->functionCount[SetGeometry], 1);
+ QCOMPARE(dlay->functionCount[SetGeometry], 1);
+
+ QCOMPARE(e->functionCount[SetGeometry], 1);
+ QCOMPARE(f->functionCount[SetGeometry], 1);
+ QCOMPARE(g->functionCount[SetGeometry], 1);
+
+ QVERIFY(e->size().width() < f->size().width());
+ QVERIFY(g->size().width() < f->size().width());
+ }
+
+ {
+ f->setPreferredSize(QSizeF());
+ f->setMinimumSize(QSizeF());
+ a->adjustSize();
+ activateAndReset(a);
+ // update two different leaf widgets,
+ // eventCount and functionCount should never be >= 2
+ e->callUpdateGeometry();
+ g->callUpdateGeometry();
+ QCOMPARE(alay->isActivated(), false);
+ QCOMPARE(blay->isActivated(), false);
+ QCOMPARE(clay->isActivated(), true);
+ QCOMPARE(dlay->isActivated(), false);
+
+ QCoreApplication::sendPostedEvents();
+ QCOMPARE(a->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(b->eventCount(QEvent::LayoutRequest), 1);
+ QCOMPARE(c->eventCount(QEvent::LayoutRequest), 0);
+ QCOMPARE(d->eventCount(QEvent::LayoutRequest), 1);
+
+ QCOMPARE(a->functionCount[SetGeometry], 1);
+ QCOMPARE(alay->functionCount[SetGeometry], 1);
+
+ QCOMPARE(b->functionCount[SetGeometry], 1);
+ QCOMPARE(c->functionCount[SetGeometry], 1);
+ QCOMPARE(d->functionCount[SetGeometry], 1);
+ // f actually got wider, need to rearrange its siblings
+ QCOMPARE(blay->functionCount[SetGeometry], 1);
+ QCOMPARE(clay->functionCount[SetGeometry], 0);
+ QCOMPARE(dlay->functionCount[SetGeometry], 1);
+
+ QCOMPARE(e->functionCount[SetGeometry], 1);
+ QCOMPARE(f->functionCount[SetGeometry], 0);
+ QCOMPARE(g->functionCount[SetGeometry], 1);
+
+ }
+
+ QGraphicsLayout::setInstantInvalidatePropagation(false);
+}
+
+class Layout : public QGraphicsLayout
+{
+public:
+ Layout(QGraphicsLayoutItem *parentItem = 0) : QGraphicsLayout(parentItem) {}
+
+ void setGeometry(const QRectF &rect)
+ {
+ QGraphicsLayout::setGeometry(rect);
+ }
+
+ int count() const {
+ return 0;
+ }
+
+ QGraphicsLayoutItem *itemAt(int index) const {
+ Q_UNUSED(index);
+ return 0;
+ }
+
+ void removeAt(int index)
+ {
+ Q_UNUSED(index);
+ }
+
+protected:
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const
+ {
+ Q_UNUSED(constraint);
+ Q_UNUSED(which);
+ return QSizeF(100,100);
+ }
+
+};
+
+void tst_QGraphicsLayout::constructors()
+{
+ // Strange test, but see the fix that was with this submit
+ QVector<Layout*> layouts;
+ for (int pass = 0; pass < 5; ++pass) {
+ Layout *lay = new Layout();
+ layouts << lay;
+ qreal left, top, right, bottom;
+ lay->getContentsMargins(&left, &top, &right, &bottom);
+ // Test if the style defaults are sane (should always be ints)
+ double intpart;
+ QVERIFY(modf(left, &intpart) == 0.0);
+ QVERIFY(modf(top, &intpart) == 0.0);
+ QVERIFY(modf(right, &intpart) == 0.0);
+ QVERIFY(modf(bottom, &intpart) == 0.0);
+
+ lay->setContentsMargins(1, 2, 4, 8);
+ lay->getContentsMargins(&left, &top, &right, &bottom);
+
+ QCOMPARE(int(left), 1);
+ QCOMPARE(int(top), 2);
+ QCOMPARE(int(right), 4);
+ QCOMPARE(int(bottom), 8);
+ }
+
+ qDeleteAll(layouts);
+}
+
+class AnimatedLayoutItem : public QGraphicsLayoutItem {
+public:
+ AnimatedLayoutItem(QGraphicsRectItem *item)
+ : QGraphicsLayoutItem()
+ {
+ setGraphicsItem(item);
+ }
+
+ void setGeometry(const QRectF &geom);
+
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF & constraint = QSizeF() ) const;
+
+ inline QGraphicsRectItem *rectItem() {
+ return static_cast<QGraphicsRectItem *>(graphicsItem());
+ }
+
+ QRectF m_geom;
+private:
+ AnimatedLayoutItem() {}
+};
+
+void AnimatedLayoutItem::setGeometry(const QRectF &geom)
+{
+ QGraphicsLayoutItem::setGeometry(geom);
+}
+
+QSizeF AnimatedLayoutItem::sizeHint(Qt::SizeHint which, const QSizeF & /* constraint */) const
+{
+ switch (which) {
+ case Qt::MinimumSize:
+ return QSizeF(32,32);
+ case Qt::PreferredSize:
+ return QSizeF(160,90);
+ case Qt::MaximumSize:
+ return QSizeF(1000,1000);
+ default:
+ return QSizeF(300, 300);
+ }
+}
+
+class AnimatedLayout : public QObject, public QGraphicsLinearLayout {
+ Q_OBJECT
+public:
+ AnimatedLayout(QGraphicsWidget *widget) : QGraphicsLinearLayout(widget), m_timeline(500, this)
+ {
+ connect(&m_timeline, SIGNAL(valueChanged(qreal)), this, SLOT(valueChanged(qreal)));
+ }
+
+ void setGeometry(const QRectF &geom) {
+ fromGeoms.clear();
+ toGeoms.clear();
+ for (int i = 0; i < count(); ++i) {
+ fromGeoms << itemAt(i)->geometry();
+ }
+
+ QGraphicsLinearLayout::setGeometry(geom);
+
+ for (int i = 0; i < count(); ++i) {
+ toGeoms << itemAt(i)->geometry();
+ }
+ m_timeline.start();
+ }
+
+private slots:
+ void valueChanged(qreal value) {
+ for (int i = 0; i < fromGeoms.count(); ++i) {
+ QGraphicsLayoutItem *li = itemAt(i);
+ QRectF from = fromGeoms.at(i);
+ QRectF to = toGeoms.at(i);
+
+ QRectF geom(from.topLeft() + (to.topLeft() - from.topLeft()) * value,
+ from.size() + (to.size() - from.size()) * value);
+ static_cast<QGraphicsRectItem*>(li->graphicsItem())->setRect(geom);
+ }
+ }
+private:
+ QTimeLine m_timeline;
+ QVector<QRectF> fromGeoms;
+ QVector<QRectF> toGeoms;
+};
+
+
+void tst_QGraphicsLayout::alternativeLayoutItems()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ QGraphicsWidget *window = new QGraphicsWidget;
+ scene.addItem(window);
+ AnimatedLayout *lout = new AnimatedLayout(window);
+ lout->setContentsMargins(0, 0, 0, 0);
+ lout->setSpacing(0);
+
+ QGraphicsRectItem *item1 = new QGraphicsRectItem;
+ AnimatedLayoutItem *li1 = new AnimatedLayoutItem(item1);
+ lout->addItem(li1);
+
+ QGraphicsRectItem *item2 = new QGraphicsRectItem;
+ AnimatedLayoutItem *li2 = new AnimatedLayoutItem(item2);
+ lout->addItem(li2);
+
+ QGraphicsRectItem *item3 = new QGraphicsRectItem;
+ AnimatedLayoutItem *li3 = new AnimatedLayoutItem(item3);
+ lout->addItem(li3);
+
+ window->setLayout(lout);
+
+ window->setGeometry(0, 0, 99, 99);
+ view.setSceneRect(QRectF(-10, -10, 110, 110));
+ view.resize(150, 150);
+ view.show();
+
+ QTRY_COMPARE(static_cast<QGraphicsRectItem*>(li1->graphicsItem())->rect(), QRectF( 0, 0, 33, 99));
+ QTRY_COMPARE(static_cast<QGraphicsRectItem*>(li2->graphicsItem())->rect(), QRectF(33, 0, 33, 99));
+ QTRY_COMPARE(static_cast<QGraphicsRectItem*>(li3->graphicsItem())->rect(), QRectF(66, 0, 33, 99));
+
+ lout->setOrientation(Qt::Vertical);
+
+ QTRY_COMPARE(static_cast<QGraphicsRectItem*>(li1->graphicsItem())->rect(), QRectF(0, 0, 99, 33));
+ QTRY_COMPARE(static_cast<QGraphicsRectItem*>(li2->graphicsItem())->rect(), QRectF(0, 33, 99, 33));
+ QTRY_COMPARE(static_cast<QGraphicsRectItem*>(li3->graphicsItem())->rect(), QRectF(0, 66, 99, 33));
+
+}
+
+class CustomLayoutItem : public QGraphicsLayoutItem {
+public:
+ CustomLayoutItem(QSet<QGraphicsLayoutItem*> *destructedSet)
+ : QGraphicsLayoutItem()
+ {
+ m_destructedSet = destructedSet;
+ setOwnedByLayout(true);
+ }
+
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF & constraint = QSizeF() ) const;
+
+ ~CustomLayoutItem() {
+ m_destructedSet->insert(this);
+ }
+private:
+ QSet<QGraphicsLayoutItem*> *m_destructedSet;
+};
+
+QSizeF CustomLayoutItem::sizeHint(Qt::SizeHint which, const QSizeF & /* constraint */) const
+{
+ switch (which) {
+ case Qt::MinimumSize:
+ return QSizeF(32,32);
+ case Qt::PreferredSize:
+ return QSizeF(160,90);
+ case Qt::MaximumSize:
+ return QSizeF(1000,1000);
+ default:
+ return QSizeF(300, 300);
+ }
+}
+
+class CustomGraphicsWidget : public QGraphicsWidget {
+public:
+ CustomGraphicsWidget(QSet<QGraphicsLayoutItem*> *destructedSet = 0)
+ : QGraphicsWidget()
+ {
+ m_destructedSet = destructedSet;
+ }
+
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF & constraint = QSizeF() ) const;
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget * = 0)
+ {
+ const QRect r = option->rect.adjusted(0, 0, -1, -1);
+ painter->drawLine(r.topLeft(), r.bottomRight());
+ painter->drawLine(r.bottomLeft(), r.topRight());
+ painter->drawRect(r);
+ }
+
+ ~CustomGraphicsWidget() {
+ if (m_destructedSet)
+ m_destructedSet->insert(this);
+ }
+private:
+ QSet<QGraphicsLayoutItem*> *m_destructedSet;
+};
+
+QSizeF CustomGraphicsWidget::sizeHint(Qt::SizeHint which, const QSizeF & /* constraint */) const
+{
+ switch (which) {
+ case Qt::MinimumSize:
+ return QSizeF(32,32);
+ case Qt::PreferredSize:
+ return QSizeF(160,90);
+ case Qt::MaximumSize:
+ return QSizeF(1000,1000);
+ default:
+ return QSizeF(300, 300);
+ }
+}
+
+static bool compareSets(const QSet<QGraphicsLayoutItem*> &actual, const QSet<QGraphicsLayoutItem*> &expected)
+{
+ if (actual != expected) {
+ qDebug() << "actual:" << actual << "expected:" << expected;
+ return false;
+ }
+ return true;
+}
+
+class CustomLayout : public QGraphicsLayout
+{
+public :
+CustomLayout(QGraphicsLayoutItem *parent)
+ : QGraphicsLayout(parent)
+{
+}
+
+
+~CustomLayout()
+{
+}
+
+int count() const
+{
+ return items.count();
+}
+
+QGraphicsLayoutItem* itemAt(int index) const
+{
+ return items.at(index);
+}
+
+
+void removeAt(int index)
+{
+ items.removeAt(index);
+}
+
+void addItem(QGraphicsLayoutItem *item)
+{
+ insertItem(items.count(), item);
+}
+
+void insertItem(int index, QGraphicsLayoutItem *item)
+{
+ index = qBound(0, index, items.count());
+
+ item->setParentLayoutItem(this);
+
+ QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
+ updateParentWidget(widget);
+
+
+ if (index == items.count()) {
+ items.append(item);
+ } else {
+ items.insert(index, item);
+ }
+
+ updateGeometry();
+ activate();
+}
+
+void updateParentWidget(QGraphicsWidget *item)
+{
+ QGraphicsLayoutItem *parentItem = parentLayoutItem();
+ while (parentItem && parentItem->isLayout()) {
+ parentItem = parentItem->parentLayoutItem();
+ }
+
+ if (parentItem) {
+ item->setParentItem(static_cast<QGraphicsWidget*>(parentItem));
+ }
+}
+
+QSizeF sizeHint(Qt::SizeHint /* which */, const QSizeF & /* constraint */) const
+{
+ return QSizeF(50,50);
+}
+
+QList<QGraphicsLayoutItem*> items;
+
+};
+
+void tst_QGraphicsLayout::ownership()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ {
+ QGraphicsLinearLayout *lay = new QGraphicsLinearLayout;
+ QSet<QGraphicsLayoutItem*> destructedSet;
+ CustomLayoutItem *li1 = new CustomLayoutItem(&destructedSet);
+ lay->addItem(li1);
+ CustomLayoutItem *li2 = new CustomLayoutItem(&destructedSet);
+ lay->addItem(li2);
+ CustomLayoutItem *li3 = new CustomLayoutItem(&destructedSet);
+ lay->addItem(li3);
+ destructedSet.clear();
+
+ delete lay;
+ QSet<QGraphicsLayoutItem*> expected;
+ expected << li1 << li2 << li3;
+ QVERIFY(compareSets(destructedSet, expected));
+ }
+
+ {
+ QGraphicsWidget *window = new QGraphicsWidget;
+ QGraphicsLinearLayout *lay = new QGraphicsLinearLayout;
+ QSet<QGraphicsLayoutItem*> destructedSet;
+ CustomGraphicsWidget *li1 = new CustomGraphicsWidget(&destructedSet);
+ lay->addItem(li1);
+ CustomGraphicsWidget *li2 = new CustomGraphicsWidget(&destructedSet);
+ lay->addItem(li2);
+ CustomGraphicsWidget *li3 = new CustomGraphicsWidget(&destructedSet);
+ lay->addItem(li3);
+ window->setLayout(lay);
+ scene.addItem(window);
+
+ destructedSet.clear();
+ window->setLayout(0);
+ QVERIFY(destructedSet.count() == 0);
+ delete window;
+ }
+
+ {
+ QGraphicsWidget *window = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsLinearLayout *lay = new QGraphicsLinearLayout;
+
+ CustomGraphicsWidget *li1 = new CustomGraphicsWidget;
+ lay->addItem(li1);
+
+ QGraphicsLinearLayout *li2 = new QGraphicsLinearLayout;
+ CustomGraphicsWidget *li2_1 = new CustomGraphicsWidget;
+ li2->addItem(li2_1);
+ CustomGraphicsWidget *li2_2 = new CustomGraphicsWidget;
+ li2->addItem(li2_2);
+ CustomGraphicsWidget *li2_3 = new CustomGraphicsWidget;
+ li2->addItem(li2_3);
+ lay->addItem(li2);
+
+ CustomGraphicsWidget *li3 = new CustomGraphicsWidget;
+ lay->addItem(li3);
+
+ window->setLayout(lay);
+ scene.addItem(window);
+ view.resize(500, 200);
+ view.show();
+
+ for (int i = li2->count(); i > 0; --i) {
+ QCOMPARE(li2->count(), i);
+ delete li2->itemAt(0);
+ }
+
+ for (int i = lay->count(); i > 0; --i) {
+ QCOMPARE(lay->count(), i);
+ delete lay->itemAt(0);
+ }
+
+ delete window;
+ }
+
+ {
+ QGraphicsWidget *top = new QGraphicsWidget;
+ QGraphicsWidget *w = new QGraphicsWidget;
+ QGraphicsWidget *w2 = new QGraphicsWidget;
+ CustomLayout *layout = new CustomLayout(top);
+ layout->addItem(w);
+ layout->addItem(w2);
+ top->setLayout(layout);
+ delete top;
+ //don't crash after that.
+ }
+}
+
+QTEST_MAIN(tst_QGraphicsLayout)
+#include "tst_qgraphicslayout.moc"
diff --git a/tests/auto/widgets/graphicsview/qgraphicslayoutitem/.gitignore b/tests/auto/widgets/graphicsview/qgraphicslayoutitem/.gitignore
new file mode 100644
index 0000000000..55a8d18acb
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicslayoutitem/.gitignore
@@ -0,0 +1 @@
+tst_qgraphicslayoutitem
diff --git a/tests/auto/widgets/graphicsview/qgraphicslayoutitem/qgraphicslayoutitem.pro b/tests/auto/widgets/graphicsview/qgraphicslayoutitem/qgraphicslayoutitem.pro
new file mode 100644
index 0000000000..ed9adf87fd
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicslayoutitem/qgraphicslayoutitem.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qgraphicslayoutitem.cpp
+CONFIG += parallel_test
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicslayoutitem/tst_qgraphicslayoutitem.cpp b/tests/auto/widgets/graphicsview/qgraphicslayoutitem/tst_qgraphicslayoutitem.cpp
new file mode 100644
index 0000000000..a8b6c0854e
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicslayoutitem/tst_qgraphicslayoutitem.cpp
@@ -0,0 +1,376 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.1, 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qgraphicslayoutitem.h>
+#include <float.h>
+#include <limits.h>
+
+class tst_QGraphicsLayoutItem : public QObject {
+Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void qgraphicslayoutitem();
+
+ void contentsRect();
+ void effectiveSizeHint_data();
+ void effectiveSizeHint();
+ void getContentsMargins();
+ void isLayout_data();
+ void isLayout();
+ void maximumSize();
+ void minimumSize();
+ void parentLayoutItem_data();
+ void parentLayoutItem();
+ void preferredSize();
+ void setMaximumSize_data();
+ void setMaximumSize();
+ void setMinimumSize_data();
+ void setMinimumSize();
+ void setPreferredSize_data();
+ void setPreferredSize();
+ void setSizePolicy_data();
+ void setPreferredSize2();
+ void setSizePolicy();
+};
+
+// Subclass that exposes the protected functions.
+class SubQGraphicsLayoutItem : public QGraphicsLayoutItem {
+public:
+ SubQGraphicsLayoutItem(QGraphicsLayoutItem *par = 0, bool layout = false)
+ : QGraphicsLayoutItem(par, layout), updateGeometryCalled(0)
+ {}
+
+ // QGraphicsLayoutItem::geometry is a pure virtual function
+ QRectF geometry() const
+ { return QRectF(); }
+
+ // QGraphicsLayoutItem::setGeometry is a pure virtual function
+ void setGeometry(QRectF const& rect)
+ { Q_UNUSED(rect); }
+
+ // QGraphicsLayoutItem::sizeHint is a pure virtual function
+ QSizeF sizeHint(Qt::SizeHint which, QSizeF const& constraint = QSizeF()) const
+ { Q_UNUSED(which); Q_UNUSED(constraint); return QSizeF(); }
+
+ void updateGeometry()
+ { updateGeometryCalled++; QGraphicsLayoutItem::updateGeometry(); }
+ int updateGeometryCalled;
+
+};
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_QGraphicsLayoutItem::initTestCase()
+{
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_QGraphicsLayoutItem::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_QGraphicsLayoutItem::init()
+{
+}
+
+// This will be called after every test function.
+void tst_QGraphicsLayoutItem::cleanup()
+{
+}
+
+void tst_QGraphicsLayoutItem::qgraphicslayoutitem()
+{
+ SubQGraphicsLayoutItem layoutItem;
+ layoutItem.contentsRect();
+ layoutItem.effectiveSizeHint(Qt::MinimumSize);
+ layoutItem.geometry();
+ QCOMPARE(layoutItem.isLayout(), false);
+ layoutItem.maximumSize();
+ layoutItem.minimumSize();
+ QCOMPARE(layoutItem.parentLayoutItem(), (QGraphicsLayoutItem*)0);
+ layoutItem.preferredSize();
+ layoutItem.sizePolicy();
+ layoutItem.sizeHint(Qt::MinimumSize);
+}
+
+// QRectF contentsRect() const public
+void tst_QGraphicsLayoutItem::contentsRect()
+{
+ SubQGraphicsLayoutItem layoutItem;
+ QRectF f = layoutItem.contentsRect();
+ QCOMPARE(f, QRectF(QPoint(), QSizeF(0, 0)));
+}
+Q_DECLARE_METATYPE(Qt::SizeHint)
+void tst_QGraphicsLayoutItem::effectiveSizeHint_data()
+{
+ QTest::addColumn<Qt::SizeHint>("sizeHint");
+ QTest::addColumn<QSizeF>("constraint");
+ for (int i = 0; i < 15; ++i) {
+ QTestData &data = QTest::newRow(QString("%1").arg(i).toLatin1());
+ switch(i % 5) {
+ case 0: data << Qt::MinimumSize; break;
+ case 1: data << Qt::PreferredSize; break;
+ case 2: data << Qt::MaximumSize; break;
+ case 3: data << Qt::MinimumDescent; break;
+ case 4: data << Qt::NSizeHints; break;
+ }
+ switch(i % 3) {
+ case 0: data << QSizeF(-1, -1); break;
+ case 1: data << QSizeF(0, 0); break;
+ case 2: data << QSizeF(10, 10); break;
+ }
+ }
+}
+
+// QSizeF effectiveSizeHint(Qt::SizeHint which, QSizeF const& constraint = QSize()) const public
+void tst_QGraphicsLayoutItem::effectiveSizeHint()
+{
+ QFETCH(Qt::SizeHint, sizeHint);
+ QFETCH(QSizeF, constraint);
+ SubQGraphicsLayoutItem layoutItem;
+ QSizeF r = layoutItem.effectiveSizeHint(sizeHint, constraint);
+ if (constraint.width() != -1)
+ QCOMPARE(r.width(), constraint.width());
+ if (constraint.height() != -1)
+ QCOMPARE(r.height(), constraint.height());
+}
+
+// void getContentsMargins(qreal* left, qreal* top, qreal* right, qreal* bottom) const public
+void tst_QGraphicsLayoutItem::getContentsMargins()
+{
+ SubQGraphicsLayoutItem layoutItem;
+ qreal left;
+ qreal top;
+ qreal right;
+ qreal bottom;
+ layoutItem.getContentsMargins(&left, &top, &right, &bottom);
+ QCOMPARE(left, (qreal)0);
+ QCOMPARE(top, (qreal)0);
+ QCOMPARE(right, (qreal)0);
+ QCOMPARE(bottom, (qreal)0);
+}
+
+void tst_QGraphicsLayoutItem::isLayout_data()
+{
+ QTest::addColumn<bool>("isLayout");
+ QTest::newRow("no") << false;
+ QTest::newRow("yes") << true;
+}
+
+// bool isLayout() const public
+void tst_QGraphicsLayoutItem::isLayout()
+{
+ QFETCH(bool, isLayout);
+ SubQGraphicsLayoutItem layoutItem(0, isLayout);
+ QCOMPARE(layoutItem.isLayout(), isLayout);
+}
+
+// QSizeF maximumSize() const public
+void tst_QGraphicsLayoutItem::maximumSize()
+{
+ SubQGraphicsLayoutItem layoutItem;
+ QCOMPARE(layoutItem.maximumSize(), QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
+ // layoutItem.effectiveSizeHint(Qt::MaximumSize);
+}
+
+// QSizeF minimumSize() const public
+void tst_QGraphicsLayoutItem::minimumSize()
+{
+ SubQGraphicsLayoutItem layoutItem;
+ QCOMPARE(layoutItem.minimumSize(), QSizeF(0, 0));
+ // layoutItem.effectiveSizeHint(Qt::MinimumSize);
+}
+
+void tst_QGraphicsLayoutItem::parentLayoutItem_data()
+{
+ QTest::addColumn<bool>("parent");
+ QTest::newRow("no") << false;
+ QTest::newRow("yes") << true;
+}
+
+// QGraphicsLayoutItem* parentLayoutItem() const public
+void tst_QGraphicsLayoutItem::parentLayoutItem()
+{
+ QFETCH(bool, parent);
+ SubQGraphicsLayoutItem parentLayout;
+ SubQGraphicsLayoutItem layoutItem(parent ? &parentLayout : 0);
+ QCOMPARE(layoutItem.parentLayoutItem(), static_cast<QGraphicsLayoutItem*>( parent ? &parentLayout : 0));
+}
+
+// QSizeF preferredSize() const public
+void tst_QGraphicsLayoutItem::preferredSize()
+{
+ SubQGraphicsLayoutItem layoutItem;
+ QCOMPARE(layoutItem.preferredSize(), QSizeF(0, 0));
+ // layoutItem.effectiveSizeHint(Qt::PreferredSize));
+}
+
+void tst_QGraphicsLayoutItem::setMaximumSize_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::addColumn<QSizeF>("outputSize");
+ QTest::newRow("-1") << QSizeF(-1, -1) << QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
+ QTest::newRow("0") << QSizeF(0, 0) << QSizeF(0, 0);
+ QTest::newRow("10") << QSizeF(10, 10) << QSizeF(10, 10);
+}
+
+// void setMaximumSize(QSizeF const& size) public
+void tst_QGraphicsLayoutItem::setMaximumSize()
+{
+ QFETCH(QSizeF, size);
+ QFETCH(QSizeF, outputSize);
+ SubQGraphicsLayoutItem layoutItem;
+ QSizeF oldSize = layoutItem.maximumSize();
+ layoutItem.setMaximumSize(size);
+ if (size.isValid())
+ QCOMPARE(layoutItem.updateGeometryCalled, (oldSize == size) ? 0 : 1);
+ else
+ QVERIFY(!layoutItem.updateGeometryCalled);
+ layoutItem.setMinimumSize(1, 1);
+
+ QVERIFY(layoutItem.maximumSize().width() <= outputSize.width());
+ QVERIFY(layoutItem.maximumSize().height() <= outputSize.height());
+ QVERIFY(layoutItem.minimumSize().width() <= outputSize.width());
+ QVERIFY(layoutItem.minimumSize().height() <= outputSize.height());
+ QVERIFY(layoutItem.preferredSize().width() <= outputSize.width());
+ QVERIFY(layoutItem.preferredSize().height() <= outputSize.height());
+}
+
+void tst_QGraphicsLayoutItem::setMinimumSize_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::addColumn<QSizeF>("outputSize");
+ QTest::newRow("-1") << QSizeF(-1, -1) << QSizeF(0, 0);
+ QTest::newRow("0") << QSizeF(0, 0) << QSizeF(0, 0);
+ QTest::newRow("10") << QSizeF(10, 10) << QSizeF(10, 10);
+}
+
+// void setMinimumSize(QSizeF const& size) public
+void tst_QGraphicsLayoutItem::setMinimumSize()
+{
+ QFETCH(QSizeF, size);
+ QFETCH(QSizeF, outputSize);
+ SubQGraphicsLayoutItem layoutItem;
+ QSizeF oldSize = layoutItem.minimumSize();
+
+ layoutItem.setMinimumSize(size);
+ if (size.isValid()) {
+ QEXPECT_FAIL("0", "updateGeometry() is called when it doesn't have to be.", Continue);
+ QCOMPARE(layoutItem.updateGeometryCalled, (oldSize == size) ? 0 : 1);
+ } else {
+ QVERIFY(!layoutItem.updateGeometryCalled);
+ }
+ layoutItem.setMaximumSize(5, 5);
+ QEXPECT_FAIL("10", "layoutItem.maximumSize().width() < size.width()", Abort);
+ QVERIFY(layoutItem.maximumSize().width() >= size.width());
+ QVERIFY(layoutItem.maximumSize().height() >= size.height());
+ QVERIFY(layoutItem.minimumSize().width() >= size.width());
+ QVERIFY(layoutItem.minimumSize().height() >= size.height());
+ QVERIFY(layoutItem.preferredSize().width() >= size.width());
+ QVERIFY(layoutItem.preferredSize().height() >= size.height());
+}
+
+void tst_QGraphicsLayoutItem::setPreferredSize_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::newRow("-1") << QSizeF(-1, -1);
+ QTest::newRow("0") << QSizeF(0, 0);
+ QTest::newRow("10") << QSizeF(10, 10);
+}
+
+// void setPreferredSize(QSizeF const& size) public
+void tst_QGraphicsLayoutItem::setPreferredSize()
+{
+ QFETCH(QSizeF, size);
+ SubQGraphicsLayoutItem layoutItem;
+ QSizeF oldSize = layoutItem.preferredSize();
+ layoutItem.setPreferredSize(size);
+ if (size.isValid())
+ QCOMPARE(layoutItem.preferredSize(), size);
+
+ if (size.isValid()) {
+ QEXPECT_FAIL("0", "updateGeometry() is called when it doesn't have to be.", Continue);
+ QCOMPARE(layoutItem.updateGeometryCalled, (oldSize == size) ? 0 : 1);
+ } else {
+ QVERIFY(!layoutItem.updateGeometryCalled);
+ }
+}
+
+void tst_QGraphicsLayoutItem::setPreferredSize2()
+{
+ SubQGraphicsLayoutItem layoutItem;
+ layoutItem.setPreferredSize(QSizeF(30, -1));
+ QCOMPARE(layoutItem.preferredWidth(), qreal(30));
+}
+
+void tst_QGraphicsLayoutItem::setSizePolicy_data()
+{
+ QTest::addColumn<QSizePolicy>("policy");
+ QTest::newRow("default") << QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed, QSizePolicy::DefaultType);
+ QTest::newRow("rand") << QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
+}
+
+// void setSizePolicy(QSizePolicy const& policy) public
+void tst_QGraphicsLayoutItem::setSizePolicy()
+{
+ QFETCH(QSizePolicy, policy);
+ SubQGraphicsLayoutItem layoutItem;
+ QSizePolicy defaultPolicy(QSizePolicy::Preferred, QSizePolicy::Preferred, QSizePolicy::DefaultType);
+ QCOMPARE(layoutItem.sizePolicy(), defaultPolicy);
+
+ layoutItem.setSizePolicy(policy);
+ QCOMPARE(layoutItem.sizePolicy(), policy);
+ QCOMPARE(layoutItem.updateGeometryCalled, (defaultPolicy == policy) ? 0 : 1);
+}
+
+QTEST_MAIN(tst_QGraphicsLayoutItem)
+#include "tst_qgraphicslayoutitem.moc"
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicslinearlayout/.gitignore b/tests/auto/widgets/graphicsview/qgraphicslinearlayout/.gitignore
new file mode 100644
index 0000000000..95c7dac979
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicslinearlayout/.gitignore
@@ -0,0 +1 @@
+tst_qgraphicslinearlayout
diff --git a/tests/auto/widgets/graphicsview/qgraphicslinearlayout/qgraphicslinearlayout.pro b/tests/auto/widgets/graphicsview/qgraphicslinearlayout/qgraphicslinearlayout.pro
new file mode 100644
index 0000000000..1f7ff0cc6e
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicslinearlayout/qgraphicslinearlayout.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qgraphicslinearlayout.cpp
+CONFIG += parallel_test
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp b/tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp
new file mode 100644
index 0000000000..873a711127
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicslinearlayout/tst_qgraphicslinearlayout.cpp
@@ -0,0 +1,1650 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.1, 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qgraphicslinearlayout.h>
+#include <qgraphicsproxywidget.h>
+#include <qgraphicswidget.h>
+#include <qgraphicsscene.h>
+#include <qgraphicsview.h>
+#include <qapplication.h>
+#include <qplastiquestyle.h>
+
+class tst_QGraphicsLinearLayout : public QObject {
+Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void qgraphicslinearlayout_data();
+ void qgraphicslinearlayout();
+
+ void alignment_data();
+ void alignment();
+ void count_data();
+ void count();
+ void dump_data();
+ void dump();
+ void geometry_data();
+ void geometry();
+ void insertItem_data();
+ void insertItem();
+ void insertStretch_data();
+ void insertStretch();
+ void invalidate_data();
+ void invalidate();
+ void itemAt_data();
+ void itemAt();
+ void itemAt_visualOrder();
+ void orientation_data();
+ void orientation();
+ void removeAt_data();
+ void removeAt();
+ void removeItem_data();
+ void removeItem();
+ void setGeometry_data();
+ void setGeometry();
+ void setSpacing_data();
+ void setSpacing();
+ void setItemSpacing_data();
+ void setItemSpacing();
+ void itemSpacing();
+ void setStretchFactor_data();
+ void setStretchFactor();
+ void testStretch();
+ void defaultStretchFactors_data();
+ void defaultStretchFactors();
+ void sizeHint_data();
+ void sizeHint();
+ void updateGeometry();
+ void layoutDirection();
+ void removeLayout();
+ void avoidRecursionInInsertItem();
+ void styleInfoLeak();
+ void testAlignmentInLargerLayout();
+ void testOffByOneInLargerLayout();
+ void testDefaultAlignment();
+ void combineSizePolicies();
+
+ // Task specific tests
+ void task218400_insertStretchCrash();
+};
+
+// Subclass that exposes the protected functions.
+class SubQGraphicsLinearLayout : public QGraphicsLinearLayout {
+public:
+ SubQGraphicsLinearLayout(Qt::Orientation orientation = Qt::Horizontal) : QGraphicsLinearLayout(orientation),
+ graphicsSceneResize(0),
+ layoutRequest(0),
+ layoutDirectionChange(0)
+ { }
+
+ void widgetEvent(QEvent *e)
+ {
+ switch (e->type()) {
+ case QEvent::GraphicsSceneResize:
+ graphicsSceneResize++;
+ break;
+ case QEvent::LayoutRequest:
+ layoutRequest++;
+ break;
+ case QEvent::LayoutDirectionChange:
+ layoutDirectionChange++;
+ break;
+ default:
+ break;
+ }
+
+ QGraphicsLinearLayout::widgetEvent(e);
+ }
+
+ int graphicsSceneResize;
+ int layoutRequest;
+ int layoutDirectionChange;
+};
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_QGraphicsLinearLayout::initTestCase()
+{
+ // since the style will influence the results, we have to ensure
+ // that the tests are run using the same style on all platforms
+#if defined (Q_WS_WINCE)
+ QApplication::setStyle(new QWindowsStyle);
+#else
+ QApplication::setStyle(new QPlastiqueStyle);
+#endif
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_QGraphicsLinearLayout::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_QGraphicsLinearLayout::init()
+{
+}
+
+// This will be called after every test function.
+void tst_QGraphicsLinearLayout::cleanup()
+{
+}
+
+class RectWidget : public QGraphicsWidget
+{
+public:
+ RectWidget(QGraphicsItem *parent = 0, const QBrush &brush = QBrush()) : QGraphicsWidget(parent){ m_brush = brush;}
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+ painter->setBrush(m_brush);
+ painter->drawRoundRect(rect());
+ }
+
+ void setSizeHint(Qt::SizeHint which, const QSizeF &size) {
+ m_sizeHints[which] = size;
+ updateGeometry();
+ }
+
+ virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const {
+ if (m_sizeHints[which].isValid()) {
+ return m_sizeHints[which];
+ }
+ return QGraphicsWidget::sizeHint(which, constraint);
+ }
+
+ QSizeF m_sizeHints[Qt::NSizeHints];
+ QBrush m_brush;
+};
+
+
+Q_DECLARE_METATYPE(Qt::Orientation)
+void tst_QGraphicsLinearLayout::qgraphicslinearlayout_data()
+{
+ QTest::addColumn<Qt::Orientation>("orientation");
+ QTest::newRow("vertical") << Qt::Vertical;
+ QTest::newRow("horizontal") << Qt::Horizontal;
+}
+
+void tst_QGraphicsLinearLayout::qgraphicslinearlayout()
+{
+ QFETCH(Qt::Orientation, orientation);
+ SubQGraphicsLinearLayout layout(orientation);
+ QVERIFY(layout.isLayout());
+
+ qApp->processEvents();
+ QCOMPARE(layout.graphicsSceneResize, 0);
+ QCOMPARE(layout.layoutRequest, 0);
+ QCOMPARE(layout.layoutDirectionChange, 0);
+
+ layout.setOrientation(Qt::Vertical);
+ layout.orientation();
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsLinearLayout::insertItem: cannot insert null item");
+ QCOMPARE(layout.count(), 0);
+ layout.addItem(0);
+ QCOMPARE(layout.count(), 0);
+ layout.addStretch(0);
+ QCOMPARE(layout.count(), 0);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsLinearLayout::insertItem: cannot insert null item");
+ layout.insertItem(0, 0);
+ layout.insertStretch(0, 0);
+ layout.removeItem(0);
+ QCOMPARE(layout.count(), 0);
+ layout.setSpacing(0);
+ layout.spacing();
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsLinearLayout::setStretchFactor: cannot assign a stretch factor to a null item");
+ layout.setStretchFactor(0, 0);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsLinearLayout::setStretchFactor: cannot return a stretch factor for a null item");
+ layout.stretchFactor(0);
+ layout.setAlignment(0, Qt::AlignHCenter);
+ QCOMPARE(layout.alignment(0), 0);
+ layout.setGeometry(QRectF());
+ layout.geometry();
+ QCOMPARE(layout.count(), 0);
+ layout.invalidate();
+ layout.sizeHint(Qt::MinimumSize, QSizeF());
+}
+
+Q_DECLARE_METATYPE(Qt::AlignmentFlag)
+void tst_QGraphicsLinearLayout::alignment_data()
+{
+ QTest::addColumn<Qt::Orientation>("orientation");
+ QTest::addColumn<QSize>("newSize");
+ QTest::newRow("h-defaultsize") << Qt::Horizontal << QSize();
+ QTest::newRow("v-defaultsize") << Qt::Vertical << QSize();
+ QTest::newRow("h-300") << Qt::Horizontal << QSize(300,100);
+ QTest::newRow("v-300") << Qt::Vertical << QSize(100, 300);
+}
+
+void tst_QGraphicsLinearLayout::alignment()
+{
+ QFETCH(Qt::Orientation, orientation);
+ QFETCH(QSize, newSize);
+
+ //if (alignment == Qt::AlignAbsolute)
+ // QApplication::setLayoutDirection(Qt::RightToLeft);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.setSceneRect(0, 0, 320, 240);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ SubQGraphicsLinearLayout &layout = *(new SubQGraphicsLinearLayout(orientation));
+ scene.addItem(widget);
+ widget->setLayout(&layout);
+
+ static const Qt::Alignment alignmentsToTest[] = {
+ (Qt::Alignment)0,
+ Qt::AlignLeft,
+ Qt::AlignRight,
+ Qt::AlignHCenter,
+ Qt::AlignTop,
+ Qt::AlignBottom,
+ Qt::AlignVCenter,
+ Qt::AlignCenter,
+ (Qt::Alignment)0,
+ Qt::AlignLeft,
+ Qt::AlignRight,
+ Qt::AlignHCenter,
+ Qt::AlignTop,
+ Qt::AlignBottom,
+ Qt::AlignVCenter,
+ Qt::AlignCenter
+ };
+
+ int i;
+ bool addWidget = true;
+ for (size_t i = 0; i < sizeof(alignmentsToTest)/sizeof(Qt::Alignment); ++i) {
+ QGraphicsLayoutItem *loutItem;
+ Qt::Alignment align = alignmentsToTest[i];
+ if (!align && i > 0)
+ addWidget = false;
+ if (addWidget)
+ loutItem = new RectWidget(widget, QBrush(Qt::blue));
+ else {
+ SubQGraphicsLinearLayout *lay = new SubQGraphicsLinearLayout(Qt::Vertical);
+ lay->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred, QSizePolicy::DefaultType);
+ lay->setContentsMargins(0,0,0,0);
+ QGraphicsWidget *w = new RectWidget(widget, QBrush(Qt::red));
+ if (align) {
+ w->setMinimumSize(QSizeF(10,10));
+ w->setMaximumSize(QSizeF(10,10));
+ } else {
+ w->setMinimumSize(QSizeF(50,50));
+ w->setMaximumSize(QSizeF(50,50));
+ }
+ lay->addItem(w);
+ loutItem = lay;
+ }
+ if (align) {
+ loutItem->setMinimumSize(QSizeF(10,10));
+ loutItem->setMaximumSize(QSizeF(10,10));
+ } else {
+ loutItem->setMinimumSize(QSizeF(50,50));
+ loutItem->setMaximumSize(QSizeF(50,50));
+ }
+ layout.addItem(loutItem);
+ layout.setAlignment(loutItem, align);
+
+ }
+ layout.setContentsMargins(0,0,0,0);
+ int spacing = 1;
+ layout.setSpacing(spacing);
+ if (newSize.isValid())
+ widget->resize(newSize);
+ view.show();
+ widget->show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
+
+ int x = 0;
+ int y = 0;
+ for (i = 0; i < layout.count(); ++i) {
+ QGraphicsLayoutItem *item = layout.itemAt(i);
+ Qt::Alignment align = layout.alignment(item);
+
+ int w = 10;
+ int h = 10;
+ switch(align) {
+ case Qt::AlignLeft:
+ break;
+ case Qt::AlignRight:
+ if (orientation == Qt::Vertical)
+ x += 40;
+ break;
+ case Qt::AlignHCenter:
+ if (orientation == Qt::Vertical)
+ x += 20;
+ break;
+ case Qt::AlignTop:
+ break;
+ case Qt::AlignBottom:
+ if (orientation == Qt::Horizontal)
+ y += 40;
+ break;
+ case Qt::AlignVCenter:
+ if (orientation == Qt::Horizontal)
+ y += 20;
+ break;
+ case Qt::AlignCenter:
+ if (orientation == Qt::Horizontal)
+ y += 20;
+ else
+ x += 20;
+ break;
+ case 0:
+ w = 50;
+ h = 50;
+ break;
+ default:
+ break;
+ }
+ QRectF expectedGeometry(x, y, w, h);
+ QCOMPARE(item->geometry(), expectedGeometry);
+ if (orientation == Qt::Horizontal) {
+ x += w;
+ y = 0;
+ x += spacing;
+ } else {
+ x = 0;
+ y += h;
+ y += spacing;
+ }
+ }
+}
+
+void tst_QGraphicsLinearLayout::count_data()
+{
+ QTest::addColumn<int>("itemCount");
+ QTest::addColumn<int>("layoutCount");
+ QTest::newRow("0, 0") << 0 << 0;
+ QTest::newRow("0, 5") << 0 << 5;
+ QTest::newRow("5, 0") << 5 << 0;
+ QTest::newRow("5, 5") << 5 << 5;
+}
+
+// int count() const public
+void tst_QGraphicsLinearLayout::count()
+{
+ QFETCH(int, itemCount);
+ QFETCH(int, layoutCount);
+
+ SubQGraphicsLinearLayout layout;
+ QCOMPARE(layout.count(), 0);
+
+ for (int i = 0; i < itemCount; ++i)
+ layout.addItem(new QGraphicsWidget);
+ QCOMPARE(layout.count(), itemCount);
+
+ for (int i = 0; i < layoutCount; ++i)
+ layout.addItem(new SubQGraphicsLinearLayout);
+ QCOMPARE(layout.count(), itemCount + layoutCount);
+
+ // see also removeAt()
+}
+
+void tst_QGraphicsLinearLayout::dump_data()
+{
+ QTest::addColumn<int>("itemCount");
+ QTest::addColumn<int>("layoutCount");
+ for (int i = -1; i < 3; ++i) {
+ QTest::newRow(QString("%1, 0, 0").arg(i).toLatin1()) << 0 << 0;
+ QTest::newRow(QString("%1, 0, 5").arg(i).toLatin1()) << 5 << 5;
+ QTest::newRow(QString("%1, 5, 0").arg(i).toLatin1()) << 5 << 5;
+ QTest::newRow(QString("%1, 5, 5").arg(i).toLatin1()) << 5 << 5;
+ }
+}
+
+// void dump(int indent = 0) const public
+void tst_QGraphicsLinearLayout::dump()
+{
+ QFETCH(int, itemCount);
+ QFETCH(int, layoutCount);
+ SubQGraphicsLinearLayout layout;
+ for (int i = 0; i < itemCount; ++i)
+ layout.addItem(new QGraphicsWidget);
+ for (int i = 0; i < layoutCount; ++i)
+ layout.addItem(new SubQGraphicsLinearLayout);
+}
+
+void tst_QGraphicsLinearLayout::geometry_data()
+{
+ QTest::addColumn<int>("itemCount");
+ QTest::addColumn<int>("layoutCount");
+ QTest::addColumn<int>("itemSpacing");
+ QTest::addColumn<int>("spacing");
+ QTest::addColumn<Qt::Orientation>("orientation");
+ QTest::addColumn<QRectF>("rect");
+
+ QTest::newRow("null") << 0 << 0 << 0 << 0 << Qt::Horizontal << QRectF();
+
+ QTest::newRow("one item") << 1 << 0 << 0 << 0 << Qt::Horizontal << QRectF(0, 0, 10, 10);
+ QTest::newRow("one layout") << 0 << 1 << 0 << 0 << Qt::Horizontal << QRectF(0, 0, 10, 10);
+ QTest::newRow("two h") << 1 << 1 << 0 << 0 << Qt::Horizontal << QRectF(0, 0, 20, 10);
+ QTest::newRow("two v") << 1 << 1 << 0 << 0 << Qt::Vertical << QRectF(0, 0, 10, 20);
+
+ QTest::newRow("two w/itemspacing") << 1 << 1 << 5 << 0 << Qt::Horizontal << QRectF(0, 0, 25, 10);
+ QTest::newRow("two w/spacing") << 1 << 1 << 8 << 0 << Qt::Horizontal << QRectF(0, 0, 28, 10);
+
+ QTest::newRow("two w/itemspacing v") << 1 << 1 << 5 << 0 << Qt::Vertical << QRectF(0, 0, 10, 25);
+ QTest::newRow("two w/spacing v") << 1 << 1 << 8 << 0 << Qt::Vertical << QRectF(0, 0, 10, 28);
+}
+
+// QRectF geometry() const public
+void tst_QGraphicsLinearLayout::geometry()
+{
+ QFETCH(int, itemCount);
+ QFETCH(int, layoutCount);
+ QFETCH(int, itemSpacing);
+ QFETCH(int, spacing);
+ QFETCH(Qt::Orientation, orientation);
+ QFETCH(QRectF, rect);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ SubQGraphicsLinearLayout &layout = *(new SubQGraphicsLinearLayout(orientation));
+ scene.addItem(widget);
+ widget->setLayout(&layout);
+ widget->setContentsMargins(0, 0, 0, 0);
+ for (int i = 0; i < itemCount; ++i)
+ layout.addItem(new QGraphicsWidget);
+ for (int i = 0; i < layoutCount; ++i)
+ layout.addItem(new SubQGraphicsLinearLayout);
+
+ for (int i = 0; i < layout.count(); ++i) {
+ QGraphicsLayoutItem *item = layout.itemAt(i);
+ item->setMaximumSize(10, 10);
+ item->setMinimumSize(10, 10);
+ }
+ layout.setItemSpacing(0, itemSpacing);
+ layout.setSpacing(spacing);
+ layout.setContentsMargins(0, 0, 0, 0);
+
+ widget->show();
+ view.show();
+ QApplication::processEvents();
+ QCOMPARE(layout.geometry(), rect);
+ delete widget;
+}
+
+void tst_QGraphicsLinearLayout::insertItem_data()
+{
+ QTest::addColumn<int>("itemCount");
+ QTest::addColumn<int>("layoutCount");
+ QTest::addColumn<int>("insertItemAt");
+ QTest::addColumn<bool>("isWidget");
+ for (int i = -1; i < 4; ++i) {
+ for (int j = 0; j < 2; ++j) {
+ QTest::newRow(QString("0, 0, %1 %2").arg(i).arg(j).toLatin1()) << 0 << 0 << i << (bool)j;
+ QTest::newRow(QString("1, 0, %1 %2").arg(i).arg(j).toLatin1()) << 1 << 0 << i << (bool)j;
+ QTest::newRow(QString("0, 1, %1 %2").arg(i).arg(j).toLatin1()) << 0 << 1 << i << (bool)j;
+ QTest::newRow(QString("2, 2, %1 %2").arg(i).arg(j).toLatin1()) << 2 << 2 << i << (bool)j;
+ }
+ }
+}
+
+// void insertItem(int index, QGraphicsLayoutItem* item) public
+void tst_QGraphicsLinearLayout::insertItem()
+{
+ QFETCH(int, itemCount);
+ QFETCH(int, layoutCount);
+ QFETCH(int, insertItemAt);
+ QFETCH(bool, isWidget);
+ if (insertItemAt > layoutCount + itemCount)
+ return;
+
+ SubQGraphicsLinearLayout layout;
+ for (int i = 0; i < itemCount; ++i)
+ layout.addItem(new QGraphicsWidget);
+ for (int i = 0; i < layoutCount; ++i)
+ layout.addItem(new SubQGraphicsLinearLayout);
+
+ QGraphicsLayoutItem *item = 0;
+ if (isWidget)
+ item = new QGraphicsWidget;
+ else
+ item = new SubQGraphicsLinearLayout;
+
+ QSizeF oldSizeHint = layout.sizeHint(Qt::PreferredSize, QSizeF());
+ layout.insertItem(insertItemAt, item);
+ QCOMPARE(layout.count(), itemCount + layoutCount + 1);
+
+ if (insertItemAt >= 0 && (itemCount + layoutCount >= 0)) {
+ QCOMPARE(layout.itemAt(insertItemAt), item);
+ }
+
+ layout.activate();
+ QSizeF newSizeHint = layout.sizeHint(Qt::PreferredSize, QSizeF());
+ if (!isWidget && layout.count() == 1)
+ QCOMPARE(oldSizeHint.width(), newSizeHint.width());
+ else if (itemCount + layoutCount > 0)
+ QVERIFY(oldSizeHint.width() < newSizeHint.width());
+}
+
+void tst_QGraphicsLinearLayout::insertStretch_data()
+{
+ QTest::addColumn<int>("itemCount");
+ QTest::addColumn<int>("layoutCount");
+ QTest::addColumn<int>("insertItemAt");
+ QTest::addColumn<int>("stretch");
+ for (int i = -1; i < 4; ++i) {
+ for (int j = 0; j < 2; ++j) {
+ QTest::newRow(QString("0, 0, %1 %2").arg(i).arg(j).toLatin1()) << 0 << 0 << i << j;
+ QTest::newRow(QString("1, 0, %1 %2").arg(i).arg(j).toLatin1()) << 1 << 0 << i << j;
+ QTest::newRow(QString("0, 1, %1 %2").arg(i).arg(j).toLatin1()) << 0 << 1 << i << j;
+ QTest::newRow(QString("2, 2, %1 %2").arg(i).arg(j).toLatin1()) << 2 << 2 << i << j;
+ }
+ }
+}
+
+// void insertStretch(int index, int stretch = 1) public
+void tst_QGraphicsLinearLayout::insertStretch()
+{
+ QFETCH(int, itemCount);
+ QFETCH(int, layoutCount);
+ QFETCH(int, insertItemAt);
+ QFETCH(int, stretch);
+ if (insertItemAt > layoutCount + itemCount)
+ return;
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ SubQGraphicsLinearLayout *layout = new SubQGraphicsLinearLayout;
+ scene.addItem(widget);
+
+ QList<QGraphicsWidget *>items;
+ QGraphicsWidget *item = 0;
+ for (int i = 0; i < itemCount; ++i) {
+ item = new RectWidget;
+ item->setMinimumSize(10, 10);
+ item->setPreferredSize(25, 25);
+ item->setMaximumSize(50, 50);
+ layout->addItem(item);
+ }
+ for (int i = 0; i < layoutCount; ++i) {
+ item = new RectWidget;
+ item->setMinimumSize(10, 10);
+ item->setPreferredSize(25, 25);
+ item->setMaximumSize(50, 50);
+ SubQGraphicsLinearLayout *sublayout = new SubQGraphicsLinearLayout;
+ sublayout->addItem(item);
+ layout->addItem(sublayout);
+ }
+ widget->setLayout(layout);
+ layout->insertStretch(insertItemAt, stretch);
+ QCOMPARE(layout->count(), itemCount + layoutCount);
+
+ layout->activate();
+ view.show();
+ widget->show();
+
+ int prevStretch = -2;
+ int prevWidth = -2;
+ widget->resize((layoutCount + itemCount) * 25 + 25, 25);
+ for (int i = 0; i < layout->count(); ++i) {
+ if (QGraphicsLayoutItem *item = layout->itemAt(i)) {
+ if (prevStretch != -2) {
+ if (layout->stretchFactor(item) >= prevStretch) {
+ QVERIFY(item->geometry().width() >= prevWidth);
+ } else {
+ QVERIFY(item->geometry().width() < prevWidth);
+ }
+ }
+ prevStretch = layout->stretchFactor(item);
+ prevWidth = (int)(item->geometry().width());
+ }
+ }
+
+ //QTest::qWait(1000);
+ delete widget;
+}
+
+void tst_QGraphicsLinearLayout::invalidate_data()
+{
+ QTest::addColumn<int>("count");
+ QTest::newRow("0") << 0;
+ QTest::newRow("1") << 1;
+ QTest::newRow("2") << 2;
+ QTest::newRow("3") << 3;
+}
+
+// void invalidate() public
+void tst_QGraphicsLinearLayout::invalidate()
+{
+ QFETCH(int, count);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ SubQGraphicsLinearLayout &layout = *(new SubQGraphicsLinearLayout);
+ scene.addItem(widget);
+ widget->setLayout(&layout);
+ widget->setContentsMargins(0, 0, 0, 0);
+ layout.setContentsMargins(0, 0, 0, 0);
+ view.show();
+ widget->show();
+ //QTest::qWait(1000);
+ QTest::qWaitForWindowShown(&view);
+ qApp->processEvents();
+ layout.layoutRequest = 0;
+
+ layout.setContentsMargins(1, 2, 3, 4);
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(layout.layoutRequest, 1);
+
+ layout.setOrientation(Qt::Vertical);
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(layout.layoutRequest, 2);
+
+ for (int i = 0; i < count; ++i)
+ layout.invalidate(); // Event is compressed, should only get one layoutrequest
+ QApplication::sendPostedEvents(0, 0);
+ QCOMPARE(layout.layoutRequest, count ? 3 : 2);
+ delete widget;
+}
+
+void tst_QGraphicsLinearLayout::itemAt_data()
+{
+ QTest::addColumn<int>("index");
+ QTest::newRow("0") << 0;
+ QTest::newRow("1") << 1;
+ QTest::newRow("2") << 2;
+}
+
+// QGraphicsLayoutItem* itemAt(int index) const public
+void tst_QGraphicsLinearLayout::itemAt()
+{
+ // see also the insertItem() etc tests
+ QFETCH(int, index);
+ SubQGraphicsLinearLayout layout;
+ for (int i = 0; i < 3; ++i)
+ layout.addItem(new QGraphicsWidget);
+
+ QVERIFY(layout.itemAt(index) != 0);
+}
+
+void tst_QGraphicsLinearLayout::itemAt_visualOrder()
+{
+ QGraphicsLinearLayout *l = new QGraphicsLinearLayout;
+
+ QGraphicsWidget *w1 = new QGraphicsWidget;
+ l->addItem(w1);
+
+ QGraphicsWidget *w3 = new QGraphicsWidget;
+ l->addItem(w3);
+
+ QGraphicsWidget *w0 = new QGraphicsWidget;
+ l->insertItem(0, w0);
+
+ QGraphicsWidget *w2 = new QGraphicsWidget;
+ l->insertItem(2, w2);
+
+ QCOMPARE(l->itemAt(0), static_cast<QGraphicsLayoutItem*>(w0));
+ QCOMPARE(l->itemAt(1), static_cast<QGraphicsLayoutItem*>(w1));
+ QCOMPARE(l->itemAt(2), static_cast<QGraphicsLayoutItem*>(w2));
+ QCOMPARE(l->itemAt(3), static_cast<QGraphicsLayoutItem*>(w3));
+}
+
+void tst_QGraphicsLinearLayout::orientation_data()
+{
+ QTest::addColumn<Qt::Orientation>("orientation");
+ QTest::newRow("vertical") << Qt::Vertical;
+ QTest::newRow("horizontal") << Qt::Horizontal;
+}
+
+// Qt::Orientation orientation() const public
+void tst_QGraphicsLinearLayout::orientation()
+{
+ QFETCH(Qt::Orientation, orientation);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ Qt::Orientation initialOrientation = (orientation == Qt::Vertical ? Qt::Horizontal : Qt::Vertical);
+ SubQGraphicsLinearLayout &layout = *(new SubQGraphicsLinearLayout(initialOrientation));
+ scene.addItem(widget);
+ widget->setLayout(&layout);
+ widget->setContentsMargins(0, 0, 0, 0);
+ layout.setContentsMargins(0, 0, 0, 0);
+ int i;
+ int itemCount = 3;
+ for (i = 0; i < itemCount; ++i)
+ layout.addItem(new RectWidget);
+ QCOMPARE(layout.orientation(), initialOrientation);
+ QList<qreal> positions;
+
+ view.show();
+ widget->show();
+ qApp->processEvents();
+
+ for (i = 0; i < itemCount; ++i) {
+ QGraphicsWidget *item = static_cast<QGraphicsWidget*>(layout.itemAt(i));
+ qreal pos;
+ if (initialOrientation == Qt::Horizontal)
+ pos = item->pos().x();
+ else
+ pos = item->pos().y();
+ positions.append(pos);
+
+ }
+
+ layout.setOrientation(orientation);
+ QCOMPARE(layout.orientation(), orientation);
+ // important to resize to preferredsize when orientation is switched
+ widget->resize(widget->effectiveSizeHint(Qt::PreferredSize));
+ qApp->processEvents();
+ for (i = 0; i < positions.count(); ++i) {
+ QGraphicsWidget *item = static_cast<QGraphicsWidget*>(layout.itemAt(i));
+ if (initialOrientation == Qt::Horizontal)
+ QCOMPARE(item->pos().y(), positions.at(i));
+ else
+ QCOMPARE(item->pos().x(), positions.at(i));
+ }
+}
+
+void tst_QGraphicsLinearLayout::removeAt_data()
+{
+ QTest::addColumn<int>("itemCount");
+ QTest::addColumn<int>("layoutCount");
+ QTest::addColumn<int>("removeItemAt");
+ QTest::addColumn<Qt::Orientation>("orientation");
+ for (int i = -1; i < 4; ++i) {
+ for (int k = 0; k < 2; ++k) {
+ Qt::Orientation orientation = (k == 0) ? Qt::Vertical : Qt::Horizontal;
+ QTest::newRow(QString("0, 0, %1").arg(i).toLatin1()) << 0 << 0 << i << orientation;
+ QTest::newRow(QString("1, 0, %1").arg(i).toLatin1()) << 1 << 0 << i << orientation;
+ QTest::newRow(QString("0, 1, %1").arg(i).toLatin1()) << 0 << 1 << i << orientation;
+ QTest::newRow(QString("2, 2, %1").arg(i).toLatin1()) << 2 << 2 << i << orientation;
+ }
+ }
+}
+
+// void removeAt(int index) public
+void tst_QGraphicsLinearLayout::removeAt()
+{
+ QFETCH(int, itemCount);
+ QFETCH(int, layoutCount);
+ QFETCH(int, removeItemAt);
+ QFETCH(Qt::Orientation, orientation);
+ if (removeItemAt >= layoutCount + itemCount)
+ return;
+
+ SubQGraphicsLinearLayout layout(orientation);
+ for (int i = 0; i < itemCount; ++i)
+ layout.addItem(new QGraphicsWidget);
+ for (int i = 0; i < layoutCount; ++i)
+ layout.addItem(new SubQGraphicsLinearLayout);
+ QSizeF oldSizeHint = layout.sizeHint(Qt::PreferredSize, QSizeF());
+
+ QGraphicsLayoutItem *w = 0;
+ if (removeItemAt >= 0 && removeItemAt < layout.count())
+ w = layout.itemAt(removeItemAt);
+ if (w) {
+ QGraphicsLayoutItem *wParent = w->parentLayoutItem();
+ QCOMPARE(wParent, static_cast<QGraphicsLayoutItem *>(&layout));
+ layout.removeAt(removeItemAt);
+ wParent = w->parentLayoutItem();
+ QCOMPARE(wParent, static_cast<QGraphicsLayoutItem *>(0));
+ delete w;
+ }
+ QCOMPARE(layout.count(), itemCount + layoutCount - (w ? 1 : 0));
+
+ layout.activate();
+ QSizeF newSizeHint = layout.sizeHint(Qt::PreferredSize, QSizeF());
+ if (orientation == Qt::Horizontal)
+ QVERIFY(oldSizeHint.width() >= newSizeHint.width());
+ else
+ QVERIFY(oldSizeHint.height() >= newSizeHint.height());
+}
+
+void tst_QGraphicsLinearLayout::removeItem_data()
+{
+ QTest::addColumn<int>("itemCount");
+ QTest::addColumn<int>("layoutCount");
+ QTest::addColumn<int>("removeItemAt");
+ for (int i = -1; i < 4; ++i) {
+ QTest::newRow(QString("0, 0, %1").arg(i).toLatin1()) << 0 << 0 << i;
+ QTest::newRow(QString("1, 0, %1").arg(i).toLatin1()) << 1 << 0 << i;
+ QTest::newRow(QString("0, 1, %1").arg(i).toLatin1()) << 0 << 1 << i;
+ QTest::newRow(QString("2, 2, %1").arg(i).toLatin1()) << 2 << 2 << i;
+ }
+}
+
+// void removeItem(QGraphicsLayoutItem* item) public
+void tst_QGraphicsLinearLayout::removeItem()
+{
+ QFETCH(int, itemCount);
+ QFETCH(int, layoutCount);
+ QFETCH(int, removeItemAt);
+ if (removeItemAt >= layoutCount + itemCount)
+ return;
+
+ SubQGraphicsLinearLayout layout;
+ for (int i = 0; i < itemCount; ++i)
+ layout.addItem(new QGraphicsWidget);
+ for (int i = 0; i < layoutCount; ++i)
+ layout.addItem(new SubQGraphicsLinearLayout);
+
+ QGraphicsLayoutItem *w = 0;
+ if (removeItemAt >= 0 && removeItemAt < layout.count())
+ w = layout.itemAt(removeItemAt);
+ QSizeF oldSizeHint = layout.sizeHint(Qt::PreferredSize, QSizeF());
+ if (w) {
+ layout.removeItem(w);
+ delete w;
+ }
+ QCOMPARE(layout.count(), itemCount + layoutCount - (w ? 1 : 0));
+
+ layout.activate();
+ QSizeF newSizeHint = layout.sizeHint(Qt::PreferredSize, QSizeF());
+ QVERIFY(oldSizeHint.width() >= newSizeHint.width());
+}
+
+void tst_QGraphicsLinearLayout::setGeometry_data()
+{
+ QTest::addColumn<QRectF>("rect");
+ QTest::newRow("null") << QRectF();
+ QTest::newRow("small") << QRectF(0, 0, 10, 10);
+}
+
+// void setGeometry(QRectF const& rect) public
+void tst_QGraphicsLinearLayout::setGeometry()
+{
+ QFETCH(QRectF, rect);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ SubQGraphicsLinearLayout &layout = *(new SubQGraphicsLinearLayout);
+ scene.addItem(widget);
+ widget->setLayout(&layout);
+ widget->setContentsMargins(0, 0, 0, 0);
+ layout.setContentsMargins(0, 0, 0, 0);
+ layout.setMaximumSize(100, 100);
+ view.show();
+ widget->show();
+ QApplication::processEvents();
+ widget->setGeometry(rect);
+ QCOMPARE(layout.geometry(), rect);
+ // see also geometry()
+ delete widget;
+}
+
+void tst_QGraphicsLinearLayout::setSpacing_data()
+{
+ QTest::addColumn<qreal>("spacing");
+ QTest::newRow("0") << (qreal)0;
+ QTest::newRow("5") << (qreal)5;
+ QTest::newRow("3.3") << (qreal)3.3;
+ QTest::newRow("-4.3") << (qreal)4.3;
+}
+
+// void setSpacing(qreal spacing) public
+void tst_QGraphicsLinearLayout::setSpacing()
+{
+ QFETCH(qreal, spacing);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ SubQGraphicsLinearLayout &layout = *(new SubQGraphicsLinearLayout);
+ scene.addItem(widget);
+ widget->setLayout(&layout);
+ layout.setContentsMargins(0, 0, 0, 0);
+
+ qreal oldSpacing = layout.spacing();
+ if (oldSpacing != -1) {
+ for (int i = 0; i < 3; ++i)
+ layout.addItem(new QGraphicsWidget);
+ QSizeF oldSizeHint = layout.sizeHint(Qt::PreferredSize);
+
+ layout.setSpacing(spacing);
+ QCOMPARE(layout.spacing(), spacing);
+
+ view.show();
+ widget->show();
+ QApplication::processEvents();
+ QSizeF newSizeHint = layout.sizeHint(Qt::PreferredSize);
+
+ QCOMPARE(oldSizeHint.width() - oldSpacing * 2, newSizeHint.width() - spacing * 2);
+ } else {
+ QSKIP("This style uses non-uniform spacings (layoutSpacingImplementation() is reimplemented)", SkipAll);
+ }
+ delete widget;
+}
+
+void tst_QGraphicsLinearLayout::setItemSpacing_data()
+{
+ QTest::addColumn<int>("index");
+ QTest::addColumn<int>("spacing");
+
+ QTest::newRow("0 at 0") << 0 << 0;
+ QTest::newRow("10 at 0") << 0 << 10;
+ QTest::newRow("10 at 1") << 1 << 10;
+ QTest::newRow("10 at the end") << 4 << 10;
+}
+
+void tst_QGraphicsLinearLayout::setItemSpacing()
+{
+ QFETCH(int, index);
+ QFETCH(int, spacing);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ SubQGraphicsLinearLayout *layout = new SubQGraphicsLinearLayout;
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ for (int i = 0; i < 5; ++i) {
+ QGraphicsWidget *w = new QGraphicsWidget;
+ layout->addItem(w);
+ }
+ QSizeF oldSizeHint = layout->sizeHint(Qt::PreferredSize);
+ qreal oldSpacing = 0;
+ if (index < layout->count() - 1)
+ oldSpacing = layout->spacing();
+ else
+ spacing = 0;
+
+ layout->setItemSpacing(index, spacing);
+ view.show();
+ QApplication::processEvents();
+ QSizeF newSizeHint = layout->sizeHint(Qt::PreferredSize);
+ if (oldSpacing >= 0) {
+ QCOMPARE(newSizeHint.width() - spacing, oldSizeHint.width() - oldSpacing);
+ } else {
+ QSKIP("This style uses non-uniform spacings (layoutSpacingImplementation() is reimplemented)", SkipAll);
+ }
+ delete widget;
+}
+
+void tst_QGraphicsLinearLayout::itemSpacing()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ SubQGraphicsLinearLayout *layout = new SubQGraphicsLinearLayout;
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ for (int i = 0; i < 5; ++i) {
+ QGraphicsWidget *w = new QGraphicsWidget;
+ layout->addItem(w);
+ }
+
+ // Check defaults
+ qreal defaultSpacing = layout->spacing();
+ if (defaultSpacing >= 0) {
+ QCOMPARE(layout->itemSpacing(0), defaultSpacing);
+ } else {
+ // all widgets are the same, so the spacing should be uniform
+ QCOMPARE(layout->itemSpacing(0), layout->itemSpacing(1));
+ }
+
+ layout->setItemSpacing(1, 42);
+ QCOMPARE(layout->itemSpacing(1), qreal(42));
+
+ // try to unset
+ layout->setItemSpacing(1, -1);
+ QCOMPARE(layout->itemSpacing(1), defaultSpacing);
+
+ delete widget;
+}
+
+/**
+ * The stretch factors are not applied linearly, but they are used together with both the preferred size, maximum size to form the
+ * internal effective stretch factor.
+ * There is only need to apply stretch factors if the size of the layout is different than the layouts preferred size.
+ * (If the size of the layout is the preferred size, then all items should get their preferred sizes.
+ * However, imagine this use case:
+ * Layout
+ * +----------+----------+----------+
+ * name | A | B | C |
+ * stretch | 1 | 2 | 3 |
+ * sizehints|[5,10,50] |[5,10,50] |[5,10,50] |
+ * +----------+----------+----------+
+ *
+ * layout->resize(120, h)
+ *
+ * In QLayout, C would become 50, B would become 50 and A would get 20. When scaling a layout this would give a jerky feeling, since
+ * the item with the highest stretch factor will first resize. When that has reached its maximum the next candidate for stretch will
+ * resize, and finally, item with the lowest stretch factor will resize.
+ * In QGraphicsLinearLayout we try to scale all items so that they all reach their maximum at the same time. This means that
+ * their relative sizes are not proportional to their stretch factors.
+ */
+
+typedef QList<int> IntList;
+Q_DECLARE_METATYPE(IntList)
+Q_DECLARE_METATYPE(qreal)
+
+void tst_QGraphicsLinearLayout::setStretchFactor_data()
+{
+ QTest::addColumn<qreal>("totalSize");
+ QTest::addColumn<IntList>("stretches");
+
+ QTest::newRow(QString("60 [1,2]").toLatin1()) << qreal(60.0) << (IntList() << 1 << 2);
+ QTest::newRow(QString("60 [1,2,3]").toLatin1()) << qreal(60.0) << (IntList() << 1 << 2 << 3);
+ QTest::newRow(QString("120 [1,2,3,6]").toLatin1()) << qreal(120.0) << (IntList() << 1 << 2 << 3 << 6);
+}
+
+// void setStretchFactor(QGraphicsLayoutItem* item, int stretch) public
+void tst_QGraphicsLinearLayout::setStretchFactor()
+{
+ QFETCH(qreal, totalSize);
+ QFETCH(IntList, stretches);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ SubQGraphicsLinearLayout &layout = *(new SubQGraphicsLinearLayout);
+ scene.addItem(widget);
+ widget->setLayout(&layout);
+ layout.setContentsMargins(0, 0, 0, 0);
+ layout.setSpacing(0.0);
+ widget->setContentsMargins(0, 0, 0, 0);
+
+
+ int i;
+ for (i = 0; i < stretches.count(); ++i) {
+ QGraphicsWidget *item = new RectWidget(widget);
+ item->setMinimumSize(5,5);
+ item->setPreferredSize(10,5);
+ item->setMaximumSize(50,5);
+ layout.addItem(item);
+ layout.setStretchFactor(item, stretches.at(i));
+ }
+
+ widget->resize(totalSize, 10);
+ QApplication::processEvents();
+
+ view.show();
+ widget->show();
+
+ qreal firstStretch = -1;
+ qreal firstExtent = -1.;
+ qreal sumExtent = 0;
+ for (i = 0; i < stretches.count(); ++i) {
+ QGraphicsWidget *item = static_cast<QGraphicsWidget*>(layout.itemAt(i));
+ qreal extent = item->size().width();
+ qreal stretch = (qreal)stretches.at(i);
+ if (firstStretch != -1 && firstExtent != -1) {
+ // The resulting widths does not correspond linearly to the stretch factors.
+ if (stretch == firstStretch)
+ QCOMPARE(extent, firstExtent);
+ else if (stretch > firstStretch)
+ QVERIFY(extent > firstExtent);
+ else
+ QVERIFY(extent < firstExtent);
+ } else {
+ firstStretch = (qreal)stretch;
+ firstExtent = extent;
+ }
+ sumExtent+= extent;
+ }
+ QCOMPARE(sumExtent, totalSize);
+
+ delete widget;
+}
+
+void tst_QGraphicsLinearLayout::testStretch()
+{
+ QGraphicsScene scene;
+ QGraphicsView *view = new QGraphicsView(&scene);
+ Q_UNUSED(view);
+ QGraphicsWidget *form = new QGraphicsWidget(0, Qt::Window);
+
+ scene.addItem(form);
+ form->setMinimumSize(600, 600);
+ form->setMaximumSize(600, 600);
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Horizontal, form);
+ QGraphicsWidget *w1 = new RectWidget;
+ w1->setPreferredSize(100,100);
+ w1->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ QGraphicsWidget *w2 = new RectWidget;
+ w2->setPreferredSize(200,200);
+ w2->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ layout->setSpacing(0);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->addItem(w1);
+ layout->addStretch(2);
+ layout->addItem(w2);
+ QCOMPARE(layout->count(), 2);
+ QVERIFY(layout->itemAt(0) == w1);
+ QVERIFY(layout->itemAt(1) == w2);
+ layout->activate();
+
+ //view->setSceneRect(-50, -50, 800, 800);
+ //view->show();
+ //QTest::qWaitForWindowShown(view);
+ //QTest::qWait(5000);
+ QCOMPARE(form->geometry().size(), QSizeF(600,600));
+ QCOMPARE(w1->geometry(), QRectF(0, 0, 100, 100));
+ QCOMPARE(w2->geometry(), QRectF(400, 0, 200, 200));
+}
+
+void tst_QGraphicsLinearLayout::defaultStretchFactors_data()
+{
+ QTest::addColumn<Qt::Orientation>("orientation");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<IntList>("preferredSizeHints");
+ QTest::addColumn<IntList>("stretches");
+ QTest::addColumn<IntList>("ignoreFlag");
+ QTest::addColumn<QSizeF>("newSize");
+ QTest::addColumn<IntList>("expectedSizes");
+
+ QTest::newRow("hor") << Qt::Horizontal << 3
+ << (IntList() << 20 << 40 << 60)
+ << (IntList())
+ << (IntList())
+ << QSizeF()
+ << (IntList() << 20 << 40 << 60);
+
+ QTest::newRow("ver") << Qt::Vertical << 3
+ << (IntList() << 20 << 40 << 60)
+ << (IntList())
+ << (IntList())
+ << QSizeF()
+ << (IntList() << 20 << 40 << 60);
+
+ QTest::newRow("hor,ignore123") << Qt::Horizontal << 3
+ << (IntList() << 20 << 40 << 60)
+ << (IntList())
+ << (IntList() << 1 << 1 << 1)
+ << QSizeF()
+ << (IntList() << 0 << 0 << 0);
+
+ QTest::newRow("hor,ignore23") << Qt::Horizontal << 3
+ << (IntList() << 10 << 10 << 10)
+ << (IntList())
+ << (IntList() << 0 << 1 << 1)
+ << QSizeF(200, 50)
+ << (IntList()); //### stretches are not linear.
+
+ QTest::newRow("hor,ignore2") << Qt::Horizontal << 3
+ << (IntList() << 10 << 10 << 10)
+ << (IntList())
+ << (IntList() << 0 << 1 << 0)
+ << QSizeF()
+ << (IntList() << 10 << 0 << 10);
+
+}
+
+void tst_QGraphicsLinearLayout::defaultStretchFactors()
+{
+ QFETCH(Qt::Orientation, orientation);
+ QFETCH(int, count);
+ QFETCH(IntList, preferredSizeHints);
+ QFETCH(IntList, stretches);
+ QFETCH(IntList, ignoreFlag);
+ QFETCH(QSizeF, newSize);
+ QFETCH(IntList, expectedSizes);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ SubQGraphicsLinearLayout *layout = new SubQGraphicsLinearLayout(orientation);
+ scene.addItem(widget);
+ widget->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0.0);
+ widget->setContentsMargins(0, 0, 0, 0);
+
+ int i;
+ for (i = 0; i < count; ++i) {
+ RectWidget *item = new RectWidget(widget);
+ layout->addItem(item);
+ if (preferredSizeHints.value(i, -1) >= 0) {
+ item->setSizeHint(Qt::PreferredSize, QSizeF(preferredSizeHints.at(i), preferredSizeHints.at(i)));
+ }
+ if (stretches.value(i, -1) >= 0) {
+ layout->setStretchFactor(item, stretches.at(i));
+ }
+ if (ignoreFlag.value(i, 0) != 0) {
+ QSizePolicy sp = item->sizePolicy();
+ if (orientation == Qt::Horizontal)
+ sp.setHorizontalPolicy(QSizePolicy::Policy(sp.horizontalPolicy() | QSizePolicy::IgnoreFlag));
+ else
+ sp.setVerticalPolicy(QSizePolicy::Policy(sp.verticalPolicy() | QSizePolicy::IgnoreFlag));
+ item->setSizePolicy(sp);
+ }
+ }
+
+ QApplication::processEvents();
+
+ widget->show();
+ view.show();
+ view.resize(400,300);
+ if (newSize.isValid())
+ widget->resize(newSize);
+
+ QApplication::processEvents();
+ for (i = 0; i < count; ++i) {
+ QSizeF itemSize = layout->itemAt(i)->geometry().size();
+ if (orientation == Qt::Vertical)
+ itemSize.transpose();
+ if (i < expectedSizes.count())
+ QCOMPARE(itemSize.width(), qreal(expectedSizes.at(i)));
+ }
+
+ delete widget;
+}
+
+Q_DECLARE_METATYPE(Qt::SizeHint)
+void tst_QGraphicsLinearLayout::sizeHint_data()
+{
+ QTest::addColumn<Qt::SizeHint>("which");
+ QTest::addColumn<QSizeF>("constraint");
+ QTest::addColumn<qreal>("spacing");
+ QTest::addColumn<qreal>("layoutMargin");
+ QTest::addColumn<QSizeF>("sizeHint");
+
+ QTest::newRow("minimumSize") << Qt::MinimumSize << QSizeF() << qreal(0.0) << qreal(0.0) << QSizeF(30, 10);
+ QTest::newRow("preferredSize") << Qt::PreferredSize << QSizeF() << qreal(0.0) << qreal(0.0) << QSizeF(75, 25);
+ QTest::newRow("maximumSize") << Qt::MaximumSize << QSizeF() << qreal(0.0) << qreal(0.0) << QSizeF(150, 50);
+ QTest::newRow("minimumSize, spacing=3") << Qt::MinimumSize << QSizeF() << qreal(3.0) << qreal(0.0) << QSizeF(30 + 2*3, 10);
+ QTest::newRow("minimumSize, spacing=3, layoutMargin=10") << Qt::MinimumSize << QSizeF() << qreal(3.0) << qreal(10.0) << QSizeF(30 + 2*3 + 2*10, 10 + 2*10);
+ QTest::newRow("minimumSize, spacing=0, layoutMargin=7") << Qt::MinimumSize << QSizeF() << qreal(0.0) << qreal(7.0) << QSizeF(30 + 0 + 2*7, 10 + 2*7);
+}
+
+// QSizeF sizeHint(Qt::SizeHint which, QSizeF const& constraint) const public
+void tst_QGraphicsLinearLayout::sizeHint()
+{
+ QFETCH(Qt::SizeHint, which);
+ QFETCH(QSizeF, constraint);
+ QFETCH(qreal, spacing);
+ QFETCH(qreal, layoutMargin);
+ QFETCH(QSizeF, sizeHint);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Window);
+ SubQGraphicsLinearLayout &layout = *(new SubQGraphicsLinearLayout);
+ scene.addItem(widget);
+ widget->setLayout(&layout);
+ layout.setContentsMargins(layoutMargin, layoutMargin, layoutMargin, layoutMargin);
+ layout.setSpacing(spacing);
+ for (int i = 0; i < 3; ++i) {
+ QGraphicsWidget *item = new QGraphicsWidget(widget);
+ item->setMinimumSize(10, 10);
+ item->setPreferredSize(25, 25);
+ item->setMaximumSize(50, 50);
+ layout.addItem(item);
+ }
+ QApplication::processEvents();
+ QCOMPARE(layout.sizeHint(which, constraint), sizeHint);
+ delete widget;
+}
+
+void tst_QGraphicsLinearLayout::updateGeometry()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ QGraphicsWidget *window = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsWidget *w1 = new QGraphicsWidget(window);
+ w1->setMinimumSize(100, 40);
+ SubQGraphicsLinearLayout *layout = new SubQGraphicsLinearLayout;
+ layout->addItem(w1);
+ scene.addItem(window);
+ window->setLayout(layout);
+ layout->setContentsMargins(0, 0, 0, 0);
+ QCOMPARE(w1->parentLayoutItem(), static_cast<QGraphicsLayoutItem*>(layout));
+ QCOMPARE(layout->parentLayoutItem(), static_cast<QGraphicsLayoutItem*>(window));
+
+ view.show();
+ QApplication::processEvents();
+ QCOMPARE(window->size().toSize(), QSize(100, 50));
+ w1->setMinimumSize(110, 60);
+ QApplication::processEvents();
+ QCOMPARE(window->size().toSize(), QSize(110, 60));
+ QApplication::processEvents();
+
+ {
+ delete window;
+ window = new QGraphicsWidget(0, Qt::Window);
+ SubQGraphicsLinearLayout *layout2a = new SubQGraphicsLinearLayout;
+ QGraphicsWidget *w1 = new QGraphicsWidget(window);
+ w1->setMinimumSize(110, 50);
+ layout2a->addItem(w1);
+ SubQGraphicsLinearLayout *layout2 = new SubQGraphicsLinearLayout;
+ layout2->addItem(layout2a);
+ layout2->setContentsMargins(1, 1, 1, 1);
+ layout2a->setContentsMargins(1, 1, 1, 1);
+ window->setLayout(layout2);
+ QApplication::processEvents();
+ QCOMPARE(w1->parentLayoutItem(), static_cast<QGraphicsLayoutItem*>(layout2a));
+ QCOMPARE(layout2a->parentLayoutItem(), static_cast<QGraphicsLayoutItem*>(layout2));
+ QCOMPARE(layout2->parentLayoutItem(), static_cast<QGraphicsLayoutItem*>(window));
+ QCOMPARE(window->size().toSize(), QSize(114, 54));
+ QApplication::processEvents();
+ w1->setMinimumSize(120, 60);
+ QApplication::processEvents();
+ QCOMPARE(window->size().toSize(), QSize(124, 64));
+ }
+
+ {
+ delete window;
+ window = new QGraphicsWidget(0, Qt::Window);
+ scene.addItem(window);
+ window->show();
+ QGraphicsWidget *w1 = new QGraphicsWidget(window);
+ w1->setMinimumSize(100, 50);
+ SubQGraphicsLinearLayout *layout2a = new SubQGraphicsLinearLayout;
+ layout2a->addItem(w1);
+ SubQGraphicsLinearLayout *layout2 = new SubQGraphicsLinearLayout;
+ layout2->addItem(layout2a);
+ layout2a->setContentsMargins(1, 1, 1, 1);
+ window->setLayout(layout2);
+ QApplication::processEvents();
+ qreal left, top, right, bottom;
+ layout2->getContentsMargins(&left, &top, &right, &bottom);
+ QCOMPARE(window->size().toSize(), QSize(102 +left + right, 52 + top + bottom));
+ }
+
+ {
+ delete window;
+ window = new QGraphicsWidget(0, Qt::Window);
+ scene.addItem(window);
+ QGraphicsWidget *w1 = new QGraphicsWidget(window);
+ w1->setMinimumSize(100, 50);
+ window->setLayout(0);
+ SubQGraphicsLinearLayout *layout2a = new SubQGraphicsLinearLayout;
+ layout2a->addItem(w1);
+ SubQGraphicsLinearLayout *layout2 = new SubQGraphicsLinearLayout;
+ layout2->addItem(layout2a);
+ window->resize(200, 80);
+ window->setLayout(layout2);
+ window->show();
+ QApplication::processEvents();
+ QCOMPARE(window->size().toSize(), QSize(200, 80));
+ }
+
+}
+
+void tst_QGraphicsLinearLayout::layoutDirection()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ QGraphicsWidget *window = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout;
+ layout->setContentsMargins(1, 2, 3, 4);
+ layout->setSpacing(6);
+
+ RectWidget *w1 = new RectWidget;
+ w1->setPreferredSize(20, 20);
+ w1->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ layout->addItem(w1);
+ RectWidget *w2 = new RectWidget;
+ w2->setPreferredSize(20, 20);
+ w2->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ layout->addItem(w2);
+
+ scene.addItem(window);
+ window->setLayout(layout);
+ view.show();
+ window->resize(50, 20);
+ window->setLayoutDirection(Qt::LeftToRight);
+ QApplication::processEvents();
+ QCOMPARE(w1->geometry().left(), 1.0);
+ QCOMPARE(w1->geometry().right(), 21.0);
+ QCOMPARE(w2->geometry().left(), 27.0);
+ QCOMPARE(w2->geometry().right(), 47.0);
+
+ window->setLayoutDirection(Qt::RightToLeft);
+ QApplication::processEvents();
+ QCOMPARE(w1->geometry().right(), 49.0);
+ QCOMPARE(w1->geometry().left(), 29.0);
+ QCOMPARE(w2->geometry().right(), 23.0);
+ QCOMPARE(w2->geometry().left(), 3.0);
+
+ delete window;
+}
+
+void tst_QGraphicsLinearLayout::removeLayout()
+{
+ QGraphicsScene scene;
+ RectWidget *textEdit = new RectWidget;
+ RectWidget *pushButton = new RectWidget;
+ scene.addItem(textEdit);
+ scene.addItem(pushButton);
+
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout;
+ layout->addItem(textEdit);
+ layout->addItem(pushButton);
+
+ QGraphicsWidget *form = new QGraphicsWidget;
+ form->setLayout(layout);
+ scene.addItem(form);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWait(20);
+
+ QRectF r1 = textEdit->geometry();
+ QRectF r2 = pushButton->geometry();
+ form->setLayout(0);
+ //documentation of QGraphicsWidget::setLayout:
+ //If layout is 0, the widget is left without a layout. Existing subwidgets' geometries will remain unaffected.
+ QCOMPARE(textEdit->geometry(), r1);
+ QCOMPARE(pushButton->geometry(), r2);
+}
+
+void tst_QGraphicsLinearLayout::avoidRecursionInInsertItem()
+{
+ QGraphicsWidget window(0, Qt::Window);
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(&window);
+ QCOMPARE(layout->count(), 0);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsLinearLayout::insertItem: cannot insert itself");
+ layout->insertItem(0, layout);
+ QCOMPARE(layout->count(), 0);
+}
+
+void tst_QGraphicsLinearLayout::styleInfoLeak()
+{
+ QGraphicsLinearLayout layout;
+ layout.spacing();
+}
+
+void tst_QGraphicsLinearLayout::task218400_insertStretchCrash()
+{
+ QGraphicsScene *scene = new QGraphicsScene;
+ QGraphicsWidget *a = scene->addWidget(new QWidget);
+ QGraphicsWidget *b = scene->addWidget(new QWidget);
+
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout;
+ layout->addItem(a);
+ layout->addItem(b);
+ layout->insertStretch(0); // inserts gap in item grid in the layout engine
+
+ QGraphicsWidget *form = new QGraphicsWidget;
+ form->setLayout(layout); // crash
+}
+
+void tst_QGraphicsLinearLayout::testAlignmentInLargerLayout()
+{
+ QGraphicsScene *scene = new QGraphicsScene;
+ QGraphicsWidget *form = new QGraphicsWidget;
+ scene->addItem(form);
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical, form);
+ layout->setSpacing(0);
+ layout->setContentsMargins(0,0,0,0);
+
+ QGraphicsWidget *a = new QGraphicsWidget;
+ a->setMaximumSize(100,100);
+ layout->addItem(a);
+
+ QCOMPARE(form->maximumSize(), QSizeF(100,100));
+ QCOMPARE(layout->maximumSize(), QSizeF(100,100));
+ layout->setMinimumSize(QSizeF(200,200));
+ layout->setMaximumSize(QSizeF(200,200));
+
+ layout->setAlignment(a, Qt::AlignCenter);
+ layout->activate();
+ QCOMPARE(a->geometry(), QRectF(50,50,100,100));
+
+ layout->setAlignment(a, Qt::AlignRight | Qt::AlignBottom);
+ layout->activate();
+ QCOMPARE(a->geometry(), QRectF(100,100,100,100));
+
+ layout->setAlignment(a, Qt::AlignHCenter | Qt::AlignTop);
+ layout->activate();
+ QCOMPARE(a->geometry(), QRectF(50,0,100,100));
+
+ QGraphicsWidget *b = new QGraphicsWidget;
+ b->setMaximumSize(100,100);
+ layout->addItem(b);
+
+ layout->setAlignment(a, Qt::AlignCenter);
+ layout->setAlignment(b, Qt::AlignCenter);
+ layout->activate();
+ QCOMPARE(a->geometry(), QRectF(50,0,100,100));
+ QCOMPARE(b->geometry(), QRectF(50,100,100,100));
+
+ layout->setAlignment(a, Qt::AlignRight | Qt::AlignBottom);
+ layout->setAlignment(b, Qt::AlignLeft | Qt::AlignTop);
+ layout->activate();
+ QCOMPARE(a->geometry(), QRectF(100,0,100,100));
+ QCOMPARE(b->geometry(), QRectF(0,100,100,100));
+}
+
+void tst_QGraphicsLinearLayout::testOffByOneInLargerLayout() {
+ QGraphicsScene *scene = new QGraphicsScene;
+ QGraphicsWidget *form = new QGraphicsWidget;
+ scene->addItem(form);
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical, form);
+ layout->setSpacing(0);
+ layout->setContentsMargins(0,0,0,0);
+
+ QGraphicsWidget *a = new QGraphicsWidget;
+ QGraphicsWidget *b = new QGraphicsWidget;
+ a->setMaximumSize(100,100);
+ b->setMaximumSize(100,100);
+ layout->addItem(a);
+ layout->addItem(b);
+
+ layout->setAlignment(a, Qt::AlignRight | Qt::AlignBottom);
+ layout->setAlignment(b, Qt::AlignLeft | Qt::AlignTop);
+ layout->setMinimumSize(QSizeF(101,201));
+ layout->setMaximumSize(QSizeF(101,201));
+ layout->activate();
+ QCOMPARE(a->geometry(), QRectF(1,0.5,100,100));
+ QCOMPARE(b->geometry(), QRectF(0,100.5,100,100));
+
+ layout->setMinimumSize(QSizeF(100,200));
+ layout->setMaximumSize(QSizeF(100,200));
+ layout->activate();
+ QCOMPARE(a->geometry(), QRectF(0,0,100,100));
+ QCOMPARE(b->geometry(), QRectF(0,100,100,100));
+
+ layout->setMinimumSize(QSizeF(99,199));
+ layout->setMaximumSize(QSizeF(99,199));
+ layout->activate();
+ QCOMPARE(a->geometry(), QRectF(0,0,99,99.5));
+ QCOMPARE(b->geometry(), QRectF(0,99.5,99,99.5));
+}
+void tst_QGraphicsLinearLayout::testDefaultAlignment()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical, widget);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ QGraphicsWidget *w = new QGraphicsWidget;
+ w->setMinimumSize(50,50);
+ w->setMaximumSize(50,50);
+ layout->addItem(w);
+
+ //Default alignment should be to the top-left
+ QCOMPARE(layout->alignment(w), 0);
+
+ //First, check by forcing the layout to be bigger
+ layout->setMinimumSize(100,100);
+ layout->activate();
+ QCOMPARE(layout->geometry(), QRectF(0,0,100,100));
+ QCOMPARE(w->geometry(), QRectF(0,0,50,50));
+ layout->setMinimumSize(-1,-1);
+
+ //Second, check by adding a larger item in the column
+ QGraphicsWidget *w2 = new QGraphicsWidget;
+ w2->setMinimumSize(100,100);
+ w2->setMaximumSize(100,100);
+ layout->addItem(w2);
+ layout->activate();
+ QCOMPARE(layout->geometry(), QRectF(0,0,100,150));
+ QCOMPARE(w->geometry(), QRectF(0,0,50,50));
+ QCOMPARE(w2->geometry(), QRectF(0,50,100,100));
+}
+
+void tst_QGraphicsLinearLayout::combineSizePolicies()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Horizontal, widget);
+ layout->setContentsMargins(0, 0, 0, 0);
+ layout->setSpacing(0);
+
+ QGraphicsWidget *w1 = new QGraphicsWidget;
+ w1->setMaximumSize(200,200);
+ w1->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ layout->addItem(w1);
+
+ QGraphicsWidget *w2 = new QGraphicsWidget;
+ w2->setPreferredSize(50,50);
+ w2->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ layout->addItem(w2);
+ QCOMPARE(layout->maximumHeight(), qreal(200));
+
+ // now remove the fixed vertical size policy, and set instead the maximum height to 50
+ // this should in effect give the same maximumHeight
+ w2->setMaximumHeight(50);
+ w2->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
+ QCOMPARE(layout->maximumHeight(), qreal(200));
+}
+
+QTEST_MAIN(tst_QGraphicsLinearLayout)
+#include "tst_qgraphicslinearlayout.moc"
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicsobject/qgraphicsobject.pro b/tests/auto/widgets/graphicsview/qgraphicsobject/qgraphicsobject.pro
new file mode 100644
index 0000000000..5232ec8372
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsobject/qgraphicsobject.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+
+QT += widgets
+QT += core-private
+
+SOURCES += tst_qgraphicsobject.cpp
+CONFIG += parallel_test
diff --git a/tests/auto/widgets/graphicsview/qgraphicsobject/tst_qgraphicsobject.cpp b/tests/auto/widgets/graphicsview/qgraphicsobject/tst_qgraphicsobject.cpp
new file mode 100644
index 0000000000..85e36b74b2
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsobject/tst_qgraphicsobject.cpp
@@ -0,0 +1,297 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.1, 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qgraphicsitem.h>
+#include <qgraphicsscene.h>
+#include <qgraphicssceneevent.h>
+#include <qgraphicsview.h>
+#include <qstyleoption.h>
+#include <private/qobject_p.h>
+
+class tst_QGraphicsObject : public QObject {
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void pos();
+ void x();
+ void y();
+ void z();
+ void opacity();
+ void enabled();
+ void visible();
+ void deleted();
+};
+
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_QGraphicsObject::initTestCase()
+{
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_QGraphicsObject::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_QGraphicsObject::init()
+{
+}
+
+// This will be called after every test function.
+void tst_QGraphicsObject::cleanup()
+{
+}
+
+
+class MyGraphicsObject : public QGraphicsObject
+{
+public:
+ MyGraphicsObject() : QGraphicsObject() {}
+ virtual QRectF boundingRect() const { return QRectF(); }
+ virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) {}
+};
+
+void tst_QGraphicsObject::pos()
+{
+ MyGraphicsObject object;
+ QSignalSpy xSpy(&object, SIGNAL(xChanged()));
+ QSignalSpy ySpy(&object, SIGNAL(yChanged()));
+ QVERIFY(object.pos() == QPointF(0, 0));
+ object.setPos(10, 10);
+ QCOMPARE(xSpy.count(), 1);
+ QCOMPARE(ySpy.count(), 1);
+
+ QVERIFY(object.pos() == QPointF(10,10));
+
+ object.setPos(10, 10);
+ QCOMPARE(xSpy.count(), 1);
+ QCOMPARE(ySpy.count(), 1);
+
+ object.setProperty("pos", QPointF(0, 0));
+ QCOMPARE(xSpy.count(), 2);
+ QCOMPARE(ySpy.count(), 2);
+ QVERIFY(object.property("pos") == QPointF(0,0));
+
+ object.setProperty("pos", QPointF(10, 0));
+ QCOMPARE(xSpy.count(), 3);
+ QCOMPARE(ySpy.count(), 2);
+ QVERIFY(object.property("pos") == QPointF(10,0));
+
+ object.setProperty("pos", QPointF(10, 10));
+ QCOMPARE(xSpy.count(), 3);
+ QCOMPARE(ySpy.count(), 3);
+ QVERIFY(object.property("pos") == QPointF(10, 10));
+}
+
+void tst_QGraphicsObject::x()
+{
+ MyGraphicsObject object;
+ QSignalSpy xSpy(&object, SIGNAL(xChanged()));
+ QSignalSpy ySpy(&object, SIGNAL(yChanged()));
+ QVERIFY(object.pos() == QPointF(0, 0));
+ object.setX(10);
+ QCOMPARE(xSpy.count(), 1);
+ QCOMPARE(ySpy.count(), 0);
+
+ QVERIFY(object.pos() == QPointF(10, 0));
+ QVERIFY(object.x() == 10);
+
+ object.setX(10);
+ QCOMPARE(xSpy.count(), 1);
+ QCOMPARE(ySpy.count(), 0);
+
+ object.setProperty("x", 0);
+ QCOMPARE(xSpy.count(), 2);
+ QCOMPARE(ySpy.count(), 0);
+ QVERIFY(object.property("x") == 0);
+}
+
+void tst_QGraphicsObject::y()
+{
+ MyGraphicsObject object;
+ QSignalSpy xSpy(&object, SIGNAL(xChanged()));
+ QSignalSpy ySpy(&object, SIGNAL(yChanged()));
+ QVERIFY(object.pos() == QPointF(0, 0));
+ object.setY(10);
+ QCOMPARE(xSpy.count(), 0);
+ QCOMPARE(ySpy.count(), 1);
+
+ QVERIFY(object.pos() == QPointF(0, 10));
+ QVERIFY(object.y() == 10);
+
+ object.setY(10);
+ QCOMPARE(xSpy.count(), 0);
+ QCOMPARE(ySpy.count(), 1);
+
+ object.setProperty("y", 0);
+ QCOMPARE(xSpy.count(), 0);
+ QCOMPARE(ySpy.count(), 2);
+ QVERIFY(object.property("y") == 0);
+}
+
+void tst_QGraphicsObject::z()
+{
+ MyGraphicsObject object;
+ QSignalSpy zSpy(&object, SIGNAL(zChanged()));
+ QVERIFY(object.zValue() == 0);
+ object.setZValue(10);
+ QCOMPARE(zSpy.count(), 1);
+
+ QVERIFY(object.zValue() == 10);
+
+ object.setZValue(10);
+ QCOMPARE(zSpy.count(), 1);
+
+ object.setProperty("z", 0);
+ QCOMPARE(zSpy.count(), 2);
+ QVERIFY(object.property("z") == 0);
+}
+
+void tst_QGraphicsObject::opacity()
+{
+ MyGraphicsObject object;
+ QSignalSpy spy(&object, SIGNAL(opacityChanged()));
+ QVERIFY(object.opacity() == 1.);
+ object.setOpacity(0);
+ QCOMPARE(spy.count(), 1);
+
+ QVERIFY(object.opacity() == 0.);
+
+ object.setOpacity(0);
+ QCOMPARE(spy.count(), 1);
+
+ object.setProperty("opacity", .5);
+ QCOMPARE(spy.count(), 2);
+ QVERIFY(object.property("opacity") == .5);
+}
+
+void tst_QGraphicsObject::enabled()
+{
+ MyGraphicsObject object;
+ QSignalSpy spy(&object, SIGNAL(enabledChanged()));
+ QVERIFY(object.isEnabled() == true);
+ object.setEnabled(false);
+ QCOMPARE(spy.count(), 1);
+
+ QVERIFY(object.isEnabled() == false);
+
+ object.setEnabled(false);
+ QCOMPARE(spy.count(), 1);
+
+ object.setProperty("enabled", true);
+ QCOMPARE(spy.count(), 2);
+ QVERIFY(object.property("enabled") == true);
+}
+
+void tst_QGraphicsObject::visible()
+{
+ MyGraphicsObject object;
+ QSignalSpy spy(&object, SIGNAL(visibleChanged()));
+ QVERIFY(object.isVisible() == true);
+ object.setVisible(false);
+ QCOMPARE(spy.count(), 1);
+
+ QVERIFY(object.isVisible() == false);
+
+ object.setVisible(false);
+ QCOMPARE(spy.count(), 1);
+
+ object.setProperty("visible", true);
+ QCOMPARE(spy.count(), 2);
+ QVERIFY(object.property("visible") == true);
+}
+
+class DeleteTester : public QGraphicsObject
+{
+public:
+ DeleteTester(bool *w, bool *pw, QGraphicsItem *parent = 0)
+ : QGraphicsObject(parent), wasDeleted(w), parentWasDeleted(pw)
+ { }
+
+ ~DeleteTester()
+ {
+ *wasDeleted = QObjectPrivate::get(this)->wasDeleted;
+ if (QGraphicsItem *p = parentItem()) {
+ if (QGraphicsObject *o = p->toGraphicsObject())
+ *parentWasDeleted = QObjectPrivate::get(o)->wasDeleted;
+ }
+ }
+
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = 0)
+ { }
+ QRectF boundingRect() const
+ { return QRectF(); }
+
+ bool *wasDeleted;
+ bool *parentWasDeleted;
+};
+
+void tst_QGraphicsObject::deleted()
+{
+ bool item1_parentWasDeleted = false;
+ bool item1_wasDeleted = false;
+ bool item2_parentWasDeleted = false;
+ bool item2_wasDeleted = false;
+ DeleteTester *item1 = new DeleteTester(&item1_wasDeleted, &item1_parentWasDeleted);
+ DeleteTester *item2 = new DeleteTester(&item2_wasDeleted, &item2_parentWasDeleted, item1);
+ Q_UNUSED(item2);
+ delete item1;
+
+ QVERIFY(!item1_wasDeleted); // destructor not called yet
+ QVERIFY(!item1_parentWasDeleted); // no parent
+ QVERIFY(!item2_wasDeleted); // destructor not called yet
+ QVERIFY(item2_parentWasDeleted);
+}
+
+QTEST_MAIN(tst_QGraphicsObject)
+#include "tst_qgraphicsobject.moc"
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicspixmapitem/.gitignore b/tests/auto/widgets/graphicsview/qgraphicspixmapitem/.gitignore
new file mode 100644
index 0000000000..1e92419fd0
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicspixmapitem/.gitignore
@@ -0,0 +1 @@
+tst_qgraphicspixmapitem
diff --git a/tests/auto/widgets/graphicsview/qgraphicspixmapitem/qgraphicspixmapitem.pro b/tests/auto/widgets/graphicsview/qgraphicspixmapitem/qgraphicspixmapitem.pro
new file mode 100644
index 0000000000..6b1ad34057
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicspixmapitem/qgraphicspixmapitem.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qgraphicspixmapitem.cpp
+CONFIG += parallel_test
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp b/tests/auto/widgets/graphicsview/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp
new file mode 100644
index 0000000000..b2dccb0b09
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicspixmapitem/tst_qgraphicspixmapitem.cpp
@@ -0,0 +1,427 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.1, 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qgraphicsscene.h>
+#include <qgraphicsitem.h>
+
+class tst_QGraphicsPixmapItem : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void qgraphicspixmapitem_data();
+ void qgraphicspixmapitem();
+ void boundingRect_data();
+ void boundingRect();
+ void contains_data();
+ void contains();
+ void isObscuredBy_data();
+ void isObscuredBy();
+ void offset_data();
+ void offset();
+ void opaqueArea_data();
+ void opaqueArea();
+ void pixmap_data();
+ void pixmap();
+ void setPixmap_data();
+ void setPixmap();
+ void setShapeMode_data();
+ void setShapeMode();
+ void setTransformationMode_data();
+ void setTransformationMode();
+ void shape_data();
+ void shape();
+ void extension_data();
+ void extension();
+ void setExtension_data();
+ void setExtension();
+ void supportsExtension_data();
+ void supportsExtension();
+};
+
+// Subclass that exposes the protected functions.
+class SubQGraphicsPixmapItem : public QGraphicsPixmapItem
+{
+public:
+ enum Extension {
+ UserExtension = QGraphicsItem::UserExtension
+ };
+ SubQGraphicsPixmapItem(QGraphicsItem *parent = 0) : QGraphicsPixmapItem(parent)
+ {
+ }
+
+ SubQGraphicsPixmapItem(const QPixmap &pixmap, QGraphicsItem *parent = 0) : QGraphicsPixmapItem(pixmap, parent)
+ {
+ }
+
+ QVariant call_extension(QVariant const& variant) const
+ { return SubQGraphicsPixmapItem::extension(variant); }
+
+ void call_setExtension(Extension extension, QVariant const& variant)
+ { return SubQGraphicsPixmapItem::setExtension((QGraphicsItem::Extension)extension, variant); }
+
+ bool call_supportsExtension(Extension extension) const
+ { return SubQGraphicsPixmapItem::supportsExtension((QGraphicsItem::Extension)extension); }
+};
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_QGraphicsPixmapItem::initTestCase()
+{
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_QGraphicsPixmapItem::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_QGraphicsPixmapItem::init()
+{
+}
+
+// This will be called after every test function.
+void tst_QGraphicsPixmapItem::cleanup()
+{
+}
+
+void tst_QGraphicsPixmapItem::qgraphicspixmapitem_data()
+{
+}
+
+void tst_QGraphicsPixmapItem::qgraphicspixmapitem()
+{
+ SubQGraphicsPixmapItem item;
+ item.boundingRect();
+ item.contains(QPoint());
+ item.isObscuredBy(0);
+ item.opaqueArea();
+ //item.paint();
+ QCOMPARE(item.offset(), QPointF());
+ QCOMPARE(item.pixmap(), QPixmap());
+ QCOMPARE(item.shapeMode(), QGraphicsPixmapItem::MaskShape);
+ QCOMPARE(item.transformationMode(), Qt::FastTransformation);
+ item.setOffset(0, 0);
+ item.setOffset(QPointF(0, 0));
+ item.setPixmap(QPixmap());
+ item.setShapeMode(QGraphicsPixmapItem::MaskShape);
+ item.setTransformationMode(Qt::FastTransformation);
+ item.shape();
+ item.type();
+ item.call_extension(QVariant());
+ item.call_setExtension(SubQGraphicsPixmapItem::UserExtension, QVariant());
+ item.call_supportsExtension(SubQGraphicsPixmapItem::UserExtension);
+}
+
+void tst_QGraphicsPixmapItem::boundingRect_data()
+{
+ QTest::addColumn<QPixmap>("pixmap");
+ QTest::addColumn<QRectF>("boundingRect");
+ QTest::newRow("null") << QPixmap() << QRectF();
+ QTest::newRow("10x10") << QPixmap(10, 10) << QRectF(0, 0, 10, 10);
+}
+
+// public QRectF boundingRect() const
+void tst_QGraphicsPixmapItem::boundingRect()
+{
+ QFETCH(QPixmap, pixmap);
+ QFETCH(QRectF, boundingRect);
+
+ SubQGraphicsPixmapItem item(pixmap);
+ QCOMPARE(item.boundingRect(), boundingRect);
+}
+
+void tst_QGraphicsPixmapItem::contains_data()
+{
+ QTest::addColumn<QPixmap>("pixmap");
+ QTest::addColumn<QPointF>("point");
+ QTest::addColumn<bool>("contains");
+ QTest::newRow("null") << QPixmap() << QPointF() << false;
+ QTest::newRow("10x10, 100x100") << QPixmap(10, 10) << QPointF(100, 100) << false;
+ QTest::newRow("10x10, 5x5") << QPixmap(10, 10) << QPointF(5, 5) << true;
+ QTest::newRow("border-1") << QPixmap(10, 10) << QPointF(10.5, 10.5) << false;
+ QTest::newRow("border-2") << QPixmap(10, 10) << QPointF(-0.5, -0.5) << false;
+}
+
+// public bool contains(QPointF const& point) const
+void tst_QGraphicsPixmapItem::contains()
+{
+ QFETCH(QPixmap, pixmap);
+ QFETCH(QPointF, point);
+ QFETCH(bool, contains);
+
+ SubQGraphicsPixmapItem item(pixmap);
+ QCOMPARE(item.contains(point), contains);
+}
+
+void tst_QGraphicsPixmapItem::isObscuredBy_data()
+{
+ QTest::addColumn<QPixmap>("pixmap");
+ QTest::addColumn<QPixmap>("otherPixmap");
+ QTest::addColumn<bool>("isObscuredBy");
+ QTest::newRow("null") << QPixmap() << QPixmap() << false;
+ QTest::newRow("(10, 10) vs. (5, 5)") << QPixmap(10, 10) << QPixmap(5, 5) << false;
+ QTest::newRow("(5, 5) vs. (10, 10)") << QPixmap(5, 5) << QPixmap(10, 10) << true;
+ QTest::newRow("(10, 10) vs. (10, 10)") << QPixmap(10, 10) << QPixmap(10, 10) << false;
+ QTest::newRow("(9, 9) vs. (10, 10)") << QPixmap(8, 8) << QPixmap(10, 10) << true;
+ QTest::newRow("(10, 10) vs. (9, 9)") << QPixmap(10, 10) << QPixmap(8, 8) << false;
+}
+
+// public bool isObscuredBy(QGraphicsItem const* item) const
+void tst_QGraphicsPixmapItem::isObscuredBy()
+{
+ QFETCH(QPixmap, pixmap);
+ QFETCH(QPixmap, otherPixmap);
+ QFETCH(bool, isObscuredBy);
+ pixmap.fill();
+ otherPixmap.fill();
+
+ SubQGraphicsPixmapItem *item = new SubQGraphicsPixmapItem(pixmap);
+ SubQGraphicsPixmapItem *otherItem = new SubQGraphicsPixmapItem(otherPixmap);
+
+ item->setOffset(-pixmap.width() / 2.0, -pixmap.height() / 2.0);
+ otherItem->setOffset(-otherPixmap.width() / 2.0, -otherPixmap.height() / 2.0);
+
+ QGraphicsScene scene;
+ scene.addItem(item);
+ scene.addItem(otherItem);
+ otherItem->setZValue(1);
+
+ QCOMPARE(item->isObscuredBy(otherItem), isObscuredBy);
+}
+
+void tst_QGraphicsPixmapItem::offset_data()
+{
+ QTest::addColumn<QPixmap>("pixmap");
+ QTest::addColumn<QPointF>("offset");
+ QTest::newRow("null") << QPixmap() << QPointF();
+ QTest::newRow("10x10, 1x1") << QPixmap(10, 10) << QPointF(1, 1);
+}
+
+// public QPointF offset() const
+void tst_QGraphicsPixmapItem::offset()
+{
+ QFETCH(QPixmap, pixmap);
+ QFETCH(QPointF, offset);
+
+ SubQGraphicsPixmapItem item(pixmap);
+ item.setOffset(offset);
+ QCOMPARE(item.offset(), offset);
+
+ // ### test actual painting and compare pixmap with offseted one?
+}
+
+Q_DECLARE_METATYPE(QPainterPath)
+void tst_QGraphicsPixmapItem::opaqueArea_data()
+{
+ QTest::addColumn<QPixmap>("pixmap");
+ QTest::addColumn<QPainterPath>("opaqueArea");
+ QTest::newRow("null") << QPixmap() << QPainterPath();
+ // Currently QGraphicsPixmapItem just calls QGraphicsItem test there
+}
+
+// public QPainterPath opaqueArea() const
+void tst_QGraphicsPixmapItem::opaqueArea()
+{
+ QFETCH(QPixmap, pixmap);
+ QFETCH(QPainterPath, opaqueArea);
+
+ SubQGraphicsPixmapItem item;
+ QCOMPARE(item.opaqueArea(), opaqueArea);
+}
+
+void tst_QGraphicsPixmapItem::pixmap_data()
+{
+ QTest::addColumn<QPixmap>("pixmap");
+ QTest::newRow("null") << QPixmap();
+ QTest::newRow("10x10") << QPixmap(10, 10);
+}
+
+// public QPixmap pixmap() const
+void tst_QGraphicsPixmapItem::pixmap()
+{
+ QFETCH(QPixmap, pixmap);
+
+ SubQGraphicsPixmapItem item(pixmap);
+ QCOMPARE(item.pixmap(), pixmap);
+}
+
+void tst_QGraphicsPixmapItem::setPixmap_data()
+{
+ QTest::addColumn<QPixmap>("pixmap");
+ QTest::newRow("null") << QPixmap();
+ QTest::newRow("10x10") << QPixmap(10, 10);
+}
+
+// public void setPixmap(QPixmap const& pixmap)
+void tst_QGraphicsPixmapItem::setPixmap()
+{
+ QFETCH(QPixmap, pixmap);
+
+ SubQGraphicsPixmapItem item;
+ item.setPixmap(pixmap);
+ QCOMPARE(item.pixmap(), pixmap);
+}
+
+Q_DECLARE_METATYPE(QGraphicsPixmapItem::ShapeMode)
+void tst_QGraphicsPixmapItem::setShapeMode_data()
+{
+ QTest::addColumn<QPixmap>("pixmap");
+ QTest::addColumn<QGraphicsPixmapItem::ShapeMode>("mode");
+ QTest::newRow("MaskShape") << QPixmap() << QGraphicsPixmapItem::MaskShape;
+ QTest::newRow("BoundingRectShape") << QPixmap() << QGraphicsPixmapItem::BoundingRectShape;
+ QTest::newRow("HeuristicMaskShape") << QPixmap() << QGraphicsPixmapItem::HeuristicMaskShape;
+}
+
+// public void setShapeMode(QGraphicsPixmapItem::ShapeMode mode)
+void tst_QGraphicsPixmapItem::setShapeMode()
+{
+ QFETCH(QPixmap, pixmap);
+ QFETCH(QGraphicsPixmapItem::ShapeMode, mode);
+
+ SubQGraphicsPixmapItem item(pixmap);
+ item.setShapeMode(mode);
+ QCOMPARE(item.shapeMode(), mode);
+}
+
+Q_DECLARE_METATYPE(Qt::TransformationMode)
+void tst_QGraphicsPixmapItem::setTransformationMode_data()
+{
+ QTest::addColumn<QPixmap>("pixmap");
+ QTest::addColumn<Qt::TransformationMode>("mode");
+ QTest::newRow("FastTransformation") << QPixmap() << Qt::FastTransformation;
+ QTest::newRow("SmoothTransformation") << QPixmap() << Qt::SmoothTransformation;
+}
+
+// public void setTransformationMode(Qt::TransformationMode mode)
+void tst_QGraphicsPixmapItem::setTransformationMode()
+{
+ QFETCH(QPixmap, pixmap);
+ QFETCH(Qt::TransformationMode, mode);
+
+ SubQGraphicsPixmapItem item(pixmap);
+ item.setTransformationMode(mode);
+ QCOMPARE(item.transformationMode(), mode);
+}
+
+void tst_QGraphicsPixmapItem::shape_data()
+{
+ QTest::addColumn<QPixmap>("pixmap");
+ QTest::addColumn<QPainterPath>("shape");
+ QTest::newRow("null") << QPixmap() << QPainterPath();
+ // ### what does a normal shape look like?
+}
+
+// public QPainterPath shape() const
+void tst_QGraphicsPixmapItem::shape()
+{
+ QFETCH(QPixmap, pixmap);
+ QFETCH(QPainterPath, shape);
+
+ SubQGraphicsPixmapItem item(pixmap);
+ QCOMPARE(item.shape(), shape);
+}
+
+Q_DECLARE_METATYPE(SubQGraphicsPixmapItem::Extension)
+Q_DECLARE_METATYPE(QVariant)
+void tst_QGraphicsPixmapItem::extension_data()
+{
+ QTest::addColumn<QVariant>("variant");
+ QTest::addColumn<QVariant>("extension");
+ QTest::newRow("null") << QVariant() << QVariant();
+}
+
+// protected QVariant extension(QVariant const& variant) const
+void tst_QGraphicsPixmapItem::extension()
+{
+ QFETCH(QVariant, variant);
+ QFETCH(QVariant, extension);
+
+ SubQGraphicsPixmapItem item;
+ QCOMPARE(item.call_extension(variant), extension);
+}
+
+void tst_QGraphicsPixmapItem::setExtension_data()
+{
+ QTest::addColumn<SubQGraphicsPixmapItem::Extension>("extension");
+ QTest::addColumn<QVariant>("variant");
+ QTest::newRow("null") << SubQGraphicsPixmapItem::UserExtension << QVariant();
+}
+
+// protected void setExtension(QGraphicsItem::Extension extension, QVariant const& variant)
+void tst_QGraphicsPixmapItem::setExtension()
+{
+ QFETCH(SubQGraphicsPixmapItem::Extension, extension);
+ QFETCH(QVariant, variant);
+
+ SubQGraphicsPixmapItem item;
+ item.call_setExtension(extension, variant);
+}
+
+void tst_QGraphicsPixmapItem::supportsExtension_data()
+{
+ QTest::addColumn<SubQGraphicsPixmapItem::Extension>("extension");
+ QTest::addColumn<bool>("supportsExtension");
+ QTest::newRow("null") << SubQGraphicsPixmapItem::UserExtension << false;
+}
+
+// protected bool supportsExtension(QGraphicsItem::Extension extension) const
+void tst_QGraphicsPixmapItem::supportsExtension()
+{
+ QFETCH(SubQGraphicsPixmapItem::Extension, extension);
+ QFETCH(bool, supportsExtension);
+
+ SubQGraphicsPixmapItem item;
+ QCOMPARE(item.call_supportsExtension(extension), supportsExtension);
+}
+
+QTEST_MAIN(tst_QGraphicsPixmapItem)
+#include "tst_qgraphicspixmapitem.moc"
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicspolygonitem/.gitignore b/tests/auto/widgets/graphicsview/qgraphicspolygonitem/.gitignore
new file mode 100644
index 0000000000..595076024b
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicspolygonitem/.gitignore
@@ -0,0 +1 @@
+tst_qgraphicspolygonitem
diff --git a/tests/auto/widgets/graphicsview/qgraphicspolygonitem/qgraphicspolygonitem.pro b/tests/auto/widgets/graphicsview/qgraphicspolygonitem/qgraphicspolygonitem.pro
new file mode 100644
index 0000000000..2aa16751e6
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicspolygonitem/qgraphicspolygonitem.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qgraphicspolygonitem.cpp
+CONFIG += parallel_test
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicspolygonitem/tst_qgraphicspolygonitem.cpp b/tests/auto/widgets/graphicsview/qgraphicspolygonitem/tst_qgraphicspolygonitem.cpp
new file mode 100644
index 0000000000..061b3eda81
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicspolygonitem/tst_qgraphicspolygonitem.cpp
@@ -0,0 +1,349 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.1, 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qgraphicsitem.h>
+
+Q_DECLARE_METATYPE(QPolygonF)
+
+class tst_QGraphicsPolygonItem : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void qgraphicspolygonitem_data();
+ void qgraphicspolygonitem();
+ void boundingRect_data();
+ void boundingRect();
+ void contains_data();
+ void contains();
+ void fillRule_data();
+ void fillRule();
+ void isObscuredBy_data();
+ void isObscuredBy();
+ void opaqueArea_data();
+ void opaqueArea();
+ void polygon_data();
+ void polygon();
+ void shape_data();
+ void shape();
+ void extension_data();
+ void extension();
+ void setExtension_data();
+ void setExtension();
+ void supportsExtension_data();
+ void supportsExtension();
+};
+
+// Subclass that exposes the protected functions.
+class SubQGraphicsPolygonItem : public QGraphicsPolygonItem
+{
+public:
+ enum Extension {
+ UserExtension = QGraphicsItem::UserExtension
+ };
+
+ SubQGraphicsPolygonItem(QGraphicsItem *parent = 0) : QGraphicsPolygonItem(parent)
+ {
+ }
+
+ SubQGraphicsPolygonItem(const QPolygonF &polygon, QGraphicsItem *parent = 0) : QGraphicsPolygonItem(polygon, parent)
+ {
+ }
+
+ QVariant call_extension(QVariant const& variant) const
+ { return SubQGraphicsPolygonItem::extension(variant); }
+
+ void call_setExtension(SubQGraphicsPolygonItem::Extension extension, QVariant const& variant)
+ { return SubQGraphicsPolygonItem::setExtension((QGraphicsItem::Extension)extension, variant); }
+
+ bool call_supportsExtension(SubQGraphicsPolygonItem::Extension extension) const
+ { return SubQGraphicsPolygonItem::supportsExtension((QGraphicsItem::Extension)extension); }
+};
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_QGraphicsPolygonItem::initTestCase()
+{
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_QGraphicsPolygonItem::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_QGraphicsPolygonItem::init()
+{
+}
+
+// This will be called after every test function.
+void tst_QGraphicsPolygonItem::cleanup()
+{
+}
+
+void tst_QGraphicsPolygonItem::qgraphicspolygonitem_data()
+{
+}
+
+void tst_QGraphicsPolygonItem::qgraphicspolygonitem()
+{
+ SubQGraphicsPolygonItem item;
+
+ item.boundingRect();
+ item.contains(QPoint());
+ item.isObscuredBy(0);
+ item.opaqueArea();
+ //item.paint();
+ item.shape();
+ item.type();
+ item.call_extension(QVariant());
+ item.call_setExtension(SubQGraphicsPolygonItem::UserExtension, QVariant());
+ item.call_supportsExtension(SubQGraphicsPolygonItem::UserExtension);
+ item.fillRule();
+ item.polygon();
+ item.setFillRule(Qt::OddEvenFill);
+ item.setPolygon(QPolygonF());
+}
+
+void tst_QGraphicsPolygonItem::boundingRect_data()
+{
+ QTest::addColumn<QPolygonF>("polygon");
+ QTest::addColumn<QRectF>("boundingRect");
+ QTest::newRow("null") << QPolygonF() << QRectF();
+ QPolygonF example;
+ example << QPointF(10.4, 20.5) << QPointF(20.2, 30.2);
+ QTest::newRow("example") << example << example.boundingRect();
+ // ### set pen width?
+}
+
+// public QRectF boundingRect() const
+void tst_QGraphicsPolygonItem::boundingRect()
+{
+ QFETCH(QPolygonF, polygon);
+ QFETCH(QRectF, boundingRect);
+
+ SubQGraphicsPolygonItem item(polygon);
+ QCOMPARE(item.boundingRect(), boundingRect);
+}
+
+void tst_QGraphicsPolygonItem::contains_data()
+{
+ QTest::addColumn<QPolygonF>("polygon");
+ QTest::addColumn<QPointF>("point");
+ QTest::addColumn<bool>("contains");
+ QTest::newRow("null") << QPolygonF() << QPointF() << false;
+}
+
+// public bool contains(QPointF const& point) const
+void tst_QGraphicsPolygonItem::contains()
+{
+ QFETCH(QPolygonF, polygon);
+ QFETCH(QPointF, point);
+ QFETCH(bool, contains);
+
+ SubQGraphicsPolygonItem item(polygon);
+
+ QCOMPARE(item.contains(point), contains);
+}
+
+Q_DECLARE_METATYPE(Qt::FillRule)
+void tst_QGraphicsPolygonItem::fillRule_data()
+{
+ QTest::addColumn<QPolygonF>("polygon");
+ QTest::addColumn<Qt::FillRule>("fillRule");
+ QTest::newRow("OddEvenFill") << QPolygonF() << Qt::OddEvenFill;
+ QTest::newRow("WindingFill") << QPolygonF() << Qt::WindingFill;
+}
+
+// public Qt::FillRule fillRule() const
+void tst_QGraphicsPolygonItem::fillRule()
+{
+ QFETCH(QPolygonF, polygon);
+ QFETCH(Qt::FillRule, fillRule);
+
+ SubQGraphicsPolygonItem item(polygon);
+
+ item.setFillRule(fillRule);
+ QCOMPARE(item.fillRule(), fillRule);
+ // ### Check that the painting is different?
+}
+
+void tst_QGraphicsPolygonItem::isObscuredBy_data()
+{
+ QTest::addColumn<QPolygonF>("polygon");
+ QTest::addColumn<QPolygonF>("otherPolygon");
+ QTest::addColumn<bool>("isObscuredBy");
+ QTest::newRow("null") << QPolygonF() << QPolygonF() << false;
+ //QTest::newRow("ontop-inside") << QPixmap(10, 10) << QPixmap(5, 5) << false;
+ //QTest::newRow("ontop-larger") << QPixmap(10, 10) << QPixmap(11, 11) << true;
+}
+
+// public bool isObscuredBy(QGraphicsItem const* item) const
+void tst_QGraphicsPolygonItem::isObscuredBy()
+{
+ QFETCH(QPolygonF, polygon);
+ QFETCH(QPolygonF, otherPolygon);
+ QFETCH(bool, isObscuredBy);
+ SubQGraphicsPolygonItem item(polygon);
+ SubQGraphicsPolygonItem otherItem(otherPolygon);
+ QCOMPARE(item.isObscuredBy(&otherItem), isObscuredBy);
+}
+
+Q_DECLARE_METATYPE(QPainterPath)
+void tst_QGraphicsPolygonItem::opaqueArea_data()
+{
+ QTest::addColumn<QPolygonF>("polygon");
+ QTest::addColumn<QPainterPath>("opaqueArea");
+ QTest::newRow("null") << QPolygonF() << QPainterPath();
+ // Currently QGraphicsPolygonItem just calls QGraphicsItem test there
+}
+
+// public QPainterPath opaqueArea() const
+void tst_QGraphicsPolygonItem::opaqueArea()
+{
+ QFETCH(QPolygonF, polygon);
+ QFETCH(QPainterPath, opaqueArea);
+
+ SubQGraphicsPolygonItem item(polygon);
+ QCOMPARE(item.opaqueArea(), opaqueArea);
+}
+
+void tst_QGraphicsPolygonItem::polygon_data()
+{
+ QTest::addColumn<QPolygonF>("polygon");
+ QTest::newRow("null") << QPolygonF();
+ QPolygonF example;
+ example << QPointF(10.4, 20.5) << QPointF(20.2, 30.2);
+ QTest::newRow("example") << example;
+}
+
+// public QPolygonF polygon() const
+void tst_QGraphicsPolygonItem::polygon()
+{
+ QFETCH(QPolygonF, polygon);
+
+ SubQGraphicsPolygonItem item;
+ item.setPolygon(polygon);
+ QCOMPARE(item.polygon(), polygon);
+}
+
+void tst_QGraphicsPolygonItem::shape_data()
+{
+ QTest::addColumn<QPainterPath>("shape");
+ QTest::newRow("null") << QPainterPath();
+ // ### what should a normal shape look like?
+}
+
+// public QPainterPath shape() const
+void tst_QGraphicsPolygonItem::shape()
+{
+ QFETCH(QPainterPath, shape);
+
+ SubQGraphicsPolygonItem item;
+ QCOMPARE(item.shape(), shape);
+}
+
+Q_DECLARE_METATYPE(QVariant)
+void tst_QGraphicsPolygonItem::extension_data()
+{
+ QTest::addColumn<QVariant>("variant");
+ QTest::addColumn<QVariant>("extension");
+ QTest::newRow("null") << QVariant() << QVariant();
+}
+
+// protected QVariant extension(QVariant const& variant) const
+void tst_QGraphicsPolygonItem::extension()
+{
+ QFETCH(QVariant, variant);
+ QFETCH(QVariant, extension);
+
+ SubQGraphicsPolygonItem item;
+
+ QCOMPARE(item.call_extension(variant), extension);
+}
+
+Q_DECLARE_METATYPE(SubQGraphicsPolygonItem::Extension)
+void tst_QGraphicsPolygonItem::setExtension_data()
+{
+ QTest::addColumn<SubQGraphicsPolygonItem::Extension>("extension");
+ QTest::addColumn<QVariant>("variant");
+ QTest::newRow("null") << SubQGraphicsPolygonItem::Extension() << QVariant();
+}
+
+// protected void setExtension(SubQGraphicsPolygonItem::Extension extension, QVariant const& variant)
+void tst_QGraphicsPolygonItem::setExtension()
+{
+ QFETCH(SubQGraphicsPolygonItem::Extension, extension);
+ QFETCH(QVariant, variant);
+
+ SubQGraphicsPolygonItem item;
+ item.call_setExtension(extension, variant);
+}
+
+void tst_QGraphicsPolygonItem::supportsExtension_data()
+{
+ QTest::addColumn<SubQGraphicsPolygonItem::Extension>("extension");
+ QTest::addColumn<bool>("supportsExtension");
+ QTest::newRow("null") << SubQGraphicsPolygonItem::Extension() << false;
+}
+
+// protected bool supportsExtension(SubQGraphicsPolygonItem::Extension extension) const
+void tst_QGraphicsPolygonItem::supportsExtension()
+{
+ QFETCH(SubQGraphicsPolygonItem::Extension, extension);
+ QFETCH(bool, supportsExtension);
+
+ SubQGraphicsPolygonItem item;
+ QCOMPARE(item.call_supportsExtension(extension), supportsExtension);
+}
+
+QTEST_MAIN(tst_QGraphicsPolygonItem)
+#include "tst_qgraphicspolygonitem.moc"
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/.gitignore b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/.gitignore
new file mode 100644
index 0000000000..530452478b
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/.gitignore
@@ -0,0 +1 @@
+tst_qgraphicsproxywidget
diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/qgraphicsproxywidget.pro b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/qgraphicsproxywidget.pro
new file mode 100644
index 0000000000..a649ae1a3c
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/qgraphicsproxywidget.pro
@@ -0,0 +1,8 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+QT += core-private gui-private
+
+SOURCES += tst_qgraphicsproxywidget.cpp
+
+contains(QT_CONFIG,xcb):qpa:CONFIG+=insignificant_test # QTBUG-20756 crashes on qpa, xcb
diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
new file mode 100644
index 0000000000..78c545e25a
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
@@ -0,0 +1,3649 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.1, 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtGui>
+#include <QtWidgets>
+#include <private/qgraphicsproxywidget_p.h>
+#include <private/qlayoutengine_p.h> // qSmartMin functions...
+#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
+#include <QMacStyle>
+#endif
+#ifdef Q_WS_X11
+#include <private/qt_x11_p.h>
+#endif
+
+static void sendMouseMove(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::NoButton)
+{
+ QMouseEvent event(QEvent::MouseMove, point, widget->mapToGlobal(point), button, button, 0);
+ QApplication::sendEvent(widget, &event);
+}
+
+/*
+ Notes:
+
+ 1) The proxy and the widget geometries are linked.
+ proxy resize => widget resize => stop (no livelock)
+ widget resize => proxy resize => stop (no livelock)
+
+ 2) As far as possible, the properties are linked.
+ proxy enable => widget enable => stop
+ widget disabled => proxy disabled => stop
+
+ 3) Windowed state is linked
+ Windowed proxy state => windowed widget state => stop
+ Windowed widget state => windowed proxy state => stop
+*/
+
+class EventSpy : public QObject
+{
+public:
+ EventSpy(QObject *receiver)
+ {
+ receiver->installEventFilter(this);
+ }
+
+ QMap<QEvent::Type, int> counts;
+
+protected:
+ bool eventFilter(QObject *, QEvent *event)
+ {
+ ++counts[event->type()];
+ return false;
+ }
+};
+
+class tst_QGraphicsProxyWidget : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void qgraphicsproxywidget_data();
+ void qgraphicsproxywidget();
+ void paint();
+ void paint_2();
+ void setWidget_data();
+ void setWidget();
+ void eventFilter_data();
+ void eventFilter();
+ void focusInEvent_data();
+ void focusInEvent();
+ void focusInEventNoWidget();
+ void focusNextPrevChild_data();
+ void focusNextPrevChild();
+ void focusOutEvent_data();
+ void focusOutEvent();
+#if !defined(Q_OS_WINCE) || (defined(GWES_ICONCURS) && !defined(QT_NO_CURSOR))
+ void hoverEnterLeaveEvent_data();
+ void hoverEnterLeaveEvent();
+#endif
+ void hoverMoveEvent_data();
+ void hoverMoveEvent();
+ void keyPressEvent_data();
+ void keyPressEvent();
+ void keyReleaseEvent_data();
+ void keyReleaseEvent();
+ void mouseDoubleClickEvent_data();
+ void mouseDoubleClickEvent();
+ void mousePressReleaseEvent_data();
+ void mousePressReleaseEvent();
+ void resizeEvent_data();
+ void resizeEvent();
+ void paintEvent();
+ void wheelEvent();
+ void sizeHint_data();
+ void sizeHint();
+ void sizePolicy();
+ void minimumSize();
+ void maximumSize();
+ void scrollUpdate();
+ void setWidget_simple();
+ void setWidget_ownership();
+ void resize_simple_data();
+ void resize_simple();
+ void symmetricMove();
+ void symmetricResize();
+ void symmetricEnabled();
+ void symmetricVisible();
+ void tabFocus_simpleWidget();
+ void tabFocus_simpleTwoWidgets();
+ void tabFocus_complexWidget();
+ void tabFocus_complexTwoWidgets();
+ void setFocus_simpleWidget();
+ void setFocus_simpleTwoWidgets();
+ void setFocus_complexTwoWidgets();
+ void popup_basic();
+ void popup_subwidget();
+#if !defined(QT_NO_CURSOR) && (!defined(Q_OS_WINCE) || defined(GWES_ICONCURS))
+ void changingCursor_basic();
+#endif
+ void tooltip_basic();
+ void childPos_data();
+ void childPos();
+ void autoShow();
+ void windowOpacity();
+ void stylePropagation();
+ void palettePropagation();
+ void fontPropagation();
+ void dontCrashWhenDie();
+ void createProxyForChildWidget();
+ void actionsContextMenu();
+ void actionsContextMenu_data();
+ void deleteProxyForChildWidget();
+ void bypassGraphicsProxyWidget_data();
+ void bypassGraphicsProxyWidget();
+ void dragDrop();
+ void windowFlags_data();
+ void windowFlags();
+ void comboboxWindowFlags();
+ void updateAndDelete();
+ void inputMethod();
+ void clickFocus();
+ void windowFrameMargins();
+ void QTBUG_6986_sendMouseEventToAlienWidget();
+};
+
+// Subclass that exposes the protected functions.
+class SubQGraphicsProxyWidget : public QGraphicsProxyWidget
+{
+
+public:
+ SubQGraphicsProxyWidget(QGraphicsItem *parent = 0) : QGraphicsProxyWidget(parent),
+ paintCount(0), keyPress(0), focusOut(0)
+ {}
+
+ bool call_eventFilter(QObject* object, QEvent* event)
+ { return SubQGraphicsProxyWidget::eventFilter(object, event); }
+
+ void call_focusInEvent(QFocusEvent* event)
+ { return SubQGraphicsProxyWidget::focusInEvent(event); }
+
+ bool call_focusNextPrevChild(bool next)
+ { return SubQGraphicsProxyWidget::focusNextPrevChild(next); }
+
+ void call_focusOutEvent(QFocusEvent* event)
+ { return SubQGraphicsProxyWidget::focusOutEvent(event); }
+
+ void call_hideEvent(QHideEvent* event)
+ { return SubQGraphicsProxyWidget::hideEvent(event); }
+
+ void call_hoverEnterEvent(QGraphicsSceneHoverEvent* event)
+ { return SubQGraphicsProxyWidget::hoverEnterEvent(event); }
+
+ void call_hoverLeaveEvent(QGraphicsSceneHoverEvent* event)
+ { return SubQGraphicsProxyWidget::hoverLeaveEvent(event); }
+
+ void call_hoverMoveEvent(QGraphicsSceneHoverEvent* event)
+ { return SubQGraphicsProxyWidget::hoverMoveEvent(event); }
+
+ void call_keyPressEvent(QKeyEvent* event)
+ { return SubQGraphicsProxyWidget::keyPressEvent(event); }
+
+ void call_keyReleaseEvent(QKeyEvent* event)
+ { return SubQGraphicsProxyWidget::keyReleaseEvent(event); }
+
+ void call_mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
+ { return SubQGraphicsProxyWidget::mouseDoubleClickEvent(event); }
+
+ void call_mouseMoveEvent(QGraphicsSceneMouseEvent* event)
+ { return SubQGraphicsProxyWidget::mouseMoveEvent(event); }
+
+ void call_mousePressEvent(QGraphicsSceneMouseEvent* event)
+ { return SubQGraphicsProxyWidget::mousePressEvent(event); }
+
+ void call_mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
+ { return SubQGraphicsProxyWidget::mouseReleaseEvent(event); }
+
+ void call_resizeEvent(QGraphicsSceneResizeEvent* event)
+ { return SubQGraphicsProxyWidget::resizeEvent(event); }
+
+ QSizeF call_sizeHint(Qt::SizeHint which, QSizeF const& constraint = QSizeF()) const
+ { return SubQGraphicsProxyWidget::sizeHint(which, constraint); }
+
+ void call_showEvent(QShowEvent* event)
+ { return SubQGraphicsProxyWidget::showEvent(event); }
+
+ void paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) {
+ paintCount++;
+ QGraphicsProxyWidget::paint(painter, option, widget);
+ }
+
+ void focusOutEvent(QFocusEvent *event)
+ {
+ focusOut++;
+ QGraphicsProxyWidget::focusOutEvent(event);
+ }
+
+ bool eventFilter(QObject *object, QEvent *event) {
+ if (event->type() == QEvent::KeyPress && object == widget())
+ keyPress++;
+ return QGraphicsProxyWidget::eventFilter(object, event);
+ }
+ int paintCount;
+ int keyPress;
+ int focusOut;
+};
+
+class WheelWidget : public QWidget
+{
+public:
+ WheelWidget() : wheelEventCalled(false) { setFocusPolicy(Qt::WheelFocus); }
+
+ virtual void wheelEvent(QWheelEvent *event) { event->accept(); wheelEventCalled = true; }
+
+ bool wheelEventCalled;
+};
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_QGraphicsProxyWidget::initTestCase()
+{
+#ifdef Q_OS_WINCE //disable magic for WindowsCE
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_QGraphicsProxyWidget::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_QGraphicsProxyWidget::init()
+{
+}
+
+// This will be called after every test function.
+void tst_QGraphicsProxyWidget::cleanup()
+{
+}
+
+void tst_QGraphicsProxyWidget::qgraphicsproxywidget_data()
+{
+}
+
+void tst_QGraphicsProxyWidget::qgraphicsproxywidget()
+{
+ SubQGraphicsProxyWidget proxy;
+ proxy.paint(0, 0, 0);
+ proxy.setWidget(0);
+ QVERIFY(proxy.type() == QGraphicsProxyWidget::Type);
+ QVERIFY(!proxy.widget());
+ QEvent event(QEvent::None);
+ proxy.call_eventFilter(0, &event);
+ QFocusEvent focusEvent(QEvent::FocusIn);
+ focusEvent.ignore();
+ proxy.call_focusInEvent(&focusEvent);
+ QCOMPARE(focusEvent.isAccepted(), false);
+ QCOMPARE(proxy.call_focusNextPrevChild(false), false);
+ QCOMPARE(proxy.call_focusNextPrevChild(true), false);
+ proxy.call_focusOutEvent(&focusEvent);
+ QHideEvent hideEvent;
+ proxy.call_hideEvent(&hideEvent);
+ QGraphicsSceneHoverEvent hoverEvent;
+ proxy.call_hoverEnterEvent(&hoverEvent);
+ proxy.call_hoverLeaveEvent(&hoverEvent);
+ proxy.call_hoverMoveEvent(&hoverEvent);
+ QKeyEvent keyEvent(QEvent::KeyPress, 0, Qt::NoModifier);
+ proxy.call_keyPressEvent(&keyEvent);
+ proxy.call_keyReleaseEvent(&keyEvent);
+ QGraphicsSceneMouseEvent mouseEvent;
+ proxy.call_mouseDoubleClickEvent(&mouseEvent);
+ proxy.call_mouseMoveEvent(&mouseEvent);
+ proxy.call_mousePressEvent(&mouseEvent);
+ proxy.call_mouseReleaseEvent(&mouseEvent);
+ QGraphicsSceneResizeEvent resizeEvent;
+ proxy.call_resizeEvent(&resizeEvent);
+ QShowEvent showEvent;
+ proxy.call_showEvent(&showEvent);
+ proxy.call_sizeHint(Qt::PreferredSize, QSizeF());
+}
+
+// public void paint(QPainter* painter, QStyleOptionGraphicsItem const* option, QWidget* widget)
+void tst_QGraphicsProxyWidget::paint()
+{
+ SubQGraphicsProxyWidget proxy;
+ proxy.paint(0, 0, 0);
+}
+
+class MyProxyWidget : public QGraphicsProxyWidget
+{
+public:
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ // Make sure QGraphicsProxyWidget::paint does not modify the render hints set on the painter.
+ painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform
+ | QPainter::NonCosmeticDefaultPen | QPainter::TextAntialiasing);
+ const QPainter::RenderHints oldRenderHints = painter->renderHints();
+ QGraphicsProxyWidget::paint(painter, option, widget);
+ QCOMPARE(painter->renderHints(), oldRenderHints);
+ }
+};
+
+void tst_QGraphicsProxyWidget::paint_2()
+{
+ MyProxyWidget *proxyWidget = new MyProxyWidget;
+ proxyWidget->setWidget(new QLineEdit);
+
+ QGraphicsScene scene;
+ scene.addItem(proxyWidget);
+ scene.setSceneRect(scene.itemsBoundingRect());
+
+ // Trigger repaint.
+ QPixmap pixmap(scene.sceneRect().toRect().size());
+ QPainter painter(&pixmap);
+ scene.render(&painter);
+}
+
+void tst_QGraphicsProxyWidget::setWidget_data()
+{
+ QTest::addColumn<bool>("widgetExists");
+ QTest::addColumn<bool>("insertWidget");
+ QTest::addColumn<bool>("hasParent");
+ QTest::addColumn<bool>("proxyHasParent");
+
+ QTest::newRow("setWidget(0)") << false << false << false << false;
+ QTest::newRow("setWidget(widget)") << false << true << false << false;
+ QTest::newRow("setWidget(widgetWParent)") << false << true << true << false;
+ QTest::newRow("setWidget(1), setWidget(0)") << true << false << false << false;
+ QTest::newRow("setWidget(1), setWidget(widget)") << true << true << false << false;
+ QTest::newRow("setWidget(1), setWidget(widgetWParent)") << true << true << true << false;
+ QTest::newRow("p setWidget(0)") << false << false << false << true;
+ QTest::newRow("p setWidget(widget)") << false << true << false << true;
+ QTest::newRow("p setWidget(widgetWParent)") << false << true << true << true;
+ QTest::newRow("p setWidget(1), setWidget(0)") << true << false << false << true;
+ QTest::newRow("p setWidget(1), setWidget(widget)") << true << true << false << true;
+ QTest::newRow("p setWidget(1), setWidget(widgetWParent)") << true << true << true << true;
+}
+
+// public void setWidget(QWidget* widget)
+void tst_QGraphicsProxyWidget::setWidget()
+{
+ QFETCH(bool, widgetExists);
+ QFETCH(bool, insertWidget);
+ QFETCH(bool, hasParent);
+ QFETCH(bool, proxyHasParent);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QPointer<SubQGraphicsProxyWidget> proxy = new SubQGraphicsProxyWidget;
+ SubQGraphicsProxyWidget parentProxy;
+ scene.addItem(proxy);
+ scene.addItem(&parentProxy);
+ if (proxyHasParent)
+ proxy->setParent(&parentProxy);
+ QPointer<QWidget> existingSubWidget = new QWidget;
+ proxy->setVisible(false);
+ proxy->setEnabled(false);
+
+ if (widgetExists) {
+ existingSubWidget->setAttribute(Qt::WA_QuitOnClose, true);
+ proxy->setWidget(existingSubWidget);
+ }
+
+ QWidget *widget = new QWidget;
+#ifndef QT_NO_CURSOR
+ widget->setCursor(Qt::IBeamCursor);
+#endif
+ widget->setPalette(QPalette(Qt::magenta));
+ widget->setLayoutDirection(Qt::RightToLeft);
+ QCleanlooksStyle cleanlooksStyle;
+ widget->setStyle(&cleanlooksStyle);
+ widget->setFont(QFont("Times"));
+ widget->setVisible(true);
+ QApplication::setActiveWindow(widget);
+ widget->activateWindow();
+ widget->setEnabled(true);
+ widget->resize(325, 241);
+ widget->setMinimumSize(100, 200);
+ widget->setMaximumSize(1000, 2000);
+ widget->setFocusPolicy(Qt::TabFocus);
+ widget->setContentsMargins(10, 29, 19, 81);
+ widget->setFocus(Qt::TabFocusReason);
+ widget->setAcceptDrops(true);
+ QTRY_VERIFY(widget->hasFocus());
+ QVERIFY(widget->isActiveWindow());
+
+ QWidget parentWidget;
+ if (hasParent)
+ widget->setParent(&parentWidget);
+
+ QWidget *subWidget = insertWidget ? widget : 0;
+ bool shouldBeInsertable = !hasParent && subWidget;
+ if (shouldBeInsertable)
+ subWidget->setAttribute(Qt::WA_QuitOnClose, true);
+
+ proxy->setWidget(subWidget);
+
+ if (shouldBeInsertable) {
+ QCOMPARE(proxy->widget(), subWidget);
+ QVERIFY(subWidget->testAttribute(Qt::WA_DontShowOnScreen));
+ QVERIFY(!subWidget->testAttribute(Qt::WA_QuitOnClose));
+ QCOMPARE(proxy->acceptHoverEvents(), true);
+#ifndef QT_NO_CURSOR
+ QVERIFY(proxy->hasCursor());
+
+ // These should match
+ QCOMPARE(proxy->cursor().shape(), widget->cursor().shape());
+#endif
+ //###QCOMPARE(proxy->palette(), widget->palette());
+ QCOMPARE(proxy->layoutDirection(), widget->layoutDirection());
+ QCOMPARE(proxy->style(), widget->style());
+ QCOMPARE(proxy->isVisible(), widget->isVisible());
+ QCOMPARE(proxy->isEnabled(), widget->isEnabled());
+ QVERIFY(proxy->flags() & QGraphicsItem::ItemIsFocusable);
+ QCOMPARE(proxy->effectiveSizeHint(Qt::MinimumSize).toSize(),
+ qSmartMinSize(widget));
+ QCOMPARE(proxy->minimumSize().toSize(),
+ qSmartMinSize(widget) );
+ QCOMPARE(proxy->maximumSize().toSize(), QSize(1000, 2000));
+ QCOMPARE(proxy->effectiveSizeHint(Qt::PreferredSize).toSize(),
+ qSmartMinSize(widget));
+ QCOMPARE(proxy->size().toSize(), widget->size());
+ QCOMPARE(proxy->rect().toRect(), widget->rect());
+ QCOMPARE(proxy->focusPolicy(), Qt::WheelFocus);
+ QVERIFY(proxy->acceptDrops());
+ QCOMPARE(proxy->acceptsHoverEvents(), true); // to get widget enter events
+ int left, top, right, bottom;
+ widget->getContentsMargins(&left, &top, &right, &bottom);
+ qreal rleft, rtop, rright, rbottom;
+ proxy->getContentsMargins(&rleft, &rtop, &rright, &rbottom);
+ QCOMPARE((qreal)left, rleft);
+ QCOMPARE((qreal)top, rtop);
+ QCOMPARE((qreal)right, rright);
+ QCOMPARE((qreal)bottom, rbottom);
+ } else {
+ // proxy shouldn't mess with the widget if it can't insert it.
+ QCOMPARE(proxy->widget(), (QWidget*)0);
+ QCOMPARE(proxy->acceptHoverEvents(), false);
+ if (subWidget) {
+ QVERIFY(!subWidget->testAttribute(Qt::WA_DontShowOnScreen));
+ QVERIFY(subWidget->testAttribute(Qt::WA_QuitOnClose));
+ // reset
+ subWidget->setAttribute(Qt::WA_QuitOnClose, false);
+ }
+ }
+
+ if (widgetExists) {
+ QCOMPARE(existingSubWidget->parent(), static_cast<QObject*>(0));
+ QVERIFY(!existingSubWidget->testAttribute(Qt::WA_DontShowOnScreen));
+ QVERIFY(!existingSubWidget->testAttribute(Qt::WA_QuitOnClose));
+ }
+
+ if (hasParent)
+ widget->setParent(0);
+
+ delete widget;
+ if (shouldBeInsertable)
+ QVERIFY(!proxy);
+ delete existingSubWidget;
+ if (!shouldBeInsertable) {
+ QVERIFY(proxy);
+ delete proxy;
+ }
+ QVERIFY(!proxy);
+}
+
+Q_DECLARE_METATYPE(QEvent::Type)
+void tst_QGraphicsProxyWidget::eventFilter_data()
+{
+ QTest::addColumn<QEvent::Type>("eventType");
+ QTest::addColumn<bool>("fromObject"); // big grin evil
+ QTest::newRow("none") << QEvent::None << false;
+ for (int i = 0; i < 2; ++i) {
+ bool fromObject = (i == 0);
+ QTest::newRow(QString("resize %1").arg(fromObject).toLatin1()) << QEvent::Resize << fromObject;
+ QTest::newRow(QString("move %1").arg(fromObject).toLatin1()) << QEvent::Move << fromObject;
+ QTest::newRow(QString("hide %1").arg(fromObject).toLatin1()) << QEvent::Hide << fromObject;
+ QTest::newRow(QString("show %1").arg(fromObject).toLatin1()) << QEvent::Show << fromObject;
+ QTest::newRow(QString("enabled %1").arg(fromObject).toLatin1()) << QEvent::EnabledChange << fromObject;
+ QTest::newRow(QString("focusIn %1").arg(fromObject).toLatin1()) << QEvent::FocusIn << fromObject;
+ QTest::newRow(QString("focusOut %1").arg(fromObject).toLatin1()) << QEvent::FocusOut << fromObject;
+ QTest::newRow(QString("keyPress %1").arg(fromObject).toLatin1()) << QEvent::KeyPress << fromObject;
+ }
+}
+
+// protected bool eventFilter(QObject* object, QEvent* event)
+void tst_QGraphicsProxyWidget::eventFilter()
+{
+ QFETCH(QEvent::Type, eventType);
+ QFETCH(bool, fromObject);
+
+ QGraphicsScene scene;
+ QEvent windowActivate(QEvent::WindowActivate);
+ qApp->sendEvent(&scene, &windowActivate);
+
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ scene.addItem(proxy);
+
+ QWidget *widget = new QWidget(0, Qt::FramelessWindowHint);
+ widget->setFocusPolicy(Qt::TabFocus);
+ widget->resize(10, 10);
+ widget->show();
+ proxy->setWidget(widget);
+ proxy->show();
+
+ // mirror whatever is happening to the widget
+ // don't get in a loop
+ switch (eventType) {
+ case QEvent::None: {
+ QEvent event(QEvent::None);
+ proxy->call_eventFilter(widget, &event);
+ break;
+ }
+ case QEvent::Resize: {
+ QSize oldSize = widget->size();
+ QSize newSize = QSize(100, 100);
+ if (fromObject) {
+ widget->resize(newSize);
+ } else {
+ proxy->resize(newSize);
+ }
+ QCOMPARE(proxy->size().toSize(), newSize);
+ QCOMPARE(widget->size(), newSize);
+ break;
+ }
+ case QEvent::Move: {
+ QPoint oldPoint = widget->pos();
+ QPoint newPoint = QPoint(100, 100);
+ if (fromObject) {
+ widget->move(newPoint);
+ } else {
+ proxy->setPos(newPoint);
+ }
+ QCOMPARE(proxy->pos().toPoint(), newPoint);
+ QCOMPARE(widget->pos(), newPoint);
+ break;
+ }
+ case QEvent::Hide: {
+ // A hide event can only come from a widget
+ if (fromObject) {
+ widget->setFocus(Qt::TabFocusReason);
+ widget->hide();
+ } else {
+ QHideEvent event;
+ proxy->call_eventFilter(widget, &event);
+ }
+ QCOMPARE(proxy->isVisible(), false);
+ break;
+ }
+ case QEvent::Show: {
+ // A show event can either come from a widget or somewhere else
+ widget->hide();
+ if (fromObject) {
+ widget->show();
+ } else {
+ QShowEvent event;
+ proxy->call_eventFilter(widget, &event);
+ }
+ QCOMPARE(proxy->isVisible(), true);
+ break;
+ }
+ case QEvent::EnabledChange: {
+ widget->setEnabled(false);
+ proxy->setEnabled(false);
+ if (fromObject) {
+ widget->setEnabled(true);
+ QCOMPARE(proxy->isEnabled(), true);
+ widget->setEnabled(false);
+ QCOMPARE(proxy->isEnabled(), false);
+ } else {
+ QEvent event(QEvent::EnabledChange);
+ proxy->call_eventFilter(widget, &event);
+ // match the widget not the event
+ QCOMPARE(proxy->isEnabled(), false);
+ }
+ break;
+ }
+ case QEvent::FocusIn: {
+ if (fromObject) {
+ widget->setFocus(Qt::TabFocusReason);
+ QVERIFY(proxy->hasFocus());
+ }
+ break;
+ }
+ case QEvent::FocusOut: {
+ widget->setFocus(Qt::TabFocusReason);
+ QVERIFY(proxy->hasFocus());
+ QVERIFY(widget->hasFocus());
+ if (fromObject) {
+ widget->clearFocus();
+ QVERIFY(!proxy->hasFocus());
+ }
+ break;
+ }
+ case QEvent::KeyPress: {
+ if (fromObject) {
+ QTest::keyPress(widget, Qt::Key_A, Qt::NoModifier);
+ } else {
+ QKeyEvent event(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier);
+ proxy->call_eventFilter(widget, &event);
+ }
+ QCOMPARE(proxy->keyPress, 1);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void tst_QGraphicsProxyWidget::focusInEvent_data()
+{
+ QTest::addColumn<bool>("widgetHasFocus");
+ QTest::addColumn<bool>("widgetCanHaveFocus");
+ QTest::newRow("no focus, can't get") << false << false;
+ QTest::newRow("no focus, can get") << false << true;
+ QTest::newRow("has focus, can't get") << true << false;
+ QTest::newRow("has focus, can get") << true << true;
+ // ### add test for widget having a focusNextPrevChild
+}
+
+// protected void focusInEvent(QFocusEvent* event)
+void tst_QGraphicsProxyWidget::focusInEvent()
+{
+ // ### This test is just plain old broken
+ QFETCH(bool, widgetHasFocus);
+ QFETCH(bool, widgetCanHaveFocus);
+
+ QGraphicsScene scene;
+ QEvent windowActivate(QEvent::WindowActivate);
+ qApp->sendEvent(&scene, &windowActivate);
+
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ proxy->setEnabled(true);
+ scene.addItem(proxy);
+ proxy->setVisible(true);
+
+ QWidget *widget = new QWidget;
+ widget->resize(100, 100);
+ if (widgetCanHaveFocus)
+ widget->setFocusPolicy(Qt::WheelFocus);
+ widget->show();
+
+ if (widgetHasFocus)
+ widget->setFocus(Qt::TabFocusReason);
+
+ proxy->setWidget(widget);
+ proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // <- shouldn't need to do this
+
+ // ### This test is just plain old broken - sending a focus in event
+ // does not cause items to gain input focus. The widget has focus
+ // because the proxy has focus, not because it got this event.
+
+ QFocusEvent event(QEvent::FocusIn, Qt::TabFocusReason);
+ event.ignore();
+ proxy->call_focusInEvent(&event);
+ QTRY_COMPARE(widget->hasFocus(), widgetCanHaveFocus);
+}
+
+void tst_QGraphicsProxyWidget::focusInEventNoWidget()
+{
+ QGraphicsView view;
+ QGraphicsScene scene(&view);
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ proxy->setEnabled(true);
+ scene.addItem(proxy);
+ proxy->setVisible(true);
+ view.show();
+
+ proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // <- shouldn't need to do this
+ QFocusEvent event(QEvent::FocusIn, Qt::TabFocusReason);
+ event.ignore();
+ //should not crash
+ proxy->call_focusInEvent(&event);
+}
+
+void tst_QGraphicsProxyWidget::focusNextPrevChild_data()
+{
+ QTest::addColumn<bool>("hasWidget");
+ QTest::addColumn<bool>("hasScene");
+ QTest::addColumn<bool>("next");
+ QTest::addColumn<bool>("focusNextPrevChild");
+
+ for (int i = 0; i < 2; ++i) {
+ for (int j = 0; j < 2; ++j) {
+ for (int k = 0; k < 2; ++k) {
+ bool next = (i == 0);
+ bool hasWidget = (j == 0);
+ bool hasScene = (k == 0);
+ bool result = hasScene && hasWidget;
+ QString name = QString("Forward: %1, hasWidget: %2, hasScene: %3, result: %4").arg(next).arg(hasWidget).arg(hasScene).arg(result);
+ QTest::newRow(name.toLatin1()) << hasWidget << hasScene << next << result;
+ }
+ }
+ }
+}
+
+// protected bool focusNextPrevChild(bool next)
+void tst_QGraphicsProxyWidget::focusNextPrevChild()
+{
+ QFETCH(bool, next);
+ QFETCH(bool, focusNextPrevChild);
+ QFETCH(bool, hasWidget);
+ QFETCH(bool, hasScene);
+
+ // If a widget has its own focusNextPrevChild we need to respect it
+ // otherwise respect the scene
+ // Respect the widget over the scene!
+
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+
+ QLabel *widget = new QLabel;
+ // I can't believe designer adds this much junk!
+ widget->setText("<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\"> p, li { white-space: pre-wrap; } </style></head><body style=\" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;\"> <p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><a href=\"http://www.slashdot.org\"><span style=\" text-decoration: underline; color:#0000ff;\">old</span></a> foo <a href=\"http://www.reddit.org\"><span style=\" text-decoration: underline; color:#0000ff;\">new</span></a></p></body></html>");
+ widget->setTextInteractionFlags(Qt::TextBrowserInteraction);
+
+ if (hasWidget)
+ proxy->setWidget(widget);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
+ if (hasScene) {
+ scene.addItem(proxy);
+ proxy->show();
+
+ // widget should take precedence over scene so make scene.focusNextPrevChild return false
+ // so we know that a true can only come from the widget
+ if (!(hasWidget && hasScene)) {
+ QGraphicsTextItem *item = new QGraphicsTextItem("Foo");
+ item->setTextInteractionFlags(Qt::TextBrowserInteraction);
+ scene.addItem(item);
+ item->setPos(50, 40);
+ }
+ scene.setFocusItem(proxy);
+ QVERIFY(proxy->hasFocus());
+ }
+
+ QCOMPARE(proxy->call_focusNextPrevChild(next), focusNextPrevChild);
+
+ if (!hasScene)
+ delete proxy;
+}
+
+void tst_QGraphicsProxyWidget::focusOutEvent_data()
+{
+ QTest::addColumn<bool>("hasWidget");
+ QTest::addColumn<bool>("call");
+ QTest::newRow("no widget, focus to other widget") << false << false;
+ QTest::newRow("no widget, focusOutCalled") << false << true;
+ QTest::newRow("widget, focus to other widget") << true << false;
+ QTest::newRow("widget, focusOutCalled") << true << true;
+}
+
+// protected void focusOutEvent(QFocusEvent* event)
+void tst_QGraphicsProxyWidget::focusOutEvent()
+{
+ QFETCH(bool, hasWidget);
+ QFETCH(bool, call);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ scene.addItem(proxy);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ view.activateWindow();
+ view.setFocus();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.isVisible());
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
+
+ QWidget *widget = new QWidget;
+ widget->setFocusPolicy(Qt::WheelFocus);
+ if (hasWidget)
+ proxy->setWidget(widget);
+ proxy->show();
+ proxy->setFocus();
+ QVERIFY(proxy->hasFocus());
+ QEXPECT_FAIL("widget, focus to other widget", "Widget should have focus but doesn't", Continue);
+ QEXPECT_FAIL("widget, focusOutCalled", "Widget should have focus but doesn't", Continue);
+ QCOMPARE(widget->hasFocus(), hasWidget);
+
+ if (!call) {
+ QWidget *other = new QLineEdit(&view);
+ other->show();
+ QApplication::processEvents();
+ QTRY_VERIFY(other->isVisible());
+ other->setFocus();
+ QTRY_VERIFY(other->hasFocus());
+ qApp->processEvents();
+ QTRY_COMPARE(proxy->hasFocus(), false);
+ QVERIFY(proxy->focusOut);
+ QCOMPARE(widget->hasFocus(), false);
+ } else {
+ {
+ /*
+ ### Test doesn't make sense
+ QFocusEvent focusEvent(QEvent::FocusOut);
+ proxy->call_focusOutEvent(&focusEvent);
+ QCOMPARE(focusEvent.isAccepted(), hasWidget);
+ qApp->processEvents();
+ QCOMPARE(proxy->paintCount, hasWidget ? 1 : 0);
+ */
+ }
+ {
+ /*
+ ### Test doesn't make sense
+ proxy->setFlag(QGraphicsItem::ItemIsFocusable, false);
+ QFocusEvent focusEvent(QEvent::FocusOut);
+ proxy->call_focusOutEvent(&focusEvent);
+ QCOMPARE(focusEvent.isAccepted(), hasWidget);
+ qApp->processEvents();
+ QCOMPARE(proxy->paintCount, 0);
+ */
+ }
+ }
+}
+
+class EventLogger : public QWidget
+{
+public:
+ EventLogger() : QWidget(), enterCount(0), leaveCount(0), moveCount(0),
+ hoverEnter(0), hoverLeave(0), hoverMove(0)
+ {
+ installEventFilter(this);
+ }
+
+ void enterEvent(QEvent *event)
+ {
+ enterCount++;
+ QWidget::enterEvent(event);
+ }
+
+ void leaveEvent(QEvent *event )
+ {
+ leaveCount++;
+ QWidget::leaveEvent(event);
+ }
+
+ void mouseMoveEvent(QMouseEvent *event)
+ {
+ event->setAccepted(true);
+ moveCount++;
+ QWidget::mouseMoveEvent(event);
+ }
+
+ int enterCount;
+ int leaveCount;
+ int moveCount;
+
+ int hoverEnter;
+ int hoverLeave;
+ int hoverMove;
+protected:
+ bool eventFilter(QObject *object, QEvent *event)
+ {
+ switch (event->type()) {
+ case QEvent::HoverEnter:
+ hoverEnter++;
+ break;
+ case QEvent::HoverLeave:
+ hoverLeave++;
+ break;
+ case QEvent::HoverMove:
+ hoverMove++;
+ break;
+ default:
+ break;
+ }
+ return QWidget::eventFilter(object, event);
+ }
+};
+
+// protected void hoverEnterEvent(QGraphicsSceneHoverEvent* event)
+#if !defined(Q_OS_WINCE) || (defined(GWES_ICONCURS) && !defined(QT_NO_CURSOR))
+void tst_QGraphicsProxyWidget::hoverEnterLeaveEvent_data()
+{
+ QTest::addColumn<bool>("hasWidget");
+ QTest::addColumn<bool>("hoverEnabled");
+ QTest::newRow("widget, no hover") << true << false;
+ QTest::newRow("no widget, no hover") << false << false;
+ QTest::newRow("widget, hover") << true << true;
+ QTest::newRow("no widget, hover") << false << true;
+}
+
+void tst_QGraphicsProxyWidget::hoverEnterLeaveEvent()
+{
+ QFETCH(bool, hasWidget);
+ QFETCH(bool, hoverEnabled);
+
+ // proxy should translate this into events that the widget would expect
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ //do not let the window manager move the window while we are moving the mouse on it
+ view.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ EventLogger *widget = new EventLogger;
+ widget->resize(50, 50);
+ widget->setAttribute(Qt::WA_Hover, hoverEnabled);
+ widget->setMouseTracking(true);
+ view.resize(100, 100);
+ if (hasWidget)
+ proxy->setWidget(widget);
+ proxy->setPos(50, 0);
+ scene.addItem(proxy);
+ QTest::qWait(30);
+ QTest::mouseMove(&view, QPoint(10, 10));
+ QTest::qWait(30);
+
+ // in
+ QTest::mouseMove(&view, QPoint(50, 50));
+ QTRY_COMPARE(widget->testAttribute(Qt::WA_UnderMouse), hasWidget ? true : false);
+ // ### this attribute isn't supported
+ QCOMPARE(widget->enterCount, hasWidget ? 1 : 0);
+ QCOMPARE(widget->hoverEnter, (hasWidget && hoverEnabled) ? 1 : 0);
+ // does not work on all platforms
+ //QCOMPARE(widget->moveCount, 0);
+
+ // out
+ QTest::mouseMove(&view, QPoint(10, 10));
+ // QTRY_COMPARE(widget->testAttribute(Qt::WA_UnderMouse), false);
+ // ### this attribute isn't supported
+ QTRY_COMPARE(widget->leaveCount, hasWidget ? 1 : 0);
+ QTRY_COMPARE(widget->hoverLeave, (hasWidget && hoverEnabled) ? 1 : 0);
+ // does not work on all platforms
+ //QCOMPARE(widget->moveCount, 0);
+
+ if (!hasWidget)
+ delete widget;
+}
+#endif
+
+void tst_QGraphicsProxyWidget::hoverMoveEvent_data()
+{
+ QTest::addColumn<bool>("hasWidget");
+ QTest::addColumn<bool>("hoverEnabled");
+ QTest::addColumn<bool>("mouseTracking");
+ QTest::addColumn<bool>("mouseDown");
+ for (int i = 0; i < 2; ++i) {
+ for (int j = 0; j < 2; ++j) {
+ for (int k = 0; k < 2; ++k) {
+ for (int l = 0; l < 2; ++l) {
+ bool hasWidget = (i == 0);
+ bool hoverEnabled = (j == 0);
+ bool mouseTracking = (k == 0);
+ bool mouseDown = (l == 0);
+ QString name = QString("hasWidget:%1, hover:%2, mouseTracking:%3, mouseDown: %4").arg(hasWidget).arg(hoverEnabled).arg(mouseTracking).arg(mouseDown);
+ QTest::newRow(name.toLatin1()) << hasWidget << hoverEnabled << mouseTracking << mouseDown;
+ }
+ }
+ }
+ }
+}
+
+// protected void hoverMoveEvent(QGraphicsSceneHoverEvent* event)
+void tst_QGraphicsProxyWidget::hoverMoveEvent()
+{
+ QFETCH(bool, hasWidget);
+ QFETCH(bool, hoverEnabled);
+ QFETCH(bool, mouseTracking);
+ QFETCH(bool, mouseDown);
+
+ QSKIP("Ambiguous test...", SkipAll);
+
+ // proxy should translate the move events to what the widget would expect
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // ### remove me!!!
+ EventLogger *widget = new EventLogger;
+ widget->resize(50, 50);
+ widget->setAttribute(Qt::WA_Hover, hoverEnabled);
+ if (mouseTracking)
+ widget->setMouseTracking(true);
+ view.resize(100, 100);
+ if (hasWidget)
+ proxy->setWidget(widget);
+ proxy->setPos(50, 0);
+ scene.addItem(proxy);
+
+ // in
+ QTest::mouseMove(&view, QPoint(50, 50));
+ QTest::qWait(12);
+
+ if (mouseDown)
+ QTest::mousePress(view.viewport(), Qt::LeftButton);
+
+ // move a little bit
+ QTest::mouseMove(&view, QPoint(60, 60));
+ QTRY_COMPARE(widget->hoverEnter, (hasWidget && hoverEnabled) ? 1 : 0);
+ QCOMPARE(widget->moveCount, (hasWidget && mouseTracking) || (hasWidget && mouseDown) ? 1 : 0);
+
+ if (!hasWidget)
+ delete widget;
+}
+
+void tst_QGraphicsProxyWidget::keyPressEvent_data()
+{
+ QTest::addColumn<bool>("hasWidget");
+ QTest::newRow("widget") << true;
+ QTest::newRow("no widget") << false;
+}
+
+// protected void keyPressEvent(QKeyEvent* event)
+void tst_QGraphicsProxyWidget::keyPressEvent()
+{
+ QFETCH(bool, hasWidget);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+ view.viewport()->setFocus();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
+
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // ### remove me!!!
+
+ QLineEdit *widget = new QLineEdit;
+ widget->resize(50, 50);
+ view.resize(100, 100);
+ if (hasWidget) {
+ proxy->setWidget(widget);
+ proxy->show();
+ }
+ proxy->setPos(50, 0);
+ scene.addItem(proxy);
+ proxy->setFocus();
+
+ QTest::keyPress(view.viewport(), 'x');
+
+ QTRY_COMPARE(widget->text(), hasWidget ? QString("x") : QString());
+
+ if (!hasWidget)
+ delete widget;
+}
+
+void tst_QGraphicsProxyWidget::keyReleaseEvent_data()
+{
+ QTest::addColumn<bool>("hasWidget");
+ QTest::newRow("widget") << true;
+ QTest::newRow("no widget") << false;
+}
+
+// protected void keyReleaseEvent(QKeyEvent* event)
+void tst_QGraphicsProxyWidget::keyReleaseEvent()
+{
+ QFETCH(bool, hasWidget);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
+
+
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // ### remove me!!!
+ QPushButton *widget = new QPushButton;
+ QSignalSpy spy(widget, SIGNAL(clicked()));
+ widget->resize(50, 50);
+ view.resize(100, 100);
+ if (hasWidget) {
+ proxy->setWidget(widget);
+ proxy->show();
+ }
+ proxy->setPos(50, 0);
+ scene.addItem(proxy);
+ proxy->setFocus();
+
+ QTest::keyPress(view.viewport(), Qt::Key_Space);
+ QTRY_COMPARE(spy.count(), 0);
+ QTest::keyRelease(view.viewport(), Qt::Key_Space);
+ QTRY_COMPARE(spy.count(), (hasWidget) ? 1 : 0);
+
+ if (!hasWidget)
+ delete widget;
+}
+
+void tst_QGraphicsProxyWidget::mouseDoubleClickEvent_data()
+{
+ QTest::addColumn<bool>("hasWidget");
+ QTest::newRow("widget") << true;
+ QTest::newRow("no widget") << false;
+}
+
+// protected void mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
+void tst_QGraphicsProxyWidget::mouseDoubleClickEvent()
+{
+ QFETCH(bool, hasWidget);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
+
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // ### remove me!!!
+ QLineEdit *widget = new QLineEdit;
+ widget->setText("foo");
+ widget->resize(50, 50);
+ view.resize(100, 100);
+ if (hasWidget) {
+ proxy->setWidget(widget);
+ proxy->show();
+ }
+ proxy->setPos(50, 0);
+ scene.addItem(proxy);
+ proxy->setFocus();
+
+ QTest::mouseMove(view.viewport(), view.mapFromScene(proxy->mapToScene(15, proxy->boundingRect().center().y())));
+ QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(proxy->mapToScene(15, proxy->boundingRect().center().y())));
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(proxy->mapToScene(15, proxy->boundingRect().center().y())));
+ QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(proxy->mapToScene(15, proxy->boundingRect().center().y())));
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(proxy->mapToScene(15, proxy->boundingRect().center().y())));
+
+ QTRY_COMPARE(widget->selectedText(), hasWidget ? QString("foo") : QString());
+
+ if (!hasWidget)
+ delete widget;
+}
+
+void tst_QGraphicsProxyWidget::mousePressReleaseEvent_data()
+{
+ QTest::addColumn<bool>("hasWidget");
+ QTest::newRow("widget") << true;
+ QTest::newRow("no widget") << false;
+}
+
+// protected void mousePressEvent(QGraphicsSceneMouseEvent* event)
+void tst_QGraphicsProxyWidget::mousePressReleaseEvent()
+{
+ QFETCH(bool, hasWidget);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // ### remove me!!!
+ QPushButton *widget = new QPushButton;
+ QSignalSpy spy(widget, SIGNAL(clicked()));
+ widget->resize(50, 50);
+ view.resize(100, 100);
+ if (hasWidget) {
+ proxy->setWidget(widget);
+ proxy->show();
+ }
+ proxy->setPos(50, 0);
+ scene.addItem(proxy);
+ proxy->setFocus();
+
+ QTest::mousePress(view.viewport(), Qt::LeftButton, 0,
+ view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center())));
+ QTRY_COMPARE(spy.count(), 0);
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0,
+ view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center())));
+ QTRY_COMPARE(spy.count(), (hasWidget) ? 1 : 0);
+
+ if (!hasWidget)
+ delete widget;
+}
+
+void tst_QGraphicsProxyWidget::resizeEvent_data()
+{
+ QTest::addColumn<bool>("hasWidget");
+ QTest::newRow("widget") << true;
+ QTest::newRow("no widget") << false;
+}
+
+// protected void resizeEvent(QGraphicsSceneResizeEvent* event)
+void tst_QGraphicsProxyWidget::resizeEvent()
+{
+ QFETCH(bool, hasWidget);
+
+ SubQGraphicsProxyWidget proxy;
+ QWidget *widget = new QWidget;
+ if (hasWidget)
+ proxy.setWidget(widget);
+
+ QSize newSize(100, 100);
+ QGraphicsSceneResizeEvent event;
+ event.setOldSize(QSize(10, 10));
+ event.setNewSize(newSize);
+ proxy.call_resizeEvent(&event);
+ if (hasWidget)
+ QCOMPARE(widget->size(), newSize);
+ if (!hasWidget)
+ delete widget;
+}
+
+void tst_QGraphicsProxyWidget::paintEvent()
+{
+ //we test that calling update on a widget inside a QGraphicsView is triggering a repaint
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.isActiveWindow());
+
+ SubQGraphicsProxyWidget proxy;
+
+ QWidget *w = new QWidget;
+ //showing the widget here seems to create a bug in Graphics View
+ //this bug prevents the widget from being updated
+
+ w->show();
+ QTest::qWaitForWindowShown(w);
+ QApplication::processEvents();
+ QTest::qWait(30);
+ proxy.setWidget(w);
+ scene.addItem(&proxy);
+
+ //make sure we flush all the paint events
+ QTRY_VERIFY(proxy.paintCount > 1);
+ QTest::qWait(30);
+ proxy.paintCount = 0;
+
+ w->update();
+ QTRY_COMPARE(proxy.paintCount, 1); //the widget should have been painted now
+}
+
+
+void tst_QGraphicsProxyWidget::wheelEvent()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+
+ WheelWidget *wheelWidget = new WheelWidget();
+ wheelWidget->setFixedSize(400, 400);
+
+ QGraphicsProxyWidget *proxy = scene.addWidget(wheelWidget);
+ proxy->setVisible(true);
+
+ QGraphicsSceneWheelEvent event(QEvent::GraphicsSceneWheel);
+ event.setScenePos(QPoint(50, 50));
+ event.setAccepted(false);
+ wheelWidget->wheelEventCalled = false;
+
+ QApplication::sendEvent(&scene, &event);
+
+ QVERIFY(event.isAccepted());
+ QVERIFY(wheelWidget->wheelEventCalled);
+}
+
+Q_DECLARE_METATYPE(Qt::SizeHint)
+void tst_QGraphicsProxyWidget::sizeHint_data()
+{
+ QTest::addColumn<Qt::SizeHint>("which");
+ QTest::addColumn<QSizeF>("constraint");
+ QTest::addColumn<QSizeF>("sizeHint");
+ QTest::addColumn<bool>("hasWidget");
+
+ for (int i = 0; i < 2; ++i) {
+ bool hasWidget = (i == 0);
+ // ### What should these do?
+ QTest::newRow("min") << Qt::MinimumSize << QSizeF() << QSizeF() << hasWidget;
+ QTest::newRow("pre") << Qt::PreferredSize << QSizeF() << QSizeF() << hasWidget;
+ QTest::newRow("max") << Qt::MaximumSize << QSizeF() << QSizeF() << hasWidget;
+ QTest::newRow("mindes") << Qt::MinimumDescent << QSizeF() << QSizeF() << hasWidget;
+ QTest::newRow("nsize") << Qt::NSizeHints << QSizeF() << QSizeF() << hasWidget;
+ }
+}
+
+// protected QSizeF sizeHint(Qt::SizeHint which, QSizeF const& constraint = QSizeF()) const
+void tst_QGraphicsProxyWidget::sizeHint()
+{
+ QFETCH(Qt::SizeHint, which);
+ QFETCH(QSizeF, constraint);
+ QFETCH(QSizeF, sizeHint);
+ QFETCH(bool, hasWidget);
+ QSKIP("Broken test", SkipAll);
+ SubQGraphicsProxyWidget proxy;
+ QWidget *widget = new QWidget;
+ if (hasWidget)
+ proxy.setWidget(widget);
+ QCOMPARE(proxy.call_sizeHint(which, constraint), sizeHint);
+ if (!hasWidget)
+ delete widget;
+}
+
+void tst_QGraphicsProxyWidget::sizePolicy()
+{
+ for (int p = 0; p < 2; ++p) {
+ bool hasWidget = (p == 0 ? true : false);
+ SubQGraphicsProxyWidget proxy;
+ QWidget *widget = new QWidget;
+ QSizePolicy proxyPol(QSizePolicy::Maximum, QSizePolicy::Expanding);
+ proxy.setSizePolicy(proxyPol);
+ QSizePolicy widgetPol(QSizePolicy::Fixed, QSizePolicy::Minimum);
+ widget->setSizePolicy(widgetPol);
+
+ QCOMPARE(proxy.sizePolicy(), proxyPol);
+ QCOMPARE(widget->sizePolicy(), widgetPol);
+ if (hasWidget) {
+ proxy.setWidget(widget);
+ QCOMPARE(proxy.sizePolicy(), widgetPol);
+ } else {
+ QCOMPARE(proxy.sizePolicy(), proxyPol);
+ }
+ QCOMPARE(widget->sizePolicy(), widgetPol);
+
+ proxy.setSizePolicy(widgetPol);
+ widget->setSizePolicy(proxyPol);
+ if (hasWidget)
+ QCOMPARE(proxy.sizePolicy(), proxyPol);
+ else
+ QCOMPARE(proxy.sizePolicy(), widgetPol);
+ }
+}
+
+void tst_QGraphicsProxyWidget::minimumSize()
+{
+ SubQGraphicsProxyWidget proxy;
+ QWidget *widget = new QWidget;
+ QSize minSize(50, 50);
+ widget->setMinimumSize(minSize);
+ proxy.resize(30, 30);
+ widget->resize(30,30);
+ QCOMPARE(proxy.size(), QSizeF(30, 30));
+ proxy.setWidget(widget);
+ QCOMPARE(proxy.size().toSize(), minSize);
+ QCOMPARE(proxy.minimumSize().toSize(), minSize);
+ widget->setMinimumSize(70, 70);
+ QCOMPARE(proxy.minimumSize(), QSizeF(70, 70));
+ QCOMPARE(proxy.size(), QSizeF(70, 70));
+}
+
+void tst_QGraphicsProxyWidget::maximumSize()
+{
+ SubQGraphicsProxyWidget proxy;
+ QWidget *widget = new QWidget;
+ QSize maxSize(150, 150);
+ widget->setMaximumSize(maxSize);
+ proxy.resize(200, 200);
+ widget->resize(200,200);
+ QCOMPARE(proxy.size(), QSizeF(200, 200));
+ proxy.setWidget(widget);
+ QCOMPARE(proxy.size().toSize(), maxSize);
+ QCOMPARE(proxy.maximumSize().toSize(), maxSize);
+ widget->setMaximumSize(70, 70);
+ QCOMPARE(proxy.maximumSize(), QSizeF(70, 70));
+ QCOMPARE(proxy.size(), QSizeF(70, 70));
+}
+
+class View : public QGraphicsView
+{
+public:
+ View(QGraphicsScene *scene, QWidget *parent = 0)
+ : QGraphicsView(scene, parent), npaints(0)
+ { }
+ QRegion paintEventRegion;
+ int npaints;
+protected:
+ void paintEvent(QPaintEvent *event)
+ {
+ ++npaints;
+ paintEventRegion += event->region();
+ QGraphicsView::paintEvent(event);
+ }
+};
+
+class ScrollWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ ScrollWidget() : npaints(0)
+ {
+ resize(200, 200);
+ }
+ QRegion paintEventRegion;
+ int npaints;
+
+public slots:
+ void updateScroll()
+ {
+ update(0, 0, 200, 10);
+ scroll(0, 10, QRect(0, 0, 100, 20));
+ }
+
+protected:
+ void paintEvent(QPaintEvent *event)
+ {
+ ++npaints;
+ paintEventRegion += event->region();
+ QPainter painter(this);
+ painter.fillRect(event->rect(), Qt::blue);
+ }
+};
+
+void tst_QGraphicsProxyWidget::scrollUpdate()
+{
+ ScrollWidget *widget = new ScrollWidget;
+
+ QGraphicsScene scene;
+ scene.addWidget(widget);
+
+ View view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.npaints >= 1);
+ QTest::qWait(20);
+ widget->paintEventRegion = QRegion();
+ widget->npaints = 0;
+ view.paintEventRegion = QRegion();
+ view.npaints = 0;
+ QTimer::singleShot(0, widget, SLOT(updateScroll()));
+ QTRY_COMPARE(view.npaints, 2);
+ // QRect(0, 0, 200, 12) is the first update, expanded (-2, -2, 2, 2)
+ // QRect(0, 12, 102, 10) is the scroll update, expanded (-2, -2, 2, 2),
+ // intersected with the above update.
+ QCOMPARE(view.paintEventRegion.rects(),
+ QVector<QRect>() << QRect(0, 0, 200, 12) << QRect(0, 12, 102, 10));
+ QCOMPARE(widget->npaints, 2);
+ QCOMPARE(widget->paintEventRegion.rects(),
+ QVector<QRect>() << QRect(0, 0, 200, 12) << QRect(0, 12, 102, 10));
+}
+
+void tst_QGraphicsProxyWidget::setWidget_simple()
+{
+ QGraphicsProxyWidget proxy;
+ QLineEdit *lineEdit = new QLineEdit;
+ proxy.setWidget(lineEdit);
+
+ QVERIFY(lineEdit->testAttribute(Qt::WA_DontShowOnScreen));
+ // Size hints
+ // ### size hints are tested in a different test
+ // QCOMPARE(proxy.effectiveSizeHint(Qt::MinimumSize).toSize(), lineEdit->minimumSizeHint());
+ // QCOMPARE(proxy.effectiveSizeHint(Qt::MaximumSize).toSize(), lineEdit->maximumSize());
+ // QCOMPARE(proxy.effectiveSizeHint(Qt::PreferredSize).toSize(), lineEdit->sizeHint());
+ QCOMPARE(proxy.size().toSize(), lineEdit->minimumSizeHint().expandedTo(lineEdit->size()));
+ QRect rect = lineEdit->rect();
+ rect.setSize(rect.size().expandedTo(lineEdit->minimumSizeHint()));
+ QCOMPARE(proxy.rect().toRect(), rect);
+
+ // Properties
+ // QCOMPARE(proxy.focusPolicy(), lineEdit->focusPolicy());
+ // QCOMPARE(proxy.palette(), lineEdit->palette());
+#ifndef QT_NO_CURSOR
+ QCOMPARE(proxy.cursor().shape(), lineEdit->cursor().shape());
+#endif
+ QCOMPARE(proxy.layoutDirection(), lineEdit->layoutDirection());
+ QCOMPARE(proxy.style(), lineEdit->style());
+ QCOMPARE(proxy.font(), lineEdit->font());
+ QCOMPARE(proxy.isEnabled(), lineEdit->isEnabled());
+ QCOMPARE(proxy.isVisible(), lineEdit->isVisible());
+}
+
+void tst_QGraphicsProxyWidget::setWidget_ownership()
+{
+ QPointer<QLineEdit> lineEdit = new QLineEdit;
+ QPointer<QLineEdit> lineEdit2 = new QLineEdit;
+ QVERIFY(lineEdit);
+ {
+ // Create a proxy and transfer ownership to it
+ QGraphicsProxyWidget proxy;
+ proxy.setWidget(lineEdit);
+ QCOMPARE(proxy.widget(), (QWidget *)lineEdit);
+
+ // Remove the widget without destroying it.
+ proxy.setWidget(0);
+ QVERIFY(!proxy.widget());
+ QVERIFY(lineEdit);
+
+ // Assign the widget again and switch to another widget.
+ proxy.setWidget(lineEdit);
+ proxy.setWidget(lineEdit2);
+ QCOMPARE(proxy.widget(), (QWidget *)lineEdit2);
+
+ // Assign the first widget, and destroy the proxy.
+ proxy.setWidget(lineEdit);
+ }
+ QVERIFY(!lineEdit);
+ QVERIFY(lineEdit2);
+
+ QGraphicsScene scene;
+ QPointer<QGraphicsProxyWidget> proxy = scene.addWidget(lineEdit2);
+
+ delete lineEdit2;
+ QVERIFY(!proxy);
+}
+
+void tst_QGraphicsProxyWidget::resize_simple_data()
+{
+ QTest::addColumn<QSizeF>("size");
+
+ QTest::newRow("200, 200") << QSizeF(200, 200);
+#if !defined(QT_ARCH_ARM) && !defined(Q_OS_WINCE)
+ QTest::newRow("1000, 1000") << QSizeF(1000, 1000);
+ // Since 4.5, 10000x10000 runs out of memory.
+ // QTest::newRow("10000, 10000") << QSizeF(10000, 10000);
+#endif
+}
+
+void tst_QGraphicsProxyWidget::resize_simple()
+{
+ QFETCH(QSizeF, size);
+
+ QGraphicsProxyWidget proxy;
+ QWidget *widget = new QWidget;
+ widget->setGeometry(0, 0, (int)size.width(), (int)size.height());
+ proxy.setWidget(widget);
+ widget->show();
+ QCOMPARE(widget->pos(), QPoint());
+
+ // The proxy resizes itself, the line edit follows
+ proxy.resize(size);
+ QCOMPARE(proxy.size(), size);
+ QCOMPARE(proxy.size().toSize(), widget->size());
+
+ // The line edit resizes itself, the proxy follows (no loopback/live lock)
+ QSize doubleSize = size.toSize() * 2;
+ widget->resize(doubleSize);
+ QCOMPARE(widget->size(), doubleSize);
+ QCOMPARE(widget->size(), proxy.size().toSize());
+}
+
+void tst_QGraphicsProxyWidget::symmetricMove()
+{
+ QGraphicsProxyWidget proxy;
+ QLineEdit *lineEdit = new QLineEdit;
+ proxy.setWidget(lineEdit);
+ lineEdit->show();
+
+ proxy.setPos(10, 10);
+ QCOMPARE(proxy.pos(), QPointF(10, 10));
+ QCOMPARE(lineEdit->pos(), QPoint(10, 10));
+
+ lineEdit->move(5, 5);
+ QCOMPARE(proxy.pos(), QPointF(5, 5));
+ QCOMPARE(lineEdit->pos(), QPoint(5, 5));
+}
+
+void tst_QGraphicsProxyWidget::symmetricResize()
+{
+ QGraphicsProxyWidget proxy;
+ QLineEdit *lineEdit = new QLineEdit;
+ proxy.setWidget(lineEdit);
+ lineEdit->show();
+
+ proxy.resize(256, 256);
+ QCOMPARE(proxy.size(), QSizeF(256, 256));
+ QCOMPARE(lineEdit->size(), QSize(256, 256));
+
+ lineEdit->resize(512, 512);
+ QCOMPARE(proxy.size(), QSizeF(512, 512));
+ QCOMPARE(lineEdit->size(), QSize(512, 512));
+}
+
+void tst_QGraphicsProxyWidget::symmetricVisible()
+{
+ QGraphicsProxyWidget proxy;
+ QLineEdit *lineEdit = new QLineEdit;
+ proxy.setWidget(lineEdit);
+ lineEdit->show();
+
+ QCOMPARE(proxy.isVisible(), lineEdit->isVisible());
+
+ proxy.hide();
+ QCOMPARE(proxy.isVisible(), lineEdit->isVisible());
+ proxy.show();
+ QCOMPARE(proxy.isVisible(), lineEdit->isVisible());
+ lineEdit->hide();
+ QCOMPARE(proxy.isVisible(), lineEdit->isVisible());
+ lineEdit->show();
+ QCOMPARE(proxy.isVisible(), lineEdit->isVisible());
+ }
+
+void tst_QGraphicsProxyWidget::symmetricEnabled()
+{
+ QGraphicsProxyWidget proxy;
+ QLineEdit *lineEdit = new QLineEdit;
+ proxy.setWidget(lineEdit);
+ lineEdit->show();
+
+ QCOMPARE(proxy.isEnabled(), lineEdit->isEnabled());
+ proxy.setEnabled(false);
+ QCOMPARE(proxy.isEnabled(), lineEdit->isEnabled());
+ proxy.setEnabled(true);
+ QCOMPARE(proxy.isEnabled(), lineEdit->isEnabled());
+ lineEdit->setEnabled(false);
+ QCOMPARE(proxy.isEnabled(), lineEdit->isEnabled());
+ lineEdit->setEnabled(true);
+ QCOMPARE(proxy.isEnabled(), lineEdit->isEnabled());
+}
+
+void tst_QGraphicsProxyWidget::tabFocus_simpleWidget()
+{
+ QGraphicsScene scene;
+ QLineEdit *edit = new QLineEdit;
+ QGraphicsProxyWidget *editProxy = scene.addWidget(edit);
+ editProxy->show();
+
+ QDial *leftDial = new QDial;
+ QDial *rightDial = new QDial;
+ QGraphicsView *view = new QGraphicsView(&scene);
+
+ QWidget window;
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(leftDial);
+ layout->addWidget(view);
+ layout->addWidget(rightDial);
+ window.setLayout(layout);
+
+ window.show();
+ QApplication::setActiveWindow(&window);
+ window.activateWindow();
+ QTest::qWaitForWindowShown(&window);
+
+ leftDial->setFocus();
+ QApplication::processEvents();
+ QTRY_VERIFY(leftDial->hasFocus());
+
+ EventSpy eventSpy(edit);
+
+ // Tab into line edit
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QTRY_VERIFY(!leftDial->hasFocus());
+ QTRY_VERIFY(view->hasFocus());
+ QVERIFY(view->viewport()->hasFocus());
+ QVERIFY(scene.hasFocus());
+ QVERIFY(editProxy->hasFocus());
+ QVERIFY(edit->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 0);
+
+ // Tab into right dial
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QTRY_VERIFY(!view->hasFocus());
+ QVERIFY(!view->viewport()->hasFocus());
+ QVERIFY(!scene.hasFocus());
+ QVERIFY(!editProxy->hasFocus());
+ QVERIFY(!edit->hasFocus());
+ QTRY_VERIFY(rightDial->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
+
+ // Backtab into line edit
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QTRY_VERIFY(view->hasFocus());
+ QVERIFY(view->viewport()->hasFocus());
+ QTRY_VERIFY(scene.hasFocus());
+ QVERIFY(editProxy->hasFocus());
+ QVERIFY(edit->hasFocus());
+ QVERIFY(!rightDial->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 2);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
+
+ // Backtab into left dial
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QTRY_VERIFY(!view->hasFocus());
+ QVERIFY(!view->viewport()->hasFocus());
+ QVERIFY(!scene.hasFocus());
+ QVERIFY(!editProxy->hasFocus());
+ QVERIFY(!edit->hasFocus());
+ QTRY_VERIFY(leftDial->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 2);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 2);
+
+ delete view;
+}
+
+void tst_QGraphicsProxyWidget::tabFocus_simpleTwoWidgets()
+{
+ QGraphicsScene scene;
+ QLineEdit *edit = new QLineEdit;
+ QLineEdit *edit2 = new QLineEdit;
+ QGraphicsProxyWidget *editProxy = scene.addWidget(edit);
+ editProxy->show();
+ QGraphicsProxyWidget *editProxy2 = scene.addWidget(edit2);
+ editProxy2->show();
+ editProxy2->setPos(0, editProxy->rect().height() * 1.1);
+
+ QDial *leftDial = new QDial;
+ QDial *rightDial = new QDial;
+ QGraphicsView *view = new QGraphicsView(&scene);
+
+ QWidget window;
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(leftDial);
+ layout->addWidget(view);
+ layout->addWidget(rightDial);
+ window.setLayout(layout);
+
+ window.show();
+ QApplication::setActiveWindow(&window);
+ window.activateWindow();
+ QTest::qWaitForWindowShown(&window);
+
+ leftDial->setFocus();
+ QApplication::processEvents();
+ QTRY_VERIFY(leftDial->hasFocus());
+
+ EventSpy eventSpy(edit);
+ EventSpy eventSpy2(edit2);
+
+ // Tab into line edit
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QVERIFY(!leftDial->hasFocus());
+ QVERIFY(view->hasFocus());
+ QVERIFY(view->viewport()->hasFocus());
+ QVERIFY(scene.hasFocus());
+ QVERIFY(editProxy->hasFocus());
+ QVERIFY(edit->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 0);
+
+ // Tab into second line edit
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QVERIFY(view->hasFocus());
+ QVERIFY(view->viewport()->hasFocus());
+ QVERIFY(scene.hasFocus());
+ QVERIFY(!editProxy->hasFocus());
+ QVERIFY(!edit->hasFocus());
+ QVERIFY(editProxy2->hasFocus());
+ QVERIFY(edit2->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 0);
+
+ // Tab into right dial
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QVERIFY(!view->hasFocus());
+ QVERIFY(!view->viewport()->hasFocus());
+ QVERIFY(!scene.hasFocus());
+ QVERIFY(!editProxy->hasFocus());
+ QVERIFY(!edit->hasFocus());
+ QVERIFY(!editProxy2->hasFocus());
+ QVERIFY(!edit2->hasFocus());
+ QVERIFY(rightDial->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 1);
+
+ // Backtab into line edit 2
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(view->hasFocus());
+ QVERIFY(view->viewport()->hasFocus());
+ QVERIFY(scene.hasFocus());
+ QVERIFY(!editProxy->hasFocus());
+ QVERIFY(!edit->hasFocus());
+ QVERIFY(editProxy2->hasFocus());
+ QVERIFY(edit2->hasFocus());
+ QVERIFY(!rightDial->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusIn], 2);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 1);
+
+ // Backtab into line edit 1
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(view->hasFocus());
+ QVERIFY(view->viewport()->hasFocus());
+ QVERIFY(scene.hasFocus());
+ QVERIFY(editProxy->hasFocus());
+ QVERIFY(edit->hasFocus());
+ QVERIFY(!editProxy2->hasFocus());
+ QVERIFY(!edit2->hasFocus());
+ QVERIFY(!rightDial->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 2);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusIn], 2);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 2);
+
+ // Backtab into left dial
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!view->hasFocus());
+ QVERIFY(!view->viewport()->hasFocus());
+ QVERIFY(!scene.hasFocus());
+ QVERIFY(!editProxy->hasFocus());
+ QVERIFY(!edit->hasFocus());
+ QVERIFY(leftDial->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 2);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 2);
+
+ delete view;
+}
+
+void tst_QGraphicsProxyWidget::tabFocus_complexWidget()
+{
+ QGraphicsScene scene;
+
+ QLineEdit *edit1 = new QLineEdit;
+ edit1->setText("QLineEdit 1");
+ QLineEdit *edit2 = new QLineEdit;
+ edit2->setText("QLineEdit 2");
+ QVBoxLayout *vlayout = new QVBoxLayout;
+ vlayout->addWidget(edit1);
+ vlayout->addWidget(edit2);
+
+ QGroupBox *box = new QGroupBox("QGroupBox");
+ box->setCheckable(true);
+ box->setChecked(true);
+ box->setLayout(vlayout);
+
+ QGraphicsProxyWidget *proxy = scene.addWidget(box);
+ proxy->show();
+
+ QDial *leftDial = new QDial;
+ QDial *rightDial = new QDial;
+ QGraphicsView *view = new QGraphicsView(&scene);
+
+ QWidget window;
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(leftDial);
+ layout->addWidget(view);
+ layout->addWidget(rightDial);
+ window.setLayout(layout);
+
+ window.show();
+ QApplication::setActiveWindow(&window);
+ window.activateWindow();
+ QTest::qWaitForWindowShown(&window);
+
+ leftDial->setFocus();
+ QApplication::processEvents();
+ QTRY_VERIFY(leftDial->hasFocus());
+
+ EventSpy eventSpy(edit1);
+ EventSpy eventSpy2(edit2);
+ EventSpy eventSpyBox(box);
+
+ // Tab into group box
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QVERIFY(!leftDial->hasFocus());
+ QVERIFY(view->hasFocus());
+ QVERIFY(view->viewport()->hasFocus());
+ QVERIFY(scene.hasFocus());
+ QVERIFY(proxy->hasFocus());
+ QVERIFY(box->hasFocus());
+
+ // Tab into line edit
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ edit1->hasFocus();
+ QVERIFY(!box->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 0);
+
+ // Tab into line edit 2
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ edit2->hasFocus();
+ QVERIFY(!edit1->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 0);
+
+ // Tab into right dial
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QVERIFY(!edit2->hasFocus());
+ rightDial->hasFocus();
+ QCOMPARE(eventSpy2.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 1);
+
+ // Backtab into line edit 2
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!rightDial->hasFocus());
+ edit2->hasFocus();
+ QCOMPARE(eventSpy2.counts[QEvent::FocusIn], 2);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 1);
+
+ // Backtab into line edit 1
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!edit2->hasFocus());
+ edit1->hasFocus();
+ QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 2);
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 2);
+
+ // Backtab into line box
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!edit1->hasFocus());
+ box->hasFocus();
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 2);
+
+ // Backtab into left dial
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!box->hasFocus());
+ leftDial->hasFocus();
+
+ delete view;
+}
+
+void tst_QGraphicsProxyWidget::tabFocus_complexTwoWidgets()
+{
+ // ### add event spies to this test.
+ QGraphicsScene scene;
+
+ QLineEdit *edit1 = new QLineEdit;
+ edit1->setText("QLineEdit 1");
+ QLineEdit *edit2 = new QLineEdit;
+ edit2->setText("QLineEdit 2");
+ QFontComboBox *fontComboBox = new QFontComboBox;
+ QVBoxLayout *vlayout = new QVBoxLayout;
+ vlayout->addWidget(edit1);
+ vlayout->addWidget(fontComboBox);
+ vlayout->addWidget(edit2);
+
+ QGroupBox *box = new QGroupBox("QGroupBox");
+ box->setCheckable(true);
+ box->setChecked(true);
+ box->setLayout(vlayout);
+
+ QLineEdit *edit1_2 = new QLineEdit;
+ edit1_2->setText("QLineEdit 1_2");
+ QLineEdit *edit2_2 = new QLineEdit;
+ edit2_2->setText("QLineEdit 2_2");
+ QFontComboBox *fontComboBox2 = new QFontComboBox;
+ vlayout = new QVBoxLayout;
+ vlayout->addWidget(edit1_2);
+ vlayout->addWidget(fontComboBox2);
+ vlayout->addWidget(edit2_2);
+
+ QGroupBox *box_2 = new QGroupBox("QGroupBox 2");
+ box_2->setCheckable(true);
+ box_2->setChecked(true);
+ box_2->setLayout(vlayout);
+
+ QGraphicsProxyWidget *proxy = scene.addWidget(box);
+ proxy->show();
+
+ QGraphicsProxyWidget *proxy_2 = scene.addWidget(box_2);
+ proxy_2->setPos(proxy->boundingRect().width() * 1.2, 0);
+ proxy_2->show();
+
+ QDial *leftDial = new QDial;
+ QDial *rightDial = new QDial;
+ QGraphicsView *view = new QGraphicsView(&scene);
+ view->setRenderHint(QPainter::Antialiasing);
+ view->rotate(45);
+ view->scale(0.5, 0.5);
+
+ QWidget window;
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(leftDial);
+ layout->addWidget(view);
+ layout->addWidget(rightDial);
+ window.setLayout(layout);
+
+ window.show();
+ QApplication::setActiveWindow(&window);
+ window.activateWindow();
+ QTest::qWaitForWindowShown(&window);
+ QTRY_COMPARE(QApplication::activeWindow(), &window);
+
+ leftDial->setFocus();
+ QApplication::processEvents();
+ QTRY_VERIFY(leftDial->hasFocus());
+
+ EventSpy eventSpy(edit1);
+ EventSpy eventSpy2(edit2);
+ EventSpy eventSpy3(fontComboBox);
+ EventSpy eventSpy1_2(edit1_2);
+ EventSpy eventSpy2_2(edit2_2);
+ EventSpy eventSpy2_3(fontComboBox2);
+ EventSpy eventSpyBox(box);
+
+ // Tab into group box
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QVERIFY(!leftDial->hasFocus());
+ QVERIFY(view->hasFocus());
+ QVERIFY(view->viewport()->hasFocus());
+ QVERIFY(scene.hasFocus());
+ QVERIFY(proxy->hasFocus());
+ QVERIFY(box->hasFocus());
+
+ // Tab into line edit
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ edit1->hasFocus();
+ QVERIFY(!box->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 0);
+
+ // Tab to the font combobox
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ fontComboBox->hasFocus();
+ QVERIFY(!edit2->hasFocus());
+ QCOMPARE(eventSpy3.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy3.counts[QEvent::FocusOut], 0);
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
+
+ // Tab into line edit 2
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ edit2->hasFocus();
+ QVERIFY(!edit1->hasFocus());
+ QCOMPARE(eventSpy2.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy2.counts[QEvent::FocusOut], 0);
+ QCOMPARE(eventSpy3.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
+
+ // Tab into right box
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QVERIFY(!edit2->hasFocus());
+ box_2->hasFocus();
+
+ // Tab into right top line edit
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QVERIFY(!box_2->hasFocus());
+ edit1_2->hasFocus();
+ QCOMPARE(eventSpy1_2.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy1_2.counts[QEvent::FocusOut], 0);
+
+ // Tab into right font combobox
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QVERIFY(!edit1_2->hasFocus());
+ fontComboBox2->hasFocus();
+ QCOMPARE(eventSpy1_2.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy1_2.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpy2_3.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy2_3.counts[QEvent::FocusOut], 0);
+
+ // Tab into right bottom line edit
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QVERIFY(!edit1_2->hasFocus());
+ edit2_2->hasFocus();
+ QCOMPARE(eventSpy1_2.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy1_2.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpy2_3.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy2_3.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpy2_2.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy2_2.counts[QEvent::FocusOut], 0);
+
+ // Tab into right dial
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QVERIFY(!edit2->hasFocus());
+ rightDial->hasFocus();
+ QCOMPARE(eventSpy2_2.counts[QEvent::FocusOut], 1);
+
+ // Backtab into line edit 2
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!rightDial->hasFocus());
+ edit2_2->hasFocus();
+
+ // Backtab into the right font combobox
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!edit2_2->hasFocus());
+ fontComboBox2->hasFocus();
+
+ // Backtab into line edit 1
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!edit2_2->hasFocus());
+ edit1_2->hasFocus();
+
+ // Backtab into line box
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!edit1_2->hasFocus());
+ box_2->hasFocus();
+
+ // Backtab into line edit 2
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!rightDial->hasFocus());
+ edit2->hasFocus();
+
+ // Backtab into the font combobox
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!edit2->hasFocus());
+ fontComboBox->hasFocus();
+
+ // Backtab into line edit 1
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!fontComboBox->hasFocus());
+ edit1->hasFocus();
+
+ // Backtab into line box
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!edit1->hasFocus());
+ box->hasFocus();
+
+ // Backtab into left dial
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QVERIFY(!box->hasFocus());
+ leftDial->hasFocus();
+
+ delete view;
+}
+
+void tst_QGraphicsProxyWidget::setFocus_simpleWidget()
+{
+ QGraphicsScene scene;
+ QLineEdit *edit = new QLineEdit;
+ QGraphicsProxyWidget *editProxy = scene.addWidget(edit);
+ editProxy->show();
+
+ QDial *leftDial = new QDial;
+ QDial *rightDial = new QDial;
+ QGraphicsView *view = new QGraphicsView(&scene);
+
+ QWidget window;
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(leftDial);
+ layout->addWidget(view);
+ layout->addWidget(rightDial);
+ window.setLayout(layout);
+
+ window.show();
+ QApplication::setActiveWindow(&window);
+ window.activateWindow();
+ QTest::qWaitForWindowShown(&window);
+ QTRY_COMPARE(QApplication::activeWindow(), &window);
+
+ leftDial->setFocus();
+ QApplication::processEvents();
+ QTRY_VERIFY(leftDial->hasFocus());
+
+ EventSpy eventSpy(edit);
+
+ // Calling setFocus for the line edit when the view doesn't have input
+ // focus does not steal focus from the dial. The edit, proxy and scene
+ // have focus but only in their own little space.
+ edit->setFocus();
+ QVERIFY(scene.hasFocus());
+ QVERIFY(edit->hasFocus());
+ QVERIFY(!view->hasFocus());
+ QVERIFY(!view->viewport()->hasFocus());
+ QVERIFY(leftDial->hasFocus());
+
+ // Clearing focus is a local operation.
+ edit->clearFocus();
+ QVERIFY(scene.hasFocus());
+ QVERIFY(!edit->hasFocus());
+ QVERIFY(!view->hasFocus());
+ QVERIFY(leftDial->hasFocus());
+
+ view->setFocus();
+ QVERIFY(scene.hasFocus());
+ QVERIFY(view->hasFocus());
+ QVERIFY(!leftDial->hasFocus());
+ QVERIFY(!edit->hasFocus());
+
+ scene.clearFocus();
+ QVERIFY(!scene.hasFocus());
+
+ edit->setFocus();
+ QVERIFY(scene.hasFocus());
+ QVERIFY(edit->hasFocus());
+ QVERIFY(editProxy->hasFocus());
+
+ // Symmetry
+ editProxy->clearFocus();
+ QVERIFY(!edit->hasFocus());
+
+ delete view;
+}
+
+void tst_QGraphicsProxyWidget::setFocus_simpleTwoWidgets()
+{
+ QGraphicsScene scene;
+ QLineEdit *edit = new QLineEdit;
+ QGraphicsProxyWidget *editProxy = scene.addWidget(edit);
+ editProxy->show();
+ QLineEdit *edit2 = new QLineEdit;
+ QGraphicsProxyWidget *edit2Proxy = scene.addWidget(edit2);
+ edit2Proxy->show();
+ edit2Proxy->setPos(editProxy->boundingRect().width() * 1.01, 0);
+
+ QDial *leftDial = new QDial;
+ QDial *rightDial = new QDial;
+ QGraphicsView *view = new QGraphicsView(&scene);
+
+ QWidget window;
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(leftDial);
+ layout->addWidget(view);
+ layout->addWidget(rightDial);
+ window.setLayout(layout);
+
+ window.show();
+ QApplication::setActiveWindow(&window);
+ window.activateWindow();
+ QTest::qWaitForWindowShown(&window);
+ QTRY_COMPARE(QApplication::activeWindow(), &window);
+
+ leftDial->setFocus();
+ QApplication::processEvents();
+ QTRY_VERIFY(leftDial->hasFocus());
+
+ EventSpy eventSpy(edit);
+
+ view->setFocus();
+ QVERIFY(!edit->hasFocus());
+
+ edit->setFocus();
+ QVERIFY(scene.hasFocus());
+ QVERIFY(edit->hasFocus());
+ QVERIFY(editProxy->hasFocus());
+
+ edit2->setFocus();
+ QVERIFY(scene.hasFocus());
+ QVERIFY(!edit->hasFocus());
+ QVERIFY(!editProxy->hasFocus());
+ QVERIFY(edit2->hasFocus());
+ QVERIFY(edit2Proxy->hasFocus());
+
+ delete view;
+}
+
+void tst_QGraphicsProxyWidget::setFocus_complexTwoWidgets()
+{
+ // ### add event spies to this test.
+ QGraphicsScene scene;
+
+ QLineEdit *edit1 = new QLineEdit;
+ edit1->setText("QLineEdit 1");
+ QLineEdit *edit2 = new QLineEdit;
+ edit2->setText("QLineEdit 2");
+ QVBoxLayout *vlayout = new QVBoxLayout;
+ vlayout->addWidget(edit1);
+ vlayout->addWidget(edit2);
+
+ QGroupBox *box = new QGroupBox("QGroupBox");
+ box->setCheckable(true);
+ box->setChecked(true);
+ box->setLayout(vlayout);
+
+ QLineEdit *edit1_2 = new QLineEdit;
+ edit1_2->setText("QLineEdit 1_2");
+ QLineEdit *edit2_2 = new QLineEdit;
+ edit2_2->setText("QLineEdit 2_2");
+ vlayout = new QVBoxLayout;
+ vlayout->addWidget(edit1_2);
+ vlayout->addWidget(edit2_2);
+
+ QGroupBox *box_2 = new QGroupBox("QGroupBox 2");
+ box_2->setCheckable(true);
+ box_2->setChecked(true);
+ box_2->setLayout(vlayout);
+
+ QGraphicsProxyWidget *proxy = scene.addWidget(box);
+ proxy->show();
+
+ QGraphicsProxyWidget *proxy_2 = scene.addWidget(box_2);
+ proxy_2->setPos(proxy->boundingRect().width() * 1.2, 0);
+ proxy_2->show();
+
+ QDial *leftDial = new QDial;
+ QDial *rightDial = new QDial;
+ QGraphicsView *view = new QGraphicsView(&scene);
+
+ QWidget window;
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(leftDial);
+ layout->addWidget(view);
+ layout->addWidget(rightDial);
+ window.setLayout(layout);
+
+ window.show();
+ QApplication::setActiveWindow(&window);
+ window.activateWindow();
+ QTest::qWaitForWindowShown(&window);
+ QTRY_COMPARE(QApplication::activeWindow(), &window);
+
+ leftDial->setFocus();
+ QApplication::processEvents();
+ QTRY_VERIFY(leftDial->hasFocus());
+
+ EventSpy eventSpy(edit1);
+ EventSpy eventSpy2(edit2);
+ EventSpy eventSpyBox(box);
+ EventSpy eventSpy_2(edit1_2);
+ EventSpy eventSpy2_2(edit2_2);
+ EventSpy eventSpyBox_2(box_2);
+
+ view->setFocus();
+
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 0);
+
+ edit1->setFocus();
+ QApplication::processEvents();
+ QVERIFY(scene.hasFocus());
+ QVERIFY(edit1->hasFocus());
+ QVERIFY(!box->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpyBox.counts[QEvent::FocusIn], 0);
+
+ edit2_2->setFocus();
+ QApplication::processEvents();
+ QVERIFY(!edit1->hasFocus());
+ QVERIFY(!box_2->hasFocus());
+ QVERIFY(edit2_2->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpy2_2.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpyBox.counts[QEvent::FocusIn], 0);
+ QCOMPARE(eventSpyBox_2.counts[QEvent::FocusIn], 0);
+
+ box->setFocus();
+ QApplication::processEvents();
+ QVERIFY(!edit2_2->hasFocus());
+ QVERIFY(!edit1->hasFocus());
+ QVERIFY(box->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpy2_2.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy2_2.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpyBox.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpyBox.counts[QEvent::FocusOut], 0);
+ QCOMPARE(eventSpyBox_2.counts[QEvent::FocusIn], 0);
+ QCOMPARE(eventSpyBox_2.counts[QEvent::FocusOut], 0);
+
+ edit2_2->setFocus();
+ QApplication::processEvents();
+ QVERIFY(edit2_2->hasFocus());
+ QVERIFY(!edit1->hasFocus());
+ QVERIFY(!box->hasFocus());
+ QVERIFY(!box_2->hasFocus());
+ QCOMPARE(eventSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpy.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpy2_2.counts[QEvent::FocusIn], 2);
+ QCOMPARE(eventSpy2_2.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpyBox.counts[QEvent::FocusIn], 1);
+ QCOMPARE(eventSpyBox.counts[QEvent::FocusOut], 1);
+ QCOMPARE(eventSpyBox_2.counts[QEvent::FocusIn], 0);
+ QCOMPARE(eventSpyBox_2.counts[QEvent::FocusOut], 0);
+
+ delete view;
+}
+
+void tst_QGraphicsProxyWidget::popup_basic()
+{
+ // ProxyWidget should automatically create proxy's when the widget creates a child
+ QGraphicsScene *scene = new QGraphicsScene;
+ QGraphicsView view(scene);
+ view.setAlignment(Qt::AlignLeft | Qt::AlignTop);
+ view.setGeometry(0, 100, 480, 500);
+ view.show();
+
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ QComboBox *box = new QComboBox;
+ box->setGeometry(0, 0, 320, 40);
+ box->addItems(QStringList() << "monday" << "tuesday" << "wednesday"
+ << "thursday" << "saturday" << "sunday");
+ QCOMPARE(proxy->childItems().count(), 0);
+ proxy->setWidget(box);
+ proxy->show();
+ scene->addItem(proxy);
+
+ QCOMPARE(box->pos(), QPoint());
+ QCOMPARE(proxy->pos(), QPointF());
+
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(125);
+ QApplication::processEvents();
+
+ QTest::mousePress(view.viewport(), Qt::LeftButton, 0,
+ view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center())));
+
+ QTRY_COMPARE(box->pos(), QPoint());
+
+ QCOMPARE(proxy->childItems().count(), 1);
+ QGraphicsProxyWidget *child = (QGraphicsProxyWidget*)(proxy->childItems())[0];
+ QVERIFY(child->isWidget());
+ QVERIFY(child->widget());
+ QStyleOptionComboBox opt;
+ opt.initFrom(box);
+ opt.editable = box->isEditable();
+ if (box->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt))
+ QSKIP("Does not work due to SH_Combobox_Popup", SkipAll);
+ QCOMPARE(child->widget()->parent(), static_cast<QObject*>(box));
+
+ QTRY_COMPARE(proxy->pos(), QPointF(box->pos()));
+ QCOMPARE(child->x(), qreal(box->x()));
+ QCOMPARE(child->y(), qreal(box->rect().bottom()));
+#ifndef Q_OS_WIN
+ // The popup's coordinates on Windows are in global space,
+ // regardless.
+ QCOMPARE(child->widget()->x(), box->x());
+ QCOMPARE(child->widget()->y(), box->rect().bottom());
+ QCOMPARE(child->geometry().toRect(), child->widget()->geometry());
+#endif
+ QTest::qWait(12);
+}
+
+void tst_QGraphicsProxyWidget::popup_subwidget()
+{
+ QGroupBox *groupBox = new QGroupBox;
+ groupBox->setTitle("GroupBox");
+ groupBox->setCheckable(true);
+
+ QComboBox *box = new QComboBox;
+ box->addItems(QStringList() << "monday" << "tuesday" << "wednesday"
+ << "thursday" << "saturday" << "sunday");
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(new QLineEdit("QLineEdit"));
+ layout->addWidget(box);
+ layout->addWidget(new QLineEdit("QLineEdit"));
+ groupBox->setLayout(layout);
+
+ QGraphicsScene scene;
+ QGraphicsProxyWidget *groupBoxProxy = scene.addWidget(groupBox);
+ groupBox->show();
+ groupBox->move(10000, 10000);
+ QCOMPARE(groupBox->pos(), QPoint(10000, 10000));
+ QCOMPARE(groupBoxProxy->pos(), QPointF(10000, 10000));
+
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+
+ box->showPopup();
+
+ QVERIFY(!groupBoxProxy->childItems().isEmpty());
+
+ QStyleOptionComboBox opt;
+ opt.initFrom(box);
+ opt.editable = box->isEditable();
+ if (box->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt))
+ QSKIP("Does not work due to SH_Combobox_Popup", SkipAll);
+ QGraphicsProxyWidget *child = (QGraphicsProxyWidget*)(groupBoxProxy->childItems())[0];
+ QWidget *popup = child->widget();
+ QCOMPARE(popup->parent(), static_cast<QObject*>(box));
+ QCOMPARE(popup->x(), box->mapToGlobal(QPoint()).x());
+ QCOMPARE(popup->y(), QRect(box->mapToGlobal(QPoint()), box->size()).bottom());
+ QCOMPARE(popup->size(), child->size().toSize());
+}
+
+#if !defined(QT_NO_CURSOR) && (!defined(Q_OS_WINCE) || defined(GWES_ICONCURS))
+void tst_QGraphicsProxyWidget::changingCursor_basic()
+{
+ // Confirm that mouse events are working properly by checking that
+ // when moving the mouse over a line edit it will change the cursor into the I
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+
+ SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget;
+ QLineEdit *widget = new QLineEdit;
+ proxy->setWidget(widget);
+ proxy->show();
+ scene.addItem(proxy);
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
+ QTRY_VERIFY(view.isActiveWindow());
+
+ // in
+ QTest::mouseMove(view.viewport(), view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center())));
+ sendMouseMove(view.viewport(), view.mapFromScene(proxy->mapToScene(proxy->boundingRect().center())));
+ QTRY_COMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
+
+ // out
+ QTest::mouseMove(view.viewport(), QPoint(1, 1));
+ sendMouseMove(view.viewport(), QPoint(1, 1));
+ QTRY_COMPARE(view.viewport()->cursor().shape(), Qt::ArrowCursor);
+}
+#endif
+
+void tst_QGraphicsProxyWidget::tooltip_basic()
+{
+ QString toolTip = "Qt rocks!";
+ QString toolTip2 = "Qt rocks even more!";
+
+ QPushButton *button = new QPushButton("button");
+ QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget;
+ QGraphicsProxyWidgetPrivate *proxyd = static_cast<QGraphicsProxyWidgetPrivate *>(QGraphicsItemPrivate::get(proxy));
+ proxy->setWidget(button);
+ proxyd->lastWidgetUnderMouse = button; // force widget under mouse
+
+ QVERIFY(button->toolTip().isEmpty());
+ QVERIFY(proxy->toolTip().isEmpty());
+ // Check that setting the tooltip on the proxy also set it on the widget
+ proxy->setToolTip(toolTip);
+ QCOMPARE(proxy->toolTip(), toolTip);
+ QCOMPARE(button->toolTip(), toolTip);
+ // Check that setting the tooltip on the widget also set it on the proxy
+ button->setToolTip(toolTip2);
+ QCOMPARE(proxy->toolTip(), toolTip2);
+ QCOMPARE(button->toolTip(), toolTip2);
+
+ QGraphicsScene scene;
+ scene.addItem(proxy);
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(200, 200);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ {
+ QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().topLeft(),
+ view.viewport()->mapToGlobal(view.viewport()->rect().topLeft()));
+ QApplication::sendEvent(view.viewport(), &helpEvent);
+ QTest::qWait(350);
+
+ 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.mapFromScene(proxy->boundingRect().center()),
+ view.viewport()->mapToGlobal(view.mapFromScene(proxy->boundingRect().center())));
+ QApplication::sendEvent(view.viewport(), &helpEvent);
+ QTest::qWait(350);
+
+ 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);
+ }
+}
+
+void tst_QGraphicsProxyWidget::childPos_data()
+{
+ QTest::addColumn<bool>("moveCombo");
+ QTest::addColumn<QPoint>("comboPos");
+ QTest::addColumn<QPointF>("proxyPos");
+ QTest::addColumn<QPointF>("menuPos");
+
+ QTest::newRow("0") << true << QPoint() << QPointF() << QPointF();
+ QTest::newRow("1") << true << QPoint(10, 0) << QPointF(10, 0) << QPointF();
+ QTest::newRow("2") << true << QPoint(100, 0) << QPointF(100, 0) << QPointF();
+ QTest::newRow("3") << true << QPoint(1000, 0) << QPointF(1000, 0) << QPointF();
+ QTest::newRow("4") << true << QPoint(10000, 0) << QPointF(10000, 0) << QPointF();
+ QTest::newRow("5") << true << QPoint(-10000, 0) << QPointF(-10000, 0) << QPointF();
+ QTest::newRow("6") << true << QPoint(-1000, 0) << QPointF(-1000, 0) << QPointF();
+ QTest::newRow("7") << true << QPoint(-100, 0) << QPointF(-100, 0) << QPointF();
+ QTest::newRow("8") << true << QPoint(-10, 0) << QPointF(-10, 0) << QPointF();
+ QTest::newRow("0-") << false << QPoint() << QPointF() << QPointF();
+ QTest::newRow("1-") << false << QPoint(10, 0) << QPointF(10, 0) << QPointF();
+ QTest::newRow("2-") << false << QPoint(100, 0) << QPointF(100, 0) << QPointF();
+ QTest::newRow("3-") << false << QPoint(1000, 0) << QPointF(1000, 0) << QPointF();
+ QTest::newRow("4-") << false << QPoint(10000, 0) << QPointF(10000, 0) << QPointF();
+ QTest::newRow("5-") << false << QPoint(-10000, 0) << QPointF(-10000, 0) << QPointF();
+ QTest::newRow("6-") << false << QPoint(-1000, 0) << QPointF(-1000, 0) << QPointF();
+ QTest::newRow("7-") << false << QPoint(-100, 0) << QPointF(-100, 0) << QPointF();
+ QTest::newRow("8-") << false << QPoint(-10, 0) << QPointF(-10, 0) << QPointF();
+}
+
+void tst_QGraphicsProxyWidget::childPos()
+{
+#ifdef Q_OS_IRIX
+ QSKIP("This test is not reliable on IRIX.", SkipAll);
+#endif
+ QFETCH(bool, moveCombo);
+ QFETCH(QPoint, comboPos);
+ QFETCH(QPointF, proxyPos);
+ QFETCH(QPointF, menuPos);
+
+ QGraphicsScene scene;
+
+ QComboBox *box = new QComboBox;
+ box->addItem("Item 1");
+ box->addItem("Item 2");
+ box->addItem("Item 3");
+ box->addItem("Item 4");
+
+ if (moveCombo)
+ box->move(comboPos);
+
+ QGraphicsProxyWidget *proxy = scene.addWidget(box);
+ proxy->show();
+ QVERIFY(proxy->isVisible());
+ QVERIFY(box->isVisible());
+
+ if (!moveCombo)
+ proxy->setPos(proxyPos);
+
+ QCOMPARE(proxy->pos(), proxyPos);
+ QCOMPARE(box->pos(), comboPos);
+
+ for (int i = 0; i < 2; ++i) {
+ box->showPopup();
+ QApplication::processEvents();
+ QApplication::processEvents();
+
+ QWidget *menu = 0;
+ foreach (QObject *child, box->children()) {
+ if ((menu = qobject_cast<QWidget *>(child)))
+ break;
+ }
+ QVERIFY(menu);
+ QVERIFY(menu->isVisible());
+ QVERIFY(menu->testAttribute(Qt::WA_DontShowOnScreen));
+
+ QCOMPARE(proxy->childItems().size(), 1);
+ QGraphicsProxyWidget *proxyChild = 0;
+ foreach (QGraphicsItem *child, proxy->childItems()) {
+ if (child->isWidget() && (proxyChild = qobject_cast<QGraphicsProxyWidget *>(static_cast<QGraphicsWidget *>(child))))
+ break;
+ }
+ QVERIFY(proxyChild);
+ QVERIFY(proxyChild->isVisible());
+ qreal expectedXPosition = 0.0;
+#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
+ // The Mac style wants the popup to show up at QPoint(4 - 11, 1).
+ // See QMacStyle::subControlRect SC_ComboBoxListBoxPopup.
+ if (qobject_cast<QMacStyle *>(QApplication::style()))
+ expectedXPosition = qreal(4 - 11);
+#endif
+ QCOMPARE(proxyChild->pos().x(), expectedXPosition);
+ menu->hide();
+ }
+}
+
+void tst_QGraphicsProxyWidget::autoShow()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ QGraphicsProxyWidget *proxy1 = scene.addWidget(new QPushButton("Button1"));
+
+ QPushButton *button2 = new QPushButton("Button2");
+ button2->hide();
+ QGraphicsProxyWidget *proxy2 = new QGraphicsProxyWidget();
+ proxy2->setWidget(button2);
+ scene.addItem(proxy2);
+
+ view.show();
+ QApplication::processEvents();
+
+ QCOMPARE(proxy1->isVisible(), true);
+ QCOMPARE(proxy2->isVisible(), false);
+
+}
+
+Q_DECLARE_METATYPE(QList<QRectF>)
+void tst_QGraphicsProxyWidget::windowOpacity()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ QWidget *widget = new QWidget;
+ widget->resize(100, 100);
+ QGraphicsProxyWidget *proxy = scene.addWidget(widget);
+ proxy->setCacheMode(QGraphicsItem::ItemCoordinateCache);
+
+ QApplication::setActiveWindow(&view);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::sendPostedEvents();
+ QTRY_VERIFY(view.isActiveWindow());
+
+ qRegisterMetaType<QList<QRectF> >("QList<QRectF>");
+ QSignalSpy signalSpy(&scene, SIGNAL(changed(const QList<QRectF> &)));
+
+ EventSpy eventSpy(widget);
+ QVERIFY(widget->isVisible());
+
+ widget->setWindowOpacity(0.5);
+ QApplication::processEvents();
+
+ // Make sure setWindowOpacity triggers an update on the scene,
+ // and not on the widget or the proxy itself. The entire proxy needs an update
+ // in case it has a window decoration. Update: QGraphicsItem::CacheMode is
+ // disabled on platforms without alpha channel support in QPixmap (e.g.,
+ // X11 without XRender).
+ int paints = 0;
+#ifdef Q_WS_X11
+ paints = !X11->use_xrender;
+#endif
+ QTRY_COMPARE(eventSpy.counts[QEvent::UpdateRequest], 0);
+ QTRY_COMPARE(eventSpy.counts[QEvent::Paint], paints);
+
+ QCOMPARE(signalSpy.count(), 1);
+ const QList<QVariant> arguments = signalSpy.takeFirst();
+ const QList<QRectF> updateRects = qvariant_cast<QList<QRectF> >(arguments.at(0));
+ QCOMPARE(updateRects.size(), 1);
+ QCOMPARE(updateRects.at(0), proxy->sceneBoundingRect());
+}
+
+void tst_QGraphicsProxyWidget::stylePropagation()
+{
+ QPointer<QWindowsStyle> windowsStyle = new QWindowsStyle;
+
+ QLineEdit *edit = new QLineEdit;
+ QGraphicsProxyWidget proxy;
+ proxy.setWidget(edit);
+
+ EventSpy editSpy(edit);
+ EventSpy proxySpy(&proxy);
+
+ // Widget to proxy
+ QCOMPARE(proxy.style(), QApplication::style());
+ edit->setStyle(windowsStyle);
+ QCOMPARE(editSpy.counts[QEvent::StyleChange], 1);
+ QCOMPARE(proxySpy.counts[QEvent::StyleChange], 1);
+ QCOMPARE(proxy.style(), (QStyle *)windowsStyle);
+ edit->setStyle(0);
+ QCOMPARE(editSpy.counts[QEvent::StyleChange], 2);
+ QCOMPARE(proxySpy.counts[QEvent::StyleChange], 2);
+ QCOMPARE(proxy.style(), QApplication::style());
+ QCOMPARE(edit->style(), QApplication::style());
+ QVERIFY(windowsStyle); // not deleted
+
+ // Proxy to widget
+ proxy.setStyle(windowsStyle);
+ QCOMPARE(editSpy.counts[QEvent::StyleChange], 3);
+ QCOMPARE(proxySpy.counts[QEvent::StyleChange], 3);
+ QCOMPARE(edit->style(), (QStyle *)windowsStyle);
+ proxy.setStyle(0);
+ QCOMPARE(editSpy.counts[QEvent::StyleChange], 4);
+ QCOMPARE(proxySpy.counts[QEvent::StyleChange], 4);
+ QCOMPARE(proxy.style(), QApplication::style());
+ QCOMPARE(edit->style(), QApplication::style());
+ QVERIFY(windowsStyle); // not deleted
+
+ delete windowsStyle;
+}
+
+void tst_QGraphicsProxyWidget::palettePropagation()
+{
+ // Construct a palette with an unlikely setup
+ QPalette lineEditPalette = QApplication::palette("QLineEdit");
+ QPalette palette = lineEditPalette;
+ palette.setBrush(QPalette::Text, Qt::red);
+
+ QLineEdit *edit = new QLineEdit;
+ QGraphicsProxyWidget proxy;
+ proxy.setWidget(edit);
+
+ EventSpy editSpy(edit);
+ EventSpy proxySpy(&proxy);
+
+ // Widget to proxy (no change)
+ QVERIFY(!edit->testAttribute(Qt::WA_SetPalette));
+ edit->setPalette(palette);
+ QCOMPARE(editSpy.counts[QEvent::PaletteChange], 1);
+ QCOMPARE(proxySpy.counts[QEvent::PaletteChange], 0);
+ QVERIFY(edit->testAttribute(Qt::WA_SetPalette));
+ QVERIFY(!proxy.testAttribute(Qt::WA_SetPalette));
+ QCOMPARE(proxy.palette(), QPalette());
+ edit->setPalette(QPalette());
+ QCOMPARE(editSpy.counts[QEvent::PaletteChange], 2);
+ QCOMPARE(proxySpy.counts[QEvent::PaletteChange], 0);
+ QVERIFY(!edit->testAttribute(Qt::WA_SetPalette));
+ QVERIFY(!proxy.testAttribute(Qt::WA_SetPalette));
+ QCOMPARE(proxy.palette(), QPalette());
+
+ // Proxy to widget
+ proxy.setPalette(palette);
+ QVERIFY(proxy.testAttribute(Qt::WA_SetPalette));
+ QCOMPARE(editSpy.counts[QEvent::PaletteChange], 3);
+ QCOMPARE(proxySpy.counts[QEvent::PaletteChange], 1);
+ QVERIFY(!edit->testAttribute(Qt::WA_SetPalette));
+ QCOMPARE(edit->palette(), palette);
+ QCOMPARE(edit->palette(), proxy.palette());
+ QCOMPARE(edit->palette().color(QPalette::Text), QColor(Qt::red));
+ proxy.setPalette(QPalette());
+ QVERIFY(!proxy.testAttribute(Qt::WA_SetPalette));
+ QVERIFY(!edit->testAttribute(Qt::WA_SetPalette));
+ QCOMPARE(editSpy.counts[QEvent::PaletteChange], 4);
+ QCOMPARE(proxySpy.counts[QEvent::PaletteChange], 2);
+ QCOMPARE(edit->palette(), lineEditPalette);
+}
+
+void tst_QGraphicsProxyWidget::fontPropagation()
+{
+ // Construct a font with an unlikely setup
+ QGraphicsScene scene;
+ QFont lineEditFont = QApplication::font("QLineEdit");
+ QFont font = lineEditFont;
+ font.setPointSize(43);
+
+ QLineEdit *edit = new QLineEdit;
+ QGraphicsProxyWidget proxy;
+ proxy.setWidget(edit);
+
+ scene.addItem(&proxy);
+ EventSpy editSpy(edit);
+ EventSpy proxySpy(&proxy);
+
+ // Widget to proxy (no change)
+ QVERIFY(!edit->testAttribute(Qt::WA_SetFont));
+ edit->setFont(font);
+ QCOMPARE(editSpy.counts[QEvent::FontChange], 1);
+ QCOMPARE(proxySpy.counts[QEvent::FontChange], 0);
+ QVERIFY(edit->testAttribute(Qt::WA_SetFont));
+ QVERIFY(!proxy.testAttribute(Qt::WA_SetFont));
+ QCOMPARE(proxy.font(), lineEditFont);
+ edit->setFont(QFont());
+ QCOMPARE(editSpy.counts[QEvent::FontChange], 2);
+ QCOMPARE(proxySpy.counts[QEvent::FontChange], 0);
+ QVERIFY(!edit->testAttribute(Qt::WA_SetFont));
+ QVERIFY(!proxy.testAttribute(Qt::WA_SetFont));
+ QCOMPARE(proxy.font(), lineEditFont);
+
+ // Proxy to widget
+ proxy.setFont(font);
+ QApplication::processEvents(); // wait for QEvent::Polish
+ QVERIFY(proxy.testAttribute(Qt::WA_SetFont));
+ QCOMPARE(editSpy.counts[QEvent::FontChange], 3);
+ QCOMPARE(proxySpy.counts[QEvent::FontChange], 1);
+ QVERIFY(!edit->testAttribute(Qt::WA_SetFont));
+ QCOMPARE(edit->font(), font);
+ QCOMPARE(edit->font(), proxy.font());
+ QCOMPARE(edit->font().pointSize(), 43);
+ proxy.setFont(QFont());
+ QVERIFY(!proxy.testAttribute(Qt::WA_SetFont));
+ QVERIFY(!edit->testAttribute(Qt::WA_SetFont));
+ QCOMPARE(editSpy.counts[QEvent::FontChange], 4);
+ QCOMPARE(proxySpy.counts[QEvent::FontChange], 2);
+ QCOMPARE(edit->font(), lineEditFont);
+
+ proxy.setFont(font);
+ QLineEdit *edit2 = new QLineEdit;
+ proxy.setWidget(edit2);
+ delete edit;
+ QCOMPARE(edit2->font().pointSize(), 43);
+}
+
+class MainWidget : public QMainWindow
+{
+Q_OBJECT
+public:
+ MainWidget() : QMainWindow() {
+ view = new QGraphicsView(this);
+ scene = new QGraphicsScene(this);
+ item = new QGraphicsWidget();
+ widget = new QGraphicsProxyWidget(item);
+ layout = new QGraphicsLinearLayout(item);
+ layout->addItem(widget);
+ item->setLayout(layout);
+ button = new QPushButton("Push me");
+ widget->setWidget(button);
+ setCentralWidget(view);
+ scene->addItem(item);
+ view->setScene(scene);
+ scene->setFocusItem(item);
+ layout->activate();
+ }
+ QGraphicsView* view;
+ QGraphicsScene* scene;
+ QGraphicsWidget * item;
+ QGraphicsLinearLayout * layout;
+ QGraphicsProxyWidget * widget;
+ QPushButton * button;
+};
+
+void tst_QGraphicsProxyWidget::dontCrashWhenDie()
+{
+ MainWidget *w = new MainWidget();
+ w->show();
+ QTest::qWaitForWindowShown(w);
+ QTest::qWait(100);
+ QTest::mouseMove(w->view->viewport(), w->view->mapFromScene(w->widget->mapToScene(w->widget->boundingRect().center())));
+ delete w->item;
+
+ QApplication::processEvents();
+ delete w;
+}
+
+void tst_QGraphicsProxyWidget::createProxyForChildWidget()
+{
+ QGraphicsScene scene;
+
+ QLineEdit *edit1 = new QLineEdit;
+ edit1->setText("QLineEdit 1");
+ QLineEdit *edit2 = new QLineEdit;
+ edit2->setText("QLineEdit 2");
+ QCheckBox *checkbox = new QCheckBox("QCheckBox");
+ QVBoxLayout *vlayout = new QVBoxLayout;
+
+ vlayout->addWidget(edit1);
+ vlayout->addWidget(edit2);
+ vlayout->addWidget(checkbox);
+ vlayout->insertStretch(-1);
+
+ QGroupBox *box = new QGroupBox("QGroupBox");
+ box->setCheckable(true);
+ box->setChecked(true);
+ box->setLayout(vlayout);
+
+ QDial *leftDial = new QDial;
+ QDial *rightDial = new QDial;
+
+ QWidget window;
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(leftDial);
+ layout->addWidget(box);
+ layout->addWidget(rightDial);
+ window.setLayout(layout);
+
+ QVERIFY(window.graphicsProxyWidget() == 0);
+ QVERIFY(checkbox->graphicsProxyWidget() == 0);
+
+ QGraphicsProxyWidget *windowProxy = scene.addWidget(&window);
+ QGraphicsView view(&scene);
+ view.show();
+ view.resize(500,500);
+
+ QVERIFY(window.graphicsProxyWidget() == windowProxy);
+ QVERIFY(box->graphicsProxyWidget() == 0);
+ QVERIFY(checkbox->graphicsProxyWidget() == 0);
+
+ QPointer<QGraphicsProxyWidget> checkboxProxy = windowProxy->createProxyForChildWidget(checkbox);
+
+ QGraphicsProxyWidget *boxProxy = box->graphicsProxyWidget();
+
+ QVERIFY(boxProxy);
+ QVERIFY(checkbox->graphicsProxyWidget() == checkboxProxy);
+ QVERIFY(checkboxProxy->parentItem() == boxProxy);
+ QVERIFY(boxProxy->parentItem() == windowProxy);
+
+ QVERIFY(checkboxProxy->mapToScene(QPointF()) == checkbox->mapTo(&window, QPoint()));
+ QVERIFY(checkboxProxy->size() == checkbox->size());
+ QVERIFY(boxProxy->size() == box->size());
+
+ window.resize(500,500);
+ QVERIFY(windowProxy->size() == QSize(500,500));
+ QVERIFY(checkboxProxy->mapToScene(QPointF()) == checkbox->mapTo(&window, QPoint()));
+ QVERIFY(checkboxProxy->size() == checkbox->size());
+ QVERIFY(boxProxy->size() == box->size());
+
+ QTest::qWait(10);
+
+
+ QSignalSpy spy(checkbox, SIGNAL(clicked()));
+
+ QTest::mousePress(view.viewport(), Qt::LeftButton, 0,
+ view.mapFromScene(checkboxProxy->mapToScene(QPointF(8,8))));
+ QTRY_COMPARE(spy.count(), 0);
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0,
+ view.mapFromScene(checkboxProxy->mapToScene(QPointF(8,8))));
+ QTRY_COMPARE(spy.count(), 1);
+
+
+
+ boxProxy->setWidget(0);
+
+ QVERIFY(checkbox->graphicsProxyWidget() == 0);
+ QVERIFY(box->graphicsProxyWidget() == 0);
+ QVERIFY(checkboxProxy == 0);
+
+ delete boxProxy;
+}
+
+class ContextMenuWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ ContextMenuWidget()
+ : embeddedPopup(false),
+ gotContextMenuEvent(false)
+ { }
+ bool embeddedPopup;
+ bool gotContextMenuEvent;
+protected:
+ bool event(QEvent *event)
+ {
+ if (event->type() == QEvent::ContextMenu)
+ QTimer::singleShot(0, this, SLOT(checkMenu()));
+ return QWidget::event(event);
+ }
+ void contextMenuEvent(QContextMenuEvent *)
+ {
+ gotContextMenuEvent = true;
+ }
+
+private slots:
+ void checkMenu()
+ {
+ if (qFindChild<QMenu *>(this))
+ embeddedPopup = true;
+ hide();
+ }
+};
+
+void tst_QGraphicsProxyWidget::actionsContextMenu_data()
+{
+ QTest::addColumn<bool>("actionsContextMenu");
+ QTest::addColumn<bool>("hasFocus");
+
+ QTest::newRow("without actionsContextMenu and with focus") << false << true;
+ QTest::newRow("without actionsContextMenu and without focus") << false << false;
+ QTest::newRow("with actionsContextMenu and focus") << true << true;
+ QTest::newRow("with actionsContextMenu without focus") << true << false;
+}
+
+void tst_QGraphicsProxyWidget::actionsContextMenu()
+{
+ QFETCH(bool, hasFocus);
+ QFETCH(bool, actionsContextMenu);
+
+ ContextMenuWidget *widget = new ContextMenuWidget;
+ if (actionsContextMenu) {
+ widget->addAction(new QAction("item 1", widget));
+ widget->addAction(new QAction("item 2", widget));
+ widget->addAction(new QAction("item 3", widget));
+ widget->setContextMenuPolicy(Qt::ActionsContextMenu);
+ }
+ QGraphicsScene scene;
+
+ QGraphicsView view(&scene);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ view.setFocus();
+ QTRY_VERIFY(view.hasFocus());
+
+ if (hasFocus)
+ scene.addWidget(widget)->setFocus();
+ else
+ scene.addWidget(widget)->clearFocus();
+
+ QApplication::processEvents();
+
+ QContextMenuEvent contextMenuEvent(QContextMenuEvent::Mouse,
+ view.viewport()->rect().center(),
+ view.viewport()->mapToGlobal(view.viewport()->rect().center()));
+ contextMenuEvent.accept();
+ qApp->sendEvent(view.viewport(), &contextMenuEvent);
+
+ if (hasFocus) {
+ if (actionsContextMenu) {
+ //actionsContextMenu embedded popup but no contextMenuEvent (widget has focus)
+ QVERIFY(widget->embeddedPopup);
+ QVERIFY(!widget->gotContextMenuEvent);
+ } else {
+ //no embedded popup but contextMenuEvent (widget has focus)
+ QVERIFY(!widget->embeddedPopup);
+ QVERIFY(widget->gotContextMenuEvent);
+ }
+ } else {
+ //qgraphicsproxywidget doesn't have the focus, the widget must not receive any contextMenuEvent and must not create any QMenu
+ QVERIFY(!widget->embeddedPopup);
+ QVERIFY(!widget->gotContextMenuEvent);
+ }
+
+}
+
+
+void tst_QGraphicsProxyWidget::deleteProxyForChildWidget()
+{
+ QDialog dialog;
+ dialog.resize(320, 120);
+ dialog.move(80, 40);
+
+ QGraphicsScene scene;
+ scene.setSceneRect(QRectF(0, 0, 640, 480));
+ QGraphicsView view(&scene);
+ QComboBox *combo = new QComboBox;
+ combo->addItems(QStringList() << "red" << "green" << "blue" << "white" << "black" << "yellow" << "cyan" << "magenta");
+ dialog.setLayout(new QVBoxLayout);
+ dialog.layout()->addWidget(combo);
+
+ QGraphicsProxyWidget *proxy = scene.addWidget(&dialog);
+ view.show();
+
+ proxy->setWidget(0);
+ //just don't crash
+ QApplication::processEvents();
+ delete combo;
+}
+
+void tst_QGraphicsProxyWidget::bypassGraphicsProxyWidget_data()
+{
+ QTest::addColumn<bool>("bypass");
+
+ QTest::newRow("autoembed") << false;
+ QTest::newRow("bypass") << true;
+}
+
+void tst_QGraphicsProxyWidget::bypassGraphicsProxyWidget()
+{
+ QFETCH(bool, bypass);
+
+ QWidget *widget = new QWidget;
+ widget->resize(100, 100);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+
+ QGraphicsProxyWidget *proxy = scene.addWidget(widget);
+
+ QCOMPARE(proxy->widget(), widget);
+ QVERIFY(proxy->childItems().isEmpty());
+
+ Qt::WindowFlags flags;
+ flags |= Qt::Dialog;
+ if (bypass)
+ flags |= Qt::BypassGraphicsProxyWidget;
+ QFileDialog *dialog = new QFileDialog(widget, flags);
+ dialog->setOption(QFileDialog::DontUseNativeDialog, true);
+ dialog->show();
+
+ QCOMPARE(proxy->childItems().size(), bypass ? 0 : 1);
+ if (!bypass)
+ QCOMPARE(((QGraphicsProxyWidget *)proxy->childItems().first())->widget(), (QWidget *)dialog);
+
+ dialog->hide();
+ QApplication::processEvents();
+ delete dialog;
+ delete widget;
+}
+
+static void makeDndEvent(QGraphicsSceneDragDropEvent *event, QGraphicsView *view, const QPointF &pos)
+{
+ event->setScenePos(pos);
+ event->setScreenPos(view->mapToGlobal(view->mapFromScene(pos)));
+ event->setButtons(Qt::LeftButton);
+ event->setModifiers(0);
+ event->setPossibleActions(Qt::CopyAction);
+ event->setProposedAction(Qt::CopyAction);
+ event->setDropAction(Qt::CopyAction);
+ event->setWidget(view->viewport());
+ event->setSource(view->viewport());
+ event->ignore();
+}
+
+void tst_QGraphicsProxyWidget::dragDrop()
+{
+ QPushButton *button = new QPushButton; // acceptDrops(false)
+ QLineEdit *edit = new QLineEdit; // acceptDrops(true)
+
+ QGraphicsScene scene;
+ QGraphicsProxyWidget *buttonProxy = scene.addWidget(button);
+ QGraphicsProxyWidget *editProxy = scene.addWidget(edit);
+ QVERIFY(buttonProxy->acceptDrops());
+ QVERIFY(editProxy->acceptDrops());
+
+ button->setGeometry(0, 0, 100, 50);
+ edit->setGeometry(0, 60, 100, 50);
+
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+
+ QMimeData data;
+ data.setText("hei");
+ {
+ QGraphicsSceneDragDropEvent event(QEvent::GraphicsSceneDragEnter);
+ makeDndEvent(&event, &view, QPointF(50, 25));
+ event.setMimeData(&data);
+ qApp->sendEvent(&scene, &event);
+ QVERIFY(event.isAccepted());
+ }
+ {
+ QGraphicsSceneDragDropEvent event(QEvent::GraphicsSceneDragMove);
+ makeDndEvent(&event, &view, QPointF(50, 25));
+ event.setMimeData(&data);
+ qApp->sendEvent(&scene, &event);
+ QVERIFY(!event.isAccepted());
+ }
+ {
+ QGraphicsSceneDragDropEvent event(QEvent::GraphicsSceneDragMove);
+ makeDndEvent(&event, &view, QPointF(50, 75));
+ event.setMimeData(&data);
+ qApp->sendEvent(&scene, &event);
+ QVERIFY(event.isAccepted());
+ }
+ {
+ QGraphicsSceneDragDropEvent event(QEvent::GraphicsSceneDrop);
+ makeDndEvent(&event, &view, QPointF(50, 75));
+ event.setMimeData(&data);
+ qApp->sendEvent(&scene, &event);
+ QVERIFY(event.isAccepted());
+ }
+ QCOMPARE(edit->text(), QString("hei"));
+}
+
+void tst_QGraphicsProxyWidget::windowFlags_data()
+{
+ QTest::addColumn<int>("proxyFlags");
+ QTest::addColumn<int>("widgetFlags");
+ QTest::addColumn<int>("resultingProxyFlags");
+ QTest::addColumn<int>("resultingWidgetFlags");
+
+ QTest::newRow("proxy(0) widget(0)") << 0 << 0 << 0 << int(Qt::Window);
+ QTest::newRow("proxy(window)") << int(Qt::Window) << 0 << int(Qt::Window) << int(Qt::Window);
+ QTest::newRow("proxy(window) widget(window)") << int(Qt::Window) << int(Qt::Window) << int(Qt::Window) << int(Qt::Window);
+ QTest::newRow("proxy(0) widget(window)") << int(0) << int(Qt::Window) << int(0) << int(Qt::Window);
+}
+
+void tst_QGraphicsProxyWidget::windowFlags()
+{
+ QFETCH(int, proxyFlags);
+ QFETCH(int, widgetFlags);
+ QFETCH(int, resultingProxyFlags);
+ QFETCH(int, resultingWidgetFlags);
+ Qt::WindowFlags proxyWFlags = Qt::WindowFlags(proxyFlags);
+ Qt::WindowFlags widgetWFlags = Qt::WindowFlags(widgetFlags);
+ Qt::WindowFlags resultingProxyWFlags = Qt::WindowFlags(resultingProxyFlags);
+ Qt::WindowFlags resultingWidgetWFlags = Qt::WindowFlags(resultingWidgetFlags);
+
+ QGraphicsProxyWidget proxy(0, proxyWFlags);
+ QVERIFY((proxy.windowFlags() & proxyWFlags) == proxyWFlags);
+
+ QWidget *widget = new QWidget(0, widgetWFlags);
+ QVERIFY((widget->windowFlags() & widgetWFlags) == widgetWFlags);
+
+ proxy.setWidget(widget);
+
+ if (resultingProxyFlags == 0)
+ QVERIFY(!proxy.windowFlags());
+ else
+ QVERIFY((proxy.windowFlags() & resultingProxyWFlags) == resultingProxyWFlags);
+ QVERIFY((widget->windowFlags() & resultingWidgetWFlags) == resultingWidgetWFlags);
+}
+
+void tst_QGraphicsProxyWidget::comboboxWindowFlags()
+{
+ QComboBox *comboBox = new QComboBox;
+ comboBox->addItem("Item 1");
+ comboBox->addItem("Item 2");
+ comboBox->addItem("Item 3");
+ QWidget *embedWidget = comboBox;
+
+ QGraphicsScene scene;
+ QGraphicsProxyWidget *proxy = scene.addWidget(embedWidget);
+ proxy->setWindowFlags(Qt::Window);
+ QVERIFY(embedWidget->isWindow());
+ QVERIFY(proxy->isWindow());
+
+ comboBox->showPopup();
+
+ QCOMPARE(proxy->childItems().size(), 1);
+ QGraphicsItem *popupProxy = proxy->childItems().first();
+ QVERIFY(popupProxy->isWindow());
+ QVERIFY((static_cast<QGraphicsWidget *>(popupProxy)->windowFlags() & Qt::Popup) == Qt::Popup);
+}
+
+void tst_QGraphicsProxyWidget::updateAndDelete()
+{
+ QGraphicsScene scene;
+ QGraphicsProxyWidget *proxy = scene.addWidget(new QPushButton("Hello World"));
+ View view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTRY_VERIFY(view.npaints > 0);
+
+ const QRect itemDeviceBoundingRect = proxy->deviceTransform(view.viewportTransform())
+ .mapRect(proxy->boundingRect()).toRect();
+ const QRegion expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2);
+
+ view.npaints = 0;
+ view.paintEventRegion = QRegion();
+
+ // Update and hide.
+ proxy->update();
+ proxy->hide();
+ QTRY_COMPARE(view.npaints, 1);
+ QCOMPARE(view.paintEventRegion, expectedRegion);
+
+ proxy->show();
+ QTest::qWait(50);
+ view.npaints = 0;
+ view.paintEventRegion = QRegion();
+
+ // Update and delete.
+ proxy->update();
+ delete proxy;
+ QTRY_COMPARE(view.npaints, 1);
+ QCOMPARE(view.paintEventRegion, expectedRegion);
+}
+
+class InputMethod_LineEdit : public QLineEdit
+{
+ bool event(QEvent *e)
+ {
+ if (e->type() == QEvent::InputMethod)
+ ++inputMethodEvents;
+ return QLineEdit::event(e);
+ }
+public:
+ int inputMethodEvents;
+};
+
+void tst_QGraphicsProxyWidget::inputMethod()
+{
+ QGraphicsScene scene;
+
+ // check that the proxy is initialized with the correct input method sensitivity
+ for (int i = 0; i < 2; ++i)
+ {
+ QLineEdit *lineEdit = new QLineEdit;
+ lineEdit->setAttribute(Qt::WA_InputMethodEnabled, !!i);
+ QGraphicsProxyWidget *proxy = scene.addWidget(lineEdit);
+ QCOMPARE(!!(proxy->flags() & QGraphicsItem::ItemAcceptsInputMethod), !!i);
+ }
+
+ // check that input method events are only forwarded to widgets with focus
+ for (int i = 0; i < 2; ++i)
+ {
+ InputMethod_LineEdit *lineEdit = new InputMethod_LineEdit;
+ lineEdit->setAttribute(Qt::WA_InputMethodEnabled, true);
+ QGraphicsProxyWidget *proxy = scene.addWidget(lineEdit);
+
+ if (i)
+ lineEdit->setFocus();
+
+ lineEdit->inputMethodEvents = 0;
+ QInputMethodEvent event;
+ qApp->sendEvent(proxy, &event);
+ QCOMPARE(lineEdit->inputMethodEvents, i);
+ }
+
+ scene.clear();
+ QGraphicsView view(&scene);
+ QWidget *w = new QWidget;
+ w->setLayout(new QVBoxLayout(w));
+ QLineEdit *lineEdit = new QLineEdit;
+ lineEdit->setEchoMode(QLineEdit::Password);
+ w->layout()->addWidget(lineEdit);
+ lineEdit->setAttribute(Qt::WA_InputMethodEnabled, true);
+ QGraphicsProxyWidget *proxy = scene.addWidget(w);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(!(proxy->flags() & QGraphicsItem::ItemAcceptsInputMethod));
+ lineEdit->setFocus();
+ QVERIFY((proxy->flags() & QGraphicsItem::ItemAcceptsInputMethod));
+}
+
+void tst_QGraphicsProxyWidget::clickFocus()
+{
+ QGraphicsScene scene;
+ scene.setItemIndexMethod(QGraphicsScene::NoIndex);
+ QGraphicsProxyWidget *proxy = scene.addWidget(new QLineEdit);
+
+ QGraphicsView view(&scene);
+
+ {
+ EventSpy proxySpy(proxy);
+ EventSpy widgetSpy(proxy->widget());
+
+ view.setFrameStyle(0);
+ view.resize(300, 300);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QApplication::setActiveWindow(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
+
+ QVERIFY(!proxy->hasFocus());
+ QVERIFY(!proxy->widget()->hasFocus());
+
+ QCOMPARE(proxySpy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(proxySpy.counts[QEvent::FocusOut], 0);
+ QCOMPARE(widgetSpy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(widgetSpy.counts[QEvent::FocusOut], 0);
+
+ QPointF lineEditCenter = proxy->mapToScene(proxy->boundingRect().center());
+ // Spontaneous mouse click sets focus on a clickable widget.
+ for (int retry = 0; retry < 50 && !proxy->hasFocus(); retry++)
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(lineEditCenter));
+ QVERIFY(proxy->hasFocus());
+ QVERIFY(proxy->widget()->hasFocus());
+ QCOMPARE(proxySpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(widgetSpy.counts[QEvent::FocusIn], 1);
+
+ scene.setFocusItem(0);
+ QVERIFY(!proxy->hasFocus());
+ QVERIFY(!proxy->widget()->hasFocus());
+ QCOMPARE(proxySpy.counts[QEvent::FocusOut], 1);
+ QCOMPARE(widgetSpy.counts[QEvent::FocusOut], 1);
+
+ // Non-spontaneous mouse click sets focus if the widget has been clicked before
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setScenePos(lineEditCenter);
+ event.setButton(Qt::LeftButton);
+ qApp->sendEvent(&scene, &event);
+ QVERIFY(proxy->hasFocus());
+ QVERIFY(proxy->widget()->hasFocus());
+ QCOMPARE(proxySpy.counts[QEvent::FocusIn], 2);
+ QCOMPARE(widgetSpy.counts[QEvent::FocusIn], 2);
+ }
+ }
+
+ scene.setFocusItem(0);
+ proxy->setWidget(new QLineEdit); // resets focusWidget
+
+ {
+ QPointF lineEditCenter = proxy->mapToScene(proxy->boundingRect().center());
+ EventSpy proxySpy(proxy);
+ EventSpy widgetSpy(proxy->widget());
+ QVERIFY(!proxy->hasFocus());
+ QVERIFY(!proxy->widget()->hasFocus());
+ QCOMPARE(proxySpy.counts[QEvent::FocusOut], 0);
+ QCOMPARE(widgetSpy.counts[QEvent::FocusOut], 0);
+
+ // Non-spontaneous mouse click does not set focus on the embedded widget.
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setScenePos(lineEditCenter);
+ event.setButton(Qt::LeftButton);
+ qApp->sendEvent(&scene, &event);
+ QVERIFY(!proxy->hasFocus());
+ QVERIFY(!proxy->widget()->hasFocus());
+ QCOMPARE(proxySpy.counts[QEvent::FocusIn], 0);
+ QCOMPARE(widgetSpy.counts[QEvent::FocusIn], 0);
+ }
+
+ scene.setFocusItem(0);
+ QVERIFY(!proxy->hasFocus());
+ QVERIFY(!proxy->widget()->hasFocus());
+ QCOMPARE(proxySpy.counts[QEvent::FocusOut], 0);
+ QCOMPARE(widgetSpy.counts[QEvent::FocusOut], 0);
+
+ // Spontaneous click on non-clickable widget does not give focus.
+ proxy->widget()->setFocusPolicy(Qt::NoFocus);
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(lineEditCenter));
+ QVERIFY(!proxy->hasFocus());
+ QVERIFY(!proxy->widget()->hasFocus());
+
+ // Multiple clicks should only result in one FocusIn.
+ proxy->widget()->setFocusPolicy(Qt::StrongFocus);
+ scene.setFocusItem(0);
+ QVERIFY(!proxy->hasFocus());
+ QVERIFY(!proxy->widget()->hasFocus());
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(lineEditCenter));
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(lineEditCenter));
+ QVERIFY(proxy->hasFocus());
+ QVERIFY(proxy->widget()->hasFocus());
+ QCOMPARE(widgetSpy.counts[QEvent::FocusIn], 1);
+ QCOMPARE(proxySpy.counts[QEvent::FocusIn], 1);
+ }
+}
+
+void tst_QGraphicsProxyWidget::windowFrameMargins()
+{
+ // Make sure the top margin is non-zero when passing Qt::Window.
+ QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(0, Qt::Window);
+
+ qreal left, top, right, bottom;
+ proxy->getWindowFrameMargins(&left, &top, &right, &bottom);
+ QVERIFY(top > 0);
+
+ proxy->setWidget(new QPushButton("testtest"));
+ proxy->getWindowFrameMargins(&left, &top, &right, &bottom);
+ QVERIFY(top > 0);
+
+ QGraphicsScene scene;
+ scene.addItem(proxy);
+ proxy->getWindowFrameMargins(&left, &top, &right, &bottom);
+ QVERIFY(top > 0);
+
+ proxy->unsetWindowFrameMargins();
+ proxy->getWindowFrameMargins(&left, &top, &right, &bottom);
+ QVERIFY(top > 0);
+}
+
+class HoverButton : public QPushButton
+{
+public:
+ HoverButton(QWidget *parent = 0) : QPushButton(parent), hoverLeaveReceived(false)
+ {}
+
+ bool hoverLeaveReceived;
+
+ bool event(QEvent* e)
+ {
+ if(QEvent::HoverLeave == e->type())
+ hoverLeaveReceived = true;
+ return QPushButton::event(e);
+ }
+};
+
+class Scene : public QGraphicsScene
+{
+Q_OBJECT
+public:
+ Scene() {
+ QWidget *background = new QWidget;
+ background->setGeometry(0, 0, 500, 500);
+ hoverButton = new HoverButton;
+ hoverButton->setParent(background);
+ hoverButton->setText("Second button");
+ hoverButton->setGeometry(10, 10, 200, 50);
+ addWidget(background);
+
+ QPushButton *hideButton = new QPushButton("I'm a button with a very very long text");
+ hideButton->setGeometry(10, 10, 400, 50);
+ topButton = addWidget(hideButton);
+ connect(hideButton, SIGNAL(clicked()), this, SLOT(hideButton()));
+ topButton->setFocus();
+ }
+
+ QGraphicsProxyWidget *topButton;
+ HoverButton *hoverButton;
+
+public slots:
+ void hideButton() {
+ QCursor::setPos(600,600);
+ topButton->hide();
+ }
+};
+
+void tst_QGraphicsProxyWidget::QTBUG_6986_sendMouseEventToAlienWidget()
+{
+#if defined(Q_OS_MAC) || defined(Q_OS_WIN) || defined(QT_NO_CURSOR)
+ QSKIP("Test case unstable on this platform", SkipAll);
+#endif
+ QGraphicsView view;
+ Scene scene;
+ view.setScene(&scene);
+ view.resize(600, 600);
+ QApplication::setActiveWindow(&view);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), &view);
+ QCursor::setPos(view.mapToGlobal(view.mapFromScene(scene.topButton->boundingRect().center())));
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(scene.topButton->scenePos()));
+ QTRY_COMPARE(scene.hoverButton->hoverLeaveReceived, true);
+}
+
+QTEST_MAIN(tst_QGraphicsProxyWidget)
+#include "tst_qgraphicsproxywidget.moc"
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/.gitignore b/tests/auto/widgets/graphicsview/qgraphicsscene/.gitignore
new file mode 100644
index 0000000000..df1097ad74
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/.gitignore
@@ -0,0 +1 @@
+tst_qgraphicsscene
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/Ash_European.jpg b/tests/auto/widgets/graphicsview/qgraphicsscene/Ash_European.jpg
new file mode 100644
index 0000000000..8581d322ba
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/Ash_European.jpg
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/graphicsScene_selection.data b/tests/auto/widgets/graphicsview/qgraphicsscene/graphicsScene_selection.data
new file mode 100644
index 0000000000..8ff3feebb1
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/graphicsScene_selection.data
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/images.qrc b/tests/auto/widgets/graphicsview/qgraphicsscene/images.qrc
new file mode 100644
index 0000000000..cac10bef82
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/images.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>Ash_European.jpg</file>
+</qresource>
+</RCC>
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro b/tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro
new file mode 100644
index 0000000000..75b4d84fb4
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/qgraphicsscene.pro
@@ -0,0 +1,20 @@
+load(qttest_p4)
+QT += widgets widgets-private
+QT += core-private gui-private
+SOURCES += tst_qgraphicsscene.cpp
+RESOURCES += images.qrc
+win32:!wince*: LIBS += -lUser32
+
+!wince*:DEFINES += SRCDIR=\\\"$$PWD\\\"
+DEFINES += QT_NO_CAST_TO_ASCII
+
+wince* {
+ rootFiles.files = Ash_European.jpg graphicsScene_selection.data
+ rootFiles.path = .
+ renderFiles.files = testData\\render\\*
+ renderFiles.path = testData\\render
+ DEPLOYMENT += rootFiles renderFiles
+ DEFINES += SRCDIR=\\\".\\\"
+}
+
+contains(QT_CONFIG,xcb):qpa:CONFIG+=insignificant_test # QTBUG-20756 crashes on qpa, xcb
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-45-deg-left.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-45-deg-left.png
new file mode 100644
index 0000000000..526b897c1c
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-45-deg-left.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-45-deg-right.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-45-deg-right.png
new file mode 100644
index 0000000000..83563872c1
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-45-deg-right.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-scale-2x.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-scale-2x.png
new file mode 100644
index 0000000000..a929621bca
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-scale-2x.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-translate-0-50.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-translate-0-50.png
new file mode 100644
index 0000000000..aeaf20ae41
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-translate-0-50.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-translate-50-0.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-translate-50-0.png
new file mode 100644
index 0000000000..ed80dba118
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-translate-50-0.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed-clip-ellipse.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed-clip-ellipse.png
new file mode 100644
index 0000000000..9b401b41c7
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed-clip-ellipse.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed-clip-rect.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed-clip-rect.png
new file mode 100644
index 0000000000..1c5969870d
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed-clip-rect.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed.png
new file mode 100644
index 0000000000..3592744bda
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-all-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-bottomleft-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-bottomleft-untransformed.png
new file mode 100644
index 0000000000..ab15e7228b
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-bottomleft-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-bottomright-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-bottomright-untransformed.png
new file mode 100644
index 0000000000..82e25762fa
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-bottomright-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-topleft-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-topleft-untransformed.png
new file mode 100644
index 0000000000..934ee4679b
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-topleft-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-topright-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-topright-untransformed.png
new file mode 100644
index 0000000000..aced485c75
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/all-topright-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottom-bottomright-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottom-bottomright-untransformed.png
new file mode 100644
index 0000000000..5df8ab0612
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottom-bottomright-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottom-topleft-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottom-topleft-untransformed.png
new file mode 100644
index 0000000000..bb04881763
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottom-topleft-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomleft-all-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomleft-all-untransformed.png
new file mode 100644
index 0000000000..907dec647d
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomleft-all-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomleft-topleft-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomleft-topleft-untransformed.png
new file mode 100644
index 0000000000..d37313c06d
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomleft-topleft-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomright-all-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomright-all-untransformed.png
new file mode 100644
index 0000000000..9fbafe48d5
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomright-all-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomright-topleft-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomright-topleft-untransformed.png
new file mode 100644
index 0000000000..1d0253796e
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/bottomright-topleft-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/left-bottomright-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/left-bottomright-untransformed.png
new file mode 100644
index 0000000000..bcfda9968b
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/left-bottomright-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/left-topleft-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/left-topleft-untransformed.png
new file mode 100644
index 0000000000..b443a4f991
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/left-topleft-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/right-bottomright-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/right-bottomright-untransformed.png
new file mode 100644
index 0000000000..e6922e0920
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/right-bottomright-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/right-topleft-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/right-topleft-untransformed.png
new file mode 100644
index 0000000000..a74f218876
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/right-topleft-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/top-bottomright-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/top-bottomright-untransformed.png
new file mode 100644
index 0000000000..6c51907a6d
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/top-bottomright-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/top-topleft-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/top-topleft-untransformed.png
new file mode 100644
index 0000000000..0a37133e31
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/top-topleft-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topleft-all-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topleft-all-untransformed.png
new file mode 100644
index 0000000000..edc7dc9ce6
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topleft-all-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topleft-topleft-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topleft-topleft-untransformed.png
new file mode 100644
index 0000000000..e37051f7d2
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topleft-topleft-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topright-all-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topright-all-untransformed.png
new file mode 100644
index 0000000000..a185d14ebd
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topright-all-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topright-topleft-untransformed.png b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topright-topleft-untransformed.png
new file mode 100644
index 0000000000..42e07f11ea
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/testData/render/topright-topleft-untransformed.png
Binary files differ
diff --git a/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp
new file mode 100644
index 0000000000..9ac1573b2a
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsscene/tst_qgraphicsscene.cpp
@@ -0,0 +1,4710 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.1, 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#if defined(Q_OS_WINCE)
+#include <ceconfig.h>
+#endif
+
+#include <QtGui>
+#include <QtWidgets>
+#include <private/qgraphicsscene_p.h>
+#include <private/qgraphicssceneindex_p.h>
+#include <math.h>
+#include "../../../gui/painting/qpathclipper/pathcompare.h"
+
+#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
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+Q_DECLARE_METATYPE(QList<int>)
+Q_DECLARE_METATYPE(QList<QRectF>)
+Q_DECLARE_METATYPE(QMatrix)
+Q_DECLARE_METATYPE(QPainterPath)
+Q_DECLARE_METATYPE(QPointF)
+Q_DECLARE_METATYPE(QRectF)
+Q_DECLARE_METATYPE(Qt::AspectRatioMode)
+Q_DECLARE_METATYPE(Qt::ItemSelectionMode)
+
+static const int randomX[] = {276, 40, 250, 864, -56, 426, 855, 825, 184, 955, -798, -804, 773,
+ 282, 489, 686, 780, -220, 50, 749, -856, -205, 81, 492, -819, 518,
+ 895, 57, -559, 788, -965, 68, -442, -247, -339, -648, 292, 891,
+ -865, 462, 864, 673, 640, 523, 194, 500, -727, 307, -243, 320,
+ -545, 415, 448, 341, -619, 652, 892, -16, -14, -659, -101, -934,
+ 532, 356, 824, 132, 160, 130, 104, 886, -179, -174, 543, -644, 60,
+ -470, -354, -728, 689, 682, -587, -694, -221, -741, 37, 372, -289,
+ 741, -300, 858, -320, 729, -602, -956, -544, -403, 203, 398, 284,
+ -972, -572, -946, 81, 51, -403, -580, 867, 546, 565, -580, -484,
+ 659, 982, -518, -976, 423, -800, 659, -297, 712, 938, -19, -16,
+ 824, -252, 197, 321, -837, 824, 136, 226, -980, -909, -826, -479,
+ -835, -503, -828, -901, -810, -641, -548, -179, 194, 749, -296, 539,
+ -37, -599, -235, 121, 35, -230, -915, 789, 764, -622, -382, -90, -701,
+ 676, -407, 998, 267, 913, 817, -748, -370, -162, -797, 19, -556, 933,
+ -670, -101, -765, -941, -17, 360, 31, 960, 509, 933, -35, 974, -924,
+ -734, 589, 963, 724, 794, 843, 16, -272, -811, 721, 99, -122, 216,
+ -404, 158, 787, -443, -437, -337, 383, -342, 538, -641, 791, 637,
+ -848, 397, 820, 109, 11, 45, 809, 591, 933, 961, 625, -140, -592,
+ -694, -969, 317, 293, 777, -18, -282, 835, -455, -708, -407, -204,
+ 748, 347, -501, -545, 292, -362, 176, 546, -573, -38, -854, -395,
+ 560, -624, -940, -971, 66, -910, 782, 985};
+
+static const int randomY[] = {603, 70, -318, 843, 450, -637, 199, -527, 407, 964, -54, 620, -207,
+ -736, -700, -476, -706, -142, 837, 621, 522, -98, 232, 292, -267, 900,
+ 615, -356, -415, 783, 290, 462, -857, -314, 677, 36, 772, 424, -72,
+ -121, 547, -533, 537, -656, 289, 508, 914, 601, 434, 588, -779, -714,
+ -368, 628, -276, 432, -1, -929, 638, -36, 253, -922, -943, 979, -34,
+ -268, -193, 601, 686, -330, 165, 98, 75, -691, -605, 617, 773, 617,
+ 619, 238, -42, -405, 17, 384, -472, -846, 520, 110, 591, -217, 936,
+ -373, 731, 734, 810, 961, 881, 939, 379, -905, -137, 437, 298, 688,
+ -71, -204, 573, -120, -821, 489, -722, -926, 529, -113, -243, 543,
+ 868, -301, -781, -549, -842, -489, -80, -910, -928, 51, -91, 324,
+ 204, -92, 867, 723, 248, 709, -357, 591, -365, -379, 266, -649, -95,
+ 205, 551, 355, -631, 79, -186, 795, -7, -225, 46, -410, 665, -874,
+ -618, 845, -548, 443, 471, -644, 606, -607, 59, -619, 288, -244, 529,
+ 690, 349, -738, -611, -879, -642, 801, -178, 823, -748, -552, -247,
+ -223, -408, 651, -62, 949, -795, 171, -107, -210, -207, -842, -86,
+ 436, 528, 366, -178, 245, -695, 665, 613, -948, 667, -620, -979, -949,
+ 905, 181, -412, -467, -437, -774, 750, -10, 54, 205, -674, -290, -924,
+ -361, -463, 912, -702, 622, -542, 220, 115, 832, 451, -38, -952, -230,
+ -588, 864, 234, 225, -303, 493, 246, 153, 338, -378, 377, -819, 140, 136,
+ 467, -849, -326, -533, 166, 252, -994, -699, 904, -566, 621, -752};
+
+class HoverItem : public QGraphicsRectItem
+{
+public:
+ HoverItem()
+ : QGraphicsRectItem(QRectF(-10, -10, 20, 20)), isHovered(false)
+ { setAcceptsHoverEvents(true); }
+
+ bool isHovered;
+
+protected:
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
+ {
+ isHovered = (option->state & QStyle::State_MouseOver);
+
+ painter->setOpacity(0.75);
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(Qt::darkGray);
+ painter->drawRoundRect(boundingRect().adjusted(3, 3, -3, -3), Qt::darkGray);
+ painter->setPen(Qt::black);
+ if (isHovered) {
+ painter->setBrush(QColor(Qt::blue).light(120));
+ } else {
+ painter->setBrush(Qt::gray);
+ }
+ painter->drawRoundRect(boundingRect().adjusted(0, 0, -5, -5));
+ }
+};
+
+class EventSpy : public QGraphicsWidget
+{
+ Q_OBJECT
+public:
+ EventSpy(QObject *watched, QEvent::Type type)
+ : _count(0), spied(type)
+ {
+ watched->installEventFilter(this);
+ }
+
+ EventSpy(QGraphicsScene *scene, QGraphicsItem *watched, QEvent::Type type)
+ : _count(0), spied(type)
+ {
+ scene->addItem(this);
+ watched->installSceneEventFilter(this);
+ }
+
+ int count() const { return _count; }
+
+protected:
+ bool eventFilter(QObject *watched, QEvent *event)
+ {
+ Q_UNUSED(watched);
+ if (event->type() == spied)
+ ++_count;
+ return false;
+ }
+
+ bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
+ {
+ Q_UNUSED(watched);
+ if (event->type() == spied)
+ ++_count;
+ return false;
+ }
+
+ int _count;
+ QEvent::Type spied;
+};
+
+class tst_QGraphicsScene : public QObject
+{
+ Q_OBJECT
+public slots:
+ void initTestCase();
+
+private slots:
+ void construction();
+ void sceneRect();
+ void itemIndexMethod();
+ void bspTreeDepth();
+ void itemsBoundingRect_data();
+ void itemsBoundingRect();
+ void items();
+ void items_QPointF_data();
+ void items_QPointF();
+ void items_QRectF();
+ void items_QRectF_2_data();
+ void items_QRectF_2();
+ void items_QPolygonF();
+ void items_QPolygonF_2();
+ void items_QPainterPath();
+ void items_QPainterPath_2();
+ void selection();
+ void selectionChanged();
+ void selectionChanged2();
+ void addItem();
+ void addEllipse();
+ void addLine();
+ void addPath();
+ void addPixmap();
+ void addRect();
+ void addText();
+#if !defined(Q_OS_WINCE) || defined(GWES_ICONCURS)
+ void removeItem();
+#endif
+ void clear();
+ void focusItem();
+ void focusItemLostFocus();
+ void setFocusItem();
+ void setFocusItem_inactive();
+ void mouseGrabberItem();
+ void hoverEvents_siblings();
+ void hoverEvents_parentChild();
+ void createItemGroup();
+ void mouseEventPropagation();
+ void mouseEventPropagation_ignore();
+ void mouseEventPropagation_focus();
+ void mouseEventPropagation_doubleclick();
+ void mouseEventPropagation_mouseMove();
+#ifndef QT_NO_DRAGANDDROP
+ void dragAndDrop_simple();
+ void dragAndDrop_disabledOrInvisible();
+ void dragAndDrop_propagate();
+#endif
+ void render_data();
+ void render();
+ void renderItemsWithNegativeWidthOrHeight();
+ void contextMenuEvent();
+ void contextMenuEvent_ItemIgnoresTransformations();
+ void update();
+ void update2();
+ void views();
+ void event();
+ void eventsToDisabledItems();
+ void exposedRect();
+ void tabFocus_emptyScene();
+ void tabFocus_sceneWithFocusableItems();
+ void tabFocus_sceneWithFocusWidgets();
+ void tabFocus_sceneWithNestedFocusWidgets();
+ void style();
+ void sorting_data();
+ void sorting();
+ void changedSignal_data();
+ void changedSignal();
+ void stickyFocus_data();
+ void stickyFocus();
+ void sendEvent();
+ void inputMethod_data();
+ void inputMethod();
+ void dispatchHoverOnPress();
+ void initialFocus_data();
+ void initialFocus();
+ void polishItems();
+ void polishItems2();
+ void isActive();
+ void siblingIndexAlwaysValid();
+ void removeFullyTransparentItem();
+ void zeroScale();
+
+ // task specific tests below me
+ void task139710_bspTreeCrash();
+ void task139782_containsItemBoundingRect();
+ void task176178_itemIndexMethodBreaksSceneRect();
+ void task160653_selectionChanged();
+ void task250680_childClip();
+ void taskQTBUG_5904_crashWithDeviceCoordinateCache();
+ void taskQT657_paintIntoCacheWithTransparentParts();
+ void taskQTBUG_7863_paintIntoCacheWithTransparentParts();
+ void taskQT_3674_doNotCrash();
+ void taskQTBUG_15977_renderWithDeviceCoordinateCache();
+ void taskQTBUG_16401_focusItem();
+};
+
+void tst_QGraphicsScene::initTestCase()
+{
+#ifdef Q_OS_WINCE //disable magic for WindowsCE
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+}
+
+void tst_QGraphicsScene::construction()
+{
+ QGraphicsScene scene;
+ QCOMPARE(scene.itemsBoundingRect(), QRectF());
+ QVERIFY(scene.items().isEmpty());
+ QVERIFY(scene.items(QPointF()).isEmpty());
+ QVERIFY(scene.items(QRectF()).isEmpty());
+ QVERIFY(scene.items(QPolygonF()).isEmpty());
+ QVERIFY(scene.items(QPainterPath()).isEmpty());
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsScene::collidingItems: cannot find collisions for null item");
+ QVERIFY(scene.collidingItems(0).isEmpty());
+ QVERIFY(!scene.itemAt(QPointF()));
+ QVERIFY(scene.selectedItems().isEmpty());
+ QVERIFY(!scene.focusItem());
+}
+
+void tst_QGraphicsScene::sceneRect()
+{
+ QGraphicsScene scene;
+ QSignalSpy sceneRectChanged(&scene, SIGNAL(sceneRectChanged(QRectF)));
+ QCOMPARE(scene.sceneRect(), QRectF());
+ QCOMPARE(sceneRectChanged.count(), 0);
+
+ QGraphicsItem *item = scene.addRect(QRectF(0, 0, 10, 10));
+ item->setPos(-5, -5);
+ QCOMPARE(sceneRectChanged.count(), 0);
+
+ QCOMPARE(scene.itemAt(0, 0), item);
+ QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0);
+ QCOMPARE(sceneRectChanged.count(), 0);
+ QCOMPARE(scene.sceneRect(), QRectF(-5, -5, 10, 10));
+ QCOMPARE(sceneRectChanged.count(), 1);
+ QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect());
+
+ item->setPos(0, 0);
+ QCOMPARE(scene.sceneRect(), QRectF(-5, -5, 15, 15));
+ QCOMPARE(sceneRectChanged.count(), 2);
+ QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect());
+
+ scene.setSceneRect(-100, -100, 10, 10);
+ QCOMPARE(sceneRectChanged.count(), 3);
+ QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect());
+
+ QCOMPARE(scene.itemAt(0, 0), item);
+ QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0);
+ QCOMPARE(scene.sceneRect(), QRectF(-100, -100, 10, 10));
+ item->setPos(10, 10);
+ QCOMPARE(scene.sceneRect(), QRectF(-100, -100, 10, 10));
+ QCOMPARE(sceneRectChanged.count(), 3);
+ QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect());
+
+ scene.setSceneRect(QRectF());
+
+ QCOMPARE(scene.itemAt(10, 10), item);
+ QCOMPARE(scene.itemAt(20, 20), (QGraphicsItem *)0);
+ QCOMPARE(sceneRectChanged.count(), 4);
+ QCOMPARE(scene.sceneRect(), QRectF(-5, -5, 25, 25));
+ QCOMPARE(sceneRectChanged.count(), 5);
+ QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect());
+}
+
+void tst_QGraphicsScene::itemIndexMethod()
+{
+ QGraphicsScene scene;
+ QCOMPARE(scene.itemIndexMethod(), QGraphicsScene::BspTreeIndex);
+
+#ifdef QT_ARCH_ARM
+ const int minY = -500;
+ const int maxY = 500;
+ const int minX = -500;
+ const int maxX = 500;
+#else
+ const int minY = -1000;
+ const int maxY = 2000;
+ const int minX = -1000;
+ const int maxX = 2000;
+#endif
+
+ QList<QGraphicsItem *> items;
+ for (int y = minY; y < maxY; y += 100) {
+ for (int x = minX; x < maxX; x += 100) {
+ QGraphicsItem *item = scene.addRect(QRectF(0, 0, 10, 10));
+ item->setPos(x, y);
+ QCOMPARE(scene.itemAt(x, y), item);
+ items << item;
+ }
+ }
+
+ int n = 0;
+ for (int y = minY; y < maxY; y += 100) {
+ for (int x = minX; x < maxX; x += 100)
+ QCOMPARE(scene.itemAt(x, y), items.at(n++));
+ }
+
+ scene.setItemIndexMethod(QGraphicsScene::NoIndex);
+ QCOMPARE(scene.itemIndexMethod(), QGraphicsScene::NoIndex);
+
+ n = 0;
+ for (int y = minY; y < maxY; y += 100) {
+ for (int x = minX; x < maxX; x += 100)
+ QCOMPARE(scene.itemAt(x, y), items.at(n++));
+ }
+
+ scene.setItemIndexMethod(QGraphicsScene::BspTreeIndex);
+ QCOMPARE(scene.itemIndexMethod(), QGraphicsScene::BspTreeIndex);
+
+ n = 0;
+ for (int y = minY; y < maxY; y += 100) {
+ for (int x = minX; x < maxX; x += 100)
+ QCOMPARE(scene.itemAt(x, y), items.at(n++));
+ }
+}
+
+void tst_QGraphicsScene::bspTreeDepth()
+{
+ QGraphicsScene scene;
+ QCOMPARE(scene.itemIndexMethod(), QGraphicsScene::BspTreeIndex);
+ QCOMPARE(scene.bspTreeDepth(), 0);
+ scene.setBspTreeDepth(1);
+ QCOMPARE(scene.bspTreeDepth(), 1);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsScene::setBspTreeDepth: invalid depth -1 ignored; must be >= 0");
+ scene.setBspTreeDepth(-1);
+ QCOMPARE(scene.bspTreeDepth(), 1);
+}
+
+void tst_QGraphicsScene::items()
+{
+#ifdef QT_ARCH_ARM
+ const int minY = -500;
+ const int maxY = 500;
+ const int minX = -500;
+ const int maxX = 500;
+#else
+ const int minY = -1000;
+ const int maxY = 2000;
+ const int minX = -1000;
+ const int maxX = 2000;
+#endif
+
+ {
+ QGraphicsScene scene;
+
+ QList<QGraphicsItem *> items;
+ for (int y = minY; y < maxY; y += 100) {
+ for (int x = minX; x < maxX; x += 100)
+ items << scene.addRect(QRectF(0, 0, 10, 10));
+ }
+ QCOMPARE(scene.items().size(), items.size());
+ scene.itemAt(0, 0); // trigger indexing
+
+ scene.removeItem(items.at(5));
+ delete items.at(5);
+ QVERIFY(!scene.items().contains(0));
+ delete items.at(7);
+ QVERIFY(!scene.items().contains(0));
+ }
+ {
+ QGraphicsScene scene;
+ QGraphicsLineItem *l1 = scene.addLine(-5, 0, 5, 0);
+ QGraphicsLineItem *l2 = scene.addLine(0, -5, 0, 5);
+ QVERIFY(!l1->sceneBoundingRect().intersects(l2->sceneBoundingRect()));
+ QVERIFY(!l2->sceneBoundingRect().intersects(l1->sceneBoundingRect()));
+ QList<QGraphicsItem *> items;
+ items<<l1<<l2;
+ QCOMPARE(scene.items().size(), items.size());
+ QVERIFY(scene.items(-1, -1, 2, 2).contains(l1));
+ QVERIFY(scene.items(-1, -1, 2, 2).contains(l2));
+ }
+}
+
+void tst_QGraphicsScene::itemsBoundingRect_data()
+{
+ QTest::addColumn<QList<QRectF> >("rects");
+ QTest::addColumn<QMatrix>("matrix");
+ QTest::addColumn<QRectF>("boundingRect");
+
+ QMatrix transformationMatrix;
+ transformationMatrix.translate(50, -50);
+ transformationMatrix.scale(2, 2);
+ transformationMatrix.rotate(90);
+
+ QTest::newRow("none")
+ << QList<QRectF>()
+ << QMatrix()
+ << QRectF();
+ QTest::newRow("{{0, 0, 10, 10}}")
+ << (QList<QRectF>() << QRectF(0, 0, 10, 10))
+ << QMatrix()
+ << QRectF(0, 0, 10, 10);
+ QTest::newRow("{{-10, -10, 10, 10}}")
+ << (QList<QRectF>() << QRectF(-10, -10, 10, 10))
+ << QMatrix()
+ << QRectF(-10, -10, 10, 10);
+ QTest::newRow("{{-1000, -1000, 1, 1}, {-10, -10, 10, 10}}")
+ << (QList<QRectF>() << QRectF(-1000, -1000, 1, 1) << QRectF(-10, -10, 10, 10))
+ << QMatrix()
+ << QRectF(-1000, -1000, 1000, 1000);
+ QTest::newRow("transformed {{0, 0, 10, 10}}")
+ << (QList<QRectF>() << QRectF(0, 0, 10, 10))
+ << transformationMatrix
+ << QRectF(30, -50, 20, 20);
+ QTest::newRow("transformed {{-10, -10, 10, 10}}")
+ << (QList<QRectF>() << QRectF(-10, -10, 10, 10))
+ << transformationMatrix
+ << QRectF(50, -70, 20, 20);
+ QTest::newRow("transformed {{-1000, -1000, 1, 1}, {-10, -10, 10, 10}}")
+ << (QList<QRectF>() << QRectF(-1000, -1000, 1, 1) << QRectF(-10, -10, 10, 10))
+ << transformationMatrix
+ << QRectF(50, -2050, 2000, 2000);
+
+ QList<QRectF> all;
+ for (int i = 0; i < 256; ++i)
+ all << QRectF(randomX[i], randomY[i], 10, 10);
+ QTest::newRow("all")
+ << all
+ << QMatrix()
+ << QRectF(-980, -994, 1988, 1983);
+ QTest::newRow("transformed all")
+ << all
+ << transformationMatrix
+ << QRectF(-1928, -2010, 3966, 3976);
+}
+
+void tst_QGraphicsScene::itemsBoundingRect()
+{
+ QFETCH(QList<QRectF>, rects);
+ QFETCH(QMatrix, matrix);
+ QFETCH(QRectF, boundingRect);
+
+ QGraphicsScene scene;
+
+ foreach (QRectF rect, rects) {
+ QPainterPath path;
+ path.addRect(rect);
+ scene.addPath(path)->setMatrix(matrix);
+ }
+
+ QCOMPARE(scene.itemsBoundingRect(), boundingRect);
+}
+
+void tst_QGraphicsScene::items_QPointF_data()
+{
+ QTest::addColumn<QList<QRectF> >("items");
+ QTest::addColumn<QPointF>("point");
+ QTest::addColumn<QList<int> >("itemsAtPoint");
+
+ QTest::newRow("empty")
+ << QList<QRectF>()
+ << QPointF()
+ << QList<int>();
+ QTest::newRow("1")
+ << (QList<QRectF>() << QRectF(0, 0, 10, 10))
+ << QPointF(0, 0)
+ << (QList<int>() << 0);
+ QTest::newRow("2")
+ << (QList<QRectF>() << QRectF(0, 0, 10, 10))
+ << QPointF(5, 5)
+ << (QList<int>() << 0);
+ QTest::newRow("3")
+ << (QList<QRectF>() << QRectF(0, 0, 10, 10))
+ << QPointF(9.9, 9.9)
+ << (QList<int>() << 0);
+ QTest::newRow("3.5")
+ << (QList<QRectF>() << QRectF(0, 0, 10, 10))
+ << QPointF(10, 10)
+ << QList<int>();
+ QTest::newRow("4")
+ << (QList<QRectF>() << QRectF(0, 0, 10, 10) << QRectF(9.9, 9.9, 10, 10))
+ << QPointF(9.9, 9.9)
+ << (QList<int>() << 1 << 0);
+ QTest::newRow("4.5")
+ << (QList<QRectF>() << QRectF(0, 0, 10, 10) << QRectF(10, 10, 10, 10))
+ << QPointF(10, 10)
+ << (QList<int>() << 1);
+ QTest::newRow("5")
+ << (QList<QRectF>() << QRectF(5, 5, 10, 10) << QRectF(10, 10, 10, 10))
+ << QPointF(10, 10)
+ << (QList<int>() << 1 << 0);
+ QTest::newRow("6")
+ << (QList<QRectF>() << QRectF(5, 5, 10, 10) << QRectF(10, 10, 10, 10) << QRectF(0, 0, 20, 30))
+ << QPointF(10, 10)
+ << (QList<int>() << 2 << 1 << 0);
+}
+
+void tst_QGraphicsScene::items_QPointF()
+{
+ QFETCH(QList<QRectF>, items);
+ QFETCH(QPointF, point);
+ QFETCH(QList<int>, itemsAtPoint);
+
+ QGraphicsScene scene;
+
+ int n = 0;
+ QList<QGraphicsItem *> addedItems;
+ foreach(QRectF rect, items) {
+ QPainterPath path;
+ path.addRect(0, 0, rect.width(), rect.height());
+
+ QGraphicsItem *item = scene.addPath(path);
+ item->setZValue(n++);
+ item->setPos(rect.topLeft());
+ addedItems << item;
+ }
+
+ QList<int> itemIndexes;
+ foreach (QGraphicsItem *item, scene.items(point))
+ itemIndexes << addedItems.indexOf(item);
+
+ QCOMPARE(itemIndexes, itemsAtPoint);
+}
+
+void tst_QGraphicsScene::items_QRectF()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *item1 = scene.addRect(QRectF(-10, -10, 10, 10));
+ QGraphicsItem *item2 = scene.addRect(QRectF(10, -10, 10, 10));
+ QGraphicsItem *item3 = scene.addRect(QRectF(10, 10, 10, 10));
+ QGraphicsItem *item4 = scene.addRect(QRectF(-10, 10, 10, 10));
+
+ item1->setZValue(0);
+ item2->setZValue(1);
+ item3->setZValue(2);
+ item4->setZValue(3);
+
+ QCOMPARE(scene.items(QRectF(-10, -10, 10, 10)), QList<QGraphicsItem *>() << item1);
+ QCOMPARE(scene.items(QRectF(10, -10, 10, 10)), QList<QGraphicsItem *>() << item2);
+ QCOMPARE(scene.items(QRectF(10, 10, 10, 10)), QList<QGraphicsItem *>() << item3);
+ QCOMPARE(scene.items(QRectF(-10, 10, 10, 10)), QList<QGraphicsItem *>() << item4);
+ QCOMPARE(scene.items(QRectF(-10, -10, 1, 1)), QList<QGraphicsItem *>() << item1);
+ QCOMPARE(scene.items(QRectF(10, -10, 1, 1)), QList<QGraphicsItem *>() << item2);
+ QCOMPARE(scene.items(QRectF(10, 10, 1, 1)), QList<QGraphicsItem *>() << item3);
+ QCOMPARE(scene.items(QRectF(-10, 10, 1, 1)), QList<QGraphicsItem *>() << item4);
+
+ QCOMPARE(scene.items(QRectF(-10, -10, 40, 10)), QList<QGraphicsItem *>() << item2 << item1);
+ QCOMPARE(scene.items(QRectF(-10, 10, 40, 10)), QList<QGraphicsItem *>() << item4 << item3);
+
+ item1->setZValue(3);
+ item2->setZValue(2);
+ item3->setZValue(1);
+ item4->setZValue(0);
+
+ QCOMPARE(scene.items(QRectF(-10, -10, 40, 10)), QList<QGraphicsItem *>() << item1 << item2);
+ QCOMPARE(scene.items(QRectF(-10, 10, 40, 10)), QList<QGraphicsItem *>() << item3 << item4);
+}
+
+void tst_QGraphicsScene::items_QRectF_2_data()
+{
+ QTest::addColumn<QRectF>("ellipseRect");
+ QTest::addColumn<QRectF>("sceneRect");
+ QTest::addColumn<Qt::ItemSelectionMode>("selectionMode");
+ QTest::addColumn<bool>("contained");
+ QTest::addColumn<bool>("containedRotated");
+
+ // None of the rects contain the ellipse's shape nor bounding rect
+ QTest::newRow("1") << QRectF(0, 0, 100, 100) << QRectF(1, 1, 10, 10) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("2") << QRectF(0, 0, 100, 100) << QRectF(1, 89, 10, 10) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("3") << QRectF(0, 0, 100, 100) << QRectF(89, 1, 10, 10) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("4") << QRectF(0, 0, 100, 100) << QRectF(89, 89, 10, 10) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("5") << QRectF(0, 0, 100, 100) << QRectF(1, 1, 10, 10) << Qt::ContainsItemBoundingRect << false << false;
+ QTest::newRow("6") << QRectF(0, 0, 100, 100) << QRectF(1, 89, 10, 10) << Qt::ContainsItemBoundingRect << false << false;
+ QTest::newRow("7") << QRectF(0, 0, 100, 100) << QRectF(89, 1, 10, 10) << Qt::ContainsItemBoundingRect << false << false;
+ QTest::newRow("8") << QRectF(0, 0, 100, 100) << QRectF(89, 89, 10, 10) << Qt::ContainsItemBoundingRect << false << false;
+ QTest::newRow("9") << QRectF(0, 0, 100, 100) << QRectF(0, 0, 50, 50) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("10") << QRectF(0, 0, 100, 100) << QRectF(0, 50, 50, 50) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("11") << QRectF(0, 0, 100, 100) << QRectF(50, 0, 50, 50) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("12") << QRectF(0, 0, 100, 100) << QRectF(50, 50, 50, 50) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("13") << QRectF(0, 0, 100, 100) << QRectF(0, 0, 50, 50) << Qt::ContainsItemBoundingRect << false << false;
+ QTest::newRow("14") << QRectF(0, 0, 100, 100) << QRectF(0, 50, 50, 50) << Qt::ContainsItemBoundingRect << false << false;
+ QTest::newRow("15") << QRectF(0, 0, 100, 100) << QRectF(50, 0, 50, 50) << Qt::ContainsItemBoundingRect << false << false;
+ QTest::newRow("16") << QRectF(0, 0, 100, 100) << QRectF(50, 50, 50, 50) << Qt::ContainsItemBoundingRect << false << false;
+ QTest::newRow("17") << QRectF(0, 0, 100, 100) << QRectF(-50, -50, 100, 100) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("18") << QRectF(0, 0, 100, 100) << QRectF(0, -50, 100, 100) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("19") << QRectF(0, 0, 100, 100) << QRectF(-50, 0, 100, 100) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("20") << QRectF(0, 0, 100, 100) << QRectF(0, 0, 100, 100) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("21") << QRectF(0, 0, 100, 100) << QRectF(-50, -50, 100, 100) << Qt::ContainsItemBoundingRect << false << false;
+ QTest::newRow("22") << QRectF(0, 0, 100, 100) << QRectF(0, -50, 100, 100) << Qt::ContainsItemBoundingRect << false << false;
+ QTest::newRow("23") << QRectF(0, 0, 100, 100) << QRectF(-50, 0, 100, 100) << Qt::ContainsItemBoundingRect << false << false;
+
+ // The rect is the same as the ellipse's bounding rect
+ QTest::newRow("24") << QRectF(0, 0, 100, 100) << QRectF(0, 0, 100, 100) << Qt::ContainsItemBoundingRect << false << false;
+
+ // None intersects with the item's shape, but they all intersects with the
+ // item's bounding rect.
+ QTest::newRow("25") << QRectF(0, 0, 100, 100) << QRectF(1, 1, 10, 10) << Qt::IntersectsItemShape << false << false;
+ QTest::newRow("26") << QRectF(0, 0, 100, 100) << QRectF(1, 89, 10, 10) << Qt::IntersectsItemShape << false << true;
+ QTest::newRow("27") << QRectF(0, 0, 100, 100) << QRectF(89, 1, 10, 10) << Qt::IntersectsItemShape << false << false;
+ QTest::newRow("28") << QRectF(0, 0, 100, 100) << QRectF(89, 89, 10, 10) << Qt::IntersectsItemShape << false << false;
+ QTest::newRow("29") << QRectF(0, 0, 100, 100) << QRectF(1, 1, 10, 10) << Qt::IntersectsItemBoundingRect << true << true;
+ QTest::newRow("30") << QRectF(0, 0, 100, 100) << QRectF(1, 89, 10, 10) << Qt::IntersectsItemBoundingRect << true << true;
+ QTest::newRow("31") << QRectF(0, 0, 100, 100) << QRectF(89, 1, 10, 10) << Qt::IntersectsItemBoundingRect << true << false;
+ QTest::newRow("32") << QRectF(0, 0, 100, 100) << QRectF(89, 89, 10, 10) << Qt::IntersectsItemBoundingRect << true << false;
+
+ // This rect does not contain the shape nor the bounding rect
+ QTest::newRow("33") << QRectF(0, 0, 100, 100) << QRectF(5, 5, 90, 90) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("34") << QRectF(0, 0, 100, 100) << QRectF(5, 5, 90, 90) << Qt::ContainsItemBoundingRect << false << false;
+
+ // It will, however, intersect with both
+ QTest::newRow("35") << QRectF(0, 0, 100, 100) << QRectF(5, 5, 90, 90) << Qt::IntersectsItemShape << true << true;
+ QTest::newRow("36") << QRectF(0, 0, 100, 100) << QRectF(5, 5, 90, 90) << Qt::IntersectsItemBoundingRect << true << true;
+
+ // A rect that contains the whole ellipse will both contain and intersect
+ // with both the ellipse's shape and bounding rect.
+ QTest::newRow("37") << QRectF(0, 0, 100, 100) << QRectF(-5, -5, 110, 110) << Qt::IntersectsItemBoundingRect << true << true;
+ QTest::newRow("38") << QRectF(0, 0, 100, 100) << QRectF(-5, -5, 110, 110) << Qt::IntersectsItemShape << true << true;
+ QTest::newRow("39") << QRectF(0, 0, 100, 100) << QRectF(-5, -5, 110, 110) << Qt::ContainsItemBoundingRect << true << false;
+ QTest::newRow("40") << QRectF(0, 0, 100, 100) << QRectF(-5, -5, 110, 110) << Qt::ContainsItemShape << true << false;
+
+ // A rect that is fully contained within the ellipse will intersect only
+ QTest::newRow("41") << QRectF(0, 0, 100, 100) << QRectF(40, 40, 20, 20) << Qt::ContainsItemShape << false << false;
+ QTest::newRow("42") << QRectF(0, 0, 100, 100) << QRectF(40, 40, 20, 20) << Qt::ContainsItemBoundingRect << false << false;
+ QTest::newRow("43") << QRectF(0, 0, 100, 100) << QRectF(40, 40, 20, 20) << Qt::IntersectsItemShape << true << true;
+ QTest::newRow("44") << QRectF(0, 0, 100, 100) << QRectF(40, 40, 20, 20) << Qt::IntersectsItemBoundingRect << true << true;
+}
+
+void tst_QGraphicsScene::items_QRectF_2()
+{
+ QFETCH(QRectF, ellipseRect);
+ QFETCH(QRectF, sceneRect);
+ QFETCH(Qt::ItemSelectionMode, selectionMode);
+ QFETCH(bool, contained);
+ QFETCH(bool, containedRotated);
+
+ QGraphicsScene scene;
+ QGraphicsItem *item = scene.addEllipse(ellipseRect);
+
+ QCOMPARE(!scene.items(sceneRect, selectionMode).isEmpty(), contained);
+ item->rotate(45);
+ QCOMPARE(!scene.items(sceneRect, selectionMode).isEmpty(), containedRotated);
+}
+
+void tst_QGraphicsScene::items_QPolygonF()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *item1 = scene.addRect(QRectF(-10, -10, 10, 10));
+ QGraphicsItem *item2 = scene.addRect(QRectF(10, -10, 10, 10));
+ QGraphicsItem *item3 = scene.addRect(QRectF(10, 10, 10, 10));
+ QGraphicsItem *item4 = scene.addRect(QRectF(-10, 10, 10, 10));
+
+ item1->setZValue(0);
+ item2->setZValue(1);
+ item3->setZValue(2);
+ item4->setZValue(3);
+
+ QPolygonF poly1(item1->boundingRect());
+ QPolygonF poly2(item2->boundingRect());
+ QPolygonF poly3(item3->boundingRect());
+ QPolygonF poly4(item4->boundingRect());
+
+ QCOMPARE(scene.items(poly1), QList<QGraphicsItem *>() << item1);
+ QCOMPARE(scene.items(poly2), QList<QGraphicsItem *>() << item2);
+ QCOMPARE(scene.items(poly3), QList<QGraphicsItem *>() << item3);
+ QCOMPARE(scene.items(poly4), QList<QGraphicsItem *>() << item4);
+
+ poly1 = QPolygonF(QRectF(-10, -10, 1, 1));
+ poly2 = QPolygonF(QRectF(10, -10, 1, 1));
+ poly3 = QPolygonF(QRectF(10, 10, 1, 1));
+ poly4 = QPolygonF(QRectF(-10, 10, 1, 1));
+
+ QCOMPARE(scene.items(poly1), QList<QGraphicsItem *>() << item1);
+ QCOMPARE(scene.items(poly2), QList<QGraphicsItem *>() << item2);
+ QCOMPARE(scene.items(poly3), QList<QGraphicsItem *>() << item3);
+ QCOMPARE(scene.items(poly4), QList<QGraphicsItem *>() << item4);
+
+ poly1 = QPolygonF(QRectF(-10, -10, 40, 10));
+ poly2 = QPolygonF(QRectF(-10, 10, 40, 10));
+
+ QCOMPARE(scene.items(poly1), QList<QGraphicsItem *>() << item2 << item1);
+ QCOMPARE(scene.items(poly2), QList<QGraphicsItem *>() << item4 << item3);
+
+ item1->setZValue(3);
+ item2->setZValue(2);
+ item3->setZValue(1);
+ item4->setZValue(0);
+
+ QCOMPARE(scene.items(poly1), QList<QGraphicsItem *>() << item1 << item2);
+ QCOMPARE(scene.items(poly2), QList<QGraphicsItem *>() << item3 << item4);
+}
+
+void tst_QGraphicsScene::items_QPolygonF_2()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *ellipse = scene.addEllipse(QRectF(0, 0, 100, 100));
+
+ // None of the rects contain the ellipse's shape nor bounding rect
+ QVERIFY(scene.items(QPolygonF(QRectF(1, 1, 10, 10)), Qt::ContainsItemShape).isEmpty());
+ QVERIFY(scene.items(QPolygonF(QRectF(1, 89, 10, 10)), Qt::ContainsItemShape).isEmpty());
+ QVERIFY(scene.items(QPolygonF(QRectF(89, 1, 10, 10)), Qt::ContainsItemShape).isEmpty());
+ QVERIFY(scene.items(QPolygonF(QRectF(89, 89, 10, 10)), Qt::ContainsItemShape).isEmpty());
+ QVERIFY(scene.items(QPolygonF(QRectF(1, 1, 10, 10)), Qt::ContainsItemBoundingRect).isEmpty());
+ QVERIFY(scene.items(QPolygonF(QRectF(1, 89, 10, 10)), Qt::ContainsItemBoundingRect).isEmpty());
+ QVERIFY(scene.items(QPolygonF(QRectF(89, 1, 10, 10)), Qt::ContainsItemBoundingRect).isEmpty());
+ QVERIFY(scene.items(QPolygonF(QRectF(89, 89, 10, 10)), Qt::ContainsItemBoundingRect).isEmpty());
+
+ // None intersects with the item's shape, but they all intersects with the
+ // item's bounding rect.
+ QVERIFY(scene.items(QPolygonF(QRectF(1, 1, 10, 10)), Qt::IntersectsItemShape).isEmpty());
+ QVERIFY(scene.items(QPolygonF(QRectF(1, 89, 10, 10)), Qt::IntersectsItemShape).isEmpty());
+ QVERIFY(scene.items(QPolygonF(QRectF(89, 1, 10, 10)), Qt::IntersectsItemShape).isEmpty());
+ QVERIFY(scene.items(QPolygonF(QRectF(89, 89, 10, 10)), Qt::IntersectsItemShape).isEmpty());
+ QCOMPARE(scene.items(QPolygonF(QRectF(1, 1, 10, 10)), Qt::IntersectsItemBoundingRect).first(), ellipse);
+ QCOMPARE(scene.items(QPolygonF(QRectF(1, 89, 10, 10)), Qt::IntersectsItemBoundingRect).first(), ellipse);
+ QCOMPARE(scene.items(QPolygonF(QRectF(89, 1, 10, 10)), Qt::IntersectsItemBoundingRect).first(), ellipse);
+ QCOMPARE(scene.items(QPolygonF(QRectF(89, 89, 10, 10)), Qt::IntersectsItemBoundingRect).first(), ellipse);
+
+ // This rect does not contain the shape nor the bounding rect
+ QVERIFY(scene.items(QPolygonF(QRectF(5, 5, 90, 90)), Qt::ContainsItemShape).isEmpty());
+ QVERIFY(scene.items(QPolygonF(QRectF(5, 5, 90, 90)), Qt::ContainsItemBoundingRect).isEmpty());
+
+ // It will, however, intersect with both
+ QCOMPARE(scene.items(QPolygonF(QRectF(5, 5, 90, 90)), Qt::IntersectsItemShape).first(), ellipse);
+ QCOMPARE(scene.items(QPolygonF(QRectF(5, 5, 90, 90)), Qt::IntersectsItemBoundingRect).first(), ellipse);
+
+ // A rect that contains the whole ellipse will both contain and intersect
+ // with both the ellipse's shape and bounding rect.
+ QCOMPARE(scene.items(QPolygonF(QRectF(-5, -5, 110, 110)), Qt::IntersectsItemShape).first(), ellipse);
+ QCOMPARE(scene.items(QPolygonF(QRectF(-5, -5, 110, 110)), Qt::ContainsItemShape).first(), ellipse);
+ QCOMPARE(scene.items(QPolygonF(QRectF(-5, -5, 110, 110)), Qt::IntersectsItemBoundingRect).first(), ellipse);
+ QCOMPARE(scene.items(QPolygonF(QRectF(-5, -5, 110, 110)), Qt::ContainsItemBoundingRect).first(), ellipse);
+}
+
+void tst_QGraphicsScene::items_QPainterPath()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *item1 = scene.addRect(QRectF(-10, -10, 10, 10));
+ QGraphicsItem *item2 = scene.addRect(QRectF(10, -10, 10, 10));
+ QGraphicsItem *item3 = scene.addRect(QRectF(10, 10, 10, 10));
+ QGraphicsItem *item4 = scene.addRect(QRectF(-10, 10, 10, 10));
+
+ item1->setZValue(0);
+ item2->setZValue(1);
+ item3->setZValue(2);
+ item4->setZValue(3);
+
+ QPainterPath path1; path1.addEllipse(item1->boundingRect());
+ QPainterPath path2; path2.addEllipse(item2->boundingRect());
+ QPainterPath path3; path3.addEllipse(item3->boundingRect());
+ QPainterPath path4; path4.addEllipse(item4->boundingRect());
+
+ QCOMPARE(scene.items(path1), QList<QGraphicsItem *>() << item1);
+ QCOMPARE(scene.items(path2), QList<QGraphicsItem *>() << item2);
+ QCOMPARE(scene.items(path3), QList<QGraphicsItem *>() << item3);
+ QCOMPARE(scene.items(path4), QList<QGraphicsItem *>() << item4);
+
+ path1 = QPainterPath(); path1.addEllipse(QRectF(-10, -10, 1, 1));
+ path2 = QPainterPath(); path2.addEllipse(QRectF(10, -10, 1, 1));
+ path3 = QPainterPath(); path3.addEllipse(QRectF(10, 10, 1, 1));
+ path4 = QPainterPath(); path4.addEllipse(QRectF(-10, 10, 1, 1));
+
+ QCOMPARE(scene.items(path1), QList<QGraphicsItem *>() << item1);
+ QCOMPARE(scene.items(path2), QList<QGraphicsItem *>() << item2);
+ QCOMPARE(scene.items(path3), QList<QGraphicsItem *>() << item3);
+ QCOMPARE(scene.items(path4), QList<QGraphicsItem *>() << item4);
+
+ path1 = QPainterPath(); path1.addRect(QRectF(-10, -10, 40, 10));
+ path2 = QPainterPath(); path2.addRect(QRectF(-10, 10, 40, 10));
+
+ QCOMPARE(scene.items(path1), QList<QGraphicsItem *>() << item2 << item1);
+ QCOMPARE(scene.items(path2), QList<QGraphicsItem *>() << item4 << item3);
+
+ item1->setZValue(3);
+ item2->setZValue(2);
+ item3->setZValue(1);
+ item4->setZValue(0);
+
+ QCOMPARE(scene.items(path1), QList<QGraphicsItem *>() << item1 << item2);
+ QCOMPARE(scene.items(path2), QList<QGraphicsItem *>() << item3 << item4);
+}
+
+void tst_QGraphicsScene::items_QPainterPath_2()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *ellipse = scene.addEllipse(QRectF(0, 0, 100, 100));
+
+ QPainterPath p1; p1.addRect(QRectF(1, 1, 10, 10));
+ QPainterPath p2; p2.addRect(QRectF(1, 89, 10, 10));
+ QPainterPath p3; p3.addRect(QRectF(89, 1, 10, 10));
+ QPainterPath p4; p4.addRect(QRectF(89, 89, 10, 10));
+
+ // None of the rects contain the ellipse's shape nor bounding rect
+ QVERIFY(scene.items(p1, Qt::ContainsItemShape).isEmpty());
+ QVERIFY(scene.items(p2, Qt::ContainsItemShape).isEmpty());
+ QVERIFY(scene.items(p3, Qt::ContainsItemShape).isEmpty());
+ QVERIFY(scene.items(p4, Qt::ContainsItemShape).isEmpty());
+ QVERIFY(scene.items(p1, Qt::ContainsItemBoundingRect).isEmpty());
+ QVERIFY(scene.items(p2, Qt::ContainsItemBoundingRect).isEmpty());
+ QVERIFY(scene.items(p3, Qt::ContainsItemBoundingRect).isEmpty());
+ QVERIFY(scene.items(p4, Qt::ContainsItemBoundingRect).isEmpty());
+
+ // None intersects with the item's shape, but they all intersects with the
+ // item's bounding rect.
+ QVERIFY(scene.items(p1, Qt::IntersectsItemShape).isEmpty());
+ QVERIFY(scene.items(p2, Qt::IntersectsItemShape).isEmpty());
+ QVERIFY(scene.items(p3, Qt::IntersectsItemShape).isEmpty());
+ QVERIFY(scene.items(p4, Qt::IntersectsItemShape).isEmpty());
+ QCOMPARE(scene.items(p1, Qt::IntersectsItemBoundingRect).first(), ellipse);
+ QCOMPARE(scene.items(p2, Qt::IntersectsItemBoundingRect).first(), ellipse);
+ QCOMPARE(scene.items(p3, Qt::IntersectsItemBoundingRect).first(), ellipse);
+ QCOMPARE(scene.items(p4, Qt::IntersectsItemBoundingRect).first(), ellipse);
+
+ QPainterPath p5;
+ p5.addRect(QRectF(5, 5, 90, 90));
+
+ // This rect does not contain the shape nor the bounding rect
+ QVERIFY(scene.items(p5, Qt::ContainsItemShape).isEmpty());
+ QVERIFY(scene.items(p5, Qt::ContainsItemBoundingRect).isEmpty());
+
+ // It will, however, intersect with both
+ QCOMPARE(scene.items(p5, Qt::IntersectsItemShape).first(), ellipse);
+ QCOMPARE(scene.items(p5, Qt::IntersectsItemBoundingRect).first(), ellipse);
+
+ QPainterPath p6;
+ p6.addRect(QRectF(-5, -5, 110, 110));
+
+ // A rect that contains the whole ellipse will both contain and intersect
+ // with both the ellipse's shape and bounding rect.
+ QCOMPARE(scene.items(p6, Qt::IntersectsItemShape).first(), ellipse);
+ QCOMPARE(scene.items(p6, Qt::ContainsItemShape).first(), ellipse);
+ QCOMPARE(scene.items(p6, Qt::IntersectsItemBoundingRect).first(), ellipse);
+ QCOMPARE(scene.items(p6, Qt::ContainsItemBoundingRect).first(), ellipse);
+}
+
+void tst_QGraphicsScene::selection()
+{
+ // ### This test is difficult to make work for all platforms; instead, a
+ // hand crafted data set would make it stable. Its behavior is thoroughly
+ // covered by other tests. Todo: Fix this test.
+
+ /*
+ QGraphicsScene scene;
+ QMap<QGraphicsItem *, int> itemIndexes;
+ for (int i = 0; i < 256; ++i) {
+ QPainterPath path;
+ path.addRect(randomX[i], randomY[i], 25, 25);
+
+ QGraphicsPathItem *pathItem = scene.addPath(path);
+ pathItem->setFlag(QGraphicsItem::ItemIsSelectable);
+ itemIndexes.insert(pathItem, i);
+ }
+
+#if 0
+ // Write data
+ QFile::remove("graphicsScene_selection.data");
+ QFile file("graphicsScene_selection.data");
+ if (!file.open(QFile::WriteOnly))
+ QFAIL("Unable to generate data file graphicsScene_selection.data");
+ QDataStream stream(&file);
+ for (qreal y = -1000; y < 1000; y += 33) {
+ for (qreal x = -1000; x < 1000; x += 33) {
+ for (qreal size = 1; size < 200; size += 33) {
+ QPainterPath path;
+ path.addRect(QRectF(x, y, size, size));
+ scene.setSelectionArea(path);
+ QCOMPARE(scene.selectionArea(), path);
+
+ QList<int> indexes;
+ foreach (QGraphicsItem *item, scene.selectedItems())
+ indexes << itemIndexes.value(item);
+
+ stream << x << y << size << indexes;
+ }
+ }
+ }
+#else
+ // Read data
+ QFile file("graphicsScene_selection.data");
+ if (!file.open(QFile::ReadOnly))
+ QFAIL("Unable to load data file graphicsScene_selection.data");
+
+ QDataStream stream(&file);
+
+ while (!stream.atEnd()) {
+ QList<int> expectedIndexes;
+
+ qreal x, y, size;
+ stream >> x >> y >> size >> expectedIndexes;
+
+ QPainterPath path;
+ path.addRect(QRectF(x, y, size, size));
+ scene.setSelectionArea(path);
+ QCOMPARE(scene.selectionArea(), path);
+
+ QList<int> indexes;
+ foreach (QGraphicsItem *item, scene.selectedItems())
+ indexes << itemIndexes.value(item);
+
+ qSort(indexes);
+ qSort(expectedIndexes);
+
+ QCOMPARE(indexes, expectedIndexes);
+
+ scene.clearSelection();
+ QVERIFY(scene.selectedItems().isEmpty());
+ }
+#endif
+ */
+}
+
+class CustomView : public QGraphicsView
+{
+public:
+ CustomView() : repaints(0)
+ { }
+
+ int repaints;
+protected:
+ void paintEvent(QPaintEvent *event)
+ {
+ ++repaints;
+ QGraphicsView::paintEvent(event);
+ }
+};
+
+void tst_QGraphicsScene::selectionChanged()
+{
+ QGraphicsScene scene(0, 0, 1000, 1000);
+ QSignalSpy spy(&scene, SIGNAL(selectionChanged()));
+ QCOMPARE(spy.count(), 0);
+
+ QPainterPath path;
+ path.addRect(scene.sceneRect());
+ QCOMPARE(scene.selectionArea(), QPainterPath());
+ scene.setSelectionArea(path);
+ QCOMPARE(scene.selectionArea(), path);
+ QCOMPARE(spy.count(), 0); // selection didn't change
+ QVERIFY(scene.selectedItems().isEmpty());
+
+ QGraphicsItem *rect = scene.addRect(QRectF(0, 0, 100, 100));
+ QCOMPARE(spy.count(), 0); // selection didn't change
+
+ rect->setSelected(true);
+ QVERIFY(!rect->isSelected());
+ QCOMPARE(spy.count(), 0); // selection didn't change, item isn't selectable
+
+ rect->setFlag(QGraphicsItem::ItemIsSelectable);
+ rect->setSelected(true);
+ QVERIFY(rect->isSelected());
+ QCOMPARE(spy.count(), 1); // selection changed
+ QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>() << rect);
+
+ rect->setSelected(false);
+ QVERIFY(!rect->isSelected());
+ QCOMPARE(spy.count(), 2); // selection changed
+ QVERIFY(scene.selectedItems().isEmpty());
+
+ QGraphicsEllipseItem *parentItem = new QGraphicsEllipseItem(QRectF(0, 0, 100, 100));
+ QGraphicsEllipseItem *childItem = new QGraphicsEllipseItem(QRectF(0, 0, 100, 100), parentItem);
+ QGraphicsEllipseItem *grandChildItem = new QGraphicsEllipseItem(QRectF(0, 0, 100, 100), childItem);
+ grandChildItem->setFlag(QGraphicsItem::ItemIsSelectable);
+ grandChildItem->setSelected(true);
+ grandChildItem->setSelected(false);
+ grandChildItem->setSelected(true);
+ scene.addItem(parentItem);
+
+ QCOMPARE(spy.count(), 3); // the grandchild was added, so the selection changed once
+
+ scene.removeItem(parentItem);
+ QCOMPARE(spy.count(), 4); // the grandchild was removed, so the selection changed
+
+ rect->setSelected(true);
+ QCOMPARE(spy.count(), 5); // the rect was reselected, so the selection changed
+
+ scene.clearSelection();
+ QCOMPARE(spy.count(), 6); // the scene selection was cleared
+
+ rect->setSelected(true);
+ QCOMPARE(spy.count(), 7); // the rect was reselected, so the selection changed
+
+ rect->setFlag(QGraphicsItem::ItemIsSelectable, false);
+ QCOMPARE(spy.count(), 8); // the rect was unselected, so the selection changed
+
+ rect->setSelected(true);
+ QCOMPARE(spy.count(), 8); // the rect is not longer selectable, so the selection does not change
+
+
+ rect->setFlag(QGraphicsItem::ItemIsSelectable, true);
+ rect->setSelected(true);
+ QCOMPARE(spy.count(), 9); // the rect is again selectable, so the selection changed
+
+ delete rect;
+ QCOMPARE(spy.count(), 10); // a selected item was deleted; selection changed
+}
+
+void tst_QGraphicsScene::selectionChanged2()
+{
+ QGraphicsScene scene;
+ QSignalSpy spy(&scene, SIGNAL(selectionChanged()));
+
+ QGraphicsItem *item1 = scene.addRect(0, 0, 100, 100);
+ QGraphicsItem *item2 = scene.addRect(100, 100, 100, 100);
+ item1->setFlag(QGraphicsItem::ItemIsSelectable);
+ item2->setFlag(QGraphicsItem::ItemIsSelectable);
+
+ QCOMPARE(spy.count(), 0);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setScenePos(QPointF(50, 50));
+ event.setButton(Qt::LeftButton);
+ qApp->sendEvent(&scene, &event);
+ }
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.setScenePos(QPointF(50, 50));
+ event.setButton(Qt::LeftButton);
+ qApp->sendEvent(&scene, &event);
+ }
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+ QCOMPARE(spy.count(), 1);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setScenePos(QPointF(150, 150));
+ event.setButton(Qt::LeftButton);
+ qApp->sendEvent(&scene, &event);
+ }
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.setScenePos(QPointF(150, 150));
+ event.setButton(Qt::LeftButton);
+ qApp->sendEvent(&scene, &event);
+ }
+ QVERIFY(!item1->isSelected());
+ QVERIFY(item2->isSelected());
+ QCOMPARE(spy.count(), 2);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setScenePos(QPointF(50, 50));
+ event.setButton(Qt::LeftButton);
+ event.setModifiers(Qt::ControlModifier);
+ qApp->sendEvent(&scene, &event);
+ }
+ QVERIFY(!item1->isSelected());
+ QVERIFY(item2->isSelected());
+ QCOMPARE(spy.count(), 2);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.setScenePos(QPointF(50, 50));
+ event.setButton(Qt::LeftButton);
+ qApp->sendEvent(&scene, &event);
+ }
+ QVERIFY(item1->isSelected());
+ QVERIFY(!item2->isSelected());
+ QCOMPARE(spy.count(), 3);
+}
+
+void tst_QGraphicsScene::addItem()
+{
+ Q_CHECK_PAINTEVENTS
+ {
+ // 1) Create item, then scene, then add item
+ QGraphicsItem *path = new QGraphicsEllipseItem(QRectF(-10, -10, 20, 20));
+ QGraphicsScene scene;
+
+ CustomView view;
+ view.setScene(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ qApp->processEvents();
+ view.repaints = 0;
+
+ scene.addItem(path);
+
+ // Adding an item should always issue a repaint.
+ qApp->processEvents(); // <- delayed update is called
+ qApp->processEvents(); // <- scene schedules pending update
+ qApp->processEvents(); // <- pending update is sent to view
+ QVERIFY(view.repaints > 0);
+ view.repaints = 0;
+
+ QCOMPARE(scene.itemAt(0, 0), path);
+
+ QGraphicsItem *path2 = new QGraphicsEllipseItem(QRectF(-10, -10, 20, 20));
+ path2->setPos(100, 100);
+
+ QCOMPARE(scene.itemAt(0, 0), path);
+ QCOMPARE(scene.itemAt(100, 100), (QGraphicsItem *)0);
+ scene.addItem(path2);
+
+ // Adding an item should always issue a repaint.
+ qApp->processEvents(); // <- delayed update is called
+ qApp->processEvents(); // <- scene schedules pending update
+ qApp->processEvents(); // <- pending update is sent to view
+ QVERIFY(view.repaints > 0);
+
+ QCOMPARE(scene.itemAt(100, 100), path2);
+ }
+ {
+ // 2) Create scene, then item, then add item
+ QGraphicsScene scene;
+ QGraphicsItem *path = new QGraphicsEllipseItem(QRectF(-10, -10, 20, 20));
+ scene.addItem(path);
+
+ QGraphicsItem *path2 = new QGraphicsEllipseItem(QRectF(-10, -10, 20, 20));
+ path2->setPos(100, 100);
+ scene.addItem(path2);
+
+ QCOMPARE(scene.itemAt(0, 0), path);
+ QCOMPARE(scene.itemAt(100, 100), path2);
+ }
+}
+
+void tst_QGraphicsScene::addEllipse()
+{
+ QGraphicsScene scene;
+ QGraphicsEllipseItem *ellipse = scene.addEllipse(QRectF(-10, -10, 20, 20),
+ QPen(Qt::red), QBrush(Qt::blue));
+ QCOMPARE(ellipse->pos(), QPointF());
+ QCOMPARE(ellipse->pen(), QPen(Qt::red));
+ QCOMPARE(ellipse->brush(), QBrush(Qt::blue));
+ QCOMPARE(ellipse->rect(), QRectF(-10, -10, 20, 20));
+ QCOMPARE(scene.itemAt(0, 0), (QGraphicsItem *)ellipse);
+ QCOMPARE(scene.itemAt(-10, -10), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(-9.9, 0), (QGraphicsItem *)ellipse);
+ QCOMPARE(scene.itemAt(-10, 10), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(0, -9.9), (QGraphicsItem *)ellipse);
+ QCOMPARE(scene.itemAt(0, 9.9), (QGraphicsItem *)ellipse);
+ QCOMPARE(scene.itemAt(10, -10), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(9.9, 0), (QGraphicsItem *)ellipse);
+ QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0);
+}
+
+void tst_QGraphicsScene::addLine()
+{
+ QGraphicsScene scene;
+ QPen pen(Qt::red);
+ pen.setWidthF(1.0);
+ QGraphicsLineItem *line = scene.addLine(QLineF(-10, -10, 20, 20),
+ pen);
+ QCOMPARE(line->pos(), QPointF());
+ QCOMPARE(line->pen(), pen);
+ QCOMPARE(line->line(), QLineF(-10, -10, 20, 20));
+ QCOMPARE(scene.itemAt(0, 0), (QGraphicsItem *)line);
+ QCOMPARE(scene.itemAt(-10, -10), (QGraphicsItem *)line);
+ QCOMPARE(scene.itemAt(-9.9, 0), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(-10, 10), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(0, -9.9), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(0, 9.9), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(10, -10), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(9.9, 0), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)line);
+}
+
+void tst_QGraphicsScene::addPath()
+{
+ QGraphicsScene scene;
+ QPainterPath p;
+ p.addEllipse(QRectF(-10, -10, 20, 20));
+ p.addEllipse(QRectF(-10, 20, 20, 20));
+
+ QGraphicsPathItem *path = scene.addPath(p, QPen(Qt::red), QBrush(Qt::blue));
+ QCOMPARE(path->pos(), QPointF());
+ QCOMPARE(path->pen(), QPen(Qt::red));
+ QCOMPARE(path->path(), p);
+ QCOMPARE(path->brush(), QBrush(Qt::blue));
+ QCOMPARE(scene.itemAt(0, 0), (QGraphicsItem *)path);
+ QCOMPARE(scene.itemAt(-9.9, 0), (QGraphicsItem *)path);
+ QCOMPARE(scene.itemAt(9.9, 0), (QGraphicsItem *)path);
+ QCOMPARE(scene.itemAt(0, -9.9), (QGraphicsItem *)path);
+ QCOMPARE(scene.itemAt(0, 9.9), (QGraphicsItem *)path);
+ QCOMPARE(scene.itemAt(0, 30), (QGraphicsItem *)path);
+ QCOMPARE(scene.itemAt(-9.9, 30), (QGraphicsItem *)path);
+ QCOMPARE(scene.itemAt(9.9, 30), (QGraphicsItem *)path);
+ QCOMPARE(scene.itemAt(0, 20.1), (QGraphicsItem *)path);
+ QCOMPARE(scene.itemAt(0, 39.9), (QGraphicsItem *)path);
+ QCOMPARE(scene.itemAt(-10, -10), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(10, -10), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(-10, 10), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(-10, 20), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(10, 20), (QGraphicsItem *)0);
+if (sizeof(qreal) != sizeof(double))
+ QWARN("Skipping test because of rounding errors when qreal != double");
+else
+ QCOMPARE(scene.itemAt(-10, 30), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(10.1, 30), (QGraphicsItem *)0);
+}
+
+void tst_QGraphicsScene::addPixmap()
+{
+ QGraphicsScene scene;
+ QPixmap pix(":/Ash_European.jpg");
+ QGraphicsPixmapItem *pixmap = scene.addPixmap(pix);
+
+ QCOMPARE(pixmap->pos(), QPointF());
+ QCOMPARE(pixmap->pixmap(), pix);
+ QCOMPARE(scene.itemAt(0, 0), (QGraphicsItem *)pixmap);
+ QCOMPARE(scene.itemAt(pix.width() - 1, 0), (QGraphicsItem *)pixmap);
+ QCOMPARE(scene.itemAt(0, pix.height() - 1), (QGraphicsItem *)pixmap);
+ QCOMPARE(scene.itemAt(pix.width() - 1, pix.height() - 1), (QGraphicsItem *)pixmap);
+ QCOMPARE(scene.itemAt(-1, -1), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(pix.width() - 1, -1), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(-1, pix.height() - 1), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(pix.width(), pix.height()), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(0, pix.height()), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(pix.width(), 0), (QGraphicsItem *)0);
+}
+
+void tst_QGraphicsScene::addRect()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect = scene.addRect(QRectF(-10, -10, 20, 20),
+ QPen(Qt::red), QBrush(Qt::blue));
+ QCOMPARE(rect->pos(), QPointF());
+ QCOMPARE(rect->pen(), QPen(Qt::red));
+ QCOMPARE(rect->brush(), QBrush(Qt::blue));
+ QCOMPARE(rect->rect(), QRectF(-10, -10, 20, 20));
+ QCOMPARE(scene.itemAt(0, 0), (QGraphicsItem *)rect);
+ QCOMPARE(scene.itemAt(-10, -10), (QGraphicsItem *)rect);
+ QCOMPARE(scene.itemAt(-9.9, 0), (QGraphicsItem *)rect);
+ QCOMPARE(scene.itemAt(-10, 10), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(0, -9.9), (QGraphicsItem *)rect);
+ QCOMPARE(scene.itemAt(0, 9.9), (QGraphicsItem *)rect);
+ QCOMPARE(scene.itemAt(10, -10), (QGraphicsItem *)0);
+ QCOMPARE(scene.itemAt(9.9, 0), (QGraphicsItem *)rect);
+ QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0);
+}
+
+void tst_QGraphicsScene::addText()
+{
+ QGraphicsScene scene;
+ QGraphicsTextItem *text = scene.addText("Qt", QFont());
+ QCOMPARE(text->pos(), QPointF());
+ QCOMPARE(text->toPlainText(), QString("Qt"));
+ QCOMPARE(text->font(), QFont());
+}
+
+#if !defined(Q_OS_WINCE) || defined(GWES_ICONCURS)
+void tst_QGraphicsScene::removeItem()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *item = scene.addRect(QRectF(0, 0, 10, 10));
+ QCOMPARE(scene.itemAt(0, 0), item); // forces indexing
+ scene.removeItem(item);
+ QCOMPARE(scene.itemAt(0, 0), (QGraphicsItem *)0);
+ delete item;
+
+ QGraphicsItem *item2 = scene.addRect(QRectF(0, 0, 10, 10));
+ item2->setFlag(QGraphicsItem::ItemIsSelectable);
+ QCOMPARE(scene.itemAt(0, 0), item2);
+
+ // Removing a selected item
+ QVERIFY(scene.selectedItems().isEmpty());
+ item2->setSelected(true);
+ QVERIFY(scene.selectedItems().contains(item2));
+ scene.removeItem(item2);
+ QVERIFY(scene.selectedItems().isEmpty());
+
+ // Check that we are in a state that can receive paint events
+ // (i.e., not logged out on Windows).
+ Q_CHECK_PAINTEVENTS
+
+ // Removing a hovered item
+ HoverItem *hoverItem = new HoverItem;
+ scene.addItem(hoverItem);
+ scene.setSceneRect(-50, -50, 100, 100);
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(150, 150);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::mouseMove(view.viewport(), QPoint(-1, -1));
+ {
+ QMouseEvent moveEvent(QEvent::MouseMove, view.mapFromScene(hoverItem->scenePos() + QPointF(20, 20)), Qt::NoButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &moveEvent);
+ }
+ qApp->processEvents(); // update
+ qApp->processEvents(); // draw
+ QVERIFY(!hoverItem->isHovered);
+
+ {
+ QTest::qWait(250);
+ QTest::mouseMove(view.viewport(), view.mapFromScene(hoverItem->scenePos()), Qt::NoButton);
+ QTest::qWait(10);
+ QMouseEvent moveEvent(QEvent::MouseMove, view.mapFromScene(hoverItem->scenePos()), Qt::NoButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &moveEvent);
+ }
+ qApp->processEvents(); // update
+ qApp->processEvents(); // draw
+ QVERIFY(hoverItem->isHovered);
+
+ scene.removeItem(hoverItem);
+ hoverItem->setAcceptsHoverEvents(false);
+ scene.addItem(hoverItem);
+ qApp->processEvents(); // <- delayed update is called
+ qApp->processEvents(); // <- scene schedules pending update
+ qApp->processEvents(); // <- pending update is sent to view
+ QVERIFY(!hoverItem->isHovered);
+}
+#endif
+
+void tst_QGraphicsScene::focusItem()
+{
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ QVERIFY(!scene.focusItem());
+ QGraphicsItem *item = scene.addText("Qt");
+ QVERIFY(!scene.focusItem());
+ item->setFocus();
+ QVERIFY(!scene.focusItem());
+ item->setFlag(QGraphicsItem::ItemIsFocusable);
+ QVERIFY(!scene.focusItem());
+ item->setFocus();
+ QCOMPARE(scene.focusItem(), item);
+
+ QFocusEvent focusOut(QEvent::FocusOut);
+ QApplication::sendEvent(&scene, &focusOut);
+
+ QVERIFY(!scene.focusItem());
+
+ QFocusEvent focusIn(QEvent::FocusIn);
+ QApplication::sendEvent(&scene, &focusIn);
+ QCOMPARE(scene.focusItem(), item);
+
+ QGraphicsItem *item2 = scene.addText("Qt");
+ item2->setFlag(QGraphicsItem::ItemIsFocusable);
+ QCOMPARE(scene.focusItem(), item);
+
+ item2->setFocus();
+ QCOMPARE(scene.focusItem(), item2);
+ item->setFocus();
+ QCOMPARE(scene.focusItem(), item);
+
+ item2->setFocus();
+ QCOMPARE(scene.focusItem(), item2);
+ QApplication::sendEvent(&scene, &focusOut);
+ QVERIFY(!scene.hasFocus());
+ QVERIFY(!scene.focusItem());
+ QApplication::sendEvent(&scene, &focusIn);
+ QCOMPARE(scene.focusItem(), item2);
+
+ QApplication::sendEvent(&scene, &focusOut);
+
+ QVERIFY(!scene.focusItem());
+ scene.removeItem(item2);
+ delete item2;
+
+ QApplication::sendEvent(&scene, &focusIn);
+ QVERIFY(!scene.focusItem());
+}
+
+class FocusItem : public QGraphicsTextItem
+{
+protected:
+ void focusOutEvent(QFocusEvent *)
+ {
+ QVERIFY(!scene()->focusItem());
+ }
+};
+
+void tst_QGraphicsScene::focusItemLostFocus()
+{
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ FocusItem *item = new FocusItem;
+ item->setTextInteractionFlags(Qt::TextEditorInteraction);
+ scene.addItem(item);
+
+ item->setFocus();
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *)item);
+ item->clearFocus();
+}
+
+class ClearTestItem : public QGraphicsRectItem
+{
+public:
+ ClearTestItem(QGraphicsItem *parent = 0) : QGraphicsRectItem(parent) {}
+ ~ClearTestItem() { qDeleteAll(items); }
+ QList<QGraphicsItem *> items;
+};
+
+void tst_QGraphicsScene::clear()
+{
+ QGraphicsScene scene;
+ scene.clear();
+ QVERIFY(scene.items().isEmpty());
+ scene.addRect(0, 0, 100, 100);
+ QCOMPARE(scene.sceneRect(), QRectF(0, 0, 100, 100));
+ scene.clear();
+ QVERIFY(scene.items().isEmpty());
+ QCOMPARE(scene.sceneRect(), QRectF(0, 0, 100, 100));
+
+ ClearTestItem *firstItem = new ClearTestItem;
+ QGraphicsItem *secondItem = new QGraphicsRectItem;
+ firstItem->items += secondItem;
+
+ scene.setItemIndexMethod(QGraphicsScene::NoIndex);
+ scene.addItem(firstItem);
+ scene.addItem(secondItem);
+ QCOMPARE(scene.items().at(0), (QGraphicsItem*)firstItem);
+ QCOMPARE(scene.items().at(1), secondItem);
+
+ ClearTestItem *thirdItem = new ClearTestItem(firstItem);
+ QGraphicsItem *forthItem = new QGraphicsRectItem(firstItem);
+ thirdItem->items += forthItem;
+
+ // must not crash even if firstItem deletes secondItem
+ scene.clear();
+ QVERIFY(scene.items().isEmpty());
+}
+
+void tst_QGraphicsScene::setFocusItem()
+{
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ QGraphicsItem *item = scene.addText("Qt");
+ QVERIFY(!scene.focusItem());
+ QVERIFY(!scene.hasFocus());
+ scene.setFocusItem(item);
+ QVERIFY(!scene.hasFocus());
+ QVERIFY(!scene.focusItem());
+ item->setFlag(QGraphicsItem::ItemIsFocusable);
+
+ for (int i = 0; i < 3; ++i) {
+ scene.setFocusItem(item);
+ QVERIFY(scene.hasFocus());
+ QCOMPARE(scene.focusItem(), item);
+ QVERIFY(item->hasFocus());
+ }
+
+ QGraphicsItem *item2 = scene.addText("Qt");
+ item2->setFlag(QGraphicsItem::ItemIsFocusable);
+
+ scene.setFocusItem(item2);
+ QVERIFY(!item->hasFocus());
+ QVERIFY(item2->hasFocus());
+
+ scene.setFocusItem(item);
+ QVERIFY(item->hasFocus());
+ QVERIFY(!item2->hasFocus());
+
+ scene.clearFocus();
+ QVERIFY(!item->hasFocus());
+ QVERIFY(!item2->hasFocus());
+
+ scene.setFocus();
+ QVERIFY(item->hasFocus());
+ QVERIFY(!item2->hasFocus());
+
+ scene.setFocusItem(0);
+ QVERIFY(!item->hasFocus());
+ QVERIFY(!item2->hasFocus());
+
+ scene.setFocus();
+ QVERIFY(!item->hasFocus());
+ QVERIFY(!item2->hasFocus());
+}
+
+void tst_QGraphicsScene::setFocusItem_inactive()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *item = scene.addText("Qt");
+ QVERIFY(!scene.focusItem());
+ QVERIFY(!scene.hasFocus());
+ scene.setFocusItem(item);
+ QVERIFY(!scene.hasFocus());
+ QVERIFY(!scene.focusItem());
+ item->setFlag(QGraphicsItem::ItemIsFocusable);
+
+ for (int i = 0; i < 3; ++i) {
+ scene.setFocusItem(item);
+ QCOMPARE(scene.focusItem(), item);
+ QVERIFY(!item->hasFocus());
+ }
+
+}
+
+
+void tst_QGraphicsScene::mouseGrabberItem()
+{
+ QGraphicsScene scene;
+ QVERIFY(!scene.mouseGrabberItem());
+
+ QGraphicsItem *item = scene.addRect(QRectF(-10, -10, 20, 20));
+ item->setFlag(QGraphicsItem::ItemIsMovable);
+ item->setZValue(1);
+
+ QGraphicsItem *item2 = scene.addRect(QRectF(-10, -10, 20, 20));
+ item2->setFlag(QGraphicsItem::ItemIsMovable);
+ item2->setZValue(0);
+
+ for (int i = 0; i < 3; ++i) {
+ item->setPos(0, 0);
+ item2->setPos(0, 0);
+ item->setZValue((i & 1) ? 0 : 1);
+ item2->setZValue((i & 1) ? 1 : 0);
+ QGraphicsItem *topMostItem = (i & 1) ? item2 : item;
+
+ QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
+ pressEvent.setButton(Qt::LeftButton);
+ pressEvent.setScenePos(QPointF(0, 0));
+ pressEvent.setScreenPos(QPoint(100, 100));
+
+ QApplication::sendEvent(&scene, &pressEvent);
+ QCOMPARE(scene.mouseGrabberItem(), topMostItem);
+
+ for (int i = 0; i < 1000; ++i) {
+ QGraphicsSceneMouseEvent moveEvent(QEvent::GraphicsSceneMouseMove);
+ moveEvent.setButtons(Qt::LeftButton);
+ moveEvent.setScenePos(QPointF(i * 10, i * 10));
+ moveEvent.setScreenPos(QPoint(100 + i * 10, 100 + i * 10));
+ QApplication::sendEvent(&scene, &moveEvent);
+ QCOMPARE(scene.mouseGrabberItem(), topMostItem);
+
+ // Geometrical changes should not affect the mouse grabber.
+ item->setZValue(rand() % 500);
+ item2->setZValue(rand() % 500);
+ item->setPos(rand() % 50000, rand() % 50000);
+ item2->setPos(rand() % 50000, rand() % 50000);
+ }
+
+ QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
+ releaseEvent.setScenePos(QPointF(10000, 10000));
+ releaseEvent.setScreenPos(QPoint(1000000, 1000000));
+ QApplication::sendEvent(&scene, &releaseEvent);
+ QVERIFY(!scene.mouseGrabberItem());
+ }
+
+ // Structural change: deleting the mouse grabber
+ item->setPos(0, 0);
+ item->setZValue(1);
+ item2->setPos(0, 0);
+ item2->setZValue(0);
+ QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
+ pressEvent.setButton(Qt::LeftButton);
+ pressEvent.setScenePos(QPointF(0, 0));
+ pressEvent.setScreenPos(QPoint(100, 100));
+
+ QGraphicsSceneMouseEvent moveEvent(QEvent::GraphicsSceneMouseMove);
+ moveEvent.setButtons(Qt::LeftButton);
+ moveEvent.setScenePos(QPointF(0, 0));
+ moveEvent.setScreenPos(QPoint(100, 100));
+
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &moveEvent);
+ QCOMPARE(scene.mouseGrabberItem(), item);
+ item->setVisible(false);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ QApplication::sendEvent(&scene, &pressEvent);
+ QCOMPARE(scene.mouseGrabberItem(), item2);
+ item2->setVisible(false);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ QApplication::sendEvent(&scene, &moveEvent);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ item2->setVisible(true);
+ QApplication::sendEvent(&scene, &moveEvent);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ QApplication::sendEvent(&scene, &pressEvent);
+ QApplication::sendEvent(&scene, &moveEvent);
+ QCOMPARE(scene.mouseGrabberItem(), item2);
+ scene.removeItem(item2);
+ delete item2;
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+}
+
+void tst_QGraphicsScene::hoverEvents_siblings()
+{
+ Q_CHECK_PAINTEVENTS
+
+ QGraphicsScene scene;
+ QGraphicsItem *lastItem = 0;
+ QList<HoverItem *> items;
+ for (int i = 0; i < 15; ++i) {
+ QGraphicsItem *item = new HoverItem;
+ scene.addItem(item);
+ items << (HoverItem *)item;
+ if (lastItem) {
+ item->setPos(lastItem->pos() + QPointF(sin(i / 3.0) * 17, cos(i / 3.0) * 17));
+ }
+ item->setZValue(i);
+ lastItem = item;
+ }
+
+ QGraphicsView view(&scene);
+ view.setRenderHint(QPainter::Antialiasing, true);
+#if defined(Q_OS_WINCE)
+ view.setMinimumSize(230, 200);
+#else
+ view.setMinimumSize(400, 300);
+#endif
+ view.rotate(10);
+ view.scale(1.7, 1.7);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ qApp->setActiveWindow(&view);
+ view.activateWindow();
+ QTest::qWait(70);
+
+ QCursor::setPos(view.mapToGlobal(QPoint(-5, -5)));
+
+ QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
+ mouseEvent.setScenePos(QPointF(-1000, -1000));
+ QApplication::sendEvent(&scene, &mouseEvent);
+
+ QTest::qWait(50);
+
+ for (int j = 1; j >= 0; --j) {
+ int i = j ? 0 : 14;
+ forever {
+ if (j)
+ QVERIFY(!items.at(i)->isHovered);
+ else
+ QVERIFY(!items.at(i)->isHovered);
+ QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
+ mouseEvent.setScenePos(items.at(i)->mapToScene(0, 0));
+ QApplication::sendEvent(&scene, &mouseEvent);
+
+ qApp->processEvents(); // this posts updates from the scene to the view
+ qApp->processEvents(); // which trigger a repaint here
+
+ QTRY_VERIFY(items.at(i)->isHovered);
+ if (j && i > 0)
+ QVERIFY(!items.at(i - 1)->isHovered);
+ if (!j && i < 14)
+ QVERIFY(!items.at(i + 1)->isHovered);
+ i += j ? 1 : -1;
+ if ((j && i == 15) || (!j && i == -1))
+ break;
+ }
+
+ QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
+ mouseEvent.setScenePos(QPointF(-1000, -1000));
+ QApplication::sendEvent(&scene, &mouseEvent);
+
+ qApp->processEvents(); // this posts updates from the scene to the view
+ qApp->processEvents(); // which trigger a repaint here
+ }
+}
+
+void tst_QGraphicsScene::hoverEvents_parentChild()
+{
+ Q_CHECK_PAINTEVENTS
+
+ QGraphicsScene scene;
+ QGraphicsItem *lastItem = 0;
+ QList<HoverItem *> items;
+ for (int i = 0; i < 15; ++i) {
+ QGraphicsItem *item = new HoverItem;
+ scene.addItem(item);
+ items << (HoverItem *)item;
+ if (lastItem) {
+ item->setParentItem(lastItem);
+ item->setPos(sin(i / 3.0) * 17, cos(i / 3.0) * 17);
+ }
+ lastItem = item;
+ }
+
+ QGraphicsView view(&scene);
+ view.setRenderHint(QPainter::Antialiasing, true);
+#if defined(Q_OS_WINCE)
+ view.setMinimumSize(230, 200);
+#else
+ view.setMinimumSize(400, 300);
+#endif
+ view.rotate(10);
+ view.scale(1.7, 1.7);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(70);
+
+ QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
+ mouseEvent.setScenePos(QPointF(-1000, -1000));
+ QApplication::sendEvent(&scene, &mouseEvent);
+
+ for (int j = 1; j >= 0; --j) {
+ int i = j ? 0 : 14;
+ forever {
+ if (j) {
+ QVERIFY(!items.at(i)->isHovered);
+ } else {
+ if (i == 14)
+ QVERIFY(!items.at(13)->isHovered);
+ }
+ mouseEvent.setScenePos(items.at(i)->mapToScene(0, 0));
+ QApplication::sendEvent(&scene, &mouseEvent);
+
+ qApp->processEvents(); // this posts updates from the scene to the view
+ qApp->processEvents(); // which trigger a repaint here
+
+ QTRY_VERIFY(items.at(i)->isHovered);
+ if (i < 14)
+ QVERIFY(!items.at(i + 1)->isHovered);
+ i += j ? 1 : -1;
+ if ((j && i == 15) || (!j && i == -1))
+ break;
+ }
+
+ mouseEvent.setScenePos(QPointF(-1000, -1000));
+ QApplication::sendEvent(&scene, &mouseEvent);
+
+ qApp->processEvents(); // this posts updates from the scene to the view
+ qApp->processEvents(); // which trigger a repaint here
+ }
+}
+
+void tst_QGraphicsScene::createItemGroup()
+{
+ QGraphicsScene scene;
+
+ QList<QGraphicsItem *> children1;
+ children1 << scene.addRect(QRectF(-10, -10, 20, 20));
+ children1 << scene.addRect(QRectF(-10, -10, 20, 20));
+ children1 << scene.addRect(QRectF(-10, -10, 20, 20));
+ children1 << scene.addRect(QRectF(-10, -10, 20, 20));
+
+ QList<QGraphicsItem *> children2;
+ children2 << scene.addRect(QRectF(-10, -10, 20, 20));
+ children2 << scene.addRect(QRectF(-10, -10, 20, 20));
+ children2 << scene.addRect(QRectF(-10, -10, 20, 20));
+ children2 << scene.addRect(QRectF(-10, -10, 20, 20));
+
+ QList<QGraphicsItem *> children3;
+ children3 << scene.addRect(QRectF(-10, -10, 20, 20));
+ children3 << scene.addRect(QRectF(-10, -10, 20, 20));
+ children3 << scene.addRect(QRectF(-10, -10, 20, 20));
+ children3 << scene.addRect(QRectF(-10, -10, 20, 20));
+
+ // All items in children1 are children of parent1
+ QGraphicsItem *parent1 = scene.addRect(QRectF(-10, -10, 20, 20));
+ foreach (QGraphicsItem *item, children1)
+ item->setParentItem(parent1);
+
+ QGraphicsItemGroup *group = scene.createItemGroup(children1);
+ QCOMPARE(group->parentItem(), parent1);
+ QCOMPARE(children1.first()->parentItem(), (QGraphicsItem *)group);
+ scene.destroyItemGroup(group);
+ QCOMPARE(children1.first()->parentItem(), parent1);
+ group = scene.createItemGroup(children1);
+ QCOMPARE(group->parentItem(), parent1);
+ QCOMPARE(children1.first()->parentItem(), (QGraphicsItem *)group);
+ scene.destroyItemGroup(group);
+ QCOMPARE(children1.first()->parentItem(), parent1);
+
+ // All items in children2 are children of parent2
+ QGraphicsItem *parent2 = scene.addRect(QRectF(-10, -10, 20, 20));
+ foreach (QGraphicsItem *item, children2)
+ item->setParentItem(parent2);
+
+ // Now make parent2 a child of parent1, so all children2 are also children
+ // of parent1.
+ parent2->setParentItem(parent1);
+
+ // The children2 group should still have parent2 as their common ancestor.
+ group = scene.createItemGroup(children2);
+ QCOMPARE(group->parentItem(), parent2);
+ QCOMPARE(children2.first()->parentItem(), (QGraphicsItem *)group);
+ scene.destroyItemGroup(group);
+ QCOMPARE(children2.first()->parentItem(), parent2);
+
+ // But the set of both children2 and children1 share only parent1.
+ group = scene.createItemGroup(children2 + children1);
+ QCOMPARE(group->parentItem(), parent1);
+ QCOMPARE(children1.first()->parentItem(), (QGraphicsItem *)group);
+ QCOMPARE(children2.first()->parentItem(), (QGraphicsItem *)group);
+ scene.destroyItemGroup(group);
+ QCOMPARE(children1.first()->parentItem(), parent1);
+ QCOMPARE(children2.first()->parentItem(), parent1);
+
+ // Fixup the parent-child chain
+ foreach (QGraphicsItem *item, children2)
+ item->setParentItem(parent2);
+
+ // These share no common parent
+ group = scene.createItemGroup(children3);
+ QCOMPARE(group->parentItem(), (QGraphicsItem *)0);
+ scene.destroyItemGroup(group);
+
+ // Make children3 children of parent3
+ QGraphicsItem *parent3 = scene.addRect(QRectF(-10, -10, 20, 20));
+ foreach (QGraphicsItem *item, children3)
+ item->setParentItem(parent3);
+
+ // These should have parent3 as a parent
+ group = scene.createItemGroup(children3);
+ QCOMPARE(group->parentItem(), parent3);
+ scene.destroyItemGroup(group);
+
+ // Now make them all children of parent1
+ parent3->setParentItem(parent1);
+
+ group = scene.createItemGroup(children3);
+ QCOMPARE(group->parentItem(), parent3);
+ scene.destroyItemGroup(group);
+
+ group = scene.createItemGroup(children2);
+ QCOMPARE(group->parentItem(), parent2);
+ scene.destroyItemGroup(group);
+
+ group = scene.createItemGroup(children1);
+ QCOMPARE(group->parentItem(), parent1);
+ scene.destroyItemGroup(group);
+
+ QGraphicsItemGroup *emptyGroup = scene.createItemGroup(QList<QGraphicsItem *>());
+ QCOMPARE(emptyGroup->children(), QList<QGraphicsItem *>());
+ QVERIFY(!emptyGroup->parentItem());
+ QCOMPARE(emptyGroup->scene(), &scene);
+}
+
+class EventTester : public QGraphicsEllipseItem
+{
+public:
+ EventTester()
+ : QGraphicsEllipseItem(QRectF(-10, -10, 20, 20)), ignoreMouse(false)
+ { }
+
+ bool ignoreMouse;
+ QList<QEvent::Type> eventTypes;
+
+protected:
+ bool sceneEvent(QEvent *event)
+ {
+ eventTypes << QEvent::Type(event->type());
+ switch (event->type()) {
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::GraphicsSceneMouseRelease:
+ if (ignoreMouse) {
+ event->ignore();
+ return true;
+ }
+ default:
+ break;
+ }
+
+ return QGraphicsEllipseItem::sceneEvent(event);
+ }
+};
+
+void tst_QGraphicsScene::mouseEventPropagation()
+{
+ EventTester *a = new EventTester;
+ EventTester *b = new EventTester;
+ EventTester *c = new EventTester;
+ EventTester *d = new EventTester;
+ b->setParentItem(a);
+ c->setParentItem(b);
+ d->setParentItem(c);
+
+ a->setFlag(QGraphicsItem::ItemIsMovable);
+ b->setFlag(QGraphicsItem::ItemIsMovable);
+ c->setFlag(QGraphicsItem::ItemIsMovable);
+ d->setFlag(QGraphicsItem::ItemIsMovable);
+
+ a->setData(0, "A");
+ b->setData(0, "B");
+ c->setData(0, "C");
+ d->setData(0, "D");
+
+ // scene -> a -> b -> c -> d
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ scene.addItem(a);
+
+ // Prepare some events
+ QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
+ pressEvent.setButton(Qt::LeftButton);
+ pressEvent.setScenePos(QPointF(0, 0));
+ QGraphicsSceneMouseEvent moveEvent(QEvent::GraphicsSceneMouseMove);
+ moveEvent.setButton(Qt::LeftButton);
+ moveEvent.setScenePos(QPointF(0, 0));
+ QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
+ releaseEvent.setButton(Qt::LeftButton);
+ releaseEvent.setScenePos(QPointF(0, 0));
+
+ // Send a press
+ QApplication::sendEvent(&scene, &pressEvent);
+ QCOMPARE(d->eventTypes.size(), 2);
+ QCOMPARE(d->eventTypes.at(0), QEvent::GrabMouse);
+ QCOMPARE(d->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
+ QCOMPARE(c->eventTypes.size(), 0);
+ QCOMPARE(b->eventTypes.size(), 0);
+ QCOMPARE(a->eventTypes.size(), 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)d);
+
+ // Send a move
+ QApplication::sendEvent(&scene, &moveEvent);
+ QCOMPARE(d->eventTypes.size(), 3);
+ QCOMPARE(d->eventTypes.at(2), QEvent::GraphicsSceneMouseMove);
+ QCOMPARE(c->eventTypes.size(), 0);
+ QCOMPARE(b->eventTypes.size(), 0);
+ QCOMPARE(a->eventTypes.size(), 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)d);
+
+ // Send a release
+ QApplication::sendEvent(&scene, &releaseEvent);
+ QCOMPARE(d->eventTypes.size(), 5);
+ QCOMPARE(d->eventTypes.at(3), QEvent::GraphicsSceneMouseRelease);
+ QCOMPARE(d->eventTypes.at(4), QEvent::UngrabMouse);
+ QCOMPARE(c->eventTypes.size(), 0);
+ QCOMPARE(b->eventTypes.size(), 0);
+ QCOMPARE(a->eventTypes.size(), 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+
+ d->setAcceptedMouseButtons(Qt::RightButton);
+
+ // Send a press
+ QApplication::sendEvent(&scene, &pressEvent);
+ QCOMPARE(d->eventTypes.size(), 5);
+ QCOMPARE(c->eventTypes.size(), 2);
+ QCOMPARE(c->eventTypes.at(0), QEvent::GrabMouse);
+ QCOMPARE(c->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
+ QCOMPARE(b->eventTypes.size(), 0);
+ QCOMPARE(a->eventTypes.size(), 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)c);
+
+ // Send another press, with a button that isn't actually accepted
+ QApplication::sendEvent(&scene, &pressEvent);
+ pressEvent.setButton(Qt::RightButton);
+ QCOMPARE(d->eventTypes.size(), 5);
+ QCOMPARE(c->eventTypes.size(), 3);
+ QCOMPARE(c->eventTypes.at(2), QEvent::GraphicsSceneMousePress);
+ QCOMPARE(b->eventTypes.size(), 0);
+ QCOMPARE(a->eventTypes.size(), 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)c);
+
+ // Send a move
+ QApplication::sendEvent(&scene, &moveEvent);
+ QCOMPARE(d->eventTypes.size(), 5);
+ QCOMPARE(c->eventTypes.size(), 4);
+ QCOMPARE(c->eventTypes.at(3), QEvent::GraphicsSceneMouseMove);
+ QCOMPARE(b->eventTypes.size(), 0);
+ QCOMPARE(a->eventTypes.size(), 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)c);
+
+ // Send a release
+ QApplication::sendEvent(&scene, &releaseEvent);
+ QCOMPARE(d->eventTypes.size(), 5);
+ QCOMPARE(c->eventTypes.size(), 6);
+ QCOMPARE(c->eventTypes.at(4), QEvent::GraphicsSceneMouseRelease);
+ QCOMPARE(c->eventTypes.at(5), QEvent::UngrabMouse);
+ QCOMPARE(b->eventTypes.size(), 0);
+ QCOMPARE(a->eventTypes.size(), 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+
+ // Disabled items eat events. c should not get this.
+ d->setEnabled(false);
+ d->setAcceptedMouseButtons(Qt::RightButton);
+
+ // Send a right press. This disappears in d.
+ QApplication::sendEvent(&scene, &pressEvent);
+ QCOMPARE(d->eventTypes.size(), 5);
+ QCOMPARE(c->eventTypes.size(), 6);
+ QCOMPARE(b->eventTypes.size(), 0);
+ QCOMPARE(a->eventTypes.size(), 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+
+ // Send a left press. This goes to c.
+ pressEvent.setButton(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &pressEvent);
+ QCOMPARE(d->eventTypes.size(), 5);
+ QCOMPARE(c->eventTypes.size(), 8);
+ QCOMPARE(c->eventTypes.at(6), QEvent::GrabMouse);
+ QCOMPARE(c->eventTypes.at(7), QEvent::GraphicsSceneMousePress);
+ QCOMPARE(b->eventTypes.size(), 0);
+ QCOMPARE(a->eventTypes.size(), 0);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)c);
+
+ // Clicking outside the items removes the mouse grabber
+}
+
+void tst_QGraphicsScene::mouseEventPropagation_ignore()
+{
+ EventTester *a = new EventTester;
+ EventTester *b = new EventTester;
+ EventTester *c = new EventTester;
+ EventTester *d = new EventTester;
+ b->setParentItem(a);
+ c->setParentItem(b);
+ d->setParentItem(c);
+
+ a->setFlags(QGraphicsItem::ItemIsMovable);
+ b->setFlags(QGraphicsItem::ItemIsMovable);
+ c->setFlags(QGraphicsItem::ItemIsMovable);
+ d->setFlags(QGraphicsItem::ItemIsMovable);
+
+ // scene -> a -> b -> c -> d
+ QGraphicsScene scene;
+ scene.addItem(a);
+
+ // Prepare some events
+ QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
+ pressEvent.setButton(Qt::LeftButton);
+ pressEvent.setScenePos(QPointF(0, 0));
+
+ b->ignoreMouse = true;
+ c->ignoreMouse = true;
+ d->ignoreMouse = true;
+
+ QApplication::sendEvent(&scene, &pressEvent);
+ QCOMPARE(a->eventTypes.size(), 2);
+ QCOMPARE(a->eventTypes.at(0), QEvent::GrabMouse);
+ QCOMPARE(a->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
+ QCOMPARE(b->eventTypes.size(), 3);
+ QCOMPARE(b->eventTypes.at(0), QEvent::GrabMouse);
+ QCOMPARE(b->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
+ QCOMPARE(b->eventTypes.at(2), QEvent::UngrabMouse);
+ QCOMPARE(c->eventTypes.size(), 3);
+ QCOMPARE(c->eventTypes.at(0), QEvent::GrabMouse);
+ QCOMPARE(c->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
+ QCOMPARE(c->eventTypes.at(2), QEvent::UngrabMouse);
+ QCOMPARE(d->eventTypes.size(), 3);
+ QCOMPARE(d->eventTypes.at(0), QEvent::GrabMouse);
+ QCOMPARE(d->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
+ QCOMPARE(d->eventTypes.at(2), QEvent::UngrabMouse);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)a);
+
+ a->ignoreMouse = true;
+
+ QApplication::sendEvent(&scene, &pressEvent);
+ QCOMPARE(a->eventTypes.size(), 3);
+ QCOMPARE(a->eventTypes.at(2), QEvent::GraphicsSceneMousePress);
+ QCOMPARE(b->eventTypes.size(), 3);
+ QCOMPARE(c->eventTypes.size(), 3);
+ QCOMPARE(d->eventTypes.size(), 3);
+
+ QVERIFY(!pressEvent.isAccepted());
+}
+
+void tst_QGraphicsScene::mouseEventPropagation_focus()
+{
+ EventTester *a = new EventTester;
+ EventTester *b = new EventTester;
+ EventTester *c = new EventTester;
+ EventTester *d = new EventTester;
+ b->setParentItem(a);
+ c->setParentItem(b);
+ d->setParentItem(c);
+
+ a->setFlag(QGraphicsItem::ItemIsMovable);
+ b->setFlag(QGraphicsItem::ItemIsMovable);
+ c->setFlag(QGraphicsItem::ItemIsMovable);
+ d->setFlag(QGraphicsItem::ItemIsMovable);
+
+ // scene -> a -> b -> c -> d
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ scene.addItem(a);
+
+ // Prepare some events
+ QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
+ pressEvent.setButton(Qt::LeftButton);
+ pressEvent.setScenePos(QPointF(0, 0));
+
+ a->setFlag(QGraphicsItem::ItemIsFocusable);
+ QVERIFY(!a->hasFocus());
+
+ QApplication::sendEvent(&scene, &pressEvent);
+
+ QVERIFY(a->hasFocus());
+ QCOMPARE(a->eventTypes.size(), 1);
+ QCOMPARE(a->eventTypes.first(), QEvent::FocusIn);
+ QCOMPARE(d->eventTypes.size(), 2);
+ QCOMPARE(d->eventTypes.at(0), QEvent::GrabMouse);
+ QCOMPARE(d->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
+}
+
+void tst_QGraphicsScene::mouseEventPropagation_doubleclick()
+{
+ EventTester *a = new EventTester;
+ EventTester *b = new EventTester;
+ a->setFlags(QGraphicsItem::ItemIsMovable);
+ b->setFlags(QGraphicsItem::ItemIsMovable);
+
+ a->setPos(-50, 0);
+ b->setPos(50, 0);
+
+ QGraphicsScene scene;
+ scene.addItem(a);
+ scene.addItem(b);
+
+ // Prepare some events
+ QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
+ pressEvent.setButton(Qt::LeftButton);
+ pressEvent.setScenePos(QPointF(0, 0));
+ QGraphicsSceneMouseEvent doubleClickEvent(QEvent::GraphicsSceneMouseDoubleClick);
+ doubleClickEvent.setButton(Qt::LeftButton);
+ doubleClickEvent.setScenePos(QPointF(0, 0));
+ QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
+ releaseEvent.setButton(Qt::LeftButton);
+ releaseEvent.setScenePos(QPointF(0, 0));
+
+ // Send press to A
+ pressEvent.setScenePos(a->mapToScene(0, 0));
+ QApplication::sendEvent(&scene, &pressEvent);
+ QCOMPARE(a->eventTypes.size(), 2);
+ QCOMPARE(a->eventTypes.at(0), QEvent::GrabMouse);
+ QCOMPARE(a->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
+
+ // Send release to A
+ releaseEvent.setScenePos(a->mapToScene(0, 0));
+ QApplication::sendEvent(&scene, &releaseEvent);
+ QCOMPARE(a->eventTypes.size(), 4);
+ QCOMPARE(a->eventTypes.at(2), QEvent::GraphicsSceneMouseRelease);
+ QCOMPARE(a->eventTypes.at(3), QEvent::UngrabMouse);
+
+ // Send doubleclick to B
+ doubleClickEvent.setScenePos(b->mapToScene(0, 0));
+ QApplication::sendEvent(&scene, &doubleClickEvent);
+ QCOMPARE(a->eventTypes.size(), 4);
+ QCOMPARE(b->eventTypes.size(), 2);
+ QCOMPARE(b->eventTypes.at(0), QEvent::GrabMouse);
+ QCOMPARE(b->eventTypes.at(1), QEvent::GraphicsSceneMousePress);
+
+ // Send release to B
+ releaseEvent.setScenePos(b->mapToScene(0, 0));
+ QApplication::sendEvent(&scene, &releaseEvent);
+ QCOMPARE(a->eventTypes.size(), 4);
+ QCOMPARE(b->eventTypes.size(), 4);
+ QCOMPARE(b->eventTypes.at(2), QEvent::GraphicsSceneMouseRelease);
+ QCOMPARE(b->eventTypes.at(3), QEvent::UngrabMouse);
+}
+
+class Scene : public QGraphicsScene
+{
+public:
+ QList<QPointF> mouseMovePoints;
+
+protected:
+ void mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+ {
+ mouseMovePoints << event->scenePos();
+ }
+};
+
+void tst_QGraphicsScene::mouseEventPropagation_mouseMove()
+{
+ Scene scene;
+ scene.addRect(QRectF(5, 0, 12, 12));
+ scene.addRect(QRectF(15, 0, 12, 12))->setAcceptsHoverEvents(true);
+ for (int i = 0; i < 30; ++i) {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
+ event.setScenePos(QPointF(i, 5));
+ QApplication::sendEvent(&scene, &event);
+ }
+
+ QCOMPARE(scene.mouseMovePoints.size(), 30);
+ for (int i = 0; i < 30; ++i)
+ QCOMPARE(scene.mouseMovePoints.at(i), QPointF(i, 5));
+}
+
+class DndTester : public QGraphicsEllipseItem
+{
+public:
+ DndTester(const QRectF &rect)
+ : QGraphicsEllipseItem(rect), lastEvent(0),
+ ignoresDragEnter(false), ignoresDragMove(false)
+
+ {
+ }
+
+ ~DndTester()
+ {
+ delete lastEvent;
+ }
+
+ QGraphicsSceneDragDropEvent *lastEvent;
+ QList<QEvent::Type> eventList;
+ bool ignoresDragEnter;
+ bool ignoresDragMove;
+
+protected:
+ void dragEnterEvent(QGraphicsSceneDragDropEvent *event)
+ {
+ storeLastEvent(event);
+ event->setAccepted(!ignoresDragEnter);
+ if (!ignoresDragEnter)
+ event->setDropAction(Qt::IgnoreAction);
+ eventList << event->type();
+ }
+
+ void dragMoveEvent(QGraphicsSceneDragDropEvent *event)
+ {
+ storeLastEvent(event);
+ event->setAccepted(!ignoresDragMove);
+ eventList << event->type();
+ }
+
+ void dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
+ {
+ storeLastEvent(event);
+ eventList << event->type();
+ }
+
+ void dropEvent(QGraphicsSceneDragDropEvent *event)
+ {
+ storeLastEvent(event);
+ eventList << event->type();
+ }
+
+private:
+ void storeLastEvent(QGraphicsSceneDragDropEvent *event)
+ {
+ delete lastEvent;
+ lastEvent = new QGraphicsSceneDragDropEvent(event->type());
+ lastEvent->setScenePos(event->scenePos());
+ lastEvent->setScreenPos(event->screenPos());
+ lastEvent->setButtons(event->buttons());
+ lastEvent->setModifiers(event->modifiers());
+ lastEvent->setPossibleActions(event->possibleActions());
+ lastEvent->setProposedAction(event->proposedAction());
+ lastEvent->setDropAction(event->dropAction());
+ lastEvent->setMimeData(event->mimeData());
+ lastEvent->setWidget(event->widget());
+ lastEvent->setSource(event->source());
+ }
+};
+
+#ifndef QT_NO_DRAGANDDROP
+void tst_QGraphicsScene::dragAndDrop_simple()
+{
+ DndTester *item = new DndTester(QRectF(-10, -10, 20, 20));
+
+ QGraphicsScene scene;
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(100, 100);
+
+ QMimeData mimeData;
+
+ // Initial drag enter for the scene
+ QDragEnterEvent dragEnter(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragEnter);
+ QVERIFY(dragEnter.isAccepted());
+ QCOMPARE(dragEnter.dropAction(), Qt::CopyAction);
+
+ {
+ // Move outside the item
+ QDragMoveEvent dragMove(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(!dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
+ }
+ {
+ // Move inside the item without setAcceptDrops
+ QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(!dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
+ QCOMPARE(item->eventList.size(), 0);
+ }
+ item->setAcceptDrops(true);
+ {
+ // Move inside the item with setAcceptDrops
+ QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
+ QCOMPARE(item->eventList.size(), 2);
+ QCOMPARE(item->eventList.at(0), QEvent::GraphicsSceneDragEnter);
+ QCOMPARE(item->eventList.at(1), QEvent::GraphicsSceneDragMove);
+ QCOMPARE(item->lastEvent->screenPos(), view.mapToGlobal(dragMove.pos()));
+ QCOMPARE(item->lastEvent->scenePos(), view.mapToScene(dragMove.pos()));
+ QVERIFY(item->lastEvent->isAccepted());
+ QCOMPARE(item->lastEvent->dropAction(), Qt::IgnoreAction);
+ }
+ {
+ // Another move inside the item
+ QDragMoveEvent dragMove(view.mapFromScene(item->mapToScene(5, 5)), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
+ QCOMPARE(item->eventList.size(), 3);
+ QCOMPARE(item->eventList.at(2), QEvent::GraphicsSceneDragMove);
+ QCOMPARE(item->lastEvent->screenPos(), view.mapToGlobal(dragMove.pos()));
+ QCOMPARE(item->lastEvent->scenePos(), view.mapToScene(dragMove.pos()));
+ QVERIFY(item->lastEvent->isAccepted());
+ QCOMPARE(item->lastEvent->dropAction(), Qt::IgnoreAction);
+ }
+ {
+ // Move outside the item
+ QDragMoveEvent dragMove(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(!dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
+ QCOMPARE(item->eventList.size(), 4);
+ QCOMPARE(item->eventList.at(3), QEvent::GraphicsSceneDragLeave);
+ QCOMPARE(item->lastEvent->screenPos(), view.mapToGlobal(dragMove.pos()));
+ QCOMPARE(item->lastEvent->scenePos(), view.mapToScene(dragMove.pos()));
+ QVERIFY(item->lastEvent->isAccepted());
+ QCOMPARE(item->lastEvent->dropAction(), Qt::CopyAction);
+ }
+ {
+ // Move inside the item again
+ QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
+ QCOMPARE(item->eventList.size(), 6);
+ QCOMPARE(item->eventList.at(4), QEvent::GraphicsSceneDragEnter);
+ QCOMPARE(item->eventList.at(5), QEvent::GraphicsSceneDragMove);
+ QCOMPARE(item->lastEvent->screenPos(), view.mapToGlobal(dragMove.pos()));
+ QCOMPARE(item->lastEvent->scenePos(), view.mapToScene(dragMove.pos()));
+ QVERIFY(item->lastEvent->isAccepted());
+ QCOMPARE(item->lastEvent->dropAction(), Qt::IgnoreAction);
+ }
+ {
+ // Drop inside the item
+ QDropEvent drop(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &drop);
+ QVERIFY(drop.isAccepted());
+ QCOMPARE(drop.dropAction(), Qt::CopyAction);
+ QCOMPARE(item->eventList.size(), 7);
+ QCOMPARE(item->eventList.at(6), QEvent::GraphicsSceneDrop);
+ QCOMPARE(item->lastEvent->screenPos(), view.mapToGlobal(drop.pos()));
+ QCOMPARE(item->lastEvent->scenePos(), view.mapToScene(drop.pos()));
+ QVERIFY(item->lastEvent->isAccepted());
+ QCOMPARE(item->lastEvent->dropAction(), Qt::CopyAction);
+ }
+}
+
+void tst_QGraphicsScene::dragAndDrop_disabledOrInvisible()
+{
+ DndTester *item = new DndTester(QRectF(-10, -10, 20, 20));
+ item->setAcceptDrops(true);
+
+ QGraphicsScene scene;
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(100, 100);
+
+ QMimeData mimeData;
+
+ // Initial drag enter for the scene
+ QDragEnterEvent dragEnter(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragEnter);
+ QVERIFY(dragEnter.isAccepted());
+ QCOMPARE(dragEnter.dropAction(), Qt::CopyAction);
+ {
+ // Move inside the item
+ QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
+ QCOMPARE(item->eventList.size(), 2);
+ QCOMPARE(item->eventList.at(0), QEvent::GraphicsSceneDragEnter);
+ QCOMPARE(item->eventList.at(1), QEvent::GraphicsSceneDragMove);
+ }
+ {
+ // Move outside the item
+ QDragMoveEvent dragMove(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(!dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
+ QCOMPARE(item->eventList.size(), 3);
+ QCOMPARE(item->eventList.at(2), QEvent::GraphicsSceneDragLeave);
+ }
+
+ // Now disable the item
+ item->setEnabled(false);
+ QVERIFY(!item->isEnabled());
+ QVERIFY(item->isVisible());
+
+ {
+ // Move inside the item
+ QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(!dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
+ QCOMPARE(item->eventList.size(), 3);
+ QCOMPARE(item->eventList.at(2), QEvent::GraphicsSceneDragLeave);
+ }
+
+ // Reenable it, and make it invisible
+ item->setEnabled(true);
+ item->setVisible(false);
+ QVERIFY(item->isEnabled());
+ QVERIFY(!item->isVisible());
+
+ {
+ // Move inside the item
+ QDragMoveEvent dragMove(view.mapFromScene(item->scenePos()), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(!dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
+ QCOMPARE(item->eventList.size(), 3);
+ QCOMPARE(item->eventList.at(2), QEvent::GraphicsSceneDragLeave);
+ }
+
+ // Dummy drop event to keep the Mac from crashing.
+ QDropEvent dropEvent(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dropEvent);
+}
+
+void tst_QGraphicsScene::dragAndDrop_propagate()
+{
+ DndTester *item1 = new DndTester(QRectF(-10, -10, 20, 20));
+ DndTester *item2 = new DndTester(QRectF(0, 0, 20, 20));
+ item1->setAcceptDrops(true);
+ item2->setAcceptDrops(true);
+ item2->ignoresDragMove = true;
+ item2->ignoresDragEnter = false;
+ item2->setZValue(1);
+
+ item1->setData(0, "item1");
+ item2->setData(0, "item2");
+
+ QGraphicsScene scene;
+ scene.addItem(item1);
+ scene.addItem(item2);
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(100, 100);
+
+ QMimeData mimeData;
+
+ // Initial drag enter for the scene
+ QDragEnterEvent dragEnter(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragEnter);
+ QVERIFY(dragEnter.isAccepted());
+ QCOMPARE(dragEnter.dropAction(), Qt::CopyAction);
+
+ {
+ // Move outside the items
+ QDragMoveEvent dragMove(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(!dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
+ QVERIFY(item1->eventList.isEmpty());
+ QVERIFY(item2->eventList.isEmpty());
+ }
+ {
+ // Move inside item1
+ QDragMoveEvent dragMove(view.mapFromScene(-5, -5), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
+ QCOMPARE(item1->eventList.size(), 2);
+ QCOMPARE(item1->eventList.at(0), QEvent::GraphicsSceneDragEnter);
+ QCOMPARE(item1->eventList.at(1), QEvent::GraphicsSceneDragMove);
+ }
+
+ {
+ // Move into the intersection item1-item2
+ QDragMoveEvent dragMove(view.mapFromScene(5, 5), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(!dragMove.isAccepted()); // move does not propagate, (ignoresDragMove = true)
+ QCOMPARE(item1->eventList.size(), 3);
+ QCOMPARE(item1->eventList.at(2), QEvent::GraphicsSceneDragLeave);
+ QCOMPARE(item2->eventList.size(), 2);
+ QCOMPARE(item2->eventList.at(0), QEvent::GraphicsSceneDragEnter);
+ QCOMPARE(item2->eventList.at(1), QEvent::GraphicsSceneDragMove);
+ }
+ {
+ // Move into the item2
+ QDragMoveEvent dragMove(view.mapFromScene(15, 15), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(!dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::CopyAction);
+ QCOMPARE(item1->eventList.size(), 3);
+ QCOMPARE(item2->eventList.size(), 3);
+ QCOMPARE(item2->eventList.at(2), QEvent::GraphicsSceneDragMove);
+ }
+ {
+ // Move inside item1
+ QDragMoveEvent dragMove(view.mapFromScene(-5, -5), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(dragMove.isAccepted());
+ QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
+ QCOMPARE(item1->eventList.size(), 5);
+ QCOMPARE(item1->eventList.at(3), QEvent::GraphicsSceneDragEnter);
+ QCOMPARE(item1->eventList.at(4), QEvent::GraphicsSceneDragMove);
+ QCOMPARE(item2->eventList.size(), 4);
+ QCOMPARE(item2->eventList.at(3), QEvent::GraphicsSceneDragLeave);
+ }
+
+ {
+ item2->ignoresDragEnter = true;
+ // Move into the intersection item1-item2
+ QDragMoveEvent dragMove(view.mapFromScene(5, 5), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dragMove);
+ QVERIFY(dragMove.isAccepted()); // dragEnter propagates down to item1, which then accepts the move event.
+ QCOMPARE(dragMove.dropAction(), Qt::IgnoreAction);
+ QCOMPARE(item1->eventList.size(), 6);
+ QCOMPARE(item1->eventList.at(5), QEvent::GraphicsSceneDragMove);
+ QCOMPARE(item2->eventList.size(), 5);
+ QCOMPARE(item2->eventList.at(4), QEvent::GraphicsSceneDragEnter);
+ }
+
+ {
+ item2->ignoresDragEnter = false;
+ // Drop on the intersection item1-item2
+ QDropEvent drop(view.mapFromScene(5, 5), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &drop);
+ QVERIFY(drop.isAccepted());
+ QCOMPARE(drop.dropAction(), Qt::CopyAction);
+
+ QCOMPARE(item1->eventList.size(), 7);
+ QCOMPARE(item1->eventList.at(6), QEvent::GraphicsSceneDrop);
+ QCOMPARE(item2->eventList.size(), 5);
+ }
+
+ // Dummy drop event to keep the Mac from crashing.
+ QDropEvent dropEvent(QPoint(0, 0), Qt::CopyAction, &mimeData, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &dropEvent);
+}
+#endif
+
+void tst_QGraphicsScene::render_data()
+{
+ QTest::addColumn<QRectF>("targetRect");
+ QTest::addColumn<QRectF>("sourceRect");
+ QTest::addColumn<Qt::AspectRatioMode>("aspectRatioMode");
+ QTest::addColumn<QMatrix>("matrix");
+ QTest::addColumn<QPainterPath>("clip");
+
+ QPainterPath clip_rect;
+ clip_rect.addRect(50, 100, 200, 150);
+
+ QPainterPath clip_ellipse;
+ clip_ellipse.addEllipse(100,50,150,200);
+
+ QTest::newRow("all-all-untransformed") << QRectF() << QRectF()
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("all-topleft-untransformed") << QRectF(0, 0, 150, 150)
+ << QRectF() << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("all-topright-untransformed") << QRectF(150, 0, 150, 150)
+ << QRectF() << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("all-bottomleft-untransformed") << QRectF(0, 150, 150, 150)
+ << QRectF() << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("all-bottomright-untransformed") << QRectF(150, 150, 150, 150)
+ << QRectF() << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("topleft-all-untransformed") << QRectF() << QRectF(-10, -10, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("topright-all-untransformed") << QRectF() << QRectF(0, -10, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("bottomleft-all-untransformed") << QRectF() << QRectF(-10, 0, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("bottomright-all-untransformed") << QRectF() << QRectF(0, 0, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("topleft-topleft-untransformed") << QRectF(0, 0, 150, 150) << QRectF(-10, -10, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("topright-topleft-untransformed") << QRectF(150, 0, 150, 150) << QRectF(-10, -10, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("bottomleft-topleft-untransformed") << QRectF(0, 150, 150, 150) << QRectF(-10, -10, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("bottomright-topleft-untransformed") << QRectF(150, 150, 150, 150) << QRectF(-10, -10, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("top-topleft-untransformed") << QRectF(0, 0, 300, 150) << QRectF(-10, -10, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("bottom-topleft-untransformed") << QRectF(0, 150, 300, 150) << QRectF(-10, -10, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("left-topleft-untransformed") << QRectF(0, 0, 150, 300) << QRectF(-10, -10, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("right-topleft-untransformed") << QRectF(150, 0, 150, 300) << QRectF(-10, -10, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("top-bottomright-untransformed") << QRectF(0, 0, 300, 150) << QRectF(0, 0, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("bottom-bottomright-untransformed") << QRectF(0, 150, 300, 150) << QRectF(0, 0, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("left-bottomright-untransformed") << QRectF(0, 0, 150, 300) << QRectF(0, 0, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("right-bottomright-untransformed") << QRectF(150, 0, 150, 300) << QRectF(0, 0, 10, 10)
+ << Qt::IgnoreAspectRatio << QMatrix() << QPainterPath();
+ QTest::newRow("all-all-45-deg-right") << QRectF() << QRectF()
+ << Qt::IgnoreAspectRatio << QMatrix().rotate(-45) << QPainterPath();
+ QTest::newRow("all-all-45-deg-left") << QRectF() << QRectF()
+ << Qt::IgnoreAspectRatio << QMatrix().rotate(45) << QPainterPath();
+ QTest::newRow("all-all-scale-2x") << QRectF() << QRectF()
+ << Qt::IgnoreAspectRatio << QMatrix().scale(2, 2) << QPainterPath();
+ QTest::newRow("all-all-translate-50-0") << QRectF() << QRectF()
+ << Qt::IgnoreAspectRatio << QMatrix().translate(50, 0) << QPainterPath();
+ QTest::newRow("all-all-translate-0-50") << QRectF() << QRectF()
+ << Qt::IgnoreAspectRatio << QMatrix().translate(0, 50) << QPainterPath();
+ QTest::newRow("all-all-untransformed-clip-rect") << QRectF() << QRectF()
+ << Qt::IgnoreAspectRatio << QMatrix() << clip_rect;
+ QTest::newRow("all-all-untransformed-clip-ellipse") << QRectF() << QRectF()
+ << Qt::IgnoreAspectRatio << QMatrix() << clip_ellipse;
+}
+
+void tst_QGraphicsScene::render()
+{
+ QFETCH(QRectF, targetRect);
+ QFETCH(QRectF, sourceRect);
+ QFETCH(Qt::AspectRatioMode, aspectRatioMode);
+ QFETCH(QMatrix, matrix);
+ QFETCH(QPainterPath, clip);
+
+ QPixmap pix(30, 30);
+ pix.fill(Qt::blue);
+
+ QGraphicsView view;
+ QGraphicsScene scene(&view);
+ scene.addEllipse(QRectF(-10, -10, 20, 20), QPen(Qt::black), QBrush(Qt::white));
+ scene.addEllipse(QRectF(-2, -7, 4, 4), QPen(Qt::black), QBrush(Qt::yellow))->setZValue(1);
+ QGraphicsPixmapItem *item = scene.addPixmap(pix);
+ item->setZValue(2);
+ item->setOffset(QPointF(3, 3));
+ view.show();
+
+ scene.setSceneRect(scene.itemsBoundingRect());
+
+ QImage bigImage(300, 300, QImage::Format_RGB32);
+ bigImage.fill(0);
+ QPainter painter(&bigImage);
+ painter.setPen(Qt::lightGray);
+ for (int i = 0; i <= 300; i += 25) {
+ painter.drawLine(0, i, 300, i);
+ painter.drawLine(i, 0, i, 300);
+ }
+ painter.setPen(QPen(Qt::darkGray, 2));
+ painter.drawLine(0, 150, 300, 150);
+ painter.drawLine(150, 0, 150, 300);
+ painter.setMatrix(matrix);
+ if (!clip.isEmpty()) painter.setClipPath(clip);
+ scene.render(&painter, targetRect, sourceRect, aspectRatioMode);
+ painter.end();
+
+ const QString renderPath = QLatin1String(SRCDIR) + "/testData/render";
+ QString fileName = renderPath + QString("/%1.png").arg(QTest::currentDataTag());
+ QImage original(fileName);
+ QVERIFY(!original.isNull());
+
+ // Compare
+ int wrongPixels = 0;
+ for (int y = 0; y < original.height(); ++y) {
+ for (int x = 0; x < original.width(); ++x) {
+ if (bigImage.pixel(x, y) != original.pixel(x, y))
+ ++wrongPixels;
+ }
+ }
+
+ // This is a pixmap compare test - because of rounding errors on diverse
+ // platforms, and especially because tests are compiled in release mode,
+ // we set a 95% acceptance threshold for comparing images. This number may
+ // have to be adjusted if this test fails.
+ qreal threshold = 0.95;
+ qreal similarity = (1 - (wrongPixels / qreal(original.width() * original.height())));
+ if (similarity < threshold) {
+#if 1
+ // fail
+ QLabel *expectedLabel = new QLabel;
+ expectedLabel->setPixmap(QPixmap::fromImage(original));
+
+ QLabel *newLabel = new QLabel;
+ newLabel->setPixmap(QPixmap::fromImage(bigImage));
+
+ QGridLayout *gridLayout = new QGridLayout;
+ gridLayout->addWidget(new QLabel(tr("MISMATCH: %1").arg(QTest::currentDataTag())), 0, 0, 1, 2);
+ gridLayout->addWidget(new QLabel(tr("Current")), 1, 0);
+ gridLayout->addWidget(new QLabel(tr("Expected")), 1, 1);
+ gridLayout->addWidget(expectedLabel, 2, 1);
+ gridLayout->addWidget(newLabel, 2, 0);
+
+ QWidget widget;
+ widget.setLayout(gridLayout);
+ widget.show();
+
+ QTestEventLoop::instance().enterLoop(1);
+
+ QFAIL("Images are not identical.");
+#else
+ // generate
+ qDebug() << "Updating" << QTest::currentDataTag() << ":" << bigImage.save(fileName, "png");
+#endif
+ }
+}
+
+void tst_QGraphicsScene::renderItemsWithNegativeWidthOrHeight()
+{
+ QGraphicsScene scene(0, 0, 150, 150);
+
+ // Add item with negative width.
+ QGraphicsRectItem *item1 = new QGraphicsRectItem(0, 0, -150, 50);
+ item1->setBrush(Qt::red);
+ item1->setPos(150, 50);
+ scene.addItem(item1);
+
+ // Add item with negative height.
+ QGraphicsRectItem *item2 = new QGraphicsRectItem(0, 0, 50, -150);
+ item2->setBrush(Qt::blue);
+ item2->setPos(50, 150);
+ scene.addItem(item2);
+
+ QGraphicsView view(&scene);
+ view.setFrameStyle(QFrame::NoFrame);
+ view.resize(150, 150);
+ view.show();
+ QCOMPARE(view.viewport()->size(), QSize(150, 150));
+
+ QImage expected(view.viewport()->size(), QImage::Format_RGB32);
+ view.viewport()->render(&expected);
+
+ // Make sure the scene background is the same as the viewport background.
+ scene.setBackgroundBrush(view.viewport()->palette().brush(view.viewport()->backgroundRole()));
+ QImage actual(150, 150, QImage::Format_RGB32);
+ QPainter painter(&actual);
+ scene.render(&painter);
+ painter.end();
+
+ QCOMPARE(actual, expected);
+}
+
+void tst_QGraphicsScene::contextMenuEvent()
+{
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ EventTester *item = new EventTester;
+ scene.addItem(item);
+ item->setFlag(QGraphicsItem::ItemIsFocusable);
+ item->setFocus();
+
+ QVERIFY(item->hasFocus());
+ QVERIFY(scene.hasFocus());
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ view.activateWindow();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ view.centerOn(item);
+
+ {
+ QContextMenuEvent event(QContextMenuEvent::Keyboard, view.viewport()->rect().center(),
+ view.mapToGlobal(view.viewport()->rect().center()));
+ QApplication::sendEvent(view.viewport(), &event);
+ QCOMPARE(item->eventTypes.last(), QEvent::GraphicsSceneContextMenu);
+ }
+}
+
+class ContextMenuItem : public QGraphicsRectItem
+{
+public:
+ ContextMenuItem() : QGraphicsRectItem(0, 0, 100, 100)
+ { setBrush(Qt::red); }
+
+protected:
+ void contextMenuEvent(QGraphicsSceneContextMenuEvent *)
+ { /* just accept */ }
+};
+
+void tst_QGraphicsScene::contextMenuEvent_ItemIgnoresTransformations()
+{
+ QGraphicsScene scene(0, 0, 200, 200);
+ ContextMenuItem *item = new ContextMenuItem;
+ item->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+ scene.addItem(item);
+
+ QWidget topLevel;
+ QGraphicsView view(&scene, &topLevel);
+ view.resize(200, 200);
+ topLevel.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWaitForWindowShown(&topLevel);
+
+ {
+ QPoint pos(50, 50);
+ QContextMenuEvent event(QContextMenuEvent::Keyboard, pos, view.viewport()->mapToGlobal(pos));
+ event.ignore();
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(event.isAccepted());
+ }
+ {
+ QPoint pos(150, 150);
+ QContextMenuEvent event(QContextMenuEvent::Keyboard, pos, view.viewport()->mapToGlobal(pos));
+ event.ignore();
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(!event.isAccepted());
+ }
+ view.scale(1.5, 1.5);
+ {
+ QPoint pos(25, 25);
+ QContextMenuEvent event(QContextMenuEvent::Keyboard, pos, view.viewport()->mapToGlobal(pos));
+ event.ignore();
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(event.isAccepted());
+ }
+ {
+ QPoint pos(55, 55);
+ QContextMenuEvent event(QContextMenuEvent::Keyboard, pos, view.viewport()->mapToGlobal(pos));
+ event.ignore();
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(!event.isAccepted());
+ }
+}
+
+void tst_QGraphicsScene::update()
+{
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *rect = new QGraphicsRectItem(0, 0, 100, 100);
+ scene.addItem(rect);
+ qApp->processEvents();
+ rect->setPos(-100, -100);
+
+ // This function forces indexing
+ scene.itemAt(0, 0);
+
+ qRegisterMetaType<QList<QRectF> >("QList<QRectF>");
+ QSignalSpy spy(&scene, SIGNAL(changed(QList<QRectF>)));
+
+ // We update the scene.
+ scene.update();
+
+ // This function forces a purge, which will post an update signal
+ scene.itemAt(0, 0);
+
+ // This will process the pending update
+ QApplication::instance()->processEvents();
+
+ // Check that the update region is correct
+ QCOMPARE(spy.count(), 1);
+ QRectF region;
+ foreach (QRectF rectF, qVariantValue<QList<QRectF> >(spy.at(0).at(0)))
+ region |= rectF;
+ QCOMPARE(region, QRectF(-100, -100, 200, 200));
+}
+
+void tst_QGraphicsScene::update2()
+{
+ QGraphicsScene scene;
+ scene.setSceneRect(-200, -200, 200, 200);
+ CustomView view;
+ view.setScene(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.repaints >= 1);
+ view.repaints = 0;
+
+ // Make sure QGraphicsScene::update only requires one event-loop iteration
+ // before the view is updated.
+ scene.update();
+ qApp->processEvents();
+ QTRY_COMPARE(view.repaints, 1);
+ view.repaints = 0;
+
+ // The same for partial scene updates.
+ scene.update(QRectF(-100, -100, 100, 100));
+ qApp->processEvents();
+ QCOMPARE(view.repaints, 1);
+}
+
+void tst_QGraphicsScene::views()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ QCOMPARE(scene.views().size(), 1);
+ QCOMPARE(scene.views().at(0), &view);
+
+ QGraphicsView view1(&scene);
+ QCOMPARE(scene.views().size(), 2);
+ QVERIFY(scene.views().contains(&view1));
+
+ view.setScene(0);
+ QCOMPARE(scene.views().size(), 1);
+ QCOMPARE(scene.views().at(0), &view1);
+
+ QGraphicsView *view2 = new QGraphicsView(&scene);
+ QCOMPARE(scene.views().size(), 2);
+ QCOMPARE(scene.views().at(0), &view1);
+ QCOMPARE(scene.views().at(1), view2);
+
+ delete view2;
+
+ QCOMPARE(scene.views().size(), 1);
+ QCOMPARE(scene.views().at(0), &view1);
+}
+
+class CustomScene : public QGraphicsScene
+{
+public:
+ CustomScene() : gotTimerEvent(false)
+ { startTimer(10); }
+
+ bool gotTimerEvent;
+protected:
+ void timerEvent(QTimerEvent *)
+ {
+ gotTimerEvent = true;
+ }
+};
+
+void tst_QGraphicsScene::event()
+{
+ // Test that QGraphicsScene properly propagates events to QObject.
+ CustomScene scene;
+ QTestEventLoop::instance().enterLoop(1);
+ QVERIFY(scene.gotTimerEvent);
+}
+
+class DisabledItemTester : public QGraphicsRectItem
+{
+public:
+ DisabledItemTester(const QRectF &rect, QGraphicsItem *parent = 0)
+ : QGraphicsRectItem(rect, parent)
+ { }
+
+ QList<QEvent::Type> receivedSceneEvents;
+ QList<QEvent::Type> receivedSceneEventFilters;
+
+protected:
+ bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
+ {
+ receivedSceneEventFilters << event->type();
+ return QGraphicsRectItem::sceneEventFilter(watched, event);
+ }
+
+ bool sceneEvent(QEvent *event)
+ {
+ receivedSceneEvents << event->type();
+ return QGraphicsRectItem::sceneEvent(event);
+ }
+};
+
+void tst_QGraphicsScene::eventsToDisabledItems()
+{
+ QGraphicsScene scene;
+
+ DisabledItemTester *item1 = new DisabledItemTester(QRectF(-50, -50, 100, 100));
+ DisabledItemTester *item2 = new DisabledItemTester(QRectF(-50, -50, 100, 100));
+ item1->setZValue(1); // on top
+
+ scene.addItem(item1);
+ scene.addItem(item2);
+
+ item1->installSceneEventFilter(item2);
+
+ QVERIFY(item1->receivedSceneEvents.isEmpty());
+ QVERIFY(item2->receivedSceneEvents.isEmpty());
+ QVERIFY(item1->receivedSceneEventFilters.isEmpty());
+ QVERIFY(item2->receivedSceneEventFilters.isEmpty());
+
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setButton(Qt::LeftButton);
+ QApplication::sendEvent(&scene, &event);
+
+ // First item2 receives a scene event filter. Then item1 receives the
+ // actual event. Finally the event propagates to item2. So both items
+ // should have received the event, and item1 also got the filter.
+ QCOMPARE(item1->receivedSceneEvents.size(), 3);
+ QCOMPARE(item2->receivedSceneEvents.size(), 3);
+ QCOMPARE(item1->receivedSceneEventFilters.size(), 0);
+ QCOMPARE(item2->receivedSceneEventFilters.size(), 3);
+
+ item1->receivedSceneEvents.clear();
+ item1->receivedSceneEventFilters.clear();
+ item2->receivedSceneEvents.clear();
+ item2->receivedSceneEventFilters.clear();
+
+ item1->setEnabled(false); // disable the topmost item, eat mouse events
+
+ event.setButton(Qt::LeftButton);
+ event.setAccepted(false);
+ QApplication::sendEvent(&scene, &event);
+
+ // Check that only item1 received anything - it only got the filter.
+ QCOMPARE(item1->receivedSceneEvents.size(), 0);
+ QCOMPARE(item2->receivedSceneEvents.size(), 0);
+ QCOMPARE(item1->receivedSceneEventFilters.size(), 0);
+ QCOMPARE(item2->receivedSceneEventFilters.size(), 3);
+}
+
+class ExposedPixmapItem : public QGraphicsPixmapItem
+{
+public:
+ ExposedPixmapItem(QGraphicsItem *item = 0)
+ : QGraphicsPixmapItem(item)
+ { }
+
+ void paint(QPainter *, const QStyleOptionGraphicsItem *option, QWidget *)
+ {
+ exposed = option->exposedRect;
+ }
+
+ QRectF exposed;
+};
+
+void tst_QGraphicsScene::exposedRect()
+{
+ ExposedPixmapItem *item = new ExposedPixmapItem;
+ item->setPixmap(QPixmap(":/Ash_European.jpg"));
+ QGraphicsScene scene;
+ scene.addItem(item);
+
+ QCOMPARE(item->exposed, QRectF());
+
+ QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
+ QPainter painter(&image);
+
+ scene.render(&painter);
+ QCOMPARE(item->exposed, item->boundingRect());
+
+ painter.rotate(180);
+ painter.translate(100, 100);
+
+ scene.render(&painter);
+ QCOMPARE(item->exposed, item->boundingRect());
+}
+
+void tst_QGraphicsScene::tabFocus_emptyScene()
+{
+ QGraphicsScene scene;
+ QDial *dial1 = new QDial;
+ QGraphicsView *view = new QGraphicsView(&scene);
+ QDial *dial2 = new QDial;
+
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(dial1);
+ layout->addWidget(view);
+ layout->addWidget(dial2);
+
+ QWidget widget;
+ widget.setLayout(layout);
+ widget.show();
+ qApp->setActiveWindow(&widget);
+ widget.activateWindow();
+ QTest::qWait(125);
+
+ dial1->setFocus();
+ QVERIFY(dial1->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QVERIFY(!dial1->hasFocus());
+ QVERIFY(view->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QVERIFY(!view->hasFocus());
+ QVERIFY(dial2->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QVERIFY(!dial2->hasFocus());
+ QVERIFY(view->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QVERIFY(dial1->hasFocus());
+ QVERIFY(!dial2->hasFocus());
+}
+
+void tst_QGraphicsScene::tabFocus_sceneWithFocusableItems()
+{
+ QGraphicsScene scene;
+ QGraphicsTextItem *item = scene.addText("Qt rocks!");
+ item->setTabChangesFocus(true);
+ item->setTextInteractionFlags(Qt::TextEditorInteraction);
+ QVERIFY(item->flags() & QGraphicsItem::ItemIsFocusable);
+ item->setFocus();
+ item->clearFocus();
+
+ QGraphicsTextItem *item2 = scene.addText("Trolltech rocks!");
+ item2->setTabChangesFocus(true);
+ item2->setTextInteractionFlags(Qt::TextEditorInteraction);
+ item2->setPos(0, item->boundingRect().bottom());
+ QVERIFY(item2->flags() & QGraphicsItem::ItemIsFocusable);
+
+ QDial *dial1 = new QDial;
+ QGraphicsView *view = new QGraphicsView(&scene);
+ QDial *dial2 = new QDial;
+
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(dial1);
+ layout->addWidget(view);
+ layout->addWidget(dial2);
+
+ QWidget widget;
+ widget.setLayout(layout);
+ widget.show();
+ qApp->setActiveWindow(&widget);
+ widget.activateWindow();
+ QTest::qWaitForWindowShown(&widget);
+ QApplication::processEvents();
+
+ dial1->setFocus();
+ QTRY_VERIFY(dial1->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QTRY_VERIFY(view->hasFocus());
+ QVERIFY(view->viewport()->hasFocus());
+ QVERIFY(scene.hasFocus());
+ QVERIFY(item->hasFocus());
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QTRY_VERIFY(dial2->hasFocus());
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QTRY_VERIFY(view->hasFocus());
+ QTRY_VERIFY(view->viewport()->hasFocus());
+ QTRY_VERIFY(scene.hasFocus());
+ QTRY_VERIFY(item->hasFocus());
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QTRY_VERIFY(dial1->hasFocus());
+
+ // If the item requests input focus, it can only ensure that the scene
+ // sets focus on itself, but the scene cannot request focus from any view.
+ item->setFocus();
+ QApplication::processEvents();
+ QTRY_VERIFY(!view->hasFocus());
+ QVERIFY(!view->viewport()->hasFocus());
+ QTRY_VERIFY(scene.hasFocus());
+ QVERIFY(item->hasFocus());
+
+ view->setFocus();
+ QApplication::processEvents();
+ QTRY_VERIFY(view->hasFocus());
+ QTRY_VERIFY(view->viewport()->hasFocus());
+ QTRY_VERIFY(scene.hasFocus());
+ QTRY_VERIFY(item->hasFocus());
+
+ // Check that everyone loses focus when the widget is hidden.
+ widget.hide();
+ QTest::qWait(15);
+ QTRY_VERIFY(!view->hasFocus());
+ QVERIFY(!view->viewport()->hasFocus());
+ QVERIFY(!scene.hasFocus());
+ QVERIFY(!item->hasFocus());
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
+
+ // Check that the correct item regains focus.
+ widget.show();
+ qApp->setActiveWindow(&widget);
+ widget.activateWindow();
+ QTest::qWaitForWindowShown(&widget);
+ QTRY_VERIFY(view->hasFocus());
+ QTRY_VERIFY(scene.isActive());
+ QVERIFY(view->viewport()->hasFocus());
+ QVERIFY(scene.hasFocus());
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
+ QVERIFY(item->hasFocus());
+}
+
+class FocusWidget : public QGraphicsWidget
+{
+ Q_OBJECT
+public:
+ FocusWidget(QGraphicsItem *parent = 0)
+ : QGraphicsWidget(parent), tabs(0), backTabs(0)
+ {
+ setFocusPolicy(Qt::StrongFocus);
+ resize(100, 100);
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
+ {
+ if (option->state & QStyle::State_HasFocus) {
+ painter->fillRect(rect(), Qt::blue);
+ }
+ painter->setBrush(Qt::green);
+ painter->drawEllipse(rect());
+ if (option->state & QStyle::State_HasFocus) {
+ painter->setPen(QPen(Qt::black, 1, Qt::DashLine));
+ painter->setBrush(Qt::NoBrush);
+ painter->drawEllipse(rect().adjusted(5, 5, -5, -5));
+ }
+ }
+
+ int tabs;
+ int backTabs;
+
+protected:
+ bool sceneEvent(QEvent *event)
+ {
+ if (event->type() == QEvent::KeyPress) {
+ QKeyEvent *k = static_cast<QKeyEvent *>(event);
+ if (k->key() == Qt::Key_Tab)
+ ++tabs;
+ if (k->key() == Qt::Key_Backtab)
+ ++backTabs;
+ }
+ return QGraphicsWidget::sceneEvent(event);
+ }
+
+ void focusInEvent(QFocusEvent *)
+ { update(); }
+ void focusOutEvent(QFocusEvent *)
+ { update(); }
+};
+
+void tst_QGraphicsScene::tabFocus_sceneWithFocusWidgets()
+{
+ QGraphicsScene scene;
+
+ FocusWidget *widget1 = new FocusWidget;
+ FocusWidget *widget2 = new FocusWidget;
+ widget2->setPos(widget1->boundingRect().right(), 0);
+ scene.addItem(widget1);
+ scene.addItem(widget2);
+
+ QDial *dial1 = new QDial;
+ QGraphicsView *view = new QGraphicsView(&scene);
+ view->setRenderHint(QPainter::Antialiasing);
+ QDial *dial2 = new QDial;
+
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(dial1);
+ layout->addWidget(view);
+ layout->addWidget(dial2);
+
+ QWidget widget;
+ widget.setLayout(layout);
+ widget.show();
+ qApp->setActiveWindow(&widget);
+ widget.activateWindow();
+ QTest::qWaitForWindowShown(&widget);
+ QApplication::processEvents();
+
+ dial1->setFocus();
+ QTRY_VERIFY(dial1->hasFocus());
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QTRY_VERIFY(view->hasFocus());
+ QTRY_VERIFY(view->viewport()->hasFocus());
+ QTRY_VERIFY(scene.hasFocus());
+ QCOMPARE(widget1->tabs, 0);
+ QVERIFY(widget1->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QTRY_COMPARE(widget1->tabs, 1);
+ QTRY_VERIFY(widget2->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QTRY_COMPARE(widget2->tabs, 1);
+ QTRY_VERIFY(dial2->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QTRY_VERIFY(widget2->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QTRY_COMPARE(widget2->backTabs, 1);
+ QTRY_VERIFY(widget1->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QTRY_COMPARE(widget1->backTabs, 1);
+ QTRY_VERIFY(dial1->hasFocus());
+
+ widget1->setFocus();
+ view->viewport()->setFocus();
+ widget.hide();
+ QTest::qWait(15);
+ widget.show();
+ qApp->setActiveWindow(&widget);
+ widget.activateWindow();
+ QTest::qWaitForWindowShown(&widget);
+ QTRY_VERIFY(widget1->hasFocus());
+}
+
+void tst_QGraphicsScene::tabFocus_sceneWithNestedFocusWidgets()
+{
+ QGraphicsScene scene;
+
+ FocusWidget *widget1 = new FocusWidget;
+ FocusWidget *widget1_1 = new FocusWidget;
+ FocusWidget *widget1_2 = new FocusWidget;
+ widget1_1->setParentItem(widget1);
+ widget1_1->scale(0.5, 0.5);
+ widget1_1->setPos(0, widget1->boundingRect().height() / 2);
+ widget1_2->setParentItem(widget1);
+ widget1_2->scale(0.5, 0.5);
+ widget1_2->setPos(widget1->boundingRect().width() / 2, widget1->boundingRect().height() / 2);
+
+ FocusWidget *widget2 = new FocusWidget;
+ widget2->setPos(widget1->boundingRect().right(), 0);
+
+ widget1->setData(0, "widget1");
+ widget1_1->setData(0, "widget1_1");
+ widget1_2->setData(0, "widget1_2");
+ widget2->setData(0, "widget2");
+
+ scene.addItem(widget1);
+ scene.addItem(widget2);
+
+ QDial *dial1 = new QDial;
+ QGraphicsView *view = new QGraphicsView(&scene);
+ view->setRenderHint(QPainter::Antialiasing);
+ QDial *dial2 = new QDial;
+
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(dial1);
+ layout->addWidget(view);
+ layout->addWidget(dial2);
+
+ QWidget widget;
+ widget.setLayout(layout);
+ widget.show();
+ qApp->setActiveWindow(&widget);
+ widget.activateWindow();
+ QTest::qWaitForWindowShown(&widget);
+
+ dial1->setFocus();
+ QTRY_VERIFY(dial1->hasFocus());
+
+ EventSpy focusInSpy_1(widget1, QEvent::FocusIn);
+ EventSpy focusOutSpy_1(widget1, QEvent::FocusOut);
+ EventSpy focusInSpy_1_1(widget1_1, QEvent::FocusIn);
+ EventSpy focusOutSpy_1_1(widget1_1, QEvent::FocusOut);
+ EventSpy focusInSpy_1_2(widget1_2, QEvent::FocusIn);
+ EventSpy focusOutSpy_1_2(widget1_2, QEvent::FocusOut);
+ EventSpy focusInSpy_2(widget2, QEvent::FocusIn);
+ EventSpy focusOutSpy_2(widget2, QEvent::FocusOut);
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QTRY_VERIFY(widget1->hasFocus());
+ QCOMPARE(focusInSpy_1.count(), 1);
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QTRY_VERIFY(!widget1->hasFocus());
+ QVERIFY(widget1_1->hasFocus());
+ QCOMPARE(focusOutSpy_1.count(), 1);
+ QCOMPARE(focusInSpy_1_1.count(), 1);
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QTRY_VERIFY(!widget1_1->hasFocus());
+ QVERIFY(widget1_2->hasFocus());
+ QCOMPARE(focusOutSpy_1_1.count(), 1);
+ QCOMPARE(focusInSpy_1_2.count(), 1);
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QTRY_VERIFY(!widget1_2->hasFocus());
+ QVERIFY(widget2->hasFocus());
+ QCOMPARE(focusOutSpy_1_2.count(), 1);
+ QCOMPARE(focusInSpy_2.count(), 1);
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QApplication::processEvents();
+ QTRY_VERIFY(!widget2->hasFocus());
+ QVERIFY(dial2->hasFocus());
+ QCOMPARE(focusOutSpy_2.count(), 1);
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QTRY_VERIFY(widget2->hasFocus());
+ QCOMPARE(focusInSpy_2.count(), 2);
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QTRY_VERIFY(!widget2->hasFocus());
+ QTRY_VERIFY(widget1_2->hasFocus());
+ QCOMPARE(focusOutSpy_2.count(), 2);
+ QCOMPARE(focusInSpy_1_2.count(), 2);
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QTRY_VERIFY(!widget1_2->hasFocus());
+ QTRY_VERIFY(widget1_1->hasFocus());
+ QCOMPARE(focusOutSpy_1_2.count(), 2);
+ QCOMPARE(focusInSpy_1_1.count(), 2);
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QTRY_VERIFY(!widget1_1->hasFocus());
+ QTRY_VERIFY(widget1->hasFocus());
+ QCOMPARE(focusOutSpy_1_1.count(), 2);
+ QCOMPARE(focusInSpy_1.count(), 2);
+
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QApplication::processEvents();
+ QTRY_VERIFY(!widget1->hasFocus());
+ QTRY_VERIFY(dial1->hasFocus());
+ QCOMPARE(focusOutSpy_1.count(), 2);
+
+ widget1->setFocus();
+ view->viewport()->setFocus();
+ widget.hide();
+ QTest::qWait(12);
+ widget.show();
+ qApp->setActiveWindow(&widget);
+ widget.activateWindow();
+ QTest::qWaitForWindowShown(&widget);
+ QApplication::processEvents();
+ QTRY_VERIFY(widget1->hasFocus());
+}
+
+void tst_QGraphicsScene::style()
+{
+ QPointer<QWindowsStyle> windowsStyle = new QWindowsStyle;
+
+ QGraphicsScene scene;
+ QLineEdit *edit = new QLineEdit;
+ QGraphicsProxyWidget *proxy = scene.addWidget(edit);
+
+ EventSpy sceneSpy(&scene, QEvent::StyleChange);
+ EventSpy proxySpy(proxy, QEvent::StyleChange);
+ EventSpy editSpy(edit, QEvent::StyleChange);
+
+ QCOMPARE(scene.style(), QApplication::style());
+
+ scene.setStyle(windowsStyle);
+ QCOMPARE(sceneSpy.count(), 1);
+ QCOMPARE(proxySpy.count(), 1);
+ QCOMPARE(editSpy.count(), 1);
+ QCOMPARE(scene.style(), (QStyle *)windowsStyle);
+ QCOMPARE(proxy->style(), (QStyle *)windowsStyle);
+ QCOMPARE(edit->style(), (QStyle *)windowsStyle);
+
+ scene.setStyle(0);
+ QCOMPARE(sceneSpy.count(), 2);
+ QCOMPARE(proxySpy.count(), 2);
+ QCOMPARE(editSpy.count(), 2);
+ QCOMPARE(scene.style(), QApplication::style());
+ QCOMPARE(proxy->style(), QApplication::style());
+ QCOMPARE(edit->style(), QApplication::style());
+ QVERIFY(!windowsStyle); // deleted
+}
+
+void tst_QGraphicsScene::task139710_bspTreeCrash()
+{
+ // create a scene with 2000 items
+ QGraphicsScene scene(0, 0, 1000, 1000);
+
+ for (int i = 0; i < 2; ++i) {
+ // trigger delayed item indexing
+ qApp->processEvents();
+ scene.setSceneRect(0, 0, 10000, 10000);
+
+ // delete all items in the scene - pointers are now likely to be recycled
+ foreach (QGraphicsItem *item, scene.items()) {
+ scene.removeItem(item);
+ delete item;
+ }
+
+ // add 1000 more items - the BSP tree is now resized
+ for (int i = 0; i < 1000; ++i) {
+ QGraphicsRectItem *item = scene.addRect(QRectF(0, 0, 200, 200));
+ item->setPos(qrand() % 10000, qrand() % 10000);
+ }
+
+ // trigger delayed item indexing for the first 1000 items
+ qApp->processEvents();
+
+ // add 1000 more items - the BSP tree is now resized
+ for (int i = 0; i < 1000; ++i) {
+ QGraphicsRectItem *item = scene.addRect(QRectF(0, 0, 200, 200));
+ item->setPos(qrand() % 10000, qrand() % 10000);
+ }
+
+ // get items from the BSP tree and use them. there was junk in the tree
+ // the second time this happened.
+ foreach (QGraphicsItem *item, scene.items(QRectF(0, 0, 1000, 1000)))
+ item->moveBy(0, 0);
+ }
+}
+
+void tst_QGraphicsScene::task139782_containsItemBoundingRect()
+{
+ // The item in question has a scene bounding rect of (10, 10, 50, 50)
+ QGraphicsScene scene(0.0, 0.0, 200.0, 200.0);
+ QGraphicsRectItem *item = new QGraphicsRectItem(0.0, 0.0, 50.0, 50.0, 0, &scene);
+ item->setPos(10.0, 10.0);
+
+ // The (0, 0, 50, 50) scene rect should not include the item's bounding rect
+ QVERIFY(!scene.items(QRectF(0.0, 0.0, 50.0, 50.0), Qt::ContainsItemBoundingRect).contains(item));
+
+ // The (9, 9, 500, 500) scene rect _should_ include the item's bounding rect
+ QVERIFY(scene.items(QRectF(9.0, 9.0, 500.0, 500.0), Qt::ContainsItemBoundingRect).contains(item));
+
+ // The (25, 25, 5, 5) scene rect should not include the item's bounding rect
+ QVERIFY(!scene.items(QRectF(25.0, 25.0, 5.0, 5.0), Qt::ContainsItemBoundingRect).contains(item));
+}
+
+void tst_QGraphicsScene::task176178_itemIndexMethodBreaksSceneRect()
+{
+ QGraphicsScene scene;
+ scene.setItemIndexMethod(QGraphicsScene::NoIndex);
+ QGraphicsRectItem *rect = new QGraphicsRectItem;
+ rect->setRect(0,0,100,100);
+ scene.addItem(rect);
+ QCOMPARE(scene.sceneRect(), rect->rect());
+}
+
+void tst_QGraphicsScene::task160653_selectionChanged()
+{
+ QGraphicsScene scene(0, 0, 100, 100);
+ scene.addItem(new QGraphicsRectItem(0, 0, 20, 20));
+ scene.addItem(new QGraphicsRectItem(30, 30, 20, 20));
+ foreach (QGraphicsItem *item, scene.items()) {
+ item->setFlags(
+ item->flags() | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable);
+ item->setSelected(true);
+ }
+ QVERIFY(scene.items().size() > 1);
+ QCOMPARE(scene.items().size(), scene.selectedItems().size());
+
+ QSignalSpy spy(&scene, SIGNAL(selectionChanged()));
+ QGraphicsView view(&scene);
+ QTest::mouseClick(
+ view.viewport(), Qt::LeftButton, 0, view.mapFromScene(scene.items().first()->scenePos()));
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QGraphicsScene::task250680_childClip()
+{
+ QGraphicsRectItem *clipper = new QGraphicsRectItem;
+ clipper->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ clipper->setPen(QPen(Qt::green));
+ clipper->setRect(200, 200, 640, 480);
+
+ QGraphicsRectItem *rect = new QGraphicsRectItem(clipper);
+ rect->setPen(QPen(Qt::red));
+ rect->setBrush(QBrush(QColor(255, 0, 0, 75)));
+ rect->setPos(320, 240);
+ rect->setRect(-25, -25, 50, 50);
+
+ QGraphicsScene scene;
+ scene.addItem(clipper);
+
+ QPainterPath path;
+ path.addRect(-25, -25, 50, 50);
+ QVERIFY(QPathCompare::comparePaths(rect->clipPath().simplified(), path));
+
+ QCOMPARE(scene.items(QRectF(320, 240, 5, 5)).size(), 2);
+ rect->rotate(45);
+ QCOMPARE(scene.items(QRectF(320, 240, 5, 5)).size(), 2);
+}
+
+void tst_QGraphicsScene::sorting_data()
+{
+ QTest::addColumn<bool>("cache");
+
+ QTest::newRow("Normal sorting") << false;
+ QTest::newRow("Cached sorting") << true;
+}
+
+void tst_QGraphicsScene::sorting()
+{
+ QFETCH(bool, cache);
+
+ QGraphicsScene scene;
+ scene.setSortCacheEnabled(cache);
+
+ QGraphicsRectItem *t_1 = new QGraphicsRectItem(0, 0, 50, 50);
+ QGraphicsRectItem *c_1 = new QGraphicsRectItem(0, 0, 40, 40, t_1);
+ QGraphicsRectItem *c_1_1 = new QGraphicsRectItem(0, 0, 30, 30, c_1);
+ QGraphicsRectItem *c_1_1_1 = new QGraphicsRectItem(0, 0, 20, 20, c_1_1);
+ QGraphicsRectItem *c_1_2 = new QGraphicsRectItem(0, 0, 30, 30, c_1);
+ QGraphicsRectItem *c_2 = new QGraphicsRectItem(0, 0, 40, 40, t_1);
+ QGraphicsRectItem *c_2_1 = new QGraphicsRectItem(0, 0, 30, 30, c_2);
+ QGraphicsRectItem *c_2_1_1 = new QGraphicsRectItem(0, 0, 20, 20, c_2_1);
+ QGraphicsRectItem *c_2_2 = new QGraphicsRectItem(0, 0, 30, 30, c_2);
+ t_1->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
+ c_1->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
+ c_1_1->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
+ c_1_1_1->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
+ c_1_2->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
+ c_2->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
+ c_2_1->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
+ c_2_1_1->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
+ c_2_2->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
+
+ c_1->setPos(23, 18);
+ c_1_1->setPos(24, 28);
+ c_1_1_1->setPos(-16, 16);
+ c_1_2->setPos(-16, 28);
+ c_1_2->setZValue(1);
+ c_2->setPos(-23, 18);
+ c_2->setZValue(1);
+ c_2_1->setPos(24, 28);
+ c_2_1_1->setPos(-16, 16);
+ c_2_2->setPos(-16, 28);
+ c_2_2->setZValue(1);
+
+ c_1->setFlag(QGraphicsItem::ItemIsMovable);
+ c_1_1->setFlag(QGraphicsItem::ItemIsMovable);
+ c_1_1_1->setFlag(QGraphicsItem::ItemIsMovable);
+ c_1_2->setFlag(QGraphicsItem::ItemIsMovable);
+ c_2->setFlag(QGraphicsItem::ItemIsMovable);
+ c_2_1->setFlag(QGraphicsItem::ItemIsMovable);
+ c_2_1_1->setFlag(QGraphicsItem::ItemIsMovable);
+ c_2_2->setFlag(QGraphicsItem::ItemIsMovable);
+
+ t_1->setData(0, "t_1");
+ c_1->setData(0, "c_1");
+ c_1_1->setData(0, "c_1_1");
+ c_1_1_1->setData(0, "c_1_1_1");
+ c_1_2->setData(0, "c_1_2");
+ c_2->setData(0, "c_2");
+ c_2_1->setData(0, "c_2_1");
+ c_2_1_1->setData(0, "c_2_1_1");
+ c_2_2->setData(0, "c_2_2");
+
+ scene.addItem(t_1);
+
+ foreach (QGraphicsItem *item, scene.items())
+ item->setFlag(QGraphicsItem::ItemIsSelectable);
+
+ // QGraphicsView view(&scene);
+ // view.setDragMode(QGraphicsView::RubberBandDrag);
+ // view.show();
+
+ qDebug() << "items: {";
+ foreach (QGraphicsItem *item, scene.items(32, 31, 4, 55))
+ qDebug() << "\t" << item->data(0).toString();
+ qDebug() << "}";
+
+ QCOMPARE(scene.items(32, 31, 4, 55),
+ QList<QGraphicsItem *>()
+ << c_1_2 << c_1_1_1 << c_1 << t_1);
+ QCOMPARE(scene.items(-53, 47, 136, 3),
+ QList<QGraphicsItem *>()
+ << c_2_2 << c_2_1 << c_2 << c_1_2 << c_1_1 << c_1 << t_1);
+ QCOMPARE(scene.items(-23, 79, 104, 3),
+ QList<QGraphicsItem *>()
+ << c_2_1_1 << c_1_1_1);
+ QCOMPARE(scene.items(-26, -3, 92, 79),
+ QList<QGraphicsItem *>()
+ << c_2_2 << c_2_1_1 << c_2_1 << c_2
+ << c_1_2 << c_1_1_1 << c_1_1 << c_1
+ << t_1);
+}
+
+class ChangedListener : public QObject
+{
+ Q_OBJECT
+public:
+ QList<QList<QRectF> > changes;
+
+public slots:
+ void changed(const QList<QRectF> &dirty)
+ {
+ changes << dirty;
+ }
+};
+
+void tst_QGraphicsScene::changedSignal_data()
+{
+ QTest::addColumn<bool>("withView");
+
+ QTest::newRow("without view") << false;
+ QTest::newRow("with view") << true;
+}
+
+void tst_QGraphicsScene::changedSignal()
+{
+ QFETCH(bool, withView);
+ QGraphicsScene scene;
+ ChangedListener cl;
+ connect(&scene, SIGNAL(changed(const QList<QRectF> &)), &cl, SLOT(changed(const QList<QRectF> &)));
+
+ QGraphicsView *view = 0;
+ if (withView)
+ view = new QGraphicsView(&scene);
+
+ QGraphicsRectItem *rect = new QGraphicsRectItem(0, 0, 10, 10);
+ scene.addItem(rect);
+
+ QCOMPARE(cl.changes.size(), 0);
+ QTRY_COMPARE(cl.changes.size(), 1);
+ QCOMPARE(cl.changes.at(0).size(), 1);
+ QCOMPARE(cl.changes.at(0).first(), QRectF(0, 0, 10, 10));
+
+ rect->setPos(20, 0);
+
+ QCOMPARE(cl.changes.size(), 1);
+ qApp->processEvents();
+ QCOMPARE(cl.changes.size(), 2);
+ QCOMPARE(cl.changes.at(1).size(), 2);
+ QCOMPARE(cl.changes.at(1).first(), QRectF(0, 0, 10, 10));
+ QCOMPARE(cl.changes.at(1).last(), QRectF(20, 0, 10, 10));
+
+ QCOMPARE(scene.sceneRect(), QRectF(0, 0, 30, 10));
+
+ if (withView)
+ delete view;
+}
+
+void tst_QGraphicsScene::stickyFocus_data()
+{
+ QTest::addColumn<bool>("sticky");
+ QTest::newRow("sticky") << true;
+ QTest::newRow("not sticky") << false;
+}
+
+void tst_QGraphicsScene::stickyFocus()
+{
+ QFETCH(bool, sticky);
+
+ QGraphicsScene scene;
+ QEvent activate(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activate);
+
+ QGraphicsTextItem *text = scene.addText("Hei");
+ text->setTextInteractionFlags(Qt::TextEditorInteraction);
+ text->setFocus();
+
+ scene.setStickyFocus(sticky);
+
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setScenePos(QPointF(-10, -10)); // outside item
+ event.setButton(Qt::LeftButton);
+ qApp->sendEvent(&scene, &event);
+
+ QCOMPARE(text->hasFocus(), sticky);
+}
+
+void tst_QGraphicsScene::sendEvent()
+{
+ QGraphicsScene scene;
+ QGraphicsTextItem *item = scene.addText(QString());
+ EventSpy *spy = new EventSpy(&scene, item, QEvent::User);
+ QCOMPARE(spy->count(), 0);
+ QEvent event(QEvent::User);
+ scene.sendEvent(item, &event);
+ QCOMPARE(spy->count(), 1);
+}
+
+void tst_QGraphicsScene::inputMethod_data()
+{
+ QTest::addColumn<int>("flags");
+ QTest::addColumn<bool>("callFocusItem");
+ QTest::newRow("0") << 0 << false;
+ QTest::newRow("1") << (int)QGraphicsItem::ItemAcceptsInputMethod << false;
+ QTest::newRow("2") << (int)QGraphicsItem::ItemIsFocusable << false;
+ QTest::newRow("3") <<
+ (int)(QGraphicsItem::ItemAcceptsInputMethod|QGraphicsItem::ItemIsFocusable) << true;
+}
+
+class InputMethodTester : public QGraphicsRectItem
+{
+ void inputMethodEvent(QInputMethodEvent *) { ++eventCalls; }
+ QVariant inputMethodQuery(Qt::InputMethodQuery) const { ++queryCalls; return QVariant(); }
+public:
+ int eventCalls;
+ mutable int queryCalls;
+};
+
+class TestInputContext : public QInputContext
+{
+public:
+ TestInputContext() {}
+
+ QString identifierName() { return QString(); }
+ QString language() { return QString(); }
+
+ void reset() {
+ ++resetCalls;
+ sendEvent(QInputMethodEvent()); }
+
+ bool isComposing() const { return false; }
+
+ int resetCalls;
+};
+
+void tst_QGraphicsScene::inputMethod()
+{
+ QFETCH(int, flags);
+ QFETCH(bool, callFocusItem);
+
+ InputMethodTester *item = new InputMethodTester;
+ item->setFlags((QGraphicsItem::GraphicsItemFlags)flags);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ TestInputContext *inputContext = new TestInputContext;
+ qApp->setInputContext(inputContext);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ view.setFocus();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
+
+ inputContext->resetCalls = 0;
+ scene.addItem(item);
+ QInputMethodEvent event;
+
+ scene.setFocusItem(item);
+ QCOMPARE(!!(item->flags() & QGraphicsItem::ItemIsFocusable), scene.focusItem() == item);
+ QCOMPARE(inputContext->resetCalls, 0);
+
+ item->eventCalls = 0;
+ qApp->sendEvent(&scene, &event);
+ QCOMPARE(item->eventCalls, callFocusItem ? 1 : 0);
+
+ item->queryCalls = 0;
+ scene.inputMethodQuery((Qt::InputMethodQuery)0);
+ QCOMPARE(item->queryCalls, callFocusItem ? 1 : 0);
+
+ scene.setFocusItem(0);
+ // the input context is reset twice, once because an item has lost focus and again because
+ // the Qt::WA_InputMethodEnabled flag is cleared because no item has focus.
+ QCOMPARE(inputContext->resetCalls, callFocusItem ? 2 : 0);
+ QCOMPARE(item->eventCalls, callFocusItem ? 2 : 0); // verify correct delivery of "reset" event
+ QCOMPARE(item->queryCalls, callFocusItem ? 1 : 0); // verify that value is unaffected
+
+ item->eventCalls = 0;
+ qApp->sendEvent(&scene, &event);
+ QCOMPARE(item->eventCalls, 0);
+
+ item->queryCalls = 0;
+ scene.inputMethodQuery((Qt::InputMethodQuery)0);
+ QCOMPARE(item->queryCalls, 0);
+}
+
+void tst_QGraphicsScene::dispatchHoverOnPress()
+{
+ QGraphicsScene scene;
+ EventTester *tester1 = new EventTester;
+ tester1->setAcceptHoverEvents(true);
+ EventTester *tester2 = new EventTester;
+ tester2->setAcceptHoverEvents(true);
+ tester2->setPos(30, 30);
+ scene.addItem(tester1);
+ scene.addItem(tester2);
+
+ tester1->eventTypes.clear();
+ tester2->eventTypes.clear();
+
+ {
+ QGraphicsSceneMouseEvent me(QEvent::GraphicsSceneMousePress);
+ me.setButton(Qt::LeftButton);
+ me.setButtons(Qt::LeftButton);
+ QGraphicsSceneMouseEvent me2(QEvent::GraphicsSceneMouseRelease);
+ me2.setButton(Qt::LeftButton);
+ qApp->sendEvent(&scene, &me);
+ qApp->sendEvent(&scene, &me2);
+ QCOMPARE(tester1->eventTypes, QList<QEvent::Type>()
+ << QEvent::GraphicsSceneHoverEnter
+ << QEvent::GraphicsSceneHoverMove
+ << QEvent::GrabMouse
+ << QEvent::GraphicsSceneMousePress
+ << QEvent::UngrabMouse);
+ tester1->eventTypes.clear();
+ qApp->sendEvent(&scene, &me);
+ qApp->sendEvent(&scene, &me2);
+ QCOMPARE(tester1->eventTypes, QList<QEvent::Type>()
+ << QEvent::GraphicsSceneHoverMove
+ << QEvent::GrabMouse
+ << QEvent::GraphicsSceneMousePress
+ << QEvent::UngrabMouse);
+ }
+ {
+ QGraphicsSceneMouseEvent me(QEvent::GraphicsSceneMousePress);
+ me.setScenePos(QPointF(30, 30));
+ me.setButton(Qt::LeftButton);
+ me.setButtons(Qt::LeftButton);
+ QGraphicsSceneMouseEvent me2(QEvent::GraphicsSceneMouseRelease);
+ me2.setScenePos(QPointF(30, 30));
+ me2.setButton(Qt::LeftButton);
+ tester1->eventTypes.clear();
+ qApp->sendEvent(&scene, &me);
+ qApp->sendEvent(&scene, &me2);
+ qDebug() << tester1->eventTypes;
+ QCOMPARE(tester1->eventTypes, QList<QEvent::Type>()
+ << QEvent::GraphicsSceneHoverLeave);
+ QCOMPARE(tester2->eventTypes, QList<QEvent::Type>()
+ << QEvent::GraphicsSceneHoverEnter
+ << QEvent::GraphicsSceneHoverMove
+ << QEvent::GrabMouse
+ << QEvent::GraphicsSceneMousePress
+ << QEvent::UngrabMouse);
+ tester2->eventTypes.clear();
+ qApp->sendEvent(&scene, &me);
+ qApp->sendEvent(&scene, &me2);
+ QCOMPARE(tester2->eventTypes, QList<QEvent::Type>()
+ << QEvent::GraphicsSceneHoverMove
+ << QEvent::GrabMouse
+ << QEvent::GraphicsSceneMousePress
+ << QEvent::UngrabMouse);
+ }
+}
+
+void tst_QGraphicsScene::initialFocus_data()
+{
+ QTest::addColumn<bool>("activeScene");
+ QTest::addColumn<bool>("explicitSetFocus");
+ QTest::addColumn<bool>("isPanel");
+ QTest::addColumn<bool>("shouldHaveFocus");
+
+ QTest::newRow("inactive scene, normal item") << false << false << false << false;
+ QTest::newRow("inactive scene, panel item") << false << false << true << false;
+ QTest::newRow("inactive scene, normal item, explicit focus") << false << true << false << true;
+ QTest::newRow("inactive scene, panel, explicit focus") << false << true << true << true;
+ QTest::newRow("active scene, normal item") << true << false << false << false;
+ QTest::newRow("active scene, panel item") << true << false << true << false;
+ QTest::newRow("active scene, normal item, explicit focus") << true << true << false << true;
+ QTest::newRow("active scene, panel, explicit focus") << true << true << true << true;
+}
+
+void tst_QGraphicsScene::initialFocus()
+{
+ QFETCH(bool, activeScene);
+ QFETCH(bool, explicitSetFocus);
+ QFETCH(bool, isPanel);
+ QFETCH(bool, shouldHaveFocus);
+
+ QGraphicsRectItem *rect = new QGraphicsRectItem;
+ rect->setFlag(QGraphicsItem::ItemIsFocusable);
+ QVERIFY(!rect->hasFocus());
+
+ if (isPanel)
+ rect->setFlag(QGraphicsItem::ItemIsPanel);
+
+ // Setting focus on an item before adding to the scene will ensure
+ // it gets focus when the scene is activated.
+ if (explicitSetFocus)
+ rect->setFocus();
+
+ QGraphicsScene scene;
+ QVERIFY(!scene.isActive());
+
+ if (activeScene) {
+ QEvent windowActivate(QEvent::WindowActivate);
+ qApp->sendEvent(&scene, &windowActivate);
+ scene.setFocus();
+ }
+
+ scene.addItem(rect);
+
+ if (!activeScene) {
+ QEvent windowActivate(QEvent::WindowActivate);
+ qApp->sendEvent(&scene, &windowActivate);
+ scene.setFocus();
+ }
+
+ QCOMPARE(rect->hasFocus(), shouldHaveFocus);
+}
+
+class PolishItem : public QGraphicsTextItem
+{
+public:
+ PolishItem(QGraphicsItem *parent = 0)
+ : QGraphicsTextItem(parent), polished(false), deleteChildrenInPolish(true), addChildrenInPolish(false) { }
+
+ bool polished;
+ bool deleteChildrenInPolish;
+ bool addChildrenInPolish;
+protected:
+ QVariant itemChange(GraphicsItemChange change, const QVariant& value)
+ {
+ if (change == ItemVisibleChange) {
+ polished = true;
+ if (deleteChildrenInPolish)
+ qDeleteAll(childItems());
+ if (addChildrenInPolish) {
+ for (int i = 0; i < 10; ++i)
+ new PolishItem(this);
+ }
+ }
+ return QGraphicsItem::itemChange(change, value);
+ }
+};
+
+void tst_QGraphicsScene::polishItems()
+{
+ QGraphicsScene scene;
+ PolishItem *parent = new PolishItem;
+ scene.addItem(parent);
+ PolishItem *child = new PolishItem(parent);
+ Q_UNUSED(child)
+ // test that QGraphicsScenePrivate::_q_polishItems() doesn't crash
+ QMetaObject::invokeMethod(&scene,"_q_polishItems");
+}
+
+void tst_QGraphicsScene::polishItems2()
+{
+ QGraphicsScene scene;
+ PolishItem *item = new PolishItem;
+ item->addChildrenInPolish = true;
+ item->deleteChildrenInPolish = true;
+ // These children should be deleted in the polish.
+ for (int i = 0; i < 20; ++i)
+ new PolishItem(item);
+ scene.addItem(item);
+
+ // Wait for the polish event to be delivered.
+ QVERIFY(!item->polished);
+ QApplication::sendPostedEvents(&scene, QEvent::MetaCall);
+ QVERIFY(item->polished);
+
+ // We deleted the children we added above, but we also
+ // added 10 new children. These should be polished in the next
+ // event loop iteration.
+ QList<QGraphicsItem *> children = item->childItems();
+ QCOMPARE(children.count(), 10);
+ foreach (QGraphicsItem *child, children)
+ QVERIFY(!static_cast<PolishItem *>(child)->polished);
+
+ QApplication::sendPostedEvents(&scene, QEvent::MetaCall);
+ foreach (QGraphicsItem *child, children)
+ QVERIFY(static_cast<PolishItem *>(child)->polished);
+}
+
+void tst_QGraphicsScene::isActive()
+{
+ QGraphicsScene scene1;
+ QVERIFY(!scene1.isActive());
+ QGraphicsScene scene2;
+ QVERIFY(!scene2.isActive());
+
+ {
+ QWidget toplevel1;
+ QHBoxLayout *layout = new QHBoxLayout;
+ toplevel1.setLayout(layout);
+ QGraphicsView *view1 = new QGraphicsView(&scene1);
+ QGraphicsView *view2 = new QGraphicsView(&scene2);
+ layout->addWidget(view1);
+ layout->addWidget(view2);
+
+ QVERIFY(!scene1.isActive());
+ QVERIFY(!scene2.isActive());
+
+ view1->setVisible(false);
+
+ toplevel1.show();
+ QApplication::setActiveWindow(&toplevel1);
+ QTest::qWaitForWindowShown(&toplevel1);
+ QTRY_COMPARE(QApplication::activeWindow(), &toplevel1);
+
+ QVERIFY(!scene1.isActive()); //it is hidden;
+ QVERIFY(scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(scene2.hasFocus());
+
+ view1->show();
+ QVERIFY(scene1.isActive());
+ QVERIFY(scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(scene2.hasFocus());
+
+ view2->hide();
+
+ QVERIFY(scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ toplevel1.hide();
+ QTest::qWait(50);
+ QTRY_VERIFY(!scene1.isActive());
+ QTRY_VERIFY(!scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ toplevel1.show();
+ QApplication::setActiveWindow(&toplevel1);
+ QApplication::processEvents();
+ QTRY_COMPARE(QApplication::activeWindow(), &toplevel1);
+
+ QTRY_VERIFY(scene1.isActive());
+ QTRY_VERIFY(!scene2.isActive());
+ QVERIFY(scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ view2->show();
+ QVERIFY(scene1.isActive());
+ QVERIFY(scene2.isActive());
+ QVERIFY(scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+ }
+
+ QVERIFY(!scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+
+ {
+ QWidget toplevel2;
+ QHBoxLayout *layout = new QHBoxLayout;
+ toplevel2.setLayout(layout);
+ QGraphicsView *view1 = new QGraphicsView(&scene1);
+ QGraphicsView *view2 = new QGraphicsView();
+ layout->addWidget(view1);
+ layout->addWidget(view2);
+
+ QVERIFY(!scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ toplevel2.show();
+ QApplication::setActiveWindow(&toplevel2);
+ QTest::qWaitForWindowShown(&toplevel2);
+ QTRY_COMPARE(QApplication::activeWindow(), &toplevel2);
+
+ QVERIFY(scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ view2->setScene(&scene2);
+
+ QVERIFY(scene1.isActive());
+ QVERIFY(scene2.isActive());
+ QVERIFY(scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ view1->setScene(&scene2);
+ QVERIFY(!scene1.isActive());
+ QVERIFY(scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(scene2.hasFocus());
+
+ view1->hide();
+ QVERIFY(!scene1.isActive());
+ QVERIFY(scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(scene2.hasFocus());
+
+ view1->setScene(&scene1);
+ QVERIFY(!scene1.isActive());
+ QVERIFY(scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(scene2.hasFocus());
+
+ view1->show();
+ QVERIFY(scene1.isActive());
+ QVERIFY(scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(scene2.hasFocus());
+
+ view2->hide();
+ QVERIFY(scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ QGraphicsView topLevelView;
+ topLevelView.show();
+ QApplication::setActiveWindow(&topLevelView);
+ topLevelView.setFocus();
+ QTest::qWaitForWindowShown(&topLevelView);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&topLevelView));
+
+ QVERIFY(!scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ topLevelView.setScene(&scene1);
+ QVERIFY(scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ view2->show();
+ QVERIFY(scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ view1->hide();
+ QVERIFY(scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ QApplication::setActiveWindow(&toplevel2);
+ QTRY_COMPARE(QApplication::activeWindow(), &toplevel2);
+
+ QVERIFY(!scene1.isActive());
+ QVERIFY(scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(scene2.hasFocus());
+ }
+
+ QVERIFY(!scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ {
+ QWidget toplevel3;
+ QHBoxLayout *layout = new QHBoxLayout;
+ toplevel3.setLayout(layout);
+ QGraphicsView *view1 = new QGraphicsView(&scene1);
+ QGraphicsView *view2 = new QGraphicsView(&scene2);
+ layout->addWidget(view1);
+
+ QVERIFY(!scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+
+ toplevel3.show();
+ QApplication::setActiveWindow(&toplevel3);
+ QTest::qWaitForWindowShown(&toplevel3);
+ QTRY_COMPARE(QApplication::activeWindow(), &toplevel3);
+
+ QVERIFY(scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ layout->addWidget(view2);
+ QApplication::processEvents();
+ QVERIFY(scene1.isActive());
+ QVERIFY(scene2.isActive());
+ QVERIFY(scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+ view1->setParent(0);
+ QVERIFY(!scene1.isActive());
+ QVERIFY(scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(scene2.hasFocus());
+ delete view1;
+ }
+
+ QVERIFY(!scene1.isActive());
+ QVERIFY(!scene2.isActive());
+ QVERIFY(!scene1.hasFocus());
+ QVERIFY(!scene2.hasFocus());
+
+}
+
+void tst_QGraphicsScene::siblingIndexAlwaysValid()
+{
+ QGraphicsScene scene;
+
+ QGraphicsWidget *parent = new QGraphicsWidget;
+ parent->setZValue(350);
+ parent->setGeometry(0, 0, 100, 100);
+ QGraphicsWidget *parent2 = new QGraphicsWidget;
+ parent2->setGeometry(10, 10, 50, 50);
+ QGraphicsWidget *child = new QGraphicsWidget(parent2);
+ child->setGeometry(15, 15, 25, 25);
+ child->setZValue(150);
+ //Both are top level
+ scene.addItem(parent);
+ scene.addItem(parent2);
+
+ //Then we make the child a top level
+ child->setParentItem(0);
+
+ //This is trigerred by a repaint...
+ QGraphicsScenePrivate::get(&scene)->index->estimateTopLevelItems(QRectF(), Qt::AscendingOrder);
+
+ delete child;
+
+ //If there are in the list that's bad, we crash...
+ QVERIFY(!QGraphicsScenePrivate::get(&scene)->topLevelItems.contains(static_cast<QGraphicsItem *>(child)));
+
+ //Other case
+ QGraphicsScene scene2;
+ // works with bsp tree index
+ scene2.setItemIndexMethod(QGraphicsScene::NoIndex);
+
+ QGraphicsView view2(&scene2);
+
+ // first add the blue rect
+ QGraphicsRectItem* const item1 = new QGraphicsRectItem(QRect( 10, 10, 10, 10 ));
+ item1->setPen(QColor(Qt::blue));
+ item1->setBrush(Qt::blue);
+ scene2.addItem(item1);
+
+ // then add the red rect
+ QGraphicsRectItem* const item2 = new QGraphicsRectItem(5, 5, 10, 10);
+ item2->setPen(QColor(Qt::red));
+ item2->setBrush(Qt::red);
+ scene2.addItem(item2);
+
+ // now the blue one is visible on top of the red one -> swap them (important for the bug)
+ item1->setZValue(1.0);
+ item2->setZValue(0.0);
+
+ view2.show();
+
+ // handle events as a real life app would do
+ QApplication::processEvents();
+
+ // now delete the red rect
+ delete item2;
+
+ // handle events as a real life app would do
+ QApplication::processEvents();
+
+ //We should not crash
+
+}
+
+void tst_QGraphicsScene::removeFullyTransparentItem()
+{
+ QGraphicsScene scene;
+
+ QGraphicsItem *parent = scene.addRect(0, 0, 100, 100);
+ parent->setFlag(QGraphicsItem::ItemHasNoContents);
+
+ QGraphicsItem *child = scene.addRect(0, 0, 100, 100);
+ child->setParentItem(parent);
+
+ CustomView view;
+ view.setScene(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ // NB! The parent has the ItemHasNoContents flag set, which means
+ // the parent itself doesn't generate any update requests, only the
+ // child can possibly trigger an update. Also note that the child
+ // is removed before processing events.
+ view.repaints = 0;
+ parent->setOpacity(0);
+ QVERIFY(qFuzzyIsNull(child->effectiveOpacity()));
+ scene.removeItem(child);
+ QVERIFY(!scene.items().contains(child));
+ QTRY_VERIFY(view.repaints > 0);
+
+ // Re-add child. There's nothing new to display (child is still
+ // effectively hidden), so it shouldn't trigger an update.
+ view.repaints = 0;
+ child->setParentItem(parent);
+ QVERIFY(scene.items().contains(child));
+ QVERIFY(qFuzzyIsNull(child->effectiveOpacity()));
+ QApplication::processEvents();
+ QCOMPARE(view.repaints, 0);
+
+ // Nothing is visible on the screen, removing child item shouldn't trigger an update.
+ scene.removeItem(child);
+ QApplication::processEvents();
+ QCOMPARE(view.repaints, 0);
+ delete child;
+}
+
+void tst_QGraphicsScene::taskQTBUG_5904_crashWithDeviceCoordinateCache()
+{
+ QGraphicsScene scene;
+ QGraphicsRectItem *rectItem = scene.addRect(QRectF(0, 0, 100, 200), QPen(Qt::black), QBrush(Qt::green));
+
+ rectItem->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+
+ QPixmap pixmap(100,200);
+ QPainter painter(&pixmap);
+ painter.setRenderHint(QPainter::Antialiasing);
+ scene.render(&painter);
+ painter.end();
+ // No crash, then it passed!
+}
+
+void tst_QGraphicsScene::taskQT657_paintIntoCacheWithTransparentParts()
+{
+ // Test using DeviceCoordinateCache and opaque item
+ QWidget *w = new QWidget();
+ w->setPalette(QColor(0, 0, 255));
+ w->setGeometry(0, 0, 50, 50);
+
+ QGraphicsScene *scene = new QGraphicsScene();
+ CustomView *view = new CustomView;
+ view->setScene(scene);
+
+ QGraphicsProxyWidget *proxy = scene->addWidget(w);
+ proxy->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ proxy->rotate(15);
+
+ view->show();
+ QTest::qWaitForWindowShown(view);
+ view->repaints = 0;
+ proxy->update(10, 10, 10, 10);
+ QTest::qWait(50);
+ QTRY_VERIFY(view->repaints > 0);
+
+ QPixmap pix;
+ QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(proxy);
+ QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->deviceData.value(view->viewport()).key, &pix));
+
+ QTransform t = proxy->sceneTransform();
+ // Map from scene coordinates to pixmap coordinates.
+ // X origin in the pixmap is the most-left point
+ // of the item's boundingRect in the scene.
+ qreal adjust = t.mapRect(proxy->boundingRect().toRect()).left();
+ QRect rect = t.mapRect(QRect(10, 10, 10, 10)).adjusted(-adjust, 0, -adjust + 1, 1);
+ QPixmap subpix = pix.copy(rect);
+
+ QImage im = subpix.toImage();
+ for(int i = 0; i < im.width(); i++) {
+ for(int j = 0; j < im.height(); j++)
+ QCOMPARE(qAlpha(im.pixel(i, j)), 255);
+ }
+
+ delete w;
+}
+
+void tst_QGraphicsScene::taskQTBUG_7863_paintIntoCacheWithTransparentParts()
+{
+ // Test using DeviceCoordinateCache and semi-transparent item
+ {
+ QGraphicsRectItem *backItem = new QGraphicsRectItem(0, 0, 100, 100);
+ backItem->setBrush(QColor(255, 255, 0));
+ QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 50, 50);
+ rectItem->setBrush(QColor(0, 0, 255, 125));
+ rectItem->setParentItem(backItem);
+
+ QGraphicsScene *scene = new QGraphicsScene();
+ CustomView *view = new CustomView;
+ view->setScene(scene);
+
+ scene->addItem(backItem);
+ rectItem->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+ backItem->rotate(15);
+
+ view->show();
+ QTest::qWaitForWindowShown(view);
+ view->repaints = 0;
+ rectItem->update(10, 10, 10, 10);
+ QTest::qWait(50);
+ QTRY_VERIFY(view->repaints > 0);
+
+ QPixmap pix;
+ QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(rectItem);
+ QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->deviceData.value(view->viewport()).key, &pix));
+
+ QTransform t = rectItem->sceneTransform();
+ // Map from scene coordinates to pixmap coordinates.
+ // X origin in the pixmap is the most-left point
+ // of the item's boundingRect in the scene.
+ qreal adjust = t.mapRect(rectItem->boundingRect().toRect()).left();
+ QRect rect = t.mapRect(QRect(10, 10, 10, 10)).adjusted(-adjust, 0, -adjust + 1, 1);
+ QPixmap subpix = pix.copy(rect);
+
+ QImage im = subpix.toImage();
+ for(int i = 0; i < im.width(); i++) {
+ for(int j = 0; j < im.height(); j++) {
+ QCOMPARE(qAlpha(im.pixel(i, j)), 125);
+ }
+ }
+
+ delete view;
+ }
+
+ // Test using ItemCoordinateCache and opaque item
+ {
+ QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 50, 50);
+ rectItem->setBrush(QColor(0, 0, 255));
+
+ QGraphicsScene *scene = new QGraphicsScene();
+ CustomView *view = new CustomView;
+ view->setScene(scene);
+
+ scene->addItem(rectItem);
+ rectItem->setCacheMode(QGraphicsItem::ItemCoordinateCache);
+ rectItem->rotate(15);
+
+ view->show();
+ QTest::qWaitForWindowShown(view);
+ view->repaints = 0;
+ rectItem->update(10, 10, 10, 10);
+ QTest::qWait(50);
+ QTRY_VERIFY(view->repaints > 0);
+
+ QPixmap pix;
+ QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(rectItem);
+ QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->key, &pix));
+
+ QTransform t = rectItem->sceneTransform();
+ // Map from scene coordinates to pixmap coordinates.
+ // X origin in the pixmap is the most-left point
+ // of the item's boundingRect in the scene.
+ qreal adjust = t.mapRect(rectItem->boundingRect().toRect()).left();
+ QRect rect = t.mapRect(QRect(10, 10, 10, 10)).adjusted(-adjust, 0, -adjust + 1, 1);
+ QPixmap subpix = pix.copy(rect);
+
+ QImage im = subpix.toImage();
+ for(int i = 0; i < im.width(); i++) {
+ for(int j = 0; j < im.height(); j++)
+ QCOMPARE(qAlpha(im.pixel(i, j)), 255);
+ }
+
+ delete view;
+ }
+
+ // Test using ItemCoordinateCache and semi-transparent item
+ {
+ QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 50, 50);
+ rectItem->setBrush(QColor(0, 0, 255, 125));
+
+ QGraphicsScene *scene = new QGraphicsScene();
+ CustomView *view = new CustomView;
+ view->setScene(scene);
+
+ scene->addItem(rectItem);
+ rectItem->setCacheMode(QGraphicsItem::ItemCoordinateCache);
+ rectItem->rotate(15);
+
+ view->show();
+ QTest::qWaitForWindowShown(view);
+ view->repaints = 0;
+ rectItem->update(10, 10, 10, 10);
+ QTest::qWait(50);
+ QTRY_VERIFY(view->repaints > 0);
+
+ QPixmap pix;
+ QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(rectItem);
+ QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->key, &pix));
+
+ QTransform t = rectItem->sceneTransform();
+ // Map from scene coordinates to pixmap coordinates.
+ // X origin in the pixmap is the most-left point
+ // of the item's boundingRect in the scene.
+ qreal adjust = t.mapRect(rectItem->boundingRect().toRect()).left();
+ QRect rect = t.mapRect(QRect(10, 10, 10, 10)).adjusted(-adjust, 0, -adjust + 1, 1);
+ QPixmap subpix = pix.copy(rect);
+
+ QImage im = subpix.toImage();
+ for(int i = 0; i < im.width(); i++) {
+ for(int j = 0; j < im.height(); j++)
+ QCOMPARE(qAlpha(im.pixel(i, j)), 125);
+ }
+
+ delete view;
+ }
+}
+
+void tst_QGraphicsScene::taskQT_3674_doNotCrash()
+{
+ QGraphicsScene scene;
+
+ QGraphicsView view(&scene);
+ view.resize(200, 200);
+
+ QPixmap pixmap(view.size());
+ QPainter painter(&pixmap);
+ view.render(&painter);
+ painter.end();
+
+ scene.addItem(new QGraphicsWidget);
+ scene.setBackgroundBrush(Qt::green);
+
+ QApplication::processEvents();
+ QApplication::processEvents();
+}
+
+void tst_QGraphicsScene::zeroScale()
+{
+ //should not crash
+ QGraphicsScene scene;
+ scene.setSceneRect(-100, -100, 100, 100);
+ QGraphicsView view(&scene);
+
+ ChangedListener cl;
+ connect(&scene, SIGNAL(changed(const QList<QRectF> &)), &cl, SLOT(changed(const QList<QRectF> &)));
+
+ QGraphicsRectItem *rect1 = new QGraphicsRectItem(0, 0, 0.0000001, 0.00000001);
+ scene.addItem(rect1);
+ rect1->setRotation(82);
+ rect1->setScale(0.00000001);
+
+ QApplication::processEvents();
+ QTRY_COMPARE(cl.changes.count(), 1);
+ QGraphicsRectItem *rect2 = new QGraphicsRectItem(-0.0000001, -0.0000001, 0.0000001, 0.0000001);
+ rect2->setScale(0.00000001);
+ scene.addItem(rect2);
+ rect1->setPos(20,20);
+ QApplication::processEvents();
+ QTRY_COMPARE(cl.changes.count(), 2);
+}
+
+void tst_QGraphicsScene::taskQTBUG_15977_renderWithDeviceCoordinateCache()
+{
+ QGraphicsScene scene;
+ scene.setSceneRect(0, 0, 100, 100);
+ QGraphicsRectItem *rect = scene.addRect(0, 0, 100, 100);
+ rect->setPen(Qt::NoPen);
+ rect->setBrush(Qt::red);
+ rect->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
+
+ QImage image(100, 100, QImage::Format_RGB32);
+ QPainter p(&image);
+ scene.render(&p);
+ p.end();
+
+ QImage expected(100, 100, QImage::Format_RGB32);
+ p.begin(&expected);
+ p.fillRect(expected.rect(), Qt::red);
+ p.end();
+
+ QCOMPARE(image, expected);
+}
+
+void tst_QGraphicsScene::taskQTBUG_16401_focusItem()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsRectItem *rect = scene.addRect(0, 0, 100, 100);
+ rect->setFlag(QGraphicsItem::ItemIsFocusable);
+
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::setActiveWindow(&view);
+
+ QVERIFY(!scene.focusItem());
+
+ rect->setFocus();
+ QCOMPARE(scene.focusItem(), rect);
+ QFocusEvent focusOut(QEvent::FocusOut);
+ QApplication::sendEvent(&view, &focusOut);
+ QVERIFY(!scene.focusItem());
+ QFocusEvent focusIn(QEvent::FocusIn);
+ QApplication::sendEvent(&view, &focusIn);
+ QCOMPARE(scene.focusItem(), rect);
+
+ rect->clearFocus();
+ QVERIFY(!scene.focusItem());
+ QApplication::sendEvent(&view, &focusOut);
+ QVERIFY(!scene.focusItem());
+ QApplication::sendEvent(&view, &focusIn);
+ QVERIFY(!scene.focusItem());
+}
+
+QTEST_MAIN(tst_QGraphicsScene)
+#include "tst_qgraphicsscene.moc"
diff --git a/tests/auto/widgets/graphicsview/qgraphicssceneindex/qgraphicssceneindex.pro b/tests/auto/widgets/graphicsview/qgraphicssceneindex/qgraphicssceneindex.pro
new file mode 100644
index 0000000000..5e61034d7c
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicssceneindex/qgraphicssceneindex.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+requires(contains(QT_CONFIG,private_tests))
+QT += widgets widgets-private
+QT += core-private gui-private
+SOURCES += tst_qgraphicssceneindex.cpp
+CONFIG += parallel_test
diff --git a/tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp
new file mode 100644
index 0000000000..7507701267
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicssceneindex/tst_qgraphicssceneindex.cpp
@@ -0,0 +1,366 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.1, 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <QtWidgets/qgraphicsscene.h>
+#include <private/qgraphicsscenebsptreeindex_p.h>
+#include <private/qgraphicssceneindex_p.h>
+#include <private/qgraphicsscenelinearindex_p.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class tst_QGraphicsSceneIndex : public QObject
+{
+ Q_OBJECT
+public slots:
+ void initTestCase();
+
+private slots:
+ void customIndex_data();
+ void customIndex();
+ void scatteredItems_data();
+ void scatteredItems();
+ void overlappedItems_data();
+ void overlappedItems();
+ void movingItems_data();
+ void movingItems();
+ void connectedToSceneRectChanged();
+ void items();
+ void removeItems();
+ void clear();
+
+private:
+ void common_data();
+ QGraphicsSceneIndex *createIndex(const QString &name);
+};
+
+void tst_QGraphicsSceneIndex::initTestCase()
+{
+}
+
+void tst_QGraphicsSceneIndex::common_data()
+{
+ QTest::addColumn<QString>("indexMethod");
+
+ QTest::newRow("BSP") << QString("bsp");
+ QTest::newRow("Linear") << QString("linear");
+}
+
+QGraphicsSceneIndex *tst_QGraphicsSceneIndex::createIndex(const QString &indexMethod)
+{
+ QGraphicsSceneIndex *index = 0;
+ QGraphicsScene *scene = new QGraphicsScene();
+ if (indexMethod == "bsp")
+ index = new QGraphicsSceneBspTreeIndex(scene);
+
+ if (indexMethod == "linear")
+ index = new QGraphicsSceneLinearIndex(scene);
+
+ return index;
+}
+
+void tst_QGraphicsSceneIndex::customIndex_data()
+{
+ common_data();
+}
+
+void tst_QGraphicsSceneIndex::customIndex()
+{
+#if 0
+ QFETCH(QString, indexMethod);
+ QGraphicsSceneIndex *index = createIndex(indexMethod);
+
+ QGraphicsScene scene;
+ scene.setSceneIndex(index);
+
+ scene.addRect(0, 0, 30, 40);
+ QCOMPARE(scene.items(QRectF(0, 0, 10, 10)).count(), 1);
+#endif
+}
+
+void tst_QGraphicsSceneIndex::scatteredItems_data()
+{
+ common_data();
+}
+
+void tst_QGraphicsSceneIndex::scatteredItems()
+{
+ QFETCH(QString, indexMethod);
+
+ QGraphicsScene scene;
+#if 1
+ scene.setItemIndexMethod(indexMethod == "linear" ? QGraphicsScene::NoIndex : QGraphicsScene::BspTreeIndex);
+#else
+ QGraphicsSceneIndex *index = createIndex(indexMethod);
+ scene.setSceneIndex(index);
+#endif
+
+ for (int i = 0; i < 10; ++i)
+ scene.addRect(i*50, i*50, 40, 35);
+
+ QCOMPARE(scene.items(QPointF(5, 5)).count(), 1);
+ QCOMPARE(scene.items(QPointF(55, 55)).count(), 1);
+ QCOMPARE(scene.items(QPointF(-100, -100)).count(), 0);
+
+ QCOMPARE(scene.items(QRectF(0, 0, 10, 10)).count(), 1);
+ QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).count(), 10);
+ QCOMPARE(scene.items(QRectF(-100, -1000, 0, 0)).count(), 0);
+}
+
+void tst_QGraphicsSceneIndex::overlappedItems_data()
+{
+ common_data();
+}
+
+void tst_QGraphicsSceneIndex::overlappedItems()
+{
+ QFETCH(QString, indexMethod);
+
+ QGraphicsScene scene;
+#if 1
+ scene.setItemIndexMethod(indexMethod == "linear" ? QGraphicsScene::NoIndex : QGraphicsScene::BspTreeIndex);
+#else
+ QGraphicsSceneIndex *index = createIndex(indexMethod);
+ scene.setSceneIndex(index);
+#endif
+
+ for (int i = 0; i < 10; ++i)
+ for (int j = 0; j < 10; ++j)
+ scene.addRect(i*50, j*50, 200, 200);
+
+ QCOMPARE(scene.items(QPointF(5, 5)).count(), 1);
+ QCOMPARE(scene.items(QPointF(55, 55)).count(), 4);
+ QCOMPARE(scene.items(QPointF(105, 105)).count(), 9);
+ QCOMPARE(scene.items(QPointF(-100, -100)).count(), 0);
+
+ QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).count(), 100);
+ QCOMPARE(scene.items(QRectF(-100, -1000, 0, 0)).count(), 0);
+ QCOMPARE(scene.items(QRectF(0, 0, 200, 200)).count(), 16);
+ QCOMPARE(scene.items(QRectF(0, 0, 100, 100)).count(), 4);
+ QCOMPARE(scene.items(QRectF(0, 0, 1, 100)).count(), 2);
+ QCOMPARE(scene.items(QRectF(0, 0, 1, 1000)).count(), 10);
+}
+
+void tst_QGraphicsSceneIndex::movingItems_data()
+{
+ common_data();
+}
+
+void tst_QGraphicsSceneIndex::movingItems()
+{
+ QFETCH(QString, indexMethod);
+
+ QGraphicsScene scene;
+#if 1
+ scene.setItemIndexMethod(indexMethod == "linear" ? QGraphicsScene::NoIndex : QGraphicsScene::BspTreeIndex);
+#else
+ QGraphicsSceneIndex *index = createIndex(indexMethod);
+ scene.setSceneIndex(index);
+#endif
+
+ for (int i = 0; i < 10; ++i)
+ scene.addRect(i*50, i*50, 40, 35);
+
+ QGraphicsRectItem *box = scene.addRect(0, 0, 10, 10);
+ QCOMPARE(scene.items(QPointF(5, 5)).count(), 2);
+ QCOMPARE(scene.items(QPointF(-1, -1)).count(), 0);
+ QCOMPARE(scene.items(QRectF(0, 0, 5, 5)).count(), 2);
+
+ box->setPos(10, 10);
+ QCOMPARE(scene.items(QPointF(9, 9)).count(), 1);
+ QCOMPARE(scene.items(QPointF(15, 15)).count(), 2);
+ QCOMPARE(scene.items(QRectF(0, 0, 1, 1)).count(), 1);
+
+ box->setPos(-5, -5);
+ QCOMPARE(scene.items(QPointF(-1, -1)).count(), 1);
+ QCOMPARE(scene.items(QRectF(0, 0, 1, 1)).count(), 2);
+
+ QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).count(), 11);
+}
+
+void tst_QGraphicsSceneIndex::connectedToSceneRectChanged()
+{
+
+ class MyScene : public QGraphicsScene
+ {
+ public:
+ using QGraphicsScene::receivers;
+ };
+
+ MyScene scene; // Uses QGraphicsSceneBspTreeIndex by default.
+ QCOMPARE(scene.receivers(SIGNAL(sceneRectChanged(const QRectF&))), 1);
+
+ scene.setItemIndexMethod(QGraphicsScene::NoIndex); // QGraphicsSceneLinearIndex
+ QCOMPARE(scene.receivers(SIGNAL(sceneRectChanged(const QRectF&))), 1);
+}
+
+void tst_QGraphicsSceneIndex::items()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *item1 = scene.addRect(0, 0, 10, 10);
+ QGraphicsItem *item2 = scene.addRect(10, 10, 10, 10);
+ QCOMPARE(scene.items().size(), 2);
+
+ // Move from unindexed items into bsp tree.
+ QTest::qWait(50);
+ QCOMPARE(scene.items().size(), 2);
+
+ // Add untransformable item.
+ QGraphicsItem *item3 = new QGraphicsRectItem(QRectF(20, 20, 10, 10));
+ item3->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+ scene.addItem(item3);
+ QCOMPARE(scene.items().size(), 3);
+
+ // Move from unindexed items into untransformable items.
+ QTest::qWait(50);
+ QCOMPARE(scene.items().size(), 3);
+
+ // Move from untransformable items into unindexed items.
+ item3->setFlag(QGraphicsItem::ItemIgnoresTransformations, false);
+ QCOMPARE(scene.items().size(), 3);
+ QTest::qWait(50);
+ QCOMPARE(scene.items().size(), 3);
+
+ // Make all items untransformable.
+ item1->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+ item2->setParentItem(item1);
+ item3->setParentItem(item2);
+ QCOMPARE(scene.items().size(), 3);
+
+ // Move from unindexed items into untransformable items.
+ QTest::qWait(50);
+ QCOMPARE(scene.items().size(), 3);
+}
+
+class RectWidget : public QGraphicsWidget
+{
+ Q_OBJECT
+public:
+ RectWidget(QGraphicsItem *parent = 0) : QGraphicsWidget(parent)
+ {
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem * /* option */, QWidget * /* widget */)
+ {
+ painter->setBrush(brush);
+ painter->drawRect(boundingRect());
+ }
+public:
+ QBrush brush;
+};
+
+void tst_QGraphicsSceneIndex::removeItems()
+{
+ QGraphicsScene scene;
+
+ RectWidget *parent = new RectWidget;
+ parent->brush = QBrush(QColor(Qt::magenta));
+ parent->setGeometry(250, 250, 400, 400);
+
+ RectWidget *widget = new RectWidget(parent);
+ widget->brush = QBrush(QColor(Qt::blue));
+ widget->setGeometry(10, 10, 200, 200);
+
+ RectWidget *widgetChild1 = new RectWidget(widget);
+ widgetChild1->brush = QBrush(QColor(Qt::green));
+ widgetChild1->setGeometry(20, 20, 100, 100);
+
+ RectWidget *widgetChild2 = new RectWidget(widgetChild1);
+ widgetChild2->brush = QBrush(QColor(Qt::yellow));
+ widgetChild2->setGeometry(25, 25, 50, 50);
+
+ scene.addItem(parent);
+
+ QGraphicsView view(&scene);
+ view.resize(600, 600);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+
+ QApplication::processEvents();
+
+ scene.removeItem(widgetChild1);
+
+ delete widgetChild1;
+
+ //We move the parent
+ scene.items(295, 295, 50, 50);
+
+ //This should not crash
+}
+
+void tst_QGraphicsSceneIndex::clear()
+{
+ class MyItem : public QGraphicsItem
+ {
+ public:
+ MyItem(QGraphicsItem *parent = 0) : QGraphicsItem(parent), numPaints(0) {}
+ int numPaints;
+ protected:
+ QRectF boundingRect() const { return QRectF(0, 0, 10, 10); }
+ void paint(QPainter * /* painter */, const QStyleOptionGraphicsItem *, QWidget *)
+ { ++numPaints; }
+ };
+
+ QGraphicsScene scene;
+ scene.setSceneRect(0, 0, 100, 100);
+ scene.addItem(new MyItem);
+
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(250);
+ scene.clear();
+
+ // Make sure the index is re-generated after QGraphicsScene::clear();
+ // otherwise no items will be painted.
+ MyItem *item = new MyItem;
+ scene.addItem(item);
+ qApp->processEvents();
+ QTRY_COMPARE(item->numPaints, 1);
+}
+
+QTEST_MAIN(tst_QGraphicsSceneIndex)
+#include "tst_qgraphicssceneindex.moc"
diff --git a/tests/auto/widgets/graphicsview/qgraphicstransform/qgraphicstransform.pro b/tests/auto/widgets/graphicsview/qgraphicstransform/qgraphicstransform.pro
new file mode 100644
index 0000000000..de7f01f36f
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicstransform/qgraphicstransform.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+QT += widgets
+SOURCES += tst_qgraphicstransform.cpp
+CONFIG += parallel_test
+
+linux-*:contains(QT_CONFIG,release):DEFINES+=MAY_HIT_QTBUG_20661
diff --git a/tests/auto/widgets/graphicsview/qgraphicstransform/tst_qgraphicstransform.cpp b/tests/auto/widgets/graphicsview/qgraphicstransform/tst_qgraphicstransform.cpp
new file mode 100644
index 0000000000..7d5a9578ad
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicstransform/tst_qgraphicstransform.cpp
@@ -0,0 +1,408 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.1, 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qgraphicsitem.h>
+#include <qgraphicstransform.h>
+
+class tst_QGraphicsTransform : public QObject {
+ Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void scale();
+ void rotation();
+ void rotation3d_data();
+ void rotation3d();
+ void rotation3dArbitraryAxis_data();
+ void rotation3dArbitraryAxis();
+
+private:
+ QString toString(QTransform const&);
+};
+
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_QGraphicsTransform::initTestCase()
+{
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_QGraphicsTransform::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_QGraphicsTransform::init()
+{
+}
+
+// This will be called after every test function.
+void tst_QGraphicsTransform::cleanup()
+{
+}
+
+static QTransform transform2D(const QGraphicsTransform& t)
+{
+ QMatrix4x4 m;
+ t.applyTo(&m);
+ return m.toTransform();
+}
+
+void tst_QGraphicsTransform::scale()
+{
+ QGraphicsScale scale;
+
+ // check initial conditions
+ QCOMPARE(scale.xScale(), qreal(1));
+ QCOMPARE(scale.yScale(), qreal(1));
+ QCOMPARE(scale.zScale(), qreal(1));
+ QCOMPARE(scale.origin(), QVector3D(0, 0, 0));
+
+ scale.setOrigin(QVector3D(10, 10, 0));
+
+ QCOMPARE(scale.xScale(), qreal(1));
+ QCOMPARE(scale.yScale(), qreal(1));
+ QCOMPARE(scale.zScale(), qreal(1));
+ QCOMPARE(scale.origin(), QVector3D(10, 10, 0));
+
+ QMatrix4x4 t;
+ scale.applyTo(&t);
+
+ QCOMPARE(t, QMatrix4x4());
+ QCOMPARE(transform2D(scale), QTransform());
+
+ scale.setXScale(10);
+ scale.setOrigin(QVector3D(0, 0, 0));
+
+ QCOMPARE(scale.xScale(), qreal(10));
+ QCOMPARE(scale.yScale(), qreal(1));
+ QCOMPARE(scale.zScale(), qreal(1));
+ QCOMPARE(scale.origin(), QVector3D(0, 0, 0));
+
+ QTransform res;
+ res.scale(10, 1);
+
+ QCOMPARE(transform2D(scale), res);
+ QCOMPARE(transform2D(scale).map(QPointF(10, 10)), QPointF(100, 10));
+
+ scale.setOrigin(QVector3D(10, 10, 0));
+ QCOMPARE(transform2D(scale).map(QPointF(10, 10)), QPointF(10, 10));
+ QCOMPARE(transform2D(scale).map(QPointF(11, 10)), QPointF(20, 10));
+
+ scale.setYScale(2);
+ scale.setZScale(4.5);
+ scale.setOrigin(QVector3D(1, 2, 3));
+
+ QCOMPARE(scale.xScale(), qreal(10));
+ QCOMPARE(scale.yScale(), qreal(2));
+ QCOMPARE(scale.zScale(), qreal(4.5));
+ QCOMPARE(scale.origin(), QVector3D(1, 2, 3));
+
+ QMatrix4x4 t2;
+ scale.applyTo(&t2);
+
+ QCOMPARE(t2.map(QVector3D(4, 5, 6)), QVector3D(31, 8, 16.5));
+
+ // Because the origin has a non-zero z, mapping (4, 5) in 2D
+ // will introduce a projective component into the result.
+ QTransform t3 = t2.toTransform();
+ QCOMPARE(t3.map(QPointF(4, 5)), QPointF(31 / t3.m33(), 8 / t3.m33()));
+}
+
+// QMatrix4x4 uses float internally, whereas QTransform uses qreal.
+// This can lead to issues with qFuzzyCompare() where it uses double
+// precision to compare values that have no more than float precision
+// after conversion from QMatrix4x4 to QTransform. The following
+// definitions correct for the difference.
+static inline bool fuzzyCompare(qreal p1, qreal p2)
+{
+ // increase delta on small machines using float instead of double
+ if (sizeof(qreal) == sizeof(float))
+ return (qAbs(p1 - p2) <= 0.00003f * qMin(qAbs(p1), qAbs(p2)));
+ else
+ return (qAbs(p1 - p2) <= 0.00001f * qMin(qAbs(p1), qAbs(p2)));
+}
+
+static bool fuzzyCompare(const QTransform& t1, const QTransform& t2)
+{
+ return fuzzyCompare(t1.m11(), t2.m11()) &&
+ fuzzyCompare(t1.m12(), t2.m12()) &&
+ fuzzyCompare(t1.m13(), t2.m13()) &&
+ fuzzyCompare(t1.m21(), t2.m21()) &&
+ fuzzyCompare(t1.m22(), t2.m22()) &&
+ fuzzyCompare(t1.m23(), t2.m23()) &&
+ fuzzyCompare(t1.m31(), t2.m31()) &&
+ fuzzyCompare(t1.m32(), t2.m32()) &&
+ fuzzyCompare(t1.m33(), t2.m33());
+}
+
+static inline bool fuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2)
+{
+ bool ok = true;
+ for (int y = 0; y < 4; ++y)
+ for (int x = 0; x < 4; ++x)
+ ok &= fuzzyCompare(m1(y, x), m2(y, x));
+ return ok;
+}
+
+void tst_QGraphicsTransform::rotation()
+{
+ QGraphicsRotation rotation;
+ QCOMPARE(rotation.axis(), QVector3D(0, 0, 1));
+ QCOMPARE(rotation.origin(), QVector3D(0, 0, 0));
+ QCOMPARE(rotation.angle(), (qreal)0);
+
+ rotation.setOrigin(QVector3D(10, 10, 0));
+
+ QCOMPARE(rotation.axis(), QVector3D(0, 0, 1));
+ QCOMPARE(rotation.origin(), QVector3D(10, 10, 0));
+ QCOMPARE(rotation.angle(), (qreal)0);
+
+ QMatrix4x4 t;
+ rotation.applyTo(&t);
+
+ QCOMPARE(t, QMatrix4x4());
+ QCOMPARE(transform2D(rotation), QTransform());
+
+ rotation.setAngle(40);
+ rotation.setOrigin(QVector3D(0, 0, 0));
+
+ QCOMPARE(rotation.axis(), QVector3D(0, 0, 1));
+ QCOMPARE(rotation.origin(), QVector3D(0, 0, 0));
+ QCOMPARE(rotation.angle(), (qreal)40);
+
+ QTransform res;
+ res.rotate(40);
+
+ QVERIFY(fuzzyCompare(transform2D(rotation), res));
+
+ rotation.setOrigin(QVector3D(10, 10, 0));
+ rotation.setAngle(90);
+ QCOMPARE(transform2D(rotation).map(QPointF(10, 10)), QPointF(10, 10));
+ QCOMPARE(transform2D(rotation).map(QPointF(20, 10)), QPointF(10, 20));
+
+ rotation.setOrigin(QVector3D(0, 0, 0));
+ rotation.setAngle(qQNaN());
+ QCOMPARE(transform2D(rotation).map(QPointF(20, 10)), QPointF(20, 10));
+}
+
+Q_DECLARE_METATYPE(Qt::Axis);
+void tst_QGraphicsTransform::rotation3d_data()
+{
+ QTest::addColumn<Qt::Axis>("axis");
+ QTest::addColumn<qreal>("angle");
+
+ for (int angle = 0; angle <= 360; angle++) {
+ QTest::newRow("test rotation on X") << Qt::XAxis << qreal(angle);
+ QTest::newRow("test rotation on Y") << Qt::YAxis << qreal(angle);
+ QTest::newRow("test rotation on Z") << Qt::ZAxis << qreal(angle);
+ }
+}
+
+void tst_QGraphicsTransform::rotation3d()
+{
+ QFETCH(Qt::Axis, axis);
+ QFETCH(qreal, angle);
+
+ QGraphicsRotation rotation;
+ rotation.setAxis(axis);
+
+ QMatrix4x4 t;
+ rotation.applyTo(&t);
+
+ QVERIFY(t.isIdentity());
+ QVERIFY(transform2D(rotation).isIdentity());
+
+ rotation.setAngle(angle);
+
+ // QGraphicsRotation uses a correct mathematical rotation in 3D.
+ // QTransform's Qt::YAxis rotation is inverted from the mathematical
+ // version of rotation. We correct for that here.
+ QTransform expected;
+ if (axis == Qt::YAxis && angle != 180.)
+ expected.rotate(-angle, axis);
+ else
+ expected.rotate(angle, axis);
+
+ QVERIFY(fuzzyCompare(transform2D(rotation), expected));
+
+ // Check that "rotation" produces the 4x4 form of the 3x3 matrix.
+ // i.e. third row and column are 0 0 1 0.
+ t.setToIdentity();
+ rotation.applyTo(&t);
+ QMatrix4x4 r(expected);
+ if (sizeof(qreal) == sizeof(float) && angle == 268) {
+ // This test fails, on only this angle, when qreal == float
+ // because the deg2rad value in QTransform is not accurate
+ // enough to match what QMatrix4x4 is doing.
+ } else {
+ QVERIFY(fuzzyCompare(t, r));
+ }
+
+ //now let's check that a null vector will not change the transform
+ rotation.setAxis(QVector3D(0, 0, 0));
+ rotation.setOrigin(QVector3D(10, 10, 0));
+
+ t.setToIdentity();
+ rotation.applyTo(&t);
+
+ QVERIFY(t.isIdentity());
+ QVERIFY(transform2D(rotation).isIdentity());
+
+ rotation.setAngle(angle);
+
+ QVERIFY(t.isIdentity());
+ QVERIFY(transform2D(rotation).isIdentity());
+
+ rotation.setOrigin(QVector3D(0, 0, 0));
+
+ QVERIFY(t.isIdentity());
+ QVERIFY(transform2D(rotation).isIdentity());
+}
+
+QByteArray labelForTest(QVector3D const& axis, int angle) {
+ return QString("rotation of %1 on (%2, %3, %4)")
+ .arg(angle)
+ .arg(axis.x())
+ .arg(axis.y())
+ .arg(axis.z())
+ .toLatin1();
+}
+
+void tst_QGraphicsTransform::rotation3dArbitraryAxis_data()
+{
+ QTest::addColumn<QVector3D>("axis");
+ QTest::addColumn<qreal>("angle");
+
+ QVector3D axis1 = QVector3D(1.0f, 1.0f, 1.0f);
+ QVector3D axis2 = QVector3D(2.0f, -3.0f, 0.5f);
+ QVector3D axis3 = QVector3D(-2.0f, 0.0f, -0.5f);
+ QVector3D axis4 = QVector3D(0.0001f, 0.0001f, 0.0001f);
+ QVector3D axis5 = QVector3D(0.01f, 0.01f, 0.01f);
+
+ for (int angle = 0; angle <= 360; angle++) {
+ QTest::newRow(labelForTest(axis1, angle).constData()) << axis1 << qreal(angle);
+ QTest::newRow(labelForTest(axis2, angle).constData()) << axis2 << qreal(angle);
+ QTest::newRow(labelForTest(axis3, angle).constData()) << axis3 << qreal(angle);
+ QTest::newRow(labelForTest(axis4, angle).constData()) << axis4 << qreal(angle);
+ QTest::newRow(labelForTest(axis5, angle).constData()) << axis5 << qreal(angle);
+ }
+}
+
+void tst_QGraphicsTransform::rotation3dArbitraryAxis()
+{
+ QFETCH(QVector3D, axis);
+ QFETCH(qreal, angle);
+
+ QGraphicsRotation rotation;
+ rotation.setAxis(axis);
+
+ QMatrix4x4 t;
+ rotation.applyTo(&t);
+
+ QVERIFY(t.isIdentity());
+ QVERIFY(transform2D(rotation).isIdentity());
+
+ rotation.setAngle(angle);
+
+ // Compute the expected answer using QMatrix4x4 and a projection.
+ // These two steps are performed in one hit by QGraphicsRotation.
+ QMatrix4x4 exp;
+ exp.rotate(angle, axis);
+ QTransform expected = exp.toTransform(1024.0f);
+
+#if defined(MAY_HIT_QTBUG_20661)
+ // These failures possibly relate to the float vs qreal issue mentioned
+ // in the comment above fuzzyCompare().
+ if (sizeof(qreal) == sizeof(double)) {
+ QEXPECT_FAIL("rotation of 120 on (1, 1, 1)", "QTBUG-20661", Abort);
+ QEXPECT_FAIL("rotation of 240 on (1, 1, 1)", "QTBUG-20661", Abort);
+ QEXPECT_FAIL("rotation of 120 on (0.01, 0.01, 0.01)", "QTBUG-20661", Abort);
+ QEXPECT_FAIL("rotation of 240 on (0.01, 0.01, 0.01)", "QTBUG-20661", Abort);
+ QEXPECT_FAIL("rotation of 120 on (0.0001, 0.0001, 0.0001)", "QTBUG-20661", Abort);
+ QEXPECT_FAIL("rotation of 240 on (0.0001, 0.0001, 0.0001)", "QTBUG-20661", Abort);
+ }
+#endif
+
+ QTransform actual = transform2D(rotation);
+ QVERIFY2(fuzzyCompare(actual, expected), qPrintable(
+ QString("\nactual: %1\n"
+ "expected: %2")
+ .arg(toString(actual))
+ .arg(toString(expected))
+ ));
+
+ // Check that "rotation" produces the 4x4 form of the 3x3 matrix.
+ // i.e. third row and column are 0 0 1 0.
+ t.setToIdentity();
+ rotation.applyTo(&t);
+ QMatrix4x4 r(expected);
+ QVERIFY(qFuzzyCompare(t, r));
+}
+
+QString tst_QGraphicsTransform::toString(QTransform const& t)
+{
+ return QString("[ [ %1 %2 %3 ]; [ %4 %5 %6 ]; [ %7 %8 %9 ] ]")
+ .arg(t.m11())
+ .arg(t.m12())
+ .arg(t.m13())
+ .arg(t.m21())
+ .arg(t.m22())
+ .arg(t.m23())
+ .arg(t.m31())
+ .arg(t.m32())
+ .arg(t.m33())
+ ;
+}
+
+
+QTEST_MAIN(tst_QGraphicsTransform)
+#include "tst_qgraphicstransform.moc"
+
diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/.gitignore b/tests/auto/widgets/graphicsview/qgraphicsview/.gitignore
new file mode 100644
index 0000000000..c8182c9e0d
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsview/.gitignore
@@ -0,0 +1 @@
+tst_qgraphicsview
diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/qgraphicsview.pro b/tests/auto/widgets/graphicsview/qgraphicsview/qgraphicsview.pro
new file mode 100644
index 0000000000..9f32522546
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsview/qgraphicsview.pro
@@ -0,0 +1,9 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+QT += core-private gui-private
+
+SOURCES += tst_qgraphicsview.cpp tst_qgraphicsview_2.cpp
+DEFINES += QT_NO_CAST_TO_ASCII
+
+contains(QT_CONFIG,xcb):qpa:CONFIG+=insignificant_test # QTBUG-20756 crashes on qpa, xcb
diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
new file mode 100644
index 0000000000..0a404cab46
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
@@ -0,0 +1,4558 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.1, 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <qgraphicsitem.h>
+#include <qgraphicsscene.h>
+#include <qgraphicssceneevent.h>
+#include <qgraphicsview.h>
+#include <qgraphicswidget.h>
+#include <qgraphicsproxywidget.h>
+
+#include <math.h>
+
+#include <QtWidgets/QLabel>
+#if !defined(QT_NO_STYLE_MOTIF)
+#include <QtWidgets/QMotifStyle>
+#endif
+#if !defined(QT_NO_STYLE_WINDOWS)
+#include <QtWidgets/QWindowsStyle>
+#endif
+#if !defined(QT_NO_STYLE_PLASTIQUE)
+#include <QtWidgets/QPlastiqueStyle>
+#endif
+#include <QtGui/QPainterPath>
+#include <QtWidgets/QRubberBand>
+#include <QtWidgets/QScrollBar>
+#include <QtWidgets/QStyleOption>
+#include <QtWidgets/QBoxLayout>
+#include <QtWidgets/QStyle>
+#include <QtWidgets/QPushButton>
+#include <QtWidgets/QInputContext>
+#include <QtWidgets/QDesktopWidget>
+#include <private/qgraphicsview_p.h>
+#include "../../../platformquirks.h"
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+Q_DECLARE_METATYPE(QList<int>)
+Q_DECLARE_METATYPE(QList<QRectF>)
+Q_DECLARE_METATYPE(QMatrix)
+Q_DECLARE_METATYPE(QPainterPath)
+Q_DECLARE_METATYPE(QPointF)
+Q_DECLARE_METATYPE(QPolygonF)
+Q_DECLARE_METATYPE(QRectF)
+Q_DECLARE_METATYPE(Qt::ScrollBarPolicy)
+
+#ifdef Q_WS_MAC
+//On mac we get full update. So check that the expected region is contained inside the actual
+#define COMPARE_REGIONS(ACTUAL, EXPECTED) QVERIFY((EXPECTED).subtracted(ACTUAL).isEmpty())
+#else
+#define COMPARE_REGIONS QCOMPARE
+#endif
+
+static void sendMousePress(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::LeftButton)
+{
+ QMouseEvent event(QEvent::MouseButtonPress, point, widget->mapToGlobal(point), button, 0, 0);
+ QApplication::sendEvent(widget, &event);
+}
+
+static void sendMouseMove(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::NoButton, Qt::MouseButtons buttons = 0)
+{
+ QTest::mouseMove(widget, point);
+ QMouseEvent event(QEvent::MouseMove, point, button, buttons, 0);
+ QApplication::sendEvent(widget, &event);
+ QApplication::processEvents();
+}
+
+static void sendMouseRelease(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::LeftButton)
+{
+ QMouseEvent event(QEvent::MouseButtonRelease, point, widget->mapToGlobal(point), button, 0, 0);
+ QApplication::sendEvent(widget, &event);
+}
+
+class EventSpy : public QObject
+{
+ Q_OBJECT
+public:
+ EventSpy(QObject *watched, QEvent::Type type)
+ : _count(0), spied(type)
+ {
+ watched->installEventFilter(this);
+ }
+
+ int count() const { return _count; }
+ void reset() { _count = 0; }
+
+protected:
+ bool eventFilter(QObject *watched, QEvent *event)
+ {
+ Q_UNUSED(watched);
+ if (event->type() == spied)
+ ++_count;
+ return false;
+ }
+
+ int _count;
+ QEvent::Type spied;
+};
+
+class tst_QGraphicsView : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+ void construction();
+ void renderHints();
+ void alignment();
+ void interactive();
+ void scene();
+ void setScene();
+ void deleteScene();
+ void sceneRect();
+ void sceneRect_growing();
+ void setSceneRect();
+ void viewport();
+ void dragMode_scrollHand();
+ void dragMode_rubberBand();
+ void rubberBandSelectionMode();
+ void backgroundBrush();
+ void foregroundBrush();
+ void matrix();
+ void matrix_convenience();
+ void matrix_combine();
+ void centerOnPoint();
+ void centerOnItem();
+ void ensureVisibleRect();
+ void fitInView();
+ void itemsAtPoint();
+ void itemsInRect();
+ void itemsInRect_cosmeticAdjust_data();
+ void itemsInRect_cosmeticAdjust();
+ void itemsInPoly();
+ void itemsInPath();
+ void itemAt();
+ void itemAt2();
+ void mapToScene();
+ void mapToScenePoint();
+ void mapToSceneRect_data();
+ void mapToSceneRect();
+ void mapToScenePoly();
+ void mapToScenePath();
+ void mapFromScenePoint();
+ void mapFromSceneRect();
+ void mapFromScenePoly();
+ void mapFromScenePath();
+ void sendEvent();
+ void wheelEvent();
+#if !defined(QT_NO_CURSOR) && !defined(Q_OS_WINCE)
+ void cursor();
+ void cursor2();
+#endif
+ void transformationAnchor();
+ void resizeAnchor();
+ void viewportUpdateMode();
+ void viewportUpdateMode2();
+#ifndef QT_NO_DRAGANDDROP
+ void acceptDrops();
+#endif
+ void optimizationFlags();
+ void optimizationFlags_dontSavePainterState();
+ void optimizationFlags_dontSavePainterState2_data();
+ void optimizationFlags_dontSavePainterState2();
+ void levelOfDetail_data();
+ void levelOfDetail();
+ void scrollBarRanges_data();
+ void scrollBarRanges();
+ void acceptMousePressEvent();
+ void replayMouseMove();
+ void itemsUnderMouse();
+ void embeddedViews();
+ void scrollAfterResize_data();
+ void scrollAfterResize();
+ void moveItemWhileScrolling_data();
+ void moveItemWhileScrolling();
+ void centerOnDirtyItem();
+ void mouseTracking();
+ void mouseTracking2();
+ void mouseTracking3();
+ void render();
+ void exposeRegion();
+ void update_data();
+ void update();
+ void update2_data();
+ void update2();
+ void update_ancestorClipsChildrenToShape();
+ void update_ancestorClipsChildrenToShape2();
+ void inputMethodSensitivity();
+ void inputContextReset();
+ void indirectPainting();
+ void compositionModeInDrawBackground();
+
+ // task specific tests below me
+ void task172231_untransformableItems();
+ void task180429_mouseReleaseDragMode();
+ void task187791_setSceneCausesUpdate();
+ void task186827_deleteReplayedItem();
+ void task207546_focusCrash();
+ void task210599_unsetDragWhileDragging();
+ void task236394_sendShortcutOverrideEvent();
+ void task239729_noViewUpdate_data();
+ void task239729_noViewUpdate();
+ void task239047_fitInViewSmallViewport();
+ void task245469_itemsAtPointWithClip();
+ void task253415_reconnectUpdateSceneOnSceneChanged();
+#ifndef Q_OS_WINCE
+ void task255529_transformationAnchorMouseAndViewportMargins();
+#endif
+ void task259503_scrollingArtifacts();
+ void QTBUG_4151_clipAndIgnore_data();
+ void QTBUG_4151_clipAndIgnore();
+ void QTBUG_5859_exposedRect();
+#if !defined(QT_NO_CURSOR) && !defined(Q_OS_WINCE)
+ void QTBUG_7438_cursor();
+#endif
+ void hoverLeave();
+ void QTBUG_16063_microFocusRect();
+
+public slots:
+ void dummySlot() {}
+};
+
+void tst_QGraphicsView::initTestCase()
+{
+#ifdef Q_OS_WINCE_WM
+ qApp->setAutoMaximizeThreshold(-1);
+#endif
+}
+
+void tst_QGraphicsView::construction()
+{
+ QGraphicsView view;
+ QCOMPARE(view.renderHints(), QPainter::TextAntialiasing);
+ QCOMPARE(view.dragMode(), QGraphicsView::NoDrag);
+ QVERIFY(view.isInteractive());
+ QVERIFY(!view.scene());
+ QCOMPARE(view.sceneRect(), QRectF());
+ QVERIFY(view.viewport());
+ QCOMPARE(view.viewport()->metaObject()->className(), "QWidget");
+ QCOMPARE(view.matrix(), QMatrix());
+ QVERIFY(view.items().isEmpty());
+ QVERIFY(view.items(QPoint()).isEmpty());
+ QVERIFY(view.items(QRect()).isEmpty());
+ QVERIFY(view.items(QPolygon()).isEmpty());
+ QVERIFY(view.items(QPainterPath()).isEmpty());
+ QVERIFY(!view.itemAt(QPoint()));
+ QCOMPARE(view.mapToScene(QPoint()), QPointF());
+ QCOMPARE(view.mapToScene(QRect()), QPolygonF());
+ QCOMPARE(view.mapToScene(QPolygon()), QPolygonF());
+ QCOMPARE(view.mapFromScene(QPointF()), QPoint());
+ QPolygon poly;
+ poly << QPoint() << QPoint() << QPoint() << QPoint();
+ QCOMPARE(view.mapFromScene(QRectF()), poly);
+ QCOMPARE(view.mapFromScene(QPolygonF()), QPolygon());
+ QCOMPARE(view.transformationAnchor(), QGraphicsView::AnchorViewCenter);
+ QCOMPARE(view.resizeAnchor(), QGraphicsView::NoAnchor);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+}
+
+class TestItem : public QGraphicsItem
+{
+public:
+ QRectF boundingRect() const
+ { return QRectF(-10, -10, 20, 20); }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ { hints = painter->renderHints(); painter->drawRect(boundingRect()); }
+
+ bool sceneEvent(QEvent *event)
+ {
+ events << event->type();
+ return QGraphicsItem::sceneEvent(event);
+ }
+
+ QList<QEvent::Type> events;
+ QPainter::RenderHints hints;
+};
+
+void tst_QGraphicsView::renderHints()
+{
+ QGraphicsView view;
+ QCOMPARE(view.renderHints(), QPainter::TextAntialiasing);
+ view.setRenderHint(QPainter::TextAntialiasing, false);
+ QCOMPARE(view.renderHints(), 0);
+ view.setRenderHint(QPainter::Antialiasing, false);
+ QCOMPARE(view.renderHints(), 0);
+ view.setRenderHint(QPainter::TextAntialiasing, true);
+ QCOMPARE(view.renderHints(), QPainter::TextAntialiasing);
+ view.setRenderHint(QPainter::Antialiasing);
+ QCOMPARE(view.renderHints(), QPainter::TextAntialiasing | QPainter::Antialiasing);
+ view.setRenderHints(0);
+ QCOMPARE(view.renderHints(), 0);
+
+ TestItem *item = new TestItem;
+ QGraphicsScene scene;
+ scene.addItem(item);
+
+ view.setScene(&scene);
+
+ view.setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing | QPainter::NonCosmeticDefaultPen);
+ QCOMPARE(view.renderHints(), QPainter::TextAntialiasing | QPainter::Antialiasing | QPainter::NonCosmeticDefaultPen);
+
+ QCOMPARE(item->hints, 0);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ view.repaint();
+ QTRY_COMPARE(item->hints, view.renderHints());
+
+ view.setRenderHints(QPainter::Antialiasing | QPainter::NonCosmeticDefaultPen);
+ QCOMPARE(view.renderHints(), QPainter::Antialiasing | QPainter::NonCosmeticDefaultPen);
+
+ view.repaint();
+ QTRY_COMPARE(item->hints, view.renderHints());
+}
+
+void tst_QGraphicsView::alignment()
+{
+ QGraphicsScene scene;
+ scene.addRect(QRectF(-10, -10, 20, 20));
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ for (int i = 0; i < 3; ++i) {
+ for (int j = 0; j < 3; ++j) {
+ Qt::Alignment alignment = 0;
+ switch (i) {
+ case 0:
+ alignment |= Qt::AlignLeft;
+ break;
+ case 1:
+ alignment |= Qt::AlignHCenter;
+ break;
+ case 2:
+ default:
+ alignment |= Qt::AlignRight;
+ break;
+ }
+ switch (j) {
+ case 0:
+ alignment |= Qt::AlignTop;
+ break;
+ case 1:
+ alignment |= Qt::AlignVCenter;
+ break;
+ case 2:
+ default:
+ alignment |= Qt::AlignBottom;
+ break;
+ }
+ view.setAlignment(alignment);
+ QCOMPARE(view.alignment(), alignment);
+
+ for (int k = 0; k < 3; ++k) {
+ view.resize(100 + k * 25, 100 + k * 25);
+ QApplication::processEvents();
+ }
+ }
+ }
+}
+
+void tst_QGraphicsView::interactive()
+{
+ TestItem *item = new TestItem;
+ item->setFlags(QGraphicsItem::ItemIsMovable);
+ QCOMPARE(item->events.size(), 0);
+
+ QGraphicsScene scene(-200, -200, 400, 400);
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+ if (PlatformQuirks::isAutoMaximizing())
+ view.setWindowFlags(view.windowFlags()|Qt::X11BypassWindowManagerHint);
+ view.setFixedSize(300, 300);
+ QCOMPARE(item->events.size(), 0);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ view.activateWindow();
+
+ QApplication::processEvents();
+ QTRY_COMPARE(item->events.size(), 1); // activate
+
+ QPoint itemPoint = view.mapFromScene(item->scenePos());
+
+ QVERIFY(view.itemAt(itemPoint));
+
+ for (int i = 0; i < 100; ++i) {
+ sendMousePress(view.viewport(), itemPoint);
+ QCOMPARE(item->events.size(), i * 5 + 3);
+ QCOMPARE(item->events.at(item->events.size() - 2), QEvent::GrabMouse);
+ QCOMPARE(item->events.at(item->events.size() - 1), QEvent::GraphicsSceneMousePress);
+ sendMouseRelease(view.viewport(), itemPoint);
+ QCOMPARE(item->events.size(), i * 5 + 5);
+ QCOMPARE(item->events.at(item->events.size() - 2), QEvent::GraphicsSceneMouseRelease);
+ QCOMPARE(item->events.at(item->events.size() - 1), QEvent::UngrabMouse);
+ QContextMenuEvent contextEvent(QContextMenuEvent::Mouse, itemPoint, view.mapToGlobal(itemPoint));
+ QApplication::sendEvent(view.viewport(), &contextEvent);
+ QCOMPARE(item->events.size(), i * 5 + 6);
+ QCOMPARE(item->events.last(), QEvent::GraphicsSceneContextMenu);
+ }
+
+ view.setInteractive(false);
+
+ for (int i = 0; i < 100; ++i) {
+ sendMousePress(view.viewport(), itemPoint);
+ QCOMPARE(item->events.size(), 501);
+ QCOMPARE(item->events.last(), QEvent::GraphicsSceneContextMenu);
+ sendMouseRelease(view.viewport(), itemPoint);
+ QCOMPARE(item->events.size(), 501);
+ QCOMPARE(item->events.last(), QEvent::GraphicsSceneContextMenu);
+ QContextMenuEvent contextEvent(QContextMenuEvent::Mouse, itemPoint, view.mapToGlobal(itemPoint));
+ QApplication::sendEvent(view.viewport(), &contextEvent);
+ QCOMPARE(item->events.size(), 501);
+ QCOMPARE(item->events.last(), QEvent::GraphicsSceneContextMenu);
+ }
+}
+
+void tst_QGraphicsView::scene()
+{
+ QGraphicsView view;
+ QVERIFY(!view.scene());
+ view.setScene(0);
+ QVERIFY(!view.scene());
+
+ {
+ QGraphicsScene scene;
+ view.setScene(&scene);
+ QCOMPARE(view.scene(), &scene);
+ }
+
+ QCOMPARE(view.scene(), (QGraphicsScene *)0);
+}
+
+void tst_QGraphicsView::setScene()
+{
+ QGraphicsScene scene(-1000, -1000, 2000, 2000);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QCOMPARE(view.sceneRect(), scene.sceneRect());
+
+ QVERIFY(view.horizontalScrollBar()->isVisible());
+ QVERIFY(view.verticalScrollBar()->isVisible());
+ QVERIFY(!view.horizontalScrollBar()->isHidden());
+ QVERIFY(!view.verticalScrollBar()->isHidden());
+
+ view.setScene(0);
+
+ QTest::qWait(25);
+
+ QVERIFY(!view.horizontalScrollBar()->isVisible());
+ QVERIFY(!view.verticalScrollBar()->isVisible());
+ QVERIFY(!view.horizontalScrollBar()->isHidden());
+ QVERIFY(!view.verticalScrollBar()->isHidden());
+
+ QCOMPARE(view.sceneRect(), QRectF());
+}
+
+void tst_QGraphicsView::deleteScene()
+{
+ QGraphicsScene *scene = new QGraphicsScene;
+ QGraphicsView view1(scene);
+ view1.show();
+ QGraphicsView view2(scene);
+ view2.show();
+ QGraphicsView view3(scene);
+ view3.show();
+ delete scene;
+ QCOMPARE(view1.scene(), (QGraphicsScene *)0);
+ QCOMPARE(view2.scene(), (QGraphicsScene *)0);
+ QCOMPARE(view3.scene(), (QGraphicsScene *)0);
+}
+
+void tst_QGraphicsView::sceneRect()
+{
+ QGraphicsView view;
+ QCOMPARE(view.sceneRect(), QRectF());
+
+ view.setSceneRect(QRectF(-100, -100, 200, 200));
+ QCOMPARE(view.sceneRect(), QRectF(-100, -100, 200, 200));
+ view.setSceneRect(-100, -100, 200, 200);
+ QCOMPARE(view.sceneRect(), QRectF(-100, -100, 200, 200));
+
+ view.setSceneRect(QRectF());
+ QCOMPARE(view.sceneRect(), QRectF());
+ QGraphicsScene scene;
+ QGraphicsRectItem *item = scene.addRect(QRectF(-100, -100, 100, 100));
+
+ view.setScene(&scene);
+
+ QCOMPARE(view.sceneRect(), QRectF(-100, -100, 100, 100));
+ item->moveBy(-100, -100);
+ QCOMPARE(view.sceneRect(), QRectF(-200, -200, 200, 200));
+ item->moveBy(100, 100);
+ QCOMPARE(view.sceneRect(), QRectF(-200, -200, 200, 200));
+
+ view.setScene(0);
+ view.setSceneRect(QRectF());
+ QCOMPARE(view.sceneRect(), QRectF());
+}
+
+void tst_QGraphicsView::sceneRect_growing()
+{
+ QWidget toplevel;
+
+ QGraphicsScene scene;
+ for (int i = 0; i < 100; ++i)
+ scene.addText(QString("(0, %1)").arg((i - 50) * 20))->setPos(0, (i - 50) * 20);
+
+ QGraphicsView view(&scene, &toplevel);
+ view.setFixedSize(200, 200);
+ toplevel.show();
+
+ int size = 200;
+ scene.setSceneRect(-size, -size, size * 2, size * 2);
+ QCOMPARE(view.sceneRect(), scene.sceneRect());
+
+ QTest::qWait(25);
+
+ QPointF topLeft = view.mapToScene(0, 0);
+
+ for (int i = 0; i < 5; ++i) {
+ size *= 2;
+ scene.setSceneRect(-size, -size, size * 2, size * 2);
+
+ QApplication::processEvents();
+
+ QCOMPARE(view.sceneRect(), scene.sceneRect());
+ QCOMPARE(view.mapToScene(0, 0), topLeft);
+ view.setSceneRect(-size, -size, size * 2, size * 2);
+ QCOMPARE(view.mapToScene(0, 0), topLeft);
+ view.setSceneRect(QRectF());
+ }
+}
+
+void tst_QGraphicsView::setSceneRect()
+{
+ QRectF rect1(-100, -100, 200, 200);
+ QRectF rect2(-300, -300, 150, 150);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ scene.setSceneRect(rect1);
+ QCOMPARE(scene.sceneRect(), rect1);
+ QCOMPARE(view.sceneRect(), rect1);
+
+ scene.setSceneRect(rect2);
+ QCOMPARE(scene.sceneRect(), rect2);
+ QCOMPARE(view.sceneRect(), rect2);
+
+ view.setSceneRect(rect1);
+ QCOMPARE(scene.sceneRect(), rect2);
+ QCOMPARE(view.sceneRect(), rect1);
+
+ view.setSceneRect(rect2);
+ QCOMPARE(scene.sceneRect(), rect2);
+ QCOMPARE(view.sceneRect(), rect2);
+
+ scene.setSceneRect(rect1);
+ QCOMPARE(scene.sceneRect(), rect1);
+ QCOMPARE(view.sceneRect(), rect2);
+
+ // extreme transformations will max out the scrollbars' ranges.
+ view.setSceneRect(-2000000, -2000000, 4000000, 4000000);
+ view.scale(9000, 9000);
+ QCOMPARE(view.horizontalScrollBar()->minimum(), INT_MIN);
+ QCOMPARE(view.horizontalScrollBar()->maximum(), INT_MAX);
+ QCOMPARE(view.verticalScrollBar()->minimum(), INT_MIN);
+ QCOMPARE(view.verticalScrollBar()->maximum(), INT_MAX);
+}
+
+void tst_QGraphicsView::viewport()
+{
+ QGraphicsScene scene;
+ scene.addText("GraphicsView");
+
+ QGraphicsView view(&scene);
+ QVERIFY(view.viewport() != 0);
+
+ view.show();
+ QTest::qWait(25);
+
+ QPointer<QWidget> widget = new QWidget;
+ view.setViewport(widget);
+ QCOMPARE(view.viewport(), (QWidget *)widget);
+
+ view.show();
+ QTest::qWait(25);
+
+ view.setViewport(0);
+ QVERIFY(widget.isNull());
+ QVERIFY(view.viewport() != 0);
+ QVERIFY(view.viewport() != widget);
+
+ view.show();
+ QTest::qWait(25);
+}
+
+void tst_QGraphicsView::dragMode_scrollHand()
+{
+ for (int j = 0; j < 2; ++j) {
+ QGraphicsView view;
+ QCOMPARE(view.dragMode(), QGraphicsView::NoDrag);
+
+ view.setSceneRect(-1000, -1000, 2000, 2000);
+ view.setFixedSize(100, 100);
+ view.show();
+
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
+
+ view.setInteractive(j ? false : true);
+
+ QGraphicsScene scene;
+ scene.addRect(QRectF(-100, -100, 5, 5));
+ scene.addRect(QRectF(95, -100, 5, 5));
+ scene.addRect(QRectF(95, 95, 5, 5));
+ QGraphicsItem *item = scene.addRect(QRectF(-100, 95, 5, 5));
+ item->setFlag(QGraphicsItem::ItemIsSelectable);
+ item->setSelected(true);
+ QVERIFY(item->isSelected());
+ QVERIFY(!view.scene());
+
+ view.setDragMode(QGraphicsView::ScrollHandDrag);
+
+ for (int i = 0; i < 2; ++i) {
+ // ScrollHandDrag
+#ifndef QT_NO_CURSOR
+ Qt::CursorShape cursorShape = view.viewport()->cursor().shape();
+#endif
+ int horizontalScrollBarValue = view.horizontalScrollBar()->value();
+ int verticalScrollBarValue = view.verticalScrollBar()->value();
+ {
+ // Press
+ QMouseEvent event(QEvent::MouseButtonPress,
+ view.viewport()->rect().center(),
+ Qt::LeftButton, Qt::LeftButton, 0);
+ event.setAccepted(true);
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(event.isAccepted());
+ }
+ QApplication::processEvents();
+
+ QTRY_VERIFY(item->isSelected());
+
+ for (int k = 0; k < 4; ++k) {
+#ifndef QT_NO_CURSOR
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::ClosedHandCursor);
+#endif
+ {
+ // Move
+ QMouseEvent event(QEvent::MouseMove,
+ view.viewport()->rect().center() + QPoint(10, 0),
+ Qt::LeftButton, Qt::LeftButton, 0);
+ event.setAccepted(true);
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(event.isAccepted());
+ }
+ QVERIFY(item->isSelected());
+ QCOMPARE(view.horizontalScrollBar()->value(), horizontalScrollBarValue - 10);
+ QCOMPARE(view.verticalScrollBar()->value(), verticalScrollBarValue);
+ {
+ // Move
+ QMouseEvent event(QEvent::MouseMove,
+ view.viewport()->rect().center() + QPoint(10, 10),
+ Qt::LeftButton, Qt::LeftButton, 0);
+ event.setAccepted(true);
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(event.isAccepted());
+ }
+ QVERIFY(item->isSelected());
+ QCOMPARE(view.horizontalScrollBar()->value(), horizontalScrollBarValue - 10);
+ QCOMPARE(view.verticalScrollBar()->value(), verticalScrollBarValue - 10);
+ }
+
+ {
+ // Release
+ QMouseEvent event(QEvent::MouseButtonRelease,
+ view.viewport()->rect().center() + QPoint(10, 10),
+ Qt::LeftButton, Qt::LeftButton, 0);
+ event.setAccepted(true);
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(event.isAccepted());
+ }
+ QApplication::processEvents();
+
+ QTRY_VERIFY(item->isSelected());
+ QCOMPARE(view.horizontalScrollBar()->value(), horizontalScrollBarValue - 10);
+ QCOMPARE(view.verticalScrollBar()->value(), verticalScrollBarValue - 10);
+#ifndef QT_NO_CURSOR
+ QCOMPARE(view.viewport()->cursor().shape(), cursorShape);
+#endif
+
+ // Check that items are not unselected because of a scroll hand drag.
+ QVERIFY(item->isSelected());
+
+ // Check that a click will still unselect the item.
+ {
+ // Press
+ QMouseEvent event(QEvent::MouseButtonPress,
+ view.viewport()->rect().center() + QPoint(10, 10),
+ Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &event);
+ }
+ {
+ // Release
+ QMouseEvent event(QEvent::MouseButtonRelease,
+ view.viewport()->rect().center() + QPoint(10, 10),
+ Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &event);
+ }
+
+ if (view.isInteractive()) {
+ if (view.scene()) {
+ QVERIFY(!item->isSelected());
+ item->setSelected(true);
+ } else {
+ QVERIFY(item->isSelected());
+ }
+ } else {
+ QVERIFY(item->isSelected());
+ }
+
+ view.setScene(&scene);
+ }
+ }
+}
+
+void tst_QGraphicsView::dragMode_rubberBand()
+{
+ QGraphicsView view;
+ QCOMPARE(view.dragMode(), QGraphicsView::NoDrag);
+
+ view.setSceneRect(-1000, -1000, 2000, 2000);
+ view.show();
+
+ QGraphicsScene scene;
+ scene.addRect(QRectF(-100, -100, 25, 25))->setFlag(QGraphicsItem::ItemIsSelectable);
+ scene.addRect(QRectF(75, -100, 25, 25))->setFlag(QGraphicsItem::ItemIsSelectable);
+ scene.addRect(QRectF(75, 75, 25, 25))->setFlag(QGraphicsItem::ItemIsSelectable);
+ scene.addRect(QRectF(-100, 75, 25, 25))->setFlag(QGraphicsItem::ItemIsSelectable);
+
+ view.setDragMode(QGraphicsView::RubberBandDrag);
+
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
+
+ for (int i = 0; i < 2; ++i) {
+ // RubberBandDrag
+#ifndef QT_NO_CURSOR
+ Qt::CursorShape cursorShape = view.viewport()->cursor().shape();
+#endif
+ int horizontalScrollBarValue = view.horizontalScrollBar()->value();
+ int verticalScrollBarValue = view.verticalScrollBar()->value();
+ {
+ // Press
+ QMouseEvent event(QEvent::MouseButtonPress,
+ view.viewport()->rect().center(),
+ Qt::LeftButton, Qt::LeftButton, 0);
+ event.setAccepted(true);
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(event.isAccepted());
+ }
+#ifndef QT_NO_CURSOR
+ QCOMPARE(view.viewport()->cursor().shape(), cursorShape);
+#endif
+
+ QApplication::processEvents();
+
+ {
+ // Move
+ QMouseEvent event(QEvent::MouseMove,
+ view.viewport()->rect().center() + QPoint(100, 0),
+ Qt::LeftButton, Qt::LeftButton, 0);
+ event.setAccepted(true);
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(event.isAccepted());
+ }
+ QCOMPARE(view.horizontalScrollBar()->value(), horizontalScrollBarValue);
+ QCOMPARE(view.verticalScrollBar()->value(), verticalScrollBarValue);
+
+ // We don't use QRubberBand as of 4.3; the band is drawn internally.
+ QVERIFY(!qFindChild<QRubberBand *>(&view));
+
+ QTest::qWait(25);
+
+ {
+ // Move
+ QMouseEvent event(QEvent::MouseMove,
+ view.viewport()->rect().center() + QPoint(100, 100),
+ Qt::LeftButton, Qt::LeftButton, 0);
+ event.setAccepted(true);
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(event.isAccepted());
+ }
+ QCOMPARE(view.horizontalScrollBar()->value(), horizontalScrollBarValue);
+ QCOMPARE(view.verticalScrollBar()->value(), verticalScrollBarValue);
+
+ QTest::qWait(25);
+
+ {
+ // Release
+ QMouseEvent event(QEvent::MouseButtonRelease,
+ view.viewport()->rect().center() + QPoint(100, 100),
+ Qt::LeftButton, Qt::LeftButton, 0);
+ event.setAccepted(true);
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(event.isAccepted());
+ }
+ QCOMPARE(view.horizontalScrollBar()->value(), horizontalScrollBarValue);
+ QCOMPARE(view.verticalScrollBar()->value(), verticalScrollBarValue);
+#ifndef QT_NO_CURSOR
+ QCOMPARE(view.viewport()->cursor().shape(), cursorShape);
+#endif
+
+ QTest::qWait(25);
+
+ if (view.scene())
+ QCOMPARE(scene.selectedItems().size(), 1);
+
+ view.setScene(&scene);
+ view.centerOn(0, 0);
+ }
+}
+
+void tst_QGraphicsView::rubberBandSelectionMode()
+{
+ QWidget toplevel;
+
+ QGraphicsScene scene;
+ QGraphicsRectItem *rect = scene.addRect(QRectF(10, 10, 80, 80));
+ rect->setFlag(QGraphicsItem::ItemIsSelectable);
+
+ QGraphicsView view(&scene, &toplevel);
+ QCOMPARE(view.rubberBandSelectionMode(), Qt::IntersectsItemShape);
+ view.setDragMode(QGraphicsView::RubberBandDrag);
+ view.resize(120, 120);
+ toplevel.show();
+
+ // Disable mouse tracking to prevent the window system from sending mouse
+ // move events to the viewport while we are synthesizing events. If
+ // QGraphicsView gets a mouse move event with no buttons down, it'll
+ // terminate the rubber band.
+ view.viewport()->setMouseTracking(false);
+
+ QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>());
+ sendMousePress(view.viewport(), QPoint(), Qt::LeftButton);
+ sendMouseMove(view.viewport(), view.viewport()->rect().center(),
+ Qt::LeftButton, Qt::LeftButton);
+ QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>() << rect);
+ sendMouseRelease(view.viewport(), QPoint(), Qt::LeftButton);
+
+ view.setRubberBandSelectionMode(Qt::ContainsItemShape);
+ QCOMPARE(view.rubberBandSelectionMode(), Qt::ContainsItemShape);
+ sendMousePress(view.viewport(), QPoint(), Qt::LeftButton);
+ QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>());
+ sendMouseMove(view.viewport(), view.viewport()->rect().center(),
+ Qt::LeftButton, Qt::LeftButton);
+ QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>());
+ sendMouseMove(view.viewport(), view.viewport()->rect().bottomRight(),
+ Qt::LeftButton, Qt::LeftButton);
+ QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>() << rect);
+}
+
+void tst_QGraphicsView::backgroundBrush()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ scene.setBackgroundBrush(Qt::blue);
+ QCOMPARE(scene.backgroundBrush(), QBrush(Qt::blue));
+
+ view.show();
+ QTest::qWait(25);
+
+ scene.setBackgroundBrush(QBrush());
+ QCOMPARE(scene.backgroundBrush(), QBrush());
+ QTest::qWait(25);
+
+ QRadialGradient gradient(0, 0, 10);
+ gradient.setSpread(QGradient::RepeatSpread);
+ scene.setBackgroundBrush(gradient);
+
+ QCOMPARE(scene.backgroundBrush(), QBrush(gradient));
+ QTest::qWait(25);
+}
+
+void tst_QGraphicsView::foregroundBrush()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ scene.setForegroundBrush(Qt::blue);
+ QCOMPARE(scene.foregroundBrush(), QBrush(Qt::blue));
+
+ view.show();
+ QTest::qWait(25);
+
+ scene.setForegroundBrush(QBrush());
+ QCOMPARE(scene.foregroundBrush(), QBrush());
+ QTest::qWait(25);
+
+ QRadialGradient gradient(0, 0, 10);
+ gradient.setSpread(QGradient::RepeatSpread);
+ scene.setForegroundBrush(gradient);
+
+ QCOMPARE(scene.foregroundBrush(), QBrush(gradient));
+ QTest::qWait(25);
+
+ for (int i = 0; i < 50; ++i) {
+ QRadialGradient gradient(view.rect().center() + QPoint(int(sin(i / 2.0) * 10), int(cos(i / 2.0) * 10)), 10);
+ gradient.setColorAt(0, Qt::transparent);
+ gradient.setColorAt(0.5, Qt::black);
+ gradient.setColorAt(1, Qt::transparent);
+ gradient.setSpread(QGradient::RepeatSpread);
+ scene.setForegroundBrush(gradient);
+
+ QRadialGradient gradient2(view.rect().center() + QPoint(int(sin(i / 1.7) * 10), int(cos(i / 1.7) * 10)), 10);
+ gradient2.setColorAt(0, Qt::transparent);
+ gradient2.setColorAt(0.5, Qt::black);
+ gradient2.setColorAt(1, Qt::transparent);
+ gradient2.setSpread(QGradient::RepeatSpread);
+ scene.setBackgroundBrush(gradient2);
+
+ QRadialGradient gradient3(view.rect().center() + QPoint(int(sin(i / 1.85) * 10), int(cos(i / 1.85) * 10)), 10);
+ gradient3.setColorAt(0, Qt::transparent);
+ gradient3.setColorAt(0.5, Qt::black);
+ gradient3.setColorAt(1, Qt::transparent);
+ gradient3.setSpread(QGradient::RepeatSpread);
+ scene.setBackgroundBrush(gradient3);
+
+ QApplication::processEvents();
+ }
+
+ view.setSceneRect(-1000, -1000, 2000, 2000);
+ for (int i = -500; i < 500; i += 10) {
+ view.centerOn(i, 0);
+ QApplication::processEvents();
+ QApplication::processEvents();
+ }
+ for (int i = -500; i < 500; i += 10) {
+ view.centerOn(0, i);
+ QApplication::processEvents();
+ QApplication::processEvents();
+ }
+}
+
+void tst_QGraphicsView::matrix()
+{
+ {
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+
+ // Show rendering of background with no scene
+ for (int i = 0; i < 50; ++i) {
+ view.rotate(5);
+ QRadialGradient gradient(view.rect().center() + QPoint(int(sin(i / 2.0) * 10), int(cos(i / 2.0) * 10)), 10);
+ gradient.setColorAt(0, Qt::transparent);
+ gradient.setColorAt(0.5, Qt::black);
+ gradient.setColorAt(1, Qt::transparent);
+ gradient.setSpread(QGradient::RepeatSpread);
+ scene.setForegroundBrush(gradient);
+ QRadialGradient gradient2(view.rect().center() + QPoint(int(sin(i / 1.7) * 10), int(cos(i / 1.7) * 10)), 10);
+ gradient2.setColorAt(0, Qt::transparent);
+ gradient2.setColorAt(0.5, Qt::black);
+ gradient2.setColorAt(1, Qt::transparent);
+ gradient2.setSpread(QGradient::RepeatSpread);
+ scene.setBackgroundBrush(gradient2);
+ QApplication::processEvents();
+ QApplication::processEvents();
+ }
+ }
+
+ // Test transformation extremes, see if they cause crashes
+ {
+ QGraphicsScene scene;
+ scene.addText("GraphicsView rotated clockwise");
+
+ QGraphicsView view(&scene);
+ view.show();
+ for (int i = 0; i < 160; ++i) {
+ view.rotate(18);
+ QApplication::processEvents();
+ QApplication::processEvents();
+ }
+ /*
+ // These cause a crash
+ for (int i = 0; i < 40; ++i) {
+ view.shear(1.2, 1.2);
+ QTest::qWait(20);
+ }
+ for (int i = 0; i < 40; ++i) {
+ view.shear(-1.2, -1.2);
+ QTest::qWait(20);
+ }
+ */
+ for (int i = 0; i < 20; ++i) {
+ view.scale(1.2, 1.2);
+ QApplication::processEvents();
+ QApplication::processEvents();
+ }
+ for (int i = 0; i < 20; ++i) {
+ view.scale(0.6, 0.6);
+ QApplication::processEvents();
+ QApplication::processEvents();
+ }
+ }
+}
+
+void tst_QGraphicsView::matrix_convenience()
+{
+ QGraphicsView view;
+ QCOMPARE(view.matrix(), QMatrix());
+
+ // Check the convenience functions
+ view.rotate(90);
+ QCOMPARE(view.matrix(), QMatrix().rotate(90));
+ view.scale(2, 2);
+ QCOMPARE(view.matrix(), QMatrix().scale(2, 2) * QMatrix().rotate(90));
+ view.shear(1.2, 1.2);
+ QCOMPARE(view.matrix(), QMatrix().shear(1.2, 1.2) * QMatrix().scale(2, 2) * QMatrix().rotate(90));
+ view.translate(1, 1);
+ QCOMPARE(view.matrix(), QMatrix().translate(1, 1) * QMatrix().shear(1.2, 1.2) * QMatrix().scale(2, 2) * QMatrix().rotate(90));
+}
+
+void tst_QGraphicsView::matrix_combine()
+{
+ // Check matrix combining
+ QGraphicsView view;
+ QCOMPARE(view.matrix(), QMatrix());
+ view.setMatrix(QMatrix().rotate(90), true);
+ view.setMatrix(QMatrix().rotate(90), true);
+ view.setMatrix(QMatrix().rotate(90), true);
+ view.setMatrix(QMatrix().rotate(90), true);
+ QCOMPARE(view.matrix(), QMatrix());
+
+ view.resetMatrix();
+ QCOMPARE(view.matrix(), QMatrix());
+ view.setMatrix(QMatrix().rotate(90), false);
+ view.setMatrix(QMatrix().rotate(90), false);
+ view.setMatrix(QMatrix().rotate(90), false);
+ view.setMatrix(QMatrix().rotate(90), false);
+ QCOMPARE(view.matrix(), QMatrix().rotate(90));
+}
+
+void tst_QGraphicsView::centerOnPoint()
+{
+ QWidget toplevel;
+
+ QGraphicsScene scene;
+ scene.addEllipse(QRectF(-100, -100, 50, 50));
+ scene.addEllipse(QRectF(50, -100, 50, 50));
+ scene.addEllipse(QRectF(-100, 50, 50, 50));
+ scene.addEllipse(QRectF(50, 50, 50, 50));
+
+ QGraphicsView view(&scene, &toplevel);
+ view.setSceneRect(-400, -400, 800, 800);
+ view.setFixedSize(100, 100);
+ toplevel.show();
+
+ int tolerance = 5;
+
+ for (int i = 0; i < 3; ++i) {
+ for (int y = -100; y < 100; y += 23) {
+ for (int x = -100; x < 100; x += 23) {
+ view.centerOn(x, y);
+ QPoint viewCenter = view.mapToScene(view.viewport()->rect().center()).toPoint();
+
+ // Fuzzy compare
+ if (viewCenter.x() < x - tolerance || viewCenter.x() > x + tolerance
+ || viewCenter.y() < y - tolerance || viewCenter.y() > y + tolerance) {
+ QString error = QString("Compared values are not the same\n\tActual: (%1, %2)\n\tExpected: (%3, %4)")
+ .arg(viewCenter.x()).arg(viewCenter.y()).arg(x).arg(y);
+ QFAIL(qPrintable(error));
+ }
+
+ QApplication::processEvents();
+ }
+ }
+
+ view.rotate(13);
+ view.scale(1.5, 1.5);
+ view.shear(1.25, 1.25);
+ }
+}
+
+void tst_QGraphicsView::centerOnItem()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *items[4];
+ items[0] = scene.addEllipse(QRectF(-25, -25, 50, 50));
+ items[1] = scene.addEllipse(QRectF(-25, -25, 50, 50));
+ items[2] = scene.addEllipse(QRectF(-25, -25, 50, 50));
+ items[3] = scene.addEllipse(QRectF(-25, -25, 50, 50));
+ items[0]->setPos(-100, -100);
+ items[1]->setPos(100, -100);
+ items[2]->setPos(-100, 100);
+ items[3]->setPos(100, 100);
+
+ QGraphicsView view(&scene);
+ view.setSceneRect(-1000, -1000, 2000, 2000);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ int tolerance = 7;
+
+ for (int x = 0; x < 3; ++x) {
+ for (int i = 0; i < 4; ++i) {
+ QApplication::processEvents();
+ view.centerOn(items[i]);
+
+ QPoint viewCenter = view.mapToScene(view.viewport()->rect().center()).toPoint();
+ qreal x = items[i]->pos().x();
+ qreal y = items[i]->pos().y();
+
+ // Fuzzy compare
+ if (viewCenter.x() < x - tolerance || viewCenter.x() > x + tolerance
+ || viewCenter.y() < y - tolerance || viewCenter.y() > y + tolerance) {
+ QString error = QString("Compared values are not the same\n\tActual: (%1, %2)\n\tExpected: (%3, %4)")
+ .arg(viewCenter.x()).arg(viewCenter.y()).arg(x).arg(y);
+ QFAIL(qPrintable(error));
+ }
+
+ QApplication::processEvents();
+ }
+
+ view.rotate(13);
+ view.scale(1.5, 1.5);
+ view.shear(1.25, 1.25);
+ }
+}
+
+void tst_QGraphicsView::ensureVisibleRect()
+{
+ QWidget toplevel;
+
+ QGraphicsScene scene;
+ QGraphicsItem *items[4];
+ items[0] = scene.addEllipse(QRectF(-25, -25, 50, 50), QPen(Qt::black), QBrush(Qt::green));
+ items[1] = scene.addEllipse(QRectF(-25, -25, 50, 50), QPen(Qt::black), QBrush(Qt::red));
+ items[2] = scene.addEllipse(QRectF(-25, -25, 50, 50), QPen(Qt::black), QBrush(Qt::blue));
+ items[3] = scene.addEllipse(QRectF(-25, -25, 50, 50), QPen(Qt::black), QBrush(Qt::yellow));
+ scene.addLine(QLineF(0, -100, 0, 100), QPen(Qt::blue, 2));
+ scene.addLine(QLineF(-100, 0, 100, 0), QPen(Qt::blue, 2));
+ items[0]->setPos(-100, -100);
+ items[1]->setPos(100, -100);
+ items[2]->setPos(-100, 100);
+ items[3]->setPos(100, 100);
+
+ QGraphicsItem *icon = scene.addEllipse(QRectF(-10, -10, 20, 20), QPen(Qt::black), QBrush(Qt::gray));
+
+ QGraphicsView view(&scene, &toplevel);
+ view.setSceneRect(-500, -500, 1000, 1000);
+ view.setFixedSize(250, 250);
+ toplevel.show();
+ QTest::qWaitForWindowShown(&toplevel);
+
+ for (int y = -100; y < 100; y += 25) {
+ for (int x = -100; x < 100; x += 13) {
+
+ icon->setPos(x, y);
+
+ switch (x & 3) {
+ case 0:
+ view.centerOn(-500, -500);
+ break;
+ case 1:
+ view.centerOn(500, -500);
+ break;
+ case 2:
+ view.centerOn(-500, 500);
+ break;
+ case 3:
+ default:
+ view.centerOn(500, 500);
+ break;
+ }
+
+ QVERIFY(!view.viewport()->rect().contains(view.mapFromScene(x, y)));
+
+ for (int margin = 10; margin < 60; margin += 15) {
+ view.ensureVisible(x, y, 0, 0, margin, margin);
+
+ QRect viewRect = view.viewport()->rect();
+ QPoint viewPoint = view.mapFromScene(x, y);
+
+ QVERIFY(viewRect.contains(viewPoint));
+ QVERIFY(qAbs(viewPoint.x() - viewRect.left()) >= margin -1);
+ QVERIFY(qAbs(viewPoint.x() - viewRect.right()) >= margin -1);
+ QVERIFY(qAbs(viewPoint.y() - viewRect.top()) >= margin -1);
+ QVERIFY(qAbs(viewPoint.y() - viewRect.bottom()) >= margin -1);
+
+ QApplication::processEvents();
+ }
+ }
+ view.rotate(5);
+ view.scale(1.05, 1.05);
+ view.translate(30, -30);
+ }
+}
+
+void tst_QGraphicsView::fitInView()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *items[4];
+ items[0] = scene.addEllipse(QRectF(-25, -25, 100, 20), QPen(Qt::black), QBrush(Qt::green));
+ items[1] = scene.addEllipse(QRectF(-25, -25, 20, 100), QPen(Qt::black), QBrush(Qt::red));
+ items[2] = scene.addEllipse(QRectF(-25, -25, 50, 50), QPen(Qt::black), QBrush(Qt::blue));
+ items[3] = scene.addEllipse(QRectF(-25, -25, 50, 50), QPen(Qt::black), QBrush(Qt::yellow));
+ scene.addLine(QLineF(0, -100, 0, 100), QPen(Qt::blue, 2));
+ scene.addLine(QLineF(-100, 0, 100, 0), QPen(Qt::blue, 2));
+ items[0]->setPos(-100, -100);
+ items[1]->setPos(100, -100);
+ items[2]->setPos(-100, 100);
+ items[3]->setPos(100, 100);
+
+ items[0]->rotate(30);
+ items[1]->rotate(-30);
+
+#if defined(Q_OS_WINCE)
+ //Is the standard scrollbar size
+ int scrollbarSize = qApp->style()->pixelMetric(QStyle::PM_ScrollBarExtent) - 13;
+#endif
+
+ QGraphicsView view(&scene);
+ view.setSceneRect(-400, -400, 800, 800);
+
+#if defined(Q_OS_WINCE)
+ //We need to take in account the scrollbar size for the WindowsMobilStyle
+ view.setFixedSize(400 + scrollbarSize, 200 + scrollbarSize);
+#else
+ view.setFixedSize(400, 200);
+#endif
+
+ if (PlatformQuirks::isAutoMaximizing())
+ view.setWindowFlags(view.windowFlags()|Qt::X11BypassWindowManagerHint);
+
+ view.show();
+ view.fitInView(scene.itemsBoundingRect(), Qt::IgnoreAspectRatio);
+ qApp->processEvents();
+
+ // Sampled coordinates.
+ QVERIFY(!view.itemAt(45, 41));
+ QVERIFY(!view.itemAt(297, 44));
+ QVERIFY(!view.itemAt(359, 143));
+ QCOMPARE(view.itemAt(79, 22), items[0]);
+ QCOMPARE(view.itemAt(329, 41), items[1]);
+ QCOMPARE(view.itemAt(38, 158), items[2]);
+ QCOMPARE(view.itemAt(332, 160), items[3]);
+
+ view.fitInView(items[0], Qt::IgnoreAspectRatio);
+ qApp->processEvents();
+
+ QCOMPARE(view.itemAt(19, 13), items[0]);
+ QCOMPARE(view.itemAt(91, 47), items[0]);
+ QCOMPARE(view.itemAt(202, 94), items[0]);
+ QCOMPARE(view.itemAt(344, 161), items[0]);
+ QVERIFY(!view.itemAt(236, 54));
+ QVERIFY(!view.itemAt(144, 11));
+ QVERIFY(!view.itemAt(29, 69));
+ QVERIFY(!view.itemAt(251, 167));
+
+ view.fitInView(items[0], Qt::KeepAspectRatio);
+ qApp->processEvents();
+
+ QCOMPARE(view.itemAt(325, 170), items[0]);
+ QCOMPARE(view.itemAt(206, 74), items[0]);
+ QCOMPARE(view.itemAt(190, 115), items[0]);
+ QCOMPARE(view.itemAt(55, 14), items[0]);
+ QVERIFY(!view.itemAt(109, 4));
+ QVERIFY(!view.itemAt(244, 68));
+ QVERIFY(!view.itemAt(310, 125));
+ QVERIFY(!view.itemAt(261, 168));
+
+ view.fitInView(items[0], Qt::KeepAspectRatioByExpanding);
+ qApp->processEvents();
+
+ QCOMPARE(view.itemAt(18, 10), items[0]);
+ QCOMPARE(view.itemAt(95, 4), items[0]);
+ QCOMPARE(view.itemAt(279, 175), items[0]);
+ QCOMPARE(view.itemAt(359, 170), items[0]);
+ QVERIFY(!view.itemAt(370, 166));
+ QVERIFY(!view.itemAt(136, 7));
+ QVERIFY(!view.itemAt(31, 44));
+ QVERIFY(!view.itemAt(203, 153));
+}
+
+void tst_QGraphicsView::itemsAtPoint()
+{
+ QGraphicsScene scene;
+ scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(1);
+ scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(0);
+ scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(2);
+ scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(-1);
+ scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(3);
+
+ QGraphicsView view;
+ QVERIFY(view.items(0, 0).isEmpty());
+
+ view.setScene(&scene);
+ view.setSceneRect(-10000, -10000, 20000, 20000);
+ view.show();
+
+ QList<QGraphicsItem *> items = view.items(view.viewport()->rect().center());
+ QCOMPARE(items.size(), 5);
+ QCOMPARE(items.takeFirst()->zValue(), qreal(3));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(2));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(1));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(0));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(-1));
+}
+
+void tst_QGraphicsView::itemsInRect()
+{
+ QGraphicsScene scene;
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(1);
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(0);
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(2);
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(-1);
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(3);
+
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(5);
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(4);
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(6);
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(3);
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(7);
+
+ QGraphicsView view;
+ QVERIFY(view.items(QRect(-100, -100, 200, 200)).isEmpty());
+ view.setScene(&scene);
+ view.setSceneRect(-10000, -10000, 20000, 20000);
+ view.show();
+
+ QPoint centerPoint = view.viewport()->rect().center();
+ QRect leftRect = view.mapFromScene(-30, -10, 20, 20).boundingRect();
+ QRect rightRect = view.mapFromScene(30, -10, 20, 20).boundingRect();
+
+ QList<QGraphicsItem *> items = view.items(leftRect);
+ QCOMPARE(items.size(), 5);
+ QCOMPARE(items.takeFirst()->zValue(), qreal(3));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(2));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(1));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(0));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(-1));
+
+ items = view.items(rightRect);
+ QCOMPARE(items.size(), 5);
+ QCOMPARE(items.takeFirst()->zValue(), qreal(7));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(6));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(5));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(4));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(3));
+}
+
+class CountPaintItem : public QGraphicsRectItem
+{
+public:
+ int numPaints;
+
+ CountPaintItem(const QRectF &rect)
+ : QGraphicsRectItem(rect), numPaints(0)
+ { }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
+ {
+ ++numPaints;
+ QGraphicsRectItem::paint(painter, option, widget);
+ }
+};
+
+void tst_QGraphicsView::itemsInRect_cosmeticAdjust_data()
+{
+ QTest::addColumn<QRect>("updateRect");
+ QTest::addColumn<int>("numPaints");
+ QTest::addColumn<bool>("adjustForAntialiasing");
+
+ // Aliased.
+ QTest::newRow("nil") << QRect() << 1 << false;
+ QTest::newRow("0, 0, 300, 100") << QRect(0, 0, 300, 100) << 1 << false;
+ QTest::newRow("0, 0, 100, 300") << QRect(0, 0, 100, 300) << 1 << false;
+ QTest::newRow("200, 0, 100, 300") << QRect(200, 0, 100, 300) << 1 << false;
+ QTest::newRow("0, 200, 300, 100") << QRect(0, 200, 300, 100) << 1 << false;
+ QTest::newRow("0, 0, 300, 99") << QRect(0, 0, 300, 99) << 0 << false;
+ QTest::newRow("0, 0, 99, 300") << QRect(0, 0, 99, 300) << 0 << false;
+ QTest::newRow("201, 0, 99, 300") << QRect(201, 0, 99, 300) << 0 << false;
+ QTest::newRow("0, 201, 300, 99") << QRect(0, 201, 300, 99) << 0 << false;
+
+ // Anti-aliased.
+ QTest::newRow("nil") << QRect() << 1 << true;
+ QTest::newRow("0, 0, 300, 100") << QRect(0, 0, 300, 100) << 1 << true;
+ QTest::newRow("0, 0, 100, 300") << QRect(0, 0, 100, 300) << 1 << true;
+ QTest::newRow("200, 0, 100, 300") << QRect(200, 0, 100, 300) << 1 << true;
+ QTest::newRow("0, 200, 300, 100") << QRect(0, 200, 300, 100) << 1 << true;
+ QTest::newRow("0, 0, 300, 99") << QRect(0, 0, 300, 99) << 1 << true;
+ QTest::newRow("0, 0, 99, 300") << QRect(0, 0, 99, 300) << 1 << true;
+ QTest::newRow("201, 0, 99, 300") << QRect(201, 0, 99, 300) << 1 << true;
+ QTest::newRow("0, 201, 300, 99") << QRect(0, 201, 300, 99) << 1 << true;
+ QTest::newRow("0, 0, 300, 98") << QRect(0, 0, 300, 98) << 0 << false;
+ QTest::newRow("0, 0, 98, 300") << QRect(0, 0, 98, 300) << 0 << false;
+ QTest::newRow("202, 0, 98, 300") << QRect(202, 0, 98, 300) << 0 << false;
+ QTest::newRow("0, 202, 300, 98") << QRect(0, 202, 300, 98) << 0 << false;
+}
+
+void tst_QGraphicsView::itemsInRect_cosmeticAdjust()
+{
+ QFETCH(QRect, updateRect);
+ QFETCH(int, numPaints);
+ QFETCH(bool, adjustForAntialiasing);
+
+ QGraphicsScene scene(-100, -100, 200, 200);
+ CountPaintItem *rect = new CountPaintItem(QRectF(-50, -50, 100, 100));
+ scene.addItem(rect);
+
+ QGraphicsView view(&scene);
+ view.setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing, !adjustForAntialiasing);
+ view.setRenderHint(QPainter::Antialiasing, adjustForAntialiasing);
+ if (PlatformQuirks::isAutoMaximizing())
+ view.setWindowFlags(view.windowFlags()|Qt::X11BypassWindowManagerHint);
+ view.setFrameStyle(0);
+ view.resize(300, 300);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(rect->numPaints > 0);
+
+ rect->numPaints = 0;
+ if (updateRect.isNull())
+ view.viewport()->update();
+ else
+ view.viewport()->update(updateRect);
+ qApp->processEvents();
+ QTRY_COMPARE(rect->numPaints, numPaints);
+}
+
+void tst_QGraphicsView::itemsInPoly()
+{
+ QGraphicsScene scene;
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(1);
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(0);
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(2);
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(-1);
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(3);
+
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(5);
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(4);
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(6);
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(3);
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(7);
+
+ QGraphicsView view;
+ QVERIFY(view.items(QPolygon()).isEmpty());
+ view.setScene(&scene);
+ view.setSceneRect(-10000, -10000, 20000, 20000);
+ view.show();
+
+ QPoint centerPoint = view.viewport()->rect().center();
+ QPolygon leftPoly = view.mapFromScene(QRectF(-30, -10, 20, 20));
+ QPolygon rightPoly = view.mapFromScene(QRectF(30, -10, 20, 20));
+
+ QList<QGraphicsItem *> items = view.items(leftPoly);
+ QCOMPARE(items.size(), 5);
+ QCOMPARE(items.takeFirst()->zValue(), qreal(3));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(2));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(1));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(0));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(-1));
+
+ items = view.items(rightPoly);
+ QCOMPARE(items.size(), 5);
+ QCOMPARE(items.takeFirst()->zValue(), qreal(7));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(6));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(5));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(4));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(3));
+}
+
+void tst_QGraphicsView::itemsInPath()
+{
+ QGraphicsScene scene;
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(1);
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(0);
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(2);
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(-1);
+ scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(3);
+
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(5);
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(4);
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(6);
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(3);
+ scene.addRect(QRectF(30, -10, 20, 20))->setZValue(7);
+
+ QGraphicsView view;
+ QVERIFY(view.items(QPainterPath()).isEmpty());
+ view.setScene(&scene);
+ view.translate(100, 400);
+ view.rotate(22.3);
+ view.setSceneRect(-10000, -10000, 20000, 20000);
+ view.show();
+
+ QPoint centerPoint = view.viewport()->rect().center();
+ QPainterPath leftPath;
+ leftPath.addEllipse(QRect(view.mapFromScene(-30, -10), QSize(20, 20)));
+
+ QPainterPath rightPath;
+ rightPath.addEllipse(QRect(view.mapFromScene(30, -10), QSize(20, 20)));
+
+ QList<QGraphicsItem *> items = view.items(leftPath);
+
+ QCOMPARE(items.size(), 5);
+ QCOMPARE(items.takeFirst()->zValue(), qreal(3));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(2));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(1));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(0));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(-1));
+
+ items = view.items(rightPath);
+ QCOMPARE(items.size(), 5);
+ QCOMPARE(items.takeFirst()->zValue(), qreal(7));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(6));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(5));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(4));
+ QCOMPARE(items.takeFirst()->zValue(), qreal(3));
+}
+
+void tst_QGraphicsView::itemAt()
+{
+ QGraphicsScene scene;
+ scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(1);
+ scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(0);
+ scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(2);
+ scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(-1);
+ scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(3);
+
+ QGraphicsView view;
+ QCOMPARE(view.itemAt(0, 0), (QGraphicsItem *)0);
+
+ view.setScene(&scene);
+ view.setSceneRect(-10000, -10000, 20000, 20000);
+ view.show();
+
+ QCOMPARE(view.itemAt(0, 0), (QGraphicsItem *)0);
+ QGraphicsItem* item = view.itemAt(view.viewport()->rect().center());
+ QVERIFY(item);
+ QCOMPARE(item->zValue(), qreal(3));
+}
+
+void tst_QGraphicsView::itemAt2()
+{
+ // test precision of the itemAt() function with items that are smaller
+ // than 1 pixel.
+ QGraphicsScene scene(0, 0, 100, 100);
+
+ // Add a 0.5x0.5 item at position 0 on the scene, top-left corner at -0.25, -0.25.
+ QGraphicsItem *item = scene.addRect(QRectF(-0.25, -0.25, 0.5, 0.5), QPen(Qt::black, 0.1));
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(200, 200);
+ view.setTransformationAnchor(QGraphicsView::NoAnchor);
+ view.setRenderHint(QPainter::Antialiasing);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
+
+ QPoint itemViewPoint = view.mapFromScene(item->scenePos());
+
+ for (int i = 0; i < 3; ++i) {
+ QVERIFY(view.itemAt(itemViewPoint));
+ QVERIFY(!view.items(itemViewPoint).isEmpty());
+ QVERIFY(view.itemAt(itemViewPoint + QPoint(-1, 0)));
+ QVERIFY(!view.items(itemViewPoint + QPoint(-1, 0)).isEmpty());
+ QVERIFY(view.itemAt(itemViewPoint + QPoint(-1, -1)));
+ QVERIFY(!view.items(itemViewPoint + QPoint(-1, -1)).isEmpty());
+ QVERIFY(view.itemAt(itemViewPoint + QPoint(0, -1)));
+ QVERIFY(!view.items(itemViewPoint + QPoint(0, -1)).isEmpty());
+ item->moveBy(0.1, 0);
+ }
+
+ // Here
+ QVERIFY(view.itemAt(itemViewPoint));
+ QVERIFY(!view.items(itemViewPoint).isEmpty());
+ QVERIFY(view.itemAt(itemViewPoint + QPoint(0, -1)));
+ QVERIFY(!view.items(itemViewPoint + QPoint(0, -1)).isEmpty());
+
+ if (sizeof(qreal) != sizeof(double)) {
+ QSKIP("Skipped due to rounding errors", SkipAll);
+ }
+ // Not here
+ QVERIFY(!view.itemAt(itemViewPoint + QPoint(-1, 0)));
+ QVERIFY(view.items(itemViewPoint + QPoint(-1, 0)).isEmpty());
+ QVERIFY(!view.itemAt(itemViewPoint + QPoint(-1, -1)));
+ QVERIFY(view.items(itemViewPoint + QPoint(-1, -1)).isEmpty());
+}
+
+void tst_QGraphicsView::mapToScene()
+{
+ // Uncomment the commented-out code to see what's going on. It doesn't
+ // affect the test; it just slows it down.
+
+ QGraphicsScene scene;
+ scene.addPixmap(QPixmap("3D-Qt-1-2.png"));
+
+ QWidget topLevel;
+ QGraphicsView view(&topLevel);
+ view.setScene(&scene);
+ view.setSceneRect(-500, -500, 1000, 1000);
+#if defined(Q_OS_WINCE)
+ QSize viewSize(200,200);
+#else
+ QSize viewSize(300,300);
+#endif
+
+ view.setFixedSize(viewSize);
+ topLevel.show();
+ QApplication::processEvents();
+ QVERIFY(view.isVisible());
+ QCOMPARE(view.size(), viewSize);
+
+ // First once without setting the scene rect
+#ifdef QT_ARCH_ARM
+ const int step = 20;
+#else
+ const int step = 1;
+#endif
+
+ for (int x = 0; x < view.width(); x += step) {
+ for (int y = 0; y < view.height(); y += step) {
+ QCOMPARE(view.mapToScene(QPoint(x, y)),
+ QPointF(view.horizontalScrollBar()->value() + x,
+ view.verticalScrollBar()->value() + y));
+ }
+ }
+
+ for (int sceneRectHeight = 250; sceneRectHeight < 1000; sceneRectHeight += 250) {
+ for (int sceneRectWidth = 250; sceneRectWidth < 1000; sceneRectWidth += 250) {
+ view.setSceneRect(QRectF(-int(sceneRectWidth / 2), -int(sceneRectHeight / 2),
+ sceneRectWidth, sceneRectHeight));
+ QApplication::processEvents();
+
+ int hmin = view.horizontalScrollBar()->minimum();
+ int hmax = view.horizontalScrollBar()->maximum();
+ int hstep = (hmax - hmin) / 3;
+ int vmin = view.verticalScrollBar()->minimum();
+ int vmax = view.verticalScrollBar()->maximum();
+ int vstep = (vmax - vmin) / 3;
+
+ for (int hscrollValue = hmin; hscrollValue < hmax; hscrollValue += hstep) {
+ for (int vscrollValue = vmin; vscrollValue < vmax; vscrollValue += vstep) {
+
+ view.horizontalScrollBar()->setValue(hscrollValue);
+ view.verticalScrollBar()->setValue(vscrollValue);
+ QApplication::processEvents();
+
+ int h = view.horizontalScrollBar()->value();
+ int v = view.verticalScrollBar()->value();
+
+ for (int x = 0; x < view.width(); x += step) {
+ for (int y = 0; y < view.height(); y += step) {
+ QCOMPARE(view.mapToScene(QPoint(x, y)), QPointF(h + x, v + y));
+ QCOMPARE(view.mapFromScene(QPointF(h + x, v + y)), QPoint(x, y));
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void tst_QGraphicsView::mapToScenePoint()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.rotate(90);
+ view.setFixedSize(117, 117);
+ view.show();
+ QPoint center = view.viewport()->rect().center();
+ QCOMPARE(view.mapToScene(center + QPoint(10, 0)),
+ view.mapToScene(center) + QPointF(0, -10));
+}
+
+void tst_QGraphicsView::mapToSceneRect_data()
+{
+ QTest::addColumn<QRect>("viewRect");
+ QTest::addColumn<QPolygonF>("scenePoly");
+ QTest::addColumn<qreal>("rotation");
+
+ QTest::newRow("nil") << QRect() << QPolygonF() << qreal(0);
+ QTest::newRow("0, 0, 1, 1") << QRect(0, 0, 1, 1) << QPolygonF(QRectF(0, 0, 1, 1)) << qreal(0);
+ QTest::newRow("0, 0, 10, 10") << QRect(0, 0, 10, 10) << QPolygonF(QRectF(0, 0, 10, 10)) << qreal(0);
+ QTest::newRow("nil") << QRect() << QPolygonF() << qreal(90);
+ QPolygonF p;
+ p << QPointF(0, 0) << QPointF(0, -1) << QPointF(1, -1) << QPointF(1, 0) << QPointF(0, 0);
+ QTest::newRow("0, 0, 1, 1") << QRect(0, 0, 1, 1)
+ << p
+ << qreal(90);
+ p.clear();
+ p << QPointF(0, 0) << QPointF(0, -10) << QPointF(10, -10) << QPointF(10, 0) << QPointF(0, 0);
+ QTest::newRow("0, 0, 10, 10") << QRect(0, 0, 10, 10)
+ << p
+ << qreal(90);
+}
+
+void tst_QGraphicsView::mapToSceneRect()
+{
+ QFETCH(QRect, viewRect);
+ QFETCH(QPolygonF, scenePoly);
+ QFETCH(qreal, rotation);
+
+ QGraphicsScene scene(-1000, -1000, 2000, 2000);
+ scene.addRect(25, -25, 50, 50);
+ QGraphicsView view(&scene);
+ view.setFrameStyle(0);
+ view.setAlignment(Qt::AlignTop | Qt::AlignLeft);
+ view.setFixedSize(200, 200);
+ view.setTransformationAnchor(QGraphicsView::NoAnchor);
+ view.setResizeAnchor(QGraphicsView::NoAnchor);
+ view.show();
+
+ view.rotate(rotation);
+
+ QPolygonF poly = view.mapToScene(viewRect);
+ if (!poly.isEmpty())
+ poly << poly[0];
+
+ QCOMPARE(poly, scenePoly);
+}
+
+void tst_QGraphicsView::mapToScenePoly()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.translate(100, 100);
+ view.setFixedSize(117, 117);
+ view.show();
+ QPoint center = view.viewport()->rect().center();
+ QRect rect(center + QPoint(10, 0), QSize(10, 10));
+
+ QPolygon poly;
+ poly << rect.topLeft();
+ poly << rect.topRight();
+ poly << rect.bottomRight();
+ poly << rect.bottomLeft();
+
+ QPolygonF poly2;
+ poly2 << view.mapToScene(rect.topLeft());
+ poly2 << view.mapToScene(rect.topRight());
+ poly2 << view.mapToScene(rect.bottomRight());
+ poly2 << view.mapToScene(rect.bottomLeft());
+
+ QCOMPARE(view.mapToScene(poly), poly2);
+}
+
+void tst_QGraphicsView::mapToScenePath()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.setSceneRect(-300, -300, 600, 600);
+ view.translate(10, 10);
+ view.setFixedSize(300, 300);
+ view.show();
+ QPoint center = view.viewport()->rect().center();
+ QRect rect(QPoint(10, 0), QSize(10, 10));
+
+ QPainterPath path;
+ path.addRect(rect);
+
+ QPainterPath path2;
+ path2.addRect(rect.translated(view.horizontalScrollBar()->value() - 10,
+ view.verticalScrollBar()->value() - 10));
+ QCOMPARE(view.mapToScene(path), path2);
+}
+
+void tst_QGraphicsView::mapFromScenePoint()
+{
+ {
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.rotate(90);
+ view.scale(10, 10);
+ view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view.show();
+
+ QPoint mapped = view.mapFromScene(0, 0);
+ QPoint center = view.viewport()->rect().center();
+ if (qAbs(mapped.x() - center.x()) >= 2
+ || qAbs(mapped.y() - center.y()) >= 2) {
+ QString error = QString("Compared values are not the same\n\tActual: (%1, %2)\n\tExpected: (%3, %4)")
+ .arg(mapped.x()).arg(mapped.y()).arg(center.x()).arg(center.y());
+ QFAIL(qPrintable(error));
+ }
+ }
+ {
+ QWidget toplevel;
+
+ QGraphicsScene scene(0, 0, 200, 200);
+ scene.addRect(QRectF(0, 0, 200, 200), QPen(Qt::black, 1));
+ QGraphicsView view(&scene, &toplevel);
+ view.ensurePolished();
+ view.resize(view.sizeHint());
+ toplevel.show();
+
+ QCOMPARE(view.mapFromScene(0, 0), QPoint(0, 0));
+ QCOMPARE(view.mapFromScene(0.4, 0.4), QPoint(0, 0));
+ QCOMPARE(view.mapFromScene(0.5, 0.5), QPoint(1, 1));
+ QCOMPARE(view.mapFromScene(0.9, 0.9), QPoint(1, 1));
+ QCOMPARE(view.mapFromScene(1.0, 1.0), QPoint(1, 1));
+ QCOMPARE(view.mapFromScene(100, 100), QPoint(100, 100));
+ QCOMPARE(view.mapFromScene(100.5, 100.5), QPoint(101, 101));
+ QCOMPARE(view.mapToScene(0, 0), QPointF(0, 0));
+ QCOMPARE(view.mapToScene(1, 1), QPointF(1, 1));
+ QCOMPARE(view.mapToScene(100, 100), QPointF(100, 100));
+ }
+}
+
+void tst_QGraphicsView::mapFromSceneRect()
+{
+ QGraphicsScene scene;
+ QWidget topLevel;
+ QGraphicsView view(&scene,&topLevel);
+ view.rotate(90);
+ view.setFixedSize(200, 200);
+ view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ topLevel.show();
+ QTest::qWait(25);
+
+ QPolygon polygon;
+ polygon << QPoint(98, 98);
+ polygon << QPoint(98, 108);
+ polygon << QPoint(88, 108);
+ polygon << QPoint(88, 98);
+
+
+ QPolygon viewPolygon = view.mapFromScene(0, 0, 10, 10);
+ for (int i = 0; i < 4; ++i) {
+ QVERIFY(qAbs(viewPolygon[i].x() - polygon[i].x()) < 3);
+ QVERIFY(qAbs(viewPolygon[i].y() - polygon[i].y()) < 3);
+ }
+
+ QPoint pt = view.mapFromScene(QPointF());
+ QPolygon p;
+ p << pt << pt << pt << pt;
+ QCOMPARE(view.mapFromScene(QRectF()), p);
+}
+
+void tst_QGraphicsView::mapFromScenePoly()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.rotate(90);
+ view.setFixedSize(200, 200);
+ view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view.show();
+
+ QPolygonF polygon;
+ polygon << QPoint(0, 0);
+ polygon << QPoint(10, 0);
+ polygon << QPoint(10, 10);
+ polygon << QPoint(0, 10);
+
+ QPolygon polygon2;
+ polygon2 << QPoint(98, 98);
+ polygon2 << QPoint(98, 108);
+ polygon2 << QPoint(88, 108);
+ polygon2 << QPoint(88, 98);
+
+ QPolygon viewPolygon = view.mapFromScene(polygon);
+ for (int i = 0; i < 4; ++i) {
+ QVERIFY(qAbs(viewPolygon[i].x() - polygon2[i].x()) < 3);
+ QVERIFY(qAbs(viewPolygon[i].y() - polygon2[i].y()) < 3);
+ }
+}
+
+void tst_QGraphicsView::mapFromScenePath()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.rotate(90);
+ view.setFixedSize(200, 200);
+ view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view.show();
+
+ QPolygonF polygon;
+ polygon << QPoint(0, 0);
+ polygon << QPoint(10, 0);
+ polygon << QPoint(10, 10);
+ polygon << QPoint(0, 10);
+ QPainterPath path;
+ path.addPolygon(polygon);
+
+ QPolygon polygon2;
+ polygon2 << QPoint(98, 98);
+ polygon2 << QPoint(98, 108);
+ polygon2 << QPoint(88, 108);
+ polygon2 << QPoint(88, 98);
+ QPainterPath path2;
+ path2.addPolygon(polygon2);
+
+ QPolygonF pathPoly = view.mapFromScene(path).toFillPolygon();
+ QPolygonF path2Poly = path2.toFillPolygon();
+
+ for (int i = 0; i < pathPoly.size(); ++i) {
+ QVERIFY(qAbs(pathPoly[i].x() - path2Poly[i].x()) < 3);
+ QVERIFY(qAbs(pathPoly[i].y() - path2Poly[i].y()) < 3);
+ }
+}
+
+void tst_QGraphicsView::sendEvent()
+{
+ QGraphicsScene scene;
+
+ TestItem *item = new TestItem;
+ scene.addItem(item);
+ item->setFlag(QGraphicsItem::ItemIsFocusable);
+ item->setFlag(QGraphicsItem::ItemIsMovable);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::setActiveWindow(&view);
+ QTest::qWait(20);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
+
+ item->setFocus();
+
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *)item);
+ QCOMPARE(item->events.size(), 2);
+ QCOMPARE(item->events.last(), QEvent::FocusIn);
+
+ QPoint itemPoint = view.mapFromScene(item->scenePos());
+ sendMousePress(view.viewport(), itemPoint);
+ QCOMPARE(item->events.size(), 4);
+ QCOMPARE(item->events.at(item->events.size() - 2), QEvent::GrabMouse);
+ QCOMPARE(item->events.at(item->events.size() - 1), QEvent::GraphicsSceneMousePress);
+
+ QMouseEvent mouseMoveEvent(QEvent::MouseMove, itemPoint, view.viewport()->mapToGlobal(itemPoint),
+ Qt::LeftButton, Qt::LeftButton, 0);
+ QApplication::sendEvent(view.viewport(), &mouseMoveEvent);
+ QCOMPARE(item->events.size(), 5);
+ QCOMPARE(item->events.last(), QEvent::GraphicsSceneMouseMove);
+
+ QMouseEvent mouseReleaseEvent(QEvent::MouseButtonRelease, itemPoint,
+ view.viewport()->mapToGlobal(itemPoint),
+ Qt::LeftButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &mouseReleaseEvent);
+ QCOMPARE(item->events.size(), 7);
+ QCOMPARE(item->events.at(item->events.size() - 2), QEvent::GraphicsSceneMouseRelease);
+ QCOMPARE(item->events.at(item->events.size() - 1), QEvent::UngrabMouse);
+
+ QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Space, 0);
+ QApplication::sendEvent(view.viewport(), &keyPress);
+ QCOMPARE(item->events.size(), 9);
+ QCOMPARE(item->events.at(item->events.size() - 2), QEvent::ShortcutOverride);
+ QCOMPARE(item->events.last(), QEvent::KeyPress);
+}
+
+class MouseWheelScene : public QGraphicsScene
+{
+public:
+ Qt::Orientation orientation;
+
+ void wheelEvent(QGraphicsSceneWheelEvent *event)
+ {
+ orientation = event->orientation();
+ QGraphicsScene::wheelEvent(event);
+ }
+};
+
+void tst_QGraphicsView::wheelEvent()
+{
+ // Create a scene with an invalid orientation.
+ MouseWheelScene scene;
+ scene.orientation = Qt::Orientation(-1);
+
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ widget->setGeometry(0, 0, 400, 400);
+ widget->setFocusPolicy(Qt::WheelFocus);
+
+ EventSpy spy(widget, QEvent::GraphicsSceneWheel);
+ QCOMPARE(spy.count(), 0);
+
+ scene.addItem(widget);
+
+ // Assign a view.
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::setActiveWindow(&view);
+ QTest::qWait(20);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
+
+
+ // Send a wheel event with horizontal orientation.
+ {
+ QWheelEvent event(view.mapFromScene(widget->boundingRect().center()),
+ view.mapToGlobal(view.mapFromScene(widget->boundingRect().center())),
+ 120, 0, 0, Qt::Horizontal);
+ QApplication::sendEvent(view.viewport(), &event);
+ QCOMPARE(scene.orientation, Qt::Horizontal);
+ }
+
+ // Send a wheel event with vertical orientation.
+ {
+ QWheelEvent event(view.mapFromScene(widget->boundingRect().center()),
+ view.mapToGlobal(view.mapFromScene(widget->boundingRect().center())),
+ 120, 0, 0, Qt::Vertical);
+ QApplication::sendEvent(view.viewport(), &event);
+ QCOMPARE(scene.orientation, Qt::Vertical);
+ }
+
+ QCOMPARE(spy.count(), 2);
+ QVERIFY(widget->hasFocus());
+}
+
+// Qt/CE does not have regular cursor support.
+#if !defined(QT_NO_CURSOR) && !defined(Q_OS_WINCE)
+void tst_QGraphicsView::cursor()
+{
+ if (PlatformQuirks::haveMouseCursor())
+ QSKIP("The Platform does not have regular cursor support", SkipAll);
+
+ QGraphicsScene scene;
+ QGraphicsItem *item = scene.addRect(QRectF(-10, -10, 20, 20));
+ item->setCursor(Qt::IBeamCursor);
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(400, 400);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QCOMPARE(view.viewport()->cursor().shape(), QCursor().shape());
+ view.viewport()->setCursor(Qt::PointingHandCursor);
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+
+ sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
+
+ sendMouseMove(view.viewport(), QPoint(5, 5));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+}
+#endif
+
+// Qt/CE does not have regular cursor support.
+#if !defined(QT_NO_CURSOR) && !defined(Q_OS_WINCE)
+void tst_QGraphicsView::cursor2()
+{
+ if (PlatformQuirks::haveMouseCursor())
+ QSKIP("The Platform does not have regular cursor support", SkipAll);
+
+ QGraphicsScene scene;
+ QGraphicsItem *item = scene.addRect(QRectF(-10, -10, 20, 20));
+ item->setCursor(Qt::IBeamCursor);
+ item->setZValue(1);
+
+ QGraphicsItem *item2 = scene.addRect(QRectF(-20, -20, 40, 40));
+ item2->setZValue(0);
+
+ QGraphicsView view(&scene);
+ view.viewport()->setCursor(Qt::PointingHandCursor);
+ view.setFixedSize(400, 400);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(-15, 0));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+
+ view.setDragMode(QGraphicsView::ScrollHandDrag);
+
+ sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::OpenHandCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(-15, -15));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::OpenHandCursor);
+
+ view.setDragMode(QGraphicsView::NoDrag);
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::ArrowCursor);
+ view.viewport()->setCursor(Qt::PointingHandCursor);
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+
+ item2->setCursor(Qt::SizeAllCursor);
+
+ sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(-15, -15));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::SizeAllCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(-15, -15));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::SizeAllCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+
+ view.setDragMode(QGraphicsView::ScrollHandDrag);
+
+ sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::OpenHandCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(-15, -15));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::SizeAllCursor);
+}
+#endif
+
+void tst_QGraphicsView::transformationAnchor()
+{
+ QGraphicsScene scene(-1000, -1000, 2000, 2000);
+ scene.addRect(QRectF(-50, -50, 100, 100), QPen(Qt::black), QBrush(Qt::blue));
+
+ QGraphicsView view(&scene);
+
+ for (int i = 0; i < 2; ++i) {
+ view.resize(100, 100);
+ view.show();
+
+ if (i == 0) {
+ QCOMPARE(view.transformationAnchor(), QGraphicsView::AnchorViewCenter);
+ } else {
+ view.setTransformationAnchor(QGraphicsView::NoAnchor);
+ }
+ view.centerOn(0, 0);
+ view.horizontalScrollBar()->setValue(100);
+ QApplication::processEvents();
+
+ QPointF center = view.mapToScene(view.viewport()->rect().center());
+
+ view.scale(10, 10);
+
+ QPointF newCenter = view.mapToScene(view.viewport()->rect().center());
+
+ if (i == 0) {
+ qreal slack = 3;
+ QVERIFY(qAbs(newCenter.x() - center.x()) < slack);
+ QVERIFY(qAbs(newCenter.y() - center.y()) < slack);
+ } else {
+ qreal slack = qreal(0.3);
+ QVERIFY(qAbs(newCenter.x() - center.x() / 10) < slack);
+ QVERIFY(qAbs(newCenter.y() - center.y() / 10) < slack);
+ }
+ }
+}
+
+void tst_QGraphicsView::resizeAnchor()
+{
+ QGraphicsScene scene(-1000, -1000, 2000, 2000);
+ scene.addRect(QRectF(-50, -50, 100, 100), QPen(Qt::black), QBrush(Qt::blue));
+
+ QGraphicsView view(&scene);
+
+ for (int i = 0; i < 2; ++i) {
+ view.resize(100, 100);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
+
+ if (i == 0) {
+ QCOMPARE(view.resizeAnchor(), QGraphicsView::NoAnchor);
+ } else {
+ view.setResizeAnchor(QGraphicsView::AnchorViewCenter);
+ }
+ view.centerOn(0, 0);
+ QTest::qWait(25);
+
+ QPointF f = view.mapToScene(50, 50);
+ QPointF center = view.mapToScene(view.viewport()->rect().center());
+
+ QApplication::processEvents();
+
+ for (int size = 200; size <= 400; size += 25) {
+ view.resize(size, size);
+ if (i == 0) {
+ QTRY_COMPARE(view.mapToScene(50, 50), f);
+ QTRY_VERIFY(view.mapToScene(view.viewport()->rect().center()) != center);
+ } else {
+ QTRY_VERIFY(view.mapToScene(50, 50) != f);
+
+ QPointF newCenter = view.mapToScene(view.viewport()->rect().center());
+ int slack = 3;
+ QVERIFY(qAbs(newCenter.x() - center.x()) < slack);
+ QVERIFY(qAbs(newCenter.y() - center.y()) < slack);
+ }
+ QApplication::processEvents();
+ }
+ }
+}
+
+class CustomView : public QGraphicsView
+{
+ Q_OBJECT
+public:
+ CustomView(QGraphicsScene *s = 0) : QGraphicsView(s) {}
+ CustomView(QGraphicsScene *s, QWidget *parent)
+ : QGraphicsView(s, parent) {}
+ QList<QRegion> lastUpdateRegions;
+ bool painted;
+
+protected:
+ void paintEvent(QPaintEvent *event)
+ {
+ lastUpdateRegions << event->region();
+ painted = true;
+ QGraphicsView::paintEvent(event);
+ }
+};
+
+void tst_QGraphicsView::viewportUpdateMode()
+{
+ QGraphicsScene scene(0, 0, 100, 100);
+ scene.setBackgroundBrush(Qt::red);
+
+ CustomView view;
+ QDesktopWidget desktop;
+ view.setFixedSize(QSize(500, 500).boundedTo(desktop.availableGeometry().size())); // 500 is too big for all common smartphones
+ view.setScene(&scene);
+ if(PlatformQuirks::isAutoMaximizing())
+ view.setWindowFlags(view.windowFlags()|Qt::X11BypassWindowManagerHint);
+ QCOMPARE(view.viewportUpdateMode(), QGraphicsView::MinimalViewportUpdate);
+
+ // Show the view, and initialize our test.
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(!view.lastUpdateRegions.isEmpty());
+ view.lastUpdateRegions.clear();
+
+ // Issue two scene updates.
+ scene.update(QRectF(0, 0, 10, 10));
+ scene.update(QRectF(20, 0, 10, 10));
+ QTest::qWait(50);
+
+ // The view gets two updates for the update scene updates.
+ QTRY_VERIFY(!view.lastUpdateRegions.isEmpty());
+#ifndef Q_OS_MAC //cocoa doesn't support drawing regions
+ QCOMPARE(view.lastUpdateRegions.last().rects().size(), 2);
+ QCOMPARE(view.lastUpdateRegions.last().rects().at(0).size(), QSize(14, 14));
+ QCOMPARE(view.lastUpdateRegions.last().rects().at(1).size(), QSize(14, 14));
+#endif
+
+ // Set full update mode.
+ view.setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
+ QCOMPARE(view.viewportUpdateMode(), QGraphicsView::FullViewportUpdate);
+ view.lastUpdateRegions.clear();
+
+ // Issue two scene updates.
+ scene.update(QRectF(0, 0, 10, 10));
+ scene.update(QRectF(20, 0, 10, 10));
+ qApp->processEvents();
+ qApp->processEvents();
+
+ // The view gets one full viewport update for the update scene updates.
+ QCOMPARE(view.lastUpdateRegions.last().rects().size(), 1);
+ QCOMPARE(view.lastUpdateRegions.last().rects().at(0).size(), view.viewport()->size());
+ view.lastUpdateRegions.clear();
+
+ // Set smart update mode
+ view.setViewportUpdateMode(QGraphicsView::SmartViewportUpdate);
+ QCOMPARE(view.viewportUpdateMode(), QGraphicsView::SmartViewportUpdate);
+
+ // Issue 100 mini-updates
+ for (int i = 0; i < 10; ++i) {
+ for (int j = 0; j < 10; ++j) {
+ scene.update(QRectF(i * 3, j * 3, 1, 1));
+ }
+ }
+ qApp->processEvents();
+ qApp->processEvents();
+
+ // The view gets one bounding rect update.
+ QCOMPARE(view.lastUpdateRegions.last().rects().size(), 1);
+ QCOMPARE(view.lastUpdateRegions.last().rects().at(0).size(), QSize(32, 32));
+
+ // Set no update mode
+ view.setViewportUpdateMode(QGraphicsView::NoViewportUpdate);
+ QCOMPARE(view.viewportUpdateMode(), QGraphicsView::NoViewportUpdate);
+
+ // Issue two scene updates.
+ view.lastUpdateRegions.clear();
+ TestItem item;
+ scene.addItem(&item);
+ item.moveBy(10, 10);
+ scene.update(QRectF(0, 0, 10, 10));
+ scene.update(QRectF(20, 0, 10, 10));
+ qApp->processEvents();
+ qApp->processEvents();
+
+ // The view should not get any painting calls from the scene updates
+ QCOMPARE(view.lastUpdateRegions.size(), 0);
+}
+
+void tst_QGraphicsView::viewportUpdateMode2()
+{
+ QWidget toplevel;
+
+ // Create a view with viewport rect equal to QRect(0, 0, 200, 200).
+ QGraphicsScene dummyScene;
+ CustomView view(0, &toplevel);
+ view.painted = false;
+ view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
+ view.setScene(&dummyScene);
+ view.ensurePolished(); // make sure we get the right content margins
+ int left, top, right, bottom;
+ view.getContentsMargins(&left, &top, &right, &bottom);
+ view.resize(200 + left + right, 200 + top + bottom);
+ toplevel.show();
+ QTest::qWaitForWindowShown(&toplevel);
+ QTest::qWait(50);
+ QTRY_VERIFY(view.painted);
+ const QRect viewportRect = view.viewport()->rect();
+ QCOMPARE(viewportRect, QRect(0, 0, 200, 200));
+
+#if defined QT_BUILD_INTERNAL
+ QGraphicsViewPrivate *viewPrivate = static_cast<QGraphicsViewPrivate *>(qt_widget_private(&view));
+
+ QRect boundingRect;
+ const QRect rect1(0, 0, 10, 10);
+ QVERIFY(viewPrivate->updateRect(rect1));
+ QVERIFY(!viewPrivate->fullUpdatePending);
+ boundingRect |= rect1;
+ QCOMPARE(viewPrivate->dirtyBoundingRect, boundingRect);
+
+ const QRect rect2(50, 50, 10, 10);
+ QVERIFY(viewPrivate->updateRect(rect2));
+ QVERIFY(!viewPrivate->fullUpdatePending);
+ boundingRect |= rect2;
+ QCOMPARE(viewPrivate->dirtyBoundingRect, boundingRect);
+
+ const QRect rect3(190, 190, 10, 10);
+ QVERIFY(viewPrivate->updateRect(rect3));
+ QVERIFY(viewPrivate->fullUpdatePending);
+ boundingRect |= rect3;
+ QCOMPARE(viewPrivate->dirtyBoundingRect, boundingRect);
+
+ view.lastUpdateRegions.clear();
+ viewPrivate->processPendingUpdates();
+ QTest::qWait(50);
+ QCOMPARE(view.lastUpdateRegions.size(), 1);
+ // Note that we adjust by 2 for antialiasing.
+ QCOMPARE(view.lastUpdateRegions.at(0), QRegion(boundingRect.adjusted(-2, -2, 2, 2) & viewportRect));
+#endif
+}
+
+#ifndef QT_NO_DRAGANDDROP
+void tst_QGraphicsView::acceptDrops()
+{
+ QGraphicsView view;
+
+ // Excepted default behavior.
+ QVERIFY(view.acceptDrops());
+ QVERIFY(view.viewport()->acceptDrops());
+
+ // Excepted behavior with no drops.
+ view.setAcceptDrops(false);
+ QVERIFY(!view.acceptDrops());
+ QVERIFY(!view.viewport()->acceptDrops());
+
+ // Setting a widget with drops on a QGraphicsView without drops.
+ QWidget *widget = new QWidget;
+ widget->setAcceptDrops(true);
+ view.setViewport(widget);
+ QVERIFY(!view.acceptDrops());
+ QVERIFY(!view.viewport()->acceptDrops());
+
+ // Switching the view to accept drops.
+ view.setAcceptDrops(true);
+ QVERIFY(view.acceptDrops());
+ QVERIFY(view.viewport()->acceptDrops());
+
+ // Setting a widget with no drops on a QGraphicsView with drops.
+ widget = new QWidget;
+ widget->setAcceptDrops(false);
+ view.setViewport(widget);
+ QVERIFY(view.viewport()->acceptDrops());
+ QVERIFY(view.acceptDrops());
+
+ // Switching the view to not accept drops.
+ view.setAcceptDrops(false);
+ QVERIFY(!view.viewport()->acceptDrops());
+}
+#endif
+
+void tst_QGraphicsView::optimizationFlags()
+{
+ QGraphicsView view;
+ QVERIFY(!view.optimizationFlags());
+
+ view.setOptimizationFlag(QGraphicsView::DontClipPainter);
+ QVERIFY(view.optimizationFlags() & QGraphicsView::DontClipPainter);
+ view.setOptimizationFlag(QGraphicsView::DontClipPainter, false);
+ QVERIFY(!view.optimizationFlags());
+
+ view.setOptimizationFlag(QGraphicsView::DontSavePainterState);
+ QVERIFY(view.optimizationFlags() & QGraphicsView::DontSavePainterState);
+ view.setOptimizationFlag(QGraphicsView::DontSavePainterState, false);
+ QVERIFY(!view.optimizationFlags());
+
+ view.setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing);
+ QVERIFY(view.optimizationFlags() & QGraphicsView::DontAdjustForAntialiasing);
+ view.setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing, false);
+ QVERIFY(!view.optimizationFlags());
+
+ view.setOptimizationFlags(QGraphicsView::DontAdjustForAntialiasing
+ | QGraphicsView::DontClipPainter);
+ QCOMPARE(view.optimizationFlags(), QGraphicsView::OptimizationFlags(QGraphicsView::DontAdjustForAntialiasing
+ | QGraphicsView::DontClipPainter));
+}
+
+class MessUpPainterItem : public QGraphicsRectItem
+{
+public:
+ MessUpPainterItem(const QRectF &rect) : QGraphicsRectItem(rect), dirtyPainter(false)
+ { }
+
+ bool dirtyPainter;
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ {
+ dirtyPainter = (painter->pen().width() != 0);
+ painter->setPen(QPen(Qt::black, 1.0));
+ }
+};
+
+class MyGraphicsView : public QGraphicsView
+{
+public:
+ MyGraphicsView(QGraphicsScene * scene) : QGraphicsView(scene)
+ { }
+
+ void drawBackground(QPainter * painter, const QRectF & rect) {
+ painter->setCompositionMode(QPainter::CompositionMode_Source);
+ painter->drawRect(rect);
+ }
+
+ void drawItems (QPainter * painter, int numItems, QGraphicsItem *items[], const QStyleOptionGraphicsItem options[]) {
+ if (!(optimizationFlags() & QGraphicsView::DontSavePainterState))
+ QCOMPARE(painter->compositionMode(),QPainter::CompositionMode_SourceOver);
+ else
+ QCOMPARE(painter->compositionMode(),QPainter::CompositionMode_Source);
+ QGraphicsView::drawItems(painter,numItems,items,options);
+ }
+};
+
+void tst_QGraphicsView::optimizationFlags_dontSavePainterState()
+{
+ MessUpPainterItem *parent = new MessUpPainterItem(QRectF(0, 0, 100, 100));
+ MessUpPainterItem *child = new MessUpPainterItem(QRectF(0, 0, 100, 100));
+ child->setParentItem(parent);
+
+ QGraphicsScene scene;
+ scene.addItem(parent);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ view.viewport()->repaint();
+
+ QVERIFY(!parent->dirtyPainter);
+ QVERIFY(!child->dirtyPainter);
+
+ view.setOptimizationFlags(QGraphicsView::DontSavePainterState);
+ view.viewport()->repaint();
+
+#ifdef Q_WS_MAC
+ // Repaint on Mac OS X actually does require spinning the event loop.
+ QTest::qWait(100);
+#endif
+ QVERIFY(!parent->dirtyPainter);
+ QVERIFY(child->dirtyPainter);
+
+ MyGraphicsView painter(&scene);
+ painter.show();
+ QTest::qWaitForWindowShown(&painter);
+
+ MyGraphicsView painter2(&scene);
+ painter2.setOptimizationFlag(QGraphicsView::DontSavePainterState,true);
+ painter2.show();
+ QTest::qWaitForWindowShown(&painter2);
+}
+
+void tst_QGraphicsView::optimizationFlags_dontSavePainterState2_data()
+{
+ QTest::addColumn<bool>("savePainter");
+ QTest::addColumn<bool>("indirectPainting");
+ QTest::newRow("With painter state protection, without indirect painting") << true << false;
+ QTest::newRow("Without painter state protection, without indirect painting") << false << false;
+ QTest::newRow("With painter state protectionm, with indirect painting") << true << true;
+ QTest::newRow("Without painter state protection, with indirect painting") << false << true;
+}
+
+void tst_QGraphicsView::optimizationFlags_dontSavePainterState2()
+{
+ QFETCH(bool, savePainter);
+ QFETCH(bool, indirectPainting);
+
+ class MyScene : public QGraphicsScene
+ {
+ public:
+ void drawBackground(QPainter *p, const QRectF &)
+ { transformInDrawBackground = p->worldTransform(); opacityInDrawBackground = p->opacity(); }
+
+ void drawForeground(QPainter *p, const QRectF &)
+ { transformInDrawForeground = p->worldTransform(); opacityInDrawForeground = p->opacity(); }
+
+ QTransform transformInDrawBackground;
+ QTransform transformInDrawForeground;
+ qreal opacityInDrawBackground;
+ qreal opacityInDrawForeground;
+ };
+
+ MyScene scene;
+ // Add transformed dummy items to make sure the painter's worldTransform() is changed in drawItems.
+ scene.addRect(0, 0, 20, 20)->setTransform(QTransform::fromScale(2, 2));
+ scene.addRect(50, 50, 20, 20)->setTransform(QTransform::fromTranslate(200, 200));
+
+ foreach (QGraphicsItem *item, scene.items())
+ item->setOpacity(0.6);
+
+ CustomView view(&scene);
+ if (!savePainter)
+ view.setOptimizationFlag(QGraphicsView::DontSavePainterState);
+ view.setOptimizationFlag(QGraphicsView::IndirectPainting, indirectPainting);
+ view.rotate(45);
+ view.scale(1.5, 1.5);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+
+ // Make sure the view is repainted; otherwise the tests below will fail.
+ view.viewport()->repaint();
+ QTest::qWait(200);
+ QVERIFY(view.painted);
+
+ // Make sure the painter's world transform is preserved after drawItems.
+ QTransform expectedTransform = view.viewportTransform();
+ QVERIFY(!expectedTransform.isIdentity());
+ QCOMPARE(scene.transformInDrawForeground, expectedTransform);
+ QCOMPARE(scene.transformInDrawBackground, expectedTransform);
+
+ qreal expectedOpacity = 1.0;
+ QCOMPARE(scene.opacityInDrawBackground, expectedOpacity);
+ QCOMPARE(scene.opacityInDrawForeground, expectedOpacity);
+
+ // Trigger more painting, this time from QGraphicsScene::render.
+ QImage image(scene.sceneRect().size().toSize(), QImage::Format_RGB32);
+ QPainter painter(&image);
+ scene.render(&painter);
+ painter.end();
+
+ expectedTransform = QTransform();
+ QCOMPARE(scene.transformInDrawForeground, expectedTransform);
+ QCOMPARE(scene.transformInDrawBackground, expectedTransform);
+ QCOMPARE(scene.opacityInDrawBackground, expectedOpacity);
+ QCOMPARE(scene.opacityInDrawForeground, expectedOpacity);
+
+ // Trigger more painting with another opacity on the painter.
+ painter.begin(&image);
+ painter.setOpacity(0.4);
+ expectedOpacity = 0.4;
+ scene.render(&painter);
+ painter.end();
+
+ QCOMPARE(scene.transformInDrawForeground, expectedTransform);
+ QCOMPARE(scene.transformInDrawBackground, expectedTransform);
+ QCOMPARE(scene.opacityInDrawBackground, expectedOpacity);
+ QCOMPARE(scene.opacityInDrawForeground, expectedOpacity);
+}
+
+class LodItem : public QGraphicsRectItem
+{
+public:
+ LodItem(const QRectF &rect) : QGraphicsRectItem(rect), lastLod(-42)
+ { }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *viewport)
+ {
+ lastLod = option->levelOfDetailFromTransform(painter->worldTransform());
+ QGraphicsRectItem::paint(painter, option, viewport);
+ }
+
+ qreal lastLod;
+};
+
+void tst_QGraphicsView::levelOfDetail_data()
+{
+ QTest::addColumn<QTransform>("transform");
+ QTest::addColumn<qreal>("lod");
+
+ QTest::newRow("1:4, 1:4") << QTransform().scale(0.25, 0.25) << qreal(0.25);
+ QTest::newRow("1:2, 1:4") << QTransform().scale(0.5, 0.25) << qreal(::sqrt(0.125));
+ QTest::newRow("4:1, 1:2") << QTransform().scale(0.25, 0.5) << qreal(::sqrt(0.125));
+
+ QTest::newRow("1:2, 1:2") << QTransform().scale(0.5, 0.5) << qreal(0.5);
+ QTest::newRow("1:1, 1:2") << QTransform().scale(1, 0.5) << qreal(::sqrt(0.5));
+ QTest::newRow("2:1, 1:1") << QTransform().scale(0.5, 1) << qreal(::sqrt(0.5));
+
+ QTest::newRow("1:1, 1:1") << QTransform().scale(1, 1) << qreal(1.0);
+ QTest::newRow("2:1, 1:1") << QTransform().scale(2, 1) << qreal(::sqrt(2.0));
+ QTest::newRow("1:1, 2:1") << QTransform().scale(2, 1) << qreal(::sqrt(2.0));
+ QTest::newRow("2:1, 2:1") << QTransform().scale(2, 2) << qreal(2.0);
+ QTest::newRow("2:1, 4:1") << QTransform().scale(2, 4) << qreal(::sqrt(8.0));
+ QTest::newRow("4:1, 2:1") << QTransform().scale(4, 2) << qreal(::sqrt(8.0));
+ QTest::newRow("4:1, 4:1") << QTransform().scale(4, 4) << qreal(4.0);
+}
+
+void tst_QGraphicsView::levelOfDetail()
+{
+ QFETCH(QTransform, transform);
+ QFETCH(qreal, lod);
+
+ LodItem *item = new LodItem(QRectF(0, 0, 100, 100));
+
+ QGraphicsScene scene;
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QTRY_COMPARE(item->lastLod, qreal(1));
+
+ view.setTransform(transform);
+
+ QTRY_COMPARE(item->lastLod, lod);
+}
+
+// Moved to tst_qgraphicsview_2.cpp
+extern void _scrollBarRanges_data();
+
+void tst_QGraphicsView::scrollBarRanges_data()
+{
+ _scrollBarRanges_data();
+}
+
+void tst_QGraphicsView::scrollBarRanges()
+{
+ QFETCH(QSize, viewportSize);
+ QFETCH(QRectF, sceneRect);
+ QFETCH(QTransform, transform);
+ QFETCH(Qt::ScrollBarPolicy, hbarpolicy);
+ QFETCH(Qt::ScrollBarPolicy, vbarpolicy);
+ QFETCH(int, hmin);
+ QFETCH(int, hmax);
+ QFETCH(int, vmin);
+ QFETCH(int, vmax);
+ QFETCH(bool, useMotif);
+ QFETCH(bool, useStyledPanel);
+
+ QGraphicsScene scene(sceneRect);
+ scene.addRect(sceneRect, QPen(Qt::blue), QBrush(QColor(Qt::green)));
+ QGraphicsView view(&scene);
+ view.setRenderHint(QPainter::Antialiasing);
+ view.setTransform(transform);
+ view.setFrameStyle(useStyledPanel ? QFrame::StyledPanel : QFrame::NoFrame);
+
+ if (useMotif) {
+#if !defined(QT_NO_STYLE_MOTIF)
+ view.setStyle(new QMotifStyle);
+#else
+ QSKIP("No Motif style compiled.", SkipSingle);
+#endif
+ } else {
+#if defined(Q_OS_WINCE)
+ view.setStyle(new QWindowsStyle);
+#elif !defined(QT_NO_STYLE_PLASTIQUE)
+ view.setStyle(new QPlastiqueStyle);
+#endif
+ }
+ view.setStyleSheet(" "); // enables style propagation ;-)
+
+ int adjust = 0;
+ if (useStyledPanel)
+ adjust = view.style()->pixelMetric(QStyle::PM_DefaultFrameWidth) * 2;
+ view.resize(viewportSize + QSize(adjust, adjust));
+
+ view.setHorizontalScrollBarPolicy(hbarpolicy);
+ view.setVerticalScrollBarPolicy(vbarpolicy);
+
+ view.show();
+
+ QCOMPARE(view.horizontalScrollBar()->minimum(), hmin);
+ QCOMPARE(view.verticalScrollBar()->minimum(), vmin);
+ QCOMPARE(view.horizontalScrollBar()->maximum(), hmax);
+ QCOMPARE(view.verticalScrollBar()->maximum(), vmax);
+}
+
+class TestView : public QGraphicsView
+{
+public:
+ TestView(QGraphicsScene *scene)
+ : QGraphicsView(scene), accepted(false)
+ { }
+
+ bool accepted;
+
+protected:
+ void mousePressEvent(QMouseEvent *event)
+ {
+ QGraphicsView::mousePressEvent(event);
+ accepted = event->isAccepted();
+ }
+};
+
+void tst_QGraphicsView::acceptMousePressEvent()
+{
+ QGraphicsScene scene;
+
+ TestView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QMouseEvent event(QEvent::MouseButtonPress,
+ view.viewport()->rect().center(),
+ view.viewport()->mapToGlobal(view.viewport()->rect().center()),
+ Qt::LeftButton, 0, 0);
+ event.setAccepted(false);
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(!view.accepted);
+
+ scene.addRect(0, 0, 2000, 2000)->setFlag(QGraphicsItem::ItemIsMovable);
+
+ qApp->processEvents(); // ensure scene rect is updated
+
+ QApplication::sendEvent(view.viewport(), &event);
+ QVERIFY(view.accepted);
+}
+
+void tst_QGraphicsView::replayMouseMove()
+{
+ // An empty scene in a view. The view will send the events to the scene in
+ // any case. Note that the view doesn't have to be shown - the mouse event
+ // sending functions below send the events directly to the viewport.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+
+ EventSpy sceneSpy(&scene, QEvent::GraphicsSceneMouseMove);
+ EventSpy viewSpy(view.viewport(), QEvent::MouseMove);
+
+ sendMousePress(view.viewport(), view.viewport()->rect().center());
+
+ // One mouse event should be translated into one scene event.
+ for (int i = 0; i < 3; ++i) {
+ sendMouseMove(view.viewport(), view.viewport()->rect().center(),
+ Qt::LeftButton, Qt::MouseButtons(Qt::LeftButton));
+ QCOMPARE(viewSpy.count(), i + 1);
+ QCOMPARE(sceneSpy.count(), i + 1);
+ }
+
+ // When the view is transformed, the view should get no more events. But
+ // the scene should get replays.
+ for (int i = 0; i < 3; ++i) {
+ view.rotate(10);
+ QCOMPARE(viewSpy.count(), 3);
+ QCOMPARE(sceneSpy.count(), 3 + i + 1);
+ }
+
+ // When the view is scrolled, the view should get no more events. But the
+ // scene should get replays.
+ for (int i = 0; i < 3; ++i) {
+ view.horizontalScrollBar()->setValue((i + 1) * 10);
+ QCOMPARE(viewSpy.count(), 3);
+ QCOMPARE(sceneSpy.count(), 6 + i + 1);
+ }
+}
+
+void tst_QGraphicsView::itemsUnderMouse()
+{
+ QGraphicsScene scene;
+ QGraphicsProxyWidget w;
+ w.setWidget(new QPushButton("W"));
+ w.resize(50,50);
+ QGraphicsProxyWidget w2(&w);
+ w2.setWidget(new QPushButton("W2"));
+ w2.resize(50,50);
+ QGraphicsProxyWidget w3(&w2);
+ w3.setWidget(new QPushButton("W3"));
+ w3.resize(50,50);
+ w.setZValue(150);
+ w2.setZValue(50);
+ w3.setZValue(0);
+ scene.addItem(&w);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QCOMPARE(view.items(view.mapFromScene(w3.boundingRect().center())).first(),
+ static_cast<QGraphicsItem *>(&w3));
+ w2.setFlag(QGraphicsItem::ItemIgnoresTransformations, true);
+ QCOMPARE(view.items(view.mapFromScene(w3.boundingRect().center())).first(),
+ static_cast<QGraphicsItem *>(&w3));
+}
+
+class QGraphicsTextItem_task172231 : public QGraphicsTextItem
+{
+public:
+ QGraphicsTextItem_task172231(const QString & text, QGraphicsItem * parent = 0)
+ : QGraphicsTextItem(text, parent) {}
+ QRectF exposedRect;
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ exposedRect = option->exposedRect;
+ QGraphicsTextItem::paint(painter, option, widget);
+ }
+};
+
+void tst_QGraphicsView::task172231_untransformableItems()
+{
+ // check fix in QGraphicsView::paintEvent()
+
+ QGraphicsScene scene;
+
+ QGraphicsTextItem_task172231 *text =
+ new QGraphicsTextItem_task172231("abcdefghijklmnopqrstuvwxyz");
+ text->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+ scene.addItem(text);
+
+ QGraphicsView view(&scene);
+
+ view.scale(2, 1);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::setActiveWindow(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
+
+ QRectF origExposedRect = text->exposedRect;
+
+ view.resize(int(0.75 * view.width()), view.height());
+ qApp->processEvents();
+
+ QCOMPARE(text->exposedRect, origExposedRect);
+
+ // notice that the fix also goes into QGraphicsView::render()
+ // and QGraphicsScene::render(), but in duplicated code that
+ // is pending a refactoring, so for now we omit autotesting
+ // these functions separately
+}
+
+class MousePressReleaseScene : public QGraphicsScene
+{
+public:
+ MousePressReleaseScene()
+ : presses(0), releases(0)
+ { }
+ int presses;
+ int releases;
+
+protected:
+ void mousePressEvent(QGraphicsSceneMouseEvent *event)
+ { ++presses; QGraphicsScene::mousePressEvent(event); }
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+ { ++releases; QGraphicsScene::mouseReleaseEvent(event); }
+};
+
+void tst_QGraphicsView::task180429_mouseReleaseDragMode()
+{
+ MousePressReleaseScene scene;
+
+ QGraphicsView view(&scene);
+ view.show();
+
+ sendMousePress(view.viewport(), view.viewport()->rect().center());
+ QCOMPARE(scene.presses, 1);
+ QCOMPARE(scene.releases, 0);
+ sendMouseRelease(view.viewport(), view.viewport()->rect().center());
+ QCOMPARE(scene.presses, 1);
+ QCOMPARE(scene.releases, 1);
+
+ view.setDragMode(QGraphicsView::RubberBandDrag);
+ sendMousePress(view.viewport(), view.viewport()->rect().center());
+ QCOMPARE(scene.presses, 2);
+ QCOMPARE(scene.releases, 1);
+ sendMouseRelease(view.viewport(), view.viewport()->rect().center());
+ QCOMPARE(scene.presses, 2);
+ QCOMPARE(scene.releases, 2);
+}
+
+void tst_QGraphicsView::task187791_setSceneCausesUpdate()
+{
+ QGraphicsScene scene(0, 0, 200, 200);
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ EventSpy updateSpy(view.viewport(), QEvent::Paint);
+ QCOMPARE(updateSpy.count(), 0);
+
+ view.setScene(0);
+ QApplication::processEvents();
+ QTRY_COMPARE(updateSpy.count(), 1);
+ view.setScene(&scene);
+ QApplication::processEvents();
+ QTRY_COMPARE(updateSpy.count(), 2);
+}
+
+class MouseMoveCounter : public QGraphicsView
+{
+public:
+ MouseMoveCounter() : mouseMoves(0)
+ { }
+ int mouseMoves;
+protected:
+ void mouseMoveEvent(QMouseEvent *event)
+ {
+ ++mouseMoves;
+ QGraphicsView::mouseMoveEvent(event);
+ foreach (QGraphicsItem *item, scene()->items()) {
+ scene()->removeItem(item);
+ delete item;
+ }
+ scene()->addRect(0, 0, 50, 50);
+ scene()->addRect(0, 0, 100, 100);
+ }
+};
+
+void tst_QGraphicsView::task186827_deleteReplayedItem()
+{
+ // make sure the mouse is not over the window, causing spontaneous mouse moves
+ QCursor::setPos(1, 1);
+
+ QGraphicsScene scene;
+ scene.addRect(0, 0, 50, 50);
+ scene.addRect(0, 0, 100, 100);
+
+ MouseMoveCounter view;
+ view.setScene(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ view.viewport()->setMouseTracking(true);
+
+ QCOMPARE(view.mouseMoves, 0);
+ {
+ QMouseEvent event(QEvent::MouseMove, view.mapFromScene(25, 25), Qt::NoButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &event);
+ }
+ QCOMPARE(view.mouseMoves, 1);
+ QTest::qWait(25);
+ QTRY_COMPARE(view.mouseMoves, 1);
+ QTest::qWait(25);
+ {
+ QMouseEvent event(QEvent::MouseMove, view.mapFromScene(25, 25), Qt::NoButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &event);
+ }
+ QCOMPARE(view.mouseMoves, 2);
+ QTest::qWait(15);
+}
+
+void tst_QGraphicsView::task207546_focusCrash()
+{
+ class _Widget : public QWidget
+ {
+ public:
+ bool focusNextPrevChild(bool next) { return QWidget::focusNextPrevChild(next); }
+ } widget;
+
+ widget.setLayout(new QVBoxLayout());
+ QGraphicsView *gr1 = new QGraphicsView(&widget);
+ QGraphicsView *gr2 = new QGraphicsView(&widget);
+ widget.layout()->addWidget(gr1);
+ widget.layout()->addWidget(gr2);
+ widget.show();
+ QTest::qWaitForWindowShown(&widget);
+ widget.activateWindow();
+ QApplication::setActiveWindow(&widget);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&widget));
+ widget.focusNextPrevChild(true);
+ QCOMPARE(static_cast<QWidget *>(gr2), widget.focusWidget());
+}
+
+void tst_QGraphicsView::task210599_unsetDragWhileDragging()
+{
+ QGraphicsScene scene(0, 0, 400, 400);
+ QGraphicsView view(&scene);
+ view.setGeometry(0, 0, 200, 200);
+ view.show();
+
+ QPoint origPos = QPoint(100, 100);
+ QPoint step1Pos = QPoint(100, 110);
+ QPoint step2Pos = QPoint(100, 120);
+
+ // Enable and do a drag
+ {
+ view.setDragMode(QGraphicsView::ScrollHandDrag);
+ QMouseEvent press(QEvent::MouseButtonPress, origPos, Qt::LeftButton, 0, 0);
+ QMouseEvent move(QEvent::MouseMove, step1Pos, Qt::LeftButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &press);
+ QApplication::sendEvent(view.viewport(), &move);
+ }
+
+ // unset drag and release mouse, inverse order
+ {
+ view.setDragMode(QGraphicsView::NoDrag);
+ QMouseEvent release(QEvent::MouseButtonRelease, step1Pos, Qt::LeftButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &release);
+ }
+
+ QPoint basePos = view.mapFromScene(0, 0);
+
+ // reset drag, and move mouse without holding button down.
+ {
+ view.setDragMode(QGraphicsView::ScrollHandDrag);
+ QMouseEvent move(QEvent::MouseMove, step2Pos, Qt::LeftButton, 0, 0);
+ QApplication::sendEvent(view.viewport(), &move);
+ }
+
+ // Check that no draggin has occurred...
+ QCOMPARE(basePos, view.mapFromScene(0, 0));
+}
+
+void tst_QGraphicsView::task236394_sendShortcutOverrideEvent()
+{
+ QGraphicsView view;
+ view.show();
+ QKeyEvent event(QEvent::ShortcutOverride, Qt::Key_A, 0, QString("A"));
+ QApplication::sendEvent(&view, &event);
+}
+
+class ChangedListener : public QObject
+{
+ Q_OBJECT
+public:
+ QList<QList<QRectF> > changes;
+
+public slots:
+ void changed(const QList<QRectF> &dirty)
+ {
+ changes << dirty;
+ }
+};
+
+void tst_QGraphicsView::task239729_noViewUpdate_data()
+{
+ QTest::addColumn<bool>("a");
+
+ QTest::newRow("a") << false;
+ QTest::newRow("b") << true;
+}
+
+void tst_QGraphicsView::task239729_noViewUpdate()
+{
+ QFETCH(bool, a);
+ // The scene's changed signal is connected to something that isn't a view.
+ QGraphicsScene scene;
+ ChangedListener cl;
+ QGraphicsView *view = 0;
+
+ if (a) {
+ view = new QGraphicsView(&scene);
+ connect(&scene, SIGNAL(changed(const QList<QRectF> &)), &cl, SLOT(changed(const QList<QRectF> &)));
+ } else {
+ connect(&scene, SIGNAL(changed(const QList<QRectF> &)), &cl, SLOT(changed(const QList<QRectF> &)));
+ view = new QGraphicsView(&scene);
+ }
+
+ EventSpy spy(view->viewport(), QEvent::Paint);
+ QCOMPARE(spy.count(), 0);
+
+ view->show();
+ QTest::qWaitForWindowShown(view);
+
+ QTRY_VERIFY(spy.count() >= 1);
+ spy.reset();
+ scene.update();
+ QApplication::processEvents();
+ QTRY_COMPARE(spy.count(), 1);
+
+ delete view;
+}
+
+void tst_QGraphicsView::task239047_fitInViewSmallViewport()
+{
+ // Ensure that with a small viewport, fitInView doesn't mirror the
+ // scene.
+ QWidget widget;
+ QGraphicsScene scene;
+ QGraphicsView *view = new QGraphicsView(&scene, &widget);
+ view->resize(3, 3);
+ QCOMPARE(view->size(), QSize(3, 3));
+ widget.show();
+ view->fitInView(0, 0, 100, 100);
+ QPointF topLeft = view->mapToScene(0, 0);
+ QPointF bottomRight = view->mapToScene(100, 100);
+ QVERIFY(bottomRight.x() > topLeft.x());
+ QVERIFY(bottomRight.y() > topLeft.y());
+
+ view->fitInView(0, 0, 0, 100);
+
+ // Don't crash
+ view->scale(0, 0);
+ view->fitInView(0, 0, 100, 100);
+}
+
+void tst_QGraphicsView::task245469_itemsAtPointWithClip()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *parent = scene.addRect(0, 0, 100, 100);
+ QGraphicsItem *child = new QGraphicsRectItem(40, 40, 20, 20, parent);
+ parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+
+ QGraphicsView view(&scene);
+ view.resize(150,150);
+ view.rotate(90);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QList<QGraphicsItem *> itemsAtCenter = view.items(view.viewport()->rect().center());
+ QCOMPARE(itemsAtCenter, (QList<QGraphicsItem *>() << child << parent));
+
+ QPolygonF p = view.mapToScene(QRect(view.viewport()->rect().center(), QSize(1, 1)));
+ QList<QGraphicsItem *> itemsAtCenter2 = scene.items(p);
+ QCOMPARE(itemsAtCenter2, itemsAtCenter);
+}
+
+static QGraphicsView *createSimpleViewAndScene()
+{
+ QGraphicsView *view = new QGraphicsView;
+ QGraphicsScene *scene = new QGraphicsScene;
+ view->setScene(scene);
+
+ view->setBackgroundBrush(Qt::blue);
+
+ QGraphicsRectItem *rect = scene->addRect(0, 0, 10, 10);
+ rect->setBrush(Qt::red);
+ rect->setPen(Qt::NoPen);
+ return view;
+}
+
+class SpyItem : public QGraphicsRectItem
+{
+public:
+ SpyItem()
+ : QGraphicsRectItem(QRectF(0, 0, 100, 100))
+ {
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ {
+ transform = painter->transform();
+ }
+
+ QTransform transform;
+};
+
+void tst_QGraphicsView::embeddedViews()
+{
+ QGraphicsView *v1 = createSimpleViewAndScene();
+ QGraphicsView *v2 = createSimpleViewAndScene();
+
+ QGraphicsProxyWidget *proxy = v1->scene()->addWidget(v2);
+
+ SpyItem *item = new SpyItem;
+ v2->scene()->addItem(item);
+
+ proxy->translate(5, 5);
+
+ QImage actual(64, 64, QImage::Format_ARGB32_Premultiplied);
+ actual.fill(0);
+ v1->QWidget::render(&actual);
+ QTransform a = item->transform;
+
+ v2->QWidget::render(&actual);
+ QTransform b = item->transform;
+
+ QVERIFY(a == b);
+ delete v1;
+}
+
+void tst_QGraphicsView::scrollAfterResize_data()
+{
+ QTest::addColumn<bool>("reverse");
+ QTest::addColumn<QTransform>("x1");
+ QTest::addColumn<QTransform>("x2");
+ QTest::addColumn<QTransform>("x3");
+
+#if !defined(QT_NO_STYLE_PLASTIQUE)
+ QPlastiqueStyle style;
+#elif !defined(QT_NO_STYLE_WINDOWS)
+ QWindowsStyle style;
+#else
+ QCommonStyle style;
+#endif
+
+ int frameWidth = style.pixelMetric(QStyle::PM_DefaultFrameWidth);
+ int extent = style.pixelMetric(QStyle::PM_ScrollBarExtent);
+ int inside = style.styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents);
+ int viewportWidth = 300;
+ int scrollBarIndent = viewportWidth - extent - (inside ? 4 : 2)*frameWidth;
+
+ QTest::newRow("normal") << false
+ << QTransform()
+ << QTransform()
+ << QTransform().translate(-10, 0);
+ QTest::newRow("reverse") << true
+ << QTransform().translate(scrollBarIndent, 0)
+ << QTransform().translate(scrollBarIndent + 100, 0)
+ << QTransform().translate(scrollBarIndent + 110, 0);
+}
+
+void tst_QGraphicsView::scrollAfterResize()
+{
+ QFETCH(bool, reverse);
+ QFETCH(QTransform, x1);
+ QFETCH(QTransform, x2);
+ QFETCH(QTransform, x3);
+
+#if !defined(QT_NO_STYLE_PLASTIQUE)
+ QPlastiqueStyle style;
+#elif !defined(QT_NO_STYLE_WINDOWS)
+ QWindowsStyle style;
+#else
+ QCommonStyle style;
+#endif
+ QWidget toplevel;
+
+ QGraphicsView view(&toplevel);
+ view.setStyle(&style);
+ if (reverse)
+ view.setLayoutDirection(Qt::RightToLeft);
+
+ view.setSceneRect(-1000, -1000, 2000, 2000);
+ view.resize(300, 300);
+ toplevel.show();
+ QTest::qWaitForWindowShown(&toplevel);
+ view.horizontalScrollBar()->setValue(0);
+ view.verticalScrollBar()->setValue(0);
+ QCOMPARE(view.viewportTransform(), x1);
+ view.resize(400, 300);
+ QCOMPARE(view.viewportTransform(), x2);
+ view.horizontalScrollBar()->setValue(10);
+ QCOMPARE(view.viewportTransform(), x3);
+}
+
+void tst_QGraphicsView::moveItemWhileScrolling_data()
+{
+ QTest::addColumn<bool>("adjustForAntialiasing");
+ QTest::addColumn<bool>("changedConnected");
+
+ QTest::newRow("no adjust") << false << false;
+ QTest::newRow("adjust") << true << false;
+ QTest::newRow("no adjust changedConnected") << false << true;
+ QTest::newRow("adjust changedConnected") << true << true;
+}
+
+void tst_QGraphicsView::moveItemWhileScrolling()
+{
+ QFETCH(bool, adjustForAntialiasing);
+ QFETCH(bool, changedConnected);
+
+ class MoveItemScrollView : public QGraphicsView
+ {
+ public:
+ MoveItemScrollView()
+ {
+ setWindowFlags(Qt::X11BypassWindowManagerHint);
+ setScene(new QGraphicsScene(0, 0, 1000, 1000));
+ rect = scene()->addRect(0, 0, 10, 10);
+ rect->setPos(50, 50);
+ painted = false;
+ }
+ QRegion lastPaintedRegion;
+ QGraphicsItem *rect;
+ bool painted;
+ void waitForPaintEvent()
+ {
+ QTimer::singleShot(2000, &eventLoop, SLOT(quit()));
+ eventLoop.exec();
+ }
+ protected:
+ QEventLoop eventLoop;
+ void paintEvent(QPaintEvent *event)
+ {
+ painted = true;
+ lastPaintedRegion = event->region();
+ QGraphicsView::paintEvent(event);
+ if (eventLoop.isRunning())
+ eventLoop.quit();
+ }
+ };
+
+ MoveItemScrollView view;
+ view.setFrameStyle(0);
+ view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ view.setResizeAnchor(QGraphicsView::NoAnchor);
+ view.setTransformationAnchor(QGraphicsView::NoAnchor);
+ if (!adjustForAntialiasing)
+ view.setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing);
+ view.resize(200, 200);
+ view.painted = false;
+ view.show();
+ if (changedConnected)
+ QObject::connect(view.scene(), SIGNAL(changed(QList<QRectF>)), this, SLOT(dummySlot()));
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
+ QTRY_VERIFY(view.painted);
+ view.painted = false;
+ view.lastPaintedRegion = QRegion();
+ view.horizontalScrollBar()->setValue(view.horizontalScrollBar()->value() + 10);
+ view.rect->moveBy(0, 10);
+ view.waitForPaintEvent();
+ QTRY_VERIFY(view.painted);
+
+ QRegion expectedRegion;
+ expectedRegion += QRect(0, 0, 200, 200);
+ expectedRegion -= QRect(0, 0, 190, 200);
+ int a = adjustForAntialiasing ? 2 : 1;
+ expectedRegion += QRect(40, 50, 10, 10).adjusted(-a, -a, a, a);
+ expectedRegion += QRect(40, 60, 10, 10).adjusted(-a, -a, a, a);
+#ifdef Q_OS_MAC
+ QEXPECT_FAIL("", "This will fail with Cocoa because paint events are not send in the order expected by graphicsview", Continue);
+#endif
+ COMPARE_REGIONS(view.lastPaintedRegion, expectedRegion);
+}
+
+void tst_QGraphicsView::centerOnDirtyItem()
+{
+ QWidget toplevel;
+
+ QGraphicsView view(&toplevel);
+ toplevel.setWindowFlags(view.windowFlags() | Qt::WindowStaysOnTopHint);
+ view.resize(200, 200);
+
+ QGraphicsScene *scene = new QGraphicsScene;
+ view.setScene(scene);
+ view.setSceneRect(-1000, -1000, 2000, 2000);
+
+ QGraphicsRectItem *item = new QGraphicsRectItem(0, 0, 10, 10);
+ item->setBrush(Qt::red);
+ scene->addItem(item);
+ view.centerOn(item);
+
+ toplevel.show();
+ QTest::qWaitForWindowShown(&toplevel);
+ QTest::qWait(50);
+
+ QImage before(view.viewport()->size(), QImage::Format_ARGB32);
+ view.viewport()->render(&before);
+
+ item->setPos(20, 0);
+ view.centerOn(item);
+
+ QTest::qWait(50);
+
+ QImage after(view.viewport()->size(), QImage::Format_ARGB32);
+ view.viewport()->render(&after);
+
+ QCOMPARE(before, after);
+}
+
+void tst_QGraphicsView::mouseTracking()
+{
+ // Mouse tracking should only be automatically enabled if items either accept hover events
+ // or have a cursor set. We never disable mouse tracking if it is already enabled.
+
+ { // Make sure mouse tracking is disabled by default.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+ QVERIFY(!view.viewport()->hasMouseTracking());
+ }
+
+ { // Make sure we don't disable mouse tracking in setupViewport/setScene.
+ QGraphicsView view;
+ QWidget *viewport = new QWidget;
+ viewport->setMouseTracking(true);
+ view.setViewport(viewport);
+ QVERIFY(viewport->hasMouseTracking());
+
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ view.setScene(&scene);
+ QVERIFY(viewport->hasMouseTracking());
+ }
+
+ // Make sure we enable mouse tracking when having items that accept hover events.
+ {
+ // Adding an item to the scene after the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ item->setAcceptHoverEvents(true);
+ scene.addItem(item);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+ {
+ // Adding an item to the scene before the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ item->setAcceptHoverEvents(true);
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+ {
+ // QGraphicsWidget implicitly accepts hover if it has window decoration.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ scene.addItem(widget);
+ QVERIFY(!view.viewport()->hasMouseTracking());
+ // Enable window decoraton.
+ widget->setWindowFlags(Qt::Window | Qt::WindowTitleHint);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+
+ // Make sure we enable mouse tracking when having items with a cursor set.
+ {
+ // Adding an item to the scene after the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+#ifndef QT_NO_CURSOR
+ item->setCursor(Qt::CrossCursor);
+#endif
+ scene.addItem(item);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+ {
+ // Adding an item to the scene before the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+#ifndef QT_NO_CURSOR
+ item->setCursor(Qt::CrossCursor);
+#endif
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+
+ // Make sure we propagate mouse tracking to all views.
+ {
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view1(&scene);
+ QGraphicsView view2(&scene);
+ QGraphicsView view3(&scene);
+
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+#ifndef QT_NO_CURSOR
+ item->setCursor(Qt::CrossCursor);
+#endif
+ scene.addItem(item);
+
+ QVERIFY(view1.viewport()->hasMouseTracking());
+ QVERIFY(view2.viewport()->hasMouseTracking());
+ QVERIFY(view3.viewport()->hasMouseTracking());
+ }
+}
+
+void tst_QGraphicsView::mouseTracking2()
+{
+ // Make sure mouse move events propagates to the scene when
+ // mouse tracking is explicitly enabled on the view,
+ // even when all items ignore hover events / use default cursor.
+
+ QGraphicsScene scene;
+ scene.addRect(0, 0, 100, 100);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QVERIFY(!view.viewport()->hasMouseTracking());
+ view.viewport()->setMouseTracking(true); // Explicitly enable mouse tracking.
+ QVERIFY(view.viewport()->hasMouseTracking());
+
+ EventSpy spy(&scene, QEvent::GraphicsSceneMouseMove);
+ QCOMPARE(spy.count(), 0);
+ QMouseEvent event(QEvent::MouseMove,view.viewport()->rect().center(), Qt::NoButton,
+ Qt::MouseButtons(Qt::NoButton), 0);
+ QApplication::sendEvent(view.viewport(), &event);
+ QCOMPARE(spy.count(), 1);
+}
+
+void tst_QGraphicsView::mouseTracking3()
+{
+ // Mouse tracking should be automatically enabled if AnchorUnderMouse is used for
+ // view transform or resize. We never disable mouse tracking if it is already enabled.
+
+ { // Make sure we enable mouse tracking when using AnchorUnderMouse for view transformation.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+ QVERIFY(!view.viewport()->hasMouseTracking());
+
+ view.setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+
+ { // Make sure we enable mouse tracking when using AnchorUnderMouse for view resizing.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+ QVERIFY(!view.viewport()->hasMouseTracking());
+
+ view.setResizeAnchor(QGraphicsView::AnchorUnderMouse);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+
+ { // Make sure we don't disable mouse tracking in setViewport/setScene (transformation anchor).
+ QGraphicsView view;
+ view.setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
+ QVERIFY(view.viewport()->hasMouseTracking());
+
+ QWidget *viewport = new QWidget;
+ view.setViewport(viewport);
+ QVERIFY(viewport->hasMouseTracking());
+
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ view.setScene(&scene);
+ QVERIFY(viewport->hasMouseTracking());
+ }
+
+ { // Make sure we don't disable mouse tracking in setViewport/setScene (resize anchor).
+ QGraphicsView view;
+ view.setResizeAnchor(QGraphicsView::AnchorUnderMouse);
+ QVERIFY(view.viewport()->hasMouseTracking());
+
+ QWidget *viewport = new QWidget;
+ view.setViewport(viewport);
+ QVERIFY(viewport->hasMouseTracking());
+
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ view.setScene(&scene);
+ QVERIFY(viewport->hasMouseTracking());
+ }
+
+ // Make sure we don't disable mouse tracking when adding an item (transformation anchor).
+ { // Adding an item to the scene before the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ scene.addItem(item);
+
+ QGraphicsView view;
+ view.setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
+ view.setScene(&scene);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+
+ { // Adding an item to the scene after the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+ view.setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
+
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ scene.addItem(item);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+
+ // Make sure we don't disable mouse tracking when adding an item (resize anchor).
+ { // Adding an item to the scene before the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ scene.addItem(item);
+
+ QGraphicsView view;
+ view.setResizeAnchor(QGraphicsView::AnchorUnderMouse);
+ view.setScene(&scene);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+
+ { // Adding an item to the scene after the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+ view.setResizeAnchor(QGraphicsView::AnchorUnderMouse);
+
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ scene.addItem(item);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+}
+
+class RenderTester : public QGraphicsRectItem
+{
+public:
+ RenderTester(const QRectF &rect)
+ : QGraphicsRectItem(rect), paints(0)
+ { }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
+ QWidget *widget)
+ {
+ QGraphicsRectItem::paint(painter, option, widget);
+ ++paints;
+ }
+
+ int paints;
+};
+
+void tst_QGraphicsView::render()
+{
+ // ### This test can be much more thorough - see QGraphicsScene::render.
+ QGraphicsScene scene;
+ CustomView view(&scene);
+ view.setFrameStyle(0);
+ view.resize(200, 200);
+ view.painted = false;
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::processEvents();
+ QTRY_VERIFY(view.painted > 0);
+
+ RenderTester *r1 = new RenderTester(QRectF(0, 0, 50, 50));
+ RenderTester *r2 = new RenderTester(QRectF(50, 50, 50, 50));
+ RenderTester *r3 = new RenderTester(QRectF(0, 50, 50, 50));
+ RenderTester *r4 = new RenderTester(QRectF(50, 0, 50, 50));
+ scene.addItem(r1);
+ scene.addItem(r2);
+ scene.addItem(r3);
+ scene.addItem(r4);
+
+ qApp->processEvents();
+
+ QTRY_COMPARE(r1->paints, 1);
+ QCOMPARE(r2->paints, 1);
+ QCOMPARE(r3->paints, 1);
+ QCOMPARE(r4->paints, 1);
+
+ QPixmap pix(200, 200);
+ pix.fill(Qt::transparent);
+ QPainter painter(&pix);
+ view.render(&painter);
+ painter.end();
+
+ QCOMPARE(r1->paints, 2);
+ QCOMPARE(r2->paints, 2);
+ QCOMPARE(r3->paints, 2);
+ QCOMPARE(r4->paints, 2);
+}
+
+void tst_QGraphicsView::exposeRegion()
+{
+ RenderTester *item = new RenderTester(QRectF(0, 0, 20, 20));
+ QGraphicsScene scene;
+ scene.addItem(item);
+
+ item->paints = 0;
+ CustomView view;
+ view.setScene(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(item->paints > 0);
+
+ item->paints = 0;
+ view.lastUpdateRegions.clear();
+
+ // Update a small area in the viewport's topLeft() and bottomRight().
+ // (the boundingRect() of this area covers the entire viewport).
+ QWidget *viewport = view.viewport();
+ QRegion expectedExposeRegion = QRect(0, 0, 5, 5);
+ expectedExposeRegion += QRect(viewport->rect().bottomRight() - QPoint(5, 5), QSize(5, 5));
+ viewport->update(expectedExposeRegion);
+ QApplication::processEvents();
+
+ // Make sure it triggers correct repaint on the view.
+ QTRY_COMPARE(view.lastUpdateRegions.size(), 1);
+ COMPARE_REGIONS(view.lastUpdateRegions.at(0), expectedExposeRegion);
+
+ // Make sure the item didn't get any repaints.
+#ifndef Q_OS_MAC
+ QCOMPARE(item->paints, 0);
+#endif
+}
+
+void tst_QGraphicsView::update_data()
+{
+ // In view.viewport() coordinates. (viewport rect: QRect(0, 0, 200, 200))
+ QTest::addColumn<QRect>("updateRect");
+ QTest::newRow("empty") << QRect();
+ QTest::newRow("outside left") << QRect(-200, 0, 100, 100);
+ QTest::newRow("outside right") << QRect(400, 0 ,100, 100);
+ QTest::newRow("outside top") << QRect(0, -200, 100, 100);
+ QTest::newRow("outside bottom") << QRect(0, 400, 100, 100);
+ QTest::newRow("partially inside left") << QRect(-50, 0, 100, 100);
+ QTest::newRow("partially inside right") << QRect(-150, 0, 100, 100);
+ QTest::newRow("partially inside top") << QRect(0, -150, 100, 100);
+ QTest::newRow("partially inside bottom") << QRect(0, 150, 100, 100);
+ QTest::newRow("on topLeft edge") << QRect(-100, -100, 100, 100);
+ QTest::newRow("on topRight edge") << QRect(200, -100, 100, 100);
+ QTest::newRow("on bottomRight edge") << QRect(200, 200, 100, 100);
+ QTest::newRow("on bottomLeft edge") << QRect(-200, 200, 100, 100);
+ QTest::newRow("inside topLeft") << QRect(-99, -99, 100, 100);
+ QTest::newRow("inside topRight") << QRect(199, -99, 100, 100);
+ QTest::newRow("inside bottomRight") << QRect(199, 199, 100, 100);
+ QTest::newRow("inside bottomLeft") << QRect(-199, 199, 100, 100);
+ QTest::newRow("large1") << QRect(50, -100, 100, 400);
+ QTest::newRow("large2") << QRect(-100, 50, 400, 100);
+ QTest::newRow("large3") << QRect(-100, -100, 400, 400);
+ QTest::newRow("viewport rect") << QRect(0, 0, 200, 200);
+}
+
+void tst_QGraphicsView::update()
+{
+ QFETCH(QRect, updateRect);
+
+ // some window manager resize the toplevel to max screen size
+ // so we must make our view a child (no layout!) of a dummy toplevel
+ // to ensure that it's really 200x200 pixels
+ QWidget toplevel;
+
+ // Create a view with viewport rect equal to QRect(0, 0, 200, 200).
+ QGraphicsScene dummyScene;
+ CustomView view(0, &toplevel);
+ view.setScene(&dummyScene);
+ view.ensurePolished(); // must ensure polished to get content margins right
+ int left, top, right, bottom;
+ view.getContentsMargins(&left, &top, &right, &bottom);
+ view.resize(200 + left + right, 200 + top + bottom);
+ toplevel.show();
+ QTest::qWaitForWindowShown(&toplevel);
+
+
+ QApplication::setActiveWindow(&toplevel);
+ QApplication::processEvents();
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&toplevel));
+
+ const QRect viewportRect = view.viewport()->rect();
+ QCOMPARE(viewportRect, QRect(0, 0, 200, 200));
+
+#if defined QT_BUILD_INTERNAL
+ const bool intersects = updateRect.intersects(viewportRect);
+ QGraphicsViewPrivate *viewPrivate = static_cast<QGraphicsViewPrivate *>(qt_widget_private(&view));
+ QTRY_COMPARE(viewPrivate->updateRect(updateRect), intersects);
+ QApplication::processEvents();
+
+ view.lastUpdateRegions.clear();
+ viewPrivate->processPendingUpdates();
+ QVERIFY(viewPrivate->dirtyRegion.isEmpty());
+ QVERIFY(viewPrivate->dirtyBoundingRect.isEmpty());
+ QApplication::processEvents();
+ if (!intersects) {
+ QTRY_VERIFY(view.lastUpdateRegions.isEmpty());
+ } else {
+ QTRY_COMPARE(view.lastUpdateRegions.size(), 1);
+ QTRY_COMPARE(view.lastUpdateRegions.at(0), QRegion(updateRect) & viewportRect);
+ }
+ QTRY_VERIFY(!viewPrivate->fullUpdatePending);
+#endif
+}
+
+void tst_QGraphicsView::update2_data()
+{
+ QTest::addColumn<qreal>("penWidth");
+ QTest::addColumn<bool>("antialiasing");
+ QTest::addColumn<bool>("changedConnected");
+
+ // Anti-aliased.
+ QTest::newRow("pen width: 0.0, antialiasing: true") << qreal(0.0) << true << false;
+ QTest::newRow("pen width: 1.5, antialiasing: true") << qreal(1.5) << true << false;
+ QTest::newRow("pen width: 2.0, antialiasing: true") << qreal(2.0) << true << false;
+ QTest::newRow("pen width: 3.0, antialiasing: true") << qreal(3.0) << true << false;
+
+ // Aliased.
+ QTest::newRow("pen width: 0.0, antialiasing: false") << qreal(0.0) << false << false;
+ QTest::newRow("pen width: 1.5, antialiasing: false") << qreal(1.5) << false << false;
+ QTest::newRow("pen width: 2.0, antialiasing: false") << qreal(2.0) << false << false;
+ QTest::newRow("pen width: 3.0, antialiasing: false") << qreal(3.0) << false << false;
+
+ // changed() connected
+ QTest::newRow("pen width: 0.0, antialiasing: false, changed") << qreal(0.0) << false << true;
+ QTest::newRow("pen width: 1.5, antialiasing: true, changed") << qreal(1.5) << true << true;
+ QTest::newRow("pen width: 2.0, antialiasing: false, changed") << qreal(2.0) << false << true;
+ QTest::newRow("pen width: 3.0, antialiasing: true, changed") << qreal(3.0) << true << true;
+}
+
+void tst_QGraphicsView::update2()
+{
+ QFETCH(qreal, penWidth);
+ QFETCH(bool, antialiasing);
+ QFETCH(bool, changedConnected);
+
+ // Create a rect item.
+ const QRectF rawItemRect(-50.4, -50.3, 100.2, 100.1);
+ CountPaintItem *rect = new CountPaintItem(rawItemRect);
+ QPen pen;
+ pen.setWidthF(penWidth);
+ rect->setPen(pen);
+
+ // Add item to a scene.
+ QGraphicsScene scene(-100, -100, 200, 200);
+ if (changedConnected)
+ QObject::connect(&scene, SIGNAL(changed(QList<QRectF>)), this, SLOT(dummySlot()));
+
+ scene.addItem(rect);
+
+ // Create a view on the scene.
+ CustomView view(&scene);
+ view.setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing, !antialiasing);
+ view.setRenderHint(QPainter::Antialiasing, antialiasing);
+ view.setFrameStyle(0);
+ view.resize(200, 200);
+ view.show();
+ QTest::qWaitForWindowShown(&view) ;
+ QTRY_VERIFY(rect->numPaints > 0);
+
+ // Calculate expected update region for the rect.
+ QRectF expectedItemBoundingRect = rawItemRect;
+ const qreal halfPenWidth = penWidth / qreal(2.0);
+ expectedItemBoundingRect.adjust(-halfPenWidth, -halfPenWidth, halfPenWidth, halfPenWidth);
+ QCOMPARE(rect->boundingRect(), expectedItemBoundingRect);
+
+ QRect expectedItemDeviceBoundingRect = rect->deviceTransform(view.viewportTransform())
+ .mapRect(expectedItemBoundingRect).toAlignedRect();
+ if (antialiasing)
+ expectedItemDeviceBoundingRect.adjust(-2, -2, 2, 2);
+ else
+ expectedItemDeviceBoundingRect.adjust(-1, -1, 1, 1);
+ const QRegion expectedUpdateRegion(expectedItemDeviceBoundingRect);
+
+ // Reset.
+ rect->numPaints = 0;
+ view.lastUpdateRegions.clear();
+ view.painted = false;
+
+ rect->update();
+ QTRY_VERIFY(view.painted);
+
+#ifndef Q_OS_MAC //cocoa doesn't support drawing regions
+ QTRY_VERIFY(view.painted);
+ QCOMPARE(view.lastUpdateRegions.size(), 1);
+ QCOMPARE(view.lastUpdateRegions.at(0), expectedUpdateRegion);
+#endif
+}
+
+void tst_QGraphicsView::update_ancestorClipsChildrenToShape()
+{
+ QGraphicsScene scene(-150, -150, 300, 300);
+
+ /*
+ Add three rects:
+
+ +------------------+
+ | child |
+ | +--------------+ |
+ | | parent | |
+ | | +-----------+ |
+ | | |grandParent| |
+ | | +-----------+ |
+ | +--------------+ |
+ +------------------+
+
+ ... where both the parent and the grand parent clips children to shape.
+ */
+ QApplication::processEvents(); // Get rid of pending update.
+
+ QGraphicsRectItem *grandParent = static_cast<QGraphicsRectItem *>(scene.addRect(0, 0, 50, 50));
+ grandParent->setBrush(Qt::black);
+ grandParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+
+ QGraphicsRectItem *parent = static_cast<QGraphicsRectItem *>(scene.addRect(-50, -50, 100, 100));
+ parent->setBrush(QColor(0, 0, 255, 125));
+ parent->setParentItem(grandParent);
+ parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+
+ QGraphicsRectItem *child = static_cast<QGraphicsRectItem *>(scene.addRect(-100, -100, 200, 200));
+ child->setBrush(QColor(255, 0, 0, 125));
+ child->setParentItem(parent);
+
+ CustomView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.painted);
+
+ view.lastUpdateRegions.clear();
+ view.painted = false;
+
+ // Call child->update() and make sure the updated area is within the ancestors' clip.
+ QRectF expected = child->deviceTransform(view.viewportTransform()).mapRect(child->boundingRect());
+ expected &= grandParent->deviceTransform(view.viewportTransform()).mapRect(grandParent->boundingRect());
+
+ child->update();
+ QTRY_VERIFY(view.painted);
+
+#ifndef Q_OS_MAC //cocoa doesn't support drawing regions
+ QTRY_VERIFY(view.painted);
+ QCOMPARE(view.lastUpdateRegions.size(), 1);
+ QCOMPARE(view.lastUpdateRegions.at(0), QRegion(expected.toAlignedRect()));
+#endif
+}
+
+void tst_QGraphicsView::update_ancestorClipsChildrenToShape2()
+{
+ QGraphicsScene scene(-150, -150, 300, 300);
+
+ /*
+ Add two rects:
+
+ +------------------+
+ | child |
+ | +--------------+ |
+ | | parent | |
+ | | | |
+ | | | |
+ | | | |
+ | +--------------+ |
+ +------------------+
+
+ ... where the parent has no contents and clips the child to shape.
+ */
+ QApplication::processEvents(); // Get rid of pending update.
+
+ QGraphicsRectItem *parent = static_cast<QGraphicsRectItem *>(scene.addRect(-50, -50, 100, 100));
+ parent->setBrush(QColor(0, 0, 255, 125));
+ parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ parent->setFlag(QGraphicsItem::ItemHasNoContents);
+
+ QGraphicsRectItem *child = static_cast<QGraphicsRectItem *>(scene.addRect(-100, -100, 200, 200));
+ child->setBrush(QColor(255, 0, 0, 125));
+ child->setParentItem(parent);
+
+ CustomView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_VERIFY(view.painted);
+
+ view.lastUpdateRegions.clear();
+ view.painted = false;
+
+ // Call child->update() and make sure the updated area is within its parent's clip.
+ QRectF expected = child->deviceTransform(view.viewportTransform()).mapRect(child->boundingRect());
+ expected &= parent->deviceTransform(view.viewportTransform()).mapRect(parent->boundingRect());
+
+ child->update();
+ QTRY_VERIFY(view.painted);
+
+#ifndef Q_OS_MAC //cocoa doesn't support drawing regions
+ QTRY_VERIFY(view.painted);
+ QCOMPARE(view.lastUpdateRegions.size(), 1);
+ QCOMPARE(view.lastUpdateRegions.at(0), QRegion(expected.toAlignedRect()));
+#endif
+
+ QTest::qWait(50);
+
+ view.lastUpdateRegions.clear();
+ view.painted = false;
+
+ // Invalidate the parent's geometry and trigger an update.
+ // The update area should be clipped to the parent's bounding rect for 'normal' items,
+ // but in this case the item has no contents (ItemHasNoContents) and its geometry
+ // is invalidated, which means we cannot clip the child update. So, the expected
+ // area is exactly the same as the child's bounding rect (adjusted for antialiasing).
+ parent->setRect(parent->rect().adjusted(-10, -10, -10, -10));
+ expected = child->deviceTransform(view.viewportTransform()).mapRect(child->boundingRect());
+ expected.adjust(-2, -2, 2, 2); // Antialiasing
+
+#ifndef Q_OS_MAC //cocoa doesn't support drawing regions
+ QTRY_VERIFY(view.painted);
+ QCOMPARE(view.lastUpdateRegions.size(), 1);
+ QCOMPARE(view.lastUpdateRegions.at(0), QRegion(expected.toAlignedRect()));
+#endif
+}
+
+class FocusItem : public QGraphicsRectItem
+{
+public:
+ FocusItem() : QGraphicsRectItem(0, 0, 20, 20) {
+ m_viewHasIMEnabledInFocusInEvent = false;
+ }
+
+ void focusInEvent(QFocusEvent * /* event */)
+ {
+ QGraphicsView *view = scene()->views().first();
+ m_viewHasIMEnabledInFocusInEvent = view->testAttribute(Qt::WA_InputMethodEnabled);
+ }
+
+ bool m_viewHasIMEnabledInFocusInEvent;
+};
+
+void tst_QGraphicsView::inputMethodSensitivity()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::setActiveWindow(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
+
+ FocusItem *item = new FocusItem;
+
+ view.setAttribute(Qt::WA_InputMethodEnabled, true);
+
+ scene.addItem(item);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
+
+ scene.removeItem(item);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
+
+ item->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
+ scene.addItem(item);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
+
+ scene.removeItem(item);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
+
+ scene.addItem(item);
+ scene.setFocusItem(item);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
+
+ scene.removeItem(item);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
+
+ item->setFlag(QGraphicsItem::ItemIsFocusable);
+ scene.addItem(item);
+ scene.setFocusItem(item);
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true);
+ QCOMPARE(item->m_viewHasIMEnabledInFocusInEvent, true);
+
+ item->setFlag(QGraphicsItem::ItemAcceptsInputMethod, false);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
+
+ item->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true);
+
+ // introduce another item that is focusable but does not accept input methods
+ FocusItem *item2 = new FocusItem;
+ item2->setFlag(QGraphicsItem::ItemIsFocusable);
+ scene.addItem(item2);
+ scene.setFocusItem(item2);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
+ QCOMPARE(item2->m_viewHasIMEnabledInFocusInEvent, false);
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item2));
+
+ scene.setFocusItem(item);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true);
+ QCOMPARE(item->m_viewHasIMEnabledInFocusInEvent, true);
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
+
+ view.setScene(0);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
+
+ view.setScene(&scene);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true);
+ QCOMPARE(item->m_viewHasIMEnabledInFocusInEvent, true);
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
+
+ scene.setFocusItem(item2);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
+ QCOMPARE(item2->m_viewHasIMEnabledInFocusInEvent, false);
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item2));
+
+ view.setScene(0);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item2));
+
+ scene.setFocusItem(item);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
+
+ view.setScene(&scene);
+ QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true);
+ QCOMPARE(item->m_viewHasIMEnabledInFocusInEvent, true);
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
+}
+
+class InputContextTester : public QInputContext
+{
+ Q_OBJECT
+public:
+ QString identifierName() { return QString(); }
+ bool isComposing() const { return false; }
+ QString language() { return QString(); }
+ void reset() { ++resets; }
+ int resets;
+};
+
+void tst_QGraphicsView::inputContextReset()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QVERIFY(view.testAttribute(Qt::WA_InputMethodEnabled));
+
+ InputContextTester *inputContext = new InputContextTester;
+ qApp->setInputContext(inputContext);
+
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QApplication::setActiveWindow(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
+
+ QGraphicsItem *item1 = new QGraphicsRectItem;
+ item1->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemAcceptsInputMethod);
+
+ inputContext->resets = 0;
+ scene.addItem(item1);
+ QCOMPARE(inputContext->resets, 0);
+
+ inputContext->resets = 0;
+ scene.setFocusItem(item1);
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *)item1);
+ QVERIFY(view.testAttribute(Qt::WA_InputMethodEnabled));
+ QCOMPARE(inputContext->resets, 0);
+
+ inputContext->resets = 0;
+ scene.setFocusItem(0);
+ // the input context is reset twice, once because an item has lost focus and again because
+ // the Qt::WA_InputMethodEnabled flag is cleared because no item has focus.
+ QCOMPARE(inputContext->resets, 2);
+
+ // introduce another item that is focusable but does not accept input methods
+ QGraphicsItem *item2 = new QGraphicsRectItem;
+ item2->setFlags(QGraphicsItem::ItemIsFocusable);
+ scene.addItem(item2);
+
+ inputContext->resets = 0;
+ scene.setFocusItem(item2);
+ QCOMPARE(inputContext->resets, 0);
+
+ inputContext->resets = 0;
+ scene.setFocusItem(item1);
+ QCOMPARE(inputContext->resets, 0);
+
+ // test changing between between items that accept input methods.
+ item2->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemAcceptsInputMethod);
+ scene.setFocusItem(item2);
+ QCOMPARE(inputContext->resets, 1);
+}
+
+void tst_QGraphicsView::indirectPainting()
+{
+ class MyScene : public QGraphicsScene
+ { public:
+ MyScene() : QGraphicsScene(), drawCount(0) {}
+ void drawItems(QPainter *, int, QGraphicsItem **, const QStyleOptionGraphicsItem *, QWidget *)
+ { ++drawCount; }
+ int drawCount;
+ };
+
+ MyScene scene;
+ QGraphicsItem *item = scene.addRect(0, 0, 50, 50);
+
+ QGraphicsView view(&scene);
+ view.setOptimizationFlag(QGraphicsView::IndirectPainting);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(100);
+
+ scene.drawCount = 0;
+ item->setPos(20, 20);
+ QApplication::processEvents();
+ QTRY_VERIFY(scene.drawCount > 0);
+}
+
+void tst_QGraphicsView::compositionModeInDrawBackground()
+{
+ class MyView : public QGraphicsView
+ { public:
+ MyView(QGraphicsScene *scene) : QGraphicsView(scene),
+ painted(false), compositionMode(QPainter::CompositionMode_SourceOver) {}
+ bool painted;
+ QPainter::CompositionMode compositionMode;
+ void drawBackground(QPainter *painter, const QRectF &)
+ {
+ compositionMode = painter->compositionMode();
+ painted = true;
+ }
+ };
+
+ QGraphicsScene dummy;
+ MyView view(&dummy);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ // Make sure the painter's composition mode is SourceOver in drawBackground.
+ QTRY_VERIFY(view.painted);
+ QCOMPARE(view.compositionMode, QPainter::CompositionMode_SourceOver);
+
+ view.painted = false;
+ view.setCacheMode(QGraphicsView::CacheBackground);
+ view.viewport()->update();
+
+ // Make sure the painter's composition mode is SourceOver in drawBackground
+ // with background cache enabled.
+ QTRY_VERIFY(view.painted);
+ QCOMPARE(view.compositionMode, QPainter::CompositionMode_SourceOver);
+}
+void tst_QGraphicsView::task253415_reconnectUpdateSceneOnSceneChanged()
+{
+ QGraphicsView view;
+ QGraphicsView dummyView;
+ view.setWindowFlags(view.windowFlags() | Qt::WindowStaysOnTopHint);
+ view.resize(200, 200);
+
+ QGraphicsScene scene1;
+ QObject::connect(&scene1, SIGNAL(changed(QList<QRectF>)), &dummyView, SLOT(updateScene(QList<QRectF>)));
+ view.setScene(&scene1);
+
+ QTest::qWait(12);
+
+ QGraphicsScene scene2;
+ QObject::connect(&scene2, SIGNAL(changed(QList<QRectF>)), &dummyView, SLOT(updateScene(QList<QRectF>)));
+ view.setScene(&scene2);
+
+ QTest::qWait(12);
+
+ bool wasConnected2 = QObject::disconnect(&scene2, SIGNAL(changed(QList<QRectF>)), &view, 0);
+ QVERIFY(wasConnected2);
+}
+
+// Qt/CE does not implement mouse tracking at this point.
+#ifndef Q_OS_WINCE
+void tst_QGraphicsView::task255529_transformationAnchorMouseAndViewportMargins()
+{
+ QGraphicsScene scene(-100, -100, 200, 200);
+ scene.addRect(QRectF(-50, -50, 100, 100), QPen(Qt::black), QBrush(Qt::blue));
+
+ class VpGraphicsView: public QGraphicsView
+ {
+ public:
+ VpGraphicsView(QGraphicsScene *scene, QWidget *parent=0)
+ : QGraphicsView(scene, parent)
+ {
+ setViewportMargins(8, 16, 12, 20);
+ setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
+ setMouseTracking(true);
+ }
+ };
+
+ VpGraphicsView view(&scene);
+ view.setWindowFlags(Qt::X11BypassWindowManagerHint);
+ view.show();
+
+ QTest::qWaitForWindowShown(&view);
+ QTest::qWait(50);
+ QPoint mouseViewPos(20, 20);
+ sendMouseMove(view.viewport(), mouseViewPos);
+
+ QPointF mouseScenePos = view.mapToScene(mouseViewPos);
+ view.setTransform(QTransform().scale(5, 5).rotate(5, Qt::ZAxis), true);
+
+ QPointF newMouseScenePos = view.mapToScene(mouseViewPos);
+
+ qreal slack = 1;
+ QVERIFY(qAbs(newMouseScenePos.x() - mouseScenePos.x()) < slack);
+ QVERIFY(qAbs(newMouseScenePos.y() - mouseScenePos.y()) < slack);
+}
+#endif
+
+void tst_QGraphicsView::task259503_scrollingArtifacts()
+{
+ QGraphicsScene scene(0, 0, 800, 600);
+
+ QGraphicsRectItem card;
+ card.setRect(0, 0, 50, 50);
+ card.setPen(QPen(Qt::darkRed));
+ card.setBrush(QBrush(Qt::cyan));
+ card.setZValue(2.0);
+ card.setPos(300, 300);
+ scene.addItem(&card);
+
+ class SAGraphicsView: public QGraphicsView
+ {
+ public:
+ SAGraphicsView(QGraphicsScene *scene)
+ : QGraphicsView(scene)
+ , itSTimeToTest(false)
+ {
+ setViewportUpdateMode( QGraphicsView::MinimalViewportUpdate );
+ resize(QSize(640, 480));
+ }
+
+ QRegion updateRegion;
+ bool itSTimeToTest;
+
+ void paintEvent(QPaintEvent *event)
+ {
+ QGraphicsView::paintEvent(event);
+
+ if (itSTimeToTest)
+ {
+// qDebug() << event->region();
+// qDebug() << updateRegion;
+ QEXPECT_FAIL("", "The event region doesn't include the original item position region. See QTBUG-4416", Continue);
+ QCOMPARE(event->region(), updateRegion);
+ }
+ }
+ };
+
+ SAGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ int hsbValue = view.horizontalScrollBar()->value();
+ view.horizontalScrollBar()->setValue(hsbValue / 2);
+ QTest::qWait(10);
+ view.horizontalScrollBar()->setValue(0);
+ QTest::qWait(10);
+
+ QRect itemDeviceBoundingRect = card.deviceTransform(view.viewportTransform()).mapRect(card.boundingRect()).toRect();
+ itemDeviceBoundingRect.adjust(-2, -2, 2, 2);
+ view.updateRegion = itemDeviceBoundingRect;
+ view.updateRegion += itemDeviceBoundingRect.translated(-100, 0);
+ view.itSTimeToTest = true;
+ card.setPos(200, 300);
+ QTest::qWait(10);
+}
+
+void tst_QGraphicsView::QTBUG_4151_clipAndIgnore_data()
+{
+ QTest::addColumn<bool>("clip");
+ QTest::addColumn<bool>("ignoreTransformations");
+ QTest::addColumn<int>("numItems");
+
+ QTest::newRow("none") << false << false << 3;
+ QTest::newRow("clip") << true << false << 3;
+ QTest::newRow("ignore") << false << true << 3;
+ QTest::newRow("clip+ignore") << true << true << 3;
+}
+
+void tst_QGraphicsView::QTBUG_4151_clipAndIgnore()
+{
+ QFETCH(bool, clip);
+ QFETCH(bool, ignoreTransformations);
+ QFETCH(int, numItems);
+
+ QGraphicsScene scene;
+
+ QGraphicsRectItem *parent = new QGraphicsRectItem(QRectF(0, 0, 50, 50), 0);
+ QGraphicsRectItem *child = new QGraphicsRectItem(QRectF(-10, -10, 40, 40), parent);
+ QGraphicsRectItem *ignore = new QGraphicsRectItem(QRectF(60, 60, 50, 50), 0);
+
+ if (clip)
+ parent->setFlags(QGraphicsItem::ItemClipsChildrenToShape);
+ if (ignoreTransformations)
+ ignore->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+
+ parent->setBrush(Qt::red);
+ child->setBrush(QColor(0, 0, 255, 128));
+ ignore->setBrush(Qt::green);
+
+ scene.addItem(parent);
+ scene.addItem(ignore);
+
+ QGraphicsView view(&scene);
+ view.setFrameStyle(0);
+ view.resize(75, 75);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ view.activateWindow();
+
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget *)&view);
+
+ QCOMPARE(view.items(view.rect()).size(), numItems);
+}
+
+void tst_QGraphicsView::QTBUG_5859_exposedRect()
+{
+ class CustomScene : public QGraphicsScene
+ {
+ public:
+ CustomScene(const QRectF &rect) : QGraphicsScene(rect) { }
+ void drawBackground(QPainter * /* painter */, const QRectF &rect)
+ { lastBackgroundExposedRect = rect; }
+ QRectF lastBackgroundExposedRect;
+ };
+
+ class CustomRectItem : public QGraphicsRectItem
+ {
+ public:
+ CustomRectItem(const QRectF &rect) : QGraphicsRectItem(rect)
+ { setFlag(QGraphicsItem::ItemUsesExtendedStyleOption); }
+ void paint(QPainter * /* painter */, const QStyleOptionGraphicsItem *option, QWidget * /* widget */ = 0)
+ { lastExposedRect = option->exposedRect; }
+ QRectF lastExposedRect;
+ };
+
+ CustomScene scene(QRectF(0,0,50,50));
+
+ CustomRectItem item(scene.sceneRect());
+
+ scene.addItem(&item);
+
+ QGraphicsView view(&scene);
+ if (PlatformQuirks::isAutoMaximizing())
+ view.setWindowFlags(view.windowFlags()|Qt::X11BypassWindowManagerHint);
+ view.scale(4.15, 4.15);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ view.viewport()->repaint(10,10,20,20);
+ QApplication::processEvents();
+
+ QCOMPARE(item.lastExposedRect, scene.lastBackgroundExposedRect);
+}
+
+// Qt/CE does not have regular cursor support.
+#if !defined(QT_NO_CURSOR) && !defined(Q_OS_WINCE)
+void tst_QGraphicsView::QTBUG_7438_cursor()
+{
+ QGraphicsScene scene;
+ QGraphicsItem *item = scene.addRect(QRectF(-10, -10, 20, 20));
+ item->setFlag(QGraphicsItem::ItemIsMovable);
+
+ QGraphicsView view(&scene);
+ view.setFixedSize(400, 400);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QCOMPARE(view.viewport()->cursor().shape(), QCursor().shape());
+ view.viewport()->setCursor(Qt::PointingHandCursor);
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+ sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+ sendMousePress(view.viewport(), view.mapFromScene(0, 0));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+ sendMouseRelease(view.viewport(), view.mapFromScene(0, 0));
+ QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
+}
+#endif
+
+class GraphicsItemWithHover : public QGraphicsRectItem
+{
+public:
+ GraphicsItemWithHover()
+ : receivedEnterEvent(false), receivedLeaveEvent(false),
+ enterWidget(0), leaveWidget(0)
+ {
+ setRect(0, 0, 100, 100);
+ setAcceptHoverEvents(true);
+ }
+
+ bool sceneEvent(QEvent *event)
+ {
+ if (event->type() == QEvent::GraphicsSceneHoverEnter) {
+ receivedEnterEvent = true;
+ enterWidget = static_cast<QGraphicsSceneHoverEvent *>(event)->widget();
+ } else if (event->type() == QEvent::GraphicsSceneHoverLeave) {
+ receivedLeaveEvent = true;
+ leaveWidget = static_cast<QGraphicsSceneHoverEvent *>(event)->widget();
+ }
+ return QGraphicsRectItem::sceneEvent(event);
+ }
+
+ bool receivedEnterEvent;
+ bool receivedLeaveEvent;
+ QWidget *enterWidget;
+ QWidget *leaveWidget;
+};
+
+void tst_QGraphicsView::hoverLeave()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ GraphicsItemWithHover *item = new GraphicsItemWithHover;
+ scene.addItem(item);
+
+ // move the cursor out of the way
+ QCursor::setPos(1,1);
+
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QPoint pos = view.viewport()->mapToGlobal(view.mapFromScene(item->mapToScene(10, 10)));
+ QCursor::setPos(pos);
+ QTest::qWait(200);
+ QVERIFY(item->receivedEnterEvent);
+ QCOMPARE(item->enterWidget, view.viewport());
+
+ QCursor::setPos(1,1);
+ QTest::qWait(200);
+ QVERIFY(item->receivedLeaveEvent);
+ QCOMPARE(item->leaveWidget, view.viewport());
+}
+
+class IMItem : public QGraphicsRectItem
+{
+public:
+ IMItem(QGraphicsItem *parent = 0):
+ QGraphicsRectItem(QRectF(0, 0, 20, 20), parent)
+ {
+ setFlag(QGraphicsItem::ItemIsFocusable, true);
+ setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
+ }
+
+ QVariant inputMethodQuery(Qt::InputMethodQuery) const
+ {
+ return mf;
+ }
+
+ static QRectF mf;
+};
+
+QRectF IMItem::mf(1.5, 1.6, 10, 10);
+
+void tst_QGraphicsView::QTBUG_16063_microFocusRect()
+{
+ QGraphicsScene scene;
+ IMItem *item = new IMItem();
+ scene.addItem(item);
+
+ QGraphicsView view(&scene);
+
+ view.setFixedSize(40, 40);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ scene.setFocusItem(item);
+ view.setFocus();
+ QRectF mfv = view.inputMethodQuery(Qt::ImMicroFocus).toRectF();
+ QCOMPARE(mfv, IMItem::mf.translated(-view.mapToScene(view.sceneRect().toRect()).boundingRect().topLeft()));
+}
+
+QTEST_MAIN(tst_QGraphicsView)
+#include "tst_qgraphicsview.moc"
diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview_2.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview_2.cpp
new file mode 100644
index 0000000000..122ffbc875
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview_2.cpp
@@ -0,0 +1,976 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.1, 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtTest/QtTest>
+#include <QSize>
+#include <QRectF>
+#include <QTransform>
+
+#ifdef Q_OS_WINCE
+#include <qguifunctions_wince.h>
+
+bool qt_wince_is_high_dpi() {
+ HDC deviceContext = GetDC(0);
+ int dpi = GetDeviceCaps(deviceContext, LOGPIXELSX);
+ ReleaseDC(0, deviceContext);
+ if ((dpi < 1000) && (dpi > 0))
+ return dpi > 96;
+ else
+ return false;
+}
+#endif
+
+Q_DECLARE_METATYPE(QList<int>)
+Q_DECLARE_METATYPE(QList<QRectF>)
+Q_DECLARE_METATYPE(QMatrix)
+Q_DECLARE_METATYPE(QPainterPath)
+Q_DECLARE_METATYPE(QPointF)
+Q_DECLARE_METATYPE(QRectF)
+Q_DECLARE_METATYPE(Qt::ScrollBarPolicy)
+
+static void _scrollBarRanges_data_1(int offset)
+{
+ // No motif, flat frame
+ QTest::newRow("1") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << 0 << 0 << 0 << false << false;
+ QTest::newRow("2") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset) << 0 << offset << false << false;
+ QTest::newRow("3") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset) << 0 << (100 + offset) << false << false;
+ QTest::newRow("4") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << 0 << 0 << 0 << false << false;
+ QTest::newRow("5") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -100 << (offset -50) << -100 << (-100 + offset) << false << false;
+ QTest::newRow("6") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -100 << (offset -50) << -100 << offset << false << false;
+ QTest::newRow("7") << QSize(150, 100) << QRectF(0, 0, 151, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (offset + 1) << 0 << offset + 1 << false << false;
+ QTest::newRow("8") << QSize(150, 100) << QRectF(0, 0, 201, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 1) << 0 << offset + 1 << false << false;
+ QTest::newRow("9") << QSize(150, 100) << QRectF(0, 0, 201, 201) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 1) << 0 << (100 + offset + 1) << false << false;
+ QTest::newRow("10") << QSize(150, 100) << QRectF(-101, -101, 151, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -101 << (-100 + offset) << -101 << (-100 + offset) << false << false;
+ QTest::newRow("11") << QSize(150, 100) << QRectF(-101, -101, 201, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-101) << (offset + -50) << -101 << (-100 + offset) << false << false;
+ QTest::newRow("12") << QSize(150, 100) << QRectF(-101, -101, 201, 201) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-101) << (offset -50) << (-101) << offset << false << false;
+ QTest::newRow("13") << QSize(150, 100) << QRectF(0, 0, 166, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (offset + 16) << 0 << (offset + 16) << false << false;
+ QTest::newRow("14") << QSize(150, 100) << QRectF(0, 0, 216, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 16) << 0 << (offset + 16) << false << false;
+ QTest::newRow("15") << QSize(150, 100) << QRectF(0, 0, 216, 216) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 16) << 0 << (100 + offset + 16) << false << false;
+ QTest::newRow("16") << QSize(150, 100) << QRectF(-116, -116, 166, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-100 - 16) << (-100 + offset) << (-100 - 16 ) << (-100 + offset) << false << false;
+ QTest::newRow("17") << QSize(150, 100) << QRectF(-116, -116, 216, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-100 - 16) << (offset -50) << (-100 - 16) << (-100 + offset) << false << false;
+ QTest::newRow("18") << QSize(150, 100) << QRectF(-116, -116, 216, 216) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-100 - 16) << (offset -50) << (-100 - 16) << offset << false << false;
+ QTest::newRow("1 x2") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (150 + offset) << 0 << (100 + offset) << false << false;
+ QTest::newRow("2 x2") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (250 + offset) << 0 << (100 + offset) << false << false;
+ QTest::newRow("3 x2") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (250 + offset) << 0 << (300 + offset) << false << false;
+ QTest::newRow("4 x2") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -200 << (-50 + offset) << -200 << (-100 + offset) << false << false;
+ QTest::newRow("5 x2") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -200 << (50 + offset) << -200 << (-100 + offset) << false << false;
+ QTest::newRow("6 x2") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -200 << (50 + offset) << -200 << (100 + offset) << false << false;
+ QTest::newRow("1 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 0 << 0 << 0 << false << false;
+ QTest::newRow("2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 50 << 0 << 0 << false << false;
+ QTest::newRow("3 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 50 << 0 << 100 << false << false;
+ QTest::newRow("4 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 0 << 0 << 0 << false << false;
+ QTest::newRow("5 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -100 << -50 << 0 << 0 << false << false;
+ QTest::newRow("6 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -100 << -50 << -100 << 0 << false << false;
+ QTest::newRow("7 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 1 << 0 << 1 << false << false;
+ QTest::newRow("8 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 51 << 0 << 1 << false << false;
+ QTest::newRow("9 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 51 << 0 << 101 << false << false;
+ QTest::newRow("10 No ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -101 << -100 << -101 << -100 << false << false;
+ QTest::newRow("11 No ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -101 << -50 << -101 << -100 << false << false;
+ QTest::newRow("12 No ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -101 << -50 << -101 << 0 << false << false;
+ QTest::newRow("13 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 16 << 0 << 16 << false << false;
+ QTest::newRow("14 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << (50 + 16) << 0 << 16 << false << false;
+ QTest::newRow("15 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << (50 + 16) << 0 << (100 + 16) << false << false;
+ QTest::newRow("16 No ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << (-100 - 16) << -100 << (-100 - 16) << -100 << false << false;
+ QTest::newRow("17 No ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << (-100 - 16) << -50 << (-100 - 16) << -100 << false << false;
+ QTest::newRow("18 No ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << (-100 - 16) << -50 << (-100 - 16) << 0 << false << false;
+ QTest::newRow("1 x2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 150 << 0 << 100 << false << false;
+ QTest::newRow("2 x2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 250 << 0 << 100 << false << false;
+ QTest::newRow("3 x2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 250 << 0 << 300 << false << false;
+ QTest::newRow("4 x2 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -200 << -50 << -200 << -100 << false << false;
+ QTest::newRow("5 x2 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -200 << 50 << -200 << -100 << false << false;
+ QTest::newRow("6 x2 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -200 << 50 << -200 << 100 << false << false;
+ QTest::newRow("1 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << 16 << 0 << 16 << false << false;
+ QTest::newRow("2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 16) << 0 << 16 << false << false;
+ QTest::newRow("3 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 16) << 0 << (100 + 16) << false << false;
+ QTest::newRow("4 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -100 << (-100 + 16) << -100 << (-100 + 16) << false << false;
+ QTest::newRow("5 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -100 << (16-50) << -100 << (-100 + 16) << false << false;
+ QTest::newRow("6 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -100 << (16-50) << -100 << 16 << false << false;
+ QTest::newRow("7 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << 17 << 0 << 17 << false << false;
+ QTest::newRow("8 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (17+50) << 0 << 17 << false << false;
+ QTest::newRow("9 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << 67 << 0 << 117 << false << false;
+ QTest::newRow("10 Always ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -101 << (-100 + 16) << -101 << (-100 + 16) << false << false;
+ QTest::newRow("11 Always ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -101 << (16-50) << -101 << (-100 + 16) << false << false;
+ QTest::newRow("12 Always ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -101 << (16-50) << -101 << 16 << false << false;
+ QTest::newRow("13 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << 32 << 0 << 32 << false << false;
+ QTest::newRow("14 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 32) << 0 << 32 << false << false;
+ QTest::newRow("15 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 32) << 0 << (100 + 32) << false << false;
+ QTest::newRow("16 Always ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << (-100 - 16) << (-100 + 16) << (-100 - 16) << (-100 + 16) << false << false;
+ QTest::newRow("17 Always ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << (-100 - 16) << (16-50) << (-100 - 16) << (-100 + 16) << false << false;
+ QTest::newRow("18 Always ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << (-100 - 16) << (16-50) << (-100 - 16) << 16 << false << false;
+ QTest::newRow("1 x2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (150 + 16) << 0 << (100 + 16) << false << false;
+ QTest::newRow("2 x2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (250 + 16) << 0 << (100 + 16) << false << false;
+ QTest::newRow("3 x2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (250 + 16) << 0 << (300 + 16) << false << false;
+ QTest::newRow("4 x2 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -200 << (-50 + 16) << -200 << (-100 + 16) << false << false;
+ QTest::newRow("5 x2 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -200 << (50 + 16) << -200 << (-100 + 16) << false << false;
+ QTest::newRow("6 x2 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -200 << (50 + 16) << -200 << (100 + 16) << false << false;
+}
+
+static void _scrollBarRanges_data_2(int offset)
+{
+ // Motif, flat frame
+ QTest::newRow("Motif, 1") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << 0 << 0 << 0 << true << false;
+ QTest::newRow("Motif, 2") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset) << 0 << offset << true << false;
+ QTest::newRow("Motif, 3") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset) << 0 << (100 + offset) << true << false;
+ QTest::newRow("Motif, 4") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << 0 << 0 << 0 << true << false;
+ QTest::newRow("Motif, 5") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -100 << (offset-50) << -100 << (-100 + offset) << true << false;
+ QTest::newRow("Motif, 6") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -100 << (offset-50) << -100 << offset << true << false;
+ QTest::newRow("Motif, 7") << QSize(150, 100) << QRectF(0, 0, 151, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << offset + 1 << 0 << offset + 1 << true << false;
+ QTest::newRow("Motif, 8") << QSize(150, 100) << QRectF(0, 0, 201, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 1) << 0 << offset + 1 << true << false;
+ QTest::newRow("Motif, 9") << QSize(150, 100) << QRectF(0, 0, 201, 201) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 1) << 0 << (100 + offset + 1) << true << false;
+ QTest::newRow("Motif, 10") << QSize(150, 100) << QRectF(-101, -101, 151, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -101 << (-100 + offset) << -101 << (-100 + offset) << true << false;
+ QTest::newRow("Motif, 11") << QSize(150, 100) << QRectF(-101, -101, 201, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-101) << (offset-50) << -101 << (-100 + offset) << true << false;
+ QTest::newRow("Motif, 12") << QSize(150, 100) << QRectF(-101, -101, 201, 201) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-101) << (offset-50) << (-101) << offset << true << false;
+ QTest::newRow("Motif, 13") << QSize(150, 100) << QRectF(0, 0, 166, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (offset + 16) << 0 << (offset + 16) << true << false;
+ QTest::newRow("Motif, 14") << QSize(150, 100) << QRectF(0, 0, 216, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 16) << 0 << (offset + 16) << true << false;
+ QTest::newRow("Motif, 15") << QSize(150, 100) << QRectF(0, 0, 216, 216) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 16) << 0 << (100 + offset + 16) << true << false;
+ QTest::newRow("Motif, 16") << QSize(150, 100) << QRectF(-116, -116, 166, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-100 - 16) << (-100 + offset) << (-100 - 16) << (-100 + offset) << true << false;
+ QTest::newRow("Motif, 17") << QSize(150, 100) << QRectF(-116, -116, 216, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-100 - 16) << (offset-50) << (-100 - 16) << (-100 + offset) << true << false;
+ QTest::newRow("Motif, 18") << QSize(150, 100) << QRectF(-116, -116, 216, 216) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-100 - 16) << (offset-50) << (-100 - 16) << offset << true << false;
+ QTest::newRow("Motif, 1 x2") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (150 + offset) << 0 << (100 + offset) << true << false;
+ QTest::newRow("Motif, 2 x2") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (250 + offset) << 0 << (100 + offset) << true << false;
+ QTest::newRow("Motif, 3 x2") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (250 + offset) << 0 << (300 + offset) << true << false;
+ QTest::newRow("Motif, 4 x2") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -200 << (-50 + offset) << -200 << (-100 + offset) << true << false;
+ QTest::newRow("Motif, 5 x2") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -200 << (50 + offset) << -200 << (-100 + offset) << true << false;
+ QTest::newRow("Motif, 6 x2") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -200 << (50 + offset) << -200 << (100 + offset) << true << false;
+ QTest::newRow("Motif, 1 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 0 << 0 << 0 << true << false;
+ QTest::newRow("Motif, 2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 50 << 0 << 0 << true << false;
+ QTest::newRow("Motif, 3 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 50 << 0 << 100 << true << false;
+ QTest::newRow("Motif, 4 No ScrollBars") << QSize(100, 100) << QRectF(-100, -100, 100, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 0 << 0 << 0 << true << false;
+ QTest::newRow("Motif, 5 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -100 << -50 << 0 << 0 << true << false;
+ QTest::newRow("Motif, 6 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -100 << -50 << -100 << 0 << true << false;
+ QTest::newRow("Motif, 7 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 1 << 0 << 1 << true << false;
+ QTest::newRow("Motif, 8 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 51 << 0 << 1 << true << false;
+ QTest::newRow("Motif, 9 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 51 << 0 << 101 << true << false;
+ QTest::newRow("Motif, 10 No ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -101 << -100 << -101 << -100 << true << false;
+ QTest::newRow("Motif, 11 No ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -101 << -50 << -101 << -100 << true << false;
+ QTest::newRow("Motif, 12 No ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -101 << -50 << -101 << 0 << true << false;
+ QTest::newRow("Motif, 13 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 16 << 0 << 16 << true << false;
+ QTest::newRow("Motif, 14 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << (50 + 16) << 0 << 16 << true << false;
+ QTest::newRow("Motif, 15 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << (50 + 16) << 0 << (100 + 16) << true << false;
+ QTest::newRow("Motif, 16 No ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << (-100 - 16) << -100 << (-100 - 16) << -100 << true << false;
+ QTest::newRow("Motif, 17 No ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << (-100 - 16) << -50 << (-100 - 16) << -100 << true << false;
+ QTest::newRow("Motif, 18 No ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << (-100 - 16) << -50 << (-100 - 16) << 0 << true << false;
+ QTest::newRow("Motif, 1 x2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 150 << 0 << 100 << true << false;
+ QTest::newRow("Motif, 2 x2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 250 << 0 << 100 << true << false;
+ QTest::newRow("Motif, 3 x2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 250 << 0 << 300 << true << false;
+ QTest::newRow("Motif, 4 x2 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -200 << -50 << -200 << -100 << true << false;
+ QTest::newRow("Motif, 5 x2 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -200 << 50 << -200 << -100 << true << false;
+ QTest::newRow("Motif, 6 x2 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -200 << 50 << -200 << 100 << true << false;
+ QTest::newRow("Motif, 1 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << 16 << 0 << 16 << true << false;
+ QTest::newRow("Motif, 2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 16) << 0 << 16 << true << false;
+ QTest::newRow("Motif, 3 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 16) << 0 << (100 + 16) << true << false;
+ QTest::newRow("Motif, 4 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -100 << (-100 + 16) << -100 << (-100 + 16) << true << false;
+ QTest::newRow("Motif, 5 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -100 << (16-50) << -100 << (-100 + 16) << true << false;
+ QTest::newRow("Motif, 6 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -100 << (16-50) << -100 << 16 << true << false;
+ QTest::newRow("Motif, 7 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << 17 << 0 << 17 << true << false;
+ QTest::newRow("Motif, 8 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (117-50) << 0 << 17 << true << false;
+ QTest::newRow("Motif, 9 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (117-50) << 0 << 117 << true << false;
+ QTest::newRow("Motif, 10 Always ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -101 << (-100 + 16) << -101 << (-100 + 16) << true << false;
+ QTest::newRow("Motif, 11 Always ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -101 << (16-50) << -101 << (-100 + 16) << true << false;
+ QTest::newRow("Motif, 12 Always ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -101 << (16-50) << -101 << 16 << true << false;
+ QTest::newRow("Motif, 13 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << 32 << 0 << 32 << true << false;
+ QTest::newRow("Motif, 14 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 32) << 0 << 32 << true << false;
+ QTest::newRow("Motif, 15 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 32) << 0 << (100 + 32) << true << false;
+ QTest::newRow("Motif, 16 Always ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << (-100 - 16) << (-100 + 16) << (-100 - 16) << (-100 + 16) << true << false;
+ QTest::newRow("Motif, 17 Always ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << (-100 - 16) << (16-50) << (-100 - 16) << (-100 + 16) << true << false;
+ QTest::newRow("Motif, 18 Always ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << (-100 - 16) << (16-50) << (-100 - 16) << 16 << true << false;
+ QTest::newRow("Motif, 1 x2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (150 + 16) << 0 << (100 + 16) << true << false;
+ QTest::newRow("Motif, 2 x2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (250 + 16) << 0 << (100 + 16) << true << false;
+ QTest::newRow("Motif, 3 x2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (250 + 16) << 0 << (300 + 16) << true << false;
+ QTest::newRow("Motif, 4 x2 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -200 << (-50 + 16) << -200 << (-100 + 16) << true << false;
+ QTest::newRow("Motif, 5 x2 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -200 << (50 + 16) << -200 << (-100 + 16) << true << false;
+ QTest::newRow("Motif, 6 x2 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -200 << (50 + 16) << -200 << (100 + 16) << true << false;
+}
+
+static void _scrollBarRanges_data_3(int offset)
+{
+ // No motif, styled panel
+ QTest::newRow("Styled, 1") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << 0 << 0 << 0 << false << true;
+ QTest::newRow("Styled, 2") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset) << 0 << offset << false << true;
+ QTest::newRow("Styled, 3") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset) << 0 << (100 + offset) << false << true;
+ QTest::newRow("Styled, 4") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << 0 << 0 << 0 << false << true;
+ QTest::newRow("Styled, 5") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -100 << (offset-50) << -100 << (-100 + offset) << false << true;
+ QTest::newRow("Styled, 6") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -100 << (offset-50) << -100 << offset << false << true;
+ QTest::newRow("Styled, 7") << QSize(150, 100) << QRectF(0, 0, 151, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << offset + 1 << 0 << offset + 1 << false << true;
+ QTest::newRow("Styled, 8") << QSize(150, 100) << QRectF(0, 0, 201, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 1) << 0 << offset + 1 << false << true;
+ QTest::newRow("Styled, 9") << QSize(150, 100) << QRectF(0, 0, 201, 201) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 1) << 0 << (100 + offset + 1) << false << true;
+ QTest::newRow("Styled, 10") << QSize(150, 100) << QRectF(-101, -101, 151, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -101 << (-100 + offset) << -101 << (-100 + offset) << false << true;
+ QTest::newRow("Styled, 11") << QSize(150, 100) << QRectF(-101, -101, 201, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-101) << (offset-50) << -101 << (-100 + offset) << false << true;
+ QTest::newRow("Styled, 12") << QSize(150, 100) << QRectF(-101, -101, 201, 201) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-101) << (offset-50) << (-101) << offset << false << true;
+ QTest::newRow("Styled, 13") << QSize(150, 100) << QRectF(0, 0, 166, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (offset + 16) << 0 << (offset + 16) << false << true;
+ QTest::newRow("Styled, 14") << QSize(150, 100) << QRectF(0, 0, 216, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 16) << 0 << (offset + 16) << false << true;
+ QTest::newRow("Styled, 15") << QSize(150, 100) << QRectF(0, 0, 216, 216) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 16) << 0 << (100 + offset + 16) << false << true;
+ QTest::newRow("Styled, 16") << QSize(150, 100) << QRectF(-116, -116, 166, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-100 - 16) << (-100 + offset) << (-100 - 16) << (-100 + offset) << false << true;
+ QTest::newRow("Styled, 17") << QSize(150, 100) << QRectF(-116, -116, 216, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-100 - 16) << (offset-50) << (-100 - 16) << (-100 + offset) << false << true;
+ QTest::newRow("Styled, 18") << QSize(150, 100) << QRectF(-116, -116, 216, 216) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-100 - 16) << (offset-50) << (-100 - 16) << offset << false << true;
+ QTest::newRow("Styled, 1 x2") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (150 + offset) << 0 << (100 + offset) << false << true;
+ QTest::newRow("Styled, 2 x2") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (250 + offset) << 0 << (100 + offset) << false << true;
+ QTest::newRow("Styled, 3 x2") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (250 + offset) << 0 << (300 + offset) << false << true;
+ QTest::newRow("Styled, 4 x2") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -200 << (-50 + offset) << -200 << (-100 + offset) << false << true;
+ QTest::newRow("Styled, 5 x2") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -200 << (50 + offset) << -200 << (-100 + offset) << false << true;
+ QTest::newRow("Styled, 6 x2") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -200 << (50 + offset) << -200 << (100 + offset) << false << true;
+ QTest::newRow("Styled, 1 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 0 << 0 << 0 << false << true;
+ QTest::newRow("Styled, 2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 50 << 0 << 0 << false << true;
+ QTest::newRow("Styled, 3 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 50 << 0 << 100 << false << true;
+ QTest::newRow("Styled, 4 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 0 << 0 << 0 << false << true;
+ QTest::newRow("Styled, 5 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -100 << -50 << 0 << 0 << false << true;
+ QTest::newRow("Styled, 6 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -100 << -50 << -100 << 0 << false << true;
+ QTest::newRow("Styled, 7 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 1 << 0 << 1 << false << true;
+ QTest::newRow("Styled, 8 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 51 << 0 << 1 << false << true;
+ QTest::newRow("Styled, 9 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 51 << 0 << 101 << false << true;
+ QTest::newRow("Styled, 10 No ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -101 << -100 << -101 << -100 << false << true;
+ QTest::newRow("Styled, 11 No ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -101 << -50 << -101 << -100 << false << true;
+ QTest::newRow("Styled, 12 No ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -101 << -50 << -101 << 0 << false << true;
+ QTest::newRow("Styled, 13 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 16 << 0 << 16 << false << true;
+ QTest::newRow("Styled, 14 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << (50 + 16) << 0 << 16 << false << true;
+ QTest::newRow("Styled, 15 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << (50 + 16) << 0 << (100 + 16) << false << true;
+ QTest::newRow("Styled, 16 No ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << (-100 - 16) << -100 << (-100 - 16) << -100 << false << true;
+ QTest::newRow("Styled, 17 No ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << (-100 - 16) << -50 << (-100 - 16) << -100 << false << true;
+ QTest::newRow("Styled, 18 No ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << (-100 - 16) << -50 << (-100 - 16) << 0 << false << true;
+ QTest::newRow("Styled, 1 x2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 150 << 0 << 100 << false << true;
+ QTest::newRow("Styled, 2 x2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 250 << 0 << 100 << false << true;
+ QTest::newRow("Styled, 3 x2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 250 << 0 << 300 << false << true;
+ QTest::newRow("Styled, 4 x2 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -200 << -50 << -200 << -100 << false << true;
+ QTest::newRow("Styled, 5 x2 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -200 << 50 << -200 << -100 << false << true;
+ QTest::newRow("Styled, 6 x2 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -200 << 50 << -200 << 100 << false << true;
+ QTest::newRow("Styled, 1 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << 16 << 0 << 16 << false << true;
+ QTest::newRow("Styled, 2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 16) << 0 << 16 << false << true;
+ QTest::newRow("Styled, 3 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 16) << 0 << (100 + 16) << false << true;
+ QTest::newRow("Styled, 4 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -100 << (-100 + 16) << -100 << (-100 + 16) << false << true;
+ QTest::newRow("Styled, 5 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -100 << (16-50) << -100 << (-100 + 16) << false << true;
+ QTest::newRow("Styled, 6 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -100 << (16-50) << -100 << 16 << false << true;
+ QTest::newRow("Styled, 7 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << 17 << 0 << 17 << false << true;
+ QTest::newRow("Styled, 8 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (117-50) << 0 << 17 << false << true;
+ QTest::newRow("Styled, 9 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (117-50) << 0 << 117 << false << true;
+ QTest::newRow("Styled, 10 Always ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -101 << (-100 + 16) << -101 << (-100 + 16) << false << true;
+ QTest::newRow("Styled, 11 Always ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -101 << (16-50) << -101 << (-100 + 16) << false << true;
+ QTest::newRow("Styled, 12 Always ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -101 << (16-50) << -101 << 16 << false << true;
+ QTest::newRow("Styled, 13 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << 32 << 0 << 32 << false << true;
+ QTest::newRow("Styled, 14 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 32) << 0 << 32 << false << true;
+ QTest::newRow("Styled, 15 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 32) << 0 << (100 + 32) << false << true;
+ QTest::newRow("Styled, 16 Always ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << (-100 - 16) << (-100 + 16) << (-100 - 16) << (-100 + 16) << false << true;
+ QTest::newRow("Styled, 17 Always ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << (-100 - 16) << (16-50) << (-100 - 16) << (-100 + 16) << false << true;
+ QTest::newRow("Styled, 18 Always ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << (-100 - 16) << (16-50) << (-100 - 16) << 16 << false << true;
+ QTest::newRow("Styled, 1 x2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (150 + 16) << 0 << (100 + 16) << false << true;
+ QTest::newRow("Styled, 2 x2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (250 + 16) << 0 << (100 + 16) << false << true;
+ QTest::newRow("Styled, 3 x2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (250 + 16) << 0 << (300 + 16) << false << true;
+ QTest::newRow("Styled, 4 x2 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -200 << (-50 + 16) << -200 << (-100 + 16) << false << true;
+ QTest::newRow("Styled, 5 x2 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -200 << (50 + 16) << -200 << (-100 + 16) << false << true;
+ QTest::newRow("Styled, 6 x2 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -200 << (50 + 16) << -200 << (100 + 16) << false << true;
+}
+
+static void _scrollBarRanges_data_4(int offset)
+{
+ // Motif, styled panel
+ QTest::newRow("Motif, Styled, 1") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << 0 << 0 << 0 << true << true;
+ QTest::newRow("Motif, Styled, 2") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 4) << 0 << (offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 3") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 4) << 0 << (100 + offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 4") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << 0 << 0 << 0 << true << true;
+ QTest::newRow("Motif, Styled, 5") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -100 << (offset + 4 - 50) << -100 << (-100 + offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 6") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -100 << (offset + 4 - 50) << -100 << (offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 7") << QSize(150, 100) << QRectF(0, 0, 151, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (offset + 1 + 4) << 0 << (offset + 1 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 8") << QSize(150, 100) << QRectF(0, 0, 201, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 1 + 4) << 0 << (offset + 1 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 9") << QSize(150, 100) << QRectF(0, 0, 201, 201) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 1 + 4) << 0 << (100 + offset + 1 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 10") << QSize(150, 100) << QRectF(-101, -101, 151, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -101 << (-100 + offset + 4) << -101 << (-100 + offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 11") << QSize(150, 100) << QRectF(-101, -101, 201, 101) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-101) << (offset + 4 - 50) << -101 << (-100 + offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 12") << QSize(150, 100) << QRectF(-101, -101, 201, 201) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-101) << (offset + 4 - 50) << (-101) << (offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 13") << QSize(150, 100) << QRectF(0, 0, 166, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (offset + 16 + 4) << 0 << (offset + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 14") << QSize(150, 100) << QRectF(0, 0, 216, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 16 + 4) << 0 << (offset + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 15") << QSize(150, 100) << QRectF(0, 0, 216, 216) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (50 + offset + 16 + 4) << 0 << (100 + offset + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 16") << QSize(150, 100) << QRectF(-116, -116, 166, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-100 - 16) << (-100 + offset + 4) << (-100 - 16) << (-100 + offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 17") << QSize(150, 100) << QRectF(-116, -116, 216, 116) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-100 - 16) << (offset + 4 - 50) << (-100 - 16) << (-100 + offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 18") << QSize(150, 100) << QRectF(-116, -116, 216, 216) << QTransform()
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << (-100 - 16) << (offset + 4 - 50) << (-100 - 16) << (offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 1 x2") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (150 + offset + 4) << 0 << (100 + offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 2 x2") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (250 + offset + 4) << 0 << (100 + offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 3 x2") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << 0 << (250 + offset + 4) << 0 << (300 + offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 4 x2") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -200 << (-50 + offset + 4) << -200 << (-100 + offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 5 x2") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -200 << (50 + offset + 4) << -200 << (-100 + offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 6 x2") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAsNeeded << Qt::ScrollBarAsNeeded
+ << -200 << (50 + offset + 4) << -200 << (100 + offset + 4) << true << true;
+ QTest::newRow("Motif, Styled, 1 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 0 << 0 << 0 << true << true;
+ QTest::newRow("Motif, Styled, 2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 50 << 0 << 0 << true << true;
+ QTest::newRow("Motif, Styled, 3 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 50 << 0 << 100 << true << true;
+ QTest::newRow("Motif, Styled, 4 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 0 << 0 << 0 << true << true;
+ QTest::newRow("Motif, Styled, 5 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -100 << -50 << 0 << 0 << true << true;
+ QTest::newRow("Motif, Styled, 6 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -100 << -50 << -100 << 0 << true << true;
+ QTest::newRow("Motif, Styled, 7 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 1 << 0 << 1 << true << true;
+ QTest::newRow("Motif, Styled, 8 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 51 << 0 << 1 << true << true;
+ QTest::newRow("Motif, Styled, 9 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 51 << 0 << 101 << true << true;
+ QTest::newRow("Motif, Styled, 10 No ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -101 << -100 << -101 << -100 << true << true;
+ QTest::newRow("Motif, Styled, 11 No ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -101 << -50 << -101 << -100 << true << true;
+ QTest::newRow("Motif, Styled, 12 No ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -101 << -50 << -101 << 0 << true << true;
+ QTest::newRow("Motif, Styled, 13 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 16 << 0 << 16 << true << true;
+ QTest::newRow("Motif, Styled, 14 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << (50 + 16) << 0 << 16 << true << true;
+ QTest::newRow("Motif, Styled, 15 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << (50 + 16) << 0 << (100 + 16) << true << true;
+ QTest::newRow("Motif, Styled, 16 No ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << (-100 - 16) << -100 << (-100 - 16) << -100 << true << true;
+ QTest::newRow("Motif, Styled, 17 No ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << (-100 - 16) << -50 << (-100 - 16) << -100 << true << true;
+ QTest::newRow("Motif, Styled, 18 No ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << (-100 - 16) << -50 << (-100 - 16) << 0 << true << true;
+ QTest::newRow("Motif, Styled, 1 x2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 150 << 0 << 100 << true << true;
+ QTest::newRow("Motif, Styled, 2 x2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 250 << 0 << 100 << true << true;
+ QTest::newRow("Motif, Styled, 3 x2 No ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << 0 << 250 << 0 << 300 << true << true;
+ QTest::newRow("Motif, Styled, 4 x2 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -200 << -50 << -200 << -100 << true << true;
+ QTest::newRow("Motif, Styled, 5 x2 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -200 << 50 << -200 << -100 << true << true;
+ QTest::newRow("Motif, Styled, 6 x2 No ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOff << Qt::ScrollBarAlwaysOff
+ << -200 << 50 << -200 << 100 << true << true;
+ QTest::newRow("Motif, Styled, 1 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (16 + 4) << 0 << (16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 16 + 4) << 0 << (16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 3 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 16 + 4) << 0 << (100 + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 4 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -100 << (-100 + 16 + 4) << -100 << (-100 + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 5 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -100 << (16 + 4 - 50) << -100 << (-100 + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 6 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -100 << (16 + 4 - 50) << -100 << (16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 7 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (17 + 4) << 0 << (17 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 8 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (117 + 4 - 50) << 0 << (17 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 9 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (117 + 4 - 50) << 0 << (117 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 10 Always ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 151, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -101 << (-100 + 16 + 4) << -101 << (-100 + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 11 Always ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 101) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -101 << (16 + 4 - 50) << -101 << (-100 + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 12 Always ScrollBars") << QSize(150, 100) << QRectF(-101, -101, 201, 201) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -101 << (16 + 4 - 50) << -101 << (16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 13 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (32 + 4) << 0 << (32 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 14 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 32 + 4) << 0 << (32 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 15 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (50 + 32 + 4) << 0 << (100 + 32 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 16 Always ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 166, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << (-100 - 16) << (-100 + 16 + 4) << (-100 - 16) << (-100 + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 17 Always ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 116) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << (-100 - 16) << (16 + 4 - 50) << (-100 - 16) << (-100 + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 18 Always ScrollBars") << QSize(150, 100) << QRectF(-116, -116, 216, 216) << QTransform()
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << (-100 - 16) << (16 + 4 - 50) << (-100 - 16) << (16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 1 x2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (150 + 16 + 4) << 0 << (100 + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 2 x2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (250 + 16 + 4) << 0 << (100 + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 3 x2 Always ScrollBars") << QSize(150, 100) << QRectF(0, 0, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << 0 << (250 + 16 + 4) << 0 << (300 + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 4 x2 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 150, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -200 << (-50 + 16 + 4) << -200 << (-100 + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 5 x2 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 100) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -200 << (50 + 16 + 4) << -200 << (-100 + 16 + 4) << true << true;
+ QTest::newRow("Motif, Styled, 6 x2 Always ScrollBars") << QSize(150, 100) << QRectF(-100, -100, 200, 200) << QTransform().scale(2, 2)
+ << Qt::ScrollBarAlwaysOn << Qt::ScrollBarAlwaysOn
+ << -200 << (50 + 16 + 4) << -200 << (100 + 16 + 4) << true << true;
+}
+
+void _scrollBarRanges_data()
+{
+ QTest::addColumn<QSize>("viewportSize");
+ QTest::addColumn<QRectF>("sceneRect");
+ QTest::addColumn<QTransform>("transform");
+ QTest::addColumn<Qt::ScrollBarPolicy>("hbarpolicy");
+ QTest::addColumn<Qt::ScrollBarPolicy>("vbarpolicy");
+ QTest::addColumn<int>("hmin");
+ QTest::addColumn<int>("hmax");
+ QTest::addColumn<int>("vmin");
+ QTest::addColumn<int>("vmax");
+ QTest::addColumn<bool>("useMotif");
+ QTest::addColumn<bool>("useStyledPanel");
+
+ int offset = 16;
+#ifdef Q_OS_WINCE
+ if (qt_wince_is_high_dpi())
+ offset *= 2;
+#endif
+
+ _scrollBarRanges_data_1(offset);
+ _scrollBarRanges_data_2(offset);
+ _scrollBarRanges_data_3(offset);
+ _scrollBarRanges_data_4(offset);
+}
diff --git a/tests/auto/widgets/graphicsview/qgraphicswidget/.gitignore b/tests/auto/widgets/graphicsview/qgraphicswidget/.gitignore
new file mode 100644
index 0000000000..ae39b803e5
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicswidget/.gitignore
@@ -0,0 +1 @@
+tst_qgraphicswidget
diff --git a/tests/auto/widgets/graphicsview/qgraphicswidget/qgraphicswidget.pro b/tests/auto/widgets/graphicsview/qgraphicswidget/qgraphicswidget.pro
new file mode 100644
index 0000000000..330076eafc
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicswidget/qgraphicswidget.pro
@@ -0,0 +1,10 @@
+load(qttest_p4)
+
+QT += widgets widgets-private
+QT += core-private gui-private
+
+SOURCES += tst_qgraphicswidget.cpp
+
+
+mac*:CONFIG+=insignificant_test
+qpa:contains(QT_CONFIG,xcb):CONFIG+=insignificant_test # QTBUG-20778 unstable on qpa, xcb
diff --git a/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp
new file mode 100644
index 0000000000..c983016a20
--- /dev/null
+++ b/tests/auto/widgets/graphicsview/qgraphicswidget/tst_qgraphicswidget.cpp
@@ -0,0 +1,3361 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** 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.1, 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.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qgraphicswidget.h>
+#include <qgraphicsscene.h>
+#include <qgraphicssceneevent.h>
+#include <qgraphicsview.h>
+#include <qstyleoption.h>
+#include <qgraphicslinearlayout.h>
+#include <qcleanlooksstyle.h>
+#include <qlineedit.h>
+#include <qboxlayout.h>
+#include <qaction.h>
+#include <qwidgetaction.h>
+#include "../../../platformquirks.h"
+
+
+class EventSpy : public QObject
+{
+ Q_OBJECT
+public:
+ EventSpy(QObject *watched, QEvent::Type type)
+ : _count(0), spied(type)
+ {
+ watched->installEventFilter(this);
+ }
+
+ int count() const { return _count; }
+
+protected:
+ bool eventFilter(QObject *watched, QEvent *event)
+ {
+ Q_UNUSED(watched);
+ if (event->type() == spied)
+ ++_count;
+ return false;
+ }
+
+ int _count;
+ QEvent::Type spied;
+};
+
+class tst_QGraphicsWidget : public QObject {
+Q_OBJECT
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void qgraphicswidget();
+
+ void activation();
+ void boundingRect_data();
+ void boundingRect();
+ void dumpFocusChain_data();
+ void dumpFocusChain();
+ void focusWidget_data();
+ void focusWidget();
+ void focusWidget2();
+ void focusWidget3();
+ void focusPolicy_data();
+ void focusPolicy();
+ void font_data();
+ void font();
+ void fontPropagation();
+ void fontChangedEvent();
+ void fontPropagationWidgetItemWidget();
+ void fontPropagationSceneChange();
+ void geometry_data();
+ void geometry();
+ void geometryChanged();
+ void width();
+ void height();
+ void getContentsMargins_data();
+ void getContentsMargins();
+ void initStyleOption_data();
+ void initStyleOption();
+ void layout_data();
+ void layout();
+ void layoutDirection_data();
+ void layoutDirection();
+ void paint_data();
+ void paint();
+ void palettePropagation();
+ void parentWidget_data();
+ void parentWidget();
+ void resize_data();
+ void resize();
+ void setAttribute_data();
+ void setAttribute();
+ void setStyle_data();
+ void setStyle();
+ void setTabOrder_data();
+ void setTabOrder();
+ void setTabOrderAndReparent();
+ void topLevelWidget_data();
+ void topLevelWidget();
+ void unsetLayoutDirection_data();
+ void unsetLayoutDirection();
+ void focusNextPrevChild_data();
+ void focusNextPrevChild();
+ void verifyFocusChain();
+ void updateFocusChainWhenChildDie();
+ void sizeHint_data();
+ void sizeHint();
+ void consistentPosSizeGeometry_data();
+ void consistentPosSizeGeometry();
+ void setSizes_data();
+ void setSizes();
+ void closePopupOnOutsideClick();
+ void defaultSize();
+ void explicitMouseGrabber();
+ void implicitMouseGrabber();
+ void doubleClickAfterExplicitMouseGrab();
+ void popupMouseGrabber();
+ void windowFlags_data();
+ void windowFlags();
+ void shortcutsDeletion();
+ void painterStateProtectionOnWindowFrame();
+ void ensureClipping();
+ void widgetSendsGeometryChanges();
+ void respectHFW();
+ void addChildInpolishEvent();
+ void polishEvent();
+ void polishEvent2();
+ void autoFillBackground();
+ void initialShow();
+ void initialShow2();
+ void itemChangeEvents();
+ void itemSendGeometryPosChangesDeactivated();
+
+ void fontPropagatesResolveToChildren();
+ void fontPropagatesResolveToGrandChildren();
+ void fontPropagatesResolveInParentChange();
+ void fontPropagatesResolveViaNonWidget();
+ void fontPropagatesResolveFromScene();
+
+ // Task fixes
+ void task236127_bspTreeIndexFails();
+ void task243004_setStyleCrash();
+ void task250119_shortcutContext();
+ void QT_BUG_6544_tabFocusFirstUnsetWhenRemovingItems();
+ void QT_BUG_12056_tabFocusFirstUnsetWhenRemovingItems();
+};
+
+
+static void sendMouseMove(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::NoButton, Qt::MouseButtons buttons = 0)
+{
+ QTest::mouseMove(widget, point);
+ QMouseEvent event(QEvent::MouseMove, point, button, buttons, 0);
+ QApplication::sendEvent(widget, &event);
+}
+
+// Subclass that exposes the protected functions.
+class SubQGraphicsWidget : public QGraphicsWidget {
+public:
+ SubQGraphicsWidget(QGraphicsItem *parent = 0, Qt::WindowFlags windowFlags = 0)
+ : QGraphicsWidget(parent, windowFlags), eventCount(0)
+ { }
+
+ void initStyleOption(QStyleOption *option)
+ { QGraphicsWidget::initStyleOption(option); }
+
+ void call_changeEvent(QEvent* event)
+ { return QGraphicsWidget::changeEvent(event); }
+
+ bool call_event(QEvent *e)
+ { return event(e); }
+
+ void call_focusInEvent(QFocusEvent* event)
+ { return QGraphicsWidget::focusInEvent(event); }
+
+ bool call_focusNextPrevChild(bool next)
+ { return QGraphicsWidget::focusNextPrevChild(next); }
+
+ void call_focusOutEvent(QFocusEvent* event)
+ { return QGraphicsWidget::focusOutEvent(event); }
+
+ void call_hideEvent(QHideEvent* event)
+ { return QGraphicsWidget::hideEvent(event); }
+
+ QVariant call_itemChange(QGraphicsItem::GraphicsItemChange change, QVariant const& value)
+ { return QGraphicsWidget::itemChange(change, value); }
+
+ void call_moveEvent(QGraphicsSceneMoveEvent* event)
+ { return QGraphicsWidget::moveEvent(event); }
+
+ void call_polishEvent()
+ { return QGraphicsWidget::polishEvent(); }
+
+ QVariant call_propertyChange(QString const& propertyName, QVariant const& value)
+ { return QGraphicsWidget::propertyChange(propertyName, value); }
+
+ void call_resizeEvent(QGraphicsSceneResizeEvent* event)
+ { return QGraphicsWidget::resizeEvent(event); }
+
+ bool call_sceneEvent(QEvent* event)
+ { return QGraphicsWidget::sceneEvent(event); }
+
+ void call_showEvent(QShowEvent* event)
+ { return QGraphicsWidget::showEvent(event); }
+
+ QSizeF call_sizeHint(Qt::SizeHint which, QSizeF const& constraint = QSizeF()) const
+ { return QGraphicsWidget::sizeHint(which, constraint); }
+
+ void call_updateGeometry()
+ { return QGraphicsWidget::updateGeometry(); }
+
+ int eventCount;
+ Qt::LayoutDirection m_painterLayoutDirection;
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ m_painterLayoutDirection = painter->layoutDirection();
+ QGraphicsWidget::paint(painter, option, widget);
+ if (hasFocus()) {
+ painter->setPen(Qt::DotLine);
+ painter->drawRect(rect());
+ }
+ //painter->drawText(QPointF(0,15), data(0).toString());
+ }
+
+protected:
+ bool event(QEvent *event)
+ {
+ eventCount++;
+ return QGraphicsWidget::event(event);
+ }
+};
+
+// This will be called before the first test function is executed.
+// It is only called once.
+void tst_QGraphicsWidget::initTestCase()
+{
+}
+
+// This will be called after the last test function is executed.
+// It is only called once.
+void tst_QGraphicsWidget::cleanupTestCase()
+{
+}
+
+// This will be called before each test function is executed.
+void tst_QGraphicsWidget::init()
+{
+}
+
+// This will be called after every test function.
+void tst_QGraphicsWidget::cleanup()
+{
+}
+
+class SizeHinter : public QGraphicsWidget
+{
+public:
+ SizeHinter(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0,
+ const QSizeF &min = QSizeF(5,5),
+ const QSizeF &pref = QSizeF(50, 50),
+ const QSizeF &max = QSizeF(500, 500))
+ : QGraphicsWidget(parent, wFlags)
+ {
+ m_sizes[Qt::MinimumSize] = min;
+ m_sizes[Qt::PreferredSize] = pref;
+ m_sizes[Qt::MaximumSize] = max;
+
+ }
+ void setSizeHint(Qt::SizeHint which, const QSizeF &newSizeHint)
+ {
+ m_sizes[which] = newSizeHint;
+ }
+
+protected:
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const
+ {
+ Q_UNUSED(constraint);
+ return m_sizes[which];
+ }
+private:
+ QSizeF m_sizes[4];
+};
+
+void tst_QGraphicsWidget::qgraphicswidget()
+{
+ SubQGraphicsWidget widget;
+ QVERIFY(widget.isVisible());
+
+ QVERIFY(!widget.isWindow());
+ QCOMPARE(widget.boundingRect(), QRectF(0, 0, 0, 0));
+ QCOMPARE(widget.focusWidget(), (QGraphicsWidget*)0);
+ QCOMPARE(widget.focusPolicy(), Qt::NoFocus);
+ QCOMPARE(widget.font(), QFont());
+ QCOMPARE(widget.geometry(), QRectF(widget.pos(), widget.size()));
+ QCOMPARE(widget.layout(), (QGraphicsLayout*)0);
+ QCOMPARE(widget.layoutDirection(), Qt::LeftToRight);
+ QCOMPARE(widget.palette(), QPalette());
+ QCOMPARE(widget.parentWidget(), (QGraphicsWidget*)0);
+ QCOMPARE(widget.rect(), QRectF(QPointF(), widget.size()));
+ QCOMPARE(widget.size(), QSizeF(0, 0));
+ QVERIFY(widget.style() != (QStyle*)0);
+ QCOMPARE(widget.testAttribute(Qt::WA_AcceptDrops), false);
+ QCOMPARE(widget.topLevelWidget(), (QGraphicsWidget*)&widget);
+ QCOMPARE(widget.type(), (int)QGraphicsWidget::Type);
+ QCOMPARE(widget.call_propertyChange(QString(), QVariant()), QVariant());
+ widget.call_sizeHint(Qt::PreferredSize, QSizeF());
+
+ QGraphicsScene scene;
+ QGraphicsWidget *parent = new QGraphicsWidget;
+ SizeHinter *child = new SizeHinter(parent);
+
+ QCOMPARE(child->minimumSize(), QSizeF(5, 5));
+}
+
+void tst_QGraphicsWidget::activation()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsWidget *window1 = new QGraphicsWidget(0, Qt::Window);
+ QGraphicsWidget *window2 = new QGraphicsWidget(0, Qt::Window);
+ QVERIFY(!widget->isActiveWindow());
+ QVERIFY(!window1->isActiveWindow());
+ QVERIFY(!window2->isActiveWindow());
+
+ QGraphicsScene scene;
+ scene.addItem(widget);
+ scene.addItem(window1);
+ scene.addItem(window2);
+
+ QVERIFY(!widget->isActiveWindow());
+ QVERIFY(!window1->isActiveWindow());
+ QVERIFY(!window2->isActiveWindow());
+
+ QEvent activateEvent(QEvent::WindowActivate);
+ QApplication::sendEvent(&scene, &activateEvent);
+
+ QVERIFY(!widget->isActiveWindow());
+ QVERIFY(window1->isActiveWindow());
+ QVERIFY(!window2->isActiveWindow());
+
+ scene.setActiveWindow(window1);
+ QVERIFY(!widget->isActiveWindow());
+ QVERIFY(window1->isActiveWindow());
+ QVERIFY(!window2->isActiveWindow());
+
+ QEvent deactivateEvent(QEvent::WindowDeactivate);
+ QApplication::sendEvent(&scene, &deactivateEvent);
+
+ QVERIFY(!widget->isActiveWindow());
+ QVERIFY(!window1->isActiveWindow());
+ QVERIFY(!window2->isActiveWindow());
+}
+
+void tst_QGraphicsWidget::boundingRect_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::newRow("null") << QSizeF(0, 0);
+ QTest::newRow("avg") << QSizeF(10, 10);
+}
+
+// QRectF boundingRect() const public
+void tst_QGraphicsWidget::boundingRect()
+{
+ QFETCH(QSizeF, size);
+ SubQGraphicsWidget widget;
+ widget.resize(size);
+ QCOMPARE(widget.rect(), QRectF(QPointF(), size));
+ QCOMPARE(widget.boundingRect(), QRectF(QPointF(0, 0), size));
+}
+
+void tst_QGraphicsWidget::dumpFocusChain_data()
+{
+ QTest::addColumn<bool>("scene");
+ QTest::addColumn<int>("children");
+ QTest::addColumn<bool>("setFocus");
+ QTest::newRow("empty world") << false << 0 << false;
+ QTest::newRow("one world") << true << 2 << false;
+ QTest::newRow("one world w/focus") << true << 2 << true;
+}
+
+// void dumpFocusChain(QGraphicsScene* scene) public (static)
+void tst_QGraphicsWidget::dumpFocusChain()
+{
+ // ### this test is very strange...
+ QFETCH(bool, scene);
+ SubQGraphicsWidget *parent = new SubQGraphicsWidget;
+ QGraphicsScene *theScene = 0;
+ if (scene) {
+ theScene = new QGraphicsScene(this);
+ theScene->addItem(parent);
+ }
+ QFETCH(int, children);
+ QFETCH(bool, setFocus);
+ for (int i = 0; i < children; ++i) {
+ SubQGraphicsWidget *widget = new SubQGraphicsWidget(parent);
+ if (setFocus) {
+ widget->setFlag(QGraphicsItem::ItemIsFocusable, true);
+ if (scene)
+ theScene->setFocusItem(widget);
+ }
+ }
+
+ if (!scene)
+ delete parent;
+}
+
+void tst_QGraphicsWidget::focusWidget_data()
+{
+ QTest::addColumn<int>("childCount");
+ QTest::addColumn<int>("childWithFocus");
+ QTest::newRow("none") << 0 << 0;
+ QTest::newRow("first") << 3 << 0;
+ QTest::newRow("last") << 3 << 2;
+}
+
+// QGraphicsWidget* focusWidget() const public
+void tst_QGraphicsWidget::focusWidget()
+{
+ SubQGraphicsWidget *parent = new SubQGraphicsWidget;
+ QCOMPARE(parent->focusWidget(), (QGraphicsWidget *)0);
+ QGraphicsScene scene;
+ QEvent windowActivate(QEvent::WindowActivate);
+ qApp->sendEvent(&scene, &windowActivate);
+ scene.addItem(parent);
+
+ QFETCH(int, childCount);
+ QList<SubQGraphicsWidget *> children;
+ for (int i = 0; i < childCount; ++i) {
+ SubQGraphicsWidget *widget = new SubQGraphicsWidget(parent);
+ widget->setFlag(QGraphicsItem::ItemIsFocusable, true);
+ children.append(widget);
+ }
+ if (childCount > 0) {
+ QFETCH(int, childWithFocus);
+ SubQGraphicsWidget *widget = children[childWithFocus];
+ widget->setFocus();
+ QTRY_VERIFY(widget->hasFocus());
+ QCOMPARE(parent->focusWidget(), static_cast<QGraphicsWidget*>(widget));
+ }
+}
+
+void tst_QGraphicsWidget::focusWidget2()
+{
+ QGraphicsScene scene;
+ QEvent windowActivate(QEvent::WindowActivate);
+ qApp->sendEvent(&scene, &windowActivate);
+
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ EventSpy focusInSpy(widget, QEvent::FocusIn);
+ EventSpy focusOutSpy(widget, QEvent::FocusOut);
+
+ scene.addItem(widget);
+
+ QTRY_VERIFY(!widget->hasFocus());
+ widget->setFocusPolicy(Qt::StrongFocus);
+ QTRY_VERIFY(!widget->hasFocus());
+
+ QGraphicsWidget *subWidget = new QGraphicsWidget(widget);
+ QTRY_VERIFY(!subWidget->hasFocus());
+
+ scene.setFocus();
+
+ QTRY_VERIFY(!widget->hasFocus());
+ QTRY_VERIFY(!subWidget->hasFocus());
+
+ widget->setFocus();
+
+ QTRY_VERIFY(widget->hasFocus());
+ QTRY_COMPARE(focusInSpy.count(), 1);
+ QTRY_VERIFY(!subWidget->hasFocus());
+
+ QGraphicsWidget *otherSubWidget = new QGraphicsWidget;
+ EventSpy otherFocusInSpy(otherSubWidget, QEvent::FocusIn);
+ EventSpy otherFocusOutSpy(otherSubWidget, QEvent::FocusOut);
+
+ otherSubWidget->setFocusPolicy(Qt::StrongFocus);
+ otherSubWidget->setParentItem(widget);
+
+ QTRY_VERIFY(widget->hasFocus());
+ QCOMPARE(scene.focusItem(), (QGraphicsItem *)widget);
+ QTRY_VERIFY(!subWidget->hasFocus());
+ QTRY_VERIFY(!otherSubWidget->hasFocus());
+
+ widget->hide();
+ QTRY_VERIFY(!widget->hasFocus()); // lose but still has subfocus
+ QCOMPARE(focusInSpy.count(), 1);
+ QCOMPARE(focusOutSpy.count(), 1);
+
+ widget->show();
+ QTRY_VERIFY(!widget->hasFocus()); // no regain
+ QCOMPARE(focusInSpy.count(), 1);
+ QCOMPARE(focusOutSpy.count(), 1);
+
+ widget->hide();
+
+ // try to setup subFocus on item that can't take focus
+ subWidget->setFocus();
+ QTRY_VERIFY(!subWidget->hasFocus());
+ QVERIFY(!scene.focusItem()); // but isn't the scene's focus item
+
+ // try to setup subFocus on item that can take focus
+ otherSubWidget->setFocus();
+ QTRY_VERIFY(!otherSubWidget->hasFocus());
+ QCOMPARE(widget->focusWidget(), otherSubWidget);
+ QVERIFY(!scene.focusItem()); // but isn't the scene's focus item
+
+ widget->show();
+
+ QTRY_COMPARE(scene.focusItem(), (QGraphicsItem *)otherSubWidget); // but isn't the scene's focus item
+ QCOMPARE(otherFocusInSpy.count(), 1);
+ QCOMPARE(otherFocusOutSpy.count(), 0);
+
+ delete otherSubWidget;
+
+ QTRY_COMPARE(otherFocusOutSpy.count(), 1);
+ QVERIFY(!scene.focusItem());
+ QVERIFY(!widget->focusWidget());
+}
+
+class FocusWatchWidget : public QGraphicsWidget
+{
+public:
+ FocusWatchWidget(QGraphicsItem *parent = 0) : QGraphicsWidget(parent) { gotFocusInCount = 0; gotFocusOutCount = 0; }
+ int gotFocusInCount, gotFocusOutCount;
+protected:
+ void focusInEvent(QFocusEvent *fe) { gotFocusInCount++; QGraphicsWidget::focusInEvent(fe); }
+ void focusOutEvent(QFocusEvent *fe) { gotFocusOutCount++; QGraphicsWidget::focusOutEvent(fe); }
+};
+
+void tst_QGraphicsWidget::focusWidget3()
+{
+ QGraphicsScene scene;
+ QEvent windowActivate(QEvent::WindowActivate);
+ qApp->sendEvent(&scene, &windowActivate);
+
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ FocusWatchWidget *subWidget = new FocusWatchWidget(widget);
+ subWidget->setFocusPolicy(Qt::StrongFocus);
+
+ scene.addItem(widget);
+ widget->show();
+
+ QTRY_VERIFY(!widget->hasFocus());
+ QTRY_VERIFY(!subWidget->hasFocus());
+
+ subWidget->setFocus();
+ QCOMPARE(subWidget->gotFocusInCount, 1);
+ QCOMPARE(subWidget->gotFocusOutCount, 0);
+ widget->hide();
+ QCOMPARE(subWidget->gotFocusOutCount, 1);
+}
+
+Q_DECLARE_METATYPE(Qt::FocusPolicy)
+void tst_QGraphicsWidget::focusPolicy_data()
+{
+ QTest::addColumn<Qt::FocusPolicy>("focusPolicy1");
+ QTest::addColumn<Qt::FocusPolicy>("focusPolicy2");
+
+ for (int i = 0; i < 25; ++i) {
+ QTestData &data = QTest::newRow(QString("%1").arg(i).toLatin1());
+ switch(i % 5) {
+ case 0: data << Qt::TabFocus; break;
+ case 1: data << Qt::ClickFocus; break;
+ case 2: data << Qt::StrongFocus; break;
+ case 3: data << Qt::WheelFocus; break;
+ case 4: data << Qt::NoFocus; break;
+ }
+ switch(i / 5) {
+ case 0: data << Qt::TabFocus; break;
+ case 1: data << Qt::ClickFocus; break;
+ case 2: data << Qt::StrongFocus; break;
+ case 3: data << Qt::WheelFocus; break;
+ case 4: data << Qt::NoFocus; break;
+ }
+ }
+}
+
+// Qt::FocusPolicy focusPolicy() const public
+void tst_QGraphicsWidget::focusPolicy()
+{
+ QGraphicsScene scene;
+ QEvent windowActivate(QEvent::WindowActivate);
+ qApp->sendEvent(&scene, &windowActivate);
+
+ SubQGraphicsWidget *widget = new SubQGraphicsWidget;
+ scene.addItem(widget);
+ QTRY_COMPARE(Qt::NoFocus, widget->focusPolicy());
+
+ QFETCH(Qt::FocusPolicy, focusPolicy1);
+ widget->setFocusPolicy(focusPolicy1);
+ QTRY_COMPARE(widget->focusPolicy(), focusPolicy1);
+ bool isFocusable = widget->flags() & QGraphicsItem::ItemIsFocusable;
+ bool wasFocusable = isFocusable;
+ QTRY_VERIFY(isFocusable == (focusPolicy1 != Qt::NoFocus));
+ widget->setFocus();
+ QTRY_COMPARE(widget->hasFocus(), isFocusable);
+
+ QFETCH(Qt::FocusPolicy, focusPolicy2);
+ widget->setFocusPolicy(focusPolicy2);
+ QCOMPARE(widget->focusPolicy(), focusPolicy2);
+ isFocusable = widget->flags() & QGraphicsItem::ItemIsFocusable;
+ QVERIFY(isFocusable == (focusPolicy2 != Qt::NoFocus));
+ QCOMPARE(widget->hasFocus(), wasFocusable && isFocusable);
+}
+
+void tst_QGraphicsWidget::font_data()
+{
+ QTest::addColumn<QString>("fontName");
+ QTest::newRow("Helvetica") << "Helvetica";
+}
+
+// QFont font() const public
+void tst_QGraphicsWidget::font()
+{
+ QFETCH(QString, fontName);
+ SubQGraphicsWidget widget;
+ QCOMPARE(widget.font(), QFont());
+
+ QFont font(fontName);
+ widget.setFont(font);
+ QCOMPARE(widget.font().family(), font.family());
+}
+
+void tst_QGraphicsWidget::fontPropagatesResolveToChildren()
+{
+ QGraphicsWidget *root = new QGraphicsWidget();
+ QGraphicsWidget *child1 = new QGraphicsWidget(root);
+
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ QFont font;
+ font.setItalic(true);
+ root->setFont(font);
+
+ QGraphicsWidget *child2 = new QGraphicsWidget(root);
+ QGraphicsWidget *child3 = new QGraphicsWidget();
+ child3->setParentItem(root);
+
+ QGraphicsView view;
+ view.setScene(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QCOMPARE(font.resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(root->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(child1->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(child2->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(child3->font().resolve(), uint(QFont::StyleResolved));
+}
+
+void tst_QGraphicsWidget::fontPropagatesResolveToGrandChildren()
+{
+ QGraphicsWidget *root = new QGraphicsWidget();
+ QGraphicsWidget *child1 = new QGraphicsWidget(root);
+ QGraphicsWidget *grandChild1 = new QGraphicsWidget(child1);
+
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ QFont font;
+ font.setItalic(true);
+ root->setFont(font);
+
+ QGraphicsWidget *child2 = new QGraphicsWidget(root);
+ QGraphicsWidget *grandChild2 = new QGraphicsWidget(child2);
+ QGraphicsWidget *grandChild3 = new QGraphicsWidget(child2);
+
+ QGraphicsWidget *child3 = new QGraphicsWidget();
+ QGraphicsWidget *grandChild4 = new QGraphicsWidget(child3);
+ QGraphicsWidget *grandChild5 = new QGraphicsWidget(child3);
+ child3->setParentItem(root);
+ grandChild5->setParentItem(child3);
+
+ QGraphicsView view;
+ view.setScene(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QCOMPARE(font.resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild1->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild2->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild3->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild4->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild5->font().resolve(), uint(QFont::StyleResolved));
+}
+
+void tst_QGraphicsWidget::fontPropagatesResolveViaNonWidget()
+{
+ QGraphicsWidget *root = new QGraphicsWidget();
+ QGraphicsPixmapItem *child1 = new QGraphicsPixmapItem(root);
+ QGraphicsWidget *grandChild1 = new QGraphicsWidget(child1);
+
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ QFont font;
+ font.setItalic(true);
+ root->setFont(font);
+
+ QGraphicsPixmapItem *child2 = new QGraphicsPixmapItem(root);
+ QGraphicsWidget *grandChild2 = new QGraphicsWidget(child2);
+ QGraphicsWidget *grandChild3 = new QGraphicsWidget(child2);
+
+ QGraphicsPixmapItem *child3 = new QGraphicsPixmapItem();
+ QGraphicsWidget *grandChild4 = new QGraphicsWidget(child3);
+ QGraphicsWidget *grandChild5 = new QGraphicsWidget(child3);
+ child3->setParentItem(root);
+ grandChild5->setParentItem(child3);
+
+ QGraphicsView view;
+ view.setScene(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QCOMPARE(font.resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild1->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild2->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild3->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild4->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild5->font().resolve(), uint(QFont::StyleResolved));
+}
+
+void tst_QGraphicsWidget::fontPropagatesResolveFromScene()
+{
+ QGraphicsWidget *root = new QGraphicsWidget();
+ QGraphicsWidget *child1 = new QGraphicsWidget(root);
+ QGraphicsWidget *grandChild1 = new QGraphicsWidget(child1);
+
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ QFont font;
+ font.setItalic(true);
+ scene.setFont(font);
+
+ QGraphicsWidget *child2 = new QGraphicsWidget(root);
+ QGraphicsWidget *grandChild2 = new QGraphicsWidget(child2);
+ QGraphicsWidget *grandChild3 = new QGraphicsWidget(child2);
+
+ QGraphicsWidget *child3 = new QGraphicsWidget();
+ QGraphicsWidget *grandChild4 = new QGraphicsWidget(child3);
+ QGraphicsWidget *grandChild5 = new QGraphicsWidget(child3);
+ child3->setParentItem(root);
+ grandChild5->setParentItem(child3);
+
+ QGraphicsView view;
+ view.setScene(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QCOMPARE(font.resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(root->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(child1->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(child2->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(child3->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild1->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild2->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild3->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild4->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild5->font().resolve(), uint(QFont::StyleResolved));
+}
+
+void tst_QGraphicsWidget::fontPropagatesResolveInParentChange()
+{
+ QGraphicsWidget *root = new QGraphicsWidget();
+
+ QGraphicsWidget *child1 = new QGraphicsWidget(root);
+ QGraphicsWidget *grandChild1 = new QGraphicsWidget(child1);
+
+ QGraphicsWidget *child2 = new QGraphicsWidget(root);
+ QGraphicsWidget *grandChild2 = new QGraphicsWidget(child2);
+
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ QFont italicFont;
+ italicFont.setItalic(true);
+ child1->setFont(italicFont);
+
+ QFont boldFont;
+ boldFont.setBold(true);
+ child2->setFont(boldFont);
+
+ QVERIFY(grandChild1->font().italic());
+ QVERIFY(!grandChild1->font().bold());
+ QVERIFY(!grandChild2->font().italic());
+ QVERIFY(grandChild2->font().bold());
+
+ QCOMPARE(grandChild1->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild2->font().resolve(), uint(QFont::WeightResolved));
+
+ grandChild2->setParentItem(child1);
+
+ QGraphicsView view;
+ view.setScene(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QVERIFY(grandChild1->font().italic());
+ QVERIFY(!grandChild1->font().bold());
+ QVERIFY(grandChild2->font().italic());
+ QVERIFY(!grandChild2->font().bold());
+
+ QCOMPARE(grandChild1->font().resolve(), uint(QFont::StyleResolved));
+ QCOMPARE(grandChild2->font().resolve(), uint(QFont::StyleResolved));
+
+}
+
+void tst_QGraphicsWidget::fontPropagation()
+{
+ QGraphicsWidget *root = new QGraphicsWidget;
+ QGraphicsWidget *child0 = new QGraphicsWidget(root);
+ QGraphicsWidget *child1 = new QGraphicsWidget(child0);
+ QGraphicsWidget *child2 = new QGraphicsWidget(child1);
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ // Check that only the application fonts apply.
+ QFont appFont = QApplication::font();
+ QCOMPARE(scene.font(), appFont);
+ QCOMPARE(root->font(), appFont);
+ QCOMPARE(child0->font(), appFont);
+ QCOMPARE(child1->font(), appFont);
+
+ // Set child0's Text, and set ToolTipBase on child1.
+ QFont boldFont;
+ boldFont.setBold(true);
+ child0->setFont(boldFont);
+ QFont italicFont;
+ italicFont.setItalic(true);
+ child1->setFont(italicFont);
+
+ // Check that the above settings propagate correctly.
+ QCOMPARE(root->font(), appFont);
+ QCOMPARE(scene.font(), appFont);
+ QVERIFY(child0->font().bold());
+ QVERIFY(!child0->font().italic());
+ QVERIFY(child1->font().bold());
+ QVERIFY(child1->font().italic());
+ QVERIFY(child2->font().bold());
+ QVERIFY(child2->font().italic());
+
+ QGraphicsWidget *child3 = new QGraphicsWidget(child2);
+ QVERIFY(child3->font().bold());
+ QVERIFY(child3->font().italic());
+
+ QGraphicsWidget *child4 = new QGraphicsWidget;
+ child4->setParentItem(child3);
+ QVERIFY(child4->font().bold());
+ QVERIFY(child4->font().italic());
+
+ // Replace the app font for child2. Button should propagate but Text
+ // should still be ignored. The previous ToolTipBase setting is gone.
+ QFont sizeFont;
+ sizeFont.setPointSize(43);
+ child1->setFont(sizeFont);
+
+ // Check that the above settings propagate correctly.
+ QCOMPARE(root->font(), appFont);
+ QCOMPARE(scene.font(), appFont);
+ QVERIFY(child0->font().bold());
+ QVERIFY(!child0->font().italic());
+ QVERIFY(child1->font().bold());
+ QVERIFY(!child1->font().italic());
+ QCOMPARE(child1->font().pointSize(), 43);
+ QVERIFY(child2->font().bold());
+ QVERIFY(!child2->font().italic());
+ QCOMPARE(child2->font().pointSize(), 43);
+}
+
+void tst_QGraphicsWidget::fontChangedEvent()
+{
+ QGraphicsWidget *root = new QGraphicsWidget;
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ // Check that only the application fonts apply.
+ QFont appFont = QApplication::font();
+ QCOMPARE(scene.font(), appFont);
+ QCOMPARE(root->font(), appFont);
+
+ EventSpy rootSpyFont(root, QEvent::FontChange);
+ EventSpy rootSpyPolish(root, QEvent::Polish);
+ QTRY_COMPARE(rootSpyFont.count(), 0);
+ QTRY_COMPARE(rootSpyPolish.count(), 1);
+ //The font is still the same so no fontChangeEvent
+ QTRY_COMPARE(rootSpyFont.count(), 0);
+
+ QFont font;
+ font.setPointSize(43);
+ root->setFont(font);
+ //The font changed
+ QTRY_COMPARE(rootSpyFont.count(), 1);
+
+ //then roll back to the default one.
+ root->setFont(appFont);
+ //The font changed
+ QTRY_COMPARE(rootSpyFont.count(), 2);
+}
+
+void tst_QGraphicsWidget::fontPropagationWidgetItemWidget()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsRectItem *rect = new QGraphicsRectItem(widget);
+ QGraphicsWidget *widget2 = new QGraphicsWidget(rect);
+
+ QGraphicsScene scene;
+ scene.addItem(widget);
+
+ QFont font;
+ font.setPointSize(43);
+ widget->setFont(font);
+
+ QCOMPARE(widget2->font().pointSize(), 43);
+ QCOMPARE(widget2->font().resolve(), uint(QFont::SizeResolved));
+
+ widget->setFont(QFont());
+
+ QCOMPARE(widget2->font().pointSize(), qApp->font().pointSize());
+ QCOMPARE(widget2->font().resolve(), QFont().resolve());
+}
+
+void tst_QGraphicsWidget::fontPropagationSceneChange()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsRectItem *rect = new QGraphicsRectItem(widget);
+ QGraphicsWidget *widget2 = new QGraphicsWidget(rect);
+
+ QGraphicsScene scene;
+ QGraphicsScene scene2;
+
+ QFont font;
+ font.setPointSize(47);
+ scene.setFont(font);
+
+ QFont font2;
+ font2.setPointSize(74);
+ scene2.setFont(font2);
+
+ scene.addItem(widget);
+ QCOMPARE(widget2->font().pointSize(), 47);
+ scene2.addItem(widget);
+ QCOMPARE(widget2->font().pointSize(), 74);
+}
+
+void tst_QGraphicsWidget::geometry_data()
+{
+ QTest::addColumn<QPointF>("pos");
+ QTest::addColumn<QSizeF>("size");
+ QTest::newRow("null, null") << QPointF() << QSizeF(0, 0);
+ QTest::newRow("null, normal") << QPointF() << QSizeF(10, 10);
+ QTest::newRow("neg, normal") << QPointF(-5, -5) << QSizeF(10, 10);
+}
+
+// QRectF geometry() const public
+void tst_QGraphicsWidget::geometry()
+{
+ SubQGraphicsWidget widget;
+ QCOMPARE(widget.geometry(), QRectF(widget.pos(), widget.size()));
+ QSignalSpy spy(&widget, SIGNAL(geometryChanged()));
+ QFETCH(QPointF, pos);
+ QFETCH(QSizeF, size);
+ widget.setPos(pos);
+ widget.resize(size);
+ if (!size.isNull() && !pos.isNull())
+ QCOMPARE(spy.count(), 2);
+ if (!size.isNull() && pos.isNull())
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(widget.geometry(), QRectF(pos, size));
+}
+
+void tst_QGraphicsWidget::geometryChanged()
+{
+ QGraphicsWidget w;
+ w.setGeometry(0, 0, 200, 200);
+ QCOMPARE(w.geometry(), QRectF(0, 0, 200, 200));
+ QSignalSpy spy(&w, SIGNAL(geometryChanged()));
+ w.setGeometry(0, 0, 100, 100);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(w.geometry(), QRectF(0, 0, 100, 100));
+ w.setPos(10, 10);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(w.geometry(), QRectF(10, 10, 100, 100));
+
+}
+
+void tst_QGraphicsWidget::width()
+{
+ QGraphicsWidget w;
+ QCOMPARE(w.property("width").toReal(), qreal(0));
+ QSignalSpy spy(&w, SIGNAL(widthChanged()));
+ w.setProperty("width", qreal(50));
+ QCOMPARE(w.property("width").toReal(), qreal(50));
+ QCOMPARE(spy.count(), 1);
+ //calling old school setGeometry should work too
+ w.setGeometry(0, 0, 200, 200);
+ QCOMPARE(spy.count(), 2);
+}
+
+void tst_QGraphicsWidget::height()
+{
+ QGraphicsWidget w;
+ QCOMPARE(w.property("height").toReal(), qreal(0));
+ QSignalSpy spy(&w, SIGNAL(heightChanged()));
+ w.setProperty("height", qreal(50));
+ QCOMPARE(w.property("height").toReal(), qreal(50));
+ QCOMPARE(spy.count(), 1);
+ //calling old school setGeometry should work too
+ w.setGeometry(0, 0, 200, 200);
+ QCOMPARE(spy.count(), 2);
+}
+
+void tst_QGraphicsWidget::getContentsMargins_data()
+{
+ QTest::addColumn<qreal>("left");
+ QTest::addColumn<qreal>("top");
+ QTest::addColumn<qreal>("right");
+ QTest::addColumn<qreal>("bottom");
+ QTest::newRow("null") << (qreal)0 << (qreal)0 << (qreal)0 << (qreal)0;
+ QTest::newRow("something") << (qreal)10 << (qreal)5 << (qreal)3 << (qreal)7;
+ QTest::newRow("real") << (qreal)1.7 << (qreal)5.9 << (qreal)3.2 << (qreal)9.7;
+}
+
+// void getContentsMargins(qreal* left, qreal* top, qreal* right, qreal* bottom) const public
+void tst_QGraphicsWidget::getContentsMargins()
+{
+ qreal gleft;
+ qreal gtop;
+ qreal gright;
+ qreal gbottom;
+
+ SubQGraphicsWidget widget;
+ widget.getContentsMargins(&gleft, &gtop, &gright, &gbottom);
+ QCOMPARE(gleft, (qreal)0);
+ QCOMPARE(gtop, (qreal)0);
+ QCOMPARE(gright, (qreal)0);
+ QCOMPARE(gbottom, (qreal)0);
+
+ QFETCH(qreal, left);
+ QFETCH(qreal, top);
+ QFETCH(qreal, right);
+ QFETCH(qreal, bottom);
+ int oldEventCounts = widget.eventCount;
+ widget.setContentsMargins(left, top, right, bottom);
+ QVERIFY(left == 0 || oldEventCounts != widget.eventCount);
+ widget.getContentsMargins(&gleft, &gtop, &gright, &gbottom);
+ QCOMPARE(gleft, left);
+ QCOMPARE(gtop, top);
+ QCOMPARE(gright, right);
+ QCOMPARE(gbottom, bottom);
+}
+
+Q_DECLARE_METATYPE(Qt::LayoutDirection)
+void tst_QGraphicsWidget::initStyleOption_data()
+{
+ QTest::addColumn<bool>("enabled");
+ QTest::addColumn<bool>("focus");
+ QTest::addColumn<bool>("underMouse");
+ QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
+ QTest::addColumn<QSizeF>("size");
+ QTest::addColumn<QPalette>("palette");
+ QTest::addColumn<QString>("fontName");
+ QTest::newRow("none") << false << false << false << Qt::LeftToRight << QSizeF(0, 0) << QPalette() << QString();
+ QTest::newRow("all") << true << true << true << Qt::RightToLeft << QSizeF(300, 300) << QPalette(Qt::magenta) << "Helvetica";
+ QTest::newRow("rand") << true << false << false << Qt::RightToLeft << QSizeF(1, 0) << QPalette(Qt::darkCyan) << "Times";
+}
+
+// void initStyleOption(QStyleOption* option) const public
+void tst_QGraphicsWidget::initStyleOption()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QApplication::setActiveWindow(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
+
+ view.setAlignment(Qt::AlignTop | Qt::AlignLeft);
+ SubQGraphicsWidget *widget = new SubQGraphicsWidget;
+ widget->setAcceptsHoverEvents(true);
+ QStyleOption option;
+ scene.addItem(widget);
+
+ QFETCH(QSizeF, size);
+ widget->resize(size);
+
+ QFETCH(bool, enabled);
+ widget->setEnabled(enabled);
+ QFETCH(bool, focus);
+ if (focus) {
+ widget->setFlag(QGraphicsItem::ItemIsFocusable, true);
+ widget->setFocus();
+ QVERIFY(widget->hasFocus());
+ }
+ QFETCH(bool, underMouse);
+ if (underMouse) {
+ view.resize(300, 300);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ sendMouseMove(view.viewport(), view.mapFromScene(widget->mapToScene(widget->boundingRect().center())));
+ }
+
+ QFETCH(QPalette, palette);
+ widget->setPalette(palette);
+
+ QFETCH(QString, fontName);
+ widget->setFont(QFont(fontName));
+
+ // The test
+ widget->initStyleOption(&option);
+
+ bool isEnabled = option.state & QStyle::State_Enabled;
+ QCOMPARE(isEnabled, enabled);
+ bool hasFocus = option.state & QStyle::State_HasFocus;
+ QCOMPARE(hasFocus, focus);
+ bool isUnderMouse = option.state & QStyle::State_MouseOver;
+#ifndef Q_OS_WINCE
+ QCOMPARE(isUnderMouse, underMouse);
+#endif
+ // if (layoutDirection != Qt::LeftToRight)
+ //QEXPECT_FAIL("", "QApplicaiton::layoutDirection doesn't propagate to QGraphicsWidget", Continue);
+ //QCOMPARE(option.direction, layoutDirection);
+ QCOMPARE(option.rect, QRectF(QPointF(), size).toRect());
+ QCOMPARE(option.palette, palette.resolve(QApplication::palette()));
+ QCOMPARE(option.fontMetrics, QFontMetrics(widget->font()));
+}
+
+void tst_QGraphicsWidget::layout_data()
+{
+ QTest::addColumn<int>("childCount");
+ QTest::newRow("empty") << 0;
+ QTest::newRow("10") << 10;
+}
+
+// QGraphicsLayout* layout() const public
+void tst_QGraphicsWidget::layout()
+{
+ SubQGraphicsWidget widget;
+ widget.setContentsMargins(10, 5, 50, 100);
+ QCOMPARE(widget.layout(), (QGraphicsLayout *)0);
+ QFETCH(int, childCount);
+
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout;
+ QList<SubQGraphicsWidget*> children;
+ for (int i = 0; i < childCount; ++i) {
+ SubQGraphicsWidget *item = new SubQGraphicsWidget;
+ layout->addItem(item);
+ children.append(item);
+ }
+ QSignalSpy spy(&widget, SIGNAL(layoutChanged()));
+ widget.setLayout(layout);
+
+ QTRY_COMPARE(widget.layout(), static_cast<QGraphicsLayout*>(layout));
+ for (int i = 0; i < children.count(); ++i) {
+ SubQGraphicsWidget *item = children[i];
+ QCOMPARE(item->parentWidget(), (QGraphicsWidget *)&widget);
+ QVERIFY(item->geometry() != QRectF(0, 0, -1, -1));
+ }
+ QCOMPARE(spy.count(), 1);
+ // don't crash
+ widget.setLayout(0);
+}
+
+void tst_QGraphicsWidget::layoutDirection_data()
+{
+ QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
+ QTest::newRow("rtl") << Qt::RightToLeft;
+ QTest::newRow("ltr") << Qt::LeftToRight;
+}
+
+// Qt::LayoutDirection layoutDirection() const public
+void tst_QGraphicsWidget::layoutDirection()
+{
+ QFETCH(Qt::LayoutDirection, layoutDirection);
+ QGraphicsScene scene;
+ QGraphicsView *view = new QGraphicsView(&scene);
+ SubQGraphicsWidget widget;
+ scene.addItem(&widget);
+ QCOMPARE(widget.layoutDirection(), Qt::LeftToRight);
+ QCOMPARE(widget.testAttribute(Qt::WA_SetLayoutDirection), false);
+
+ QList<SubQGraphicsWidget*> children;
+ for (int i = 0; i < 10; ++i) {
+ SubQGraphicsWidget *item = new SubQGraphicsWidget(&widget);
+ children.append(item);
+ QCOMPARE(item->testAttribute(Qt::WA_SetLayoutDirection), false);
+ }
+ widget.setLayoutDirection(layoutDirection);
+ QCOMPARE(widget.testAttribute(Qt::WA_SetLayoutDirection), true);
+ view->show();
+ QTest::qWaitForWindowShown(view);
+ for (int i = 0; i < children.count(); ++i) {
+ QTRY_COMPARE(children[i]->layoutDirection(), layoutDirection);
+ QTRY_COMPARE(children[i]->testAttribute(Qt::WA_SetLayoutDirection), false);
+ view->repaint();
+ QTRY_COMPARE(children[i]->m_painterLayoutDirection, layoutDirection);
+ }
+ delete view;
+}
+
+void tst_QGraphicsWidget::paint_data()
+{
+ // currently QGraphicsWidget doesn't paint or do anything ...
+}
+
+// void paint(QPainter* painter, QStyleOptionGraphicsItem const* option, QWidget* widget) public
+void tst_QGraphicsWidget::paint()
+{
+ SubQGraphicsWidget widget;
+ QPainter painter;
+ QStyleOptionGraphicsItem option;
+ widget.paint(&painter, &option, 0); // check that widget = 0 works.
+}
+
+void tst_QGraphicsWidget::palettePropagation()
+{
+ QGraphicsWidget *root = new QGraphicsWidget;
+ QGraphicsWidget *child0 = new QGraphicsWidget(root);
+ QGraphicsWidget *child1 = new QGraphicsWidget(child0);
+ QGraphicsWidget *child2 = new QGraphicsWidget(child1);
+ QGraphicsScene scene;
+ scene.addItem(root);
+
+ // These colors are unlikely to be imposed on the default palette of
+ // QWidget ;-).
+ QColor sysPalText(21, 22, 23);
+ QColor sysPalToolTipBase(12, 13, 14);
+ QColor overridePalText(42, 43, 44);
+ QColor overridePalToolTipBase(45, 46, 47);
+ QColor sysPalButton(99, 98, 97);
+
+ // Check that only the application fonts apply.
+ QPalette appPal = QApplication::palette();
+ QCOMPARE(scene.palette(), appPal);
+ QCOMPARE(root->palette(), appPal);
+ QCOMPARE(child0->palette(), appPal);
+ QCOMPARE(child1->palette(), appPal);
+
+ // Set child0's Text, and set ToolTipBase on child1.
+ QPalette textPalette;
+ textPalette.setColor(QPalette::Text, overridePalText);
+ child0->setPalette(textPalette);
+ QPalette toolTipPalette;
+ toolTipPalette.setColor(QPalette::ToolTipBase, overridePalToolTipBase);
+ child1->setPalette(toolTipPalette);
+
+ // Check that the above settings propagate correctly.
+ QCOMPARE(root->palette(), appPal);
+ QCOMPARE(scene.palette(), appPal);
+ QCOMPARE(child0->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child0->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
+ QCOMPARE(child1->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child1->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
+ QCOMPARE(child2->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child2->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
+
+ QGraphicsWidget *child3 = new QGraphicsWidget(child2);
+ QCOMPARE(child3->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child3->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
+
+ QGraphicsWidget *child4 = new QGraphicsWidget;
+ child4->setParentItem(child3);
+ QCOMPARE(child4->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child4->palette().color(QPalette::ToolTipBase), overridePalToolTipBase);
+
+ // Replace the app palette for child2. Button should propagate but Text
+ // should still be ignored. The previous ToolTipBase setting is gone.
+ QPalette buttonPalette;
+ buttonPalette.setColor(QPalette::Button, sysPalButton);
+ child1->setPalette(buttonPalette);
+
+ QCOMPARE(root->palette(), appPal);
+ QCOMPARE(scene.palette(), appPal);
+ QCOMPARE(child0->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child0->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
+ QCOMPARE(child1->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child1->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
+ QCOMPARE(child1->palette().color(QPalette::Button), sysPalButton);
+ QCOMPARE(child2->palette().color(QPalette::Text), overridePalText);
+ QCOMPARE(child2->palette().color(QPalette::ToolTipBase), appPal.color(QPalette::ToolTipBase));
+ QCOMPARE(child2->palette().color(QPalette::Button), sysPalButton);
+}
+
+void tst_QGraphicsWidget::parentWidget_data()
+{
+ QTest::addColumn<int>("childrenCount");
+ QTest::newRow("0") << 0;
+ QTest::newRow("1") << 1;
+ QTest::newRow("10") << 10;
+}
+
+// QGraphicsWidget* parentWidget() const public
+void tst_QGraphicsWidget::parentWidget()
+{
+ QFETCH(int, childrenCount);
+ SubQGraphicsWidget standAlongWidget;
+ QGraphicsLineItem standAlongItem;
+
+ SubQGraphicsWidget widgetChild(&standAlongWidget);
+ SubQGraphicsWidget itemChild(&standAlongItem);
+
+ QCOMPARE(standAlongWidget.parentWidget(), (QGraphicsWidget*)0);
+ QCOMPARE(widgetChild.parentWidget(), static_cast<QGraphicsWidget*>(&standAlongWidget));
+ QCOMPARE(itemChild.parentWidget(), (QGraphicsWidget*)0);
+
+ for (int i = 0; i < childrenCount; ++i) {
+ SubQGraphicsWidget *item = new SubQGraphicsWidget(&standAlongWidget);
+ QCOMPARE(item->parentWidget(), static_cast<QGraphicsWidget*>(&standAlongWidget));
+ }
+}
+
+void tst_QGraphicsWidget::resize_data()
+{
+ QTest::addColumn<QSizeF>("size");
+ QTest::newRow("null") << QSizeF();
+ QTest::newRow("10x10") << QSizeF(10, 10);
+ QTest::newRow("10x-1") << QSizeF(10, -1);
+}
+
+// void resize(qreal w, qreal h) public
+void tst_QGraphicsWidget::resize()
+{
+ QFETCH(QSizeF, size);
+ SubQGraphicsWidget widget;
+
+ int oldEventCounts = widget.eventCount;
+ QSizeF oldSize = widget.size();
+ widget.resize(size);
+
+ QSizeF boundedSize = size.expandedTo(widget.minimumSize()).boundedTo(widget.maximumSize());
+ QCOMPARE(widget.eventCount, oldEventCounts + ((oldSize == boundedSize) ? 0 : 1));
+ QCOMPARE(widget.size(), boundedSize);
+}
+
+Q_DECLARE_METATYPE(Qt::WidgetAttribute)
+void tst_QGraphicsWidget::setAttribute_data()
+{
+ QTest::addColumn<Qt::WidgetAttribute>("attribute");
+ QTest::addColumn<bool>("supported");
+ QTest::newRow("WA_SetLayoutDirection") << Qt::WA_SetLayoutDirection << true;
+ QTest::newRow("WA_RightToLeft") << Qt::WA_RightToLeft << true;
+ QTest::newRow("WA_SetStyle") << Qt::WA_SetStyle << true;
+ QTest::newRow("WA_Resized") << Qt::WA_Resized << true;
+ QTest::newRow("unsupported") << Qt::WA_PaintOutsidePaintEvent << false;
+}
+
+// void setAttribute(Qt::WidgetAttribute attribute, bool on = true) public
+void tst_QGraphicsWidget::setAttribute()
+{
+ QFETCH(Qt::WidgetAttribute, attribute);
+ QFETCH(bool, supported);
+ SubQGraphicsWidget widget;
+ if (attribute == Qt::WA_PaintOutsidePaintEvent)
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsWidget::setAttribute: unsupported attribute 13");
+ widget.setAttribute(attribute);
+ QCOMPARE(widget.testAttribute(attribute), supported);
+}
+
+void tst_QGraphicsWidget::setStyle_data()
+{
+ QTest::addColumn<QString>("style");
+ QTest::newRow("null") << "";
+ QTest::newRow("cleanlooks") << "QCleanlooksStyle";
+}
+
+// void setStyle(QStyle* style) public
+void tst_QGraphicsWidget::setStyle()
+{
+ SubQGraphicsWidget widget;
+ QCleanlooksStyle cleanlooksStyle;
+
+ int oldEventCounts = widget.eventCount;
+
+ QFETCH(QString, style);
+ if (style == "QCleanlooksStyle") {
+ widget.setStyle(&cleanlooksStyle);
+ QCOMPARE(widget.style(), static_cast<QStyle*>(&cleanlooksStyle));
+ } else {
+ widget.setStyle(0);
+ QVERIFY(widget.style() != (QStyle *)0);
+ }
+ QCOMPARE(widget.eventCount, oldEventCounts + 1);
+ QCOMPARE(widget.testAttribute(Qt::WA_SetStyle), !style.isEmpty());
+
+ // cleanup
+ widget.setStyle(0);
+}
+
+void tst_QGraphicsWidget::setTabOrder_data()
+{
+ QTest::addColumn<int>("childrenCount");
+ QTest::newRow("0") << 0;
+ QTest::newRow("1") << 1;
+ QTest::newRow("10") << 10;
+}
+
+// void setTabOrder(QGraphicsWidget* first, QGraphicsWidget* second) public
+void tst_QGraphicsWidget::setTabOrder()
+{
+ QFETCH(int, childrenCount);
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QApplication::setActiveWindow(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
+
+ QGraphicsWidget *lastItem = 0;
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsWidget::setTabOrder(0, 0) is undefined");
+ QGraphicsWidget::setTabOrder(0, 0);
+
+ QList<SubQGraphicsWidget*> children;
+ for (int i = 0; i < childrenCount; ++i) {
+ SubQGraphicsWidget *item = new SubQGraphicsWidget();
+ item->setFocusPolicy(Qt::TabFocus);
+ children.append(item);
+ scene.addItem(item);
+ if (lastItem)
+ QGraphicsWidget::setTabOrder(lastItem, item);
+ lastItem = item;
+ }
+
+ if (!children.isEmpty()) {
+ QGraphicsWidget *first = children.first();
+ view.viewport()->setFocus();
+ QTRY_VERIFY(view.viewport()->hasFocus());
+ first->setFocus();
+ QVERIFY(first->hasFocus());
+ QVERIFY(scene.hasFocus());
+ QVERIFY(view.viewport()->hasFocus());
+
+ int currentItem = 0;
+ while (currentItem < children.count() - 1) {
+ QTest::keyPress(view.viewport(), Qt::Key_Tab);
+ ++currentItem;
+ QVERIFY(children[currentItem % children.size()]->hasFocus());
+ }
+ }
+}
+
+static bool compareFocusChain(QGraphicsView *view, const QList<QGraphicsItem*> &order)
+{
+ QGraphicsScene *scene = view->scene();
+ QStringList actual;
+ QGraphicsItem *oldFocusItem = scene->focusItem();
+ for (int i = 0; i < order.count(); ++i) {
+ QGraphicsItem *focusItem = scene->focusItem();
+ actual << focusItem->data(0).toString();
+ //qDebug() << "i:" << i << "expected:" << QString::number(uint(order.at(i)), 16) << QString::number(uint(focusItem), 16);
+ if (focusItem != order.at(i)) {
+ qDebug() << "actual:" << actual;
+ scene->setFocusItem(oldFocusItem);
+ return false;
+ }
+ if (i < order.count() - 1)
+ QTest::keyPress(view, Qt::Key_Tab);
+ }
+ scene->setFocusItem(oldFocusItem);
+ return true;
+}
+
+void tst_QGraphicsWidget::setTabOrderAndReparent()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
+
+ int i;
+ QGraphicsWidget *w1, *w2, *w3, *w4;
+ for (i = 1; i < 4; ++i) {
+ QGraphicsWidget *wid = new QGraphicsWidget;
+ wid->setFocusPolicy(Qt::StrongFocus);
+ wid->setData(0, QString::fromAscii("w%1").arg(i));
+ scene.addItem(wid);
+ if (i == 1)
+ w1 = wid;
+ else if (i == 2)
+ w2 = wid;
+ else if (i == 3)
+ w3 = wid;
+ }
+
+ w1->setFocus();
+ QTRY_VERIFY(w1->hasFocus());
+ QVERIFY(compareFocusChain(&view, QList<QGraphicsItem*>() << w1 << w2 << w3));
+
+ QGraphicsWidget *p = new QGraphicsWidget;
+ p->setData(0, QLatin1String("parent"));
+ p->setFocusPolicy(Qt::StrongFocus);
+
+ w1->setFocus();
+ QVERIFY(compareFocusChain(&view, QList<QGraphicsItem*>() << w1 << w2 << w3));
+
+ w1->setParentItem(p);
+ w2->setFocus();
+ QVERIFY(compareFocusChain(&view, QList<QGraphicsItem*>() << w2 << w3));
+
+ w2->setParentItem(p);
+ w3->setFocus();
+ QVERIFY(compareFocusChain(&view, QList<QGraphicsItem*>() << w3));
+ w3->setParentItem(p);
+ QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem*>(0));
+
+ scene.addItem(p);
+ p->setFocus();
+
+ QVERIFY(compareFocusChain(&view, QList<QGraphicsItem*>() << p << w1 << w2 << w3));
+ delete p;
+
+ for (i = 1; i < 5; ++i) {
+ QGraphicsWidget *wid = new QGraphicsWidget;
+ wid->setFocusPolicy(Qt::StrongFocus);
+ wid->setData(0, QString::fromAscii("w%1").arg(i));
+ scene.addItem(wid);
+ if (i == 1)
+ w1 = wid;
+ else if (i == 2)
+ w2 = wid;
+ else if (i == 3)
+ w3 = wid;
+ else if (i == 4)
+ w4 = wid;
+ }
+ w4->setParentItem(w1);
+ QGraphicsWidget::setTabOrder(w1, w4);
+ w1->setFocus();
+ QVERIFY(compareFocusChain(&view, QList<QGraphicsItem*>() << w1 << w4 << w2 << w3));
+
+ p = new QGraphicsWidget;
+ p->setData(0, QLatin1String("parent"));
+ p->setFocusPolicy(Qt::StrongFocus);
+
+ w1->setParentItem(p);
+ w2->setFocus();
+ QVERIFY(compareFocusChain(&view, QList<QGraphicsItem*>() << w2 << w3));
+
+ scene.addItem(p);
+ w2->setFocus();
+ QVERIFY(compareFocusChain(&view, QList<QGraphicsItem*>() << w2 << w3 << p << w1 << w4));
+}
+
+void tst_QGraphicsWidget::topLevelWidget_data()
+{
+ QTest::addColumn<QString>("str");
+ QTest::newRow("test one") << "foo";
+}
+
+// QGraphicsWidget* topLevelWidget() const public
+void tst_QGraphicsWidget::topLevelWidget()
+{
+ QFETCH(QString, str);
+ SubQGraphicsWidget widget;
+ QCOMPARE(widget.topLevelWidget(), (QGraphicsWidget *)&widget);
+}
+
+void tst_QGraphicsWidget::unsetLayoutDirection_data()
+{
+ QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
+ QTest::newRow("rtl") << Qt::RightToLeft;
+ QTest::newRow("ltr") << Qt::LeftToRight;
+}
+
+// void unsetLayoutDirection() public
+void tst_QGraphicsWidget::unsetLayoutDirection()
+{
+ QApplication::setLayoutDirection(Qt::LeftToRight);
+ QFETCH(Qt::LayoutDirection, layoutDirection);
+ SubQGraphicsWidget widget;
+ QCOMPARE(Qt::LeftToRight, widget.layoutDirection());
+
+ QList<SubQGraphicsWidget*> children;
+ for (int i = 0; i < 10; ++i) {
+ SubQGraphicsWidget *item = new SubQGraphicsWidget(&widget);
+ children.append(item);
+ }
+ widget.setLayoutDirection(layoutDirection);
+ widget.unsetLayoutDirection();
+ QCOMPARE(widget.testAttribute(Qt::WA_SetLayoutDirection), false);
+ for (int i = 0; i < children.count(); ++i) {
+ QCOMPARE(children[i]->layoutDirection(), Qt::LeftToRight);
+ }
+}
+
+void tst_QGraphicsWidget::focusNextPrevChild_data()
+{
+ QTest::addColumn<QString>("str");
+ QTest::newRow("test one") << "foo";
+}
+
+// bool focusNextPrevChild(bool next) protected
+void tst_QGraphicsWidget::focusNextPrevChild()
+{
+ QFETCH(QString, str);
+ SubQGraphicsWidget widget;
+ // ### write test after just calling it stops crashing :)
+ widget.call_focusNextPrevChild(true);
+}
+
+void tst_QGraphicsWidget::verifyFocusChain()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
+
+ {
+ // parent/child focus
+ SubQGraphicsWidget *w = new SubQGraphicsWidget(0, Qt::Window);
+ w->setFocusPolicy(Qt::StrongFocus);
+ SubQGraphicsWidget *w1_1 = new SubQGraphicsWidget(w);
+ w1_1->setFocusPolicy(Qt::StrongFocus);
+ scene.addItem(w);
+ w->setFocus();
+ QVERIFY(w->hasFocus());
+ w->call_focusNextPrevChild(true);
+ QVERIFY(w1_1->hasFocus());
+ delete w;
+ }
+
+ {
+ // delete item in focus chain and verify chain
+ SubQGraphicsWidget *w = new SubQGraphicsWidget(0, Qt::Window);
+ SubQGraphicsWidget *w1_1 = new SubQGraphicsWidget(w);
+ SubQGraphicsWidget *w1_2 = new SubQGraphicsWidget(w);
+ SubQGraphicsWidget *w1_3 = new SubQGraphicsWidget(w);
+ w1_1->setFocusPolicy(Qt::StrongFocus);
+ w1_2->setFocusPolicy(Qt::StrongFocus);
+ w1_3->setFocusPolicy(Qt::StrongFocus);
+ scene.addItem(w);
+ w1_1->setFocus();
+ QVERIFY(w1_1->hasFocus());
+ QCOMPARE(w->call_focusNextPrevChild(true), true);
+ QVERIFY(w1_2->hasFocus());
+ QCOMPARE(w->call_focusNextPrevChild(true), true);
+ QVERIFY(w1_3->hasFocus());
+ w1_1->setFocus();
+ delete w1_2;
+ w->call_focusNextPrevChild(true);
+ QVERIFY(w1_3->hasFocus());
+ delete w;
+ }
+ {
+ // parent/child focus
+ SubQGraphicsWidget *w = new SubQGraphicsWidget(0, Qt::Window);
+ w->setFocusPolicy(Qt::StrongFocus);
+ SubQGraphicsWidget *w1_1 = new SubQGraphicsWidget(w);
+ w1_1->setFocusPolicy(Qt::StrongFocus);
+ scene.addItem(w);
+ w->setFocus();
+ QVERIFY(w->hasFocus());
+ w->call_focusNextPrevChild(true);
+ QVERIFY(w1_1->hasFocus());
+ delete w;
+ }
+ {
+ // remove the tabFocusFirst widget from the scene.
+ QWidget *window = new QWidget;
+ QVBoxLayout *layout = new QVBoxLayout;
+ window->setLayout(layout);
+ QLineEdit *lineEdit = new QLineEdit;
+ layout->addWidget(lineEdit);
+ QGraphicsView *view = new QGraphicsView(&scene);
+ scene.setSceneRect(-20, -20, 200, 50);
+ layout->addWidget(view);
+ view->setMinimumSize(150, 50);
+ SubQGraphicsWidget *w1_1 = new SubQGraphicsWidget;
+ w1_1->setData(0, "w1_1");
+ w1_1->setGeometry(0,0,25, 25);
+ w1_1->setFocusPolicy(Qt::StrongFocus);
+ scene.addItem(w1_1);
+ SubQGraphicsWidget *w1_2 = new SubQGraphicsWidget;
+ w1_2->setData(0, "w1_2");
+ w1_2->setGeometry(25,0,25, 25);
+ w1_2->setFocusPolicy(Qt::StrongFocus);
+ scene.addItem(w1_2);
+ window->show();
+ QApplication::setActiveWindow(window);
+ QTest::qWaitForWindowShown(window);
+
+ lineEdit->setFocus();
+ QTRY_VERIFY(lineEdit->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QTRY_VERIFY(w1_1->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QTRY_VERIFY(w1_2->hasFocus());
+
+ // remove the tabFocusFirst and insert new item
+ delete w1_1; // calls _q_removeItemLater
+ SubQGraphicsWidget *w1_3 = new SubQGraphicsWidget;
+ w1_3->setFocusPolicy(Qt::StrongFocus);
+ w1_3->setData(0, "w1_3");
+ w1_3->setGeometry(50,0,25, 25);
+ scene.addItem(w1_3);
+ QTRY_VERIFY(w1_2->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QTRY_VERIFY(lineEdit->hasFocus());
+ // tabFocusFirst should now point to w1_2
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QTRY_VERIFY(w1_2->hasFocus());
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QTRY_VERIFY(w1_3->hasFocus());
+ scene.removeItem(w1_2); // does not call _q_removeItemLater
+ delete w1_2; // calls _q_removeItemLater
+
+ SubQGraphicsWidget *w1_4 = new SubQGraphicsWidget;
+ w1_4->setFocusPolicy(Qt::StrongFocus);
+ w1_4->setData(0, "w1_4");
+ w1_4->setGeometry(75,0,25, 25);
+ scene.addItem(w1_4);
+ QTRY_VERIFY(w1_3->hasFocus());
+ QTRY_VERIFY(compareFocusChain(view, QList<QGraphicsItem*>() << w1_3 << w1_4));
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab);
+ QTRY_VERIFY(lineEdit->hasFocus());
+ // tabFocusFirst should now point to w1_3
+ QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
+ QTRY_VERIFY(w1_3->hasFocus());
+ QTRY_VERIFY(compareFocusChain(view, QList<QGraphicsItem*>() << w1_3 << w1_4));
+ delete window;
+ }
+}
+
+void tst_QGraphicsWidget::updateFocusChainWhenChildDie()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QApplication::setActiveWindow(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
+
+ // delete item in focus chain with no focus and verify chain
+ SubQGraphicsWidget *parent = new SubQGraphicsWidget(0, Qt::Window);
+ SubQGraphicsWidget *w = new SubQGraphicsWidget(0, Qt::Window);
+ w->resize(50,50);
+ w->resize(100,100);
+ SubQGraphicsWidget *w1_1 = new SubQGraphicsWidget(w);
+ w1_1->setFocusPolicy(Qt::StrongFocus);
+ w->setFocusPolicy(Qt::StrongFocus);
+ scene.addItem(w);
+ scene.addItem(parent);
+ w1_1->setFocus();
+
+ QVERIFY(w1_1->hasFocus());
+ QWidget myWidget(0);
+ QLineEdit edit(&myWidget);
+ myWidget.show();
+ edit.setFocus();
+ QTRY_VERIFY(edit.hasFocus());
+ delete w1_1;
+ myWidget.hide();
+ w->setParentItem(parent);
+ //We don't crash perfect
+ QVERIFY(w);
+ QTest::mouseMove(view.viewport());
+ QTest::mouseClick(view.viewport(), Qt::LeftButton, 0);
+ QTRY_COMPARE(qApp->activeWindow(), static_cast<QWidget *>(&view));
+ QTRY_COMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(w));
+}
+
+void tst_QGraphicsWidget::sizeHint_data()
+{
+ QTest::addColumn<bool>("layout");
+ QTest::newRow("no layout") << false;
+ QTest::newRow("layout") << true;
+}
+
+// QSizeF sizeHint(Qt::SizeHint which, QSizeF const& constraint = QSizeF()) const protected
+void tst_QGraphicsWidget::sizeHint()
+{
+ QFETCH(bool, layout);
+ SubQGraphicsWidget widget;
+
+ if (layout) {
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout;
+ widget.setLayout(layout);
+ }
+ widget.call_sizeHint(Qt::MinimumSize, QSizeF());
+}
+
+void tst_QGraphicsWidget::consistentPosSizeGeometry_data()
+{
+ QTest::addColumn<QSizeF>("minSize");
+ QTest::addColumn<QSizeF>("maxSize");
+ QTest::addColumn<QRectF>("geometry");
+ QTest::addColumn<QRectF>("expectedGeometry");
+
+ QTest::newRow("size is valid") << QSizeF(0, 0) << QSizeF(200, 200) << QRectF(0, 0, 100, 100) << QRectF(0, 0, 100, 100);
+ QTest::newRow("size is larger than max") << QSizeF(0, 0) << QSizeF(50, 50) << QRectF(0, 0, 100, 100) << QRectF(0, 0, 50, 50);
+ QTest::newRow("size is smaller than min") << QSizeF(50, 50) << QSizeF(150, 150) << QRectF(0, 0, 10, 10) << QRectF(0, 0, 50, 50);
+}
+
+void tst_QGraphicsWidget::consistentPosSizeGeometry()
+{
+ QFETCH(QSizeF, minSize);
+ QFETCH(QSizeF, maxSize);
+ QFETCH(QRectF, geometry);
+ QFETCH(QRectF, expectedGeometry);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *w = new QGraphicsWidget;
+ scene.addItem(w);
+ w->setMinimumSize(minSize);
+ w->setMaximumSize(maxSize);
+ w->setGeometry(geometry);
+ QCOMPARE(w->geometry(), expectedGeometry);
+ QCOMPARE(w->pos(), expectedGeometry.topLeft());
+ QCOMPARE(w->size(), expectedGeometry.size());
+
+ QRectF otherGeom = QRectF(QPointF(12.34,12.34), minSize);
+ w->setGeometry(otherGeom);
+ QCOMPARE(w->geometry(), otherGeom);
+ QCOMPARE(w->pos(), otherGeom.topLeft());
+ QCOMPARE(w->size(), otherGeom.size());
+
+ w->setPos(geometry.topLeft());
+ QCOMPARE(w->geometry().topLeft(), expectedGeometry.topLeft());
+ QCOMPARE(w->pos(), expectedGeometry.topLeft());
+
+ w->resize(geometry.size());
+ QCOMPARE(w->geometry().size(), expectedGeometry.size());
+ QCOMPARE(w->geometry(), expectedGeometry);
+
+ view.show();
+
+}
+
+
+enum WhichSize {
+ MinimumWidth,
+ PreferredWidth,
+ MaximumWidth,
+ MinimumHeight,
+ PreferredHeight,
+ MaximumHeight,
+ MinimumSize,
+ PreferredSize,
+ MaximumSize,
+ MinimumSizeHint,
+ PreferredSizeHint,
+ MaximumSizeHint,
+ Size,
+ None,
+};
+
+typedef QPair<int, QVariant> Inst;
+
+Q_DECLARE_METATYPE(Inst)
+Q_DECLARE_METATYPE(QVector<Inst>)
+
+void tst_QGraphicsWidget::setSizes_data()
+{
+
+ QTest::addColumn<QVector<Inst> >("inputInstructions");
+ QTest::addColumn<QVector<Inst> >("compareInstructions");
+
+ QTest::newRow("minSize1") << (QVector<Inst>() << Inst(Size, QSize(25, 25)) << Inst(MinimumSize, QSize(10, 10)))
+ << (QVector<Inst>() << Inst(Size, QSize(25,25)));
+ QTest::newRow("minSize2") << (QVector<Inst>() << Inst(Size, QSizeF(20, 20)) << Inst(MinimumSize, QSizeF(25, 25)))
+ << (QVector<Inst>() << Inst(Size, QSizeF(25, 25)));
+ QTest::newRow("minWidth1") << (QVector<Inst>() << Inst(Size, QSizeF(20, 20)) << Inst(MinimumWidth, 5.0))
+ << (QVector<Inst>() << Inst(Size, QSizeF(20, 20)));
+ QTest::newRow("minWidth2") << (QVector<Inst>() << Inst(Size, QSizeF(20, 20)) << Inst(MinimumWidth, 25.0))
+ << (QVector<Inst>() << Inst(Size, QSizeF(25, 20)));
+ QTest::newRow("minHeight1") << (QVector<Inst>() << Inst(Size, QSizeF(20, 20)) << Inst(MinimumHeight, 5.0))
+ << (QVector<Inst>() << Inst(Size, QSizeF(20, 20)));
+ QTest::newRow("minHeight2") << (QVector<Inst>() << Inst(Size, QSizeF(20, 20)) << Inst(MinimumHeight, 25.0))
+ << (QVector<Inst>() << Inst(Size, QSizeF(20, 25)));
+ QTest::newRow("maxSize1") << (QVector<Inst>() << Inst(Size, QSizeF(40, 40)) << Inst(MaximumSize, QSizeF(30, 30)))
+ << (QVector<Inst>() << Inst(Size, QSizeF(30, 30)));
+ QTest::newRow("maxSize2") << (QVector<Inst>() << Inst(Size, QSizeF(40, 40)) << Inst(MaximumSize, QSizeF(30, -1)))
+ << (QVector<Inst>() << Inst(Size, QSizeF(30, 40)));
+ QTest::newRow("maxSize3") << (QVector<Inst>() << Inst(Size, QSizeF(40, 40)) << Inst(MaximumSize, QSizeF(-1, 30)))
+ << (QVector<Inst>() << Inst(Size, QSizeF(40, 30)));
+ QTest::newRow("maxWidth1")<< (QVector<Inst>() << Inst(Size, QSizeF(40, 40)) << Inst(MaximumWidth, 30))
+ << (QVector<Inst>() << Inst(Size, QSizeF(30, 40)));
+ QTest::newRow("maxHeight")<< (QVector<Inst>() << Inst(Size, QSizeF(40, 40)) << Inst(MaximumHeight, 20))
+ << (QVector<Inst>() << Inst(Size, QSizeF(40, 20)));
+ QTest::newRow("unsetMinSize")<< (QVector<Inst>() << Inst(Size, QSizeF(40, 40)) << Inst(MinimumSize, QSizeF(-1, -1)))
+ << (QVector<Inst>() << Inst(MinimumSize, QSizeF(5, 5)));
+ QTest::newRow("unsetMaxSize")<< (QVector<Inst>() << Inst(Size, QSizeF(40, 40)) << Inst(MaximumSize, QSizeF(-1, -1)))
+ << (QVector<Inst>() << Inst(MaximumSize, QSizeF(500, 500)));
+ QTest::newRow("unsetMinSize, expand size to minimumSizeHint") << (QVector<Inst>()
+ << Inst(MinimumSize, QSize(0, 0))
+ << Inst(Size, QSize(1,1))
+ << Inst(MinimumSize, QSize(-1.0, -1.0))
+ )
+ << (QVector<Inst>()
+ << Inst(Size, QSize(5,5))
+ << Inst(MinimumSize, QSize(5,5))
+ );
+
+}
+
+void tst_QGraphicsWidget::setSizes()
+{
+ QFETCH(QVector<Inst>, inputInstructions);
+ QFETCH(QVector<Inst>, compareInstructions);
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ SizeHinter *widget = new SizeHinter(0, Qt::Window);
+ QSizeF min = QSizeF(10, 10);
+ QSizeF pref = QSizeF(25, 25);
+ QSizeF max = QSizeF(50, 50);
+
+ int i;
+ for (i = 0; i < inputInstructions.count(); ++i) {
+ Inst input = inputInstructions.at(i);
+
+ // defaults
+ switch (input.first) {
+ case MinimumSize:
+ min = input.second.toSizeF();
+ break;
+ case PreferredSize:
+ pref = input.second.toSizeF();
+ break;
+ case MaximumSize:
+ max = input.second.toSizeF();
+ break;
+ case Size:
+ widget->resize(input.second.toSizeF());
+ break;
+ case MinimumWidth:
+ widget->setMinimumWidth(qreal(input.second.toDouble()));
+ break;
+ case PreferredWidth:
+ widget->setPreferredWidth(qreal(input.second.toDouble()));
+ break;
+ case MaximumWidth:
+ widget->setMaximumWidth(qreal(input.second.toDouble()));
+ break;
+ case MinimumHeight:
+ widget->setMinimumHeight(qreal(input.second.toDouble()));
+ break;
+ case PreferredHeight:
+ widget->setPreferredHeight(qreal(input.second.toDouble()));
+ break;
+ case MaximumHeight:
+ widget->setMaximumHeight(qreal(input.second.toDouble()));
+ break;
+ case MinimumSizeHint:
+ widget->setSizeHint(Qt::MinimumSize, input.second.toSizeF());
+ break;
+ case PreferredSizeHint:
+ widget->setSizeHint(Qt::PreferredSize, input.second.toSizeF());
+ break;
+ case MaximumSizeHint:
+ widget->setSizeHint(Qt::MaximumSize, input.second.toSizeF());
+ break;
+ default:
+ qWarning("instruction not implemented");
+ break;
+ }
+ }
+
+ widget->setMinimumSize(min);
+ widget->setPreferredSize(pref);
+ widget->setMaximumSize(max);
+
+ for (i = 0; i < compareInstructions.count(); ++i) {
+ Inst input = compareInstructions.at(i);
+ switch (input.first) {
+ case MinimumSize:
+ QTRY_COMPARE(widget->minimumSize(), input.second.toSizeF());
+ break;
+ case PreferredSize:
+ QTRY_COMPARE(widget->preferredSize(), input.second.toSizeF());
+ break;
+ case MaximumSize:
+ QTRY_COMPARE(widget->maximumSize(), input.second.toSizeF());
+ break;
+ case Size:
+ QTRY_COMPARE(widget->size(), input.second.toSizeF());
+ break;
+ case MinimumWidth:
+ QTRY_COMPARE(widget->minimumWidth(), qreal(input.second.toDouble()));
+ break;
+ case PreferredWidth:
+ QTRY_COMPARE(widget->preferredWidth(), qreal(input.second.toDouble()));
+ break;
+ case MaximumWidth:
+ QTRY_COMPARE(widget->maximumWidth(), qreal(input.second.toDouble()));
+ break;
+ default:
+ qWarning("instruction not implemented");
+ break;
+ }
+ }
+ delete widget;
+}
+
+void tst_QGraphicsWidget::closePopupOnOutsideClick()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Popup);
+ widget->resize(100, 100);
+
+ QGraphicsScene scene;
+ scene.addItem(widget);
+
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.ignore();
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+
+ QVERIFY(widget->isVisible());
+ QVERIFY(event.isAccepted());
+
+ event.ignore();
+ event.setScenePos(QPointF(150, 150));
+ qApp->sendEvent(&scene, &event);
+
+ QVERIFY(!widget->isVisible());
+ QVERIFY(event.isAccepted());
+}
+
+void tst_QGraphicsWidget::task236127_bspTreeIndexFails()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsWidget *widget2 = new QGraphicsWidget;
+ widget->resize(10, 10);
+ widget2->resize(10, 10);
+ widget2->setZValue(1);
+ QCOMPARE(widget2->zValue(), qreal(1));
+ QCOMPARE(widget->zValue(), qreal(0));
+ widget->setData(0, "widget");
+ widget2->setData(0, "widget2");
+
+ QGraphicsScene scene;
+ scene.addItem(widget);
+ scene.addItem(widget2);
+
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+
+ QTRY_VERIFY(!scene.itemAt(25, 25));
+ widget->setGeometry(0, 112, 360, 528);
+ QTRY_COMPARE(scene.itemAt(15, 120), (QGraphicsItem *)widget);
+ widget2->setGeometry(0, 573, 360, 67);
+ QTRY_COMPARE(scene.itemAt(15, 120), (QGraphicsItem *)widget);
+ QTRY_COMPARE(scene.itemAt(50, 585), (QGraphicsItem *)widget2);
+}
+
+void tst_QGraphicsWidget::defaultSize()
+{
+ SubQGraphicsWidget *widget = new SubQGraphicsWidget;
+ widget->setMinimumSize(40, 40);
+ QGraphicsScene scene;
+ scene.addItem(widget);
+
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QSizeF initialSize = widget->size();
+
+ widget->resize(initialSize);
+ QCOMPARE(widget->geometry().size(), initialSize);
+ widget->setVisible(false);
+ widget->setMinimumSize(10, 10);
+ widget->setPreferredSize(60, 60);
+ widget->setMaximumSize(110, 110);
+ widget->setVisible(true);
+ // should still have its size set to initialsize
+ QTRY_COMPARE(widget->geometry().size(), initialSize);
+
+}
+
+void tst_QGraphicsWidget::explicitMouseGrabber()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ EventSpy widgetGrabEventSpy(widget, QEvent::GrabMouse);
+ EventSpy widgetUngrabEventSpy(widget, QEvent::UngrabMouse);
+
+ // Grab without scene
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::grabMouse: cannot grab mouse without scene");
+ widget->grabMouse();
+ QCOMPARE(widgetGrabEventSpy.count(), 0);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::ungrabMouse: cannot ungrab mouse without scene");
+ widget->ungrabMouse();
+ QCOMPARE(widgetUngrabEventSpy.count(), 0);
+
+ // Add to scene
+ QGraphicsScene scene;
+ scene.addItem(widget);
+
+ // Ungrab while not grabber
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::ungrabMouse: not a mouse grabber");
+ widget->ungrabMouse();
+
+ // Simple grab with scene
+ QVERIFY(!scene.mouseGrabberItem());
+ widget->grabMouse();
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ QCOMPARE(widgetGrabEventSpy.count(), 1);
+ widget->ungrabMouse();
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ QCOMPARE(widgetUngrabEventSpy.count(), 1);
+
+ // Grab while grabbing
+ widget->grabMouse();
+ QCOMPARE(widgetGrabEventSpy.count(), 2);
+ QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::grabMouse: already a mouse grabber");
+ widget->grabMouse();
+ QCOMPARE(widgetGrabEventSpy.count(), 2);
+ QCOMPARE(widgetUngrabEventSpy.count(), 1);
+ widget->ungrabMouse();
+ QCOMPARE(widgetUngrabEventSpy.count(), 2);
+
+ // Add two more widgets to the scene
+ QGraphicsWidget *widget2 = new QGraphicsWidget;
+ scene.addItem(widget2);
+ EventSpy widget2GrabEventSpy(widget2, QEvent::GrabMouse);
+ EventSpy widget2UngrabEventSpy(widget2, QEvent::UngrabMouse);
+ QGraphicsWidget *widget3 = new QGraphicsWidget;
+ scene.addItem(widget3);
+ EventSpy widget3GrabEventSpy(widget3, QEvent::GrabMouse);
+ EventSpy widget3UngrabEventSpy(widget3, QEvent::UngrabMouse);
+
+ widget->setData(0, "widget");
+ widget2->setData(0, "widget2");
+ widget3->setData(0, "widget3");
+
+ // Simple nested grabbing
+ widget->grabMouse();
+ QCOMPARE(widgetGrabEventSpy.count(), 3);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ widget2->grabMouse();
+ QCOMPARE(widgetUngrabEventSpy.count(), 3);
+ QCOMPARE(widget2GrabEventSpy.count(), 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget2);
+ widget3->grabMouse();
+ QCOMPARE(widget2UngrabEventSpy.count(), 1);
+ QCOMPARE(widget3GrabEventSpy.count(), 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget3);
+ widget3->ungrabMouse();
+ QCOMPARE(widget3UngrabEventSpy.count(), 1);
+ QCOMPARE(widget2GrabEventSpy.count(), 2);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget2);
+ widget2->ungrabMouse();
+ QCOMPARE(widget2UngrabEventSpy.count(), 2);
+ QCOMPARE(widgetGrabEventSpy.count(), 4);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ widget->ungrabMouse();
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+
+ // Out of order ungrab
+ widget->grabMouse();
+ QCOMPARE(widgetGrabEventSpy.count(), 5);
+ widget2->grabMouse();
+ QCOMPARE(widget2GrabEventSpy.count(), 3);
+ widget3->grabMouse();
+ QCOMPARE(widget3GrabEventSpy.count(), 2);
+ widget2->ungrabMouse();
+ QCOMPARE(widget3UngrabEventSpy.count(), 2);
+ QCOMPARE(widget2UngrabEventSpy.count(), 4);
+ QCOMPARE(widgetGrabEventSpy.count(), 6);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+}
+
+void tst_QGraphicsWidget::implicitMouseGrabber()
+{
+ QGraphicsScene scene;
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ widget->setFlag(QGraphicsItem::ItemIsMovable); // can grab mouse
+ widget->resize(200, 200);
+ EventSpy widgetGrabEventSpy(widget, QEvent::GrabMouse);
+ EventSpy widgetUngrabEventSpy(widget, QEvent::UngrabMouse);
+ scene.addItem(widget);
+
+ QVERIFY(!scene.mouseGrabberItem());
+
+ // Click on an item, see if gain and lose implicit mouse grab.
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.ignore();
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ QCOMPARE(widgetGrabEventSpy.count(), 1);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.ignore();
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ QCOMPARE(widgetGrabEventSpy.count(), 1);
+ QCOMPARE(widgetUngrabEventSpy.count(), 1);
+
+ // Click on an item that already grabs the mouse. Shouldn't have any effect.
+ widget->grabMouse();
+ QCOMPARE(widgetGrabEventSpy.count(), 2);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.ignore();
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ QCOMPARE(widgetGrabEventSpy.count(), 2);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.ignore();
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ QCOMPARE(widgetGrabEventSpy.count(), 2);
+ QCOMPARE(widgetUngrabEventSpy.count(), 1);
+ widget->ungrabMouse();
+ QCOMPARE(widgetUngrabEventSpy.count(), 2);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+
+ // Implicit mouse grabber tries to explicitly grab the mouse
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.ignore();
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ QCOMPARE(widgetGrabEventSpy.count(), 3);
+ widget->grabMouse();
+ QCOMPARE(widgetUngrabEventSpy.count(), 2);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.ignore();
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ QCOMPARE(widgetGrabEventSpy.count(), 3);
+ QCOMPARE(widgetUngrabEventSpy.count(), 2);
+ widget->ungrabMouse();
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ QCOMPARE(widgetGrabEventSpy.count(), 3);
+ QCOMPARE(widgetUngrabEventSpy.count(), 3);
+
+ // Arrival of a new widget
+ QGraphicsWidget *widget2 = new QGraphicsWidget;
+ widget2->setFlag(QGraphicsItem::ItemIsMovable); // can grab mouse
+ widget2->resize(200, 200);
+ widget2->setPos(205, 0);
+ EventSpy widget2GrabEventSpy(widget2, QEvent::GrabMouse);
+ EventSpy widget2UngrabEventSpy(widget2, QEvent::UngrabMouse);
+ scene.addItem(widget2);
+
+ // Implicit grab while there's an explicit grab is not possible.
+ widget->grabMouse();
+ QCOMPARE(widgetGrabEventSpy.count(), 4);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.ignore();
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(250, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+ QCOMPARE(widgetGrabEventSpy.count(), 4);
+ QCOMPARE(widget2GrabEventSpy.count(), 0);
+ QCOMPARE(widget2UngrabEventSpy.count(), 0);
+
+ scene.removeItem(widget);
+ QCOMPARE(widgetUngrabEventSpy.count(), 4);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+}
+
+class GrabOnPressItem : public QGraphicsRectItem
+{
+public:
+ GrabOnPressItem(const QRectF &rect)
+ : QGraphicsRectItem(rect),
+ npress(0), nrelease(0), ndoubleClick(0),
+ ngrab(0), nungrab(0)
+ {
+ }
+ int npress;
+ int nrelease;
+ int ndoubleClick;
+ int ngrab;
+ int nungrab;
+protected:
+ bool sceneEvent(QEvent *event)
+ {
+ switch (event->type()) {
+ case QEvent::GrabMouse:
+ ++ngrab;
+ break;
+ case QEvent::UngrabMouse:
+ ++nungrab;
+ break;
+ default:
+ break;
+ }
+ return QGraphicsRectItem::sceneEvent(event);
+ }
+
+ void mousePressEvent(QGraphicsSceneMouseEvent *)
+ {
+ grabMouse();
+ ++npress;
+ }
+ void mouseReleaseEvent(QGraphicsSceneMouseEvent *)
+ {
+ ungrabMouse();
+ ++nrelease;
+ }
+ void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *)
+ {
+ ++ndoubleClick;
+ }
+};
+
+void tst_QGraphicsWidget::doubleClickAfterExplicitMouseGrab()
+{
+ QGraphicsScene scene;
+ GrabOnPressItem *item = new GrabOnPressItem(QRectF(0, 0, 100, 100));
+ scene.addItem(item);
+
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.setButton(Qt::LeftButton);
+ event.setButtons(Qt::LeftButton);
+ event.ignore();
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
+ QCOMPARE(item->npress, 1);
+ QCOMPARE(item->ngrab, 1);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.setButton(Qt::LeftButton);
+ event.setButtons(0);
+ event.ignore();
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ QCOMPARE(item->nrelease, 1);
+ QCOMPARE(item->nungrab, 1);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseDoubleClick);
+ event.setButton(Qt::LeftButton);
+ event.setButtons(Qt::LeftButton);
+ event.ignore();
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
+ QCOMPARE(item->ndoubleClick, 1);
+ QCOMPARE(item->ngrab, 2);
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
+ event.setButton(Qt::LeftButton);
+ event.setButtons(0);
+ event.ignore();
+ event.setScenePos(QPointF(50, 50));
+ qApp->sendEvent(&scene, &event);
+ }
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+ QCOMPARE(item->nrelease, 2);
+ QCOMPARE(item->nungrab, 2);
+}
+
+void tst_QGraphicsWidget::popupMouseGrabber()
+{
+ QGraphicsScene scene;
+ QGraphicsWidget *widget = new QGraphicsWidget(0, Qt::Popup);
+ widget->setFlag(QGraphicsItem::ItemIsMovable); // can grab mouse
+ widget->resize(200, 200);
+ EventSpy widgetGrabEventSpy(widget, QEvent::GrabMouse);
+ EventSpy widgetUngrabEventSpy(widget, QEvent::UngrabMouse);
+
+ // Simply adding a visible popup to the scene immediately grabs the mouse.
+ scene.addItem(widget);
+ QCOMPARE(widgetGrabEventSpy.count(), 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+
+ // Hiding it loses the grab again.
+ widget->hide();
+ QCOMPARE(widgetUngrabEventSpy.count(), 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
+
+ // Showing it grabs the mouse again
+ widget->show();
+ QCOMPARE(widgetGrabEventSpy.count(), 2);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget);
+
+ // Add two popups
+ QGraphicsWidget *widget2 = new QGraphicsWidget(0, Qt::Popup);
+ widget2->setFlag(QGraphicsItem::ItemIsMovable); // can grab mouse
+ widget2->resize(200, 200);
+ EventSpy widget2GrabEventSpy(widget2, QEvent::GrabMouse);
+ EventSpy widget2UngrabEventSpy(widget2, QEvent::UngrabMouse);
+ QGraphicsWidget *widget3 = new QGraphicsWidget(0, Qt::Popup);
+ widget3->setFlag(QGraphicsItem::ItemIsMovable); // can grab mouse
+ widget3->resize(200, 200);
+ EventSpy widget3GrabEventSpy(widget3, QEvent::GrabMouse);
+ EventSpy widget3UngrabEventSpy(widget3, QEvent::UngrabMouse);
+
+ // Adding to the scene grabs
+ scene.addItem(widget2);
+ QCOMPARE(widgetUngrabEventSpy.count(), 2);
+ QCOMPARE(widget2GrabEventSpy.count(), 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget2);
+
+ // Adding to the scene grabs again
+ scene.addItem(widget3);
+ QCOMPARE(widget2UngrabEventSpy.count(), 1);
+ QCOMPARE(widget3GrabEventSpy.count(), 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget3);
+
+ // Hiding the topmost widget causes widget 2 to regain grab.
+ widget3->hide();
+ QCOMPARE(widget2GrabEventSpy.count(), 2);
+ QCOMPARE(widget3UngrabEventSpy.count(), 1);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget2);
+ widget3->show();
+ QCOMPARE(widget2UngrabEventSpy.count(), 2);
+ QCOMPARE(widget3GrabEventSpy.count(), 2);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget3);
+
+ // Clicking outside the popup still causes it to close (despite that it's
+ // an explicit mouse grabber).
+ {
+ QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
+ event.ignore();
+ event.setButton(Qt::LeftButton);
+ event.setScenePos(QPointF(500, 500)); // outside
+ qApp->sendEvent(&scene, &event);
+ }
+ QVERIFY(!widget3->isVisible());
+ QCOMPARE(widget3UngrabEventSpy.count(), 2);
+ QCOMPARE(widget2GrabEventSpy.count(), 3);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget2);
+ QVERIFY(widget2->isVisible());
+ QVERIFY(widget->isVisible());
+ widget3->show();
+ QCOMPARE(widget3GrabEventSpy.count(), 3);
+ QCOMPARE(widget2UngrabEventSpy.count(), 3);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget3);
+
+ // This is something of a curiosity. What happens if you call
+ // ungrabMouse() on a popup? The answer is - it loses the grab. If you
+ // hide and show the popup again, it will regain the grab.
+ widget3->ungrabMouse();
+ QCOMPARE(widget3UngrabEventSpy.count(), 3);
+ QCOMPARE(widget2GrabEventSpy.count(), 4);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget2);
+ widget3->hide();
+ widget3->show();
+ QCOMPARE(widget3GrabEventSpy.count(), 4);
+ QCOMPARE(widget2UngrabEventSpy.count(), 4);
+ QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)widget3);
+}
+
+void tst_QGraphicsWidget::windowFlags_data()
+{
+ QTest::addColumn<int>("inputFlags");
+ QTest::addColumn<int>("outputFlags");
+
+ QTest::newRow("nil") << 0 << 0;
+
+ // Window types
+ QTest::newRow("Qt::Window") << int(Qt::Window)
+ << int(Qt::Window | Qt::WindowTitleHint | Qt::WindowSystemMenuHint
+ | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
+ QTest::newRow("Qt::SubWindow") << int(Qt::SubWindow)
+ << int(Qt::SubWindow | Qt::WindowTitleHint | Qt::WindowSystemMenuHint
+ | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint);
+ QTest::newRow("Qt::Dialog") << int(Qt::Dialog)
+ << int(Qt::Dialog | Qt::WindowTitleHint | Qt::WindowSystemMenuHint
+ | Qt::WindowContextHelpButtonHint);
+ QTest::newRow("Qt::Sheet") << int(Qt::Sheet)
+ << int(Qt::Sheet | Qt::WindowTitleHint | Qt::WindowSystemMenuHint
+ | Qt::WindowContextHelpButtonHint);
+ QTest::newRow("Qt::Tool") << int(Qt::Tool)
+ << int(Qt::Tool | Qt::WindowTitleHint | Qt::WindowSystemMenuHint);
+
+ // Custom window flags
+ QTest::newRow("Qt::FramelessWindowHint") << int(Qt::FramelessWindowHint)
+ << int(Qt::FramelessWindowHint);
+ QTest::newRow("Qt::CustomizeWindowHint") << int(Qt::CustomizeWindowHint)
+ << int(Qt::CustomizeWindowHint);
+}
+
+void tst_QGraphicsWidget::windowFlags()
+{
+ QFETCH(int, inputFlags);
+ QFETCH(int, outputFlags);
+
+ // Construct with flags set already
+ QGraphicsWidget widget(0, Qt::WindowFlags(inputFlags));
+ QCOMPARE(widget.windowFlags(), Qt::WindowFlags(outputFlags));
+
+ // Set flags after construction
+ QGraphicsWidget widget2;
+ widget2.setWindowFlags(Qt::WindowFlags(inputFlags));
+ QCOMPARE(widget2.windowFlags(), Qt::WindowFlags(outputFlags));
+
+ // Reset flags
+ widget2.setWindowFlags(0);
+ QVERIFY(!widget2.windowFlags());
+
+ // Set flags back again
+ widget2.setWindowFlags(Qt::WindowFlags(inputFlags));
+ QCOMPARE(widget2.windowFlags(), Qt::WindowFlags(outputFlags));
+
+ // Construct with custom flags set already
+ QGraphicsWidget widget3(0, Qt::WindowFlags(inputFlags | Qt::FramelessWindowHint));
+ QCOMPARE(widget3.windowFlags(), Qt::WindowFlags(inputFlags | Qt::FramelessWindowHint));
+
+ // Set custom flags after construction
+ QGraphicsWidget widget4;
+ widget4.setWindowFlags(Qt::WindowFlags(inputFlags | Qt::FramelessWindowHint));
+ QCOMPARE(widget4.windowFlags(), Qt::WindowFlags(inputFlags | Qt::FramelessWindowHint));
+
+ // Reset flags
+ widget4.setWindowFlags(0);
+ QVERIFY(!widget4.windowFlags());
+
+ // Set custom flags back again
+ widget4.setWindowFlags(Qt::WindowFlags(inputFlags | Qt::FramelessWindowHint));
+ QCOMPARE(widget4.windowFlags(), Qt::WindowFlags(inputFlags | Qt::FramelessWindowHint));
+
+ QGraphicsWidget *widget5 = new QGraphicsWidget;
+ widget5->setWindowFlags(Qt::WindowFlags(inputFlags));
+ QCOMPARE(widget5->windowFlags(), Qt::WindowFlags(outputFlags));
+ QGraphicsWidget window(0, Qt::Window);
+ widget5->setParentItem(&window);
+ QCOMPARE(widget5->windowFlags(), Qt::WindowFlags(outputFlags));
+}
+
+void tst_QGraphicsWidget::shortcutsDeletion()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QGraphicsWidget *widget2 = new QGraphicsWidget;
+ widget->setMinimumSize(40, 40);
+ QWidgetAction *del = new QWidgetAction(widget);
+ del->setIcon(QIcon("edit-delete"));
+ del->setShortcut(Qt::Key_Delete);
+ del->setShortcutContext(Qt::WidgetShortcut);
+ widget2->addAction(del);
+ widget2->addAction(del);
+ delete widget;
+}
+
+class MessUpPainterWidget : public QGraphicsWidget
+{
+public:
+ MessUpPainterWidget(QGraphicsItem * parent = 0, Qt::WindowFlags wFlags = 0)
+ : QGraphicsWidget(parent, wFlags)
+ {}
+
+ void paintWindowFrame(QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ QCOMPARE(painter->opacity(), 1.0);
+ painter->setOpacity(0.0);
+ QGraphicsWidget::paintWindowFrame(painter, option, widget);
+ }
+ void paint(QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ QCOMPARE(painter->opacity(), 1.0);
+ painter->drawRect(0, 0, 100, 100);
+ QGraphicsWidget::paint(painter, option, widget);
+ }
+
+};
+
+void tst_QGraphicsWidget::painterStateProtectionOnWindowFrame()
+{
+ MessUpPainterWidget *widget = new MessUpPainterWidget(0, Qt::Window);
+ QGraphicsScene scene(0, 0, 300, 300);
+ QGraphicsView view(&scene);
+ scene.addItem(widget);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+}
+
+class ProxyStyle : public QCommonStyle
+{
+public:
+ ProxyStyle(QStyle *proxyStyle) : QCommonStyle()
+ {
+ m_proxyStyle = proxyStyle;
+ }
+
+ int pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option = 0, const QWidget *widget = 0) const
+ {
+ return m_proxyStyle->pixelMetric(metric, option, widget);
+ }
+
+private:
+ QStyle *m_proxyStyle;
+};
+
+class StyledGraphicsWidget : public QGraphicsWidget
+{
+public:
+ StyledGraphicsWidget(bool useOwnStyle) : QGraphicsWidget(), m_style(0) {
+ if (useOwnStyle) {
+ QStyle *oldStyle = style();
+ m_style = new ProxyStyle(oldStyle);
+ setStyle(m_style);
+ }
+
+ style()->pixelMetric(QStyle::PM_SmallIconSize); // crash when style() is still in widgetStyles
+ }
+
+ ~StyledGraphicsWidget() {
+ delete m_style;
+ }
+
+private:
+ QStyle *m_style;
+};
+
+void tst_QGraphicsWidget::task243004_setStyleCrash()
+{
+ QGraphicsItem *item1 = new StyledGraphicsWidget(true);
+ delete item1; // item1 not removed from widgetStyles
+
+ QGraphicsItem *item2 = new StyledGraphicsWidget(false);
+ delete item2;
+}
+
+class GraphicsWidget_task250119 : public QGraphicsWidget
+{
+public:
+ GraphicsWidget_task250119()
+ : shortcutEvents(0)
+ {
+ setFocusPolicy(Qt::StrongFocus);
+ resize(100, 100);
+ }
+
+ int shortcutEvents;
+
+private:
+ bool event(QEvent *event)
+ {
+ if (event->type() == QEvent::Shortcut)
+ shortcutEvents++;
+ return QGraphicsWidget::event(event);
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ {
+ if (hasFocus()) {
+ painter->setPen(QPen(Qt::black, 0, Qt::DashLine));
+ painter->drawRect(rect());
+ }
+ painter->setPen(QPen(Qt::black, 0, Qt::SolidLine));
+ painter->fillRect(rect().adjusted(2, 2, -2, -2), Qt::yellow);
+ painter->drawRect(rect().adjusted(2, 2, -2, -2));
+ }
+};
+
+void tst_QGraphicsWidget::task250119_shortcutContext()
+{
+ QGraphicsScene scene;
+ QGraphicsView view;
+ view.setScene(&scene);
+ view.show();
+ QApplication::setActiveWindow(&view);
+ QTRY_COMPARE(QApplication::activeWindow(), (QWidget*)&view);
+
+
+ // *** Event: ***
+
+ GraphicsWidget_task250119 w_event;
+ scene.addItem(&w_event);
+
+ const int id = w_event.grabShortcut(Qt::Key_A, Qt::WidgetWithChildrenShortcut);
+ w_event.setShortcutEnabled(id, true);
+
+ w_event.setFocus();
+ QTest::keyPress(&view, Qt::Key_A);
+ QCOMPARE(w_event.shortcutEvents, 1);
+
+ w_event.clearFocus();
+ QTest::keyPress(&view, Qt::Key_A);
+ QCOMPARE(w_event.shortcutEvents, 1);
+
+ scene.removeItem(&w_event);
+
+
+ // *** Signal: ***
+
+ GraphicsWidget_task250119 w_signal;
+ scene.addItem(&w_signal);
+
+ QAction action(0);
+ action.setShortcut(Qt::Key_B);
+ action.setShortcutContext(Qt::WidgetWithChildrenShortcut);
+ QSignalSpy spy(&action, SIGNAL(triggered()));
+
+ w_signal.addAction(&action);
+
+ w_signal.setFocus();
+ QTest::keyPress(&view, Qt::Key_B);
+ QCOMPARE(spy.count(), 1);
+
+ w_signal.clearFocus();
+ QTest::keyPress(&view, Qt::Key_B);
+ QCOMPARE(spy.count(), 1);
+
+ scene.removeItem(&w_signal);
+}
+
+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);
+ }
+};
+
+class RectWidget : public QGraphicsWidget
+{
+public:
+
+ RectWidget(Qt::GlobalColor color, QGraphicsItem *parent=0) : QGraphicsWidget(parent), mColor(color) {}
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ {
+ painter->setBrush(QBrush(mColor));
+ painter->drawRect(boundingRect());
+ }
+
+ Qt::GlobalColor mColor;
+};
+
+class RectItem : public QGraphicsItem
+{
+public:
+
+ RectItem(Qt::GlobalColor color, QGraphicsItem *parent=0) : QGraphicsItem(parent), mColor(color) {}
+
+ QRectF boundingRect() const
+ {return QRectF(10,10,50,50);}
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ {
+ painter->setBrush(QBrush(mColor));
+ painter->drawRect(boundingRect());
+ }
+
+ Qt::GlobalColor mColor;
+};
+
+void tst_QGraphicsWidget::ensureClipping()
+{
+ ClippingAndTransformsScene scene;
+ scene.setSceneRect(-50, -50, 200, 200);
+
+ //A root that clip children
+ RectWidget *clipWidget = new RectWidget(Qt::black);
+ scene.addItem(clipWidget);
+
+ clipWidget->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
+
+ //a child
+ RectWidget *childWidget = new RectWidget(Qt::red, clipWidget);
+ clipWidget->setGeometry(QRectF(10, 10, 100, 100));
+ childWidget->setGeometry(QRectF(25, 25, 50, 50));
+
+ //We put a QGraphicsItem to be sure this one is also paint
+ RectItem *childitem = new RectItem(Qt::blue, clipWidget);
+
+ QGraphicsView view(&scene);
+ view.setOptimizationFlag(QGraphicsView::IndirectPainting);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QList<QGraphicsItem *> expected;
+ expected << clipWidget << childWidget << childitem;
+ QTRY_VERIFY(scene.drawnItems.contains(clipWidget));
+ QVERIFY(scene.drawnItems.contains(childWidget));
+ QVERIFY(scene.drawnItems.contains(childitem));
+}
+
+class ItemChangeTester : public QGraphicsWidget
+{
+public:
+ ItemChangeTester()
+ { setFlag(ItemSendsGeometryChanges); clear(); }
+ ItemChangeTester(QGraphicsItem *parent) : QGraphicsWidget(parent)
+ { setFlag(ItemSendsGeometryChanges); clear(); }
+
+ void clear()
+ {
+ changes.clear();
+ values.clear();
+ oldValues.clear();
+ }
+ 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;
+ default:
+ break;
+ }
+ return value;
+ }
+};
+
+void tst_QGraphicsWidget::widgetSendsGeometryChanges()
+{
+ ItemChangeTester widget;
+ widget.setFlags(0);
+ widget.clear();
+
+ QPointF pos(10, 10);
+ widget.setPos(pos);
+
+ QCOMPARE(widget.pos(), pos);
+ QCOMPARE(widget.changes.size(), 0);
+
+ widget.setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
+ QCOMPARE(widget.changes.size(), 2);
+
+ widget.setPos(QPointF());
+ QCOMPARE(widget.changes.size(), 4);
+
+ QCOMPARE(widget.pos(), QPointF());
+
+ QRectF geometry(20, 20, 50, 50);
+ widget.setGeometry(geometry);
+ QCOMPARE(widget.changes.size(), 6);
+
+ QCOMPARE(widget.geometry(), geometry);
+
+ QCOMPARE(widget.changes, QList<QGraphicsItem::GraphicsItemChange>()
+ << QGraphicsItem::ItemFlagsChange
+ << QGraphicsItem::ItemFlagsHaveChanged
+ << QGraphicsItem::ItemPositionChange
+ << QGraphicsItem::ItemPositionHasChanged
+ << QGraphicsItem::ItemPositionChange
+ << QGraphicsItem::ItemPositionHasChanged);
+}
+
+class HFWWidget : public QGraphicsWidget
+{
+public:
+ HFWWidget() : QGraphicsWidget(0, Qt::Window)
+ {
+ QSizePolicy sp;
+ sp.setHeightForWidth(true);
+ setSizePolicy(sp);
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ Q_UNUSED(option);
+ Q_UNUSED(widget);
+ qreal w = rect().width();
+ QRectF box(0, 0, w, 2400/w);
+ painter->drawRoundRect(box);
+ painter->drawLine(box.topLeft(), box.bottomRight());
+ painter->drawLine(box.bottomLeft(), box.topRight());
+ }
+
+protected:
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const
+ {
+ qreal w = constraint.width();
+ switch (which) {
+ case Qt::MinimumSize:
+ if (w >= 0 && constraint.height() < 0) {
+ // keep the same area of 60x40 = 2400
+ return QSizeF(w, 2400.0/w);
+ } else {
+ return QSizeF(10, 10);
+ }
+ break;
+ case Qt::PreferredSize:
+ return QSizeF(48.989794, 48.989794);
+ default:
+ break;
+ }
+ return QGraphicsWidget::sizeHint(which, constraint);
+ }
+};
+
+void tst_QGraphicsWidget::respectHFW()
+{
+#if defined(Q_OS_WINCE) || defined(Q_OS_MAC) || defined(Q_WS_QWS)
+ qDebug("This test is platform dependent, it fails on wince, mac and qws. Please fix.");
+#else
+ QGraphicsScene scene;
+ HFWWidget *window = new HFWWidget;
+ scene.addItem(window);
+ QGraphicsView *view = new QGraphicsView(&scene);
+ view->resize(400, 400);
+ view->setSceneRect(-100, -100, 300,300);
+
+ view->show();
+ window->setGeometry(0, 0, 70, 70);
+ QTest::qWaitForWindowShown(view);
+
+ { // here we go - simulate a interactive resize of the window
+ QTest::mouseMove(view, view->mapFromScene(71, 71)); // bottom right corner
+
+ QTest::mousePress(view->viewport(), Qt::LeftButton, 0, view->mapFromScene(71, 71), 200);
+ view->grabMouse();
+ // move both mouse cursor and set correct event in order to emulate resize
+ QTest::mouseMove(view->viewport(), view->mapFromScene(60, 30), 200);
+ QMouseEvent e = QMouseEvent(QEvent::MouseMove,
+ view->mapFromScene(60, 20),
+ Qt::NoButton,
+ Qt::LeftButton,
+ Qt::NoModifier);
+ QApplication::sendEvent(view->viewport(), &e);
+ view->releaseMouse();
+ }
+ const QSizeF winSize = window->size();
+ qreal minHFW = window->effectiveSizeHint(Qt::MinimumSize, QSizeF(winSize.width(), -1)).height();
+ QTRY_VERIFY(qAbs(minHFW - winSize.height()) < 1);
+#endif
+}
+
+class PolishWidget : public QGraphicsWidget
+{
+public:
+
+ PolishWidget(Qt::GlobalColor color, QGraphicsItem *parent=0) :
+ QGraphicsWidget(parent), mColor(color)
+ {
+ }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ {
+ painter->setBrush(QBrush(mColor));
+ painter->drawRect(boundingRect());
+ }
+
+ void polishEvent()
+ {
+ if (!parentWidget()) {
+ //We add a child in the polish event for the parent
+ PolishWidget *childWidget = new PolishWidget(Qt::black, this);
+ childWidget->setGeometry(QRectF(10,10,30,30));
+ }
+
+ QGraphicsWidget::polishEvent();
+ mColor = Qt::red;
+ update();
+ numberOfPolish++;
+ }
+
+ static int numberOfPolish;
+
+private:
+ Qt::GlobalColor mColor;
+};
+
+int PolishWidget::numberOfPolish = 0;
+
+void tst_QGraphicsWidget::addChildInpolishEvent()
+{
+ QGraphicsScene scene;
+
+ PolishWidget *parentWidget = new PolishWidget(Qt::white);
+ scene.addItem(parentWidget);
+
+ QGraphicsView view(&scene);
+ view.resize(200, 200);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(PolishWidget::numberOfPolish, 2);
+}
+
+void tst_QGraphicsWidget::polishEvent()
+{
+ class MyGraphicsWidget : public QGraphicsWidget
+ { public:
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *)
+ { events << QEvent::Paint; }
+ void polishEvent()
+ { events << QEvent::Polish; }
+ QList<QEvent::Type> events;
+ };
+
+ QGraphicsScene scene;
+
+ MyGraphicsWidget *widget = new MyGraphicsWidget;
+ scene.addItem(widget);
+
+ QGraphicsView view(&scene);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ // Make sure the item is painted.
+ QTRY_VERIFY(widget->events.contains(QEvent::Paint));
+
+ // Make sure the item got polish before paint.
+ QCOMPARE(widget->events.at(0), QEvent::Polish);
+}
+
+void tst_QGraphicsWidget::polishEvent2()
+{
+ class MyGraphicsWidget : public QGraphicsWidget
+ { public:
+ void polishEvent()
+ { events << QEvent::Polish; }
+ QList<QEvent::Type> events;
+ };
+
+ QGraphicsScene scene;
+
+ MyGraphicsWidget *widget = new MyGraphicsWidget;
+ widget->hide();
+ scene.addItem(widget);
+
+ widget->events.clear();
+
+ // Make sure the item got polish event.
+ QTRY_VERIFY(widget->events.contains(QEvent::Polish));
+}
+
+void tst_QGraphicsWidget::autoFillBackground()
+{
+ QGraphicsWidget *widget = new QGraphicsWidget;
+ QCOMPARE(widget->autoFillBackground(), false);
+ widget->setAutoFillBackground(true);
+ QCOMPARE(widget->autoFillBackground(), true);
+
+ const QColor color(Qt::red);
+ const QRect rect(0, 0, 1, 1);
+
+ QGraphicsScene scene;
+ scene.addItem(widget);
+ widget->setGeometry(rect);
+
+ QPalette palette = widget->palette();
+ palette.setColor(QPalette::Window, color);
+ widget->setPalette(palette);
+
+ QImage image(rect.size(), QImage::Format_RGB32);
+ QPainter painter;
+ painter.begin(&image);
+ scene.render(&painter, rect, rect);
+ painter.end();
+ QCOMPARE(image.pixel(0, 0), color.rgb());
+}
+
+void tst_QGraphicsWidget::initialShow()
+{
+ class MyGraphicsWidget : public QGraphicsWidget
+ { public:
+ MyGraphicsWidget() : repaints(0) {}
+ int repaints;
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget*) { ++repaints; }
+ void polishEvent() { update(); }
+ };
+
+ QGraphicsScene scene;
+ MyGraphicsWidget *widget = new MyGraphicsWidget;
+
+ QGraphicsView view(&scene);
+ if(PlatformQuirks::isAutoMaximizing())
+ view.showFullScreen();
+ else
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ scene.addItem(widget);
+
+ QTRY_COMPARE(widget->repaints, 1);
+}
+
+void tst_QGraphicsWidget::initialShow2()
+{
+ class MyGraphicsWidget : public QGraphicsWidget
+ { public:
+ MyGraphicsWidget() : repaints(0) {}
+ int repaints;
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget*) { ++repaints; }
+ void polishEvent() { update(); }
+ };
+
+ // Don't let paint events triggered by the windowing system
+ // influence our test case. We're only interested in knowing
+ // whether a QGraphicsWidget generates an additional repaint
+ // on the initial show. Hence create a dummy scenario to find out
+ // how many repaints we should expect.
+ QGraphicsScene dummyScene(0, 0, 200, 200);
+ dummyScene.addItem(new QGraphicsRectItem(0, 0, 100, 100));
+
+ QGraphicsView *dummyView = new QGraphicsView(&dummyScene);
+ dummyView->setWindowFlags(Qt::X11BypassWindowManagerHint);
+ EventSpy paintSpy(dummyView->viewport(), QEvent::Paint);
+ dummyView->show();
+ QTest::qWaitForWindowShown(dummyView);
+ const int expectedRepaintCount = paintSpy.count();
+ delete dummyView;
+ dummyView = 0;
+
+ MyGraphicsWidget *widget = new MyGraphicsWidget;
+ widget->resize(100, 100);
+
+ QGraphicsScene scene(0, 0, 200, 200);
+ scene.addItem(widget);
+
+ QGraphicsView view(&scene);
+ view.setWindowFlags(view.windowFlags()|Qt::X11BypassWindowManagerHint);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ QTRY_COMPARE(widget->repaints, expectedRepaintCount);
+}
+
+void tst_QGraphicsWidget::itemChangeEvents()
+{
+ class TestGraphicsWidget : public QGraphicsWidget
+ { public:
+ TestGraphicsWidget() : QGraphicsWidget() {}
+ QHash<QEvent::Type, QVariant> valueDuringEvents;
+ bool event(QEvent *event) {
+ Q_UNUSED(event);
+ switch (event->type()) {
+ case QEvent::EnabledChange: {
+ valueDuringEvents.insert(QEvent::EnabledChange, isEnabled());
+ break;
+ }
+ case QEvent::ParentAboutToChange: {
+ valueDuringEvents.insert(QEvent::ParentAboutToChange, qVariantFromValue(parentItem()));
+ break;
+ }
+ case QEvent::ParentChange: {
+ valueDuringEvents.insert(QEvent::ParentChange, qVariantFromValue(parentItem()));
+ break;
+ }
+ case QEvent::CursorChange: {
+ valueDuringEvents.insert(QEvent::CursorChange, int(cursor().shape()));
+ break;
+ }
+ case QEvent::ToolTipChange: {
+ valueDuringEvents.insert(QEvent::ToolTipChange, toolTip());
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ return true;
+ }
+ void showEvent(QShowEvent *event) {
+ Q_UNUSED(event);
+ valueDuringEvents.insert(QEvent::Show, isVisible());
+ }
+ void hideEvent(QHideEvent *event) {
+ Q_UNUSED(event);
+ valueDuringEvents.insert(QEvent::Hide, isVisible());
+ }
+ };
+
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *parent = new QGraphicsWidget;
+ scene.addItem(parent);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+
+ TestGraphicsWidget *item = new TestGraphicsWidget;
+ item->setParentItem(parent);
+ // ParentAboutToChange should be triggered before the parent has changed
+ QTRY_COMPARE(qVariantValue<QGraphicsItem *>(item->valueDuringEvents.value(QEvent::ParentAboutToChange)),
+ static_cast<QGraphicsItem *>(0));
+ // ParentChange should be triggered after the parent has changed
+ QTRY_COMPARE(qVariantValue<QGraphicsItem *>(item->valueDuringEvents.value(QEvent::ParentChange)),
+ static_cast<QGraphicsItem *>(parent));
+
+ // ShowEvent should be triggered before the item is shown
+ QTRY_VERIFY(!item->valueDuringEvents.value(QEvent::Show).toBool());
+
+ // HideEvent should be triggered after the item is hidden
+ QVERIFY(item->isVisible());
+ item->setVisible(false);
+ QVERIFY(!item->isVisible());
+ QTRY_VERIFY(!item->valueDuringEvents.value(QEvent::Hide).toBool());
+
+ // CursorChange should be triggered after the cursor has changed
+ item->setCursor(Qt::PointingHandCursor);
+ QTRY_COMPARE(item->valueDuringEvents.value(QEvent::CursorChange).toInt(), int(item->cursor().shape()));
+
+ // ToolTipChange should be triggered after the tooltip has changed
+ item->setToolTip("tooltipText");
+ QTRY_COMPARE(item->valueDuringEvents.value(QEvent::ToolTipChange).toString(), item->toolTip());
+
+ // EnabledChange should be triggered after the enabled state has changed
+ QVERIFY(item->isEnabled());
+ item->setEnabled(false);
+ QVERIFY(!item->isEnabled());
+ QTRY_VERIFY(!item->valueDuringEvents.value(QEvent::EnabledChange).toBool());
+}
+
+void tst_QGraphicsWidget::itemSendGeometryPosChangesDeactivated()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+ QGraphicsWidget *item = new QGraphicsWidget;
+ scene.addItem(item);
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ item->setGeometry(QRectF(0, 0, 50, 50));
+ QTRY_COMPARE(item->geometry(), QRectF(0, 0, 50, 50));
+
+ item->setFlag(QGraphicsItem::ItemSendsGeometryChanges, false);
+ item->setGeometry(QRectF(0, 0, 60, 60));
+ QCOMPARE(item->geometry(), QRectF(0, 0, 60, 60));
+ QCOMPARE(item->pos(), QPointF(0, 0));
+ item->setPos(QPointF(10, 10));
+ QCOMPARE(item->pos(), QPointF(10, 10));
+ QCOMPARE(item->geometry(), QRectF(10, 10, 60, 60));
+
+ item->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, false);
+ item->setGeometry(QRectF(0, 0, 60, 60));
+ QCOMPARE(item->geometry(), QRectF(0, 0, 60, 60));
+ QCOMPARE(item->pos(), QPointF(0, 0));
+ item->setPos(QPointF(10, 10));
+ QCOMPARE(item->pos(), QPointF(10, 10));
+ QCOMPARE(item->geometry(), QRectF(10, 10, 60, 60));
+}
+
+void tst_QGraphicsWidget::QT_BUG_6544_tabFocusFirstUnsetWhenRemovingItems()
+{
+ QGraphicsScene scene;
+ QGraphicsWidget* parent1 = new QGraphicsWidget;
+ QGraphicsWidget* child1_0 = new QGraphicsWidget;
+ QGraphicsWidget* child1_1 = new QGraphicsWidget;
+
+ QGraphicsWidget* parent2 = new QGraphicsWidget;
+
+ // Add the parent and child to the scene.
+ scene.addItem(parent1);
+ child1_0->setParentItem(parent1);
+ child1_1->setParentItem(parent1);
+
+ // Hide and show the child.
+ child1_0->setParentItem(NULL);
+ scene.removeItem(child1_0);
+
+ // Remove parent from the scene.
+ scene.removeItem(parent1);
+
+ delete child1_0;
+ delete child1_1;
+ delete parent1;
+
+ // Add an item into the scene.
+ scene.addItem(parent2);
+
+ //This should not crash
+}
+void tst_QGraphicsWidget::QT_BUG_12056_tabFocusFirstUnsetWhenRemovingItems()
+{
+ QGraphicsScene scene;
+ QGraphicsWidget* item1 = new QGraphicsWidget;
+ QGraphicsWidget* item2 = new QGraphicsWidget;
+ QGraphicsWidget* item3 = new QGraphicsWidget;
+
+ scene.addItem(item1);
+ scene.addItem(item2);
+
+ scene.removeItem(item2);
+ scene.removeItem(item1);
+ delete item2;
+ delete item1;
+
+ scene.addItem(item3);
+
+ //This should not crash
+}
+
+QTEST_MAIN(tst_QGraphicsWidget)
+#include "tst_qgraphicswidget.moc"