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));
545 item->setPen(QPen(Qt::black, 0));
547 view.setScene(&scene);
549 QCOMPARE(view.sceneRect(), QRectF(-100, -100, 100, 100));
550 item->moveBy(-100, -100);
551 QCOMPARE(view.sceneRect(), QRectF(-200, -200, 200, 200));
552 item->moveBy(100, 100);
553 QCOMPARE(view.sceneRect(), QRectF(-200, -200, 200, 200));
556 view.setSceneRect(QRectF());
557 QCOMPARE(view.sceneRect(), QRectF());
560 void tst_QGraphicsView::sceneRect_growing()
564 QGraphicsScene scene;
565 for (int i = 0; i < 100; ++i)
566 scene.addText(QString("(0, %1)").arg((i - 50) * 20))->setPos(0, (i - 50) * 20);
568 QGraphicsView view(&scene, &toplevel);
569 view.setFixedSize(200, 200);
573 scene.setSceneRect(-size, -size, size * 2, size * 2);
574 QCOMPARE(view.sceneRect(), scene.sceneRect());
578 QPointF topLeft = view.mapToScene(0, 0);
580 for (int i = 0; i < 5; ++i) {
582 scene.setSceneRect(-size, -size, size * 2, size * 2);
584 QApplication::processEvents();
586 QCOMPARE(view.sceneRect(), scene.sceneRect());
587 QCOMPARE(view.mapToScene(0, 0), topLeft);
588 view.setSceneRect(-size, -size, size * 2, size * 2);
589 QCOMPARE(view.mapToScene(0, 0), topLeft);
590 view.setSceneRect(QRectF());
594 void tst_QGraphicsView::setSceneRect()
596 QRectF rect1(-100, -100, 200, 200);
597 QRectF rect2(-300, -300, 150, 150);
599 QGraphicsScene scene;
600 QGraphicsView view(&scene);
602 scene.setSceneRect(rect1);
603 QCOMPARE(scene.sceneRect(), rect1);
604 QCOMPARE(view.sceneRect(), rect1);
606 scene.setSceneRect(rect2);
607 QCOMPARE(scene.sceneRect(), rect2);
608 QCOMPARE(view.sceneRect(), rect2);
610 view.setSceneRect(rect1);
611 QCOMPARE(scene.sceneRect(), rect2);
612 QCOMPARE(view.sceneRect(), rect1);
614 view.setSceneRect(rect2);
615 QCOMPARE(scene.sceneRect(), rect2);
616 QCOMPARE(view.sceneRect(), rect2);
618 scene.setSceneRect(rect1);
619 QCOMPARE(scene.sceneRect(), rect1);
620 QCOMPARE(view.sceneRect(), rect2);
622 // extreme transformations will max out the scrollbars' ranges.
623 view.setSceneRect(-2000000, -2000000, 4000000, 4000000);
624 view.scale(9000, 9000);
625 QCOMPARE(view.horizontalScrollBar()->minimum(), INT_MIN);
626 QCOMPARE(view.horizontalScrollBar()->maximum(), INT_MAX);
627 QCOMPARE(view.verticalScrollBar()->minimum(), INT_MIN);
628 QCOMPARE(view.verticalScrollBar()->maximum(), INT_MAX);
631 void tst_QGraphicsView::viewport()
633 QGraphicsScene scene;
634 scene.addText("GraphicsView");
636 QGraphicsView view(&scene);
637 QVERIFY(view.viewport() != 0);
642 QPointer<QWidget> widget = new QWidget;
643 view.setViewport(widget);
644 QCOMPARE(view.viewport(), (QWidget *)widget);
650 QVERIFY(widget.isNull());
651 QVERIFY(view.viewport() != 0);
652 QVERIFY(view.viewport() != widget);
658 void tst_QGraphicsView::dragMode_scrollHand()
660 for (int j = 0; j < 2; ++j) {
662 QCOMPARE(view.dragMode(), QGraphicsView::NoDrag);
664 view.setSceneRect(-1000, -1000, 2000, 2000);
665 view.setFixedSize(100, 100);
668 QVERIFY(QTest::qWaitForWindowExposed(&view));
669 QApplication::processEvents();
671 view.setInteractive(j ? false : true);
673 QGraphicsScene scene;
674 scene.addRect(QRectF(-100, -100, 5, 5));
675 scene.addRect(QRectF(95, -100, 5, 5));
676 scene.addRect(QRectF(95, 95, 5, 5));
677 QGraphicsItem *item = scene.addRect(QRectF(-100, 95, 5, 5));
678 item->setFlag(QGraphicsItem::ItemIsSelectable);
679 item->setSelected(true);
680 QVERIFY(item->isSelected());
681 QVERIFY(!view.scene());
683 view.setDragMode(QGraphicsView::ScrollHandDrag);
685 for (int i = 0; i < 2; ++i) {
687 #ifndef QTEST_NO_CURSOR
688 Qt::CursorShape cursorShape = view.viewport()->cursor().shape();
690 int horizontalScrollBarValue = view.horizontalScrollBar()->value();
691 int verticalScrollBarValue = view.verticalScrollBar()->value();
694 QMouseEvent event(QEvent::MouseButtonPress,
695 view.viewport()->rect().center(),
696 Qt::LeftButton, Qt::LeftButton, 0);
697 event.setAccepted(true);
698 QApplication::sendEvent(view.viewport(), &event);
699 QVERIFY(event.isAccepted());
701 QApplication::processEvents();
703 QTRY_VERIFY(item->isSelected());
705 for (int k = 0; k < 4; ++k) {
706 #ifndef QTEST_NO_CURSOR
707 QCOMPARE(view.viewport()->cursor().shape(), Qt::ClosedHandCursor);
711 QMouseEvent event(QEvent::MouseMove,
712 view.viewport()->rect().center() + QPoint(10, 0),
713 Qt::LeftButton, Qt::LeftButton, 0);
714 event.setAccepted(true);
715 QApplication::sendEvent(view.viewport(), &event);
716 QVERIFY(event.isAccepted());
718 QVERIFY(item->isSelected());
719 QCOMPARE(view.horizontalScrollBar()->value(), horizontalScrollBarValue - 10);
720 QCOMPARE(view.verticalScrollBar()->value(), verticalScrollBarValue);
723 QMouseEvent event(QEvent::MouseMove,
724 view.viewport()->rect().center() + QPoint(10, 10),
725 Qt::LeftButton, Qt::LeftButton, 0);
726 event.setAccepted(true);
727 QApplication::sendEvent(view.viewport(), &event);
728 QVERIFY(event.isAccepted());
730 QVERIFY(item->isSelected());
731 QCOMPARE(view.horizontalScrollBar()->value(), horizontalScrollBarValue - 10);
732 QCOMPARE(view.verticalScrollBar()->value(), verticalScrollBarValue - 10);
737 QMouseEvent event(QEvent::MouseButtonRelease,
738 view.viewport()->rect().center() + QPoint(10, 10),
739 Qt::LeftButton, Qt::LeftButton, 0);
740 event.setAccepted(true);
741 QApplication::sendEvent(view.viewport(), &event);
742 QVERIFY(event.isAccepted());
744 QApplication::processEvents();
746 QTRY_VERIFY(item->isSelected());
747 QCOMPARE(view.horizontalScrollBar()->value(), horizontalScrollBarValue - 10);
748 QCOMPARE(view.verticalScrollBar()->value(), verticalScrollBarValue - 10);
749 #ifndef QTEST_NO_CURSOR
750 QCOMPARE(view.viewport()->cursor().shape(), cursorShape);
753 // Check that items are not unselected because of a scroll hand drag.
754 QVERIFY(item->isSelected());
756 // Check that a click will still unselect the item.
759 QMouseEvent event(QEvent::MouseButtonPress,
760 view.viewport()->rect().center() + QPoint(10, 10),
761 Qt::LeftButton, Qt::LeftButton, 0);
762 QApplication::sendEvent(view.viewport(), &event);
766 QMouseEvent event(QEvent::MouseButtonRelease,
767 view.viewport()->rect().center() + QPoint(10, 10),
768 Qt::LeftButton, Qt::LeftButton, 0);
769 QApplication::sendEvent(view.viewport(), &event);
772 if (view.isInteractive()) {
774 QVERIFY(!item->isSelected());
775 item->setSelected(true);
777 QVERIFY(item->isSelected());
780 QVERIFY(item->isSelected());
783 view.setScene(&scene);
788 void tst_QGraphicsView::dragMode_rubberBand()
791 QCOMPARE(view.dragMode(), QGraphicsView::NoDrag);
793 view.setSceneRect(-1000, -1000, 2000, 2000);
796 QGraphicsScene scene;
797 scene.addRect(QRectF(-100, -100, 25, 25))->setFlag(QGraphicsItem::ItemIsSelectable);
798 scene.addRect(QRectF(75, -100, 25, 25))->setFlag(QGraphicsItem::ItemIsSelectable);
799 scene.addRect(QRectF(75, 75, 25, 25))->setFlag(QGraphicsItem::ItemIsSelectable);
800 scene.addRect(QRectF(-100, 75, 25, 25))->setFlag(QGraphicsItem::ItemIsSelectable);
802 view.setDragMode(QGraphicsView::RubberBandDrag);
804 QVERIFY(QTest::qWaitForWindowExposed(&view));
805 QApplication::processEvents();
807 for (int i = 0; i < 2; ++i) {
809 #ifndef QTEST_NO_CURSOR
810 Qt::CursorShape cursorShape = view.viewport()->cursor().shape();
812 int horizontalScrollBarValue = view.horizontalScrollBar()->value();
813 int verticalScrollBarValue = view.verticalScrollBar()->value();
816 QMouseEvent event(QEvent::MouseButtonPress,
817 view.viewport()->rect().center(),
818 Qt::LeftButton, Qt::LeftButton, 0);
819 event.setAccepted(true);
820 QApplication::sendEvent(view.viewport(), &event);
821 QVERIFY(event.isAccepted());
823 #ifndef QTEST_NO_CURSOR
824 QCOMPARE(view.viewport()->cursor().shape(), cursorShape);
827 QApplication::processEvents();
831 QMouseEvent event(QEvent::MouseMove,
832 view.viewport()->rect().center() + QPoint(100, 0),
833 Qt::LeftButton, Qt::LeftButton, 0);
834 event.setAccepted(true);
835 QApplication::sendEvent(view.viewport(), &event);
836 QVERIFY(event.isAccepted());
838 QCOMPARE(view.horizontalScrollBar()->value(), horizontalScrollBarValue);
839 QCOMPARE(view.verticalScrollBar()->value(), verticalScrollBarValue);
841 // We don't use QRubberBand as of 4.3; the band is drawn internally.
842 QVERIFY(!qFindChild<QRubberBand *>(&view));
848 QMouseEvent event(QEvent::MouseMove,
849 view.viewport()->rect().center() + QPoint(100, 100),
850 Qt::LeftButton, Qt::LeftButton, 0);
851 event.setAccepted(true);
852 QApplication::sendEvent(view.viewport(), &event);
853 QVERIFY(event.isAccepted());
855 QCOMPARE(view.horizontalScrollBar()->value(), horizontalScrollBarValue);
856 QCOMPARE(view.verticalScrollBar()->value(), verticalScrollBarValue);
862 QMouseEvent event(QEvent::MouseButtonRelease,
863 view.viewport()->rect().center() + QPoint(100, 100),
864 Qt::LeftButton, Qt::LeftButton, 0);
865 event.setAccepted(true);
866 QApplication::sendEvent(view.viewport(), &event);
867 QVERIFY(event.isAccepted());
869 QCOMPARE(view.horizontalScrollBar()->value(), horizontalScrollBarValue);
870 QCOMPARE(view.verticalScrollBar()->value(), verticalScrollBarValue);
871 #ifndef QTEST_NO_CURSOR
872 QCOMPARE(view.viewport()->cursor().shape(), cursorShape);
878 QCOMPARE(scene.selectedItems().size(), 1);
880 view.setScene(&scene);
885 void tst_QGraphicsView::rubberBandSelectionMode()
889 QGraphicsScene scene;
890 QGraphicsRectItem *rect = scene.addRect(QRectF(10, 10, 80, 80));
891 rect->setFlag(QGraphicsItem::ItemIsSelectable);
893 QGraphicsView view(&scene, &toplevel);
894 QCOMPARE(view.rubberBandSelectionMode(), Qt::IntersectsItemShape);
895 view.setDragMode(QGraphicsView::RubberBandDrag);
896 view.resize(120, 120);
899 // Disable mouse tracking to prevent the window system from sending mouse
900 // move events to the viewport while we are synthesizing events. If
901 // QGraphicsView gets a mouse move event with no buttons down, it'll
902 // terminate the rubber band.
903 view.viewport()->setMouseTracking(false);
905 QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>());
906 sendMousePress(view.viewport(), QPoint(), Qt::LeftButton);
907 sendMouseMove(view.viewport(), view.viewport()->rect().center(),
908 Qt::LeftButton, Qt::LeftButton);
909 QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>() << rect);
910 sendMouseRelease(view.viewport(), QPoint(), Qt::LeftButton);
912 view.setRubberBandSelectionMode(Qt::ContainsItemShape);
913 QCOMPARE(view.rubberBandSelectionMode(), Qt::ContainsItemShape);
914 sendMousePress(view.viewport(), QPoint(), Qt::LeftButton);
915 QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>());
916 sendMouseMove(view.viewport(), view.viewport()->rect().center(),
917 Qt::LeftButton, Qt::LeftButton);
918 QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>());
919 sendMouseMove(view.viewport(), view.viewport()->rect().bottomRight(),
920 Qt::LeftButton, Qt::LeftButton);
921 QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>() << rect);
924 void tst_QGraphicsView::backgroundBrush()
926 QGraphicsScene scene;
927 QGraphicsView view(&scene);
928 scene.setBackgroundBrush(Qt::blue);
929 QCOMPARE(scene.backgroundBrush(), QBrush(Qt::blue));
934 scene.setBackgroundBrush(QBrush());
935 QCOMPARE(scene.backgroundBrush(), QBrush());
938 QRadialGradient gradient(0, 0, 10);
939 gradient.setSpread(QGradient::RepeatSpread);
940 scene.setBackgroundBrush(gradient);
942 QCOMPARE(scene.backgroundBrush(), QBrush(gradient));
946 void tst_QGraphicsView::foregroundBrush()
948 QGraphicsScene scene;
949 QGraphicsView view(&scene);
950 scene.setForegroundBrush(Qt::blue);
951 QCOMPARE(scene.foregroundBrush(), QBrush(Qt::blue));
956 scene.setForegroundBrush(QBrush());
957 QCOMPARE(scene.foregroundBrush(), QBrush());
960 QRadialGradient gradient(0, 0, 10);
961 gradient.setSpread(QGradient::RepeatSpread);
962 scene.setForegroundBrush(gradient);
964 QCOMPARE(scene.foregroundBrush(), QBrush(gradient));
967 for (int i = 0; i < 50; ++i) {
968 QRadialGradient gradient(view.rect().center() + QPoint(int(sin(i / 2.0) * 10), int(cos(i / 2.0) * 10)), 10);
969 gradient.setColorAt(0, Qt::transparent);
970 gradient.setColorAt(0.5, Qt::black);
971 gradient.setColorAt(1, Qt::transparent);
972 gradient.setSpread(QGradient::RepeatSpread);
973 scene.setForegroundBrush(gradient);
975 QRadialGradient gradient2(view.rect().center() + QPoint(int(sin(i / 1.7) * 10), int(cos(i / 1.7) * 10)), 10);
976 gradient2.setColorAt(0, Qt::transparent);
977 gradient2.setColorAt(0.5, Qt::black);
978 gradient2.setColorAt(1, Qt::transparent);
979 gradient2.setSpread(QGradient::RepeatSpread);
980 scene.setBackgroundBrush(gradient2);
982 QRadialGradient gradient3(view.rect().center() + QPoint(int(sin(i / 1.85) * 10), int(cos(i / 1.85) * 10)), 10);
983 gradient3.setColorAt(0, Qt::transparent);
984 gradient3.setColorAt(0.5, Qt::black);
985 gradient3.setColorAt(1, Qt::transparent);
986 gradient3.setSpread(QGradient::RepeatSpread);
987 scene.setBackgroundBrush(gradient3);
989 QApplication::processEvents();
992 view.setSceneRect(-1000, -1000, 2000, 2000);
993 for (int i = -500; i < 500; i += 10) {
995 QApplication::processEvents();
996 QApplication::processEvents();
998 for (int i = -500; i < 500; i += 10) {
1000 QApplication::processEvents();
1001 QApplication::processEvents();
1005 void tst_QGraphicsView::matrix()
1008 QGraphicsScene scene;
1009 QGraphicsView view(&scene);
1012 // Show rendering of background with no scene
1013 for (int i = 0; i < 50; ++i) {
1015 QRadialGradient gradient(view.rect().center() + QPoint(int(sin(i / 2.0) * 10), int(cos(i / 2.0) * 10)), 10);
1016 gradient.setColorAt(0, Qt::transparent);
1017 gradient.setColorAt(0.5, Qt::black);
1018 gradient.setColorAt(1, Qt::transparent);
1019 gradient.setSpread(QGradient::RepeatSpread);
1020 scene.setForegroundBrush(gradient);
1021 QRadialGradient gradient2(view.rect().center() + QPoint(int(sin(i / 1.7) * 10), int(cos(i / 1.7) * 10)), 10);
1022 gradient2.setColorAt(0, Qt::transparent);
1023 gradient2.setColorAt(0.5, Qt::black);
1024 gradient2.setColorAt(1, Qt::transparent);
1025 gradient2.setSpread(QGradient::RepeatSpread);
1026 scene.setBackgroundBrush(gradient2);
1027 QApplication::processEvents();
1028 QApplication::processEvents();
1032 // Test transformation extremes, see if they cause crashes
1034 QGraphicsScene scene;
1035 scene.addText("GraphicsView rotated clockwise");
1037 QGraphicsView view(&scene);
1039 for (int i = 0; i < 160; ++i) {
1041 QApplication::processEvents();
1042 QApplication::processEvents();
1045 // These cause a crash
1046 for (int i = 0; i < 40; ++i) {
1047 view.shear(1.2, 1.2);
1050 for (int i = 0; i < 40; ++i) {
1051 view.shear(-1.2, -1.2);
1055 for (int i = 0; i < 20; ++i) {
1056 view.scale(1.2, 1.2);
1057 QApplication::processEvents();
1058 QApplication::processEvents();
1060 for (int i = 0; i < 20; ++i) {
1061 view.scale(0.6, 0.6);
1062 QApplication::processEvents();
1063 QApplication::processEvents();
1068 void tst_QGraphicsView::matrix_convenience()
1071 QCOMPARE(view.matrix(), QMatrix());
1073 // Check the convenience functions
1075 QCOMPARE(view.matrix(), QMatrix().rotate(90));
1077 QCOMPARE(view.matrix(), QMatrix().scale(2, 2) * QMatrix().rotate(90));
1078 view.shear(1.2, 1.2);
1079 QCOMPARE(view.matrix(), QMatrix().shear(1.2, 1.2) * QMatrix().scale(2, 2) * QMatrix().rotate(90));
1080 view.translate(1, 1);
1081 QCOMPARE(view.matrix(), QMatrix().translate(1, 1) * QMatrix().shear(1.2, 1.2) * QMatrix().scale(2, 2) * QMatrix().rotate(90));
1084 void tst_QGraphicsView::matrix_combine()
1086 // Check matrix combining
1088 QCOMPARE(view.matrix(), QMatrix());
1089 view.setMatrix(QMatrix().rotate(90), true);
1090 view.setMatrix(QMatrix().rotate(90), true);
1091 view.setMatrix(QMatrix().rotate(90), true);
1092 view.setMatrix(QMatrix().rotate(90), true);
1093 QCOMPARE(view.matrix(), QMatrix());
1096 QCOMPARE(view.matrix(), QMatrix());
1097 view.setMatrix(QMatrix().rotate(90), false);
1098 view.setMatrix(QMatrix().rotate(90), false);
1099 view.setMatrix(QMatrix().rotate(90), false);
1100 view.setMatrix(QMatrix().rotate(90), false);
1101 QCOMPARE(view.matrix(), QMatrix().rotate(90));
1104 void tst_QGraphicsView::centerOnPoint()
1108 QGraphicsScene scene;
1109 scene.addEllipse(QRectF(-100, -100, 50, 50));
1110 scene.addEllipse(QRectF(50, -100, 50, 50));
1111 scene.addEllipse(QRectF(-100, 50, 50, 50));
1112 scene.addEllipse(QRectF(50, 50, 50, 50));
1114 QGraphicsView view(&scene, &toplevel);
1115 view.setSceneRect(-400, -400, 800, 800);
1116 view.setFixedSize(100, 100);
1121 for (int i = 0; i < 3; ++i) {
1122 for (int y = -100; y < 100; y += 23) {
1123 for (int x = -100; x < 100; x += 23) {
1124 view.centerOn(x, y);
1125 QPoint viewCenter = view.mapToScene(view.viewport()->rect().center()).toPoint();
1128 if (viewCenter.x() < x - tolerance || viewCenter.x() > x + tolerance
1129 || viewCenter.y() < y - tolerance || viewCenter.y() > y + tolerance) {
1130 QString error = QString("Compared values are not the same\n\tActual: (%1, %2)\n\tExpected: (%3, %4)")
1131 .arg(viewCenter.x()).arg(viewCenter.y()).arg(x).arg(y);
1132 QFAIL(qPrintable(error));
1135 QApplication::processEvents();
1140 view.scale(1.5, 1.5);
1141 view.shear(1.25, 1.25);
1145 void tst_QGraphicsView::centerOnItem()
1147 QGraphicsScene scene;
1148 QGraphicsItem *items[4];
1149 items[0] = scene.addEllipse(QRectF(-25, -25, 50, 50));
1150 items[1] = scene.addEllipse(QRectF(-25, -25, 50, 50));
1151 items[2] = scene.addEllipse(QRectF(-25, -25, 50, 50));
1152 items[3] = scene.addEllipse(QRectF(-25, -25, 50, 50));
1153 items[0]->setPos(-100, -100);
1154 items[1]->setPos(100, -100);
1155 items[2]->setPos(-100, 100);
1156 items[3]->setPos(100, 100);
1158 QGraphicsView view(&scene);
1159 view.setSceneRect(-1000, -1000, 2000, 2000);
1161 QVERIFY(QTest::qWaitForWindowExposed(&view));
1164 for (int x = 0; x < 3; ++x) {
1165 for (int i = 0; i < 4; ++i) {
1166 QApplication::processEvents();
1167 view.centerOn(items[i]);
1169 QPoint viewCenter = view.mapToScene(view.viewport()->rect().center()).toPoint();
1170 qreal x = items[i]->pos().x();
1171 qreal y = items[i]->pos().y();
1174 if (viewCenter.x() < x - tolerance || viewCenter.x() > x + tolerance
1175 || viewCenter.y() < y - tolerance || viewCenter.y() > y + tolerance) {
1176 QString error = QString("Compared values are not the same\n\tActual: (%1, %2)\n\tExpected: (%3, %4)")
1177 .arg(viewCenter.x()).arg(viewCenter.y()).arg(x).arg(y);
1178 QFAIL(qPrintable(error));
1181 QApplication::processEvents();
1185 view.scale(1.5, 1.5);
1186 view.shear(1.25, 1.25);
1190 void tst_QGraphicsView::ensureVisibleRect()
1194 QGraphicsScene scene;
1195 QGraphicsItem *items[4];
1196 items[0] = scene.addEllipse(QRectF(-25, -25, 50, 50), QPen(Qt::black), QBrush(Qt::green));
1197 items[1] = scene.addEllipse(QRectF(-25, -25, 50, 50), QPen(Qt::black), QBrush(Qt::red));
1198 items[2] = scene.addEllipse(QRectF(-25, -25, 50, 50), QPen(Qt::black), QBrush(Qt::blue));
1199 items[3] = scene.addEllipse(QRectF(-25, -25, 50, 50), QPen(Qt::black), QBrush(Qt::yellow));
1200 scene.addLine(QLineF(0, -100, 0, 100), QPen(Qt::blue, 2));
1201 scene.addLine(QLineF(-100, 0, 100, 0), QPen(Qt::blue, 2));
1202 items[0]->setPos(-100, -100);
1203 items[1]->setPos(100, -100);
1204 items[2]->setPos(-100, 100);
1205 items[3]->setPos(100, 100);
1207 QGraphicsItem *icon = scene.addEllipse(QRectF(-10, -10, 20, 20), QPen(Qt::black), QBrush(Qt::gray));
1209 QGraphicsView view(&scene, &toplevel);
1210 view.setSceneRect(-500, -500, 1000, 1000);
1211 view.setFixedSize(250, 250);
1213 QVERIFY(QTest::qWaitForWindowExposed(&toplevel));
1215 for (int y = -100; y < 100; y += 25) {
1216 for (int x = -100; x < 100; x += 13) {
1222 view.centerOn(-500, -500);
1225 view.centerOn(500, -500);
1228 view.centerOn(-500, 500);
1232 view.centerOn(500, 500);
1236 QVERIFY(!view.viewport()->rect().contains(view.mapFromScene(x, y)));
1238 for (int margin = 10; margin < 60; margin += 15) {
1239 view.ensureVisible(x, y, 0, 0, margin, margin);
1241 QRect viewRect = view.viewport()->rect();
1242 QPoint viewPoint = view.mapFromScene(x, y);
1244 QVERIFY(viewRect.contains(viewPoint));
1245 QVERIFY(qAbs(viewPoint.x() - viewRect.left()) >= margin -1);
1246 QVERIFY(qAbs(viewPoint.x() - viewRect.right()) >= margin -1);
1247 QVERIFY(qAbs(viewPoint.y() - viewRect.top()) >= margin -1);
1248 QVERIFY(qAbs(viewPoint.y() - viewRect.bottom()) >= margin -1);
1250 QApplication::processEvents();
1254 view.scale(1.05, 1.05);
1255 view.translate(30, -30);
1259 void tst_QGraphicsView::fitInView()
1261 QGraphicsScene scene;
1262 QGraphicsItem *items[4];
1263 items[0] = scene.addEllipse(QRectF(-25, -25, 100, 20), QPen(Qt::black), QBrush(Qt::green));
1264 items[1] = scene.addEllipse(QRectF(-25, -25, 20, 100), QPen(Qt::black), QBrush(Qt::red));
1265 items[2] = scene.addEllipse(QRectF(-25, -25, 50, 50), QPen(Qt::black), QBrush(Qt::blue));
1266 items[3] = scene.addEllipse(QRectF(-25, -25, 50, 50), QPen(Qt::black), QBrush(Qt::yellow));
1267 scene.addLine(QLineF(0, -100, 0, 100), QPen(Qt::blue, 2));
1268 scene.addLine(QLineF(-100, 0, 100, 0), QPen(Qt::blue, 2));
1269 items[0]->setPos(-100, -100);
1270 items[1]->setPos(100, -100);
1271 items[2]->setPos(-100, 100);
1272 items[3]->setPos(100, 100);
1274 items[0]->rotate(30);
1275 items[1]->rotate(-30);
1277 #if defined(Q_OS_WINCE)
1278 //Is the standard scrollbar size
1279 int scrollbarSize = qApp->style()->pixelMetric(QStyle::PM_ScrollBarExtent) - 13;
1282 QGraphicsView view(&scene);
1283 view.setSceneRect(-400, -400, 800, 800);
1285 #if defined(Q_OS_WINCE)
1286 //We need to take in account the scrollbar size for the WindowsMobilStyle
1287 view.setFixedSize(400 + scrollbarSize, 200 + scrollbarSize);
1289 view.setFixedSize(400, 200);
1293 view.fitInView(scene.itemsBoundingRect(), Qt::IgnoreAspectRatio);
1294 qApp->processEvents();
1296 // Sampled coordinates.
1297 QVERIFY(!view.itemAt(45, 41));
1298 QVERIFY(!view.itemAt(297, 44));
1299 QVERIFY(!view.itemAt(359, 143));
1300 QCOMPARE(view.itemAt(79, 22), items[0]);
1301 QCOMPARE(view.itemAt(329, 41), items[1]);
1302 QCOMPARE(view.itemAt(38, 158), items[2]);
1303 QCOMPARE(view.itemAt(332, 160), items[3]);
1305 view.fitInView(items[0], Qt::IgnoreAspectRatio);
1306 qApp->processEvents();
1308 QCOMPARE(view.itemAt(19, 13), items[0]);
1309 QCOMPARE(view.itemAt(91, 47), items[0]);
1310 QCOMPARE(view.itemAt(202, 94), items[0]);
1311 QCOMPARE(view.itemAt(344, 161), items[0]);
1312 QVERIFY(!view.itemAt(236, 54));
1313 QVERIFY(!view.itemAt(144, 11));
1314 QVERIFY(!view.itemAt(29, 69));
1315 QVERIFY(!view.itemAt(251, 167));
1317 view.fitInView(items[0], Qt::KeepAspectRatio);
1318 qApp->processEvents();
1320 QCOMPARE(view.itemAt(325, 170), items[0]);
1321 QCOMPARE(view.itemAt(206, 74), items[0]);
1322 QCOMPARE(view.itemAt(190, 115), items[0]);
1323 QCOMPARE(view.itemAt(55, 14), items[0]);
1324 QVERIFY(!view.itemAt(109, 4));
1325 QVERIFY(!view.itemAt(244, 68));
1326 QVERIFY(!view.itemAt(310, 125));
1327 QVERIFY(!view.itemAt(261, 168));
1329 view.fitInView(items[0], Qt::KeepAspectRatioByExpanding);
1330 qApp->processEvents();
1332 QCOMPARE(view.itemAt(18, 10), items[0]);
1333 QCOMPARE(view.itemAt(95, 4), items[0]);
1334 QCOMPARE(view.itemAt(279, 175), items[0]);
1335 QCOMPARE(view.itemAt(359, 170), items[0]);
1336 QVERIFY(!view.itemAt(370, 166));
1337 QVERIFY(!view.itemAt(136, 7));
1338 QVERIFY(!view.itemAt(31, 44));
1339 QVERIFY(!view.itemAt(203, 153));
1342 void tst_QGraphicsView::itemsAtPoint()
1344 QGraphicsScene scene;
1345 scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(1);
1346 scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(0);
1347 scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(2);
1348 scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(-1);
1349 scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(3);
1352 QVERIFY(view.items(0, 0).isEmpty());
1354 view.setScene(&scene);
1355 view.setSceneRect(-10000, -10000, 20000, 20000);
1358 QList<QGraphicsItem *> items = view.items(view.viewport()->rect().center());
1359 QCOMPARE(items.size(), 5);
1360 QCOMPARE(items.takeFirst()->zValue(), qreal(3));
1361 QCOMPARE(items.takeFirst()->zValue(), qreal(2));
1362 QCOMPARE(items.takeFirst()->zValue(), qreal(1));
1363 QCOMPARE(items.takeFirst()->zValue(), qreal(0));
1364 QCOMPARE(items.takeFirst()->zValue(), qreal(-1));
1367 #if defined QT_BUILD_INTERNAL
1368 void tst_QGraphicsView::itemsAtPosition_data()
1370 QTest::addColumn<float>("rotation");
1371 QTest::addColumn<float>("scale");
1372 QTest::addColumn<QPoint>("viewPos");
1373 QTest::addColumn<bool>("ignoreTransform");
1374 QTest::addColumn<bool>("hit");
1375 QTest::newRow("scaled + ignore transform, no hit") << 0.0f << 1000.0f << QPoint(0, 0) << true << false;
1376 QTest::newRow("scaled + ignore transform, hit") << 0.0f << 1000.0f << QPoint(100, 100) << true << true;
1377 QTest::newRow("rotated + scaled, no hit") << 45.0f << 2.0f << QPoint(90, 90) << false << false;
1378 QTest::newRow("rotated + scaled, hit") << 45.0f << 2.0f << QPoint(100, 100) << false << true;
1381 void tst_QGraphicsView::itemsAtPosition()
1383 QFETCH(float, rotation);
1384 QFETCH(float, scale);
1385 QFETCH(QPoint, viewPos);
1386 QFETCH(bool, ignoreTransform);
1389 FriendlyGraphicsScene scene;
1390 scene.setSceneRect(QRect(-100, -100, 200, 200));
1391 QGraphicsItem *item = scene.addRect(-5, -5, 10, 10);
1393 if (ignoreTransform)
1394 item->setFlag(QGraphicsItem::ItemIgnoresTransformations);
1397 view.setFrameStyle(QFrame::NoFrame);
1398 view.resize(200, 200);
1399 view.scale(scale, scale);
1400 view.rotate(rotation);
1401 view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1402 view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1403 view.setScene(&scene);
1405 QVERIFY(QTest::qWaitForWindowExposed(&view));
1407 QPoint screenPos = view.viewport()->mapToGlobal(viewPos);
1408 QPointF scenePos = view.mapToScene(viewPos);
1409 QGraphicsScenePrivate *viewPrivate = scene.d_func();
1410 QList<QGraphicsItem *> items;
1411 items = viewPrivate->itemsAtPosition(screenPos, scenePos, view.viewport());
1412 QCOMPARE(!items.empty(), hit);
1416 void tst_QGraphicsView::itemsInRect()
1418 QGraphicsScene scene;
1419 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(1);
1420 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(0);
1421 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(2);
1422 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(-1);
1423 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(3);
1425 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(5);
1426 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(4);
1427 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(6);
1428 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(3);
1429 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(7);
1432 QVERIFY(view.items(QRect(-100, -100, 200, 200)).isEmpty());
1433 view.setScene(&scene);
1434 view.setSceneRect(-10000, -10000, 20000, 20000);
1437 QRect leftRect = view.mapFromScene(-30, -10, 20, 20).boundingRect();
1438 QRect rightRect = view.mapFromScene(30, -10, 20, 20).boundingRect();
1440 QList<QGraphicsItem *> items = view.items(leftRect);
1441 QCOMPARE(items.size(), 5);
1442 QCOMPARE(items.takeFirst()->zValue(), qreal(3));
1443 QCOMPARE(items.takeFirst()->zValue(), qreal(2));
1444 QCOMPARE(items.takeFirst()->zValue(), qreal(1));
1445 QCOMPARE(items.takeFirst()->zValue(), qreal(0));
1446 QCOMPARE(items.takeFirst()->zValue(), qreal(-1));
1448 items = view.items(rightRect);
1449 QCOMPARE(items.size(), 5);
1450 QCOMPARE(items.takeFirst()->zValue(), qreal(7));
1451 QCOMPARE(items.takeFirst()->zValue(), qreal(6));
1452 QCOMPARE(items.takeFirst()->zValue(), qreal(5));
1453 QCOMPARE(items.takeFirst()->zValue(), qreal(4));
1454 QCOMPARE(items.takeFirst()->zValue(), qreal(3));
1457 class CountPaintItem : public QGraphicsRectItem
1462 CountPaintItem(const QRectF &rect)
1463 : QGraphicsRectItem(rect), numPaints(0)
1466 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
1469 QGraphicsRectItem::paint(painter, option, widget);
1473 void tst_QGraphicsView::itemsInRect_cosmeticAdjust_data()
1475 QTest::addColumn<QRect>("updateRect");
1476 QTest::addColumn<int>("numPaints");
1477 QTest::addColumn<bool>("adjustForAntialiasing");
1480 QTest::newRow("nil") << QRect() << 1 << false;
1481 QTest::newRow("0, 0, 300, 100") << QRect(0, 0, 300, 100) << 1 << false;
1482 QTest::newRow("0, 0, 100, 300") << QRect(0, 0, 100, 300) << 1 << false;
1483 QTest::newRow("200, 0, 100, 300") << QRect(200, 0, 100, 300) << 1 << false;
1484 QTest::newRow("0, 200, 300, 100") << QRect(0, 200, 300, 100) << 1 << false;
1485 QTest::newRow("0, 0, 300, 99") << QRect(0, 0, 300, 99) << 0 << false;
1486 QTest::newRow("0, 0, 99, 300") << QRect(0, 0, 99, 300) << 0 << false;
1487 QTest::newRow("201, 0, 99, 300") << QRect(201, 0, 99, 300) << 0 << false;
1488 QTest::newRow("0, 201, 300, 99") << QRect(0, 201, 300, 99) << 0 << false;
1491 QTest::newRow("nil") << QRect() << 1 << true;
1492 QTest::newRow("0, 0, 300, 100") << QRect(0, 0, 300, 100) << 1 << true;
1493 QTest::newRow("0, 0, 100, 300") << QRect(0, 0, 100, 300) << 1 << true;
1494 QTest::newRow("200, 0, 100, 300") << QRect(200, 0, 100, 300) << 1 << true;
1495 QTest::newRow("0, 200, 300, 100") << QRect(0, 200, 300, 100) << 1 << true;
1496 QTest::newRow("0, 0, 300, 99") << QRect(0, 0, 300, 99) << 1 << true;
1497 QTest::newRow("0, 0, 99, 300") << QRect(0, 0, 99, 300) << 1 << true;
1498 QTest::newRow("201, 0, 99, 300") << QRect(201, 0, 99, 300) << 1 << true;
1499 QTest::newRow("0, 201, 300, 99") << QRect(0, 201, 300, 99) << 1 << true;
1500 QTest::newRow("0, 0, 300, 98") << QRect(0, 0, 300, 98) << 0 << false;
1501 QTest::newRow("0, 0, 98, 300") << QRect(0, 0, 98, 300) << 0 << false;
1502 QTest::newRow("202, 0, 98, 300") << QRect(202, 0, 98, 300) << 0 << false;
1503 QTest::newRow("0, 202, 300, 98") << QRect(0, 202, 300, 98) << 0 << false;
1506 void tst_QGraphicsView::itemsInRect_cosmeticAdjust()
1508 QFETCH(QRect, updateRect);
1509 QFETCH(int, numPaints);
1510 QFETCH(bool, adjustForAntialiasing);
1512 QGraphicsScene scene(-100, -100, 200, 200);
1513 CountPaintItem *rect = new CountPaintItem(QRectF(-50, -50, 100, 100));
1514 rect->setPen(QPen(Qt::black, 0));
1515 scene.addItem(rect);
1517 QGraphicsView view(&scene);
1518 view.setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing, !adjustForAntialiasing);
1519 view.setRenderHint(QPainter::Antialiasing, adjustForAntialiasing);
1520 view.setFrameStyle(0);
1521 view.resize(300, 300);
1523 QVERIFY(QTest::qWaitForWindowActive(&view));
1524 QTRY_VERIFY(rect->numPaints > 0);
1526 rect->numPaints = 0;
1527 if (updateRect.isNull())
1528 view.viewport()->update();
1530 view.viewport()->update(updateRect);
1531 qApp->processEvents();
1532 QTRY_COMPARE(rect->numPaints, numPaints);
1535 void tst_QGraphicsView::itemsInPoly()
1537 QGraphicsScene scene;
1538 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(1);
1539 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(0);
1540 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(2);
1541 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(-1);
1542 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(3);
1544 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(5);
1545 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(4);
1546 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(6);
1547 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(3);
1548 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(7);
1551 QVERIFY(view.items(QPolygon()).isEmpty());
1552 view.setScene(&scene);
1553 view.setSceneRect(-10000, -10000, 20000, 20000);
1556 QPolygon leftPoly = view.mapFromScene(QRectF(-30, -10, 20, 20));
1557 QPolygon rightPoly = view.mapFromScene(QRectF(30, -10, 20, 20));
1559 QList<QGraphicsItem *> items = view.items(leftPoly);
1560 QCOMPARE(items.size(), 5);
1561 QCOMPARE(items.takeFirst()->zValue(), qreal(3));
1562 QCOMPARE(items.takeFirst()->zValue(), qreal(2));
1563 QCOMPARE(items.takeFirst()->zValue(), qreal(1));
1564 QCOMPARE(items.takeFirst()->zValue(), qreal(0));
1565 QCOMPARE(items.takeFirst()->zValue(), qreal(-1));
1567 items = view.items(rightPoly);
1568 QCOMPARE(items.size(), 5);
1569 QCOMPARE(items.takeFirst()->zValue(), qreal(7));
1570 QCOMPARE(items.takeFirst()->zValue(), qreal(6));
1571 QCOMPARE(items.takeFirst()->zValue(), qreal(5));
1572 QCOMPARE(items.takeFirst()->zValue(), qreal(4));
1573 QCOMPARE(items.takeFirst()->zValue(), qreal(3));
1576 void tst_QGraphicsView::itemsInPath()
1578 QGraphicsScene scene;
1579 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(1);
1580 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(0);
1581 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(2);
1582 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(-1);
1583 scene.addRect(QRectF(-30, -10, 20, 20))->setZValue(3);
1585 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(5);
1586 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(4);
1587 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(6);
1588 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(3);
1589 scene.addRect(QRectF(30, -10, 20, 20))->setZValue(7);
1592 QVERIFY(view.items(QPainterPath()).isEmpty());
1593 view.setScene(&scene);
1594 view.translate(100, 400);
1596 view.setSceneRect(-10000, -10000, 20000, 20000);
1599 QPainterPath leftPath;
1600 leftPath.addEllipse(QRect(view.mapFromScene(-30, -10), QSize(20, 20)));
1602 QPainterPath rightPath;
1603 rightPath.addEllipse(QRect(view.mapFromScene(30, -10), QSize(20, 20)));
1605 QList<QGraphicsItem *> items = view.items(leftPath);
1607 QCOMPARE(items.size(), 5);
1608 QCOMPARE(items.takeFirst()->zValue(), qreal(3));
1609 QCOMPARE(items.takeFirst()->zValue(), qreal(2));
1610 QCOMPARE(items.takeFirst()->zValue(), qreal(1));
1611 QCOMPARE(items.takeFirst()->zValue(), qreal(0));
1612 QCOMPARE(items.takeFirst()->zValue(), qreal(-1));
1614 items = view.items(rightPath);
1615 QCOMPARE(items.size(), 5);
1616 QCOMPARE(items.takeFirst()->zValue(), qreal(7));
1617 QCOMPARE(items.takeFirst()->zValue(), qreal(6));
1618 QCOMPARE(items.takeFirst()->zValue(), qreal(5));
1619 QCOMPARE(items.takeFirst()->zValue(), qreal(4));
1620 QCOMPARE(items.takeFirst()->zValue(), qreal(3));
1623 void tst_QGraphicsView::itemAt()
1625 QGraphicsScene scene;
1626 scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(1);
1627 scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(0);
1628 scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(2);
1629 scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(-1);
1630 scene.addRect(QRectF(-10, -10, 20, 20))->setZValue(3);
1633 QCOMPARE(view.itemAt(0, 0), (QGraphicsItem *)0);
1635 view.setScene(&scene);
1636 view.setSceneRect(-10000, -10000, 20000, 20000);
1639 QCOMPARE(view.itemAt(0, 0), (QGraphicsItem *)0);
1640 QGraphicsItem* item = view.itemAt(view.viewport()->rect().center());
1642 QCOMPARE(item->zValue(), qreal(3));
1645 void tst_QGraphicsView::itemAt2()
1647 // test precision of the itemAt() function with items that are smaller
1649 QGraphicsScene scene(0, 0, 100, 100);
1651 // Add a 0.5x0.5 item at position 0 on the scene, top-left corner at -0.25, -0.25.
1652 QGraphicsItem *item = scene.addRect(QRectF(-0.25, -0.25, 0.5, 0.5), QPen(Qt::black, 0.1));
1654 QGraphicsView view(&scene);
1655 view.setFixedSize(200, 200);
1656 view.setTransformationAnchor(QGraphicsView::NoAnchor);
1657 view.setRenderHint(QPainter::Antialiasing);
1659 QVERIFY(QTest::qWaitForWindowExposed(&view));
1660 QApplication::processEvents();
1662 QPoint itemViewPoint = view.mapFromScene(item->scenePos());
1664 for (int i = 0; i < 3; ++i) {
1665 QVERIFY(view.itemAt(itemViewPoint));
1666 QVERIFY(!view.items(itemViewPoint).isEmpty());
1667 QVERIFY(view.itemAt(itemViewPoint + QPoint(-1, 0)));
1668 QVERIFY(!view.items(itemViewPoint + QPoint(-1, 0)).isEmpty());
1669 QVERIFY(view.itemAt(itemViewPoint + QPoint(-1, -1)));
1670 QVERIFY(!view.items(itemViewPoint + QPoint(-1, -1)).isEmpty());
1671 QVERIFY(view.itemAt(itemViewPoint + QPoint(0, -1)));
1672 QVERIFY(!view.items(itemViewPoint + QPoint(0, -1)).isEmpty());
1673 item->moveBy(0.1, 0);
1677 QVERIFY(view.itemAt(itemViewPoint));
1678 QVERIFY(!view.items(itemViewPoint).isEmpty());
1679 QVERIFY(view.itemAt(itemViewPoint + QPoint(0, -1)));
1680 QVERIFY(!view.items(itemViewPoint + QPoint(0, -1)).isEmpty());
1682 if (sizeof(qreal) != sizeof(double))
1683 QSKIP("Skipped due to rounding errors");
1686 QVERIFY(!view.itemAt(itemViewPoint + QPoint(-1, 0)));
1687 QVERIFY(view.items(itemViewPoint + QPoint(-1, 0)).isEmpty());
1688 QVERIFY(!view.itemAt(itemViewPoint + QPoint(-1, -1)));
1689 QVERIFY(view.items(itemViewPoint + QPoint(-1, -1)).isEmpty());
1692 void tst_QGraphicsView::mapToScene()
1694 // Uncomment the commented-out code to see what's going on. It doesn't
1695 // affect the test; it just slows it down.
1697 QGraphicsScene scene;
1698 scene.addPixmap(QPixmap("3D-Qt-1-2.png"));
1701 QGraphicsView view(&topLevel);
1702 view.setScene(&scene);
1703 view.setSceneRect(-500, -500, 1000, 1000);
1704 #if defined(Q_OS_WINCE)
1705 QSize viewSize(200,200);
1707 QSize viewSize(300,300);
1710 view.setFixedSize(viewSize);
1712 QApplication::processEvents();
1713 QVERIFY(view.isVisible());
1714 QCOMPARE(view.size(), viewSize);
1716 // First once without setting the scene rect
1717 #ifdef Q_PROCESSOR_ARM
1718 const int step = 20;
1723 for (int x = 0; x < view.width(); x += step) {
1724 for (int y = 0; y < view.height(); y += step) {
1725 QCOMPARE(view.mapToScene(QPoint(x, y)),
1726 QPointF(view.horizontalScrollBar()->value() + x,
1727 view.verticalScrollBar()->value() + y));
1731 for (int sceneRectHeight = 250; sceneRectHeight < 1000; sceneRectHeight += 250) {
1732 for (int sceneRectWidth = 250; sceneRectWidth < 1000; sceneRectWidth += 250) {
1733 view.setSceneRect(QRectF(-int(sceneRectWidth / 2), -int(sceneRectHeight / 2),
1734 sceneRectWidth, sceneRectHeight));
1735 QApplication::processEvents();
1737 int hmin = view.horizontalScrollBar()->minimum();
1738 int hmax = view.horizontalScrollBar()->maximum();
1739 int hstep = (hmax - hmin) / 3;
1740 int vmin = view.verticalScrollBar()->minimum();
1741 int vmax = view.verticalScrollBar()->maximum();
1742 int vstep = (vmax - vmin) / 3;
1744 for (int hscrollValue = hmin; hscrollValue < hmax; hscrollValue += hstep) {
1745 for (int vscrollValue = vmin; vscrollValue < vmax; vscrollValue += vstep) {
1747 view.horizontalScrollBar()->setValue(hscrollValue);
1748 view.verticalScrollBar()->setValue(vscrollValue);
1749 QApplication::processEvents();
1751 int h = view.horizontalScrollBar()->value();
1752 int v = view.verticalScrollBar()->value();
1754 for (int x = 0; x < view.width(); x += step) {
1755 for (int y = 0; y < view.height(); y += step) {
1756 QCOMPARE(view.mapToScene(QPoint(x, y)), QPointF(h + x, v + y));
1757 QCOMPARE(view.mapFromScene(QPointF(h + x, v + y)), QPoint(x, y));
1766 void tst_QGraphicsView::mapToScenePoint()
1768 QGraphicsScene scene;
1769 QGraphicsView view(&scene);
1771 view.setFixedSize(117, 117);
1773 QPoint center = view.viewport()->rect().center();
1774 QCOMPARE(view.mapToScene(center + QPoint(10, 0)),
1775 view.mapToScene(center) + QPointF(0, -10));
1778 void tst_QGraphicsView::mapToSceneRect_data()
1780 QTest::addColumn<QRect>("viewRect");
1781 QTest::addColumn<QPolygonF>("scenePoly");
1782 QTest::addColumn<qreal>("rotation");
1784 QTest::newRow("nil") << QRect() << QPolygonF() << qreal(0);
1785 QTest::newRow("0, 0, 1, 1") << QRect(0, 0, 1, 1) << QPolygonF(QRectF(0, 0, 1, 1)) << qreal(0);
1786 QTest::newRow("0, 0, 10, 10") << QRect(0, 0, 10, 10) << QPolygonF(QRectF(0, 0, 10, 10)) << qreal(0);
1787 QTest::newRow("nil") << QRect() << QPolygonF() << qreal(90);
1789 p << QPointF(0, 0) << QPointF(0, -1) << QPointF(1, -1) << QPointF(1, 0) << QPointF(0, 0);
1790 QTest::newRow("0, 0, 1, 1") << QRect(0, 0, 1, 1)
1794 p << QPointF(0, 0) << QPointF(0, -10) << QPointF(10, -10) << QPointF(10, 0) << QPointF(0, 0);
1795 QTest::newRow("0, 0, 10, 10") << QRect(0, 0, 10, 10)
1800 void tst_QGraphicsView::mapToSceneRect()
1802 QFETCH(QRect, viewRect);
1803 QFETCH(QPolygonF, scenePoly);
1804 QFETCH(qreal, rotation);
1806 QGraphicsScene scene(-1000, -1000, 2000, 2000);
1807 scene.addRect(25, -25, 50, 50);
1808 QGraphicsView view(&scene);
1809 view.setFrameStyle(0);
1810 view.setAlignment(Qt::AlignTop | Qt::AlignLeft);
1811 view.setFixedSize(200, 200);
1812 view.setTransformationAnchor(QGraphicsView::NoAnchor);
1813 view.setResizeAnchor(QGraphicsView::NoAnchor);
1816 view.rotate(rotation);
1818 QPolygonF poly = view.mapToScene(viewRect);
1819 if (!poly.isEmpty())
1822 QCOMPARE(poly, scenePoly);
1825 void tst_QGraphicsView::mapToScenePoly()
1827 QGraphicsScene scene;
1828 QGraphicsView view(&scene);
1829 view.translate(100, 100);
1830 view.setFixedSize(117, 117);
1832 QPoint center = view.viewport()->rect().center();
1833 QRect rect(center + QPoint(10, 0), QSize(10, 10));
1836 poly << rect.topLeft();
1837 poly << rect.topRight();
1838 poly << rect.bottomRight();
1839 poly << rect.bottomLeft();
1842 poly2 << view.mapToScene(rect.topLeft());
1843 poly2 << view.mapToScene(rect.topRight());
1844 poly2 << view.mapToScene(rect.bottomRight());
1845 poly2 << view.mapToScene(rect.bottomLeft());
1847 QCOMPARE(view.mapToScene(poly), poly2);
1850 void tst_QGraphicsView::mapToScenePath()
1852 QGraphicsScene scene;
1853 QGraphicsView view(&scene);
1854 view.setSceneRect(-300, -300, 600, 600);
1855 view.translate(10, 10);
1856 view.setFixedSize(300, 300);
1858 QRect rect(QPoint(10, 0), QSize(10, 10));
1864 path2.addRect(rect.translated(view.horizontalScrollBar()->value() - 10,
1865 view.verticalScrollBar()->value() - 10));
1866 QCOMPARE(view.mapToScene(path), path2);
1869 void tst_QGraphicsView::mapFromScenePoint()
1872 QGraphicsScene scene;
1873 QGraphicsView view(&scene);
1876 view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1877 view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1880 QPoint mapped = view.mapFromScene(0, 0);
1881 QPoint center = view.viewport()->rect().center();
1882 if (qAbs(mapped.x() - center.x()) >= 2
1883 || qAbs(mapped.y() - center.y()) >= 2) {
1884 QString error = QString("Compared values are not the same\n\tActual: (%1, %2)\n\tExpected: (%3, %4)")
1885 .arg(mapped.x()).arg(mapped.y()).arg(center.x()).arg(center.y());
1886 QFAIL(qPrintable(error));
1892 QGraphicsScene scene(0, 0, 200, 200);
1893 scene.addRect(QRectF(0, 0, 200, 200), QPen(Qt::black, 1));
1894 QGraphicsView view(&scene, &toplevel);
1895 view.ensurePolished();
1896 view.resize(view.sizeHint());
1899 QCOMPARE(view.mapFromScene(0, 0), QPoint(0, 0));
1900 QCOMPARE(view.mapFromScene(0.4, 0.4), QPoint(0, 0));
1901 QCOMPARE(view.mapFromScene(0.5, 0.5), QPoint(1, 1));
1902 QCOMPARE(view.mapFromScene(0.9, 0.9), QPoint(1, 1));
1903 QCOMPARE(view.mapFromScene(1.0, 1.0), QPoint(1, 1));
1904 QCOMPARE(view.mapFromScene(100, 100), QPoint(100, 100));
1905 QCOMPARE(view.mapFromScene(100.5, 100.5), QPoint(101, 101));
1906 QCOMPARE(view.mapToScene(0, 0), QPointF(0, 0));
1907 QCOMPARE(view.mapToScene(1, 1), QPointF(1, 1));
1908 QCOMPARE(view.mapToScene(100, 100), QPointF(100, 100));
1912 void tst_QGraphicsView::mapFromSceneRect()
1914 QGraphicsScene scene;
1916 QGraphicsView view(&scene,&topLevel);
1918 view.setFixedSize(200, 200);
1919 view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1920 view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1925 polygon << QPoint(98, 98);
1926 polygon << QPoint(98, 108);
1927 polygon << QPoint(88, 108);
1928 polygon << QPoint(88, 98);
1931 QPolygon viewPolygon = view.mapFromScene(0, 0, 10, 10);
1932 for (int i = 0; i < 4; ++i) {
1933 QVERIFY(qAbs(viewPolygon[i].x() - polygon[i].x()) < 3);
1934 QVERIFY(qAbs(viewPolygon[i].y() - polygon[i].y()) < 3);
1937 QPoint pt = view.mapFromScene(QPointF());
1939 p << pt << pt << pt << pt;
1940 QCOMPARE(view.mapFromScene(QRectF()), p);
1943 void tst_QGraphicsView::mapFromScenePoly()
1945 QGraphicsScene scene;
1946 QGraphicsView view(&scene);
1948 view.setFixedSize(200, 200);
1949 view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1950 view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1954 polygon << QPoint(0, 0);
1955 polygon << QPoint(10, 0);
1956 polygon << QPoint(10, 10);
1957 polygon << QPoint(0, 10);
1960 polygon2 << QPoint(98, 98);
1961 polygon2 << QPoint(98, 108);
1962 polygon2 << QPoint(88, 108);
1963 polygon2 << QPoint(88, 98);
1965 QPolygon viewPolygon = view.mapFromScene(polygon);
1966 for (int i = 0; i < 4; ++i) {
1967 QVERIFY(qAbs(viewPolygon[i].x() - polygon2[i].x()) < 3);
1968 QVERIFY(qAbs(viewPolygon[i].y() - polygon2[i].y()) < 3);
1972 void tst_QGraphicsView::mapFromScenePath()
1974 QGraphicsScene scene;
1975 QGraphicsView view(&scene);
1977 view.setFixedSize(200, 200);
1978 view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1979 view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1983 polygon << QPoint(0, 0);
1984 polygon << QPoint(10, 0);
1985 polygon << QPoint(10, 10);
1986 polygon << QPoint(0, 10);
1988 path.addPolygon(polygon);
1991 polygon2 << QPoint(98, 98);
1992 polygon2 << QPoint(98, 108);
1993 polygon2 << QPoint(88, 108);
1994 polygon2 << QPoint(88, 98);
1996 path2.addPolygon(polygon2);
1998 QPolygonF pathPoly = view.mapFromScene(path).toFillPolygon();
1999 QPolygonF path2Poly = path2.toFillPolygon();
2001 for (int i = 0; i < pathPoly.size(); ++i) {
2002 QVERIFY(qAbs(pathPoly[i].x() - path2Poly[i].x()) < 3);
2003 QVERIFY(qAbs(pathPoly[i].y() - path2Poly[i].y()) < 3);
2007 void tst_QGraphicsView::sendEvent()
2009 QGraphicsScene scene;
2011 TestItem *item = new TestItem;
2012 scene.addItem(item);
2013 item->setFlag(QGraphicsItem::ItemIsFocusable);
2014 item->setFlag(QGraphicsItem::ItemIsMovable);
2016 QGraphicsView view(&scene);
2018 QApplication::setActiveWindow(&view);
2019 QVERIFY(QTest::qWaitForWindowActive(&view));
2020 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2024 QCOMPARE(scene.focusItem(), (QGraphicsItem *)item);
2025 QCOMPARE(item->events.size(), 2);
2026 QCOMPARE(item->events.last(), QEvent::FocusIn);
2028 QPoint itemPoint = view.mapFromScene(item->scenePos());
2029 sendMousePress(view.viewport(), itemPoint);
2030 QCOMPARE(item->events.size(), 4);
2031 QCOMPARE(item->events.at(item->events.size() - 2), QEvent::GrabMouse);
2032 QCOMPARE(item->events.at(item->events.size() - 1), QEvent::GraphicsSceneMousePress);
2034 QMouseEvent mouseMoveEvent(QEvent::MouseMove, itemPoint, view.viewport()->mapToGlobal(itemPoint),
2035 Qt::LeftButton, Qt::LeftButton, 0);
2036 QApplication::sendEvent(view.viewport(), &mouseMoveEvent);
2037 QCOMPARE(item->events.size(), 5);
2038 QCOMPARE(item->events.last(), QEvent::GraphicsSceneMouseMove);
2040 QMouseEvent mouseReleaseEvent(QEvent::MouseButtonRelease, itemPoint,
2041 view.viewport()->mapToGlobal(itemPoint),
2042 Qt::LeftButton, 0, 0);
2043 QApplication::sendEvent(view.viewport(), &mouseReleaseEvent);
2044 QCOMPARE(item->events.size(), 7);
2045 QCOMPARE(item->events.at(item->events.size() - 2), QEvent::GraphicsSceneMouseRelease);
2046 QCOMPARE(item->events.at(item->events.size() - 1), QEvent::UngrabMouse);
2048 QKeyEvent keyPress(QEvent::KeyPress, Qt::Key_Space, 0);
2049 QApplication::sendEvent(view.viewport(), &keyPress);
2050 QCOMPARE(item->events.size(), 9);
2051 QCOMPARE(item->events.at(item->events.size() - 2), QEvent::ShortcutOverride);
2052 QCOMPARE(item->events.last(), QEvent::KeyPress);
2055 class MouseWheelScene : public QGraphicsScene
2058 Qt::Orientation orientation;
2060 void wheelEvent(QGraphicsSceneWheelEvent *event)
2062 orientation = event->orientation();
2063 QGraphicsScene::wheelEvent(event);
2067 void tst_QGraphicsView::wheelEvent()
2069 // Create a scene with an invalid orientation.
2070 MouseWheelScene scene;
2071 scene.orientation = Qt::Orientation(-1);
2073 QGraphicsWidget *widget = new QGraphicsWidget;
2074 widget->setGeometry(0, 0, 400, 400);
2075 widget->setFocusPolicy(Qt::WheelFocus);
2077 EventSpy spy(widget, QEvent::GraphicsSceneWheel);
2078 QCOMPARE(spy.count(), 0);
2080 scene.addItem(widget);
2083 QGraphicsView view(&scene);
2085 QApplication::setActiveWindow(&view);
2086 QVERIFY(QTest::qWaitForWindowActive(&view));
2087 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2090 // Send a wheel event with horizontal orientation.
2092 QWheelEvent event(view.mapFromScene(widget->boundingRect().center()),
2093 view.mapToGlobal(view.mapFromScene(widget->boundingRect().center())),
2094 120, 0, 0, Qt::Horizontal);
2095 QApplication::sendEvent(view.viewport(), &event);
2096 QCOMPARE(scene.orientation, Qt::Horizontal);
2099 // Send a wheel event with vertical orientation.
2101 QWheelEvent event(view.mapFromScene(widget->boundingRect().center()),
2102 view.mapToGlobal(view.mapFromScene(widget->boundingRect().center())),
2103 120, 0, 0, Qt::Vertical);
2104 QApplication::sendEvent(view.viewport(), &event);
2105 QCOMPARE(scene.orientation, Qt::Vertical);
2108 QCOMPARE(spy.count(), 2);
2109 QVERIFY(widget->hasFocus());
2112 #ifndef QTEST_NO_CURSOR
2113 void tst_QGraphicsView::cursor()
2115 QGraphicsScene scene;
2116 QGraphicsItem *item = scene.addRect(QRectF(-10, -10, 20, 20));
2117 item->setCursor(Qt::IBeamCursor);
2119 QGraphicsView view(&scene);
2120 view.setFixedSize(400, 400);
2122 QVERIFY(QTest::qWaitForWindowExposed(&view));
2124 QCOMPARE(view.viewport()->cursor().shape(), QCursor().shape());
2125 view.viewport()->setCursor(Qt::PointingHandCursor);
2126 QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
2128 sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
2129 QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
2131 sendMouseMove(view.viewport(), QPoint(5, 5));
2132 QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
2136 #ifndef QTEST_NO_CURSOR
2137 void tst_QGraphicsView::cursor2()
2139 QGraphicsScene scene;
2140 QGraphicsItem *item = scene.addRect(QRectF(-10, -10, 20, 20));
2141 item->setCursor(Qt::IBeamCursor);
2144 QGraphicsItem *item2 = scene.addRect(QRectF(-20, -20, 40, 40));
2145 item2->setZValue(0);
2147 QGraphicsView view(&scene);
2148 view.viewport()->setCursor(Qt::PointingHandCursor);
2149 view.setFixedSize(400, 400);
2151 QVERIFY(QTest::qWaitForWindowExposed(&view));
2153 sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
2154 QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
2155 sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
2156 QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
2157 sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
2158 QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
2159 sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
2160 QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
2161 sendMouseMove(view.viewport(), view.mapFromScene(-15, 0));
2162 QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
2164 view.setDragMode(QGraphicsView::ScrollHandDrag);
2166 sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
2167 QCOMPARE(view.viewport()->cursor().shape(), Qt::OpenHandCursor);
2168 sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
2169 QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
2170 sendMouseMove(view.viewport(), view.mapFromScene(-15, -15));
2171 QCOMPARE(view.viewport()->cursor().shape(), Qt::OpenHandCursor);
2173 view.setDragMode(QGraphicsView::NoDrag);
2174 QCOMPARE(view.viewport()->cursor().shape(), Qt::ArrowCursor);
2175 view.viewport()->setCursor(Qt::PointingHandCursor);
2176 QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
2178 item2->setCursor(Qt::SizeAllCursor);
2180 sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
2181 QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
2182 sendMouseMove(view.viewport(), view.mapFromScene(-15, -15));
2183 QCOMPARE(view.viewport()->cursor().shape(), Qt::SizeAllCursor);
2184 sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
2185 QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
2186 sendMouseMove(view.viewport(), view.mapFromScene(-15, -15));
2187 QCOMPARE(view.viewport()->cursor().shape(), Qt::SizeAllCursor);
2188 sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
2189 QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
2190 sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
2191 QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
2193 view.setDragMode(QGraphicsView::ScrollHandDrag);
2195 sendMouseMove(view.viewport(), view.mapFromScene(-30, -30));
2196 QCOMPARE(view.viewport()->cursor().shape(), Qt::OpenHandCursor);
2197 sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
2198 QCOMPARE(view.viewport()->cursor().shape(), Qt::IBeamCursor);
2199 sendMouseMove(view.viewport(), view.mapFromScene(-15, -15));
2200 QCOMPARE(view.viewport()->cursor().shape(), Qt::SizeAllCursor);
2204 void tst_QGraphicsView::transformationAnchor()
2206 QGraphicsScene scene(-1000, -1000, 2000, 2000);
2207 scene.addRect(QRectF(-50, -50, 100, 100), QPen(Qt::black), QBrush(Qt::blue));
2209 QGraphicsView view(&scene);
2211 for (int i = 0; i < 2; ++i) {
2212 view.resize(100, 100);
2216 QCOMPARE(view.transformationAnchor(), QGraphicsView::AnchorViewCenter);
2218 view.setTransformationAnchor(QGraphicsView::NoAnchor);
2220 view.centerOn(0, 0);
2221 view.horizontalScrollBar()->setValue(100);
2222 QApplication::processEvents();
2224 QPointF center = view.mapToScene(view.viewport()->rect().center());
2228 QPointF newCenter = view.mapToScene(view.viewport()->rect().center());
2232 QVERIFY(qAbs(newCenter.x() - center.x()) < slack);
2233 QVERIFY(qAbs(newCenter.y() - center.y()) < slack);
2235 qreal slack = qreal(0.3);
2236 QVERIFY(qAbs(newCenter.x() - center.x() / 10) < slack);
2237 QVERIFY(qAbs(newCenter.y() - center.y() / 10) < slack);
2242 void tst_QGraphicsView::resizeAnchor()
2244 QGraphicsScene scene(-1000, -1000, 2000, 2000);
2245 scene.addRect(QRectF(-50, -50, 100, 100), QPen(Qt::black), QBrush(Qt::blue));
2247 QGraphicsView view(&scene);
2249 for (int i = 0; i < 2; ++i) {
2250 view.resize(100, 100);
2252 QVERIFY(QTest::qWaitForWindowExposed(&view));
2253 QApplication::processEvents();
2256 QCOMPARE(view.resizeAnchor(), QGraphicsView::NoAnchor);
2258 view.setResizeAnchor(QGraphicsView::AnchorViewCenter);
2260 view.centerOn(0, 0);
2263 QPointF f = view.mapToScene(50, 50);
2264 QPointF center = view.mapToScene(view.viewport()->rect().center());
2266 QApplication::processEvents();
2268 for (int size = 200; size <= 400; size += 25) {
2269 view.resize(size, size);
2271 QTRY_COMPARE(view.mapToScene(50, 50), f);
2272 QTRY_VERIFY(view.mapToScene(view.viewport()->rect().center()) != center);
2274 QTRY_VERIFY(view.mapToScene(50, 50) != f);
2276 QPointF newCenter = view.mapToScene(view.viewport()->rect().center());
2278 QVERIFY(qAbs(newCenter.x() - center.x()) < slack);
2279 QVERIFY(qAbs(newCenter.y() - center.y()) < slack);
2281 QApplication::processEvents();
2286 class CustomView : public QGraphicsView
2290 CustomView(QGraphicsScene *s = 0) : QGraphicsView(s) {}
2291 CustomView(QGraphicsScene *s, QWidget *parent)
2292 : QGraphicsView(s, parent) {}
2293 QList<QRegion> lastUpdateRegions;
2297 void paintEvent(QPaintEvent *event)
2299 lastUpdateRegions << event->region();
2301 QGraphicsView::paintEvent(event);
2305 void tst_QGraphicsView::viewportUpdateMode()
2307 QGraphicsScene scene(0, 0, 100, 100);
2308 scene.setBackgroundBrush(Qt::red);
2311 QDesktopWidget desktop;
2312 view.setFixedSize(QSize(500, 500).boundedTo(desktop.availableGeometry().size())); // 500 is too big for all common smartphones
2313 view.setScene(&scene);
2314 QCOMPARE(view.viewportUpdateMode(), QGraphicsView::MinimalViewportUpdate);
2316 // Show the view, and initialize our test.
2318 qApp->setActiveWindow(&view);
2319 QVERIFY(QTest::qWaitForWindowActive(&view));
2320 QTRY_VERIFY(!view.lastUpdateRegions.isEmpty());
2321 view.lastUpdateRegions.clear();
2323 // Issue two scene updates.
2324 scene.update(QRectF(0, 0, 10, 10));
2325 scene.update(QRectF(20, 0, 10, 10));
2328 // The view gets two updates for the update scene updates.
2329 QTRY_VERIFY(!view.lastUpdateRegions.isEmpty());
2330 #ifndef Q_OS_MAC //cocoa doesn't support drawing regions
2331 QCOMPARE(view.lastUpdateRegions.last().rects().size(), 2);
2332 QCOMPARE(view.lastUpdateRegions.last().rects().at(0).size(), QSize(14, 14));
2333 QCOMPARE(view.lastUpdateRegions.last().rects().at(1).size(), QSize(14, 14));
2336 // Set full update mode.
2337 view.setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
2338 QCOMPARE(view.viewportUpdateMode(), QGraphicsView::FullViewportUpdate);
2339 view.lastUpdateRegions.clear();
2341 // Issue two scene updates.
2342 scene.update(QRectF(0, 0, 10, 10));
2343 scene.update(QRectF(20, 0, 10, 10));
2344 qApp->processEvents();
2345 qApp->processEvents();
2347 // The view gets one full viewport update for the update scene updates.
2348 QCOMPARE(view.lastUpdateRegions.last().rects().size(), 1);
2349 QCOMPARE(view.lastUpdateRegions.last().rects().at(0).size(), view.viewport()->size());
2350 view.lastUpdateRegions.clear();
2352 // Set smart update mode
2353 view.setViewportUpdateMode(QGraphicsView::SmartViewportUpdate);
2354 QCOMPARE(view.viewportUpdateMode(), QGraphicsView::SmartViewportUpdate);
2356 // Issue 100 mini-updates
2357 for (int i = 0; i < 10; ++i) {
2358 for (int j = 0; j < 10; ++j) {
2359 scene.update(QRectF(i * 3, j * 3, 1, 1));
2362 qApp->processEvents();
2363 qApp->processEvents();
2365 // The view gets one bounding rect update.
2366 QCOMPARE(view.lastUpdateRegions.last().rects().size(), 1);
2367 QCOMPARE(view.lastUpdateRegions.last().rects().at(0).size(), QSize(32, 32));
2369 // Set no update mode
2370 view.setViewportUpdateMode(QGraphicsView::NoViewportUpdate);
2371 QCOMPARE(view.viewportUpdateMode(), QGraphicsView::NoViewportUpdate);
2373 // Issue two scene updates.
2374 view.lastUpdateRegions.clear();
2376 scene.addItem(&item);
2377 item.moveBy(10, 10);
2378 scene.update(QRectF(0, 0, 10, 10));
2379 scene.update(QRectF(20, 0, 10, 10));
2380 qApp->processEvents();
2381 qApp->processEvents();
2383 // The view should not get any painting calls from the scene updates
2384 QCOMPARE(view.lastUpdateRegions.size(), 0);
2387 void tst_QGraphicsView::viewportUpdateMode2()
2391 // Create a view with viewport rect equal to QRect(0, 0, 200, 200).
2392 QGraphicsScene dummyScene;
2393 CustomView view(0, &toplevel);
2394 view.painted = false;
2395 view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
2396 view.setScene(&dummyScene);
2397 view.ensurePolished(); // make sure we get the right content margins
2398 int left, top, right, bottom;
2399 view.getContentsMargins(&left, &top, &right, &bottom);
2400 view.resize(200 + left + right, 200 + top + bottom);
2402 qApp->setActiveWindow(&toplevel);
2403 QVERIFY(QTest::qWaitForWindowActive(&toplevel));
2404 QTRY_VERIFY(view.painted);
2405 const QRect viewportRect = view.viewport()->rect();
2406 QCOMPARE(viewportRect, QRect(0, 0, 200, 200));
2408 #if defined QT_BUILD_INTERNAL
2409 QGraphicsViewPrivate *viewPrivate = static_cast<QGraphicsViewPrivate *>(qt_widget_private(&view));
2412 const QRect rect1(0, 0, 10, 10);
2413 QVERIFY(viewPrivate->updateRect(rect1));
2414 QVERIFY(!viewPrivate->fullUpdatePending);
2415 boundingRect |= rect1;
2416 QCOMPARE(viewPrivate->dirtyBoundingRect, boundingRect);
2418 const QRect rect2(50, 50, 10, 10);
2419 QVERIFY(viewPrivate->updateRect(rect2));
2420 QVERIFY(!viewPrivate->fullUpdatePending);
2421 boundingRect |= rect2;
2422 QCOMPARE(viewPrivate->dirtyBoundingRect, boundingRect);
2424 const QRect rect3(190, 190, 10, 10);
2425 QVERIFY(viewPrivate->updateRect(rect3));
2426 QVERIFY(viewPrivate->fullUpdatePending);
2427 boundingRect |= rect3;
2428 QCOMPARE(viewPrivate->dirtyBoundingRect, boundingRect);
2430 view.lastUpdateRegions.clear();
2431 viewPrivate->processPendingUpdates();
2433 QCOMPARE(view.lastUpdateRegions.size(), 1);
2434 // Note that we adjust by 2 for antialiasing.
2435 QCOMPARE(view.lastUpdateRegions.at(0), QRegion(boundingRect.adjusted(-2, -2, 2, 2) & viewportRect));
2439 #ifndef QT_NO_DRAGANDDROP
2440 void tst_QGraphicsView::acceptDrops()
2444 // Excepted default behavior.
2445 QVERIFY(view.acceptDrops());
2446 QVERIFY(view.viewport()->acceptDrops());
2448 // Excepted behavior with no drops.
2449 view.setAcceptDrops(false);
2450 QVERIFY(!view.acceptDrops());
2451 QVERIFY(!view.viewport()->acceptDrops());
2453 // Setting a widget with drops on a QGraphicsView without drops.
2454 QWidget *widget = new QWidget;
2455 widget->setAcceptDrops(true);
2456 view.setViewport(widget);
2457 QVERIFY(!view.acceptDrops());
2458 QVERIFY(!view.viewport()->acceptDrops());
2460 // Switching the view to accept drops.
2461 view.setAcceptDrops(true);
2462 QVERIFY(view.acceptDrops());
2463 QVERIFY(view.viewport()->acceptDrops());
2465 // Setting a widget with no drops on a QGraphicsView with drops.
2466 widget = new QWidget;
2467 widget->setAcceptDrops(false);
2468 view.setViewport(widget);
2469 QVERIFY(view.viewport()->acceptDrops());
2470 QVERIFY(view.acceptDrops());
2472 // Switching the view to not accept drops.
2473 view.setAcceptDrops(false);
2474 QVERIFY(!view.viewport()->acceptDrops());
2478 void tst_QGraphicsView::optimizationFlags()
2481 QVERIFY(!view.optimizationFlags());
2483 view.setOptimizationFlag(QGraphicsView::DontClipPainter);
2484 QVERIFY(view.optimizationFlags() & QGraphicsView::DontClipPainter);
2485 view.setOptimizationFlag(QGraphicsView::DontClipPainter, false);
2486 QVERIFY(!view.optimizationFlags());
2488 view.setOptimizationFlag(QGraphicsView::DontSavePainterState);
2489 QVERIFY(view.optimizationFlags() & QGraphicsView::DontSavePainterState);
2490 view.setOptimizationFlag(QGraphicsView::DontSavePainterState, false);
2491 QVERIFY(!view.optimizationFlags());
2493 view.setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing);
2494 QVERIFY(view.optimizationFlags() & QGraphicsView::DontAdjustForAntialiasing);
2495 view.setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing, false);
2496 QVERIFY(!view.optimizationFlags());
2498 view.setOptimizationFlags(QGraphicsView::DontAdjustForAntialiasing
2499 | QGraphicsView::DontClipPainter);
2500 QCOMPARE(view.optimizationFlags(), QGraphicsView::OptimizationFlags(QGraphicsView::DontAdjustForAntialiasing
2501 | QGraphicsView::DontClipPainter));
2504 class MessUpPainterItem : public QGraphicsRectItem
2507 MessUpPainterItem(const QRectF &rect) : QGraphicsRectItem(rect), dirtyPainter(false)
2512 void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
2514 dirtyPainter = (painter->pen().width() != 0);
2515 painter->setPen(QPen(Qt::black, 1.0));
2519 class MyGraphicsView : public QGraphicsView
2522 MyGraphicsView(QGraphicsScene * scene) : QGraphicsView(scene)
2525 void drawBackground(QPainter * painter, const QRectF & rect) {
2526 painter->setCompositionMode(QPainter::CompositionMode_Source);
2527 painter->drawRect(rect);
2530 void drawItems (QPainter * painter, int numItems, QGraphicsItem *items[], const QStyleOptionGraphicsItem options[]) {
2531 if (!(optimizationFlags() & QGraphicsView::DontSavePainterState))
2532 QCOMPARE(painter->compositionMode(),QPainter::CompositionMode_SourceOver);
2534 QCOMPARE(painter->compositionMode(),QPainter::CompositionMode_Source);
2535 QGraphicsView::drawItems(painter,numItems,items,options);
2539 void tst_QGraphicsView::optimizationFlags_dontSavePainterState()
2541 MessUpPainterItem *parent = new MessUpPainterItem(QRectF(0, 0, 100, 100));
2542 MessUpPainterItem *child = new MessUpPainterItem(QRectF(0, 0, 100, 100));
2543 child->setParentItem(parent);
2545 QGraphicsScene scene;
2546 scene.addItem(parent);
2548 QGraphicsView view(&scene);
2550 QVERIFY(QTest::qWaitForWindowExposed(&view));
2551 view.viewport()->repaint();
2553 QVERIFY(!parent->dirtyPainter);
2554 QVERIFY(!child->dirtyPainter);
2556 view.setOptimizationFlags(QGraphicsView::DontSavePainterState);
2557 view.viewport()->repaint();
2560 // Repaint on Mac OS X actually does require spinning the event loop.
2563 QVERIFY(!parent->dirtyPainter);
2564 QVERIFY(child->dirtyPainter);
2566 MyGraphicsView painter(&scene);
2568 QVERIFY(QTest::qWaitForWindowExposed(&painter));
2570 MyGraphicsView painter2(&scene);
2571 painter2.setOptimizationFlag(QGraphicsView::DontSavePainterState,true);
2573 QVERIFY(QTest::qWaitForWindowExposed(&painter2));
2576 void tst_QGraphicsView::optimizationFlags_dontSavePainterState2_data()
2578 QTest::addColumn<bool>("savePainter");
2579 QTest::addColumn<bool>("indirectPainting");
2580 QTest::newRow("With painter state protection, without indirect painting") << true << false;
2581 QTest::newRow("Without painter state protection, without indirect painting") << false << false;
2582 QTest::newRow("With painter state protectionm, with indirect painting") << true << true;
2583 QTest::newRow("Without painter state protection, with indirect painting") << false << true;
2586 void tst_QGraphicsView::optimizationFlags_dontSavePainterState2()
2588 QFETCH(bool, savePainter);
2589 QFETCH(bool, indirectPainting);
2591 class MyScene : public QGraphicsScene
2594 void drawBackground(QPainter *p, const QRectF &)
2595 { transformInDrawBackground = p->worldTransform(); opacityInDrawBackground = p->opacity(); }
2597 void drawForeground(QPainter *p, const QRectF &)
2598 { transformInDrawForeground = p->worldTransform(); opacityInDrawForeground = p->opacity(); }
2600 QTransform transformInDrawBackground;
2601 QTransform transformInDrawForeground;
2602 qreal opacityInDrawBackground;
2603 qreal opacityInDrawForeground;
2607 // Add transformed dummy items to make sure the painter's worldTransform() is changed in drawItems.
2608 QGraphicsRectItem *rectA = scene.addRect(0, 0, 20, 20);
2609 QGraphicsRectItem *rectB = scene.addRect(50, 50, 20, 20);
2611 rectA->setTransform(QTransform::fromScale(2, 2));
2612 rectA->setPen(QPen(Qt::black, 0));
2613 rectB->setTransform(QTransform::fromTranslate(200, 200));
2614 rectB->setPen(QPen(Qt::black, 0));
2616 foreach (QGraphicsItem *item, scene.items())
2617 item->setOpacity(0.6);
2619 CustomView view(&scene);
2621 view.setOptimizationFlag(QGraphicsView::DontSavePainterState);
2622 view.setOptimizationFlag(QGraphicsView::IndirectPainting, indirectPainting);
2624 view.scale(1.5, 1.5);
2626 QVERIFY(QTest::qWaitForWindowExposed(&view));
2628 // Make sure the view is repainted; otherwise the tests below will fail.
2629 view.viewport()->repaint();
2631 QVERIFY(view.painted);
2633 // Make sure the painter's world transform is preserved after drawItems.
2634 QTransform expectedTransform = view.viewportTransform();
2635 QVERIFY(!expectedTransform.isIdentity());
2636 QCOMPARE(scene.transformInDrawForeground, expectedTransform);
2637 QCOMPARE(scene.transformInDrawBackground, expectedTransform);
2639 qreal expectedOpacity = 1.0;
2640 QCOMPARE(scene.opacityInDrawBackground, expectedOpacity);
2641 QCOMPARE(scene.opacityInDrawForeground, expectedOpacity);
2643 // Trigger more painting, this time from QGraphicsScene::render.
2644 QImage image(scene.sceneRect().size().toSize(), QImage::Format_RGB32);
2645 QPainter painter(&image);
2646 scene.render(&painter);
2649 expectedTransform = QTransform();
2650 QCOMPARE(scene.transformInDrawForeground, expectedTransform);
2651 QCOMPARE(scene.transformInDrawBackground, expectedTransform);
2652 QCOMPARE(scene.opacityInDrawBackground, expectedOpacity);
2653 QCOMPARE(scene.opacityInDrawForeground, expectedOpacity);
2655 // Trigger more painting with another opacity on the painter.
2656 painter.begin(&image);
2657 painter.setOpacity(0.4);
2658 expectedOpacity = 0.4;
2659 scene.render(&painter);
2662 QCOMPARE(scene.transformInDrawForeground, expectedTransform);
2663 QCOMPARE(scene.transformInDrawBackground, expectedTransform);
2664 QCOMPARE(scene.opacityInDrawBackground, expectedOpacity);
2665 QCOMPARE(scene.opacityInDrawForeground, expectedOpacity);
2668 class LodItem : public QGraphicsRectItem
2671 LodItem(const QRectF &rect) : QGraphicsRectItem(rect), lastLod(-42)
2674 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *viewport)
2676 lastLod = option->levelOfDetailFromTransform(painter->worldTransform());
2677 QGraphicsRectItem::paint(painter, option, viewport);
2683 void tst_QGraphicsView::levelOfDetail_data()
2685 QTest::addColumn<QTransform>("transform");
2686 QTest::addColumn<qreal>("lod");
2688 QTest::newRow("1:4, 1:4") << QTransform().scale(0.25, 0.25) << qreal(0.25);
2689 QTest::newRow("1:2, 1:4") << QTransform().scale(0.5, 0.25) << qreal(::sqrt(0.125));
2690 QTest::newRow("4:1, 1:2") << QTransform().scale(0.25, 0.5) << qreal(::sqrt(0.125));
2692 QTest::newRow("1:2, 1:2") << QTransform().scale(0.5, 0.5) << qreal(0.5);
2693 QTest::newRow("1:1, 1:2") << QTransform().scale(1, 0.5) << qreal(::sqrt(0.5));
2694 QTest::newRow("2:1, 1:1") << QTransform().scale(0.5, 1) << qreal(::sqrt(0.5));
2696 QTest::newRow("1:1, 1:1") << QTransform().scale(1, 1) << qreal(1.0);
2697 QTest::newRow("2:1, 1:1") << QTransform().scale(2, 1) << qreal(::sqrt(2.0));
2698 QTest::newRow("1:1, 2:1") << QTransform().scale(2, 1) << qreal(::sqrt(2.0));
2699 QTest::newRow("2:1, 2:1") << QTransform().scale(2, 2) << qreal(2.0);
2700 QTest::newRow("2:1, 4:1") << QTransform().scale(2, 4) << qreal(::sqrt(8.0));
2701 QTest::newRow("4:1, 2:1") << QTransform().scale(4, 2) << qreal(::sqrt(8.0));
2702 QTest::newRow("4:1, 4:1") << QTransform().scale(4, 4) << qreal(4.0);
2705 void tst_QGraphicsView::levelOfDetail()
2707 QFETCH(QTransform, transform);
2710 LodItem *item = new LodItem(QRectF(0, 0, 100, 100));
2712 QGraphicsScene scene;
2713 scene.addItem(item);
2715 QGraphicsView view(&scene);
2717 QVERIFY(QTest::qWaitForWindowExposed(&view));
2719 QTRY_COMPARE(item->lastLod, qreal(1));
2721 view.setTransform(transform);
2723 QTRY_COMPARE(item->lastLod, lod);
2726 // Moved to tst_qgraphicsview_2.cpp
2727 extern void _scrollBarRanges_data();
2729 void tst_QGraphicsView::scrollBarRanges_data()
2731 _scrollBarRanges_data();
2734 // Simulates motif scrollbar for range tests
2735 class FauxMotifStyle : public QCommonStyle {
2737 int styleHint(StyleHint hint, const QStyleOption *option,
2738 const QWidget *widget, QStyleHintReturn *returnData) const {
2739 if (hint == QStyle::SH_ScrollView_FrameOnlyAroundContents)
2741 return QCommonStyle::styleHint(hint, option, widget, returnData);
2744 int pixelMetric(PixelMetric m, const QStyleOption *opt, const QWidget *widget) const {
2745 if (m == QStyle::PM_ScrollView_ScrollBarSpacing)
2747 return QCommonStyle::pixelMetric(m, opt, widget);
2751 void tst_QGraphicsView::scrollBarRanges()
2753 QFETCH(QSize, viewportSize);
2754 QFETCH(QRectF, sceneRect);
2755 QFETCH(QTransform, transform);
2756 QFETCH(Qt::ScrollBarPolicy, hbarpolicy);
2757 QFETCH(Qt::ScrollBarPolicy, vbarpolicy);
2762 QFETCH(bool, useMotif);
2763 QFETCH(bool, useStyledPanel);
2765 QGraphicsScene scene(sceneRect);
2766 scene.addRect(sceneRect, QPen(Qt::blue), QBrush(QColor(Qt::green)));
2767 QGraphicsView view(&scene);
2768 view.setRenderHint(QPainter::Antialiasing);
2769 view.setTransform(transform);
2770 view.setFrameStyle(useStyledPanel ? QFrame::StyledPanel : QFrame::NoFrame);
2773 #if !defined(QT_NO_STYLE_WINDOWS)
2774 view.setStyle(new FauxMotifStyle);
2776 QSKIP("No Windows style compiled.");
2779 #if defined(Q_OS_WINCE)
2780 view.setStyle(new QWindowsStyle);
2781 #elif !defined(QT_NO_STYLE_PLASTIQUE)
2782 view.setStyle(new QPlastiqueStyle);
2785 view.setStyleSheet(" "); // enables style propagation ;-)
2789 adjust = view.style()->pixelMetric(QStyle::PM_DefaultFrameWidth) * 2;
2790 view.resize(viewportSize + QSize(adjust, adjust));
2792 view.setHorizontalScrollBarPolicy(hbarpolicy);
2793 view.setVerticalScrollBarPolicy(vbarpolicy);
2796 QVERIFY(QTest::qWaitForWindowExposed(&view));
2798 QCOMPARE(view.horizontalScrollBar()->minimum(), hmin);
2799 QCOMPARE(view.verticalScrollBar()->minimum(), vmin);
2800 QCOMPARE(view.horizontalScrollBar()->maximum(), hmax);
2801 QCOMPARE(view.verticalScrollBar()->maximum(), vmax);
2804 class TestView : public QGraphicsView
2807 TestView(QGraphicsScene *scene)
2808 : QGraphicsView(scene), accepted(false)
2814 void mousePressEvent(QMouseEvent *event)
2816 QGraphicsView::mousePressEvent(event);
2817 accepted = event->isAccepted();
2821 void tst_QGraphicsView::acceptMousePressEvent()
2823 QGraphicsScene scene;
2825 TestView view(&scene);
2827 QVERIFY(QTest::qWaitForWindowExposed(&view));
2829 QMouseEvent event(QEvent::MouseButtonPress,
2830 view.viewport()->rect().center(),
2831 view.viewport()->mapToGlobal(view.viewport()->rect().center()),
2832 Qt::LeftButton, 0, 0);
2833 event.setAccepted(false);
2834 QApplication::sendEvent(view.viewport(), &event);
2835 QVERIFY(!view.accepted);
2837 scene.addRect(0, 0, 2000, 2000)->setFlag(QGraphicsItem::ItemIsMovable);
2839 qApp->processEvents(); // ensure scene rect is updated
2841 QApplication::sendEvent(view.viewport(), &event);
2842 QVERIFY(view.accepted);
2845 void tst_QGraphicsView::replayMouseMove()
2847 // An empty scene in a view. The view will send the events to the scene in
2848 // any case. Note that the view doesn't have to be shown - the mouse event
2849 // sending functions below send the events directly to the viewport.
2850 QGraphicsScene scene(-10000, -10000, 20000, 20000);
2851 QGraphicsView view(&scene);
2853 EventSpy sceneSpy(&scene, QEvent::GraphicsSceneMouseMove);
2854 EventSpy viewSpy(view.viewport(), QEvent::MouseMove);
2856 sendMousePress(view.viewport(), view.viewport()->rect().center());
2858 // One mouse event should be translated into one scene event.
2859 for (int i = 0; i < 3; ++i) {
2860 sendMouseMove(view.viewport(), view.viewport()->rect().center(),
2861 Qt::LeftButton, Qt::MouseButtons(Qt::LeftButton));
2862 QCOMPARE(viewSpy.count(), i + 1);
2863 QCOMPARE(sceneSpy.count(), i + 1);
2866 // When the view is transformed, the view should get no more events. But
2867 // the scene should get replays.
2868 for (int i = 0; i < 3; ++i) {
2870 QCOMPARE(viewSpy.count(), 3);
2871 QCOMPARE(sceneSpy.count(), 3 + i + 1);
2874 // When the view is scrolled, the view should get no more events. But the
2875 // scene should get replays.
2876 for (int i = 0; i < 3; ++i) {
2877 view.horizontalScrollBar()->setValue((i + 1) * 10);
2878 QCOMPARE(viewSpy.count(), 3);
2879 QCOMPARE(sceneSpy.count(), 6 + i + 1);
2883 void tst_QGraphicsView::itemsUnderMouse()
2885 QGraphicsScene scene;
2886 QGraphicsProxyWidget w;
2887 w.setWidget(new QPushButton("W"));
2889 QGraphicsProxyWidget w2(&w);
2890 w2.setWidget(new QPushButton("W2"));
2892 QGraphicsProxyWidget w3(&w2);
2893 w3.setWidget(new QPushButton("W3"));
2900 QGraphicsView view(&scene);
2902 QVERIFY(QTest::qWaitForWindowExposed(&view));
2904 QCOMPARE(view.items(view.mapFromScene(w3.boundingRect().center())).first(),
2905 static_cast<QGraphicsItem *>(&w3));
2906 w2.setFlag(QGraphicsItem::ItemIgnoresTransformations, true);
2907 QCOMPARE(view.items(view.mapFromScene(w3.boundingRect().center())).first(),
2908 static_cast<QGraphicsItem *>(&w3));
2911 class QGraphicsTextItem_task172231 : public QGraphicsTextItem
2914 QGraphicsTextItem_task172231(const QString & text, QGraphicsItem * parent = 0)
2915 : QGraphicsTextItem(text, parent) {}
2917 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
2919 exposedRect = option->exposedRect;
2920 QGraphicsTextItem::paint(painter, option, widget);
2924 void tst_QGraphicsView::task172231_untransformableItems()
2926 // check fix in QGraphicsView::paintEvent()
2928 QGraphicsScene scene;
2930 QGraphicsTextItem_task172231 *text =
2931 new QGraphicsTextItem_task172231("abcdefghijklmnopqrstuvwxyz");
2932 text->setFlag(QGraphicsItem::ItemIgnoresTransformations);
2933 scene.addItem(text);
2935 QGraphicsView view(&scene);
2939 QApplication::setActiveWindow(&view);
2940 QVERIFY(QTest::qWaitForWindowActive(&view));
2941 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
2943 QRectF origExposedRect = text->exposedRect;
2945 view.resize(int(0.75 * view.width()), view.height());
2946 qApp->processEvents();
2948 QCOMPARE(text->exposedRect, origExposedRect);
2950 // notice that the fix also goes into QGraphicsView::render()
2951 // and QGraphicsScene::render(), but in duplicated code that
2952 // is pending a refactoring, so for now we omit autotesting
2953 // these functions separately
2956 class MousePressReleaseScene : public QGraphicsScene
2959 MousePressReleaseScene()
2960 : presses(0), releases(0)
2966 void mousePressEvent(QGraphicsSceneMouseEvent *event)
2967 { ++presses; QGraphicsScene::mousePressEvent(event); }
2968 void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
2969 { ++releases; QGraphicsScene::mouseReleaseEvent(event); }
2972 void tst_QGraphicsView::task180429_mouseReleaseDragMode()
2974 MousePressReleaseScene scene;
2976 QGraphicsView view(&scene);
2979 sendMousePress(view.viewport(), view.viewport()->rect().center());
2980 QCOMPARE(scene.presses, 1);
2981 QCOMPARE(scene.releases, 0);
2982 sendMouseRelease(view.viewport(), view.viewport()->rect().center());
2983 QCOMPARE(scene.presses, 1);
2984 QCOMPARE(scene.releases, 1);
2986 view.setDragMode(QGraphicsView::RubberBandDrag);
2987 sendMousePress(view.viewport(), view.viewport()->rect().center());
2988 QCOMPARE(scene.presses, 2);
2989 QCOMPARE(scene.releases, 1);
2990 sendMouseRelease(view.viewport(), view.viewport()->rect().center());
2991 QCOMPARE(scene.presses, 2);
2992 QCOMPARE(scene.releases, 2);
2995 void tst_QGraphicsView::task187791_setSceneCausesUpdate()
2997 QGraphicsScene scene(0, 0, 200, 200);
2998 QGraphicsView view(&scene);
3000 qApp->setActiveWindow(&view);
3001 QVERIFY(QTest::qWaitForWindowShown(&view));
3003 EventSpy updateSpy(view.viewport(), QEvent::Paint);
3004 QCOMPARE(updateSpy.count(), 0);
3007 QApplication::processEvents();
3008 QTRY_COMPARE(updateSpy.count(), 1);
3009 view.setScene(&scene);
3010 QApplication::processEvents();
3011 QTRY_COMPARE(updateSpy.count(), 2);
3014 class MouseMoveCounter : public QGraphicsView
3017 MouseMoveCounter() : mouseMoves(0)
3021 void mouseMoveEvent(QMouseEvent *event)
3024 QGraphicsView::mouseMoveEvent(event);
3025 foreach (QGraphicsItem *item, scene()->items()) {
3026 scene()->removeItem(item);
3029 scene()->addRect(0, 0, 50, 50);
3030 scene()->addRect(0, 0, 100, 100);
3034 void tst_QGraphicsView::task186827_deleteReplayedItem()
3036 // make sure the mouse is not over the window, causing spontaneous mouse moves
3037 QCursor::setPos(1, 1);
3039 QGraphicsScene scene;
3040 scene.addRect(0, 0, 50, 50);
3041 scene.addRect(0, 0, 100, 100);
3043 MouseMoveCounter view;
3044 view.setScene(&scene);
3046 QVERIFY(QTest::qWaitForWindowExposed(&view));
3047 view.viewport()->setMouseTracking(true);
3049 QCOMPARE(view.mouseMoves, 0);
3051 QMouseEvent event(QEvent::MouseMove, view.mapFromScene(25, 25), Qt::NoButton, 0, 0);
3052 QApplication::sendEvent(view.viewport(), &event);
3054 QCOMPARE(view.mouseMoves, 1);
3056 QTRY_COMPARE(view.mouseMoves, 1);
3059 QMouseEvent event(QEvent::MouseMove, view.mapFromScene(25, 25), Qt::NoButton, 0, 0);
3060 QApplication::sendEvent(view.viewport(), &event);
3062 QCOMPARE(view.mouseMoves, 2);
3066 void tst_QGraphicsView::task207546_focusCrash()
3068 class _Widget : public QWidget
3071 bool focusNextPrevChild(bool next) { return QWidget::focusNextPrevChild(next); }
3074 widget.setLayout(new QVBoxLayout());
3075 QGraphicsView *gr1 = new QGraphicsView(&widget);
3076 QGraphicsView *gr2 = new QGraphicsView(&widget);
3077 widget.layout()->addWidget(gr1);
3078 widget.layout()->addWidget(gr2);
3080 widget.activateWindow();
3081 QApplication::setActiveWindow(&widget);
3082 QVERIFY(QTest::qWaitForWindowActive(&widget));
3083 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&widget));
3084 widget.focusNextPrevChild(true);
3085 QCOMPARE(static_cast<QWidget *>(gr2), widget.focusWidget());
3088 void tst_QGraphicsView::task210599_unsetDragWhileDragging()
3090 QGraphicsScene scene(0, 0, 400, 400);
3091 QGraphicsView view(&scene);
3092 view.setGeometry(0, 0, 200, 200);
3095 QPoint origPos = QPoint(100, 100);
3096 QPoint step1Pos = QPoint(100, 110);
3097 QPoint step2Pos = QPoint(100, 120);
3099 // Enable and do a drag
3101 view.setDragMode(QGraphicsView::ScrollHandDrag);
3102 QMouseEvent press(QEvent::MouseButtonPress, origPos, Qt::LeftButton, 0, 0);
3103 QMouseEvent move(QEvent::MouseMove, step1Pos, Qt::LeftButton, 0, 0);
3104 QApplication::sendEvent(view.viewport(), &press);
3105 QApplication::sendEvent(view.viewport(), &move);
3108 // unset drag and release mouse, inverse order
3110 view.setDragMode(QGraphicsView::NoDrag);
3111 QMouseEvent release(QEvent::MouseButtonRelease, step1Pos, Qt::LeftButton, 0, 0);
3112 QApplication::sendEvent(view.viewport(), &release);
3115 QPoint basePos = view.mapFromScene(0, 0);
3117 // reset drag, and move mouse without holding button down.
3119 view.setDragMode(QGraphicsView::ScrollHandDrag);
3120 QMouseEvent move(QEvent::MouseMove, step2Pos, Qt::LeftButton, 0, 0);
3121 QApplication::sendEvent(view.viewport(), &move);
3124 // Check that no draggin has occurred...
3125 QCOMPARE(basePos, view.mapFromScene(0, 0));
3128 void tst_QGraphicsView::task236394_sendShortcutOverrideEvent()
3132 QKeyEvent event(QEvent::ShortcutOverride, Qt::Key_A, 0, QString("A"));
3133 QApplication::sendEvent(&view, &event);
3136 class ChangedListener : public QObject
3140 QList<QList<QRectF> > changes;
3143 void changed(const QList<QRectF> &dirty)
3149 void tst_QGraphicsView::task239729_noViewUpdate_data()
3151 QTest::addColumn<bool>("a");
3153 QTest::newRow("a") << false;
3154 QTest::newRow("b") << true;
3157 void tst_QGraphicsView::task239729_noViewUpdate()
3160 // The scene's changed signal is connected to something that isn't a view.
3161 QGraphicsScene scene;
3163 QGraphicsView *view = 0;
3166 view = new QGraphicsView(&scene);
3167 connect(&scene, SIGNAL(changed(QList<QRectF>)), &cl, SLOT(changed(QList<QRectF>)));
3169 connect(&scene, SIGNAL(changed(QList<QRectF>)), &cl, SLOT(changed(QList<QRectF>)));
3170 view = new QGraphicsView(&scene);
3173 EventSpy spy(view->viewport(), QEvent::Paint);
3174 QCOMPARE(spy.count(), 0);
3177 qApp->setActiveWindow(view);
3178 QVERIFY(QTest::qWaitForWindowActive(view));
3180 QTRY_VERIFY(spy.count() >= 1);
3183 QApplication::processEvents();
3184 QTRY_COMPARE(spy.count(), 1);
3189 void tst_QGraphicsView::task239047_fitInViewSmallViewport()
3191 // Ensure that with a small viewport, fitInView doesn't mirror the
3194 QGraphicsScene scene;
3195 QGraphicsView *view = new QGraphicsView(&scene, &widget);
3197 QCOMPARE(view->size(), QSize(3, 3));
3199 view->fitInView(0, 0, 100, 100);
3200 QPointF topLeft = view->mapToScene(0, 0);
3201 QPointF bottomRight = view->mapToScene(100, 100);
3202 QVERIFY(bottomRight.x() > topLeft.x());
3203 QVERIFY(bottomRight.y() > topLeft.y());
3205 view->fitInView(0, 0, 0, 100);
3209 view->fitInView(0, 0, 100, 100);
3212 void tst_QGraphicsView::task245469_itemsAtPointWithClip()
3214 QGraphicsScene scene;
3215 QGraphicsItem *parent = scene.addRect(0, 0, 100, 100);
3216 QGraphicsItem *child = new QGraphicsRectItem(40, 40, 20, 20, parent);
3217 parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
3219 QGraphicsView view(&scene);
3220 view.resize(150,150);
3223 QVERIFY(QTest::qWaitForWindowExposed(&view));
3225 QList<QGraphicsItem *> itemsAtCenter = view.items(view.viewport()->rect().center());
3226 QCOMPARE(itemsAtCenter, (QList<QGraphicsItem *>() << child << parent));
3228 QPolygonF p = view.mapToScene(QRect(view.viewport()->rect().center(), QSize(1, 1)));
3229 QList<QGraphicsItem *> itemsAtCenter2 = scene.items(p);
3230 QCOMPARE(itemsAtCenter2, itemsAtCenter);
3233 static QGraphicsView *createSimpleViewAndScene()
3235 QGraphicsView *view = new QGraphicsView;
3236 QGraphicsScene *scene = new QGraphicsScene;
3237 view->setScene(scene);
3239 view->setBackgroundBrush(Qt::blue);
3241 QGraphicsRectItem *rect = scene->addRect(0, 0, 10, 10);
3242 rect->setBrush(Qt::red);
3243 rect->setPen(Qt::NoPen);
3247 class SpyItem : public QGraphicsRectItem
3251 : QGraphicsRectItem(QRectF(0, 0, 100, 100))
3255 void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
3257 transform = painter->transform();
3260 QTransform transform;
3263 void tst_QGraphicsView::embeddedViews()
3265 QGraphicsView *v1 = createSimpleViewAndScene();
3266 QGraphicsView *v2 = createSimpleViewAndScene();
3268 QGraphicsProxyWidget *proxy = v1->scene()->addWidget(v2);
3270 SpyItem *item = new SpyItem;
3271 v2->scene()->addItem(item);
3273 proxy->translate(5, 5);
3275 QImage actual(64, 64, QImage::Format_ARGB32_Premultiplied);
3277 v1->QWidget::render(&actual);
3278 QTransform a = item->transform;
3280 v2->QWidget::render(&actual);
3281 QTransform b = item->transform;
3287 void tst_QGraphicsView::scrollAfterResize_data()
3289 QTest::addColumn<bool>("reverse");
3290 QTest::addColumn<QTransform>("x1");
3291 QTest::addColumn<QTransform>("x2");
3292 QTest::addColumn<QTransform>("x3");
3294 #if !defined(QT_NO_STYLE_PLASTIQUE)
3295 QPlastiqueStyle style;
3296 #elif !defined(QT_NO_STYLE_WINDOWS)
3297 QWindowsStyle style;
3302 int frameWidth = style.pixelMetric(QStyle::PM_DefaultFrameWidth);
3303 int extent = style.pixelMetric(QStyle::PM_ScrollBarExtent);
3304 int inside = style.styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents);
3305 int viewportWidth = 300;
3306 int scrollBarIndent = viewportWidth - extent - (inside ? 4 : 2)*frameWidth;
3308 QTest::newRow("normal") << false
3311 << QTransform().translate(-10, 0);
3312 QTest::newRow("reverse") << true
3313 << QTransform().translate(scrollBarIndent, 0)
3314 << QTransform().translate(scrollBarIndent + 100, 0)
3315 << QTransform().translate(scrollBarIndent + 110, 0);
3318 void tst_QGraphicsView::scrollAfterResize()
3320 QFETCH(bool, reverse);
3321 QFETCH(QTransform, x1);
3322 QFETCH(QTransform, x2);
3323 QFETCH(QTransform, x3);
3325 #if !defined(QT_NO_STYLE_PLASTIQUE)
3326 QPlastiqueStyle style;
3327 #elif !defined(QT_NO_STYLE_WINDOWS)
3328 QWindowsStyle style;
3334 QGraphicsView view(&toplevel);
3335 view.setStyle(&style);
3337 view.setLayoutDirection(Qt::RightToLeft);
3339 view.setSceneRect(-1000, -1000, 2000, 2000);
3340 view.resize(300, 300);
3342 QVERIFY(QTest::qWaitForWindowExposed(&toplevel));
3343 view.horizontalScrollBar()->setValue(0);
3344 view.verticalScrollBar()->setValue(0);
3345 QCOMPARE(view.viewportTransform(), x1);
3346 view.resize(400, 300);
3347 QCOMPARE(view.viewportTransform(), x2);
3348 view.horizontalScrollBar()->setValue(10);
3349 QCOMPARE(view.viewportTransform(), x3);
3352 void tst_QGraphicsView::moveItemWhileScrolling_data()
3354 QTest::addColumn<bool>("adjustForAntialiasing");
3355 QTest::addColumn<bool>("changedConnected");
3357 QTest::newRow("no adjust") << false << false;
3358 QTest::newRow("adjust") << true << false;
3359 QTest::newRow("no adjust changedConnected") << false << true;
3360 QTest::newRow("adjust changedConnected") << true << true;
3363 void tst_QGraphicsView::moveItemWhileScrolling()
3365 QFETCH(bool, adjustForAntialiasing);
3366 QFETCH(bool, changedConnected);
3368 class MoveItemScrollView : public QGraphicsView
3371 MoveItemScrollView()
3373 setWindowFlags(Qt::X11BypassWindowManagerHint);
3374 setScene(new QGraphicsScene(0, 0, 1000, 1000));
3375 rect = scene()->addRect(0, 0, 10, 10);
3376 rect->setPos(50, 50);
3377 rect->setPen(QPen(Qt::black, 0));
3380 QRegion lastPaintedRegion;
3381 QGraphicsRectItem *rect;
3383 void waitForPaintEvent()
3385 QTimer::singleShot(2000, &eventLoop, SLOT(quit()));
3389 QEventLoop eventLoop;
3390 void paintEvent(QPaintEvent *event)
3393 lastPaintedRegion = event->region();
3394 QGraphicsView::paintEvent(event);
3395 if (eventLoop.isRunning())
3400 MoveItemScrollView view;
3401 view.setFrameStyle(0);
3402 view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3403 view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
3404 view.setResizeAnchor(QGraphicsView::NoAnchor);
3405 view.setTransformationAnchor(QGraphicsView::NoAnchor);
3406 if (!adjustForAntialiasing)
3407 view.setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing);
3408 view.resize(200, 200);
3409 view.painted = false;
3411 if (changedConnected)
3412 QObject::connect(view.scene(), SIGNAL(changed(QList<QRectF>)), this, SLOT(dummySlot()));
3413 QVERIFY(QTest::qWaitForWindowExposed(&view));
3414 QApplication::processEvents();
3415 QTRY_VERIFY(view.painted);
3416 view.painted = false;
3417 view.lastPaintedRegion = QRegion();
3418 view.horizontalScrollBar()->setValue(view.horizontalScrollBar()->value() + 10);
3419 view.rect->moveBy(0, 10);
3420 view.waitForPaintEvent();
3421 QTRY_VERIFY(view.painted);
3423 QRegion expectedRegion;
3424 expectedRegion += QRect(0, 0, 200, 200);
3425 expectedRegion -= QRect(0, 0, 190, 200);
3426 int a = adjustForAntialiasing ? 2 : 1;
3427 expectedRegion += QRect(40, 50, 10, 10).adjusted(-a, -a, a, a);
3428 expectedRegion += QRect(40, 60, 10, 10).adjusted(-a, -a, a, a);
3429 COMPARE_REGIONS(view.lastPaintedRegion, expectedRegion);
3432 void tst_QGraphicsView::centerOnDirtyItem()
3436 QGraphicsView view(&toplevel);
3437 toplevel.setWindowFlags(view.windowFlags() | Qt::WindowStaysOnTopHint);
3438 view.resize(200, 200);
3440 QGraphicsScene *scene = new QGraphicsScene;
3441 view.setScene(scene);
3442 view.setSceneRect(-1000, -1000, 2000, 2000);
3444 QGraphicsRectItem *item = new QGraphicsRectItem(0, 0, 10, 10);
3445 item->setBrush(Qt::red);
3446 scene->addItem(item);
3447 view.centerOn(item);
3450 QVERIFY(QTest::qWaitForWindowExposed(&toplevel));
3453 QImage before(view.viewport()->size(), QImage::Format_ARGB32);
3454 view.viewport()->render(&before);
3456 item->setPos(20, 0);
3457 view.centerOn(item);
3461 QImage after(view.viewport()->size(), QImage::Format_ARGB32);
3462 view.viewport()->render(&after);
3464 QCOMPARE(before, after);
3467 void tst_QGraphicsView::mouseTracking()
3469 // Mouse tracking should only be automatically enabled if items either accept hover events
3470 // or have a cursor set. We never disable mouse tracking if it is already enabled.
3472 { // Make sure mouse tracking is disabled by default.
3473 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3474 QGraphicsView view(&scene);
3475 QVERIFY(!view.viewport()->hasMouseTracking());
3478 { // Make sure we don't disable mouse tracking in setupViewport/setScene.
3480 QWidget *viewport = new QWidget;
3481 viewport->setMouseTracking(true);
3482 view.setViewport(viewport);
3483 QVERIFY(viewport->hasMouseTracking());
3485 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3486 view.setScene(&scene);
3487 QVERIFY(viewport->hasMouseTracking());
3490 // Make sure we enable mouse tracking when having items that accept hover events.
3492 // Adding an item to the scene after the scene is set on the view.
3493 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3494 QGraphicsView view(&scene);
3496 QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
3497 item->setAcceptHoverEvents(true);
3498 scene.addItem(item);
3499 QVERIFY(view.viewport()->hasMouseTracking());
3502 // Adding an item to the scene before the scene is set on the view.
3503 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3504 QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
3505 item->setAcceptHoverEvents(true);
3506 scene.addItem(item);
3508 QGraphicsView view(&scene);
3509 QVERIFY(view.viewport()->hasMouseTracking());
3512 // QGraphicsWidget implicitly accepts hover if it has window decoration.
3513 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3514 QGraphicsView view(&scene);
3516 QGraphicsWidget *widget = new QGraphicsWidget;
3517 scene.addItem(widget);
3518 QVERIFY(!view.viewport()->hasMouseTracking());
3519 // Enable window decoraton.
3520 widget->setWindowFlags(Qt::Window | Qt::WindowTitleHint);
3521 QVERIFY(view.viewport()->hasMouseTracking());
3524 // Make sure we enable mouse tracking when having items with a cursor set.
3526 // Adding an item to the scene after the scene is set on the view.
3527 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3528 QGraphicsView view(&scene);
3530 QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
3531 #ifndef QTEST_NO_CURSOR
3532 item->setCursor(Qt::CrossCursor);
3534 scene.addItem(item);
3535 QVERIFY(view.viewport()->hasMouseTracking());
3538 // Adding an item to the scene before the scene is set on the view.
3539 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3540 QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
3541 #ifndef QTEST_NO_CURSOR
3542 item->setCursor(Qt::CrossCursor);
3544 scene.addItem(item);
3546 QGraphicsView view(&scene);
3547 QVERIFY(view.viewport()->hasMouseTracking());
3550 // Make sure we propagate mouse tracking to all views.
3552 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3553 QGraphicsView view1(&scene);
3554 QGraphicsView view2(&scene);
3555 QGraphicsView view3(&scene);
3557 QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
3558 #ifndef QTEST_NO_CURSOR
3559 item->setCursor(Qt::CrossCursor);
3561 scene.addItem(item);
3563 QVERIFY(view1.viewport()->hasMouseTracking());
3564 QVERIFY(view2.viewport()->hasMouseTracking());
3565 QVERIFY(view3.viewport()->hasMouseTracking());
3569 void tst_QGraphicsView::mouseTracking2()
3571 // Make sure mouse move events propagates to the scene when
3572 // mouse tracking is explicitly enabled on the view,
3573 // even when all items ignore hover events / use default cursor.
3575 QGraphicsScene scene;
3576 scene.addRect(0, 0, 100, 100);
3578 QGraphicsView view(&scene);
3580 QVERIFY(QTest::qWaitForWindowExposed(&view));
3582 QVERIFY(!view.viewport()->hasMouseTracking());
3583 view.viewport()->setMouseTracking(true); // Explicitly enable mouse tracking.
3584 QVERIFY(view.viewport()->hasMouseTracking());
3586 EventSpy spy(&scene, QEvent::GraphicsSceneMouseMove);
3587 QCOMPARE(spy.count(), 0);
3588 QMouseEvent event(QEvent::MouseMove,view.viewport()->rect().center(), Qt::NoButton,
3589 Qt::MouseButtons(Qt::NoButton), 0);
3590 QApplication::sendEvent(view.viewport(), &event);
3591 QCOMPARE(spy.count(), 1);
3594 void tst_QGraphicsView::mouseTracking3()
3596 // Mouse tracking should be automatically enabled if AnchorUnderMouse is used for
3597 // view transform or resize. We never disable mouse tracking if it is already enabled.
3599 { // Make sure we enable mouse tracking when using AnchorUnderMouse for view transformation.
3600 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3601 QGraphicsView view(&scene);
3602 QVERIFY(!view.viewport()->hasMouseTracking());
3604 view.setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
3605 QVERIFY(view.viewport()->hasMouseTracking());
3608 { // Make sure we enable mouse tracking when using AnchorUnderMouse for view resizing.
3609 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3610 QGraphicsView view(&scene);
3611 QVERIFY(!view.viewport()->hasMouseTracking());
3613 view.setResizeAnchor(QGraphicsView::AnchorUnderMouse);
3614 QVERIFY(view.viewport()->hasMouseTracking());
3617 { // Make sure we don't disable mouse tracking in setViewport/setScene (transformation anchor).
3619 view.setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
3620 QVERIFY(view.viewport()->hasMouseTracking());
3622 QWidget *viewport = new QWidget;
3623 view.setViewport(viewport);
3624 QVERIFY(viewport->hasMouseTracking());
3626 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3627 view.setScene(&scene);
3628 QVERIFY(viewport->hasMouseTracking());
3631 { // Make sure we don't disable mouse tracking in setViewport/setScene (resize anchor).
3633 view.setResizeAnchor(QGraphicsView::AnchorUnderMouse);
3634 QVERIFY(view.viewport()->hasMouseTracking());
3636 QWidget *viewport = new QWidget;
3637 view.setViewport(viewport);
3638 QVERIFY(viewport->hasMouseTracking());
3640 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3641 view.setScene(&scene);
3642 QVERIFY(viewport->hasMouseTracking());
3645 // Make sure we don't disable mouse tracking when adding an item (transformation anchor).
3646 { // Adding an item to the scene before the scene is set on the view.
3647 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3648 QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
3649 scene.addItem(item);
3652 view.setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
3653 view.setScene(&scene);
3654 QVERIFY(view.viewport()->hasMouseTracking());
3657 { // Adding an item to the scene after the scene is set on the view.
3658 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3659 QGraphicsView view(&scene);
3660 view.setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
3662 QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
3663 scene.addItem(item);
3664 QVERIFY(view.viewport()->hasMouseTracking());
3667 // Make sure we don't disable mouse tracking when adding an item (resize anchor).
3668 { // Adding an item to the scene before the scene is set on the view.
3669 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3670 QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
3671 scene.addItem(item);
3674 view.setResizeAnchor(QGraphicsView::AnchorUnderMouse);
3675 view.setScene(&scene);
3676 QVERIFY(view.viewport()->hasMouseTracking());
3679 { // Adding an item to the scene after the scene is set on the view.
3680 QGraphicsScene scene(-10000, -10000, 20000, 20000);
3681 QGraphicsView view(&scene);
3682 view.setResizeAnchor(QGraphicsView::AnchorUnderMouse);
3684 QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
3685 scene.addItem(item);
3686 QVERIFY(view.viewport()->hasMouseTracking());
3690 class RenderTester : public QGraphicsRectItem
3693 RenderTester(const QRectF &rect)
3694 : QGraphicsRectItem(rect), paints(0)
3697 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
3700 QGraphicsRectItem::paint(painter, option, widget);
3707 void tst_QGraphicsView::render()
3709 // ### This test can be much more thorough - see QGraphicsScene::render.
3710 QGraphicsScene scene;
3711 CustomView view(&scene);
3712 view.setFrameStyle(0);
3713 view.resize(200, 200);
3714 view.painted = false;
3716 QVERIFY(QTest::qWaitForWindowExposed(&view));
3717 QApplication::processEvents();
3718 QTRY_VERIFY(view.painted);
3720 RenderTester *r1 = new RenderTester(QRectF(0, 0, 50, 50));
3721 RenderTester *r2 = new RenderTester(QRectF(50, 50, 50, 50));
3722 RenderTester *r3 = new RenderTester(QRectF(0, 50, 50, 50));
3723 RenderTester *r4 = new RenderTester(QRectF(50, 0, 50, 50));
3729 qApp->processEvents();
3731 QTRY_COMPARE(r1->paints, 1);
3732 QCOMPARE(r2->paints, 1);
3733 QCOMPARE(r3->paints, 1);
3734 QCOMPARE(r4->paints, 1);
3736 QPixmap pix(200, 200);
3737 pix.fill(Qt::transparent);
3738 QPainter painter(&pix);
3739 view.render(&painter);
3742 QCOMPARE(r1->paints, 2);
3743 QCOMPARE(r2->paints, 2);
3744 QCOMPARE(r3->paints, 2);
3745 QCOMPARE(r4->paints, 2);
3748 void tst_QGraphicsView::exposeRegion()
3750 RenderTester *item = new RenderTester(QRectF(0, 0, 20, 20));
3751 QGraphicsScene scene;
3752 scene.addItem(item);
3756 view.setScene(&scene);
3758 qApp->setActiveWindow(&view);
3759 QVERIFY(QTest::qWaitForWindowActive(&view));
3761 QTRY_VERIFY(item->paints > 0);
3764 view.lastUpdateRegions.clear();
3766 // Update a small area in the viewport's topLeft() and bottomRight().
3767 // (the boundingRect() of this area covers the entire viewport).
3768 QWidget *viewport = view.viewport();
3769 QRegion expectedExposeRegion = QRect(0, 0, 5, 5);
3770 expectedExposeRegion += QRect(viewport->rect().bottomRight() - QPoint(5, 5), QSize(5, 5));
3771 viewport->update(expectedExposeRegion);
3772 QApplication::processEvents();
3774 // Make sure it triggers correct repaint on the view.
3775 QTRY_COMPARE(view.lastUpdateRegions.size(), 1);
3776 COMPARE_REGIONS(view.lastUpdateRegions.at(0), expectedExposeRegion);
3778 // Make sure the item didn't get any repaints.
3780 QCOMPARE(item->paints, 0);
3784 void tst_QGraphicsView::update_data()
3786 // In view.viewport() coordinates. (viewport rect: QRect(0, 0, 200, 200))
3787 QTest::addColumn<QRect>("updateRect");
3788 QTest::newRow("empty") << QRect();
3789 QTest::newRow("outside left") << QRect(-200, 0, 100, 100);
3790 QTest::newRow("outside right") << QRect(400, 0 ,100, 100);
3791 QTest::newRow("outside top") << QRect(0, -200, 100, 100);
3792 QTest::newRow("outside bottom") << QRect(0, 400, 100, 100);
3793 QTest::newRow("partially inside left") << QRect(-50, 0, 100, 100);
3794 QTest::newRow("partially inside right") << QRect(-150, 0, 100, 100);
3795 QTest::newRow("partially inside top") << QRect(0, -150, 100, 100);
3796 QTest::newRow("partially inside bottom") << QRect(0, 150, 100, 100);
3797 QTest::newRow("on topLeft edge") << QRect(-100, -100, 100, 100);
3798 QTest::newRow("on topRight edge") << QRect(200, -100, 100, 100);
3799 QTest::newRow("on bottomRight edge") << QRect(200, 200, 100, 100);
3800 QTest::newRow("on bottomLeft edge") << QRect(-200, 200, 100, 100);
3801 QTest::newRow("inside topLeft") << QRect(-99, -99, 100, 100);
3802 QTest::newRow("inside topRight") << QRect(199, -99, 100, 100);
3803 QTest::newRow("inside bottomRight") << QRect(199, 199, 100, 100);
3804 QTest::newRow("inside bottomLeft") << QRect(-199, 199, 100, 100);
3805 QTest::newRow("large1") << QRect(50, -100, 100, 400);
3806 QTest::newRow("large2") << QRect(-100, 50, 400, 100);
3807 QTest::newRow("large3") << QRect(-100, -100, 400, 400);
3808 QTest::newRow("viewport rect") << QRect(0, 0, 200, 200);
3811 void tst_QGraphicsView::update()
3813 QFETCH(QRect, updateRect);
3815 // some window manager resize the toplevel to max screen size
3816 // so we must make our view a child (no layout!) of a dummy toplevel
3817 // to ensure that it's really 200x200 pixels
3820 // Create a view with viewport rect equal to QRect(0, 0, 200, 200).
3821 QGraphicsScene dummyScene;
3822 CustomView view(0, &toplevel);
3823 view.setScene(&dummyScene);
3824 view.ensurePolished(); // must ensure polished to get content margins right
3825 int left, top, right, bottom;
3826 view.getContentsMargins(&left, &top, &right, &bottom);
3827 view.resize(200 + left + right, 200 + top + bottom);
3829 QVERIFY(QTest::qWaitForWindowExposed(&toplevel));
3832 QApplication::setActiveWindow(&toplevel);
3833 QApplication::processEvents();
3834 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&toplevel));
3836 const QRect viewportRect = view.viewport()->rect();
3837 QCOMPARE(viewportRect, QRect(0, 0, 200, 200));
3839 #if defined QT_BUILD_INTERNAL
3840 const bool intersects = updateRect.intersects(viewportRect);
3841 QGraphicsViewPrivate *viewPrivate = static_cast<QGraphicsViewPrivate *>(qt_widget_private(&view));
3842 QTRY_COMPARE(viewPrivate->updateRect(updateRect), intersects);
3843 QApplication::processEvents();
3845 view.lastUpdateRegions.clear();
3846 viewPrivate->processPendingUpdates();
3847 QVERIFY(viewPrivate->dirtyRegion.isEmpty());
3848 QVERIFY(viewPrivate->dirtyBoundingRect.isEmpty());
3849 QApplication::processEvents();
3851 QTRY_VERIFY(view.lastUpdateRegions.isEmpty());
3853 QTRY_COMPARE(view.lastUpdateRegions.size(), 1);
3854 QTRY_COMPARE(view.lastUpdateRegions.at(0), QRegion(updateRect) & viewportRect);
3856 QTRY_VERIFY(!viewPrivate->fullUpdatePending);
3860 void tst_QGraphicsView::update2_data()
3862 QTest::addColumn<qreal>("penWidth");
3863 QTest::addColumn<bool>("antialiasing");
3864 QTest::addColumn<bool>("changedConnected");
3867 QTest::newRow("pen width: 0.0, antialiasing: true") << qreal(0.0) << true << false;
3868 QTest::newRow("pen width: 1.5, antialiasing: true") << qreal(1.5) << true << false;
3869 QTest::newRow("pen width: 2.0, antialiasing: true") << qreal(2.0) << true << false;
3870 QTest::newRow("pen width: 3.0, antialiasing: true") << qreal(3.0) << true << false;
3873 QTest::newRow("pen width: 0.0, antialiasing: false") << qreal(0.0) << false << false;
3874 QTest::newRow("pen width: 1.5, antialiasing: false") << qreal(1.5) << false << false;
3875 QTest::newRow("pen width: 2.0, antialiasing: false") << qreal(2.0) << false << false;
3876 QTest::newRow("pen width: 3.0, antialiasing: false") << qreal(3.0) << false << false;
3878 // changed() connected
3879 QTest::newRow("pen width: 0.0, antialiasing: false, changed") << qreal(0.0) << false << true;
3880 QTest::newRow("pen width: 1.5, antialiasing: true, changed") << qreal(1.5) << true << true;
3881 QTest::newRow("pen width: 2.0, antialiasing: false, changed") << qreal(2.0) << false << true;
3882 QTest::newRow("pen width: 3.0, antialiasing: true, changed") << qreal(3.0) << true << true;
3885 void tst_QGraphicsView::update2()
3887 QFETCH(qreal, penWidth);
3888 QFETCH(bool, antialiasing);
3889 QFETCH(bool, changedConnected);
3891 // Create a rect item.
3892 const QRectF rawItemRect(-50.4, -50.3, 100.2, 100.1);
3893 CountPaintItem *rect = new CountPaintItem(rawItemRect);
3895 pen.setWidthF(penWidth);
3898 // Add item to a scene.
3899 QGraphicsScene scene(-100, -100, 200, 200);
3900 if (changedConnected)
3901 QObject::connect(&scene, SIGNAL(changed(QList<QRectF>)), this, SLOT(dummySlot()));
3903 scene.addItem(rect);
3905 // Create a view on the scene.
3906 CustomView view(&scene);
3907 view.setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing, !antialiasing);
3908 view.setRenderHint(QPainter::Antialiasing, antialiasing);
3909 view.setFrameStyle(0);
3910 view.resize(200, 200);
3912 qApp->setActiveWindow(&view);
3913 QVERIFY(QTest::qWaitForWindowActive(&view));
3914 QTRY_VERIFY(rect->numPaints > 0);
3916 // Calculate expected update region for the rect.
3917 QRectF expectedItemBoundingRect = rawItemRect;
3918 const qreal halfPenWidth = penWidth / qreal(2.0);
3919 expectedItemBoundingRect.adjust(-halfPenWidth, -halfPenWidth, halfPenWidth, halfPenWidth);
3920 QCOMPARE(rect->boundingRect(), expectedItemBoundingRect);
3922 QRect expectedItemDeviceBoundingRect = rect->deviceTransform(view.viewportTransform())
3923 .mapRect(expectedItemBoundingRect).toAlignedRect();
3925 expectedItemDeviceBoundingRect.adjust(-2, -2, 2, 2);
3927 expectedItemDeviceBoundingRect.adjust(-1, -1, 1, 1);
3928 const QRegion expectedUpdateRegion(expectedItemDeviceBoundingRect);
3931 rect->numPaints = 0;
3932 view.lastUpdateRegions.clear();
3933 view.painted = false;
3936 QTRY_VERIFY(view.painted);
3938 #ifndef Q_OS_MAC //cocoa doesn't support drawing regions
3939 QTRY_VERIFY(view.painted);
3940 QCOMPARE(view.lastUpdateRegions.size(), 1);
3941 QCOMPARE(view.lastUpdateRegions.at(0), expectedUpdateRegion);
3945 void tst_QGraphicsView::update_ancestorClipsChildrenToShape()
3947 QGraphicsScene scene(-150, -150, 300, 300);
3952 +------------------+
3954 | +--------------+ |
3959 | +--------------+ |
3960 +------------------+
3962 ... where both the parent and the grand parent clips children to shape.
3964 QApplication::processEvents(); // Get rid of pending update.
3966 QGraphicsRectItem *grandParent = static_cast<QGraphicsRectItem *>(scene.addRect(0, 0, 50, 50));
3967 grandParent->setBrush(Qt::black);
3968 grandParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
3970 QGraphicsRectItem *parent = static_cast<QGraphicsRectItem *>(scene.addRect(-50, -50, 100, 100));
3971 parent->setBrush(QColor(0, 0, 255, 125));
3972 parent->setParentItem(grandParent);
3973 parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
3975 QGraphicsRectItem *child = static_cast<QGraphicsRectItem *>(scene.addRect(-100, -100, 200, 200));
3976 child->setBrush(QColor(255, 0, 0, 125));
3977 child->setParentItem(parent);
3979 CustomView view(&scene);
3981 qApp->setActiveWindow(&view);
3982 QVERIFY(QTest::qWaitForWindowActive(&view));
3983 QTRY_VERIFY(view.painted);
3985 view.lastUpdateRegions.clear();
3986 view.painted = false;
3988 // Call child->update() and make sure the updated area is within the ancestors' clip.
3989 QRectF expected = child->deviceTransform(view.viewportTransform()).mapRect(child->boundingRect());
3990 expected &= grandParent->deviceTransform(view.viewportTransform()).mapRect(grandParent->boundingRect());
3993 QTRY_VERIFY(view.painted);
3995 #ifndef Q_OS_MAC //cocoa doesn't support drawing regions
3996 QTRY_VERIFY(view.painted);
3997 QCOMPARE(view.lastUpdateRegions.size(), 1);
3998 QCOMPARE(view.lastUpdateRegions.at(0), QRegion(expected.toAlignedRect()));
4002 void tst_QGraphicsView::update_ancestorClipsChildrenToShape2()
4004 QGraphicsScene scene(-150, -150, 300, 300);
4009 +------------------+
4011 | +--------------+ |
4016 | +--------------+ |
4017 +------------------+
4019 ... where the parent has no contents and clips the child to shape.
4021 QApplication::processEvents(); // Get rid of pending update.
4023 QGraphicsRectItem *parent = static_cast<QGraphicsRectItem *>(scene.addRect(-50, -50, 100, 100));
4024 parent->setBrush(QColor(0, 0, 255, 125));
4025 parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
4026 parent->setFlag(QGraphicsItem::ItemHasNoContents);
4028 QGraphicsRectItem *child = static_cast<QGraphicsRectItem *>(scene.addRect(-100, -100, 200, 200));
4029 child->setBrush(QColor(255, 0, 0, 125));
4030 child->setParentItem(parent);
4032 CustomView view(&scene);
4034 qApp->setActiveWindow(&view);
4035 QVERIFY(QTest::qWaitForWindowActive(&view));
4036 QTRY_VERIFY(view.painted);
4038 view.lastUpdateRegions.clear();
4039 view.painted = false;
4041 // Call child->update() and make sure the updated area is within its parent's clip.
4042 QRectF expected = child->deviceTransform(view.viewportTransform()).mapRect(child->boundingRect());
4043 expected &= parent->deviceTransform(view.viewportTransform()).mapRect(parent->boundingRect());
4046 QTRY_VERIFY(view.painted);
4048 #ifndef Q_OS_MAC //cocoa doesn't support drawing regions
4049 QTRY_VERIFY(view.painted);
4050 QCOMPARE(view.lastUpdateRegions.size(), 1);
4051 QCOMPARE(view.lastUpdateRegions.at(0), QRegion(expected.toAlignedRect()));
4056 view.lastUpdateRegions.clear();
4057 view.painted = false;
4059 // Invalidate the parent's geometry and trigger an update.
4060 // The update area should be clipped to the parent's bounding rect for 'normal' items,
4061 // but in this case the item has no contents (ItemHasNoContents) and its geometry
4062 // is invalidated, which means we cannot clip the child update. So, the expected
4063 // area is exactly the same as the child's bounding rect (adjusted for antialiasing).
4064 parent->setRect(parent->rect().adjusted(-10, -10, -10, -10));
4065 expected = child->deviceTransform(view.viewportTransform()).mapRect(child->boundingRect());
4066 expected.adjust(-2, -2, 2, 2); // Antialiasing
4068 #ifndef Q_OS_MAC //cocoa doesn't support drawing regions
4069 QTRY_VERIFY(view.painted);
4070 QCOMPARE(view.lastUpdateRegions.size(), 1);
4071 QCOMPARE(view.lastUpdateRegions.at(0), QRegion(expected.toAlignedRect()));
4075 class FocusItem : public QGraphicsRectItem
4078 FocusItem() : QGraphicsRectItem(0, 0, 20, 20) {
4079 m_viewHasIMEnabledInFocusInEvent = false;
4082 void focusInEvent(QFocusEvent * /* event */)
4084 QGraphicsView *view = scene()->views().first();
4085 m_viewHasIMEnabledInFocusInEvent = view->testAttribute(Qt::WA_InputMethodEnabled);
4088 bool m_viewHasIMEnabledInFocusInEvent;
4091 void tst_QGraphicsView::inputMethodSensitivity()
4093 QGraphicsScene scene;
4094 QGraphicsView view(&scene);
4096 QApplication::setActiveWindow(&view);
4097 QVERIFY(QTest::qWaitForWindowActive(&view));
4098 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
4100 FocusItem *item = new FocusItem;
4102 view.setAttribute(Qt::WA_InputMethodEnabled, true);
4104 scene.addItem(item);
4105 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
4107 scene.removeItem(item);
4108 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
4110 item->setFlag(QGraphicsItem::ItemAcceptsInputMethod);
4111 scene.addItem(item);
4112 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
4114 scene.removeItem(item);
4115 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
4117 scene.addItem(item);
4118 scene.setFocusItem(item);
4119 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
4121 scene.removeItem(item);
4122 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
4124 item->setFlag(QGraphicsItem::ItemIsFocusable);
4125 scene.addItem(item);
4126 scene.setFocusItem(item);
4127 QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
4128 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true);
4129 QCOMPARE(item->m_viewHasIMEnabledInFocusInEvent, true);
4131 item->setFlag(QGraphicsItem::ItemAcceptsInputMethod, false);
4132 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
4134 item->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
4135 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true);
4137 // introduce another item that is focusable but does not accept input methods
4138 FocusItem *item2 = new FocusItem;
4139 item2->setFlag(QGraphicsItem::ItemIsFocusable);
4140 scene.addItem(item2);
4141 scene.setFocusItem(item2);
4142 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
4143 QCOMPARE(item2->m_viewHasIMEnabledInFocusInEvent, false);
4144 QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item2));
4146 scene.setFocusItem(item);
4147 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true);
4148 QCOMPARE(item->m_viewHasIMEnabledInFocusInEvent, true);
4149 QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
4152 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
4153 QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
4155 view.setScene(&scene);
4156 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true);
4157 QCOMPARE(item->m_viewHasIMEnabledInFocusInEvent, true);
4158 QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
4160 scene.setFocusItem(item2);
4161 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
4162 QCOMPARE(item2->m_viewHasIMEnabledInFocusInEvent, false);
4163 QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item2));
4166 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
4167 QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item2));
4169 scene.setFocusItem(item);
4170 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), false);
4171 QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
4173 view.setScene(&scene);
4174 QCOMPARE(view.testAttribute(Qt::WA_InputMethodEnabled), true);
4175 QCOMPARE(item->m_viewHasIMEnabledInFocusInEvent, true);
4176 QCOMPARE(scene.focusItem(), static_cast<QGraphicsItem *>(item));
4179 void tst_QGraphicsView::inputContextReset()
4181 PlatformInputContext inputContext;
4182 QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
4183 inputMethodPrivate->testContext = &inputContext;
4185 QGraphicsScene scene;
4186 QGraphicsView view(&scene);
4187 QVERIFY(view.testAttribute(Qt::WA_InputMethodEnabled));
4190 QApplication::setActiveWindow(&view);
4191 QVERIFY(QTest::qWaitForWindowActive(&view));
4192 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
4194 QGraphicsItem *item1 = new QGraphicsRectItem;
4195 item1->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemAcceptsInputMethod);
4197 inputContext.m_resetCallCount = 0;
4198 inputContext.m_commitCallCount = 0;
4199 scene.addItem(item1);
4200 QCOMPARE(inputContext.m_resetCallCount, 0);
4201 QCOMPARE(inputContext.m_commitCallCount, 0);
4203 scene.setFocusItem(item1);
4204 QCOMPARE(scene.focusItem(), (QGraphicsItem *)item1);
4205 QVERIFY(view.testAttribute(Qt::WA_InputMethodEnabled));
4206 QCOMPARE(inputContext.m_resetCallCount, 0);
4207 QCOMPARE(inputContext.m_commitCallCount, 0);
4209 scene.setFocusItem(0);
4210 // the input context is reset twice, once because an item has lost focus and again because
4211 // the Qt::WA_InputMethodEnabled flag is cleared because no item has focus.
4212 // QEXPECT_FAIL("", "QTBUG-22454", Abort);
4213 QCOMPARE(inputContext.m_resetCallCount + inputContext.m_commitCallCount, 2);
4215 // introduce another item that is focusable but does not accept input methods
4216 QGraphicsItem *item2 = new QGraphicsRectItem;
4217 item2->setFlags(QGraphicsItem::ItemIsFocusable);
4218 scene.addItem(item2);
4220 inputContext.m_resetCallCount = 0;
4221 inputContext.m_commitCallCount = 0;
4222 scene.setFocusItem(item2);
4223 QCOMPARE(inputContext.m_resetCallCount, 0);
4224 QCOMPARE(inputContext.m_commitCallCount, 0);
4226 scene.setFocusItem(item1);
4227 QCOMPARE(inputContext.m_resetCallCount, 0);
4228 QCOMPARE(inputContext.m_commitCallCount, 0);
4230 // test changing between between items that accept input methods.
4231 item2->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemAcceptsInputMethod);
4232 scene.setFocusItem(item2);
4233 QCOMPARE(inputContext.m_resetCallCount + inputContext.m_commitCallCount, 1);
4236 void tst_QGraphicsView::indirectPainting()
4238 class MyScene : public QGraphicsScene
4240 MyScene() : QGraphicsScene(), drawCount(0) {}
4241 void drawItems(QPainter *, int, QGraphicsItem **, const QStyleOptionGraphicsItem *, QWidget *)
4247 QGraphicsItem *item = scene.addRect(0, 0, 50, 50);
4249 QGraphicsView view(&scene);
4250 view.setOptimizationFlag(QGraphicsView::IndirectPainting);
4252 QVERIFY(QTest::qWaitForWindowExposed(&view));
4255 scene.drawCount = 0;
4256 item->setPos(20, 20);
4257 QApplication::processEvents();
4258 QTRY_VERIFY(scene.drawCount > 0);
4261 void tst_QGraphicsView::compositionModeInDrawBackground()
4263 class MyView : public QGraphicsView
4265 MyView(QGraphicsScene *scene) : QGraphicsView(scene),
4266 painted(false), compositionMode(QPainter::CompositionMode_SourceOver) {}
4268 QPainter::CompositionMode compositionMode;
4269 void drawBackground(QPainter *painter, const QRectF &)
4271 compositionMode = painter->compositionMode();
4276 QGraphicsScene dummy;
4277 MyView view(&dummy);
4279 QVERIFY(QTest::qWaitForWindowExposed(&view));
4281 // Make sure the painter's composition mode is SourceOver in drawBackground.
4282 QTRY_VERIFY(view.painted);
4283 QCOMPARE(view.compositionMode, QPainter::CompositionMode_SourceOver);
4285 view.painted = false;
4286 view.setCacheMode(QGraphicsView::CacheBackground);
4287 view.viewport()->update();
4289 // Make sure the painter's composition mode is SourceOver in drawBackground
4290 // with background cache enabled.
4291 QTRY_VERIFY(view.painted);
4292 QCOMPARE(view.compositionMode, QPainter::CompositionMode_SourceOver);
4294 void tst_QGraphicsView::task253415_reconnectUpdateSceneOnSceneChanged()
4297 QGraphicsView dummyView;
4298 view.setWindowFlags(view.windowFlags() | Qt::WindowStaysOnTopHint);
4299 view.resize(200, 200);
4301 QGraphicsScene scene1;
4302 QObject::connect(&scene1, SIGNAL(changed(QList<QRectF>)), &dummyView, SLOT(updateScene(QList<QRectF>)));
4303 view.setScene(&scene1);
4307 QGraphicsScene scene2;
4308 QObject::connect(&scene2, SIGNAL(changed(QList<QRectF>)), &dummyView, SLOT(updateScene(QList<QRectF>)));
4309 view.setScene(&scene2);
4313 bool wasConnected2 = QObject::disconnect(&scene2, SIGNAL(changed(QList<QRectF>)), &view, 0);
4314 QVERIFY(wasConnected2);
4317 void tst_QGraphicsView::task255529_transformationAnchorMouseAndViewportMargins()
4319 #if defined(Q_OS_WINCE)
4320 QSKIP("Qt/CE does not implement mouse tracking at this point");
4322 QGraphicsScene scene(-100, -100, 200, 200);
4323 scene.addRect(QRectF(-50, -50, 100, 100), QPen(Qt::black), QBrush(Qt::blue));
4325 class VpGraphicsView: public QGraphicsView
4328 VpGraphicsView(QGraphicsScene *scene, QWidget *parent=0)
4329 : QGraphicsView(scene, parent)
4331 setViewportMargins(8, 16, 12, 20);
4332 setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
4333 setMouseTracking(true);
4337 VpGraphicsView view(&scene);
4338 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
4340 qApp->setActiveWindow(&view);
4341 QVERIFY(QTest::qWaitForWindowActive(&view));
4342 // This is highly unstable (observed to pass on Windows and some Linux configurations).
4344 for (int i = 0; i < 4; ++i) {
4345 QPoint mouseViewPos(20, 20);
4346 sendMouseMove(view.viewport(), mouseViewPos);
4348 QPointF mouseScenePos = view.mapToScene(mouseViewPos);
4349 view.setTransform(QTransform().scale(5, 5).rotate(5, Qt::ZAxis), true);
4353 QPointF newMouseScenePos = view.mapToScene(mouseViewPos);
4355 const qreal dx = qAbs(newMouseScenePos.x() - mouseScenePos.x());
4356 const qreal dy = qAbs(newMouseScenePos.y() - mouseScenePos.y());
4357 const QByteArray message = QString::fromLatin1("QTBUG-22455, distance: dx=%1, dy=%2 slack=%3 (%4).").
4358 arg(dx).arg(dy).arg(slack).arg(qApp->style()->metaObject()->className()).toLocal8Bit();
4359 if (i == 9 || (dx < slack && dy < slack)) {
4360 QVERIFY2(dx < slack && dy < slack, message.constData());
4369 void tst_QGraphicsView::task259503_scrollingArtifacts()
4371 QGraphicsScene scene(0, 0, 800, 600);
4373 QGraphicsRectItem card;
4374 card.setRect(0, 0, 50, 50);
4375 card.setPen(QPen(Qt::darkRed));
4376 card.setBrush(QBrush(Qt::cyan));
4377 card.setZValue(2.0);
4378 card.setPos(300, 300);
4379 scene.addItem(&card);
4381 class SAGraphicsView: public QGraphicsView
4384 SAGraphicsView(QGraphicsScene *scene)
4385 : QGraphicsView(scene)
4386 , itSTimeToTest(false)
4388 setViewportUpdateMode( QGraphicsView::MinimalViewportUpdate );
4389 resize(QSize(640, 480));
4392 QRegion updateRegion;
4395 void paintEvent(QPaintEvent *event)
4397 QGraphicsView::paintEvent(event);
4401 QEXPECT_FAIL("", "QTBUG-24296", Continue);
4402 QCOMPARE(event->region(), updateRegion);
4407 SAGraphicsView view(&scene);
4409 QVERIFY(QTest::qWaitForWindowExposed(&view));
4411 int hsbValue = view.horizontalScrollBar()->value();
4412 view.horizontalScrollBar()->setValue(hsbValue / 2);
4414 view.horizontalScrollBar()->setValue(0);
4417 QRect itemDeviceBoundingRect = card.deviceTransform(view.viewportTransform()).mapRect(card.boundingRect()).toRect();
4418 itemDeviceBoundingRect.adjust(-2, -2, 2, 2);
4419 view.updateRegion = itemDeviceBoundingRect;
4420 view.updateRegion += itemDeviceBoundingRect.translated(-100, 0);
4421 view.itSTimeToTest = true;
4422 card.setPos(200, 300);
4426 void tst_QGraphicsView::QTBUG_4151_clipAndIgnore_data()
4428 QTest::addColumn<bool>("clip");
4429 QTest::addColumn<bool>("ignoreTransformations");
4430 QTest::addColumn<int>("numItems");
4432 QTest::newRow("none") << false << false << 3;
4433 QTest::newRow("clip") << true << false << 3;
4434 QTest::newRow("ignore") << false << true << 3;
4435 QTest::newRow("clip+ignore") << true << true << 3;
4438 void tst_QGraphicsView::QTBUG_4151_clipAndIgnore()
4441 QFETCH(bool, ignoreTransformations);
4442 QFETCH(int, numItems);
4444 QGraphicsScene scene;
4446 QGraphicsRectItem *parent = new QGraphicsRectItem(QRectF(0, 0, 50, 50), 0);
4447 QGraphicsRectItem *child = new QGraphicsRectItem(QRectF(-10, -10, 40, 40), parent);
4448 QGraphicsRectItem *ignore = new QGraphicsRectItem(QRectF(60, 60, 50, 50), 0);
4451 parent->setFlags(QGraphicsItem::ItemClipsChildrenToShape);
4452 if (ignoreTransformations)
4453 ignore->setFlag(QGraphicsItem::ItemIgnoresTransformations);
4455 parent->setBrush(Qt::red);
4456 child->setBrush(QColor(0, 0, 255, 128));
4457 ignore->setBrush(Qt::green);
4459 scene.addItem(parent);
4460 scene.addItem(ignore);
4462 QGraphicsView view(&scene);
4463 view.setFrameStyle(0);
4464 view.resize(75, 75);
4466 view.activateWindow();
4467 QVERIFY(QTest::qWaitForWindowActive(&view));
4468 QCOMPARE(QApplication::activeWindow(), (QWidget *)&view);
4470 QCOMPARE(view.items(view.rect()).size(), numItems);
4473 void tst_QGraphicsView::QTBUG_5859_exposedRect()
4475 class CustomScene : public QGraphicsScene
4478 CustomScene(const QRectF &rect) : QGraphicsScene(rect) { }
4479 void drawBackground(QPainter * /* painter */, const QRectF &rect)
4480 { lastBackgroundExposedRect = rect; }
4481 QRectF lastBackgroundExposedRect;
4484 class CustomRectItem : public QGraphicsRectItem
4487 CustomRectItem(const QRectF &rect) : QGraphicsRectItem(rect)
4488 { setFlag(QGraphicsItem::ItemUsesExtendedStyleOption); }
4489 void paint(QPainter * /* painter */, const QStyleOptionGraphicsItem *option, QWidget * /* widget */ = 0)
4490 { lastExposedRect = option->exposedRect; }
4491 QRectF lastExposedRect;
4494 CustomScene scene(QRectF(0,0,50,50));
4496 CustomRectItem item(scene.sceneRect());
4498 scene.addItem(&item);
4500 QGraphicsView view(&scene);
4501 view.scale(4.15, 4.15);
4503 qApp->setActiveWindow(&view);
4504 QVERIFY(QTest::qWaitForWindowActive(&view));
4506 view.viewport()->repaint(10,10,20,20);
4507 QApplication::processEvents();
4509 QCOMPARE(item.lastExposedRect, scene.lastBackgroundExposedRect);
4512 #ifndef QTEST_NO_CURSOR
4513 void tst_QGraphicsView::QTBUG_7438_cursor()
4515 QGraphicsScene scene;
4516 QGraphicsItem *item = scene.addRect(QRectF(-10, -10, 20, 20));
4517 item->setFlag(QGraphicsItem::ItemIsMovable);
4519 QGraphicsView view(&scene);
4520 view.setFixedSize(400, 400);
4522 QVERIFY(QTest::qWaitForWindowExposed(&view));
4524 QCOMPARE(view.viewport()->cursor().shape(), QCursor().shape());
4525 view.viewport()->setCursor(Qt::PointingHandCursor);
4526 QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
4527 sendMouseMove(view.viewport(), view.mapFromScene(0, 0));
4528 QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
4529 sendMousePress(view.viewport(), view.mapFromScene(0, 0));
4530 QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
4531 sendMouseRelease(view.viewport(), view.mapFromScene(0, 0));
4532 QCOMPARE(view.viewport()->cursor().shape(), Qt::PointingHandCursor);
4536 class GraphicsItemWithHover : public QGraphicsRectItem
4539 GraphicsItemWithHover()
4540 : receivedEnterEvent(false), receivedLeaveEvent(false),
4541 enterWidget(0), leaveWidget(0)
4543 setRect(0, 0, 100, 100);
4544 setAcceptHoverEvents(true);
4547 bool sceneEvent(QEvent *event)
4549 if (event->type() == QEvent::GraphicsSceneHoverEnter) {
4550 receivedEnterEvent = true;
4551 enterWidget = static_cast<QGraphicsSceneHoverEvent *>(event)->widget();
4552 } else if (event->type() == QEvent::GraphicsSceneHoverLeave) {
4553 receivedLeaveEvent = true;
4554 leaveWidget = static_cast<QGraphicsSceneHoverEvent *>(event)->widget();
4556 return QGraphicsRectItem::sceneEvent(event);
4559 bool receivedEnterEvent;
4560 bool receivedLeaveEvent;
4561 QWidget *enterWidget;
4562 QWidget *leaveWidget;
4565 void tst_QGraphicsView::hoverLeave()
4567 QGraphicsScene scene;
4568 QGraphicsView view(&scene);
4569 GraphicsItemWithHover *item = new GraphicsItemWithHover;
4570 scene.addItem(item);
4572 // move the cursor out of the way
4573 QCursor::setPos(1,1);
4576 qApp->setActiveWindow(&view);
4577 QVERIFY(QTest::qWaitForWindowActive(&view));
4579 QPoint pos = view.viewport()->mapToGlobal(view.mapFromScene(item->mapToScene(10, 10)));
4580 QCursor::setPos(pos);
4582 QVERIFY(item->receivedEnterEvent);
4583 QCOMPARE(item->enterWidget, view.viewport());
4585 QCursor::setPos(1,1);
4588 QEXPECT_FAIL("", "QTBUG-26274 - behaviour regression", Abort);
4590 QVERIFY(item->receivedLeaveEvent);
4591 QCOMPARE(item->leaveWidget, view.viewport());
4594 class IMItem : public QGraphicsRectItem
4597 IMItem(QGraphicsItem *parent = 0):
4598 QGraphicsRectItem(QRectF(0, 0, 20, 20), parent)
4600 setFlag(QGraphicsItem::ItemIsFocusable, true);
4601 setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
4604 QVariant inputMethodQuery(Qt::InputMethodQuery) const
4612 QRectF IMItem::mf(1.5, 1.6, 10, 10);
4614 void tst_QGraphicsView::QTBUG_16063_microFocusRect()
4616 QGraphicsScene scene;
4617 IMItem *item = new IMItem();
4618 scene.addItem(item);
4620 QGraphicsView view(&scene);
4622 view.setFixedSize(40, 40);
4624 QVERIFY(QTest::qWaitForWindowActive(&view));
4626 scene.setFocusItem(item);
4628 QRectF mfv = view.inputMethodQuery(Qt::ImMicroFocus).toRectF();
4629 QCOMPARE(mfv, IMItem::mf.translated(-view.mapToScene(view.sceneRect().toRect()).boundingRect().topLeft()));
4632 QTEST_MAIN(tst_QGraphicsView)
4633 #include "tst_qgraphicsview.moc"