1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
43 #include <QtTest/QtTest>
45 #include <qgraphicsitem.h>
46 #include <qgraphicsscene.h>
47 #include <qgraphicssceneevent.h>
48 #include <qgraphicsview.h>
49 #include <qgraphicswidget.h>
50 #include <qgraphicsproxywidget.h>
54 #include <QtWidgets/QLabel>
55 #if !defined(QT_NO_STYLE_WINDOWS)
56 #include <QtWidgets/QWindowsStyle>
58 #if !defined(QT_NO_STYLE_PLASTIQUE)
59 #include <QtWidgets/QPlastiqueStyle>
61 #include <QtGui/QPainterPath>
62 #include <QtWidgets/QRubberBand>
63 #include <QtWidgets/QScrollBar>
64 #include <QtWidgets/QStyleOption>
65 #include <QtWidgets/QBoxLayout>
66 #include <QtWidgets/QStyle>
67 #include <QtWidgets/QPushButton>
68 #include <QtWidgets/QDesktopWidget>
69 #include <private/qgraphicsscene_p.h>
70 #include <private/qgraphicsview_p.h>
71 #include "../../../shared/platforminputcontext.h"
72 #include <private/qinputmethod_p.h>
74 #include "../../../qtest-config.h"
76 Q_DECLARE_METATYPE(QList<int>)
77 Q_DECLARE_METATYPE(QList<QRectF>)
78 Q_DECLARE_METATYPE(QMatrix)
79 Q_DECLARE_METATYPE(QPainterPath)
80 Q_DECLARE_METATYPE(QPointF)
81 Q_DECLARE_METATYPE(QPolygonF)
82 Q_DECLARE_METATYPE(QRectF)
83 Q_DECLARE_METATYPE(Qt::ScrollBarPolicy)
86 //On mac we get full update. So check that the expected region is contained inside the actual
87 #define COMPARE_REGIONS(ACTUAL, EXPECTED) QVERIFY((EXPECTED).subtracted(ACTUAL).isEmpty())
89 #define COMPARE_REGIONS QCOMPARE
92 static void sendMousePress(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::LeftButton)
94 QMouseEvent event(QEvent::MouseButtonPress, point, widget->mapToGlobal(point), button, 0, 0);
95 QApplication::sendEvent(widget, &event);
98 static void sendMouseMove(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::NoButton, Qt::MouseButtons buttons = 0)
100 QTest::mouseMove(widget, point);
101 QMouseEvent event(QEvent::MouseMove, point, button, buttons, 0);
102 QApplication::sendEvent(widget, &event);
103 QApplication::processEvents();
106 static void sendMouseRelease(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::LeftButton)
108 QMouseEvent event(QEvent::MouseButtonRelease, point, widget->mapToGlobal(point), button, 0, 0);
109 QApplication::sendEvent(widget, &event);
112 class EventSpy : public QObject
116 EventSpy(QObject *watched, QEvent::Type type)
117 : _count(0), spied(type)
119 watched->installEventFilter(this);
122 int count() const { return _count; }
123 void reset() { _count = 0; }
126 bool eventFilter(QObject *watched, QEvent *event)
129 if (event->type() == spied)
138 #if defined QT_BUILD_INTERNAL
139 class FriendlyGraphicsScene : public QGraphicsScene
141 friend class tst_QGraphicsView;
142 Q_DECLARE_PRIVATE(QGraphicsScene);
146 class tst_QGraphicsView : public QObject
161 void sceneRect_growing();
164 void dragMode_scrollHand();
165 void dragMode_rubberBand();
166 void rubberBandSelectionMode();
167 void backgroundBrush();
168 void foregroundBrush();
170 void matrix_convenience();
171 void matrix_combine();
172 void centerOnPoint();
174 void ensureVisibleRect();
177 #if defined QT_BUILD_INTERNAL
178 void itemsAtPosition_data();
179 void itemsAtPosition();
182 void itemsInRect_cosmeticAdjust_data();
183 void itemsInRect_cosmeticAdjust();
189 void mapToScenePoint();
190 void mapToSceneRect_data();
191 void mapToSceneRect();
192 void mapToScenePoly();
193 void mapToScenePath();
194 void mapFromScenePoint();
195 void mapFromSceneRect();
196 void mapFromScenePoly();
197 void mapFromScenePath();
200 #ifndef QTEST_NO_CURSOR
204 void transformationAnchor();
206 void viewportUpdateMode();
207 void viewportUpdateMode2();
208 #ifndef QT_NO_DRAGANDDROP
211 void optimizationFlags();
212 void optimizationFlags_dontSavePainterState();
213 void optimizationFlags_dontSavePainterState2_data();
214 void optimizationFlags_dontSavePainterState2();
215 void levelOfDetail_data();
216 void levelOfDetail();
217 void scrollBarRanges_data();
218 void scrollBarRanges();
219 void acceptMousePressEvent();
220 void replayMouseMove();
221 void itemsUnderMouse();
222 void embeddedViews();
223 void scrollAfterResize_data();
224 void scrollAfterResize();
225 void moveItemWhileScrolling_data();
226 void moveItemWhileScrolling();
227 void centerOnDirtyItem();
228 void mouseTracking();
229 void mouseTracking2();
230 void mouseTracking3();
237 void update_ancestorClipsChildrenToShape();
238 void update_ancestorClipsChildrenToShape2();
239 void inputMethodSensitivity();
240 void inputContextReset();
241 void indirectPainting();
242 void compositionModeInDrawBackground();
244 // task specific tests below me
245 void task172231_untransformableItems();
246 void task180429_mouseReleaseDragMode();
247 void task187791_setSceneCausesUpdate();
248 void task186827_deleteReplayedItem();
249 void task207546_focusCrash();
250 void task210599_unsetDragWhileDragging();
251 void task236394_sendShortcutOverrideEvent();
252 void task239729_noViewUpdate_data();
253 void task239729_noViewUpdate();
254 void task239047_fitInViewSmallViewport();
255 void task245469_itemsAtPointWithClip();
256 void task253415_reconnectUpdateSceneOnSceneChanged();
257 void task255529_transformationAnchorMouseAndViewportMargins();
258 void task259503_scrollingArtifacts();
259 void QTBUG_4151_clipAndIgnore_data();
260 void QTBUG_4151_clipAndIgnore();
261 void QTBUG_5859_exposedRect();
262 #ifndef QTEST_NO_CURSOR
263 void QTBUG_7438_cursor();
266 void QTBUG_16063_microFocusRect();
272 void tst_QGraphicsView::initTestCase()
275 qApp->setAutoMaximizeThreshold(-1);
279 void tst_QGraphicsView::cleanup()
281 // ensure not even skipped tests with custom input context leave it dangling
282 QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
283 inputMethodPrivate->testContext = 0;
286 void tst_QGraphicsView::construction()
289 QCOMPARE(view.renderHints(), QPainter::TextAntialiasing);
290 QCOMPARE(view.dragMode(), QGraphicsView::NoDrag);
291 QVERIFY(view.isInteractive());
292 QVERIFY(!view.scene());
293 QCOMPARE(view.sceneRect(), QRectF());
294 QVERIFY(view.viewport());
295 QCOMPARE(view.viewport()->metaObject()->className(), "QWidget");
296 QCOMPARE(view.matrix(), QMatrix());
297 QVERIFY(view.items().isEmpty());
298 QVERIFY(view.items(QPoint()).isEmpty());
299 QVERIFY(view.items(QRect()).isEmpty());
300 QVERIFY(view.items(QPolygon()).isEmpty());
301 QVERIFY(view.items(QPainterPath()).isEmpty());
302 QVERIFY(!view.itemAt(QPoint()));
303 QCOMPARE(view.mapToScene(QPoint()), QPointF());
304 QCOMPARE(view.mapToScene(QRect()), QPolygonF());
305 QCOMPARE(view.mapToScene(QPolygon()), QPolygonF());
306 QCOMPARE(view.mapFromScene(QPointF()), QPoint());
308 poly << QPoint() << QPoint() << QPoint() << QPoint();
309 QCOMPARE(view.mapFromScene(QRectF()), poly);
310 QCOMPARE(view.mapFromScene(QPolygonF()), QPolygon());
311 QCOMPARE(view.transformationAnchor(), QGraphicsView::AnchorViewCenter);
312 QCOMPARE(view.resizeAnchor(), QGraphicsView::NoAnchor);
314 QVERIFY(QTest::qWaitForWindowExposed(&view));
317 class TestItem : public QGraphicsItem
320 QRectF boundingRect() const
321 { return QRectF(-10, -10, 20, 20); }
323 void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
324 { hints = painter->renderHints(); painter->drawRect(boundingRect()); }
326 bool sceneEvent(QEvent *event)
328 events << event->type();
329 return QGraphicsItem::sceneEvent(event);
332 QList<QEvent::Type> events;
333 QPainter::RenderHints hints;
336 void tst_QGraphicsView::renderHints()
339 QCOMPARE(view.renderHints(), QPainter::TextAntialiasing);
340 view.setRenderHint(QPainter::TextAntialiasing, false);
341 QCOMPARE(view.renderHints(), 0);
342 view.setRenderHint(QPainter::Antialiasing, false);
343 QCOMPARE(view.renderHints(), 0);
344 view.setRenderHint(QPainter::TextAntialiasing, true);
345 QCOMPARE(view.renderHints(), QPainter::TextAntialiasing);
346 view.setRenderHint(QPainter::Antialiasing);
347 QCOMPARE(view.renderHints(), QPainter::TextAntialiasing | QPainter::Antialiasing);
348 view.setRenderHints(0);
349 QCOMPARE(view.renderHints(), 0);
351 TestItem *item = new TestItem;
352 QGraphicsScene scene;
355 view.setScene(&scene);
357 view.setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing | QPainter::NonCosmeticDefaultPen);
358 QCOMPARE(view.renderHints(), QPainter::TextAntialiasing | QPainter::Antialiasing | QPainter::NonCosmeticDefaultPen);
360 QCOMPARE(item->hints, 0);
362 QVERIFY(QTest::qWaitForWindowExposed(&view));
364 QTRY_COMPARE(item->hints, view.renderHints());
366 view.setRenderHints(QPainter::Antialiasing | QPainter::NonCosmeticDefaultPen);
367 QCOMPARE(view.renderHints(), QPainter::Antialiasing | QPainter::NonCosmeticDefaultPen);
370 QTRY_COMPARE(item->hints, view.renderHints());
373 void tst_QGraphicsView::alignment()
375 QGraphicsScene scene;
376 scene.addRect(QRectF(-10, -10, 20, 20));
378 QGraphicsView view(&scene);
380 QVERIFY(QTest::qWaitForWindowExposed(&view));
382 for (int i = 0; i < 3; ++i) {
383 for (int j = 0; j < 3; ++j) {
384 Qt::Alignment alignment = 0;
387 alignment |= Qt::AlignLeft;
390 alignment |= Qt::AlignHCenter;
394 alignment |= Qt::AlignRight;
399 alignment |= Qt::AlignTop;
402 alignment |= Qt::AlignVCenter;
406 alignment |= Qt::AlignBottom;
409 view.setAlignment(alignment);
410 QCOMPARE(view.alignment(), alignment);
412 for (int k = 0; k < 3; ++k) {
413 view.resize(100 + k * 25, 100 + k * 25);
414 QApplication::processEvents();
420 void tst_QGraphicsView::interactive()
422 TestItem *item = new TestItem;
423 item->setFlags(QGraphicsItem::ItemIsMovable);
424 QCOMPARE(item->events.size(), 0);
426 QGraphicsScene scene(-200, -200, 400, 400);
429 QGraphicsView view(&scene);
430 view.setFixedSize(300, 300);
431 QCOMPARE(item->events.size(), 0);
433 view.activateWindow();
434 QVERIFY(QTest::qWaitForWindowActive(&view));
436 QTRY_COMPARE(item->events.size(), 1); // activate
438 QPoint itemPoint = view.mapFromScene(item->scenePos());
440 QVERIFY(view.itemAt(itemPoint));
442 for (int i = 0; i < 100; ++i) {
443 sendMousePress(view.viewport(), itemPoint);
444 QCOMPARE(item->events.size(), i * 5 + 3);
445 QCOMPARE(item->events.at(item->events.size() - 2), QEvent::GrabMouse);
446 QCOMPARE(item->events.at(item->events.size() - 1), QEvent::GraphicsSceneMousePress);
447 sendMouseRelease(view.viewport(), itemPoint);
448 QCOMPARE(item->events.size(), i * 5 + 5);
449 QCOMPARE(item->events.at(item->events.size() - 2), QEvent::GraphicsSceneMouseRelease);
450 QCOMPARE(item->events.at(item->events.size() - 1), QEvent::UngrabMouse);
451 QContextMenuEvent contextEvent(QContextMenuEvent::Mouse, itemPoint, view.mapToGlobal(itemPoint));
452 QApplication::sendEvent(view.viewport(), &contextEvent);
453 QCOMPARE(item->events.size(), i * 5 + 6);
454 QCOMPARE(item->events.last(), QEvent::GraphicsSceneContextMenu);
457 view.setInteractive(false);
459 for (int i = 0; i < 100; ++i) {
460 sendMousePress(view.viewport(), itemPoint);
461 QCOMPARE(item->events.size(), 501);
462 QCOMPARE(item->events.last(), QEvent::GraphicsSceneContextMenu);
463 sendMouseRelease(view.viewport(), itemPoint);
464 QCOMPARE(item->events.size(), 501);
465 QCOMPARE(item->events.last(), QEvent::GraphicsSceneContextMenu);
466 QContextMenuEvent contextEvent(QContextMenuEvent::Mouse, itemPoint, view.mapToGlobal(itemPoint));
467 QApplication::sendEvent(view.viewport(), &contextEvent);
468 QCOMPARE(item->events.size(), 501);
469 QCOMPARE(item->events.last(), QEvent::GraphicsSceneContextMenu);
473 void tst_QGraphicsView::scene()
476 QVERIFY(!view.scene());
478 QVERIFY(!view.scene());
481 QGraphicsScene scene;
482 view.setScene(&scene);
483 QCOMPARE(view.scene(), &scene);
486 QCOMPARE(view.scene(), (QGraphicsScene *)0);
489 void tst_QGraphicsView::setScene()
491 QGraphicsScene scene(-1000, -1000, 2000, 2000);
493 QGraphicsView view(&scene);
495 QVERIFY(QTest::qWaitForWindowExposed(&view));
497 QCOMPARE(view.sceneRect(), scene.sceneRect());
499 QVERIFY(view.horizontalScrollBar()->isVisible());
500 QVERIFY(view.verticalScrollBar()->isVisible());
501 QVERIFY(!view.horizontalScrollBar()->isHidden());
502 QVERIFY(!view.verticalScrollBar()->isHidden());
508 QVERIFY(!view.horizontalScrollBar()->isVisible());
509 QVERIFY(!view.verticalScrollBar()->isVisible());
510 QVERIFY(!view.horizontalScrollBar()->isHidden());
511 QVERIFY(!view.verticalScrollBar()->isHidden());
513 QCOMPARE(view.sceneRect(), QRectF());
516 void tst_QGraphicsView::deleteScene()
518 QGraphicsScene *scene = new QGraphicsScene;
519 QGraphicsView view1(scene);
521 QGraphicsView view2(scene);
523 QGraphicsView view3(scene);
526 QCOMPARE(view1.scene(), (QGraphicsScene *)0);
527 QCOMPARE(view2.scene(), (QGraphicsScene *)0);
528 QCOMPARE(view3.scene(), (QGraphicsScene *)0);
531 void tst_QGraphicsView::sceneRect()
534 QCOMPARE(view.sceneRect(), QRectF());
536 view.setSceneRect(QRectF(-100, -100, 200, 200));
537 QCOMPARE(view.sceneRect(), QRectF(-100, -100, 200, 200));
538 view.setSceneRect(-100, -100, 200, 200);
539 QCOMPARE(view.sceneRect(), QRectF(-100, -100, 200, 200));
541 view.setSceneRect(QRectF());
542 QCOMPARE(view.sceneRect(), QRectF());
543 QGraphicsScene scene;
544 QGraphicsRectItem *item = scene.addRect(QRectF(-100, -100, 100, 100));
546 view.setScene(&scene);
548 QCOMPARE(view.sceneRect(), QRectF(-100, -100, 100, 100));
549 item->moveBy(-100, -100);
550 QCOMPARE(view.sceneRect(), QRectF(-200, -200, 200, 200));
551 item->moveBy(100, 100);
552 QCOMPARE(view.sceneRect(), QRectF(-200, -200, 200, 200));
555 view.setSceneRect(QRectF());
556 QCOMPARE(view.sceneRect(), QRectF());
559 void tst_QGraphicsView::sceneRect_growing()
563 QGraphicsScene scene;
564 for (int i = 0; i < 100; ++i)
565 scene.addText(QString("(0, %1)").arg((i - 50) * 20))->setPos(0, (i - 50) * 20);
567 QGraphicsView view(&scene, &toplevel);
568 view.setFixedSize(200, 200);
572 scene.setSceneRect(-size, -size, size * 2, size * 2);
573 QCOMPARE(view.sceneRect(), scene.sceneRect());
577 QPointF topLeft = view.mapToScene(0, 0);
579 for (int i = 0; i < 5; ++i) {
581 scene.setSceneRect(-size, -size, size * 2, size * 2);
583 QApplication::processEvents();
585 QCOMPARE(view.sceneRect(), scene.sceneRect());
586 QCOMPARE(view.mapToScene(0, 0), topLeft);
587 view.setSceneRect(-size, -size, size * 2, size * 2);
588 QCOMPARE(view.mapToScene(0, 0), topLeft);
589 view.setSceneRect(QRectF());
593 void tst_QGraphicsView::setSceneRect()
595 QRectF rect1(-100, -100, 200, 200);
596 QRectF rect2(-300, -300, 150, 150);
598 QGraphicsScene scene;
599 QGraphicsView view(&scene);
601 scene.setSceneRect(rect1);
602 QCOMPARE(scene.sceneRect(), rect1);
603 QCOMPARE(view.sceneRect(), rect1);
605 scene.setSceneRect(rect2);
606 QCOMPARE(scene.sceneRect(), rect2);
607 QCOMPARE(view.sceneRect(), rect2);
609 view.setSceneRect(rect1);
610 QCOMPARE(scene.sceneRect(), rect2);
611 QCOMPARE(view.sceneRect(), rect1);
613 view.setSceneRect(rect2);
614 QCOMPARE(scene.sceneRect(), rect2);
615 QCOMPARE(view.sceneRect(), rect2);
617 scene.setSceneRect(rect1);
618 QCOMPARE(scene.sceneRect(), rect1);
619 QCOMPARE(view.sceneRect(), rect2);
621 // extreme transformations will max out the scrollbars' ranges.
622 view.setSceneRect(-2000000, -2000000, 4000000, 4000000);
623 view.scale(9000, 9000);
624 QCOMPARE(view.horizontalScrollBar()->minimum(), INT_MIN);
625 QCOMPARE(view.horizontalScrollBar()->maximum(), INT_MAX);
626 QCOMPARE(view.verticalScrollBar()->minimum(), INT_MIN);
627 QCOMPARE(view.verticalScrollBar()->maximum(), INT_MAX);
630 void tst_QGraphicsView::viewport()
632 QGraphicsScene scene;
633 scene.addText("GraphicsView");
635 QGraphicsView view(&scene);
636 QVERIFY(view.viewport() != 0);
641 QPointer<QWidget> widget = new QWidget;
642 view.setViewport(widget);
643 QCOMPARE(view.viewport(), (QWidget *)widget);
649 QVERIFY(widget.isNull());
650 QVERIFY(view.viewport() != 0);
651 QVERIFY(view.viewport() != widget);
657 void tst_QGraphicsView::dragMode_scrollHand()
659 for (int j = 0; j < 2; ++j) {
661 QCOMPARE(view.dragMode(), QGraphicsView::NoDrag);
663 view.setSceneRect(-1000, -1000, 2000, 2000);
664 view.setFixedSize(100, 100);
667 QVERIFY(QTest::qWaitForWindowExposed(&view));
668 QApplication::processEvents();
670 view.setInteractive(j ? false : true);
672 QGraphicsScene scene;
673 scene.addRect(QRectF(-100, -100, 5, 5));
674 scene.addRect(QRectF(95, -100, 5, 5));
675 scene.addRect(QRectF(95, 95, 5, 5));
676 QGraphicsItem *item = scene.addRect(QRectF(-100, 95, 5, 5));
677 item->setFlag(QGraphicsItem::ItemIsSelectable);
678 item->setSelected(true);
679 QVERIFY(item->isSelected());
680 QVERIFY(!view.scene());
682 view.setDragMode(QGraphicsView::ScrollHandDrag);
684 for (int i = 0; i < 2; ++i) {
686 #ifndef QTEST_NO_CURSOR
687 Qt::CursorShape cursorShape = view.viewport()->cursor().shape();
689 int horizontalScrollBarValue = view.horizontalScrollBar()->value();
690 int verticalScrollBarValue = view.verticalScrollBar()->value();
693 QMouseEvent event(QEvent::MouseButtonPress,
694 view.viewport()->rect().center(),
695 Qt::LeftButton, Qt::LeftButton, 0);
696 event.setAccepted(true);
697 QApplication::sendEvent(view.viewport(), &event);
698 QVERIFY(event.isAccepted());
700 QApplication::processEvents();
702 QTRY_VERIFY(item->isSelected());
704 for (int k = 0; k < 4; ++k) {
705 #ifndef QTEST_NO_CURSOR
706 QCOMPARE(view.viewport()->cursor().shape(), Qt::ClosedHandCursor);
710 QMouseEvent event(QEvent::MouseMove,
711 view.viewport()->rect().center() + QPoint(10, 0),
712 Qt::LeftButton, Qt::LeftButton, 0);
713 event.setAccepted(true);
714 QApplication::sendEvent(view.viewport(), &event);
715 QVERIFY(event.isAccepted());
717 QVERIFY(item->isSelected());
718 QCOMPARE(view.horizontalScrollBar()->value(), horizontalScrollBarValue - 10);
719 QCOMPARE(view.verticalScrollBar()->value(), verticalScrollBarValue);
722 QMouseEvent event(QEvent::MouseMove,
723 view.viewport()->rect().center() + QPoint(10, 10),
724 Qt::LeftButton, Qt::LeftButton, 0);
725 event.setAccepted(true);
726 QApplication::sendEvent(view.viewport(), &event);
727 QVERIFY(event.isAccepted());
729 QVERIFY(item->isSelected());
730 QCOMPARE(view.horizontalScrollBar()->value(), horizontalScrollBarValue - 10);
731 QCOMPARE(view.verticalScrollBar()->value(), verticalScrollBarValue - 10);
736 QMouseEvent event(QEvent::MouseButtonRelease,
737 view.viewport()->rect().center() + QPoint(10, 10),
738 Qt::LeftButton, Qt::LeftButton, 0);
739 event.setAccepted(true);
740 QApplication::sendEvent(view.viewport(), &event);
741 QVERIFY(event.isAccepted());
743 QApplication::processEvents();
745 QTRY_VERIFY(item->isSelected());
746 QCOMPARE(view.horizontalScrollBar()->value(), horizontalScrollBarValue - 10);
747 QCOMPARE(view.verticalScrollBar()->value(), verticalScrollBarValue - 10);
748 #ifndef QTEST_NO_CURSOR
749 QCOMPARE(view.viewport()->cursor().shape(), cursorShape);
752 // Check that items are not unselected because of a scroll hand drag.
753 QVERIFY(item->isSelected());
755 // Check that a click will still unselect the item.
758 QMouseEvent event(QEvent::MouseButtonPress,
759 view.viewport()->rect().center() + QPoint(10, 10),
760 Qt::LeftButton, Qt::LeftButton, 0);
761 QApplication::sendEvent(view.viewport(), &event);
765 QMouseEvent event(QEvent::MouseButtonRelease,
766 view.viewport()->rect().center() + QPoint(10, 10),
767 Qt::LeftButton, Qt::LeftButton, 0);
768 QApplication::sendEvent(view.viewport(), &event);
771 if (view.isInteractive()) {
773 QVERIFY(!item->isSelected());
774 item->setSelected(true);
776 QVERIFY(item->isSelected());
779 QVERIFY(item->isSelected());
782 view.setScene(&scene);
787 void tst_QGraphicsView::dragMode_rubberBand()
790 QCOMPARE(view.dragMode(), QGraphicsView::NoDrag);
792 view.setSceneRect(-1000, -1000, 2000, 2000);
795 QGraphicsScene scene;
796 scene.addRect(QRectF(-100, -100, 25, 25))->setFlag(QGraphicsItem::ItemIsSelectable);
797 scene.addRect(QRectF(75, -100, 25, 25))->setFlag(QGraphicsItem::ItemIsSelectable);
798 scene.addRect(QRectF(75, 75, 25, 25))->setFlag(QGraphicsItem::ItemIsSelectable);
799 scene.addRect(QRectF(-100, 75, 25, 25))->setFlag(QGraphicsItem::ItemIsSelectable);
801 view.setDragMode(QGraphicsView::RubberBandDrag);
803 QVERIFY(QTest::qWaitForWindowExposed(&view));
804 QApplication::processEvents();
806 for (int i = 0; i < 2; ++i) {
808 #ifndef QTEST_NO_CURSOR
809 Qt::CursorShape cursorShape = view.viewport()->cursor().shape();
811 int horizontalScrollBarValue = view.horizontalScrollBar()->value();
812 int verticalScrollBarValue = view.verticalScrollBar()->value();
815 QMouseEvent event(QEvent::MouseButtonPress,
816 view.viewport()->rect().center(),
817 Qt::LeftButton, Qt::LeftButton, 0);
818 event.setAccepted(true);
819 QApplication::sendEvent(view.viewport(), &event);
820 QVERIFY(event.isAccepted());
822 #ifndef QTEST_NO_CURSOR
823 QCOMPARE(view.viewport()->cursor().shape(), cursorShape);
826 QApplication::processEvents();
830 QMouseEvent event(QEvent::MouseMove,
831 view.viewport()->rect().center() + QPoint(100, 0),
832 Qt::LeftButton, Qt::LeftButton, 0);
833 event.setAccepted(true);
834 QApplication::sendEvent(view.viewport(), &event);
835 QVERIFY(event.isAccepted());
837 QCOMPARE(view.horizontalScrollBar()->value(), horizontalScrollBarValue);
838 QCOMPARE(view.verticalScrollBar()->value(), verticalScrollBarValue);
840 // We don't use QRubberBand as of 4.3; the band is drawn internally.
841 QVERIFY(!qFindChild<QRubberBand *>(&view));
847 QMouseEvent event(QEvent::MouseMove,
848 view.viewport()->rect().center() + QPoint(100, 100),
849 Qt::LeftButton, Qt::LeftButton, 0);
850 event.setAccepted(true);
851 QApplication::sendEvent(view.viewport(), &event);
852 QVERIFY(event.isAccepted());
854 QCOMPARE(view.horizontalScrollBar()->value(), horizontalScrollBarValue);
855 QCOMPARE(view.verticalScrollBar()->value(), verticalScrollBarValue);
861 QMouseEvent event(QEvent::MouseButtonRelease,
862 view.viewport()->rect().center() + QPoint(100, 100),
863 Qt::LeftButton, Qt::LeftButton, 0);
864 event.setAccepted(true);
865 QApplication::sendEvent(view.viewport(), &event);
866 QVERIFY(event.isAccepted());
868 QCOMPARE(view.horizontalScrollBar()->value(), horizontalScrollBarValue);
869 QCOMPARE(view.verticalScrollBar()->value(), verticalScrollBarValue);
870 #ifndef QTEST_NO_CURSOR
871 QCOMPARE(view.viewport()->cursor().shape(), cursorShape);
877 QCOMPARE(scene.selectedItems().size(), 1);
879 view.setScene(&scene);
884 void tst_QGraphicsView::rubberBandSelectionMode()
888 QGraphicsScene scene;
889 QGraphicsRectItem *rect = scene.addRect(QRectF(10, 10, 80, 80));
890 rect->setFlag(QGraphicsItem::ItemIsSelectable);
892 QGraphicsView view(&scene, &toplevel);
893 QCOMPARE(view.rubberBandSelectionMode(), Qt::IntersectsItemShape);
894 view.setDragMode(QGraphicsView::RubberBandDrag);
895 view.resize(120, 120);
898 // Disable mouse tracking to prevent the window system from sending mouse
899 // move events to the viewport while we are synthesizing events. If
900 // QGraphicsView gets a mouse move event with no buttons down, it'll
901 // terminate the rubber band.
902 view.viewport()->setMouseTracking(false);
904 QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>());
905 sendMousePress(view.viewport(), QPoint(), Qt::LeftButton);
906 sendMouseMove(view.viewport(), view.viewport()->rect().center(),
907 Qt::LeftButton, Qt::LeftButton);
908 QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>() << rect);
909 sendMouseRelease(view.viewport(), QPoint(), Qt::LeftButton);
911 view.setRubberBandSelectionMode(Qt::ContainsItemShape);
912 QCOMPARE(view.rubberBandSelectionMode(), Qt::ContainsItemShape);
913 sendMousePress(view.viewport(), QPoint(), Qt::LeftButton);
914 QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>());
915 sendMouseMove(view.viewport(), view.viewport()->rect().center(),
916 Qt::LeftButton, Qt::LeftButton);
917 QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>());
918 sendMouseMove(view.viewport(), view.viewport()->rect().bottomRight(),
919 Qt::LeftButton, Qt::LeftButton);
920 QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>() << rect);
923 void tst_QGraphicsView::backgroundBrush()
925 QGraphicsScene scene;
926 QGraphicsView view(&scene);
927 scene.setBackgroundBrush(Qt::blue);
928 QCOMPARE(scene.backgroundBrush(), QBrush(Qt::blue));
933 scene.setBackgroundBrush(QBrush());
934 QCOMPARE(scene.backgroundBrush(), QBrush());
937 QRadialGradient gradient(0, 0, 10);
938 gradient.setSpread(QGradient::RepeatSpread);
939 scene.setBackgroundBrush(gradient);
941 QCOMPARE(scene.backgroundBrush(), QBrush(gradient));
945 void tst_QGraphicsView::foregroundBrush()
947 QGraphicsScene scene;
948 QGraphicsView view(&scene);
949 scene.setForegroundBrush(Qt::blue);
950 QCOMPARE(scene.foregroundBrush(), QBrush(Qt::blue));
955 scene.setForegroundBrush(QBrush());
956 QCOMPARE(scene.foregroundBrush(), QBrush());
959 QRadialGradient gradient(0, 0, 10);
960 gradient.setSpread(QGradient::RepeatSpread);
961 scene.setForegroundBrush(gradient);
963 QCOMPARE(scene.foregroundBrush(), QBrush(gradient));
966 for (int i = 0; i < 50; ++i) {
967 QRadialGradient gradient(view.rect().center() + QPoint(int(sin(i / 2.0) * 10), int(cos(i / 2.0) * 10)), 10);
968 gradient.setColorAt(0, Qt::transparent);
969 gradient.setColorAt(0.5, Qt::black);
970 gradient.setColorAt(1, Qt::transparent);
971 gradient.setSpread(QGradient::RepeatSpread);
972 scene.setForegroundBrush(gradient);
974 QRadialGradient gradient2(view.rect().center() + QPoint(int(sin(i / 1.7) * 10), int(cos(i / 1.7) * 10)), 10);
975 gradient2.setColorAt(0, Qt::transparent);
976 gradient2.setColorAt(0.5, Qt::black);
977 gradient2.setColorAt(1, Qt::transparent);
978 gradient2.setSpread(QGradient::RepeatSpread);
979 scene.setBackgroundBrush(gradient2);
981 QRadialGradient gradient3(view.rect().center() + QPoint(int(sin(i / 1.85) * 10), int(cos(i / 1.85) * 10)), 10);
982 gradient3.setColorAt(0, Qt::transparent);
983 gradient3.setColorAt(0.5, Qt::black);
984 gradient3.setColorAt(1, Qt::transparent);
985 gradient3.setSpread(QGradient::RepeatSpread);
986 scene.setBackgroundBrush(gradient3);
988 QApplication::processEvents();
991 view.setSceneRect(-1000, -1000, 2000, 2000);
992 for (int i = -500; i < 500; i += 10) {
994 QApplication::processEvents();
995 QApplication::processEvents();
997 for (int i = -500; i < 500; i += 10) {
999 QApplication::processEvents();
1000 QApplication::processEvents();
1004 void tst_QGraphicsView::matrix()
1007 QGraphicsScene scene;
1008 QGraphicsView view(&scene);
1011 // Show rendering of background with no scene
1012 for (int i = 0; i < 50; ++i) {
1014 QRadialGradient gradient(view.rect().center() + QPoint(int(sin(i / 2.0) * 10), int(cos(i / 2.0) * 10)), 10);
1015 gradient.setColorAt(0, Qt::transparent);
1016 gradient.setColorAt(0.5, Qt::black);
1017 gradient.setColorAt(1, Qt::transparent);
1018 gradient.setSpread(QGradient::RepeatSpread);
1019 scene.setForegroundBrush(gradient);
1020 QRadialGradient gradient2(view.rect().center() + QPoint(int(sin(i / 1.7) * 10), int(cos(i / 1.7) * 10)), 10);
1021 gradient2.setColorAt(0, Qt::transparent);
1022 gradient2.setColorAt(0.5, Qt::black);
1023 gradient2.setColorAt(1, Qt::transparent);
1024 gradient2.setSpread(QGradient::RepeatSpread);
1025 scene.setBackgroundBrush(gradient2);
1026 QApplication::processEvents();
1027 QApplication::processEvents();
1031 // Test transformation extremes, see if they cause crashes
1033 QGraphicsScene scene;
1034 scene.addText("GraphicsView rotated clockwise");
1036 QGraphicsView view(&scene);
1038 for (int i = 0; i < 160; ++i) {
1040 QApplication::processEvents();
1041 QApplication::processEvents();
1044 // These cause a crash
1045 for (int i = 0; i < 40; ++i) {
1046 view.shear(1.2, 1.2);
1049 for (int i = 0; i < 40; ++i) {
1050 view.shear(-1.2, -1.2);
1054 for (int i = 0; i < 20; ++i) {
1055 view.scale(1.2, 1.2);
1056 QApplication::processEvents();
1057 QApplication::processEvents();
1059 for (int i = 0; i < 20; ++i) {
1060 view.scale(0.6, 0.6);
1061 QApplication::processEvents();
1062 QApplication::processEvents();
1067 void tst_QGraphicsView::matrix_convenience()
1070 QCOMPARE(view.matrix(), QMatrix());
1072 // Check the convenience functions
1074 QCOMPARE(view.matrix(), QMatrix().rotate(90));
1076 QCOMPARE(view.matrix(), QMatrix().scale(2, 2) * QMatrix().rotate(90));
1077 view.shear(1.2, 1.2);
1078 QCOMPARE(view.matrix(), QMatrix().shear(1.2, 1.2) * QMatrix().scale(2, 2) * QMatrix().rotate(90));
1079 view.translate(1, 1);
1080 QCOMPARE(view.matrix(), QMatrix().translate(1, 1) * QMatrix().shear(1.2, 1.2) * QMatrix().scale(2, 2) * QMatrix().rotate(90));
1083 void tst_QGraphicsView::matrix_combine()
1085 // Check matrix combining
1087 QCOMPARE(view.matrix(), QMatrix());
1088 view.setMatrix(QMatrix().rotate(90), true);
1089 view.setMatrix(QMatrix().rotate(90), true);
1090 view.setMatrix(QMatrix().rotate(90), true);
1091 view.setMatrix(QMatrix().rotate(90), true);
1092 QCOMPARE(view.matrix(), QMatrix());
1095 QCOMPARE(view.matrix(), QMatrix());
1096 view.setMatrix(QMatrix().rotate(90), false);
1097 view.setMatrix(QMatrix().rotate(90), false);
1098 view.setMatrix(QMatrix().rotate(90), false);
1099 view.setMatrix(QMatrix().rotate(90), false);
1100 QCOMPARE(view.matrix(), QMatrix().rotate(90));
1103 void tst_QGraphicsView::centerOnPoint()
1107 QGraphicsScene scene;
1108 scene.addEllipse(QRectF(-100, -100, 50, 50));
1109 scene.addEllipse(QRectF(50, -100, 50, 50));
1110 scene.addEllipse(QRectF(-100, 50, 50, 50));
1111 scene.addEllipse(QRectF(50, 50, 50, 50));
1113 QGraphicsView view(&scene, &toplevel);
1114 view.setSceneRect(-400, -400, 800, 800);
1115 view.setFixedSize(100, 100);
1120 for (int i = 0; i < 3; ++i) {
1121 for (int y = -100; y < 100; y += 23) {
1122 for (int x = -100; x < 100; x += 23) {
1123 view.centerOn(x, y);
1124 QPoint viewCenter = view.mapToScene(view.viewport()->rect().center()).toPoint();
1127 if (viewCenter.x() < x - tolerance || viewCenter.x() > x + tolerance
1128 || viewCenter.y() < y - tolerance || viewCenter.y() > y + tolerance) {
1129 QString error = QString("Compared values are not the same\n\tActual: (%1, %2)\n\tExpected: (%3, %4)")
1130 .arg(viewCenter.x()).arg(viewCenter.y()).arg(x).arg(y);
1131 QFAIL(qPrintable(error));
1134 QApplication::processEvents();
1139 view.scale(1.5, 1.5);
1140 view.shear(1.25, 1.25);
1144 void tst_QGraphicsView::centerOnItem()
1146 QGraphicsScene scene;
1147 QGraphicsItem *items[4];
1148 items[0] = scene.addEllipse(QRectF(-25, -25, 50, 50));
1149 items[1] = scene.addEllipse(QRectF(-25, -25, 50, 50));
1150 items[2] = scene.addEllipse(QRectF(-25, -25, 50, 50));
1151 items[3] = scene.addEllipse(QRectF(-25, -25, 50, 50));
1152 items[0]->setPos(-100, -100);
1153 items[1]->setPos(100, -100);
1154 items[2]->setPos(-100, 100);
1155 items[3]->setPos(100, 100);
1157 QGraphicsView view(&scene);
1158 view.setSceneRect(-1000, -1000, 2000, 2000);
1160 QVERIFY(QTest::qWaitForWindowExposed(&view));
1163 for (int x = 0; x < 3; ++x) {
1164 for (int i = 0; i < 4; ++i) {
1165 QApplication::processEvents();
1166 view.centerOn(items[i]);
1168 QPoint viewCenter = view.mapToScene(view.viewport()->rect().center()).toPoint();
1169 qreal x = items[i]->pos().x();
1170 qreal y = items[i]->pos().y();
1173 if (viewCenter.x() < x - tolerance || viewCenter.x() > x + tolerance
1174 || viewCenter.y() < y - tolerance || viewCenter.y() > y + tolerance) {
1175 QString error = QString("Compared values are not the same\n\tActual: (%1, %2)\n\tExpected: (%3, %4)")
1176 .arg(viewCenter.x()).arg(viewCenter.y()).arg(x).arg(y);
1177 QFAIL(qPrintable(error));
1180 QApplication::processEvents();
1184 view.scale(1.5, 1.5);
1185 view.shear(1.25, 1.25);
1189 void tst_QGraphicsView::ensureVisibleRect()
1193 QGraphicsScene scene;
1194 QGraphicsItem *items[4];
1195 items[0] = scene.addEllipse(QRectF(-25, -25, 50, 50), QPen(Qt::black), QBrush(Qt::green));
1196 items[1] = scene.addEllipse(QRectF(-25, -25, 50, 50), QPen(Qt::black), QBrush(Qt::red));
1197 items[2] = scene.addEllipse(QRectF(-25, -25, 50, 50), QPen(Qt::black), QBrush(Qt::blue));
1198 items[3] = scene.addEllipse(QRectF(-25, -25, 50, 50), QPen(Qt::black), QBrush(Qt::yellow));
1199 scene.addLine(QLineF(0, -100, 0, 100), QPen(Qt::blue, 2));
1200 scene.addLine(QLineF(-100, 0, 100, 0), QPen(Qt::blue, 2));
1201 items[0]->setPos(-100, -100);
1202 items[1]->setPos(100, -100);
1203 items[2]->setPos(-100, 100);
1204 items[3]->setPos(100, 100);
1206 QGraphicsItem *icon = scene.addEllipse(QRectF(-10, -10, 20, 20), QPen(Qt::black), QBrush(Qt::gray));
1208 QGraphicsView view(&scene, &toplevel);
1209 view.setSceneRect(-500, -500, 1000, 1000);
1210 view.setFixedSize(250, 250);
1212 QVERIFY(QTest::qWaitForWindowExposed(&toplevel));
1214 for (int y = -100; y < 100; y += 25) {
1215 for (int x = -100; x < 100; x += 13) {
1221 view.centerOn(-500, -500);
1224 view.centerOn(500, -500);
1227 view.centerOn(-500, 500);
1231 view.centerOn(500, 500);
1235 QVERIFY(!view.viewport()->rect().contains(view.mapFromScene(x, y)));
1237 for (int margin = 10; margin < 60; margin += 15) {
1238 view.ensureVisible(x, y, 0, 0, margin, margin);
1240 QRect viewRect = view.viewport()->rect();
1241 QPoint viewPoint = view.mapFromScene(x, y);
1243 QVERIFY(viewRect.contains(viewPoint));
1244 QVERIFY(qAbs(viewPoint.x() - viewRect.left()) >= margin -1);
1245 QVERIFY(qAbs(viewPoint.x() - viewRect.right()) >= margin -1);
1246 QVERIFY(qAbs(viewPoint.y() - viewRect.top()) >= margin -1);
1247 QVERIFY(qAbs(viewPoint.y() - viewRect.bottom()) >= margin -1);
1249 QApplication::processEvents();
1253 view.scale(1.05, 1.05);
1254 view.translate(30, -30);
1258 void tst_QGraphicsView::fitInView()
1260 QGraphicsScene scene;
1261 QGraphicsItem *items[4];
1262 items[0] = scene.addEllipse(QRectF(-25, -25, 100, 20), QPen(Qt::black), QBrush(Qt::green));
1263 items[1] = scene.addEllipse(QRectF(-25, -25, 20, 100), QPen(Qt::black), QBrush(Qt::red));
1264 items[2] = scene.addEllipse(QRectF(-25, -25, 50, 50), QPen(Qt::black), QBrush(Qt::blue));
1265 items[3] = scene.addEllipse(QRectF(-25, -25, 50, 50), QPen(Qt::black), QBrush(Qt::yellow));
1266 scene.addLine(QLineF(0, -100, 0, 100), QPen(Qt::blue, 2));
1267 scene.addLine(QLineF(-100, 0, 100, 0), QPen(Qt::blue, 2));
1268 items[0]->setPos(-100, -100);
1269 items[1]->setPos(100, -100);
1270 items[2]->setPos(-100, 100);
1271 items[3]->setPos(100, 100);
1273 items[0]->rotate(30);
1274 items[1]->rotate(-30);
1276 #if defined(Q_OS_WINCE)
1277 //Is the standard scrollbar size
1278 int scrollbarSize = qApp->style()->pixelMetric(QStyle::PM_ScrollBarExtent) - 13;
1281 QGraphicsView view(&scene);
1282 view.setSceneRect(-400, -400, 800, 800);
1284 #if defined(Q_OS_WINCE)
1285 //We need to take in account the scrollbar size for the WindowsMobilStyle
1286 view.setFixedSize(400 + scrollbarSize, 200 + scrollbarSize);
1288 view.setFixedSize(400, 200);
1292 view.fitInView(scene.itemsBoundingRect(), Qt::IgnoreAspectRatio);
1293 qApp->processEvents();
1295 // Sampled coordinates.
1296 QVERIFY(!view.itemAt(45, 41));
1297 QVERIFY(!view.itemAt(297, 44));
1298 QVERIFY(!view.itemAt(359, 143));
1299 QCOMPARE(view.itemAt(79, 22), items[0]);
1300 QCOMPARE(view.itemAt(329, 41), items[1]);
1301 QCOMPARE(view.itemAt(38, 158), items[2]);
1302 QCOMPARE(view.itemAt(332, 160), items[3]);
1304 view.fitInView(items[0], Qt::IgnoreAspectRatio);
1305 qApp->processEvents();
1307 QCOMPARE(view.itemAt(19, 13), items[0]);
1308 QCOMPARE(view.itemAt(91, 47), items[0]);
1309 QCOMPARE(view.itemAt(202, 94), items[0]);
1310 QCOMPARE(view.itemAt(344, 161), items[0]);
1311 QVERIFY(!view.itemAt(236, 54));
1312 QVERIFY(!view.itemAt(144, 11));
1313 QVERIFY(!view.itemAt(29, 69));
1314 QVERIFY(!view.itemAt(251, 167));
1316 view.fitInView(items[0], Qt::KeepAspectRatio);
1317 qApp->processEvents();
1319 QCOMPARE(view.itemAt(325, 170), items[0]);
1320 QCOMPARE(view.itemAt(206, 74), items[0]);
1321 QCOMPARE(view.itemAt(190, 115), items[0]);
1322 QCOMPARE(view.itemAt(55, 14), items[0]);
1323 QVERIFY(!view.itemAt(109, 4));
1324 QVERIFY(!view.itemAt(244, 68));
1325 QVERIFY(!view.itemAt(310, 125));
1326 QVERIFY(!view.itemAt(261, 168));
1328 view.fitInView(items[0], Qt::KeepAspectRatioByExpanding);
1329 qApp->processEvents();
1331 QCOMPARE(view.itemAt(18, 10), items[0]);
1332 QCOMPARE(view.itemAt(95, 4), items[0]);
1333 QCOMPARE(view.itemAt(279, 175), items[0]);
1334 QCOMPARE(view.itemAt(359, 170), items[0]);
1335 QVERIFY(!view.itemAt(370, 166));
1336 QVERIFY(!view.itemAt(136, 7));
1337 QVERIFY(!view.itemAt(31, 44));
1338 QVERIFY(!view.itemAt(203, 153));
1341 void tst_QGraphicsView::itemsAtPoint()
1343 QGraphicsScene scene;
1344 scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(1);
1345 scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(0);
1346 scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(2);
1347 scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(-1);
1348 scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(3);
1351 QVERIFY(view.items(0, 0).isEmpty());
1353 view.setScene(&scene);
1354 view.setSceneRect(-10000, -10000, 20000, 20000);
1357 QList<QGraphicsItem *> items = view.items(view.viewport()->rect().center());
1358 QCOMPARE(items.size(), 5);
1359 QCOMPARE(items.takeFirst()->zValue(), qreal(3));
1360 QCOMPARE(items.takeFirst()->zValue(), qreal(2));
1361 QCOMPARE(items.takeFirst()->zValue(), qreal(1));
1362 QCOMPARE(items.takeFirst()->zValue(), qreal(0));
1363 QCOMPARE(items.takeFirst()->zValue(), qreal(-1));
1366 #if defined QT_BUILD_INTERNAL
1367 void tst_QGraphicsView::itemsAtPosition_data()
1369 QTest::addColumn<float>("rotation");
1370 QTest::addColumn<float>("scale");
1371 QTest::addColumn<QPoint>("viewPos");
1372 QTest::addColumn<bool>("ignoreTransform");
1373 QTest::addColumn<bool>("hit");
1374 QTest::newRow("scaled + ignore transform, no hit") << 0.0f << 1000.0f << QPoint(0, 0) << true << false;
1375 QTest::newRow("scaled + ignore transform, hit") << 0.0f << 1000.0f << QPoint(100, 100) << true << true;
1376 QTest::newRow("rotated + scaled, no hit") << 45.0f << 2.0f << QPoint(90, 90) << false << false;
1377 QTest::newRow("rotated + scaled, hit") << 45.0f << 2.0f << QPoint(100, 100) << false << true;
1380 void tst_QGraphicsView::itemsAtPosition()
1382 QFETCH(float, rotation);
1383 QFETCH(float, scale);
1384 QFETCH(QPoint, viewPos);
1385 QFETCH(bool, ignoreTransform);
1388 FriendlyGraphicsScene scene;
1389 scene.setSceneRect(QRect(-100, -100, 200, 200));
1390 QGraphicsItem *item = scene.addRect(-5, -5, 10, 10);
1392 if (ignoreTransform)
1393 item->setFlag(QGraphicsItem::ItemIgnoresTransformations);
1396 view.setFrameStyle(QFrame::NoFrame);
1397 view.resize(200, 200);
1398 view.scale(scale, scale);
1399 view.rotate(rotation);
1400 view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1401 view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1402 view.setScene(&scene);
1404 QVERIFY(QTest::qWaitForWindowExposed(&view));
1406 QPoint screenPos = view.viewport()->mapToGlobal(viewPos);
1407 QPointF scenePos = view.mapToScene(viewPos);
1408 QGraphicsScenePrivate *viewPrivate = scene.d_func();
1409 QList<QGraphicsItem *> items;
1410 items = viewPrivate->itemsAtPosition(screenPos, scenePos, view.viewport());
1411 QCOMPARE(!items.empty(), hit);
1415 void tst_QGraphicsView::itemsInRect()
1417 QGraphicsScene scene;
1418 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(1);
1419 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(0);
1420 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(2);
1421 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(-1);
1422 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(3);
1424 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(5);
1425 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(4);
1426 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(6);
1427 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(3);
1428 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(7);
1431 QVERIFY(view.items(QRect(-100, -100, 200, 200)).isEmpty());
1432 view.setScene(&scene);
1433 view.setSceneRect(-10000, -10000, 20000, 20000);
1436 QRect leftRect = view.mapFromScene(-30, -10, 20, 20).boundingRect();
1437 QRect rightRect = view.mapFromScene(30, -10, 20, 20).boundingRect();
1439 QList<QGraphicsItem *> items = view.items(leftRect);
1440 QCOMPARE(items.size(), 5);
1441 QCOMPARE(items.takeFirst()->zValue(), qreal(3));
1442 QCOMPARE(items.takeFirst()->zValue(), qreal(2));
1443 QCOMPARE(items.takeFirst()->zValue(), qreal(1));
1444 QCOMPARE(items.takeFirst()->zValue(), qreal(0));
1445 QCOMPARE(items.takeFirst()->zValue(), qreal(-1));
1447 items = view.items(rightRect);
1448 QCOMPARE(items.size(), 5);
1449 QCOMPARE(items.takeFirst()->zValue(), qreal(7));
1450 QCOMPARE(items.takeFirst()->zValue(), qreal(6));
1451 QCOMPARE(items.takeFirst()->zValue(), qreal(5));
1452 QCOMPARE(items.takeFirst()->zValue(), qreal(4));
1453 QCOMPARE(items.takeFirst()->zValue(), qreal(3));
1456 class CountPaintItem : public QGraphicsRectItem
1461 CountPaintItem(const QRectF &rect)
1462 : QGraphicsRectItem(rect), numPaints(0)
1465 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
1468 QGraphicsRectItem::paint(painter, option, widget);
1472 void tst_QGraphicsView::itemsInRect_cosmeticAdjust_data()
1474 QTest::addColumn<QRect>("updateRect");
1475 QTest::addColumn<int>("numPaints");
1476 QTest::addColumn<bool>("adjustForAntialiasing");
1479 QTest::newRow("nil") << QRect() << 1 << false;
1480 QTest::newRow("0, 0, 300, 100") << QRect(0, 0, 300, 100) << 1 << false;
1481 QTest::newRow("0, 0, 100, 300") << QRect(0, 0, 100, 300) << 1 << false;
1482 QTest::newRow("200, 0, 100, 300") << QRect(200, 0, 100, 300) << 1 << false;
1483 QTest::newRow("0, 200, 300, 100") << QRect(0, 200, 300, 100) << 1 << false;
1484 QTest::newRow("0, 0, 300, 99") << QRect(0, 0, 300, 99) << 0 << false;
1485 QTest::newRow("0, 0, 99, 300") << QRect(0, 0, 99, 300) << 0 << false;
1486 QTest::newRow("201, 0, 99, 300") << QRect(201, 0, 99, 300) << 0 << false;
1487 QTest::newRow("0, 201, 300, 99") << QRect(0, 201, 300, 99) << 0 << false;
1490 QTest::newRow("nil") << QRect() << 1 << true;
1491 QTest::newRow("0, 0, 300, 100") << QRect(0, 0, 300, 100) << 1 << true;
1492 QTest::newRow("0, 0, 100, 300") << QRect(0, 0, 100, 300) << 1 << true;
1493 QTest::newRow("200, 0, 100, 300") << QRect(200, 0, 100, 300) << 1 << true;
1494 QTest::newRow("0, 200, 300, 100") << QRect(0, 200, 300, 100) << 1 << true;
1495 QTest::newRow("0, 0, 300, 99") << QRect(0, 0, 300, 99) << 1 << true;
1496 QTest::newRow("0, 0, 99, 300") << QRect(0, 0, 99, 300) << 1 << true;
1497 QTest::newRow("201, 0, 99, 300") << QRect(201, 0, 99, 300) << 1 << true;
1498 QTest::newRow("0, 201, 300, 99") << QRect(0, 201, 300, 99) << 1 << true;
1499 QTest::newRow("0, 0, 300, 98") << QRect(0, 0, 300, 98) << 0 << false;
1500 QTest::newRow("0, 0, 98, 300") << QRect(0, 0, 98, 300) << 0 << false;
1501 QTest::newRow("202, 0, 98, 300") << QRect(202, 0, 98, 300) << 0 << false;
1502 QTest::newRow("0, 202, 300, 98") << QRect(0, 202, 300, 98) << 0 << false;
1505 void tst_QGraphicsView::itemsInRect_cosmeticAdjust()
1507 QFETCH(QRect, updateRect);
1508 QFETCH(int, numPaints);
1509 QFETCH(bool, adjustForAntialiasing);
1511 QGraphicsScene scene(-100, -100, 200, 200);
1512 CountPaintItem *rect = new CountPaintItem(QRectF(-50, -50, 100, 100));
1513 scene.addItem(rect);
1515 QGraphicsView view(&scene);
1516 view.setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing, !adjustForAntialiasing);
1517 view.setRenderHint(QPainter::Antialiasing, adjustForAntialiasing);
1518 view.setFrameStyle(0);
1519 view.resize(300, 300);
1521 QVERIFY(QTest::qWaitForWindowActive(&view));
1522 QTRY_VERIFY(rect->numPaints > 0);
1524 rect->numPaints = 0;
1525 if (updateRect.isNull())
1526 view.viewport()->update();
1528 view.viewport()->update(updateRect);
1529 qApp->processEvents();
1530 QTRY_COMPARE(rect->numPaints, numPaints);
1533 void tst_QGraphicsView::itemsInPoly()
1535 QGraphicsScene scene;
1536 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(1);
1537 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(0);
1538 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(2);
1539 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(-1);
1540 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(3);
1542 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(5);
1543 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(4);
1544 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(6);
1545 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(3);
1546 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(7);
1549 QVERIFY(view.items(QPolygon()).isEmpty());
1550 view.setScene(&scene);
1551 view.setSceneRect(-10000, -10000, 20000, 20000);
1554 QPolygon leftPoly = view.mapFromScene(QRectF(-30, -10, 20, 20));
1555 QPolygon rightPoly = view.mapFromScene(QRectF(30, -10, 20, 20));
1557 QList<QGraphicsItem *> items = view.items(leftPoly);
1558 QCOMPARE(items.size(), 5);
1559 QCOMPARE(items.takeFirst()->zValue(), qreal(3));
1560 QCOMPARE(items.takeFirst()->zValue(), qreal(2));
1561 QCOMPARE(items.takeFirst()->zValue(), qreal(1));
1562 QCOMPARE(items.takeFirst()->zValue(), qreal(0));
1563 QCOMPARE(items.takeFirst()->zValue(), qreal(-1));
1565 items = view.items(rightPoly);
1566 QCOMPARE(items.size(), 5);
1567 QCOMPARE(items.takeFirst()->zValue(), qreal(7));
1568 QCOMPARE(items.takeFirst()->zValue(), qreal(6));
1569 QCOMPARE(items.takeFirst()->zValue(), qreal(5));
1570 QCOMPARE(items.takeFirst()->zValue(), qreal(4));
1571 QCOMPARE(items.takeFirst()->zValue(), qreal(3));
1574 void tst_QGraphicsView::itemsInPath()
1576 QGraphicsScene scene;
1577 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(1);
1578 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(0);
1579 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(2);
1580 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(-1);
1581 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(3);
1583 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(5);
1584 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(4);
1585 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(6);
1586 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(3);
1587 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(7);
1590 QVERIFY(view.items(QPainterPath()).isEmpty());
1591 view.setScene(&scene);
1592 view.translate(100, 400);
1594 view.setSceneRect(-10000, -10000, 20000, 20000);
1597 QPainterPath leftPath;
1598 leftPath.addEllipse(QRect(view.mapFromScene(-30, -10), QSize(20, 20)));
1600 QPainterPath rightPath;
1601 rightPath.addEllipse(QRect(view.mapFromScene(30, -10), QSize(20, 20)));
1603 QList<QGraphicsItem *> items = view.items(leftPath);
1605 QCOMPARE(items.size(), 5);
1606 QCOMPARE(items.takeFirst()->zValue(), qreal(3));
1607 QCOMPARE(items.takeFirst()->zValue(), qreal(2));
1608 QCOMPARE(items.takeFirst()->zValue(), qreal(1));
1609 QCOMPARE(items.takeFirst()->zValue(), qreal(0));
1610 QCOMPARE(items.takeFirst()->zValue(), qreal(-1));
1612 items = view.items(rightPath);
1613 QCOMPARE(items.size(), 5);
1614 QCOMPARE(items.takeFirst()->zValue(), qreal(7));
1615 QCOMPARE(items.takeFirst()->zValue(), qreal(6));
1616 QCOMPARE(items.takeFirst()->zValue(), qreal(5));
1617 QCOMPARE(items.takeFirst()->zValue(), qreal(4));
1618 QCOMPARE(items.takeFirst()->zValue(), qreal(3));
1621 void tst_QGraphicsView::itemAt()
1623 QGraphicsScene scene;
1624 scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(1);
1625 scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(0);
1626 scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(2);
1627 scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(-1);
1628 scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(3);
1631 QCOMPARE(view.itemAt(0, 0), (QGraphicsItem *)0);
1633 view.setScene(&scene);
1634 view.setSceneRect(-10000, -10000, 20000, 20000);
1637 QCOMPARE(view.itemAt(0, 0), (QGraphicsItem *)0);
1638 QGraphicsItem* item = view.itemAt(view.viewport()->rect().center());
1640 QCOMPARE(item->zValue(), qreal(3));
1643 void tst_QGraphicsView::itemAt2()
1645 // test precision of the itemAt() function with items that are smaller
1647 QGraphicsScene scene(0, 0, 100, 100);
1649 // Add a 0.5x0.5 item at position 0 on the scene, top-left corner at -0.25, -0.25.
1650 QGraphicsItem *item = scene.addRect(QRectF(-0.25, -0.25, 0.5, 0.5), QPen(Qt::black, 0.1));
1652 QGraphicsView view(&scene);
1653 view.setFixedSize(200, 200);
1654 view.setTransformationAnchor(QGraphicsView::NoAnchor);
1655 view.setRenderHint(QPainter::Antialiasing);
1657 QVERIFY(QTest::qWaitForWindowExposed(&view));
1658 QApplication::processEvents();
1660 QPoint itemViewPoint = view.mapFromScene(item->scenePos());
1662 for (int i = 0; i < 3; ++i) {
1663 QVERIFY(view.itemAt(itemViewPoint));
1664 QVERIFY(!view.items(itemViewPoint).isEmpty());
1665 QVERIFY(view.itemAt(itemViewPoint + QPoint(-1, 0)));
1666 QVERIFY(!view.items(itemViewPoint + QPoint(-1, 0)).isEmpty());
1667 QVERIFY(view.itemAt(itemViewPoint + QPoint(-1, -1)));
1668 QVERIFY(!view.items(itemViewPoint + QPoint(-1, -1)).isEmpty());
1669 QVERIFY(view.itemAt(itemViewPoint + QPoint(0, -1)));
1670 QVERIFY(!view.items(itemViewPoint + QPoint(0, -1)).isEmpty());
1671 item->moveBy(0.1, 0);
1675 QVERIFY(view.itemAt(itemViewPoint));
1676 QVERIFY(!view.items(itemViewPoint).isEmpty());
1677 QVERIFY(view.itemAt(itemViewPoint + QPoint(0, -1)));
1678 QVERIFY(!view.items(itemViewPoint + QPoint(0, -1)).isEmpty());
1680 if (sizeof(qreal) != sizeof(double))
1681 QSKIP("Skipped due to rounding errors");
1684 QVERIFY(!view.itemAt(itemViewPoint + QPoint(-1, 0)));
1685 QVERIFY(view.items(itemViewPoint + QPoint(-1, 0)).isEmpty());
1686 QVERIFY(!view.itemAt(itemViewPoint + QPoint(-1, -1)));
1687 QVERIFY(view.items(itemViewPoint + QPoint(-1, -1)).isEmpty());
1690 void tst_QGraphicsView::mapToScene()
1692 // Uncomment the commented-out code to see what's going on. It doesn't
1693 // affect the test; it just slows it down.
1695 QGraphicsScene scene;
1696 scene.addPixmap(QPixmap("3D-Qt-1-2.png"));
1699 QGraphicsView view(&topLevel);
1700 view.setScene(&scene);
1701 view.setSceneRect(-500, -500, 1000, 1000);
1702 #if defined(Q_OS_WINCE)
1703 QSize viewSize(200,200);
1705 QSize viewSize(300,300);
1708 view.setFixedSize(viewSize);
1710 QApplication::processEvents();
1711 QVERIFY(view.isVisible());
1712 QCOMPARE(view.size(), viewSize);
1714 // First once without setting the scene rect
1715 #ifdef Q_PROCESSOR_ARM
1716 const int step = 20;
1721 for (int x = 0; x < view.width(); x += step) {
1722 for (int y = 0; y < view.height(); y += step) {
1723 QCOMPARE(view.mapToScene(QPoint(x, y)),
1724 QPointF(view.horizontalScrollBar()->value() + x,
1725 view.verticalScrollBar()->value() + y));
1729 for (int sceneRectHeight = 250; sceneRectHeight < 1000; sceneRectHeight += 250) {
1730 for (int sceneRectWidth = 250; sceneRectWidth < 1000; sceneRectWidth += 250) {
1731 view.setSceneRect(QRectF(-int(sceneRectWidth / 2), -int(sceneRectHeight / 2),
1732 sceneRectWidth, sceneRectHeight));
1733 QApplication::processEvents();
1735 int hmin = view.horizontalScrollBar()->minimum();
1736 int hmax = view.horizontalScrollBar()->maximum();
1737 int hstep = (hmax - hmin) / 3;
1738 int vmin = view.verticalScrollBar()->minimum();
1739 int vmax = view.verticalScrollBar()->maximum();
1740 int vstep = (vmax - vmin) / 3;
1742 for (int hscrollValue = hmin; hscrollValue < hmax; hscrollValue += hstep) {
1743 for (int vscrollValue = vmin; vscrollValue < vmax; vscrollValue += vstep) {
1745 view.horizontalScrollBar()->setValue(hscrollValue);
1746 view.verticalScrollBar()->setValue(vscrollValue);
1747 QApplication::processEvents();
1749 int h = view.horizontalScrollBar()->value();
1750 int v = view.verticalScrollBar()->value();
1752 for (int x = 0; x < view.width(); x += step) {
1753 for (int y = 0; y < view.height(); y += step) {
1754 QCOMPARE(view.mapToScene(QPoint(x, y)), QPointF(h + x, v + y));
1755 QCOMPARE(view.mapFromScene(QPointF(h + x, v + y)), QPoint(x, y));
1764 void tst_QGraphicsView::mapToScenePoint()
1766 QGraphicsScene scene;
1767 QGraphicsView view(&scene);
1769 view.setFixedSize(117, 117);
1771 QPoint center = view.viewport()->rect().center();
1772 QCOMPARE(view.mapToScene(center + QPoint(10, 0)),
1773 view.mapToScene(center) + QPointF(0, -10));
1776 void tst_QGraphicsView::mapToSceneRect_data()
1778 QTest::addColumn<QRect>("viewRect");
1779 QTest::addColumn<QPolygonF>("scenePoly");
1780 QTest::addColumn<qreal>("rotation");
1782 QTest::newRow("nil") << QRect() << QPolygonF() << qreal(0);
1783 QTest::newRow("0, 0, 1, 1") << QRect(0, 0, 1, 1) << QPolygonF(QRectF(0, 0, 1, 1)) << qreal(0);
1784 QTest::newRow("0, 0, 10, 10") << QRect(0, 0, 10, 10) << QPolygonF(QRectF(0, 0, 10, 10)) << qreal(0);
1785 QTest::newRow("nil") << QRect() << QPolygonF() << qreal(90);
1787 p << QPointF(0, 0) << QPointF(0, -1) << QPointF(1, -1) << QPointF(1, 0) << QPointF(0, 0);
1788 QTest::newRow("0, 0, 1, 1") << QRect(0, 0, 1, 1)
1792 p << QPointF(0, 0) << QPointF(0, -10) << QPointF(10, -10) << QPointF(10, 0) << QPointF(0, 0);
1793 QTest::newRow("0, 0, 10, 10") << QRect(0, 0, 10, 10)
1798 void tst_QGraphicsView::mapToSceneRect()
1800 QFETCH(QRect, viewRect);
1801 QFETCH(QPolygonF, scenePoly);
1802 QFETCH(qreal, rotation);
1804 QGraphicsScene scene(-1000, -1000, 2000, 2000);
1805 scene.addRect(25, -25, 50, 50);
1806 QGraphicsView view(&scene);
1807 view.setFrameStyle(0);
1808 view.setAlignment(Qt::AlignTop | Qt::AlignLeft);
1809 view.setFixedSize(200, 200);
1810 view.setTransformationAnchor(QGraphicsView::NoAnchor);
1811 view.setResizeAnchor(QGraphicsView::NoAnchor);
1814 view.rotate(rotation);
1816 QPolygonF poly = view.mapToScene(viewRect);
1817 if (!poly.isEmpty())
1820 QCOMPARE(poly, scenePoly);
1823 void tst_QGraphicsView::mapToScenePoly()
1825 QGraphicsScene scene;
1826 QGraphicsView view(&scene);
1827 view.translate(100, 100);
1828 view.setFixedSize(117, 117);
1830 QPoint center = view.viewport()->rect().center();
1831 QRect rect(center + QPoint(10, 0), QSize(10, 10));
1834 poly << rect.topLeft();
1835 poly << rect.topRight();
1836 poly << rect.bottomRight();
1837 poly << rect.bottomLeft();
1840 poly2 << view.mapToScene(rect.topLeft());
1841 poly2 << view.mapToScene(rect.topRight());
1842 poly2 << view.mapToScene(rect.bottomRight());
1843 poly2 << view.mapToScene(rect.bottomLeft());
1845 QCOMPARE(view.mapToScene(poly), poly2);
1848 void tst_QGraphicsView::mapToScenePath()
1850 QGraphicsScene scene;
1851 QGraphicsView view(&scene);
1852 view.setSceneRect(-300, -300, 600, 600);
1853 view.translate(10, 10);
1854 view.setFixedSize(300, 300);
1856 QRect rect(QPoint(10, 0), QSize(10, 10));
1862 path2.addRect(rect.translated(view.horizontalScrollBar()->value() - 10,
1863 view.verticalScrollBar()->value() - 10));
1864 QCOMPARE(view.mapToScene(path), path2);
1867 void tst_QGraphicsView::mapFromScenePoint()
1870 QGraphicsScene scene;
1871 QGraphicsView view(&scene);
1874 view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1875 view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1878 QPoint mapped = view.mapFromScene(0, 0);
1879 QPoint center = view.viewport()->rect().center();
1880 if (qAbs(mapped.x() - center.x()) >= 2
1881 || qAbs(mapped.y() - center.y()) >= 2) {
1882 QString error = QString("Compared values are not the same\n\tActual: (%1, %2)\n\tExpected: (%3, %4)")
1883 .arg(mapped.x()).arg(mapped.y()).arg(center.x()).arg(center.y());
1884 QFAIL(qPrintable(error));
1890 QGraphicsScene scene(0, 0, 200, 200);
1891 scene.addRect(QRectF(0, 0, 200, 200), QPen(Qt::black, 1));
1892 QGraphicsView view(&scene, &toplevel);
1893 view.ensurePolished();
1894 view.resize(view.sizeHint());
1897 QCOMPARE(view.mapFromScene(0, 0), QPoint(0, 0));
1898 QCOMPARE(view.mapFromScene(0.4, 0.4), QPoint(0, 0));
1899 QCOMPARE(view.mapFromScene(0.5, 0.5), QPoint(1, 1));
1900 QCOMPARE(view.mapFromScene(0.9, 0.9), QPoint(1, 1));
1901 QCOMPARE(view.mapFromScene(1.0, 1.0), QPoint(1, 1));
1902 QCOMPARE(view.mapFromScene(100, 100), QPoint(100, 100));
1903 QCOMPARE(view.mapFromScene(100.5, 100.5), QPoint(101, 101));
1904 QCOMPARE(view.mapToScene(0, 0), QPointF(0, 0));
1905 QCOMPARE(view.mapToScene(1, 1), QPointF(1, 1));
1906 QCOMPARE(view.mapToScene(100, 100), QPointF(100, 100));
1910 void tst_QGraphicsView::mapFromSceneRect()
1912 QGraphicsScene scene;
1914 QGraphicsView view(&scene,&topLevel);
1916 view.setFixedSize(200, 200);
1917 view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1918 view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1923 polygon << QPoint(98, 98);
1924 polygon << QPoint(98, 108);
1925 polygon << QPoint(88, 108);
1926 polygon << QPoint(88, 98);
1929 QPolygon viewPolygon = view.mapFromScene(0, 0, 10, 10);
1930 for (int i = 0; i < 4; ++i) {
1931 QVERIFY(qAbs(viewPolygon[i].x() - polygon[i].x()) < 3);
1932 QVERIFY(qAbs(viewPolygon[i].y() - polygon[i].y()) < 3);
1935 QPoint pt = view.mapFromScene(QPointF());
1937 p << pt << pt << pt << pt;
1938 QCOMPARE(view.mapFromScene(QRectF()), p);
1941 void tst_QGraphicsView::mapFromScenePoly()
1943 QGraphicsScene scene;
1944 QGraphicsView view(&scene);
1946 view.setFixedSize(200, 200);
1947 view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1948 view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1952 polygon << QPoint(0, 0);
1953 polygon << QPoint(10, 0);
1954 polygon << QPoint(10, 10);
1955 polygon << QPoint(0, 10);
1958 polygon2 << QPoint(98, 98);
1959 polygon2 << QPoint(98, 108);
1960 polygon2 << QPoint(88, 108);
1961 polygon2 << QPoint(88, 98);
1963 QPolygon viewPolygon = view.mapFromScene(polygon);
1964 for (int i = 0; i < 4; ++i) {
1965 QVERIFY(qAbs(viewPolygon[i].x() - polygon2[i].x()) < 3);
1966 QVERIFY(qAbs(viewPolygon[i].y() - polygon2[i].y()) < 3);
1970 void tst_QGraphicsView::mapFromScenePath()
1972 QGraphicsScene scene;
1973 QGraphicsView view(&scene);
1975 view.setFixedSize(200, 200);
1976 view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1977 view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1981 polygon << QPoint(0, 0);
1982 polygon << QPoint(10, 0);
1983 polygon << QPoint(10, 10);
1984 polygon << QPoint(0, 10);
1986 path.addPolygon(polygon);
1989 polygon2 << QPoint(98, 98);
1990 polygon2 << QPoint(98, 108);
1991 polygon2 << QPoint(88, 108);
1992 polygon2 << QPoint(88, 98);
1994 path2.addPolygon(polygon2);
1996 QPolygonF pathPoly = view.mapFromScene(path).toFillPolygon();
1997 QPolygonF path2Poly = path2.toFillPolygon();
1999 for (int i = 0; i < pathPoly.size(); ++i) {
2000 QVERIFY(qAbs(pathPoly[i].x() - path2Poly[i].x()) < 3);
2001 QVERIFY(qAbs(pathPoly[i].y() - path2Poly[i].y()) < 3);
2005 void tst_QGraphicsView::sendEvent()
2007 QGraphicsScene scene;
2009 TestItem *item = new TestItem;
2010 scene.addItem(item);
2011 item->setFlag(QGraphicsItem::ItemIsFocusable);
2012 item->setFlag(QGraphicsItem::ItemIsMovable);
2014 QGraphicsView view(&scene);
2016 QApplication::setActiveWindow(&view);
2017 QVERIFY(QTest::qWaitForWindowActive(&view));
2018 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2022 QCOMPARE(scene.focusItem(), (QGraphicsItem *)item);
2023 QCOMPARE(item->events.size(), 2);
2024 QCOMPARE(item->events.last(), QEvent::FocusIn);
2026 QPoint itemPoint = view.mapFromScene(item->scenePos());
2027 sendMousePress(view.viewport(), itemPoint);
2028 QCOMPARE(item->events.size(), 4);
2029 QCOMPARE(item->events.at(item->events.size() - 2), QEvent::GrabMouse);
2030 QCOMPARE(item->events.at(item->events.size() - 1), QEvent::GraphicsSceneMousePress);
2032 QMouseEvent mouseMoveEvent(QEvent::MouseMove, itemPoint, view.viewport()->mapToGlobal(itemPoint),
2033 Qt::LeftButton, Qt::LeftButton, 0);
2034 QApplication::sendEvent(view.viewport(), &mouseMoveEvent);
2035 QCOMPARE(item->events.size(), 5);
2036 QCOMPARE(item->events.last(), QEvent::GraphicsSceneMouseMove);
2038 QMouseEvent mouseReleaseEvent(QEvent::MouseButtonRelease, itemPoint,
2039 view.viewport()->mapToGlobal(itemPoint),
2040 Qt::LeftButton, 0, 0);
2041 QApplication::sendEvent(view.viewport(), &mouseReleaseEvent);
2042 QCOMPARE(item->events.size(), 7);
2043 QCOMPARE(item->events.at(item->events.size() - 2), QEvent::GraphicsSceneMouseRelease);
2044 QCOMPARE(item->events.at(item->events.size() - 1), QEvent::UngrabMouse);
2046 QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Space, 0);
2047 QApplication::sendEvent(view.viewport(), &keyPress);
2048 QCOMPARE(item->events.size(), 9);
2049 QCOMPARE(item->events.at(item->events.size() - 2), QEvent::ShortcutOverride);
2050 QCOMPARE(item->events.last(), QEvent::KeyPress);
2053 class MouseWheelScene : public QGraphicsScene
2056 Qt::Orientation orientation;
2058 void wheelEvent(QGraphicsSceneWheelEvent *event)
2060 orientation = event->orientation();
2061 QGraphicsScene::wheelEvent(event);
2065 void tst_QGraphicsView::wheelEvent()
2067 // Create a scene with an invalid orientation.
2068 MouseWheelScene scene;
2069 scene.orientation = Qt::Orientation(-1);
2071 QGraphicsWidget *widget = new QGraphicsWidget;
2072 widget->setGeometry(0, 0, 400, 400);
2073 widget->setFocusPolicy(Qt::WheelFocus);
2075 EventSpy spy(widget, QEvent::GraphicsSceneWheel);
2076 QCOMPARE(spy.count(), 0);
2078 scene.addItem(widget);
2081 QGraphicsView view(&scene);
2083 QApplication::setActiveWindow(&view);
2084 QVERIFY(QTest::qWaitForWindowActive(&view));
2085 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2088 // Send a wheel event with horizontal orientation.
2090 QWheelEvent event(view.mapFromScene(widget->boundingRect().center()),
2091 view.mapToGlobal(view.mapFromScene(widget->boundingRect().center())),
2092 120, 0, 0, Qt::Horizontal);
2093 QApplication::sendEvent(view.viewport(), &event);
2094 QCOMPARE(scene.orientation, Qt::Horizontal);
2097 // Send a wheel event with vertical orientation.
2099 QWheelEvent event(view.mapFromScene(widget->boundingRect().center()),
2100 view.mapToGlobal(view.mapFromScene(widget->boundingRect().center())),
2101 120, 0, 0, Qt::Vertical);
2102 QApplication::sendEvent(view.viewport(), &event);
2103 QCOMPARE(scene.orientation, Qt::Vertical);
2106 QCOMPARE(spy.count(), 2);
2107 QVERIFY(widget->hasFocus());
2110 #ifndef QTEST_NO_CURSOR
2111 void tst_QGraphicsView::cursor()
2113 QGraphicsScene scene;
2114 QGraphicsItem *item = scene.addRect(QRectF(-10, -10, 20, 20));
2115 item->setCursor(Qt::IBeamCursor);
2117 QGraphicsView view(&scene);
2118 view.setFixedSize(400, 400);
2120 QVERIFY(QTest::qWaitForWindowExposed(&view));
2122 QCOMPARE(view.viewport()->cursor().shape(), QCursor().shape());
2123 view.viewport()->setCursor(Qt::PointingHandCursor);
2124 QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
2126 sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
2127 QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
2129 sendMouseMove(view.viewport(), QPoint(5, 5));
2130 QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
2134 #ifndef QTEST_NO_CURSOR
2135 void tst_QGraphicsView::cursor2()
2137 QGraphicsScene scene;
2138 QGraphicsItem *item = scene.addRect(QRectF(-10, -10, 20, 20));
2139 item->setCursor(Qt::IBeamCursor);
2142 QGraphicsItem *item2 = scene.addRect(QRectF(-20, -20, 40, 40));
2143 item2->setZValue(0);
2145 QGraphicsView view(&scene);
2146 view.viewport()->setCursor(Qt::PointingHandCursor);
2147 view.setFixedSize(400, 400);
2149 QVERIFY(QTest::qWaitForWindowExposed(&view));
2151 sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
2152 QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
2153 sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
2154 QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
2155 sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
2156 QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
2157 sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
2158 QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
2159 sendMouseMove(view.viewport(), view.mapFromScene(-15, 0));
2160 QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
2162 view.setDragMode(QGraphicsView::ScrollHandDrag);
2164 sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
2165 QCOMPARE(view.viewport()->cursor().shape(), Qt::OpenHandCursor);
2166 sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
2167 QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
2168 sendMouseMove(view.viewport(), view.mapFromScene(-15, -15));
2169 QCOMPARE(view.viewport()->cursor().shape(), Qt::OpenHandCursor);
2171 view.setDragMode(QGraphicsView::NoDrag);
2172 QCOMPARE(view.viewport()->cursor().shape(), Qt::ArrowCursor);
2173 view.viewport()->setCursor(Qt::PointingHandCursor);
2174 QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
2176 item2->setCursor(Qt::SizeAllCursor);
2178 sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
2179 QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
2180 sendMouseMove(view.viewport(), view.mapFromScene(-15, -15));
2181 QCOMPARE(view.viewport()->cursor().shape(), Qt::SizeAllCursor);
2182 sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
2183 QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
2184 sendMouseMove(view.viewport(), view.mapFromScene(-15, -15));
2185 QCOMPARE(view.viewport()->cursor().shape(), Qt::SizeAllCursor);
2186 sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
2187 QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
2188 sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
2189 QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
2191 view.setDragMode(QGraphicsView::ScrollHandDrag);
2193 sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
2194 QCOMPARE(view.viewport()->cursor().shape(), Qt::OpenHandCursor);
2195 sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
2196 QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
2197 sendMouseMove(view.viewport(), view.mapFromScene(-15, -15));
2198 QCOMPARE(view.viewport()->cursor().shape(), Qt::SizeAllCursor);
2202 void tst_QGraphicsView::transformationAnchor()
2204 QGraphicsScene scene(-1000, -1000, 2000, 2000);
2205 scene.addRect(QRectF(-50, -50, 100, 100), QPen(Qt::black), QBrush(Qt::blue));
2207 QGraphicsView view(&scene);
2209 for (int i = 0; i < 2; ++i) {
2210 view.resize(100, 100);
2214 QCOMPARE(view.transformationAnchor(), QGraphicsView::AnchorViewCenter);
2216 view.setTransformationAnchor(QGraphicsView::NoAnchor);
2218 view.centerOn(0, 0);
2219 view.horizontalScrollBar()->setValue(100);
2220 QApplication::processEvents();
2222 QPointF center = view.mapToScene(view.viewport()->rect().center());
2226 QPointF newCenter = view.mapToScene(view.viewport()->rect().center());
2230 QVERIFY(qAbs(newCenter.x() - center.x()) < slack);
2231 QVERIFY(qAbs(newCenter.y() - center.y()) < slack);
2233 qreal slack = qreal(0.3);
2234 QVERIFY(qAbs(newCenter.x() - center.x() / 10) < slack);
2235 QVERIFY(qAbs(newCenter.y() - center.y() / 10) < slack);
2240 void tst_QGraphicsView::resizeAnchor()
2242 QGraphicsScene scene(-1000, -1000, 2000, 2000);
2243 scene.addRect(QRectF(-50, -50, 100, 100), QPen(Qt::black), QBrush(Qt::blue));
2245 QGraphicsView view(&scene);
2247 for (int i = 0; i < 2; ++i) {
2248 view.resize(100, 100);
2250 QVERIFY(QTest::qWaitForWindowExposed(&view));
2251 QApplication::processEvents();
2254 QCOMPARE(view.resizeAnchor(), QGraphicsView::NoAnchor);
2256 view.setResizeAnchor(QGraphicsView::AnchorViewCenter);
2258 view.centerOn(0, 0);
2261 QPointF f = view.mapToScene(50, 50);
2262 QPointF center = view.mapToScene(view.viewport()->rect().center());
2264 QApplication::processEvents();
2266 for (int size = 200; size <= 400; size += 25) {
2267 view.resize(size, size);
2269 QTRY_COMPARE(view.mapToScene(50, 50), f);
2270 QTRY_VERIFY(view.mapToScene(view.viewport()->rect().center()) != center);
2272 QTRY_VERIFY(view.mapToScene(50, 50) != f);
2274 QPointF newCenter = view.mapToScene(view.viewport()->rect().center());
2276 QVERIFY(qAbs(newCenter.x() - center.x()) < slack);
2277 QVERIFY(qAbs(newCenter.y() - center.y()) < slack);
2279 QApplication::processEvents();
2284 class CustomView : public QGraphicsView
2288 CustomView(QGraphicsScene *s = 0) : QGraphicsView(s) {}
2289 CustomView(QGraphicsScene *s, QWidget *parent)
2290 : QGraphicsView(s, parent) {}
2291 QList<QRegion> lastUpdateRegions;
2295 void paintEvent(QPaintEvent *event)
2297 lastUpdateRegions << event->region();
2299 QGraphicsView::paintEvent(event);
2303 void tst_QGraphicsView::viewportUpdateMode()
2305 QGraphicsScene scene(0, 0, 100, 100);
2306 scene.setBackgroundBrush(Qt::red);
2309 QDesktopWidget desktop;
2310 view.setFixedSize(QSize(500, 500).boundedTo(desktop.availableGeometry().size())); // 500 is too big for all common smartphones
2311 view.setScene(&scene);
2312 QCOMPARE(view.viewportUpdateMode(), QGraphicsView::MinimalViewportUpdate);
2314 // Show the view, and initialize our test.
2316 qApp->setActiveWindow(&view);
2317 QVERIFY(QTest::qWaitForWindowActive(&view));
2318 QTRY_VERIFY(!view.lastUpdateRegions.isEmpty());
2319 view.lastUpdateRegions.clear();
2321 // Issue two scene updates.
2322 scene.update(QRectF(0, 0, 10, 10));
2323 scene.update(QRectF(20, 0, 10, 10));
2326 // The view gets two updates for the update scene updates.
2327 QTRY_VERIFY(!view.lastUpdateRegions.isEmpty());
2328 #ifndef Q_OS_MAC //cocoa doesn't support drawing regions
2329 QCOMPARE(view.lastUpdateRegions.last().rects().size(), 2);
2330 QCOMPARE(view.lastUpdateRegions.last().rects().at(0).size(), QSize(14, 14));
2331 QCOMPARE(view.lastUpdateRegions.last().rects().at(1).size(), QSize(14, 14));
2334 // Set full update mode.
2335 view.setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
2336 QCOMPARE(view.viewportUpdateMode(), QGraphicsView::FullViewportUpdate);
2337 view.lastUpdateRegions.clear();
2339 // Issue two scene updates.
2340 scene.update(QRectF(0, 0, 10, 10));
2341 scene.update(QRectF(20, 0, 10, 10));
2342 qApp->processEvents();
2343 qApp->processEvents();
2345 // The view gets one full viewport update for the update scene updates.
2346 QCOMPARE(view.lastUpdateRegions.last().rects().size(), 1);
2347 QCOMPARE(view.lastUpdateRegions.last().rects().at(0).size(), view.viewport()->size());
2348 view.lastUpdateRegions.clear();
2350 // Set smart update mode
2351 view.setViewportUpdateMode(QGraphicsView::SmartViewportUpdate);
2352 QCOMPARE(view.viewportUpdateMode(), QGraphicsView::SmartViewportUpdate);
2354 // Issue 100 mini-updates
2355 for (int i = 0; i < 10; ++i) {
2356 for (int j = 0; j < 10; ++j) {
2357 scene.update(QRectF(i * 3, j * 3, 1, 1));
2360 qApp->processEvents();
2361 qApp->processEvents();
2363 // The view gets one bounding rect update.
2364 QCOMPARE(view.lastUpdateRegions.last().rects().size(), 1);
2365 QCOMPARE(view.lastUpdateRegions.last().rects().at(0).size(), QSize(32, 32));
2367 // Set no update mode
2368 view.setViewportUpdateMode(QGraphicsView::NoViewportUpdate);
2369 QCOMPARE(view.viewportUpdateMode(), QGraphicsView::NoViewportUpdate);
2371 // Issue two scene updates.
2372 view.lastUpdateRegions.clear();
2374 scene.addItem(&item);
2375 item.moveBy(10, 10);
2376 scene.update(QRectF(0, 0, 10, 10));
2377 scene.update(QRectF(20, 0, 10, 10));
2378 qApp->processEvents();
2379 qApp->processEvents();
2381 // The view should not get any painting calls from the scene updates
2382 QCOMPARE(view.lastUpdateRegions.size(), 0);
2385 void tst_QGraphicsView::viewportUpdateMode2()
2389 // Create a view with viewport rect equal to QRect(0, 0, 200, 200).
2390 QGraphicsScene dummyScene;
2391 CustomView view(0, &toplevel);
2392 view.painted = false;
2393 view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
2394 view.setScene(&dummyScene);
2395 view.ensurePolished(); // make sure we get the right content margins
2396 int left, top, right, bottom;
2397 view.getContentsMargins(&left, &top, &right, &bottom);
2398 view.resize(200 + left + right, 200 + top + bottom);
2400 qApp->setActiveWindow(&toplevel);
2401 QVERIFY(QTest::qWaitForWindowActive(&toplevel));
2402 QTRY_VERIFY(view.painted);
2403 const QRect viewportRect = view.viewport()->rect();
2404 QCOMPARE(viewportRect, QRect(0, 0, 200, 200));
2406 #if defined QT_BUILD_INTERNAL
2407 QGraphicsViewPrivate *viewPrivate = static_cast<QGraphicsViewPrivate *>(qt_widget_private(&view));
2410 const QRect rect1(0, 0, 10, 10);
2411 QVERIFY(viewPrivate->updateRect(rect1));
2412 QVERIFY(!viewPrivate->fullUpdatePending);
2413 boundingRect |= rect1;
2414 QCOMPARE(viewPrivate->dirtyBoundingRect, boundingRect);
2416 const QRect rect2(50, 50, 10, 10);
2417 QVERIFY(viewPrivate->updateRect(rect2));
2418 QVERIFY(!viewPrivate->fullUpdatePending);
2419 boundingRect |= rect2;
2420 QCOMPARE(viewPrivate->dirtyBoundingRect, boundingRect);
2422 const QRect rect3(190, 190, 10, 10);
2423 QVERIFY(viewPrivate->updateRect(rect3));
2424 QVERIFY(viewPrivate->fullUpdatePending);
2425 boundingRect |= rect3;
2426 QCOMPARE(viewPrivate->dirtyBoundingRect, boundingRect);
2428 view.lastUpdateRegions.clear();
2429 viewPrivate->processPendingUpdates();
2431 QCOMPARE(view.lastUpdateRegions.size(), 1);
2432 // Note that we adjust by 2 for antialiasing.
2433 QCOMPARE(view.lastUpdateRegions.at(0), QRegion(boundingRect.adjusted(-2, -2, 2, 2) & viewportRect));
2437 #ifndef QT_NO_DRAGANDDROP
2438 void tst_QGraphicsView::acceptDrops()
2442 // Excepted default behavior.
2443 QVERIFY(view.acceptDrops());
2444 QVERIFY(view.viewport()->acceptDrops());
2446 // Excepted behavior with no drops.
2447 view.setAcceptDrops(false);
2448 QVERIFY(!view.acceptDrops());
2449 QVERIFY(!view.viewport()->acceptDrops());
2451 // Setting a widget with drops on a QGraphicsView without drops.
2452 QWidget *widget = new QWidget;
2453 widget->setAcceptDrops(true);
2454 view.setViewport(widget);
2455 QVERIFY(!view.acceptDrops());
2456 QVERIFY(!view.viewport()->acceptDrops());
2458 // Switching the view to accept drops.
2459 view.setAcceptDrops(true);
2460 QVERIFY(view.acceptDrops());
2461 QVERIFY(view.viewport()->acceptDrops());
2463 // Setting a widget with no drops on a QGraphicsView with drops.
2464 widget = new QWidget;
2465 widget->setAcceptDrops(false);
2466 view.setViewport(widget);
2467 QVERIFY(view.viewport()->acceptDrops());
2468 QVERIFY(view.acceptDrops());
2470 // Switching the view to not accept drops.
2471 view.setAcceptDrops(false);
2472 QVERIFY(!view.viewport()->acceptDrops());
2476 void tst_QGraphicsView::optimizationFlags()
2479 QVERIFY(!view.optimizationFlags());
2481 view.setOptimizationFlag(QGraphicsView::DontClipPainter);
2482 QVERIFY(view.optimizationFlags() & QGraphicsView::DontClipPainter);
2483 view.setOptimizationFlag(QGraphicsView::DontClipPainter, false);
2484 QVERIFY(!view.optimizationFlags());
2486 view.setOptimizationFlag(QGraphicsView::DontSavePainterState);
2487 QVERIFY(view.optimizationFlags() & QGraphicsView::DontSavePainterState);
2488 view.setOptimizationFlag(QGraphicsView::DontSavePainterState, false);
2489 QVERIFY(!view.optimizationFlags());
2491 view.setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing);
2492 QVERIFY(view.optimizationFlags() & QGraphicsView::DontAdjustForAntialiasing);
2493 view.setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing, false);
2494 QVERIFY(!view.optimizationFlags());
2496 view.setOptimizationFlags(QGraphicsView::DontAdjustForAntialiasing
2497 | QGraphicsView::DontClipPainter);
2498 QCOMPARE(view.optimizationFlags(), QGraphicsView::OptimizationFlags(QGraphicsView::DontAdjustForAntialiasing
2499 | QGraphicsView::DontClipPainter));
2502 class MessUpPainterItem : public QGraphicsRectItem
2505 MessUpPainterItem(const QRectF &rect) : QGraphicsRectItem(rect), dirtyPainter(false)
2510 void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
2512 dirtyPainter = (painter->pen().width() != 0);
2513 painter->setPen(QPen(Qt::black, 1.0));
2517 class MyGraphicsView : public QGraphicsView
2520 MyGraphicsView(QGraphicsScene * scene) : QGraphicsView(scene)
2523 void drawBackground(QPainter * painter, const QRectF & rect) {
2524 painter->setCompositionMode(QPainter::CompositionMode_Source);
2525 painter->drawRect(rect);
2528 void drawItems (QPainter * painter, int numItems, QGraphicsItem *items[], const QStyleOptionGraphicsItem options[]) {
2529 if (!(optimizationFlags() & QGraphicsView::DontSavePainterState))
2530 QCOMPARE(painter->compositionMode(),QPainter::CompositionMode_SourceOver);
2532 QCOMPARE(painter->compositionMode(),QPainter::CompositionMode_Source);
2533 QGraphicsView::drawItems(painter,numItems,items,options);
2537 void tst_QGraphicsView::optimizationFlags_dontSavePainterState()
2539 MessUpPainterItem *parent = new MessUpPainterItem(QRectF(0, 0, 100, 100));
2540 MessUpPainterItem *child = new MessUpPainterItem(QRectF(0, 0, 100, 100));
2541 child->setParentItem(parent);
2543 QGraphicsScene scene;
2544 scene.addItem(parent);
2546 QGraphicsView view(&scene);
2548 QVERIFY(QTest::qWaitForWindowExposed(&view));
2549 view.viewport()->repaint();
2551 QVERIFY(!parent->dirtyPainter);
2552 QVERIFY(!child->dirtyPainter);
2554 view.setOptimizationFlags(QGraphicsView::DontSavePainterState);
2555 view.viewport()->repaint();
2558 // Repaint on Mac OS X actually does require spinning the event loop.
2561 QVERIFY(!parent->dirtyPainter);
2562 QVERIFY(child->dirtyPainter);
2564 MyGraphicsView painter(&scene);
2566 QVERIFY(QTest::qWaitForWindowExposed(&painter));
2568 MyGraphicsView painter2(&scene);
2569 painter2.setOptimizationFlag(QGraphicsView::DontSavePainterState,true);
2571 QVERIFY(QTest::qWaitForWindowExposed(&painter2));
2574 void tst_QGraphicsView::optimizationFlags_dontSavePainterState2_data()
2576 QTest::addColumn<bool>("savePainter");
2577 QTest::addColumn<bool>("indirectPainting");
2578 QTest::newRow("With painter state protection, without indirect painting") << true << false;
2579 QTest::newRow("Without painter state protection, without indirect painting") << false << false;
2580 QTest::newRow("With painter state protectionm, with indirect painting") << true << true;
2581 QTest::newRow("Without painter state protection, with indirect painting") << false << true;
2584 void tst_QGraphicsView::optimizationFlags_dontSavePainterState2()
2586 QFETCH(bool, savePainter);
2587 QFETCH(bool, indirectPainting);
2589 class MyScene : public QGraphicsScene
2592 void drawBackground(QPainter *p, const QRectF &)
2593 { transformInDrawBackground = p->worldTransform(); opacityInDrawBackground = p->opacity(); }
2595 void drawForeground(QPainter *p, const QRectF &)
2596 { transformInDrawForeground = p->worldTransform(); opacityInDrawForeground = p->opacity(); }
2598 QTransform transformInDrawBackground;
2599 QTransform transformInDrawForeground;
2600 qreal opacityInDrawBackground;
2601 qreal opacityInDrawForeground;
2605 // Add transformed dummy items to make sure the painter's worldTransform() is changed in drawItems.
2606 scene.addRect(0, 0, 20, 20)->setTransform(QTransform::fromScale(2, 2));
2607 scene.addRect(50, 50, 20, 20)->setTransform(QTransform::fromTranslate(200, 200));
2609 foreach (QGraphicsItem *item, scene.items())
2610 item->setOpacity(0.6);
2612 CustomView view(&scene);
2614 view.setOptimizationFlag(QGraphicsView::DontSavePainterState);
2615 view.setOptimizationFlag(QGraphicsView::IndirectPainting, indirectPainting);
2617 view.scale(1.5, 1.5);
2619 QVERIFY(QTest::qWaitForWindowExposed(&view));
2621 // Make sure the view is repainted; otherwise the tests below will fail.
2622 view.viewport()->repaint();
2624 QVERIFY(view.painted);
2626 // Make sure the painter's world transform is preserved after drawItems.
2627 QTransform expectedTransform = view.viewportTransform();
2628 QVERIFY(!expectedTransform.isIdentity());
2629 QCOMPARE(scene.transformInDrawForeground, expectedTransform);
2630 QCOMPARE(scene.transformInDrawBackground, expectedTransform);
2632 qreal expectedOpacity = 1.0;
2633 QCOMPARE(scene.opacityInDrawBackground, expectedOpacity);
2634 QCOMPARE(scene.opacityInDrawForeground, expectedOpacity);
2636 // Trigger more painting, this time from QGraphicsScene::render.
2637 QImage image(scene.sceneRect().size().toSize(), QImage::Format_RGB32);
2638 QPainter painter(&image);
2639 scene.render(&painter);
2642 expectedTransform = QTransform();
2643 QCOMPARE(scene.transformInDrawForeground, expectedTransform);
2644 QCOMPARE(scene.transformInDrawBackground, expectedTransform);
2645 QCOMPARE(scene.opacityInDrawBackground, expectedOpacity);
2646 QCOMPARE(scene.opacityInDrawForeground, expectedOpacity);
2648 // Trigger more painting with another opacity on the painter.
2649 painter.begin(&image);
2650 painter.setOpacity(0.4);
2651 expectedOpacity = 0.4;
2652 scene.render(&painter);
2655 QCOMPARE(scene.transformInDrawForeground, expectedTransform);
2656 QCOMPARE(scene.transformInDrawBackground, expectedTransform);
2657 QCOMPARE(scene.opacityInDrawBackground, expectedOpacity);
2658 QCOMPARE(scene.opacityInDrawForeground, expectedOpacity);
2661 class LodItem : public QGraphicsRectItem
2664 LodItem(const QRectF &rect) : QGraphicsRectItem(rect), lastLod(-42)
2667 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *viewport)
2669 lastLod = option->levelOfDetailFromTransform(painter->worldTransform());
2670 QGraphicsRectItem::paint(painter, option, viewport);
2676 void tst_QGraphicsView::levelOfDetail_data()
2678 QTest::addColumn<QTransform>("transform");
2679 QTest::addColumn<qreal>("lod");
2681 QTest::newRow("1:4, 1:4") << QTransform().scale(0.25, 0.25) << qreal(0.25);
2682 QTest::newRow("1:2, 1:4") << QTransform().scale(0.5, 0.25) << qreal(::sqrt(0.125));
2683 QTest::newRow("4:1, 1:2") << QTransform().scale(0.25, 0.5) << qreal(::sqrt(0.125));
2685 QTest::newRow("1:2, 1:2") << QTransform().scale(0.5, 0.5) << qreal(0.5);
2686 QTest::newRow("1:1, 1:2") << QTransform().scale(1, 0.5) << qreal(::sqrt(0.5));
2687 QTest::newRow("2:1, 1:1") << QTransform().scale(0.5, 1) << qreal(::sqrt(0.5));
2689 QTest::newRow("1:1, 1:1") << QTransform().scale(1, 1) << qreal(1.0);
2690 QTest::newRow("2:1, 1:1") << QTransform().scale(2, 1) << qreal(::sqrt(2.0));
2691 QTest::newRow("1:1, 2:1") << QTransform().scale(2, 1) << qreal(::sqrt(2.0));
2692 QTest::newRow("2:1, 2:1") << QTransform().scale(2, 2) << qreal(2.0);
2693 QTest::newRow("2:1, 4:1") << QTransform().scale(2, 4) << qreal(::sqrt(8.0));
2694 QTest::newRow("4:1, 2:1") << QTransform().scale(4, 2) << qreal(::sqrt(8.0));
2695 QTest::newRow("4:1, 4:1") << QTransform().scale(4, 4) << qreal(4.0);
2698 void tst_QGraphicsView::levelOfDetail()
2700 QFETCH(QTransform, transform);
2703 LodItem *item = new LodItem(QRectF(0, 0, 100, 100));
2705 QGraphicsScene scene;
2706 scene.addItem(item);
2708 QGraphicsView view(&scene);
2710 QVERIFY(QTest::qWaitForWindowExposed(&view));
2712 QTRY_COMPARE(item->lastLod, qreal(1));
2714 view.setTransform(transform);
2716 QTRY_COMPARE(item->lastLod, lod);
2719 // Moved to tst_qgraphicsview_2.cpp
2720 extern void _scrollBarRanges_data();
2722 void tst_QGraphicsView::scrollBarRanges_data()
2724 _scrollBarRanges_data();
2727 // Simulates motif scrollbar for range tests
2728 class FauxMotifStyle : public QCommonStyle {
2730 int styleHint(StyleHint hint, const QStyleOption *option,
2731 const QWidget *widget, QStyleHintReturn *returnData) const {
2732 if (hint == QStyle::SH_ScrollView_FrameOnlyAroundContents)
2734 return QCommonStyle::styleHint(hint, option, widget, returnData);
2737 int pixelMetric(PixelMetric m, const QStyleOption *opt, const QWidget *widget) const {
2738 if (m == QStyle::PM_ScrollView_ScrollBarSpacing)
2740 return QCommonStyle::pixelMetric(m, opt, widget);
2744 void tst_QGraphicsView::scrollBarRanges()
2746 QFETCH(QSize, viewportSize);
2747 QFETCH(QRectF, sceneRect);
2748 QFETCH(QTransform, transform);
2749 QFETCH(Qt::ScrollBarPolicy, hbarpolicy);
2750 QFETCH(Qt::ScrollBarPolicy, vbarpolicy);
2755 QFETCH(bool, useMotif);
2756 QFETCH(bool, useStyledPanel);
2758 QGraphicsScene scene(sceneRect);
2759 scene.addRect(sceneRect, QPen(Qt::blue), QBrush(QColor(Qt::green)));
2760 QGraphicsView view(&scene);
2761 view.setRenderHint(QPainter::Antialiasing);
2762 view.setTransform(transform);
2763 view.setFrameStyle(useStyledPanel ? QFrame::StyledPanel : QFrame::NoFrame);
2766 #if !defined(QT_NO_STYLE_WINDOWS)
2767 view.setStyle(new FauxMotifStyle);
2769 QSKIP("No Windows style compiled.");
2772 #if defined(Q_OS_WINCE)
2773 view.setStyle(new QWindowsStyle);
2774 #elif !defined(QT_NO_STYLE_PLASTIQUE)
2775 view.setStyle(new QPlastiqueStyle);
2778 view.setStyleSheet(" "); // enables style propagation ;-)
2782 adjust = view.style()->pixelMetric(QStyle::PM_DefaultFrameWidth) * 2;
2783 view.resize(viewportSize + QSize(adjust, adjust));
2785 view.setHorizontalScrollBarPolicy(hbarpolicy);
2786 view.setVerticalScrollBarPolicy(vbarpolicy);
2789 QVERIFY(QTest::qWaitForWindowExposed(&view));
2791 QCOMPARE(view.horizontalScrollBar()->minimum(), hmin);
2792 QCOMPARE(view.verticalScrollBar()->minimum(), vmin);
2793 QCOMPARE(view.horizontalScrollBar()->maximum(), hmax);
2794 QCOMPARE(view.verticalScrollBar()->maximum(), vmax);
2797 class TestView : public QGraphicsView
2800 TestView(QGraphicsScene *scene)
2801 : QGraphicsView(scene), accepted(false)
2807 void mousePressEvent(QMouseEvent *event)
2809 QGraphicsView::mousePressEvent(event);
2810 accepted = event->isAccepted();
2814 void tst_QGraphicsView::acceptMousePressEvent()
2816 QGraphicsScene scene;
2818 TestView view(&scene);
2820 QVERIFY(QTest::qWaitForWindowExposed(&view));
2822 QMouseEvent event(QEvent::MouseButtonPress,
2823 view.viewport()->rect().center(),
2824 view.viewport()->mapToGlobal(view.viewport()->rect().center()),
2825 Qt::LeftButton, 0, 0);
2826 event.setAccepted(false);
2827 QApplication::sendEvent(view.viewport(), &event);
2828 QVERIFY(!view.accepted);
2830 scene.addRect(0, 0, 2000, 2000)->setFlag(QGraphicsItem::ItemIsMovable);
2832 qApp->processEvents(); // ensure scene rect is updated
2834 QApplication::sendEvent(view.viewport(), &event);
2835 QVERIFY(view.accepted);
2838 void tst_QGraphicsView::replayMouseMove()
2840 // An empty scene in a view. The view will send the events to the scene in
2841 // any case. Note that the view doesn't have to be shown - the mouse event
2842 // sending functions below send the events directly to the viewport.
2843 QGraphicsScene scene(-10000, -10000, 20000, 20000);
2844 QGraphicsView view(&scene);
2846 EventSpy sceneSpy(&scene, QEvent::GraphicsSceneMouseMove);
2847 EventSpy viewSpy(view.viewport(), QEvent::MouseMove);
2849 sendMousePress(view.viewport(), view.viewport()->rect().center());
2851 // One mouse event should be translated into one scene event.
2852 for (int i = 0; i < 3; ++i) {
2853 sendMouseMove(view.viewport(), view.viewport()->rect().center(),
2854 Qt::LeftButton, Qt::MouseButtons(Qt::LeftButton));
2855 QCOMPARE(viewSpy.count(), i + 1);
2856 QCOMPARE(sceneSpy.count(), i + 1);
2859 // When the view is transformed, the view should get no more events. But
2860 // the scene should get replays.
2861 for (int i = 0; i < 3; ++i) {
2863 QCOMPARE(viewSpy.count(), 3);
2864 QCOMPARE(sceneSpy.count(), 3 + i + 1);
2867 // When the view is scrolled, the view should get no more events. But the
2868 // scene should get replays.
2869 for (int i = 0; i < 3; ++i) {
2870 view.horizontalScrollBar()->setValue((i + 1) * 10);
2871 QCOMPARE(viewSpy.count(), 3);
2872 QCOMPARE(sceneSpy.count(), 6 + i + 1);
2876 void tst_QGraphicsView::itemsUnderMouse()
2878 QGraphicsScene scene;
2879 QGraphicsProxyWidget w;
2880 w.setWidget(new QPushButton("W"));
2882 QGraphicsProxyWidget w2(&w);
2883 w2.setWidget(new QPushButton("W2"));
2885 QGraphicsProxyWidget w3(&w2);
2886 w3.setWidget(new QPushButton("W3"));
2893 QGraphicsView view(&scene);
2895 QVERIFY(QTest::qWaitForWindowExposed(&view));
2897 QCOMPARE(view.items(view.mapFromScene(w3.boundingRect().center())).first(),
2898 static_cast<QGraphicsItem *>(&w3));
2899 w2.setFlag(QGraphicsItem::ItemIgnoresTransformations, true);
2900 QCOMPARE(view.items(view.mapFromScene(w3.boundingRect().center())).first(),
2901 static_cast<QGraphicsItem *>(&w3));
2904 class QGraphicsTextItem_task172231 : public QGraphicsTextItem
2907 QGraphicsTextItem_task172231(const QString & text, QGraphicsItem * parent = 0)
2908 : QGraphicsTextItem(text, parent) {}
2910 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
2912 exposedRect = option->exposedRect;
2913 QGraphicsTextItem::paint(painter, option, widget);
2917 void tst_QGraphicsView::task172231_untransformableItems()
2919 // check fix in QGraphicsView::paintEvent()
2921 QGraphicsScene scene;
2923 QGraphicsTextItem_task172231 *text =
2924 new QGraphicsTextItem_task172231("abcdefghijklmnopqrstuvwxyz");
2925 text->setFlag(QGraphicsItem::ItemIgnoresTransformations);
2926 scene.addItem(text);
2928 QGraphicsView view(&scene);
2932 QApplication::setActiveWindow(&view);
2933 QVERIFY(QTest::qWaitForWindowActive(&view));
2934 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2936 QRectF origExposedRect = text->exposedRect;
2938 view.resize(int(0.75 * view.width()), view.height());
2939 qApp->processEvents();
2941 QCOMPARE(text->exposedRect, origExposedRect);
2943 // notice that the fix also goes into QGraphicsView::render()
2944 // and QGraphicsScene::render(), but in duplicated code that
2945 // is pending a refactoring, so for now we omit autotesting
2946 // these functions separately
2949 class MousePressReleaseScene : public QGraphicsScene
2952 MousePressReleaseScene()
2953 : presses(0), releases(0)
2959 void mousePressEvent(QGraphicsSceneMouseEvent *event)
2960 { ++presses; QGraphicsScene::mousePressEvent(event); }
2961 void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
2962 { ++releases; QGraphicsScene::mouseReleaseEvent(event); }
2965 void tst_QGraphicsView::task180429_mouseReleaseDragMode()
2967 MousePressReleaseScene scene;
2969 QGraphicsView view(&scene);
2972 sendMousePress(view.viewport(), view.viewport()->rect().center());
2973 QCOMPARE(scene.presses, 1);
2974 QCOMPARE(scene.releases, 0);
2975 sendMouseRelease(view.viewport(), view.viewport()->rect().center());
2976 QCOMPARE(scene.presses, 1);
2977 QCOMPARE(scene.releases, 1);
2979 view.setDragMode(QGraphicsView::RubberBandDrag);
2980 sendMousePress(view.viewport(), view.viewport()->rect().center());
2981 QCOMPARE(scene.presses, 2);
2982 QCOMPARE(scene.releases, 1);
2983 sendMouseRelease(view.viewport(), view.viewport()->rect().center());
2984 QCOMPARE(scene.presses, 2);
2985 QCOMPARE(scene.releases, 2);
2988 void tst_QGraphicsView::task187791_setSceneCausesUpdate()
2990 QGraphicsScene scene(0, 0, 200, 200);
2991 QGraphicsView view(&scene);
2993 qApp->setActiveWindow(&view);
2994 QVERIFY(QTest::qWaitForWindowShown(&view));
2996 EventSpy updateSpy(view.viewport(), QEvent::Paint);
2997 QCOMPARE(updateSpy.count(), 0);
3000 QApplication::processEvents();
3001 QTRY_COMPARE(updateSpy.count(), 1);
3002 view.setScene(&scene);
3003 QApplication::processEvents();
3004 QTRY_COMPARE(updateSpy.count(), 2);
3007 class MouseMoveCounter : public QGraphicsView
3010 MouseMoveCounter() : mouseMoves(0)
3014 void mouseMoveEvent(QMouseEvent *event)
3017 QGraphicsView::mouseMoveEvent(event);
3018 foreach (QGraphicsItem *item, scene()->items()) {
3019 scene()->removeItem(item);
3022 scene()->addRect(0, 0, 50, 50);
3023 scene()->addRect(0, 0, 100, 100);
3027 void tst_QGraphicsView::task186827_deleteReplayedItem()
3029 // make sure the mouse is not over the window, causing spontaneous mouse moves
3030 QCursor::setPos(1, 1);
3032 QGraphicsScene scene;
3033 scene.addRect(0, 0, 50, 50);
3034 scene.addRect(0, 0, 100, 100);
3036 MouseMoveCounter view;
3037 view.setScene(&scene);
3039 QVERIFY(QTest::qWaitForWindowExposed(&view));
3040 view.viewport()->setMouseTracking(true);
3042 QCOMPARE(view.mouseMoves, 0);
3044 QMouseEvent event(QEvent::MouseMove, view.mapFromScene(25, 25), Qt::NoButton, 0, 0);
3045 QApplication::sendEvent(view.viewport(), &event);
3047 QCOMPARE(view.mouseMoves, 1);
3049 QTRY_COMPARE(view.mouseMoves, 1);
3052 QMouseEvent event(QEvent::MouseMove, view.mapFromScene(25, 25), Qt::NoButton, 0, 0);
3053 QApplication::sendEvent(view.viewport(), &event);
3055 QCOMPARE(view.mouseMoves, 2);
3059 void tst_QGraphicsView::task207546_focusCrash()
3061 class _Widget : public QWidget
3064 bool focusNextPrevChild(bool next) { return QWidget::focusNextPrevChild(next); }
3067 widget.setLayout(new QVBoxLayout());
3068 QGraphicsView *gr1 = new QGraphicsView(&widget);
3069 QGraphicsView *gr2 = new QGraphicsView(&widget);
3070 widget.layout()->addWidget(gr1);
3071 widget.layout()->addWidget(gr2);
3073 widget.activateWindow();
3074 QApplication::setActiveWindow(&widget);
3075 QVERIFY(QTest::qWaitForWindowActive(&widget));
3076 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&widget));
3077 widget.focusNextPrevChild(true);
3078 QCOMPARE(static_cast<QWidget *>(gr2), widget.focusWidget());
3081 void tst_QGraphicsView::task210599_unsetDragWhileDragging()
3083 QGraphicsScene scene(0, 0, 400, 400);
3084 QGraphicsView view(&scene);
3085 view.setGeometry(0, 0, 200, 200);
3088 QPoint origPos = QPoint(100, 100);
3089 QPoint step1Pos = QPoint(100, 110);
3090 QPoint step2Pos = QPoint(100, 120);
3092 // Enable and do a drag
3094 view.setDragMode(QGraphicsView::ScrollHandDrag);
3095 QMouseEvent press(QEvent::MouseButtonPress, origPos, Qt::LeftButton, 0, 0);
3096 QMouseEvent move(QEvent::MouseMove, step1Pos, Qt::LeftButton, 0, 0);
3097 QApplication::sendEvent(view.viewport(), &press);
3098 QApplication::sendEvent(view.viewport(), &move);
3101 // unset drag and release mouse, inverse order
3103 view.setDragMode(QGraphicsView::NoDrag);
3104 QMouseEvent release(QEvent::MouseButtonRelease, step1Pos, Qt::LeftButton, 0, 0);
3105 QApplication::sendEvent(view.viewport(), &release);
3108 QPoint basePos = view.mapFromScene(0, 0);
3110 // reset drag, and move mouse without holding button down.
3112 view.setDragMode(QGraphicsView::ScrollHandDrag);
3113 QMouseEvent move(QEvent::MouseMove, step2Pos, Qt::LeftButton, 0, 0);
3114 QApplication::sendEvent(view.viewport(), &move);
3117 // Check that no draggin has occurred...
3118 QCOMPARE(basePos, view.mapFromScene(0, 0));
3121 void tst_QGraphicsView::task236394_sendShortcutOverrideEvent()
3125 QKeyEvent event(QEvent::ShortcutOverride, Qt::Key_A, 0, QString("A"));
3126 QApplication::sendEvent(&view, &event);
3129 class ChangedListener : public QObject
3133 QList<QList<QRectF> > changes;
3136 void changed(const QList<QRectF> &dirty)
3142 void tst_QGraphicsView::task239729_noViewUpdate_data()
3144 QTest::addColumn<bool>("a");
3146 QTest::newRow("a") << false;
3147 QTest::newRow("b") << true;
3150 void tst_QGraphicsView::task239729_noViewUpdate()
3153 // The scene's changed signal is connected to something that isn't a view.
3154 QGraphicsScene scene;
3156 QGraphicsView *view = 0;
3159 view = new QGraphicsView(&scene);
3160 connect(&scene, SIGNAL(changed(QList<QRectF>)), &cl, SLOT(changed(QList<QRectF>)));
3162 connect(&scene, SIGNAL(changed(QList<QRectF>)), &cl, SLOT(changed(QList<QRectF>)));
3163 view = new QGraphicsView(&scene);
3166 EventSpy spy(view->viewport(), QEvent::Paint);
3167 QCOMPARE(spy.count(), 0);
3170 qApp->setActiveWindow(view);
3171 QVERIFY(QTest::qWaitForWindowActive(view));
3173 QTRY_VERIFY(spy.count() >= 1);
3176 QApplication::processEvents();
3177 QTRY_COMPARE(spy.count(), 1);
3182 void tst_QGraphicsView::task239047_fitInViewSmallViewport()
3184 // Ensure that with a small viewport, fitInView doesn't mirror the
3187 QGraphicsScene scene;
3188 QGraphicsView *view = new QGraphicsView(&scene, &widget);
3190 QCOMPARE(view->size(), QSize(3, 3));
3192 view->fitInView(0, 0, 100, 100);
3193 QPointF topLeft = view->mapToScene(0, 0);
3194 QPointF bottomRight = view->mapToScene(100, 100);
3195 QVERIFY(bottomRight.x() > topLeft.x());
3196 QVERIFY(bottomRight.y() > topLeft.y());
3198 view->fitInView(0, 0, 0, 100);
3202 view->fitInView(0, 0, 100, 100);
3205 void tst_QGraphicsView::task245469_itemsAtPointWithClip()
3207 QGraphicsScene scene;
3208 QGraphicsItem *parent = scene.addRect(0, 0, 100, 100);
3209 QGraphicsItem *child = new QGraphicsRectItem(40, 40, 20, 20, parent);
3210 parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
3212 QGraphicsView view(&scene);
3213 view.resize(150,150);
3216 QVERIFY(QTest::qWaitForWindowExposed(&view));
3218 QList<QGraphicsItem *> itemsAtCenter = view.items(view.viewport()->rect().center());
3219 QCOMPARE(itemsAtCenter, (QList<QGraphicsItem *>() << child << parent));
3221 QPolygonF p = view.mapToScene(QRect(view.viewport()->rect().center(), QSize(1, 1)));
3222 QList<QGraphicsItem *> itemsAtCenter2 = scene.items(p);
3223 QCOMPARE(itemsAtCenter2, itemsAtCenter);
3226 static QGraphicsView *createSimpleViewAndScene()
3228 QGraphicsView *view = new QGraphicsView;
3229 QGraphicsScene *scene = new QGraphicsScene;
3230 view->setScene(scene);
3232 view->setBackgroundBrush(Qt::blue);
3234 QGraphicsRectItem *rect = scene->addRect(0, 0, 10, 10);
3235 rect->setBrush(Qt::red);
3236 rect->setPen(Qt::NoPen);
3240 class SpyItem : public QGraphicsRectItem
3244 : QGraphicsRectItem(QRectF(0, 0, 100, 100))
3248 void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
3250 transform = painter->transform();
3253 QTransform transform;
3256 void tst_QGraphicsView::embeddedViews()
3258 QGraphicsView *v1 = createSimpleViewAndScene();
3259 QGraphicsView *v2 = createSimpleViewAndScene();
3261 QGraphicsProxyWidget *proxy = v1->scene()->addWidget(v2);
3263 SpyItem *item = new SpyItem;
3264 v2->scene()->addItem(item);
3266 proxy->translate(5, 5);
3268 QImage actual(64, 64, QImage::Format_ARGB32_Premultiplied);
3270 v1->QWidget::render(&actual);
3271 QTransform a = item->transform;
3273 v2->QWidget::render(&actual);
3274 QTransform b = item->transform;
3280 void tst_QGraphicsView::scrollAfterResize_data()
3282 QTest::addColumn<bool>("reverse");
3283 QTest::addColumn<QTransform>("x1");
3284 QTest::addColumn<QTransform>("x2");
3285 QTest::addColumn<QTransform>("x3");
3287 #if !defined(QT_NO_STYLE_PLASTIQUE)
3288 QPlastiqueStyle style;
3289 #elif !defined(QT_NO_STYLE_WINDOWS)
3290 QWindowsStyle style;
3295 int frameWidth = style.pixelMetric(QStyle::PM_DefaultFrameWidth);
3296 int extent = style.pixelMetric(QStyle::PM_ScrollBarExtent);
3297 int inside = style.styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents);
3298 int viewportWidth = 300;
3299 int scrollBarIndent = viewportWidth - extent - (inside ? 4 : 2)*frameWidth;
3301 QTest::newRow("normal") << false
3304 << QTransform().translate(-10, 0);
3305 QTest::newRow("reverse") << true
3306 << QTransform().translate(scrollBarIndent, 0)
3307 << QTransform().translate(scrollBarIndent + 100, 0)
3308 << QTransform().translate(scrollBarIndent + 110, 0);
3311 void tst_QGraphicsView::scrollAfterResize()
3313 QFETCH(bool, reverse);
3314 QFETCH(QTransform, x1);
3315 QFETCH(QTransform, x2);
3316 QFETCH(QTransform, x3);
3318 #if !defined(QT_NO_STYLE_PLASTIQUE)
3319 QPlastiqueStyle style;
3320 #elif !defined(QT_NO_STYLE_WINDOWS)
3321 QWindowsStyle style;
3327 QGraphicsView view(&toplevel);
3328 view.setStyle(&style);
3330 view.setLayoutDirection(Qt::RightToLeft);
3332 view.setSceneRect(-1000, -1000, 2000, 2000);
3333 view.resize(300, 300);
3335 QVERIFY(QTest::qWaitForWindowExposed(&toplevel));
3336 view.horizontalScrollBar()->setValue(0);
3337 view.verticalScrollBar()->setValue(0);
3338 QCOMPARE(view.viewportTransform(), x1);
3339 view.resize(400, 300);
3340 QCOMPARE(view.viewportTransform(), x2);
3341 view.horizontalScrollBar()->setValue(10);
3342 QCOMPARE(view.viewportTransform(), x3);
3345 void tst_QGraphicsView::moveItemWhileScrolling_data()
3347 QTest::addColumn<bool>("adjustForAntialiasing");
3348 QTest::addColumn<bool>("changedConnected");
3350 QTest::newRow("no adjust") << false << false;
3351 QTest::newRow("adjust") << true << false;
3352 QTest::newRow("no adjust changedConnected") << false << true;
3353 QTest::newRow("adjust changedConnected") << true << true;
3356 void tst_QGraphicsView::moveItemWhileScrolling()
3358 QFETCH(bool, adjustForAntialiasing);
3359 QFETCH(bool, changedConnected);
3361 class MoveItemScrollView : public QGraphicsView
3364 MoveItemScrollView()
3366 setWindowFlags(Qt::X11BypassWindowManagerHint);
3367 setScene(new QGraphicsScene(0, 0, 1000, 1000));
3368 rect = scene()->addRect(0, 0, 10, 10);
3369 rect->setPos(50, 50);
3372 QRegion lastPaintedRegion;
3373 QGraphicsItem *rect;
3375 void waitForPaintEvent()
3377 QTimer::singleShot(2000, &eventLoop, SLOT(quit()));
3381 QEventLoop eventLoop;
3382 void paintEvent(QPaintEvent *event)
3385 lastPaintedRegion = event->region();
3386 QGraphicsView::paintEvent(event);
3387 if (eventLoop.isRunning())
3392 MoveItemScrollView view;
3393 view.setFrameStyle(0);
3394 view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3395 view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3396 view.setResizeAnchor(QGraphicsView::NoAnchor);
3397 view.setTransformationAnchor(QGraphicsView::NoAnchor);
3398 if (!adjustForAntialiasing)
3399 view.setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing);
3400 view.resize(200, 200);
3401 view.painted = false;
3403 if (changedConnected)
3404 QObject::connect(view.scene(), SIGNAL(changed(QList<QRectF>)), this, SLOT(dummySlot()));
3405 QVERIFY(QTest::qWaitForWindowExposed(&view));
3406 QApplication::processEvents();
3407 QTRY_VERIFY(view.painted);
3408 view.painted = false;
3409 view.lastPaintedRegion = QRegion();
3410 view.horizontalScrollBar()->setValue(view.horizontalScrollBar()->value() + 10);
3411 view.rect->moveBy(0, 10);
3412 view.waitForPaintEvent();
3413 QTRY_VERIFY(view.painted);
3415 QRegion expectedRegion;
3416 expectedRegion += QRect(0, 0, 200, 200);
3417 expectedRegion -= QRect(0, 0, 190, 200);
3418 int a = adjustForAntialiasing ? 2 : 1;
3419 expectedRegion += QRect(40, 50, 10, 10).adjusted(-a, -a, a, a);
3420 expectedRegion += QRect(40, 60, 10, 10).adjusted(-a, -a, a, a);
3421 COMPARE_REGIONS(view.lastPaintedRegion, expectedRegion);
3424 void tst_QGraphicsView::centerOnDirtyItem()
3428 QGraphicsView view(&toplevel);
3429 toplevel.setWindowFlags(view.windowFlags() | Qt::WindowStaysOnTopHint);
3430 view.resize(200, 200);
3432 QGraphicsScene *scene = new QGraphicsScene;
3433 view.setScene(scene);
3434 view.setSceneRect(-1000, -1000, 2000, 2000);
3436 QGraphicsRectItem *item = new QGraphicsRectItem(0, 0, 10, 10);
3437 item->setBrush(Qt::red);
3438 scene->addItem(item);
3439 view.centerOn(item);
3442 QVERIFY(QTest::qWaitForWindowExposed(&toplevel));
3445 QImage before(view.viewport()->size(), QImage::Format_ARGB32);
3446 view.viewport()->render(&before);
3448 item->setPos(20, 0);
3449 view.centerOn(item);
3453 QImage after(view.viewport()->size(), QImage::Format_ARGB32);
3454 view.viewport()->render(&after);
3456 QCOMPARE(before, after);
3459 void tst_QGraphicsView::mouseTracking()
3461 // Mouse tracking should only be automatically enabled if items either accept hover events
3462 // or have a cursor set. We never disable mouse tracking if it is already enabled.
3464 { // Make sure mouse tracking is disabled by default.
3465 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3466 QGraphicsView view(&scene);
3467 QVERIFY(!view.viewport()->hasMouseTracking());
3470 { // Make sure we don't disable mouse tracking in setupViewport/setScene.
3472 QWidget *viewport = new QWidget;
3473 viewport->setMouseTracking(true);
3474 view.setViewport(viewport);
3475 QVERIFY(viewport->hasMouseTracking());
3477 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3478 view.setScene(&scene);
3479 QVERIFY(viewport->hasMouseTracking());
3482 // Make sure we enable mouse tracking when having items that accept hover events.
3484 // Adding an item to the scene after the scene is set on the view.
3485 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3486 QGraphicsView view(&scene);
3488 QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
3489 item->setAcceptHoverEvents(true);
3490 scene.addItem(item);
3491 QVERIFY(view.viewport()->hasMouseTracking());
3494 // Adding an item to the scene before the scene is set on the view.
3495 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3496 QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
3497 item->setAcceptHoverEvents(true);
3498 scene.addItem(item);
3500 QGraphicsView view(&scene);
3501 QVERIFY(view.viewport()->hasMouseTracking());
3504 // QGraphicsWidget implicitly accepts hover if it has window decoration.
3505 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3506 QGraphicsView view(&scene);
3508 QGraphicsWidget *widget = new QGraphicsWidget;
3509 scene.addItem(widget);
3510 QVERIFY(!view.viewport()->hasMouseTracking());
3511 // Enable window decoraton.
3512 widget->setWindowFlags(Qt::Window | Qt::WindowTitleHint);
3513 QVERIFY(view.viewport()->hasMouseTracking());
3516 // Make sure we enable mouse tracking when having items with a cursor set.
3518 // Adding an item to the scene after the scene is set on the view.
3519 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3520 QGraphicsView view(&scene);
3522 QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
3523 #ifndef QTEST_NO_CURSOR
3524 item->setCursor(Qt::CrossCursor);
3526 scene.addItem(item);
3527 QVERIFY(view.viewport()->hasMouseTracking());
3530 // Adding an item to the scene before the scene is set on the view.
3531 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3532 QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
3533 #ifndef QTEST_NO_CURSOR
3534 item->setCursor(Qt::CrossCursor);
3536 scene.addItem(item);
3538 QGraphicsView view(&scene);
3539 QVERIFY(view.viewport()->hasMouseTracking());
3542 // Make sure we propagate mouse tracking to all views.
3544 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3545 QGraphicsView view1(&scene);
3546 QGraphicsView view2(&scene);
3547 QGraphicsView view3(&scene);
3549 QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
3550 #ifndef QTEST_NO_CURSOR
3551 item->setCursor(Qt::CrossCursor);
3553 scene.addItem(item);
3555 QVERIFY(view1.viewport()->hasMouseTracking());
3556 QVERIFY(view2.viewport()->hasMouseTracking());
3557 QVERIFY(view3.viewport()->hasMouseTracking());
3561 void tst_QGraphicsView::mouseTracking2()
3563 // Make sure mouse move events propagates to the scene when
3564 // mouse tracking is explicitly enabled on the view,
3565 // even when all items ignore hover events / use default cursor.
3567 QGraphicsScene scene;
3568 scene.addRect(0, 0, 100, 100);
3570 QGraphicsView view(&scene);
3572 QVERIFY(QTest::qWaitForWindowExposed(&view));
3574 QVERIFY(!view.viewport()->hasMouseTracking());
3575 view.viewport()->setMouseTracking(true); // Explicitly enable mouse tracking.
3576 QVERIFY(view.viewport()->hasMouseTracking());
3578 EventSpy spy(&scene, QEvent::GraphicsSceneMouseMove);
3579 QCOMPARE(spy.count(), 0);
3580 QMouseEvent event(QEvent::MouseMove,view.viewport()->rect().center(), Qt::NoButton,
3581 Qt::MouseButtons(Qt::NoButton), 0);
3582 QApplication::sendEvent(view.viewport(), &event);
3583 QCOMPARE(spy.count(), 1);
3586 void tst_QGraphicsView::mouseTracking3()
3588 // Mouse tracking should be automatically enabled if AnchorUnderMouse is used for
3589 // view transform or resize. We never disable mouse tracking if it is already enabled.
3591 { // Make sure we enable mouse tracking when using AnchorUnderMouse for view transformation.
3592 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3593 QGraphicsView view(&scene);
3594 QVERIFY(!view.viewport()->hasMouseTracking());
3596 view.setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
3597 QVERIFY(view.viewport()->hasMouseTracking());
3600 { // Make sure we enable mouse tracking when using AnchorUnderMouse for view resizing.
3601 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3602 QGraphicsView view(&scene);
3603 QVERIFY(!view.viewport()->hasMouseTracking());
3605 view.setResizeAnchor(QGraphicsView::AnchorUnderMouse);
3606 QVERIFY(view.viewport()->hasMouseTracking());
3609 { // Make sure we don't disable mouse tracking in setViewport/setScene (transformation anchor).
3611 view.setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
3612 QVERIFY(view.viewport()->hasMouseTracking());
3614 QWidget *viewport = new QWidget;
3615 view.setViewport(viewport);
3616 QVERIFY(viewport->hasMouseTracking());
3618 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3619 view.setScene(&scene);
3620 QVERIFY(viewport->hasMouseTracking());
3623 { // Make sure we don't disable mouse tracking in setViewport/setScene (resize anchor).
3625 view.setResizeAnchor(QGraphicsView::AnchorUnderMouse);
3626 QVERIFY(view.viewport()->hasMouseTracking());
3628 QWidget *viewport = new QWidget;
3629 view.setViewport(viewport);
3630 QVERIFY(viewport->hasMouseTracking());
3632 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3633 view.setScene(&scene);
3634 QVERIFY(viewport->hasMouseTracking());
3637 // Make sure we don't disable mouse tracking when adding an item (transformation anchor).
3638 { // Adding an item to the scene before the scene is set on the view.
3639 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3640 QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
3641 scene.addItem(item);
3644 view.setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
3645 view.setScene(&scene);
3646 QVERIFY(view.viewport()->hasMouseTracking());
3649 { // Adding an item to the scene after the scene is set on the view.
3650 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3651 QGraphicsView view(&scene);
3652 view.setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
3654 QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
3655 scene.addItem(item);
3656 QVERIFY(view.viewport()->hasMouseTracking());
3659 // Make sure we don't disable mouse tracking when adding an item (resize anchor).
3660 { // Adding an item to the scene before the scene is set on the view.
3661 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3662 QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
3663 scene.addItem(item);
3666 view.setResizeAnchor(QGraphicsView::AnchorUnderMouse);
3667 view.setScene(&scene);
3668 QVERIFY(view.viewport()->hasMouseTracking());
3671 { // Adding an item to the scene after the scene is set on the view.
3672 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3673 QGraphicsView view(&scene);
3674 view.setResizeAnchor(QGraphicsView::AnchorUnderMouse);
3676 QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
3677 scene.addItem(item);
3678 QVERIFY(view.viewport()->hasMouseTracking());
3682 class RenderTester : public QGraphicsRectItem
3685 RenderTester(const QRectF &rect)
3686 : QGraphicsRectItem(rect), paints(0)
3689 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
3692 QGraphicsRectItem::paint(painter, option, widget);
3699 void tst_QGraphicsView::render()
3701 // ### This test can be much more thorough - see QGraphicsScene::render.
3702 QGraphicsScene scene;
3703 CustomView view(&scene);
3704 view.setFrameStyle(0);
3705 view.resize(200, 200);
3706 view.painted = false;
3708 QVERIFY(QTest::qWaitForWindowExposed(&view));
3709 QApplication::processEvents();
3710 QTRY_VERIFY(view.painted);
3712 RenderTester *r1 = new RenderTester(QRectF(0, 0, 50, 50));
3713 RenderTester *r2 = new RenderTester(QRectF(50, 50, 50, 50));
3714 RenderTester *r3 = new RenderTester(QRectF(0, 50, 50, 50));
3715 RenderTester *r4 = new RenderTester(QRectF(50, 0, 50, 50));
3721 qApp->processEvents();
3723 QTRY_COMPARE(r1->paints, 1);
3724 QCOMPARE(r2->paints, 1);
3725 QCOMPARE(r3->paints, 1);
3726 QCOMPARE(r4->paints, 1);
3728 QPixmap pix(200, 200);
3729 pix.fill(Qt::transparent);
3730 QPainter painter(&pix);
3731 view.render(&painter);
3734 QCOMPARE(r1->paints, 2);
3735 QCOMPARE(r2->paints, 2);
3736 QCOMPARE(r3->paints, 2);
3737 QCOMPARE(r4->paints, 2);
3740 void tst_QGraphicsView::exposeRegion()
3742 RenderTester *item = new RenderTester(QRectF(0, 0, 20, 20));
3743 QGraphicsScene scene;
3744 scene.addItem(item);
3748 view.setScene(&scene);
3750 qApp->setActiveWindow(&view);
3751 QVERIFY(QTest::qWaitForWindowActive(&view));
3753 QTRY_VERIFY(item->paints > 0);
3756 view.lastUpdateRegions.clear();
3758 // Update a small area in the viewport's topLeft() and bottomRight().
3759 // (the boundingRect() of this area covers the entire viewport).
3760 QWidget *viewport = view.viewport();
3761 QRegion expectedExposeRegion = QRect(0, 0, 5, 5);
3762 expectedExposeRegion += QRect(viewport->rect().bottomRight() - QPoint(5, 5), QSize(5, 5));
3763 viewport->update(expectedExposeRegion);
3764 QApplication::processEvents();
3766 // Make sure it triggers correct repaint on the view.
3767 QTRY_COMPARE(view.lastUpdateRegions.size(), 1);
3768 COMPARE_REGIONS(view.lastUpdateRegions.at(0), expectedExposeRegion);
3770 // Make sure the item didn't get any repaints.
3772 QCOMPARE(item->paints, 0);
3776 void tst_QGraphicsView::update_data()
3778 // In view.viewport() coordinates. (viewport rect: QRect(0, 0, 200, 200))
3779 QTest::addColumn<QRect>("updateRect");
3780 QTest::newRow("empty") << QRect();
3781 QTest::newRow("outside left") << QRect(-200, 0, 100, 100);
3782 QTest::newRow("outside right") << QRect(400, 0 ,100, 100);
3783 QTest::newRow("outside top") << QRect(0, -200, 100, 100);
3784 QTest::newRow("outside bottom") << QRect(0, 400, 100, 100);
3785 QTest::newRow("partially inside left") << QRect(-50, 0, 100, 100);
3786 QTest::newRow("partially inside right") << QRect(-150, 0, 100, 100);
3787 QTest::newRow("partially inside top") << QRect(0, -150, 100, 100);
3788 QTest::newRow("partially inside bottom") << QRect(0, 150, 100, 100);
3789 QTest::newRow("on topLeft edge") << QRect(-100, -100, 100, 100);
3790 QTest::newRow("on topRight edge") << QRect(200, -100, 100, 100);
3791 QTest::newRow("on bottomRight edge") << QRect(200, 200, 100, 100);
3792 QTest::newRow("on bottomLeft edge") << QRect(-200, 200, 100, 100);
3793 QTest::newRow("inside topLeft") << QRect(-99, -99, 100, 100);
3794 QTest::newRow("inside topRight") << QRect(199, -99, 100, 100);
3795 QTest::newRow("inside bottomRight") << QRect(199, 199, 100, 100);
3796 QTest::newRow("inside bottomLeft") << QRect(-199, 199, 100, 100);
3797 QTest::newRow("large1") << QRect(50, -100, 100, 400);
3798 QTest::newRow("large2") << QRect(-100, 50, 400, 100);
3799 QTest::newRow("large3") << QRect(-100, -100, 400, 400);
3800 QTest::newRow("viewport rect") << QRect(0, 0, 200, 200);
3803 void tst_QGraphicsView::update()
3805 QFETCH(QRect, updateRect);
3807 // some window manager resize the toplevel to max screen size
3808 // so we must make our view a child (no layout!) of a dummy toplevel
3809 // to ensure that it's really 200x200 pixels
3812 // Create a view with viewport rect equal to QRect(0, 0, 200, 200).
3813 QGraphicsScene dummyScene;
3814 CustomView view(0, &toplevel);
3815 view.setScene(&dummyScene);
3816 view.ensurePolished(); // must ensure polished to get content margins right
3817 int left, top, right, bottom;
3818 view.getContentsMargins(&left, &top, &right, &bottom);
3819 view.resize(200 + left + right, 200 + top + bottom);
3821 QVERIFY(QTest::qWaitForWindowExposed(&toplevel));
3824 QApplication::setActiveWindow(&toplevel);
3825 QApplication::processEvents();
3826 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&toplevel));
3828 const QRect viewportRect = view.viewport()->rect();
3829 QCOMPARE(viewportRect, QRect(0, 0, 200, 200));
3831 #if defined QT_BUILD_INTERNAL
3832 const bool intersects = updateRect.intersects(viewportRect);
3833 QGraphicsViewPrivate *viewPrivate = static_cast<QGraphicsViewPrivate *>(qt_widget_private(&view));
3834 QTRY_COMPARE(viewPrivate->updateRect(updateRect), intersects);
3835 QApplication::processEvents();
3837 view.lastUpdateRegions.clear();
3838 viewPrivate->processPendingUpdates();
3839 QVERIFY(viewPrivate->dirtyRegion.isEmpty());
3840 QVERIFY(viewPrivate->dirtyBoundingRect.isEmpty());
3841 QApplication::processEvents();
3843 QTRY_VERIFY(view.lastUpdateRegions.isEmpty());
3845 QTRY_COMPARE(view.lastUpdateRegions.size(), 1);
3846 QTRY_COMPARE(view.lastUpdateRegions.at(0), QRegion(updateRect) & viewportRect);
3848 QTRY_VERIFY(!viewPrivate->fullUpdatePending);
3852 void tst_QGraphicsView::update2_data()
3854 QTest::addColumn<qreal>("penWidth");
3855 QTest::addColumn<bool>("antialiasing");
3856 QTest::addColumn<bool>("changedConnected");
3859 QTest::newRow("pen width: 0.0, antialiasing: true") << qreal(0.0) << true << false;
3860 QTest::newRow("pen width: 1.5, antialiasing: true") << qreal(1.5) << true << false;
3861 QTest::newRow("pen width: 2.0, antialiasing: true") << qreal(2.0) << true << false;
3862 QTest::newRow("pen width: 3.0, antialiasing: true") << qreal(3.0) << true << false;
3865 QTest::newRow("pen width: 0.0, antialiasing: false") << qreal(0.0) << false << false;
3866 QTest::newRow("pen width: 1.5, antialiasing: false") << qreal(1.5) << false << false;
3867 QTest::newRow("pen width: 2.0, antialiasing: false") << qreal(2.0) << false << false;
3868 QTest::newRow("pen width: 3.0, antialiasing: false") << qreal(3.0) << false << false;
3870 // changed() connected
3871 QTest::newRow("pen width: 0.0, antialiasing: false, changed") << qreal(0.0) << false << true;
3872 QTest::newRow("pen width: 1.5, antialiasing: true, changed") << qreal(1.5) << true << true;
3873 QTest::newRow("pen width: 2.0, antialiasing: false, changed") << qreal(2.0) << false << true;
3874 QTest::newRow("pen width: 3.0, antialiasing: true, changed") << qreal(3.0) << true << true;
3877 void tst_QGraphicsView::update2()
3879 QFETCH(qreal, penWidth);
3880 QFETCH(bool, antialiasing);
3881 QFETCH(bool, changedConnected);
3883 // Create a rect item.
3884 const QRectF rawItemRect(-50.4, -50.3, 100.2, 100.1);
3885 CountPaintItem *rect = new CountPaintItem(rawItemRect);
3887 pen.setWidthF(penWidth);
3890 // Add item to a scene.
3891 QGraphicsScene scene(-100, -100, 200, 200);
3892 if (changedConnected)
3893 QObject::connect(&scene, SIGNAL(changed(QList<QRectF>)), this, SLOT(dummySlot()));
3895 scene.addItem(rect);
3897 // Create a view on the scene.
3898 CustomView view(&scene);
3899 view.setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing, !antialiasing);
3900 view.setRenderHint(QPainter::Antialiasing, antialiasing);
3901 view.setFrameStyle(0);
3902 view.resize(200, 200);
3904 qApp->setActiveWindow(&view);
3905 QVERIFY(QTest::qWaitForWindowActive(&view));
3906 QTRY_VERIFY(rect->numPaints > 0);
3908 // Calculate expected update region for the rect.
3909 QRectF expectedItemBoundingRect = rawItemRect;
3910 const qreal halfPenWidth = penWidth / qreal(2.0);
3911 expectedItemBoundingRect.adjust(-halfPenWidth, -halfPenWidth, halfPenWidth, halfPenWidth);
3912 QCOMPARE(rect->boundingRect(), expectedItemBoundingRect);
3914 QRect expectedItemDeviceBoundingRect = rect->deviceTransform(view.viewportTransform())
3915 .mapRect(expectedItemBoundingRect).toAlignedRect();
3917 expectedItemDeviceBoundingRect.adjust(-2, -2, 2, 2);
3919 expectedItemDeviceBoundingRect.adjust(-1, -1, 1, 1);
3920 const QRegion expectedUpdateRegion(expectedItemDeviceBoundingRect);
3923 rect->numPaints = 0;
3924 view.lastUpdateRegions.clear();
3925 view.painted = false;
3928 QTRY_VERIFY(view.painted);
3930 #ifndef Q_OS_MAC //cocoa doesn't support drawing regions
3931 QTRY_VERIFY(view.painted);
3932 QCOMPARE(view.lastUpdateRegions.size(), 1);
3933 QCOMPARE(view.lastUpdateRegions.at(0), expectedUpdateRegion);
3937 void tst_QGraphicsView::update_ancestorClipsChildrenToShape()
3939 QGraphicsScene scene(-150, -150, 300, 300);
3944 +------------------+
3946 | +--------------+ |
3951 | +--------------+ |
3952 +------------------+
3954 ... where both the parent and the grand parent clips children to shape.
3956 QApplication::processEvents(); // Get rid of pending update.
3958 QGraphicsRectItem *grandParent = static_cast<QGraphicsRectItem *>(scene.addRect(0, 0, 50, 50));
3959 grandParent->setBrush(Qt::black);
3960 grandParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
3962 QGraphicsRectItem *parent = static_cast<QGraphicsRectItem *>(scene.addRect(-50, -50, 100, 100));
3963 parent->setBrush(QColor(0, 0, 255, 125));
3964 parent->setParentItem(grandParent);
3965 parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
3967 QGraphicsRectItem *child = static_cast<QGraphicsRectItem *>(scene.addRect(-100, -100, 200, 200));
3968 child->setBrush(QColor(255, 0, 0, 125));
3969 child->setParentItem(parent);
3971 CustomView view(&scene);
3973 qApp->setActiveWindow(&view);
3974 QVERIFY(QTest::qWaitForWindowActive(&view));
3975 QTRY_VERIFY(view.painted);
3977 view.lastUpdateRegions.clear();
3978 view.painted = false;
3980 // Call child->update() and make sure the updated area is within the ancestors' clip.
3981 QRectF expected = child->deviceTransform(view.viewportTransform()).mapRect(child->boundingRect());
3982 expected &= grandParent->deviceTransform(view.viewportTransform()).mapRect(grandParent->boundingRect());
3985 QTRY_VERIFY(view.painted);
3987 #ifndef Q_OS_MAC //cocoa doesn't support drawing regions
3988 QTRY_VERIFY(view.painted);
3989 QCOMPARE(view.lastUpdateRegions.size(), 1);
3990 QCOMPARE(view.lastUpdateRegions.at(0), QRegion(expected.toAlignedRect()));
3994 void tst_QGraphicsView::update_ancestorClipsChildrenToShape2()
3996 QGraphicsScene scene(-150, -150, 300, 300);
4001 +------------------+
4003 | +--------------+ |
4008 | +--------------+ |
4009 +------------------+
4011 ... where the parent has no contents and clips the child to shape.
4013 QApplication::processEvents(); // Get rid of pending update.
4015 QGraphicsRectItem *parent = static_cast<QGraphicsRectItem *>(scene.addRect(-50, -50, 100, 100));
4016 parent->setBrush(QColor(0, 0, 255, 125));
4017 parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
4018 parent->setFlag(QGraphicsItem::ItemHasNoContents);
4020 QGraphicsRectItem *child = static_cast<QGraphicsRectItem *>(scene.addRect(-100, -100, 200, 200));
4021 child->setBrush(QColor(255, 0, 0, 125));
4022 child->setParentItem(parent);
4024 CustomView view(&scene);
4026 qApp->setActiveWindow(&view);
4027 QVERIFY(QTest::qWaitForWindowActive(&view));
4028 QTRY_VERIFY(view.painted);
4030 view.lastUpdateRegions.clear();
4031 view.painted = false;
4033 // Call child->update() and make sure the updated area is within its parent's clip.
4034 QRectF expected = child->deviceTransform(view.viewportTransform()).mapRect(child->boundingRect());
4035 expected &= parent->deviceTransform(view.viewportTransform()).mapRect(parent->boundingRect());
4038 QTRY_VERIFY(view.painted);
4040 #ifndef Q_OS_MAC //cocoa doesn't support drawing regions
4041 QTRY_VERIFY(view.painted);
4042 QCOMPARE(view.lastUpdateRegions.size(), 1);
4043 QCOMPARE(view.lastUpdateRegions.at(0), QRegion(expected.toAlignedRect()));
4048 view.lastUpdateRegions.clear();
4049 view.painted = false;
4051 // Invalidate the parent's geometry and trigger an update.
4052 // The update area should be clipped to the parent's bounding rect for 'normal' items,
4053 // but in this case the item has no contents (ItemHasNoContents) and its geometry
4054 // is invalidated, which means we cannot clip the child update. So, the expected
4055 // area is exactly the same as the child's bounding rect (adjusted for antialiasing).
4056 parent->setRect(parent->rect().adjusted(-10, -10, -10, -10));
4057 expected = child->deviceTransform(view.viewportTransform()).mapRect(child->boundingRect());
4058 expected.adjust(-2, -2, 2, 2); // Antialiasing
4060 #ifndef Q_OS_MAC //cocoa doesn't support drawing regions
4061 QTRY_VERIFY(view.painted);
4062 QCOMPARE(view.lastUpdateRegions.size(), 1);
4063 QCOMPARE(view.lastUpdateRegions.at(0), QRegion(expected.toAlignedRect()));
4067 class FocusItem : public QGraphicsRectItem
4070 FocusItem() : QGraphicsRectItem(0, 0, 20, 20) {
4071 m_viewHasIMEnabledInFocusInEvent = false;
4074 void focusInEvent(QFocusEvent * /* event */)
4076 QGraphicsView *view = scene()->views().first();
4077 m_viewHasIMEnabledInFocusInEvent = view->testAttribute(Qt::WA_InputMethodEnabled);
4080 bool m_viewHasIMEnabledInFocusInEvent;
4083 void tst_QGraphicsView::inputMethodSensitivity()
4085 QGraphicsScene scene;
4086 QGraphicsView view(&scene);
4088 QApplication::setActiveWindow(&view);
4089 QVERIFY(QTest::qWaitForWindowActive(&view));
4090 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
4092 FocusItem *item = new FocusItem;
4094 view.setAttribute(Qt::WA_InputMethodEnabled, true);
4096 scene.addItem(item);
4097 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
4099 scene.removeItem(item);
4100 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
4102 item->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
4103 scene.addItem(item);
4104 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
4106 scene.removeItem(item);
4107 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
4109 scene.addItem(item);
4110 scene.setFocusItem(item);
4111 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
4113 scene.removeItem(item);
4114 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
4116 item->setFlag(QGraphicsItem::ItemIsFocusable);
4117 scene.addItem(item);
4118 scene.setFocusItem(item);
4119 QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
4120 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true);
4121 QCOMPARE(item->m_viewHasIMEnabledInFocusInEvent, true);
4123 item->setFlag(QGraphicsItem::ItemAcceptsInputMethod, false);
4124 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
4126 item->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
4127 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true);
4129 // introduce another item that is focusable but does not accept input methods
4130 FocusItem *item2 = new FocusItem;
4131 item2->setFlag(QGraphicsItem::ItemIsFocusable);
4132 scene.addItem(item2);
4133 scene.setFocusItem(item2);
4134 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
4135 QCOMPARE(item2->m_viewHasIMEnabledInFocusInEvent, false);
4136 QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item2));
4138 scene.setFocusItem(item);
4139 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true);
4140 QCOMPARE(item->m_viewHasIMEnabledInFocusInEvent, true);
4141 QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
4144 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
4145 QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
4147 view.setScene(&scene);
4148 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true);
4149 QCOMPARE(item->m_viewHasIMEnabledInFocusInEvent, true);
4150 QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
4152 scene.setFocusItem(item2);
4153 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
4154 QCOMPARE(item2->m_viewHasIMEnabledInFocusInEvent, false);
4155 QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item2));
4158 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
4159 QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item2));
4161 scene.setFocusItem(item);
4162 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
4163 QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
4165 view.setScene(&scene);
4166 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true);
4167 QCOMPARE(item->m_viewHasIMEnabledInFocusInEvent, true);
4168 QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
4171 void tst_QGraphicsView::inputContextReset()
4173 PlatformInputContext inputContext;
4174 QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
4175 inputMethodPrivate->testContext = &inputContext;
4177 QGraphicsScene scene;
4178 QGraphicsView view(&scene);
4179 QVERIFY(view.testAttribute(Qt::WA_InputMethodEnabled));
4182 QApplication::setActiveWindow(&view);
4183 QVERIFY(QTest::qWaitForWindowActive(&view));
4184 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
4186 QGraphicsItem *item1 = new QGraphicsRectItem;
4187 item1->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemAcceptsInputMethod);
4189 inputContext.m_resetCallCount = 0;
4190 inputContext.m_commitCallCount = 0;
4191 scene.addItem(item1);
4192 QCOMPARE(inputContext.m_resetCallCount, 0);
4193 QCOMPARE(inputContext.m_commitCallCount, 0);
4195 scene.setFocusItem(item1);
4196 QCOMPARE(scene.focusItem(), (QGraphicsItem *)item1);
4197 QVERIFY(view.testAttribute(Qt::WA_InputMethodEnabled));
4198 QCOMPARE(inputContext.m_resetCallCount, 0);
4199 QCOMPARE(inputContext.m_commitCallCount, 0);
4201 scene.setFocusItem(0);
4202 // the input context is reset twice, once because an item has lost focus and again because
4203 // the Qt::WA_InputMethodEnabled flag is cleared because no item has focus.
4204 // QEXPECT_FAIL("", "QTBUG-22454", Abort);
4205 QCOMPARE(inputContext.m_resetCallCount + inputContext.m_commitCallCount, 2);
4207 // introduce another item that is focusable but does not accept input methods
4208 QGraphicsItem *item2 = new QGraphicsRectItem;
4209 item2->setFlags(QGraphicsItem::ItemIsFocusable);
4210 scene.addItem(item2);
4212 inputContext.m_resetCallCount = 0;
4213 inputContext.m_commitCallCount = 0;
4214 scene.setFocusItem(item2);
4215 QCOMPARE(inputContext.m_resetCallCount, 0);
4216 QCOMPARE(inputContext.m_commitCallCount, 0);
4218 scene.setFocusItem(item1);
4219 QCOMPARE(inputContext.m_resetCallCount, 0);
4220 QCOMPARE(inputContext.m_commitCallCount, 0);
4222 // test changing between between items that accept input methods.
4223 item2->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemAcceptsInputMethod);
4224 scene.setFocusItem(item2);
4225 QCOMPARE(inputContext.m_resetCallCount + inputContext.m_commitCallCount, 1);
4228 void tst_QGraphicsView::indirectPainting()
4230 class MyScene : public QGraphicsScene
4232 MyScene() : QGraphicsScene(), drawCount(0) {}
4233 void drawItems(QPainter *, int, QGraphicsItem **, const QStyleOptionGraphicsItem *, QWidget *)
4239 QGraphicsItem *item = scene.addRect(0, 0, 50, 50);
4241 QGraphicsView view(&scene);
4242 view.setOptimizationFlag(QGraphicsView::IndirectPainting);
4244 QVERIFY(QTest::qWaitForWindowExposed(&view));
4247 scene.drawCount = 0;
4248 item->setPos(20, 20);
4249 QApplication::processEvents();
4250 QTRY_VERIFY(scene.drawCount > 0);
4253 void tst_QGraphicsView::compositionModeInDrawBackground()
4255 class MyView : public QGraphicsView
4257 MyView(QGraphicsScene *scene) : QGraphicsView(scene),
4258 painted(false), compositionMode(QPainter::CompositionMode_SourceOver) {}
4260 QPainter::CompositionMode compositionMode;
4261 void drawBackground(QPainter *painter, const QRectF &)
4263 compositionMode = painter->compositionMode();
4268 QGraphicsScene dummy;
4269 MyView view(&dummy);
4271 QVERIFY(QTest::qWaitForWindowExposed(&view));
4273 // Make sure the painter's composition mode is SourceOver in drawBackground.
4274 QTRY_VERIFY(view.painted);
4275 QCOMPARE(view.compositionMode, QPainter::CompositionMode_SourceOver);
4277 view.painted = false;
4278 view.setCacheMode(QGraphicsView::CacheBackground);
4279 view.viewport()->update();
4281 // Make sure the painter's composition mode is SourceOver in drawBackground
4282 // with background cache enabled.
4283 QTRY_VERIFY(view.painted);
4284 QCOMPARE(view.compositionMode, QPainter::CompositionMode_SourceOver);
4286 void tst_QGraphicsView::task253415_reconnectUpdateSceneOnSceneChanged()
4289 QGraphicsView dummyView;
4290 view.setWindowFlags(view.windowFlags() | Qt::WindowStaysOnTopHint);
4291 view.resize(200, 200);
4293 QGraphicsScene scene1;
4294 QObject::connect(&scene1, SIGNAL(changed(QList<QRectF>)), &dummyView, SLOT(updateScene(QList<QRectF>)));
4295 view.setScene(&scene1);
4299 QGraphicsScene scene2;
4300 QObject::connect(&scene2, SIGNAL(changed(QList<QRectF>)), &dummyView, SLOT(updateScene(QList<QRectF>)));
4301 view.setScene(&scene2);
4305 bool wasConnected2 = QObject::disconnect(&scene2, SIGNAL(changed(QList<QRectF>)), &view, 0);
4306 QVERIFY(wasConnected2);
4309 void tst_QGraphicsView::task255529_transformationAnchorMouseAndViewportMargins()
4311 #if defined(Q_OS_WINCE)
4312 QSKIP("Qt/CE does not implement mouse tracking at this point");
4314 QGraphicsScene scene(-100, -100, 200, 200);
4315 scene.addRect(QRectF(-50, -50, 100, 100), QPen(Qt::black), QBrush(Qt::blue));
4317 class VpGraphicsView: public QGraphicsView
4320 VpGraphicsView(QGraphicsScene *scene, QWidget *parent=0)
4321 : QGraphicsView(scene, parent)
4323 setViewportMargins(8, 16, 12, 20);
4324 setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
4325 setMouseTracking(true);
4329 VpGraphicsView view(&scene);
4330 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
4332 qApp->setActiveWindow(&view);
4333 QVERIFY(QTest::qWaitForWindowActive(&view));
4334 QPoint mouseViewPos(20, 20);
4335 sendMouseMove(view.viewport(), mouseViewPos);
4337 QPointF mouseScenePos = view.mapToScene(mouseViewPos);
4338 view.setTransform(QTransform().scale(5, 5).rotate(5, Qt::ZAxis), true);
4340 QPointF newMouseScenePos = view.mapToScene(mouseViewPos);
4344 const qreal dx = qAbs(newMouseScenePos.x() - mouseScenePos.x());
4345 const qreal dy = qAbs(newMouseScenePos.y() - mouseScenePos.y());
4346 const QByteArray message = QString::fromLatin1("QTBUG-22455, distance: dx=%1, dy=%2 slack=%3 (%4).").
4347 arg(dx).arg(dy).arg(slack).arg(qApp->style()->metaObject()->className()).toLocal8Bit();
4348 // This is highly unstable (observed to pass on Windows and some Linux configurations).
4350 QEXPECT_FAIL("", message.constData(), Abort);
4352 QVERIFY2(dx < slack && dy < slack, message.constData());
4355 void tst_QGraphicsView::task259503_scrollingArtifacts()
4357 QGraphicsScene scene(0, 0, 800, 600);
4359 QGraphicsRectItem card;
4360 card.setRect(0, 0, 50, 50);
4361 card.setPen(QPen(Qt::darkRed));
4362 card.setBrush(QBrush(Qt::cyan));
4363 card.setZValue(2.0);
4364 card.setPos(300, 300);
4365 scene.addItem(&card);
4367 class SAGraphicsView: public QGraphicsView
4370 SAGraphicsView(QGraphicsScene *scene)
4371 : QGraphicsView(scene)
4372 , itSTimeToTest(false)
4374 setViewportUpdateMode( QGraphicsView::MinimalViewportUpdate );
4375 resize(QSize(640, 480));
4378 QRegion updateRegion;
4381 void paintEvent(QPaintEvent *event)
4383 QGraphicsView::paintEvent(event);
4387 QEXPECT_FAIL("", "QTBUG-24296", Continue);
4388 QCOMPARE(event->region(), updateRegion);
4393 SAGraphicsView view(&scene);
4395 QVERIFY(QTest::qWaitForWindowExposed(&view));
4397 int hsbValue = view.horizontalScrollBar()->value();
4398 view.horizontalScrollBar()->setValue(hsbValue / 2);
4400 view.horizontalScrollBar()->setValue(0);
4403 QRect itemDeviceBoundingRect = card.deviceTransform(view.viewportTransform()).mapRect(card.boundingRect()).toRect();
4404 itemDeviceBoundingRect.adjust(-2, -2, 2, 2);
4405 view.updateRegion = itemDeviceBoundingRect;
4406 view.updateRegion += itemDeviceBoundingRect.translated(-100, 0);
4407 view.itSTimeToTest = true;
4408 card.setPos(200, 300);
4412 void tst_QGraphicsView::QTBUG_4151_clipAndIgnore_data()
4414 QTest::addColumn<bool>("clip");
4415 QTest::addColumn<bool>("ignoreTransformations");
4416 QTest::addColumn<int>("numItems");
4418 QTest::newRow("none") << false << false << 3;
4419 QTest::newRow("clip") << true << false << 3;
4420 QTest::newRow("ignore") << false << true << 3;
4421 QTest::newRow("clip+ignore") << true << true << 3;
4424 void tst_QGraphicsView::QTBUG_4151_clipAndIgnore()
4427 QFETCH(bool, ignoreTransformations);
4428 QFETCH(int, numItems);
4430 QGraphicsScene scene;
4432 QGraphicsRectItem *parent = new QGraphicsRectItem(QRectF(0, 0, 50, 50), 0);
4433 QGraphicsRectItem *child = new QGraphicsRectItem(QRectF(-10, -10, 40, 40), parent);
4434 QGraphicsRectItem *ignore = new QGraphicsRectItem(QRectF(60, 60, 50, 50), 0);
4437 parent->setFlags(QGraphicsItem::ItemClipsChildrenToShape);
4438 if (ignoreTransformations)
4439 ignore->setFlag(QGraphicsItem::ItemIgnoresTransformations);
4441 parent->setBrush(Qt::red);
4442 child->setBrush(QColor(0, 0, 255, 128));
4443 ignore->setBrush(Qt::green);
4445 scene.addItem(parent);
4446 scene.addItem(ignore);
4448 QGraphicsView view(&scene);
4449 view.setFrameStyle(0);
4450 view.resize(75, 75);
4452 view.activateWindow();
4453 QVERIFY(QTest::qWaitForWindowActive(&view));
4454 QCOMPARE(QApplication::activeWindow(), (QWidget *)&view);
4456 QCOMPARE(view.items(view.rect()).size(), numItems);
4459 void tst_QGraphicsView::QTBUG_5859_exposedRect()
4461 class CustomScene : public QGraphicsScene
4464 CustomScene(const QRectF &rect) : QGraphicsScene(rect) { }
4465 void drawBackground(QPainter * /* painter */, const QRectF &rect)
4466 { lastBackgroundExposedRect = rect; }
4467 QRectF lastBackgroundExposedRect;
4470 class CustomRectItem : public QGraphicsRectItem
4473 CustomRectItem(const QRectF &rect) : QGraphicsRectItem(rect)
4474 { setFlag(QGraphicsItem::ItemUsesExtendedStyleOption); }
4475 void paint(QPainter * /* painter */, const QStyleOptionGraphicsItem *option, QWidget * /* widget */ = 0)
4476 { lastExposedRect = option->exposedRect; }
4477 QRectF lastExposedRect;
4480 CustomScene scene(QRectF(0,0,50,50));
4482 CustomRectItem item(scene.sceneRect());
4484 scene.addItem(&item);
4486 QGraphicsView view(&scene);
4487 view.scale(4.15, 4.15);
4489 qApp->setActiveWindow(&view);
4490 QVERIFY(QTest::qWaitForWindowActive(&view));
4492 view.viewport()->repaint(10,10,20,20);
4493 QApplication::processEvents();
4495 QCOMPARE(item.lastExposedRect, scene.lastBackgroundExposedRect);
4498 #ifndef QTEST_NO_CURSOR
4499 void tst_QGraphicsView::QTBUG_7438_cursor()
4501 QGraphicsScene scene;
4502 QGraphicsItem *item = scene.addRect(QRectF(-10, -10, 20, 20));
4503 item->setFlag(QGraphicsItem::ItemIsMovable);
4505 QGraphicsView view(&scene);
4506 view.setFixedSize(400, 400);
4508 QVERIFY(QTest::qWaitForWindowExposed(&view));
4510 QCOMPARE(view.viewport()->cursor().shape(), QCursor().shape());
4511 view.viewport()->setCursor(Qt::PointingHandCursor);
4512 QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
4513 sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
4514 QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
4515 sendMousePress(view.viewport(), view.mapFromScene(0, 0));
4516 QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
4517 sendMouseRelease(view.viewport(), view.mapFromScene(0, 0));
4518 QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
4522 class GraphicsItemWithHover : public QGraphicsRectItem
4525 GraphicsItemWithHover()
4526 : receivedEnterEvent(false), receivedLeaveEvent(false),
4527 enterWidget(0), leaveWidget(0)
4529 setRect(0, 0, 100, 100);
4530 setAcceptHoverEvents(true);
4533 bool sceneEvent(QEvent *event)
4535 if (event->type() == QEvent::GraphicsSceneHoverEnter) {
4536 receivedEnterEvent = true;
4537 enterWidget = static_cast<QGraphicsSceneHoverEvent *>(event)->widget();
4538 } else if (event->type() == QEvent::GraphicsSceneHoverLeave) {
4539 receivedLeaveEvent = true;
4540 leaveWidget = static_cast<QGraphicsSceneHoverEvent *>(event)->widget();
4542 return QGraphicsRectItem::sceneEvent(event);
4545 bool receivedEnterEvent;
4546 bool receivedLeaveEvent;
4547 QWidget *enterWidget;
4548 QWidget *leaveWidget;
4551 void tst_QGraphicsView::hoverLeave()
4553 QGraphicsScene scene;
4554 QGraphicsView view(&scene);
4555 GraphicsItemWithHover *item = new GraphicsItemWithHover;
4556 scene.addItem(item);
4558 // move the cursor out of the way
4559 QCursor::setPos(1,1);
4562 qApp->setActiveWindow(&view);
4563 QVERIFY(QTest::qWaitForWindowActive(&view));
4565 QPoint pos = view.viewport()->mapToGlobal(view.mapFromScene(item->mapToScene(10, 10)));
4566 QCursor::setPos(pos);
4568 QVERIFY(item->receivedEnterEvent);
4569 QCOMPARE(item->enterWidget, view.viewport());
4571 QCursor::setPos(1,1);
4574 QEXPECT_FAIL("", "QTBUG-26274 - behaviour regression", Abort);
4576 QVERIFY(item->receivedLeaveEvent);
4577 QCOMPARE(item->leaveWidget, view.viewport());
4580 class IMItem : public QGraphicsRectItem
4583 IMItem(QGraphicsItem *parent = 0):
4584 QGraphicsRectItem(QRectF(0, 0, 20, 20), parent)
4586 setFlag(QGraphicsItem::ItemIsFocusable, true);
4587 setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
4590 QVariant inputMethodQuery(Qt::InputMethodQuery) const
4598 QRectF IMItem::mf(1.5, 1.6, 10, 10);
4600 void tst_QGraphicsView::QTBUG_16063_microFocusRect()
4602 QGraphicsScene scene;
4603 IMItem *item = new IMItem();
4604 scene.addItem(item);
4606 QGraphicsView view(&scene);
4608 view.setFixedSize(40, 40);
4610 QVERIFY(QTest::qWaitForWindowActive(&view));
4612 scene.setFocusItem(item);
4614 QRectF mfv = view.inputMethodQuery(Qt::ImMicroFocus).toRectF();
4615 QCOMPARE(mfv, IMItem::mf.translated(-view.mapToScene(view.sceneRect().toRect()).boundingRect().topLeft()));
4618 QTEST_MAIN(tst_QGraphicsView)
4619 #include "tst_qgraphicsview.moc"