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 <private/qgraphicsitem_p.h>
46 #include <private/qgraphicsview_p.h>
47 #include <private/qgraphicsscene_p.h>
48 #include <QStyleOptionGraphicsItem>
49 #include <QAbstractTextDocumentLayout>
54 #include <QGraphicsItem>
55 #include <QGraphicsScene>
56 #include <QGraphicsSceneEvent>
57 #include <QGraphicsView>
58 #include <QGraphicsWidget>
59 #include <QGraphicsProxyWidget>
62 #include <QVBoxLayout>
63 #include <QGraphicsEffect>
64 #include <QPushButton>
66 #include <QGraphicsLinearLayout>
68 #include <QStyleHints>
70 Q_DECLARE_METATYPE(QList<int>)
71 Q_DECLARE_METATYPE(QList<QRectF>)
72 Q_DECLARE_METATYPE(QPainterPath)
73 Q_DECLARE_METATYPE(QPointF)
74 Q_DECLARE_METATYPE(QRectF)
76 #include "../../../qtest-config.h"
78 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
80 #define Q_CHECK_PAINTEVENTS \
81 if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \
82 QSKIP("The Graphics View doesn't get the paint events");
84 #define Q_CHECK_PAINTEVENTS
88 // On mac (cocoa) we always get full update.
89 // So check that the expected region is contained inside the actual
90 #define COMPARE_REGIONS(ACTUAL, EXPECTED) QVERIFY((EXPECTED).subtracted(ACTUAL).isEmpty())
92 #define COMPARE_REGIONS QTRY_COMPARE
95 static QGraphicsRectItem staticItem; //QTBUG-7629, we should not crash at exit.
97 static void sendMousePress(QGraphicsScene *scene, const QPointF &point, Qt::MouseButton button = Qt::LeftButton)
99 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
100 event.setScenePos(point);
101 event.setButton(button);
102 event.setButtons(button);
103 QApplication::sendEvent(scene, &event);
106 static void sendMouseMove(QGraphicsScene *scene, const QPointF &point,
107 Qt::MouseButton button = Qt::NoButton, Qt::MouseButtons /* buttons */ = 0)
109 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
110 event.setScenePos(point);
111 event.setButton(button);
112 event.setButtons(button);
113 QApplication::sendEvent(scene, &event);
116 static void sendMouseRelease(QGraphicsScene *scene, const QPointF &point, Qt::MouseButton button = Qt::LeftButton)
118 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
119 event.setScenePos(point);
120 event.setButton(button);
121 QApplication::sendEvent(scene, &event);
124 static void sendMouseClick(QGraphicsScene *scene, const QPointF &point, Qt::MouseButton button = Qt::LeftButton)
126 sendMousePress(scene, point, button);
127 sendMouseRelease(scene, point, button);
130 static void sendKeyPress(QGraphicsScene *scene, Qt::Key key)
132 QKeyEvent keyEvent(QEvent::KeyPress, key, Qt::NoModifier);
133 QApplication::sendEvent(scene, &keyEvent);
136 static void sendKeyRelease(QGraphicsScene *scene, Qt::Key key)
138 QKeyEvent keyEvent(QEvent::KeyRelease, key, Qt::NoModifier);
139 QApplication::sendEvent(scene, &keyEvent);
142 static void sendKeyClick(QGraphicsScene *scene, Qt::Key key)
144 sendKeyPress(scene, key);
145 sendKeyRelease(scene, key);
148 class EventSpy : public QGraphicsWidget
152 EventSpy(QObject *watched, QEvent::Type type)
153 : _count(0), spied(type)
155 watched->installEventFilter(this);
158 EventSpy(QGraphicsScene *scene, QGraphicsItem *watched, QEvent::Type type)
159 : _count(0), spied(type)
161 scene->addItem(this);
162 watched->installSceneEventFilter(this);
165 int count() const { return _count; }
168 bool eventFilter(QObject *watched, QEvent *event)
171 if (event->type() == spied)
176 bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
179 if (event->type() == spied)
188 class EventSpy2 : public QGraphicsWidget
192 EventSpy2(QObject *watched)
194 watched->installEventFilter(this);
197 EventSpy2(QGraphicsScene *scene, QGraphicsItem *watched)
199 scene->addItem(this);
200 watched->installSceneEventFilter(this);
203 QMap<QEvent::Type, int> counts;
206 bool eventFilter(QObject *watched, QEvent *event)
209 ++counts[event->type()];
213 bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
216 ++counts[event->type()];
221 class EventTester : public QGraphicsItem
224 EventTester(QGraphicsItem *parent = 0) : QGraphicsItem(parent), repaints(0)
225 { br = QRectF(-10, -10, 20, 20); }
227 void setGeometry(const QRectF &rect)
229 prepareGeometryChange();
234 QRectF boundingRect() const
237 void paint(QPainter *painter, const QStyleOptionGraphicsItem *o, QWidget *)
239 hints = painter->renderHints();
240 painter->setBrush(brush);
241 painter->drawRect(boundingRect());
242 lastExposedRect = o->exposedRect;
246 bool sceneEvent(QEvent *event)
248 events << event->type();
249 return QGraphicsItem::sceneEvent(event);
255 hints = QPainter::RenderHints(0);
257 lastExposedRect = QRectF();
260 QList<QEvent::Type> events;
261 QPainter::RenderHints hints;
264 QRectF lastExposedRect;
268 class MyGraphicsView : public QGraphicsView
272 QRegion paintedRegion;
273 MyGraphicsView(QGraphicsScene *scene, QWidget *parent=0) : QGraphicsView(scene,parent), repaints(0) {}
274 void paintEvent(QPaintEvent *e)
276 paintedRegion += e->region();
278 QGraphicsView::paintEvent(e);
280 void reset() { repaints = 0; paintedRegion = QRegion(); }
283 class tst_QGraphicsItem : public QObject
292 void constructionWithParent();
294 void deleteChildItem();
297 void setParentItem();
300 void inputMethodHints();
304 void explicitlyVisible();
306 void explicitlyEnabled();
309 void selected_group();
310 void selected_textItem();
311 void selected_multi();
312 void acceptedMouseButtons();
313 void acceptsHoverEvents();
314 void childAcceptsHoverEvents();
324 void collidesWith_item();
325 void collidesWith_path_data();
326 void collidesWith_path();
327 void collidesWithItemWithClip();
330 void mapFromToParent();
331 void mapFromToScene();
332 void mapFromToItem();
333 void mapRectFromToParent_data();
334 void mapRectFromToParent();
336 void commonAncestorItem();
339 void graphicsitem_cast();
340 void hoverEventsGenerateRepaints();
341 void boundingRects_data();
342 void boundingRects();
343 void boundingRects2();
344 void sceneBoundingRect();
345 void childrenBoundingRect();
346 void childrenBoundingRectTransformed();
347 void childrenBoundingRect2();
348 void childrenBoundingRect3();
349 void childrenBoundingRect4();
350 void childrenBoundingRect5();
355 void warpChildrenIntoGroup();
356 void removeFromGroup();
357 void handlesChildEvents();
358 void handlesChildEvents2();
359 void handlesChildEvents3();
360 void filtersChildEvents();
361 void filtersChildEvents2();
362 void ensureVisible();
363 #ifndef QTEST_NO_CURSOR
366 //void textControlGetterSetter();
367 void defaultItemTest_QGraphicsLineItem();
368 void defaultItemTest_QGraphicsPixmapItem();
369 void defaultItemTest_QGraphicsTextItem();
370 void defaultItemTest_QGraphicsEllipseItem();
372 void sceneEventFilter();
373 void prepareGeometryChange();
375 void deleteItemInEventHandlers();
376 void itemClipsToShape();
377 void itemClipsChildrenToShape();
378 void itemClipsChildrenToShape2();
379 void itemClipsChildrenToShape3();
380 void itemClipsChildrenToShape4();
381 void itemClipsChildrenToShape5();
382 void itemClipsTextChildToShape();
383 void itemClippingDiscovery();
384 void ancestorFlags();
385 void untransformable();
386 void contextMenuEventPropagation();
387 void itemIsMovable();
388 void boundingRegion_data();
389 void boundingRegion();
390 void itemTransform_parentChild();
391 void itemTransform_siblings();
392 void itemTransform_unrelated();
396 void opacityZeroUpdates();
397 void itemStacksBehindParent();
398 void nestedClipping();
399 void nestedClippingTransforms();
400 void sceneTransformCache();
401 void tabChangesFocus();
402 void tabChangesFocus_data();
405 void updateCachedItemAfterMove();
406 void deviceTransform_data();
407 void deviceTransform();
409 void setTransformProperties_data();
410 void setTransformProperties();
411 void itemUsesExtendedStyleOption();
412 void itemSendsGeometryChanges();
417 void itemHasNoContents();
418 void hitTestUntransformableItem();
419 void hitTestGraphicsEffectItem();
422 void focusProxyDeletion();
423 void negativeZStacksBehindParent();
424 void setGraphicsEffect();
426 void addPanelToActiveScene();
427 void panelWithFocusItem();
429 void setActivePanelOnInactiveScene();
430 void activationOnShowHide();
431 void moveWhileDeleting();
432 void ensureDirtySceneTransform();
436 void sceneModality();
437 void panelModality();
438 void mixedModality();
439 void modality_hover();
440 void modality_mouseGrabber();
441 void modality_clickFocus();
442 void modality_keyEvents();
443 void itemIsInFront();
444 void scenePosChange();
445 void textItem_shortcuts();
447 void focusHandling_data();
448 void focusHandling();
449 void touchEventPropagation_data();
450 void touchEventPropagation();
451 void deviceCoordinateCache_simpleRotations();
453 // task specific tests below me
454 void task141694_textItemEnsureVisible();
455 void task128696_textItemEnsureMovable();
456 void ensureUpdateOnTextItem();
457 void task177918_lineItemUndetected();
458 void task240400_clickOnTextItem_data();
459 void task240400_clickOnTextItem();
460 void task243707_addChildBeforeParent();
461 void task197802_childrenVisibility();
462 void QTBUG_4233_updateCachedWithSceneRect();
463 void QTBUG_5418_textItemSetDefaultColor();
464 void QTBUG_6738_missingUpdateWithSetParent();
465 void QTBUG_7714_fullUpdateDiscardingOpacityUpdate2();
466 void QT_2653_fullUpdateDiscardingOpacityUpdate();
467 void QT_2649_focusScope();
468 void sortItemsWhileAdding();
469 void doNotMarkFullUpdateIfNotInScene();
470 void itemDiesDuringDraggingOperation();
471 void QTBUG_12112_focusItem();
472 void QTBUG_13473_sceneposchange();
473 void QTBUG_16374_crashInDestructor();
474 void QTBUG_20699_focusScopeCrash();
477 QList<QGraphicsItem *> paintedItems;
480 void tst_QGraphicsItem::init()
482 #ifdef Q_OS_WINCE //disable magic for WindowsCE
483 qApp->setAutoMaximizeThreshold(-1);
487 void tst_QGraphicsItem::construction()
489 for (int i = 0; i < 7; ++i) {
493 item = new QGraphicsEllipseItem;
494 ((QGraphicsEllipseItem *)item)->setPen(QPen(Qt::black, 0));
495 QCOMPARE(int(item->type()), int(QGraphicsEllipseItem::Type));
496 QCOMPARE(qgraphicsitem_cast<QGraphicsEllipseItem *>(item), (QGraphicsEllipseItem *)item);
497 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
498 QCOMPARE(item->flags(), 0);
501 item = new QGraphicsLineItem;
502 ((QGraphicsLineItem *)item)->setPen(QPen(Qt::black, 0));
503 QCOMPARE(int(item->type()), int(QGraphicsLineItem::Type));
504 QCOMPARE(qgraphicsitem_cast<QGraphicsLineItem *>(item), (QGraphicsLineItem *)item);
505 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
506 QCOMPARE(item->flags(), 0);
509 item = new QGraphicsPathItem;
510 ((QGraphicsPathItem *)item)->setPen(QPen(Qt::black, 0));
511 QCOMPARE(int(item->type()), int(QGraphicsPathItem::Type));
512 QCOMPARE(qgraphicsitem_cast<QGraphicsPathItem *>(item), (QGraphicsPathItem *)item);
513 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
514 QCOMPARE(item->flags(), 0);
517 item = new QGraphicsPixmapItem;
518 QCOMPARE(int(item->type()), int(QGraphicsPixmapItem::Type));
519 QCOMPARE(qgraphicsitem_cast<QGraphicsPixmapItem *>(item), (QGraphicsPixmapItem *)item);
520 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
521 QCOMPARE(item->flags(), 0);
524 item = new QGraphicsPolygonItem;
525 ((QGraphicsPolygonItem *)item)->setPen(QPen(Qt::black, 0));
526 QCOMPARE(int(item->type()), int(QGraphicsPolygonItem::Type));
527 QCOMPARE(qgraphicsitem_cast<QGraphicsPolygonItem *>(item), (QGraphicsPolygonItem *)item);
528 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
529 QCOMPARE(item->flags(), 0);
532 item = new QGraphicsRectItem;
533 ((QGraphicsRectItem *)item)->setPen(QPen(Qt::black, 0));
534 QCOMPARE(int(item->type()), int(QGraphicsRectItem::Type));
535 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)item);
536 QCOMPARE(qgraphicsitem_cast<QGraphicsLineItem *>(item), (QGraphicsLineItem *)0);
537 QCOMPARE(item->flags(), 0);
540 item = new QGraphicsTextItem;
541 QCOMPARE(int(item->type()), int(QGraphicsTextItem::Type));
542 QCOMPARE(qgraphicsitem_cast<QGraphicsTextItem *>(item), (QGraphicsTextItem *)item);
543 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
544 // This is the only item that uses an extended style option.
545 QCOMPARE(item->flags(), QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemUsesExtendedStyleOption));
548 qFatal("You broke the logic, please fix!");
552 QCOMPARE(item->scene(), (QGraphicsScene *)0);
553 QCOMPARE(item->parentItem(), (QGraphicsItem *)0);
554 QVERIFY(item->children().isEmpty());
555 QVERIFY(item->isVisible());
556 QVERIFY(item->isEnabled());
557 QVERIFY(!item->isSelected());
558 QCOMPARE(item->acceptedMouseButtons(), Qt::MouseButtons(0x1f));
559 if (item->type() == QGraphicsTextItem::Type)
560 QVERIFY(item->acceptsHoverEvents());
562 QVERIFY(!item->acceptsHoverEvents());
563 QVERIFY(!item->hasFocus());
564 QCOMPARE(item->pos(), QPointF());
565 QCOMPARE(item->matrix(), QMatrix());
566 QCOMPARE(item->sceneMatrix(), QMatrix());
567 QCOMPARE(item->zValue(), qreal(0));
568 QCOMPARE(item->sceneBoundingRect(), QRectF());
569 QCOMPARE(item->shape(), QPainterPath());
570 QVERIFY(!item->contains(QPointF(0, 0)));
571 QVERIFY(!item->collidesWithItem(0));
572 QVERIFY(item->collidesWithItem(item));
573 QVERIFY(!item->collidesWithPath(QPainterPath()));
574 QVERIFY(!item->isAncestorOf(0));
575 QVERIFY(!item->isAncestorOf(item));
576 QCOMPARE(item->data(0), QVariant());
581 class BoundingRectItem : public QGraphicsRectItem
584 BoundingRectItem(QGraphicsItem *parent = 0)
585 : QGraphicsRectItem(0, 0, parent ? 200 : 100, parent ? 200 : 100,
588 setPen(QPen(Qt::black, 0));
591 QRectF boundingRect() const
593 QRectF tmp = QGraphicsRectItem::boundingRect();
594 foreach (QGraphicsItem *child, children())
595 tmp |= child->boundingRect(); // <- might be pure virtual
600 void tst_QGraphicsItem::constructionWithParent()
602 // This test causes a crash if item1 calls item2's pure virtuals before the
603 // object has been constructed.
604 QGraphicsItem *item0 = new BoundingRectItem;
605 QGraphicsItem *item1 = new BoundingRectItem;
606 QGraphicsScene scene;
607 scene.addItem(item0);
608 scene.addItem(item1);
609 QGraphicsItem *item2 = new BoundingRectItem(item1);
610 QCOMPARE(item1->children(), QList<QGraphicsItem *>() << item2);
611 QCOMPARE(item1->boundingRect(), QRectF(0, 0, 200, 200));
613 item2->setParentItem(item0);
614 QCOMPARE(item0->children(), QList<QGraphicsItem *>() << item2);
615 QCOMPARE(item0->boundingRect(), QRectF(0, 0, 200, 200));
618 static int itemDeleted = 0;
619 class Item : public QGraphicsRectItem
626 void tst_QGraphicsItem::destruction()
628 QCOMPARE(itemDeleted, 0);
630 QGraphicsItem *parent = new QGraphicsRectItem;
631 Item *child = new Item;
632 child->setParentItem(parent);
633 QCOMPARE(child->parentItem(), parent);
635 QCOMPARE(itemDeleted, 1);
638 QGraphicsItem *parent = new QGraphicsRectItem;
639 Item *child = new Item;
640 child->setParentItem(parent);
641 QCOMPARE(parent->children().size(), 1);
643 QCOMPARE(parent->children().size(), 0);
645 QCOMPARE(itemDeleted, 2);
648 QGraphicsScene scene;
649 QGraphicsItem *parent = new QGraphicsRectItem;
650 Item *child = new Item;
651 QCOMPARE(child->parentItem(), (QGraphicsItem *)0);
652 child->setParentItem(parent);
653 QCOMPARE(child->parentItem(), parent);
654 scene.addItem(parent);
655 QCOMPARE(child->parentItem(), parent);
657 QCOMPARE(itemDeleted, 3);
660 QGraphicsScene scene;
661 QGraphicsItem *parent = new QGraphicsRectItem;
662 Item *child = new Item;
663 child->setParentItem(parent);
664 scene.addItem(parent);
665 QCOMPARE(child->scene(), &scene);
666 QCOMPARE(parent->children().size(), 1);
668 QCOMPARE(parent->children().size(), 0);
670 QCOMPARE(itemDeleted, 4);
673 QGraphicsScene scene;
674 QGraphicsItem *parent = new QGraphicsRectItem;
675 Item *child = new Item;
676 child->setParentItem(parent);
677 scene.addItem(parent);
678 QCOMPARE(child->scene(), &scene);
679 scene.removeItem(parent);
680 QCOMPARE(child->scene(), (QGraphicsScene *)0);
682 QCOMPARE(itemDeleted, 5);
685 QGraphicsScene scene;
686 QGraphicsItem *parent = new QGraphicsRectItem;
687 Item *child = new Item;
688 child->setParentItem(parent);
689 QCOMPARE(child->scene(), (QGraphicsScene *)0);
690 QCOMPARE(parent->scene(), (QGraphicsScene *)0);
691 scene.addItem(parent);
692 QCOMPARE(child->scene(), &scene);
693 scene.removeItem(child);
694 QCOMPARE(child->scene(), (QGraphicsScene *)0);
695 QCOMPARE(parent->scene(), &scene);
696 QCOMPARE(child->parentItem(), (QGraphicsItem *)0);
697 QVERIFY(parent->children().isEmpty());
699 QCOMPARE(itemDeleted, 5);
701 QCOMPARE(itemDeleted, 6);
704 QGraphicsScene scene;
705 QGraphicsItem *parent = new QGraphicsRectItem;
706 Item *child = new Item;
707 child->setParentItem(parent);
708 scene.addItem(parent);
709 scene.removeItem(child);
710 scene.removeItem(parent);
713 QCOMPARE(itemDeleted, 7);
716 QGraphicsScene scene;
717 QGraphicsItem *parent = new QGraphicsRectItem;
718 Item *child = new Item;
719 child->setParentItem(parent);
720 scene.addItem(parent);
721 QGraphicsScene scene2;
722 scene2.addItem(parent);
724 QCOMPARE(itemDeleted, 8);
727 QGraphicsScene scene;
728 QGraphicsItem *parent = new QGraphicsRectItem;
729 Item *child = new Item;
730 child->setParentItem(parent);
731 scene.addItem(parent);
732 QCOMPARE(child->scene(), &scene);
733 QGraphicsScene scene2;
734 scene2.addItem(parent);
735 QCOMPARE(child->scene(), &scene2);
736 scene.addItem(parent);
737 QCOMPARE(child->scene(), &scene);
738 scene2.addItem(parent);
739 QCOMPARE(child->scene(), &scene2);
741 QCOMPARE(itemDeleted, 9);
744 QGraphicsScene scene;
745 QGraphicsItem *parent = new QGraphicsRectItem;
746 Item *child = new Item;
747 child->setParentItem(parent);
748 scene.addItem(parent);
749 QCOMPARE(child->scene(), &scene);
750 QGraphicsScene scene2;
751 scene2.addItem(child);
752 QCOMPARE(child->scene(), &scene2);
754 QCOMPARE(itemDeleted, 9);
756 QCOMPARE(itemDeleted, 10);
759 QGraphicsScene scene;
760 QGraphicsItem *root = new QGraphicsRectItem;
761 QGraphicsItem *parent = root;
762 QGraphicsItem *middleItem = 0;
763 for (int i = 0; i < 99; ++i) {
764 Item *child = new Item;
765 child->setParentItem(parent);
772 QCOMPARE(scene.items().size(), 100);
774 QGraphicsScene scene2;
775 scene2.addItem(middleItem);
778 QCOMPARE(itemDeleted, 59);
780 QCOMPARE(itemDeleted, 109);
782 QGraphicsScene *scene = new QGraphicsScene;
783 QGraphicsRectItem *parent = new QGraphicsRectItem;
784 Item *child = new Item;
785 child->setParentItem(parent);
786 parent->setVisible(false);
787 scene->addItem(parent);
788 QCOMPARE(child->parentItem(), static_cast<QGraphicsItem*>(parent));
790 QCOMPARE(itemDeleted, 110);
794 void tst_QGraphicsItem::deleteChildItem()
796 QGraphicsScene scene;
797 QGraphicsItem *rect = scene.addRect(QRectF());
798 QGraphicsItem *child1 = new QGraphicsRectItem(rect);
799 QGraphicsItem *child2 = new QGraphicsRectItem(rect);
800 QGraphicsItem *child3 = new QGraphicsRectItem(rect);
803 child2->setParentItem(0);
807 void tst_QGraphicsItem::scene()
809 QGraphicsRectItem *item = new QGraphicsRectItem;
810 QCOMPARE(item->scene(), (QGraphicsScene *)0);
812 QGraphicsScene scene;
814 QCOMPARE(item->scene(), (QGraphicsScene *)&scene);
816 QGraphicsScene scene2;
817 scene2.addItem(item);
818 QCOMPARE(item->scene(), (QGraphicsScene *)&scene2);
820 scene2.removeItem(item);
821 QCOMPARE(item->scene(), (QGraphicsScene *)0);
826 void tst_QGraphicsItem::parentItem()
828 QGraphicsRectItem item;
829 QCOMPARE(item.parentItem(), (QGraphicsItem *)0);
831 QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(), &item);
832 QCOMPARE(item2->parentItem(), (QGraphicsItem *)&item);
833 item2->setParentItem(&item);
834 QCOMPARE(item2->parentItem(), (QGraphicsItem *)&item);
835 item2->setParentItem(0);
836 QCOMPARE(item2->parentItem(), (QGraphicsItem *)0);
841 void tst_QGraphicsItem::setParentItem()
843 QGraphicsScene scene;
844 QGraphicsItem *item = scene.addRect(QRectF(0, 0, 10, 10));
845 QCOMPARE(item->scene(), &scene);
847 QGraphicsRectItem *child = new QGraphicsRectItem;
848 QCOMPARE(child->scene(), (QGraphicsScene *)0);
850 // This implicitly adds the item to the parent's scene
851 child->setParentItem(item);
852 QCOMPARE(child->scene(), &scene);
854 // This just makes it a toplevel
855 child->setParentItem(0);
856 QCOMPARE(child->scene(), &scene);
858 // Add the child back to the parent, then remove the parent from the scene
859 child->setParentItem(item);
860 scene.removeItem(item);
861 QCOMPARE(child->scene(), (QGraphicsScene *)0);
864 void tst_QGraphicsItem::children()
866 QGraphicsRectItem item;
867 QVERIFY(item.children().isEmpty());
869 QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(), &item);
870 QCOMPARE(item.children().size(), 1);
871 QCOMPARE(item.children().first(), (QGraphicsItem *)item2);
872 QVERIFY(item2->children().isEmpty());
875 QVERIFY(item.children().isEmpty());
878 void tst_QGraphicsItem::flags()
880 QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(-10, -10, 20, 20));
881 QCOMPARE(item->flags(), 0);
883 QGraphicsScene scene;
884 QEvent activate(QEvent::WindowActivate);
885 QApplication::sendEvent(&scene, &activate);
891 item->setFlag(QGraphicsItem::ItemIsFocusable, false);
892 QVERIFY(!item->hasFocus());
894 QVERIFY(!item->hasFocus());
896 item->setFlag(QGraphicsItem::ItemIsFocusable, true);
897 QVERIFY(!item->hasFocus());
899 QVERIFY(item->hasFocus());
900 QVERIFY(scene.hasFocus());
902 item->setFlag(QGraphicsItem::ItemIsFocusable, false);
903 QVERIFY(!item->hasFocus());
904 QVERIFY(scene.hasFocus());
908 item->setFlag(QGraphicsItem::ItemIsSelectable, false);
909 QVERIFY(!item->isSelected());
910 item->setSelected(true);
911 QVERIFY(!item->isSelected());
913 item->setFlag(QGraphicsItem::ItemIsSelectable, true);
914 QVERIFY(!item->isSelected());
915 item->setSelected(true);
916 QVERIFY(item->isSelected());
917 item->setFlag(QGraphicsItem::ItemIsSelectable, false);
918 QVERIFY(!item->isSelected());
922 item->setFlag(QGraphicsItem::ItemIsMovable, false);
923 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
924 event.setScenePos(QPointF(0, 0));
925 event.setButton(Qt::LeftButton);
926 event.setButtons(Qt::LeftButton);
927 QApplication::sendEvent(&scene, &event);
928 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0); // mouse grabber is reset
930 QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove);
931 event2.setScenePos(QPointF(10, 10));
932 event2.setButton(Qt::LeftButton);
933 event2.setButtons(Qt::LeftButton);
934 QApplication::sendEvent(&scene, &event2);
935 QCOMPARE(item->pos(), QPointF());
937 QGraphicsSceneMouseEvent event3(QEvent::GraphicsSceneMouseRelease);
938 event3.setScenePos(QPointF(10, 10));
939 event3.setButtons(0);
940 QApplication::sendEvent(&scene, &event3);
941 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
943 item->setFlag(QGraphicsItem::ItemIsMovable, true);
944 QGraphicsSceneMouseEvent event4(QEvent::GraphicsSceneMousePress);
945 event4.setScenePos(QPointF(0, 0));
946 event4.setButton(Qt::LeftButton);
947 event4.setButtons(Qt::LeftButton);
948 QApplication::sendEvent(&scene, &event4);
949 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
950 QGraphicsSceneMouseEvent event5(QEvent::GraphicsSceneMouseMove);
951 event5.setScenePos(QPointF(10, 10));
952 event5.setButton(Qt::LeftButton);
953 event5.setButtons(Qt::LeftButton);
954 QApplication::sendEvent(&scene, &event5);
955 QCOMPARE(item->pos(), QPointF(10, 10));
958 QGraphicsItem* clippingParent = new QGraphicsRectItem;
959 clippingParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
961 QGraphicsItem* nonClippingParent = new QGraphicsRectItem;
962 nonClippingParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
964 QGraphicsItem* child = new QGraphicsRectItem(nonClippingParent);
965 QVERIFY(!child->isClipped());
967 child->setParentItem(clippingParent);
968 QVERIFY(child->isClipped());
970 child->setParentItem(nonClippingParent);
971 QVERIFY(!child->isClipped());
975 class ImhTester : public QGraphicsItem
977 QRectF boundingRect() const { return QRectF(); }
978 void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) {}
981 void tst_QGraphicsItem::inputMethodHints()
983 ImhTester *item = new ImhTester;
984 item->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
985 item->setFlag(QGraphicsItem::ItemIsFocusable, true);
986 QCOMPARE(item->inputMethodHints(), Qt::ImhNone);
987 ImhTester *item2 = new ImhTester;
988 item2->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
989 item2->setFlag(QGraphicsItem::ItemIsFocusable, true);
990 Qt::InputMethodHints imHints = item2->inputMethodHints();
991 imHints |= Qt::ImhHiddenText;
992 item2->setInputMethodHints(imHints);
993 QGraphicsScene scene;
995 scene.addItem(item2);
996 QGraphicsView view(&scene);
997 QApplication::setActiveWindow(&view);
999 QVERIFY(QTest::qWaitForWindowActive(&view));
1001 QTRY_VERIFY(item->hasFocus());
1002 QCOMPARE(view.inputMethodHints(), item->inputMethodHints());
1004 QTRY_VERIFY(item2->hasFocus());
1005 QCOMPARE(view.inputMethodHints(), item2->inputMethodHints());
1006 item->setFlag(QGraphicsItem::ItemAcceptsInputMethod, false);
1008 QTRY_VERIFY(item->hasFocus());
1009 //Focus has changed but the new item doesn't accept input method, no hints.
1010 QCOMPARE(view.inputMethodHints(), 0);
1012 QTRY_VERIFY(item2->hasFocus());
1013 QCOMPARE(view.inputMethodHints(), item2->inputMethodHints());
1014 imHints = item2->inputMethodHints();
1015 imHints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
1016 item2->setInputMethodHints(imHints);
1017 QCOMPARE(view.inputMethodHints(), item2->inputMethodHints());
1018 QGraphicsProxyWidget *widget = new QGraphicsProxyWidget;
1019 QLineEdit *edit = new QLineEdit;
1020 edit->setEchoMode(QLineEdit::Password);
1021 scene.addItem(widget);
1023 QTRY_VERIFY(widget->hasFocus());
1024 //No widget on the proxy, so no hints
1025 QCOMPARE(view.inputMethodHints(), 0);
1026 widget->setWidget(edit);
1027 //View should match with the line edit
1028 QCOMPARE(view.inputMethodHints(), edit->inputMethodHints());
1031 void tst_QGraphicsItem::toolTip()
1033 QString toolTip = "Qt rocks!";
1035 QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
1036 item->setPen(QPen(Qt::red, 1));
1037 item->setBrush(QBrush(Qt::blue));
1038 QVERIFY(item->toolTip().isEmpty());
1039 item->setToolTip(toolTip);
1040 QCOMPARE(item->toolTip(), toolTip);
1042 QGraphicsScene scene;
1043 scene.addItem(item);
1045 QGraphicsView view(&scene);
1046 view.setFixedSize(200, 200);
1048 QApplication::setActiveWindow(&view);
1049 QVERIFY(QTest::qWaitForWindowActive(&view));
1051 QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().topLeft(),
1052 view.viewport()->mapToGlobal(view.viewport()->rect().topLeft()));
1053 QApplication::sendEvent(view.viewport(), &helpEvent);
1056 bool foundView = false;
1057 bool foundTipLabel = false;
1058 foreach (QWidget *widget, QApplication::topLevelWidgets()) {
1059 if (widget == &view)
1061 if (widget->inherits("QTipLabel"))
1062 foundTipLabel = true;
1065 QVERIFY(!foundTipLabel);
1069 QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().center(),
1070 view.viewport()->mapToGlobal(view.viewport()->rect().center()));
1071 QApplication::sendEvent(view.viewport(), &helpEvent);
1074 bool foundView = false;
1075 bool foundTipLabel = false;
1076 foreach (QWidget *widget, QApplication::topLevelWidgets()) {
1077 if (widget == &view)
1079 if (widget->inherits("QTipLabel"))
1080 foundTipLabel = true;
1083 QVERIFY(foundTipLabel);
1087 QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().topLeft(),
1088 view.viewport()->mapToGlobal(view.viewport()->rect().topLeft()));
1089 QApplication::sendEvent(view.viewport(), &helpEvent);
1092 bool foundView = false;
1093 bool foundTipLabel = false;
1094 foreach (QWidget *widget, QApplication::topLevelWidgets()) {
1095 if (widget == &view)
1097 if (widget->inherits("QTipLabel") && widget->isVisible())
1098 foundTipLabel = true;
1101 QVERIFY(!foundTipLabel);
1105 void tst_QGraphicsItem::visible()
1107 QGraphicsItem *item = new QGraphicsRectItem(QRectF(-10, -10, 20, 20));
1108 item->setFlag(QGraphicsItem::ItemIsMovable);
1109 QVERIFY(item->isVisible());
1110 item->setVisible(false);
1111 QVERIFY(!item->isVisible());
1112 item->setVisible(true);
1113 QVERIFY(item->isVisible());
1115 QGraphicsScene scene;
1116 QEvent activate(QEvent::WindowActivate);
1117 QApplication::sendEvent(&scene, &activate);
1119 scene.addItem(item);
1120 QVERIFY(item->isVisible());
1121 QCOMPARE(scene.itemAt(0, 0), item);
1122 item->setVisible(false);
1123 QCOMPARE(scene.itemAt(0, 0), (QGraphicsItem *)0);
1124 item->setVisible(true);
1125 QCOMPARE(scene.itemAt(0, 0), item);
1127 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
1128 event.setButton(Qt::LeftButton);
1129 event.setScenePos(QPointF(0, 0));
1130 QApplication::sendEvent(&scene, &event);
1131 QCOMPARE(scene.mouseGrabberItem(), item);
1132 item->setVisible(false);
1133 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1134 item->setVisible(true);
1135 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1137 item->setFlag(QGraphicsItem::ItemIsFocusable);
1139 QVERIFY(item->hasFocus());
1140 item->setVisible(false);
1141 QVERIFY(!item->hasFocus());
1142 item->setVisible(true);
1143 QVERIFY(!item->hasFocus());
1146 void tst_QGraphicsItem::isVisibleTo()
1148 QGraphicsScene scene;
1149 QGraphicsItem *parent = scene.addRect(QRectF(0, 0, 100, 100));
1150 QGraphicsItem *child = scene.addRect(QRectF(25, 25, 50, 50));
1151 QGraphicsItem *grandChild = scene.addRect(QRectF(50, 50, 50, 50));
1152 QGraphicsItem *stranger = scene.addRect(100, 100, 100, 100);
1154 child->setParentItem(parent);
1155 grandChild->setParentItem(child);
1157 QVERIFY(grandChild->isVisible());
1158 QVERIFY(grandChild->isVisibleTo(grandChild));
1159 QVERIFY(grandChild->isVisibleTo(child));
1160 QVERIFY(grandChild->isVisibleTo(parent));
1161 QVERIFY(grandChild->isVisibleTo(0));
1162 QVERIFY(child->isVisible());
1163 QVERIFY(child->isVisibleTo(child));
1164 QVERIFY(child->isVisibleTo(parent));
1165 QVERIFY(child->isVisibleTo(0));
1166 QVERIFY(parent->isVisible());
1167 QVERIFY(parent->isVisibleTo(parent));
1168 QVERIFY(parent->isVisibleTo(0));
1169 QVERIFY(!parent->isVisibleTo(child));
1170 QVERIFY(!child->isVisibleTo(grandChild));
1171 QVERIFY(!grandChild->isVisibleTo(stranger));
1172 QVERIFY(!child->isVisibleTo(stranger));
1173 QVERIFY(!parent->isVisibleTo(stranger));
1174 QVERIFY(!stranger->isVisibleTo(grandChild));
1175 QVERIFY(!stranger->isVisibleTo(child));
1176 QVERIFY(!stranger->isVisibleTo(parent));
1178 // Case 1: only parent is explicitly hidden
1181 QVERIFY(!grandChild->isVisible());
1182 QVERIFY(grandChild->isVisibleTo(grandChild));
1183 QVERIFY(grandChild->isVisibleTo(child));
1184 QVERIFY(grandChild->isVisibleTo(parent));
1185 QVERIFY(!grandChild->isVisibleTo(0));
1186 QVERIFY(!child->isVisible());
1187 QVERIFY(child->isVisibleTo(child));
1188 QVERIFY(child->isVisibleTo(parent));
1189 QVERIFY(!child->isVisibleTo(0));
1190 QVERIFY(!parent->isVisible());
1191 QVERIFY(!parent->isVisibleTo(parent));
1192 QVERIFY(!parent->isVisibleTo(0));
1193 QVERIFY(!parent->isVisibleTo(child));
1194 QVERIFY(!child->isVisibleTo(grandChild));
1195 QVERIFY(!grandChild->isVisibleTo(stranger));
1196 QVERIFY(!child->isVisibleTo(stranger));
1197 QVERIFY(!parent->isVisibleTo(stranger));
1198 QVERIFY(!stranger->isVisibleTo(grandChild));
1199 QVERIFY(!stranger->isVisibleTo(child));
1200 QVERIFY(!stranger->isVisibleTo(parent));
1202 // Case 2: only child is hidden
1206 QVERIFY(!grandChild->isVisible());
1207 QVERIFY(grandChild->isVisibleTo(grandChild));
1208 QVERIFY(grandChild->isVisibleTo(child));
1209 QVERIFY(!grandChild->isVisibleTo(parent));
1210 QVERIFY(!grandChild->isVisibleTo(0));
1211 QVERIFY(!child->isVisible());
1212 QVERIFY(!child->isVisibleTo(child));
1213 QVERIFY(!child->isVisibleTo(parent));
1214 QVERIFY(!child->isVisibleTo(0));
1215 QVERIFY(parent->isVisible());
1216 QVERIFY(parent->isVisibleTo(parent));
1217 QVERIFY(parent->isVisibleTo(0));
1218 QVERIFY(!parent->isVisibleTo(child));
1219 QVERIFY(!child->isVisibleTo(grandChild));
1220 QVERIFY(!grandChild->isVisibleTo(stranger));
1221 QVERIFY(!child->isVisibleTo(stranger));
1222 QVERIFY(!parent->isVisibleTo(stranger));
1223 QVERIFY(!stranger->isVisibleTo(grandChild));
1224 QVERIFY(!stranger->isVisibleTo(child));
1225 QVERIFY(!stranger->isVisibleTo(parent));
1227 // Case 3: only grand child is hidden
1231 QVERIFY(!grandChild->isVisible());
1232 QVERIFY(!grandChild->isVisibleTo(grandChild));
1233 QVERIFY(!grandChild->isVisibleTo(child));
1234 QVERIFY(!grandChild->isVisibleTo(parent));
1235 QVERIFY(!grandChild->isVisibleTo(0));
1236 QVERIFY(child->isVisible());
1237 QVERIFY(child->isVisibleTo(child));
1238 QVERIFY(child->isVisibleTo(parent));
1239 QVERIFY(child->isVisibleTo(0));
1240 QVERIFY(parent->isVisible());
1241 QVERIFY(parent->isVisibleTo(parent));
1242 QVERIFY(parent->isVisibleTo(0));
1243 QVERIFY(!parent->isVisibleTo(child));
1244 QVERIFY(!child->isVisibleTo(grandChild));
1245 QVERIFY(!grandChild->isVisibleTo(stranger));
1246 QVERIFY(!child->isVisibleTo(stranger));
1247 QVERIFY(!parent->isVisibleTo(stranger));
1248 QVERIFY(!stranger->isVisibleTo(grandChild));
1249 QVERIFY(!stranger->isVisibleTo(child));
1250 QVERIFY(!stranger->isVisibleTo(parent));
1253 void tst_QGraphicsItem::explicitlyVisible()
1255 QGraphicsScene scene;
1256 QGraphicsItem *parent = scene.addRect(QRectF(0, 0, 100, 100));
1257 QGraphicsItem *child = scene.addRect(QRectF(25, 25, 50, 50));
1258 child->setParentItem(parent);
1260 QVERIFY(parent->isVisible());
1261 QVERIFY(child->isVisible());
1265 QVERIFY(!parent->isVisible());
1266 QVERIFY(!child->isVisible());
1271 QVERIFY(parent->isVisible());
1272 QVERIFY(!child->isVisible());
1276 QVERIFY(!parent->isVisible());
1277 QVERIFY(!child->isVisible());
1281 QVERIFY(parent->isVisible());
1282 QVERIFY(!child->isVisible()); // <- explicitly hidden
1286 QVERIFY(child->isVisible());
1290 QVERIFY(!parent->isVisible());
1291 QVERIFY(!child->isVisible()); // <- explicit show doesn't work
1295 QVERIFY(parent->isVisible());
1296 QVERIFY(child->isVisible()); // <- no longer explicitly hidden
1298 // ------------------- Reparenting ------------------------------
1300 QGraphicsItem *parent2 = scene.addRect(-50, -50, 200, 200);
1301 QVERIFY(parent2->isVisible());
1303 // Reparent implicitly hidden item to a visible parent.
1305 QVERIFY(!parent->isVisible());
1306 QVERIFY(!child->isVisible());
1307 child->setParentItem(parent2);
1308 QVERIFY(parent2->isVisible());
1309 QVERIFY(child->isVisible());
1311 // Reparent implicitly hidden item to a hidden parent.
1312 child->setParentItem(parent);
1314 child->setParentItem(parent2);
1315 QVERIFY(!parent2->isVisible());
1316 QVERIFY(!child->isVisible());
1318 // Reparent explicitly hidden item to a visible parent.
1321 child->setParentItem(parent);
1322 QVERIFY(parent->isVisible());
1323 QVERIFY(!child->isVisible());
1325 // Reparent explicitly hidden item to a hidden parent.
1326 child->setParentItem(parent2);
1327 QVERIFY(!parent2->isVisible());
1328 QVERIFY(!child->isVisible());
1330 // Reparent explicitly hidden item to a visible parent.
1332 child->setParentItem(parent);
1333 QVERIFY(parent->isVisible());
1334 QVERIFY(!child->isVisible());
1336 // Reparent visible item to a hidden parent.
1339 child->setParentItem(parent2);
1340 QVERIFY(!parent2->isVisible());
1341 QVERIFY(!child->isVisible());
1343 QVERIFY(parent2->isVisible());
1344 QVERIFY(child->isVisible());
1346 // Reparent implicitly hidden child to root.
1348 QVERIFY(!child->isVisible());
1349 child->setParentItem(0);
1350 QVERIFY(child->isVisible());
1352 // Reparent an explicitly hidden child to root.
1354 child->setParentItem(parent2);
1356 QVERIFY(!child->isVisible());
1357 child->setParentItem(0);
1358 QVERIFY(!child->isVisible());
1361 void tst_QGraphicsItem::enabled()
1363 QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(-10, -10, 20, 20));
1364 item->setFlag(QGraphicsItem::ItemIsMovable);
1365 QVERIFY(item->isEnabled());
1366 item->setEnabled(false);
1367 QVERIFY(!item->isEnabled());
1368 item->setEnabled(true);
1369 QVERIFY(item->isEnabled());
1370 item->setEnabled(false);
1371 item->setFlag(QGraphicsItem::ItemIsFocusable);
1372 QGraphicsScene scene;
1373 QEvent activate(QEvent::WindowActivate);
1374 QApplication::sendEvent(&scene, &activate);
1376 scene.addItem(item);
1378 QVERIFY(!item->hasFocus());
1379 item->setEnabled(true);
1381 QVERIFY(item->hasFocus());
1382 item->setEnabled(false);
1383 QVERIFY(!item->hasFocus());
1385 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
1386 event.setButton(Qt::LeftButton);
1387 event.setScenePos(QPointF(0, 0));
1388 QApplication::sendEvent(&scene, &event);
1389 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1390 item->setEnabled(true);
1391 QApplication::sendEvent(&scene, &event);
1392 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
1393 item->setEnabled(false);
1394 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1397 void tst_QGraphicsItem::explicitlyEnabled()
1399 QGraphicsScene scene;
1400 QGraphicsItem *parent = scene.addRect(QRectF(0, 0, 100, 100));
1401 QGraphicsItem *child = scene.addRect(QRectF(25, 25, 50, 50));
1402 child->setParentItem(parent);
1404 QVERIFY(parent->isEnabled());
1405 QVERIFY(child->isEnabled());
1407 parent->setEnabled(false);
1409 QVERIFY(!parent->isEnabled());
1410 QVERIFY(!child->isEnabled());
1412 parent->setEnabled(true);
1413 child->setEnabled(false);
1415 QVERIFY(parent->isEnabled());
1416 QVERIFY(!child->isEnabled());
1418 parent->setEnabled(false);
1420 QVERIFY(!parent->isEnabled());
1421 QVERIFY(!child->isEnabled());
1423 parent->setEnabled(true);
1425 QVERIFY(parent->isEnabled());
1426 QVERIFY(!child->isEnabled()); // <- explicitly disabled
1428 child->setEnabled(true);
1430 QVERIFY(child->isEnabled());
1432 parent->setEnabled(false);
1434 QVERIFY(!parent->isEnabled());
1435 QVERIFY(!child->isEnabled()); // <- explicit enabled doesn't work
1437 parent->setEnabled(true);
1439 QVERIFY(parent->isEnabled());
1440 QVERIFY(child->isEnabled()); // <- no longer explicitly disabled
1442 // ------------------- Reparenting ------------------------------
1444 QGraphicsItem *parent2 = scene.addRect(-50, -50, 200, 200);
1445 QVERIFY(parent2->isEnabled());
1447 // Reparent implicitly hidden item to a enabled parent.
1448 parent->setEnabled(false);
1449 QVERIFY(!parent->isEnabled());
1450 QVERIFY(!child->isEnabled());
1451 child->setParentItem(parent2);
1452 QVERIFY(parent2->isEnabled());
1453 QVERIFY(child->isEnabled());
1455 // Reparent implicitly hidden item to a hidden parent.
1456 child->setParentItem(parent);
1457 parent2->setEnabled(false);
1458 child->setParentItem(parent2);
1459 QVERIFY(!parent2->isEnabled());
1460 QVERIFY(!child->isEnabled());
1462 // Reparent explicitly hidden item to a enabled parent.
1463 child->setEnabled(false);
1464 parent->setEnabled(true);
1465 child->setParentItem(parent);
1466 QVERIFY(parent->isEnabled());
1467 QVERIFY(!child->isEnabled());
1469 // Reparent explicitly hidden item to a hidden parent.
1470 child->setParentItem(parent2);
1471 QVERIFY(!parent2->isEnabled());
1472 QVERIFY(!child->isEnabled());
1474 // Reparent explicitly hidden item to a enabled parent.
1475 parent->setEnabled(true);
1476 child->setParentItem(parent);
1477 QVERIFY(parent->isEnabled());
1478 QVERIFY(!child->isEnabled());
1480 // Reparent enabled item to a hidden parent.
1481 child->setEnabled(true);
1482 parent2->setEnabled(false);
1483 child->setParentItem(parent2);
1484 QVERIFY(!parent2->isEnabled());
1485 QVERIFY(!child->isEnabled());
1486 parent2->setEnabled(true);
1487 QVERIFY(parent2->isEnabled());
1488 QVERIFY(child->isEnabled());
1490 // Reparent implicitly hidden child to root.
1491 parent2->setEnabled(false);
1492 QVERIFY(!child->isEnabled());
1493 child->setParentItem(0);
1494 QVERIFY(child->isEnabled());
1496 // Reparent an explicitly hidden child to root.
1497 child->setEnabled(false);
1498 child->setParentItem(parent2);
1499 parent2->setEnabled(true);
1500 QVERIFY(!child->isEnabled());
1501 child->setParentItem(0);
1502 QVERIFY(!child->isEnabled());
1505 class SelectChangeItem : public QGraphicsRectItem
1508 SelectChangeItem() : QGraphicsRectItem(-50, -50, 100, 100) { setBrush(Qt::blue); }
1512 QVariant itemChange(GraphicsItemChange change, const QVariant &value)
1514 if (change == ItemSelectedChange)
1515 values << value.toBool();
1516 return QGraphicsRectItem::itemChange(change, value);
1520 void tst_QGraphicsItem::selected()
1522 SelectChangeItem *item = new SelectChangeItem;
1523 item->setFlag(QGraphicsItem::ItemIsSelectable);
1524 QVERIFY(!item->isSelected());
1525 QVERIFY(item->values.isEmpty());
1526 item->setSelected(true);
1527 QCOMPARE(item->values.size(), 1);
1528 QCOMPARE(item->values.last(), true);
1529 QVERIFY(item->isSelected());
1530 item->setSelected(false);
1531 QCOMPARE(item->values.size(), 2);
1532 QCOMPARE(item->values.last(), false);
1533 QVERIFY(!item->isSelected());
1534 item->setSelected(true);
1535 QCOMPARE(item->values.size(), 3);
1536 item->setEnabled(false);
1537 QCOMPARE(item->values.size(), 4);
1538 QCOMPARE(item->values.last(), false);
1539 QVERIFY(!item->isSelected());
1540 item->setEnabled(true);
1541 QCOMPARE(item->values.size(), 4);
1542 item->setSelected(true);
1543 QCOMPARE(item->values.size(), 5);
1544 QCOMPARE(item->values.last(), true);
1545 QVERIFY(item->isSelected());
1546 item->setVisible(false);
1547 QCOMPARE(item->values.size(), 6);
1548 QCOMPARE(item->values.last(), false);
1549 QVERIFY(!item->isSelected());
1550 item->setVisible(true);
1551 QCOMPARE(item->values.size(), 6);
1552 item->setSelected(true);
1553 QCOMPARE(item->values.size(), 7);
1554 QCOMPARE(item->values.last(), true);
1555 QVERIFY(item->isSelected());
1557 QGraphicsScene scene(-100, -100, 200, 200);
1558 scene.addItem(item);
1559 QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>() << item);
1560 item->setSelected(false);
1561 QVERIFY(scene.selectedItems().isEmpty());
1562 item->setSelected(true);
1563 QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>() << item);
1564 item->setSelected(false);
1565 QVERIFY(scene.selectedItems().isEmpty());
1567 // Interactive selection
1568 QGraphicsView view(&scene);
1569 view.setFixedSize(250, 250);
1572 QVERIFY(QTest::qWaitForWindowExposed(&view));
1573 qApp->processEvents();
1574 qApp->processEvents();
1576 scene.clearSelection();
1577 QCOMPARE(item->values.size(), 10);
1578 QCOMPARE(item->values.last(), false);
1579 QVERIFY(!item->isSelected());
1581 // Click inside and check that it's selected
1582 QTest::mouseMove(view.viewport());
1583 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos()));
1584 QCOMPARE(item->values.size(), 11);
1585 QCOMPARE(item->values.last(), true);
1586 QVERIFY(item->isSelected());
1588 // Click outside and check that it's not selected
1589 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos() + QPointF(item->boundingRect().width(), item->boundingRect().height())));
1590 QCOMPARE(item->values.size(), 12);
1591 QCOMPARE(item->values.last(), false);
1592 QVERIFY(!item->isSelected());
1594 SelectChangeItem *item2 = new SelectChangeItem;
1595 item2->setFlag(QGraphicsItem::ItemIsSelectable);
1596 item2->setPos(100, 0);
1597 scene.addItem(item2);
1599 // Click inside and check that it's selected
1600 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos()));
1601 QCOMPARE(item->values.size(), 13);
1602 QCOMPARE(item->values.last(), true);
1603 QVERIFY(item->isSelected());
1605 // Click inside item2 and check that it's selected, and item is not
1606 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
1607 QCOMPARE(item->values.size(), 14);
1608 QCOMPARE(item->values.last(), false);
1609 QVERIFY(!item->isSelected());
1610 QCOMPARE(item2->values.size(), 1);
1611 QCOMPARE(item2->values.last(), true);
1612 QVERIFY(item2->isSelected());
1615 void tst_QGraphicsItem::selected2()
1617 // Selecting an item, then moving another previously caused a crash.
1618 QGraphicsScene scene;
1619 QGraphicsItem *line1 = scene.addRect(QRectF(0, 0, 100, 100));
1620 line1->setPos(-105, 0);
1621 line1->setFlag(QGraphicsItem::ItemIsSelectable);
1623 QGraphicsItem *line2 = scene.addRect(QRectF(0, 0, 100, 100));
1624 line2->setFlag(QGraphicsItem::ItemIsMovable);
1626 line1->setSelected(true);
1629 QGraphicsSceneMouseEvent mousePress(QEvent::GraphicsSceneMousePress);
1630 mousePress.setScenePos(QPointF(50, 50));
1631 mousePress.setButton(Qt::LeftButton);
1632 QApplication::sendEvent(&scene, &mousePress);
1633 QVERIFY(mousePress.isAccepted());
1636 QGraphicsSceneMouseEvent mouseMove(QEvent::GraphicsSceneMouseMove);
1637 mouseMove.setScenePos(QPointF(60, 60));
1638 mouseMove.setButton(Qt::LeftButton);
1639 mouseMove.setButtons(Qt::LeftButton);
1640 QApplication::sendEvent(&scene, &mouseMove);
1641 QVERIFY(mouseMove.isAccepted());
1645 void tst_QGraphicsItem::selected_group()
1647 QGraphicsScene scene;
1648 QGraphicsItem *item1 = scene.addRect(QRectF());
1649 QGraphicsItem *item2 = scene.addRect(QRectF());
1650 item1->setFlag(QGraphicsItem::ItemIsSelectable);
1651 item2->setFlag(QGraphicsItem::ItemIsSelectable);
1652 scene.addRect(QRectF())->setParentItem(item1);
1653 QGraphicsItem *leaf = scene.addRect(QRectF());
1654 leaf->setFlag(QGraphicsItem::ItemIsSelectable);
1655 leaf->setParentItem(item2);
1657 QGraphicsItemGroup *group = scene.createItemGroup(QList<QGraphicsItem *>() << item1 << item2);
1658 QCOMPARE(group->scene(), &scene);
1659 group->setFlag(QGraphicsItem::ItemIsSelectable);
1660 foreach (QGraphicsItem *item, scene.items()) {
1662 QVERIFY(!item->group());
1664 QCOMPARE(item->group(), group);
1667 QVERIFY(group->handlesChildEvents());
1668 QVERIFY(!group->isSelected());
1669 group->setSelected(false);
1670 QVERIFY(!group->isSelected());
1671 group->setSelected(true);
1672 QVERIFY(group->isSelected());
1673 foreach (QGraphicsItem *item, scene.items())
1674 QVERIFY(item->isSelected());
1675 group->setSelected(false);
1676 QVERIFY(!group->isSelected());
1677 foreach (QGraphicsItem *item, scene.items())
1678 QVERIFY(!item->isSelected());
1679 leaf->setSelected(true);
1680 foreach (QGraphicsItem *item, scene.items())
1681 QVERIFY(item->isSelected());
1682 leaf->setSelected(false);
1683 foreach (QGraphicsItem *item, scene.items())
1684 QVERIFY(!item->isSelected());
1686 leaf->setSelected(true);
1687 QGraphicsScene scene2;
1688 scene2.addItem(item1);
1689 QVERIFY(!item1->isSelected());
1690 QVERIFY(item2->isSelected());
1693 void tst_QGraphicsItem::selected_textItem()
1695 QGraphicsScene scene;
1696 QGraphicsTextItem *text = scene.addText(QLatin1String("Text"));
1697 text->setFlag(QGraphicsItem::ItemIsSelectable);
1699 QGraphicsView view(&scene);
1701 QVERIFY(QTest::qWaitForWindowExposed(&view));
1704 QTRY_VERIFY(!text->isSelected());
1705 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0,
1706 view.mapFromScene(text->mapToScene(0, 0)));
1707 QTRY_VERIFY(text->isSelected());
1709 text->setSelected(false);
1710 text->setTextInteractionFlags(Qt::TextEditorInteraction);
1712 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0,
1713 view.mapFromScene(text->mapToScene(0, 0)));
1714 QTRY_VERIFY(text->isSelected());
1717 void tst_QGraphicsItem::selected_multi()
1719 // Test multiselection behavior
1720 QGraphicsScene scene;
1722 // Create two disjoint items
1723 QGraphicsItem *item1 = scene.addRect(QRectF(-10, -10, 20, 20));
1724 QGraphicsItem *item2 = scene.addRect(QRectF(-10, -10, 20, 20));
1725 item1->setPos(-15, 0);
1726 item2->setPos(15, 20);
1728 // Make both items selectable
1729 item1->setFlag(QGraphicsItem::ItemIsSelectable);
1730 item2->setFlag(QGraphicsItem::ItemIsSelectable);
1732 // Create and show a view
1733 QGraphicsView view(&scene);
1735 view.fitInView(scene.sceneRect());
1736 qApp->processEvents();
1738 QVERIFY(!item1->isSelected());
1739 QVERIFY(!item2->isSelected());
1745 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
1747 QVERIFY(item1->isSelected());
1748 QVERIFY(!item2->isSelected());
1751 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
1753 QVERIFY(item2->isSelected());
1754 QVERIFY(!item1->isSelected());
1756 // Ctrl-click on item1
1757 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1759 QVERIFY(item2->isSelected());
1760 QVERIFY(item1->isSelected());
1762 // Ctrl-click on item1 again
1763 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1765 QVERIFY(item2->isSelected());
1766 QVERIFY(!item1->isSelected());
1768 // Ctrl-click on item2
1769 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item2->scenePos()));
1771 QVERIFY(!item2->isSelected());
1772 QVERIFY(!item1->isSelected());
1775 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
1777 QVERIFY(item1->isSelected());
1778 QVERIFY(!item2->isSelected());
1781 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(0, 0));
1783 QVERIFY(!item1->isSelected());
1784 QVERIFY(!item2->isSelected());
1787 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
1789 QVERIFY(item1->isSelected());
1790 QVERIFY(!item2->isSelected());
1792 // Ctrl-click on scene
1793 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(0, 0));
1795 QVERIFY(!item1->isSelected());
1796 QVERIFY(!item2->isSelected());
1799 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
1801 QVERIFY(item1->isSelected());
1802 QVERIFY(!item2->isSelected());
1805 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
1807 QVERIFY(!item1->isSelected());
1808 QVERIFY(item2->isSelected());
1811 QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
1813 QVERIFY(!item1->isSelected());
1814 QVERIFY(item2->isSelected());
1817 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
1819 QVERIFY(item1->isSelected());
1820 QVERIFY(!item2->isSelected());
1822 // Ctrl-click on item1
1823 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1825 QVERIFY(!item1->isSelected());
1826 QVERIFY(!item2->isSelected());
1828 // Ctrl-press on item1
1829 QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1831 QVERIFY(!item1->isSelected());
1832 QVERIFY(!item2->isSelected());
1835 // Ctrl-move on item1
1836 QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item1->scenePos()) + QPoint(1, 0), Qt::LeftButton, Qt::LeftButton, Qt::ControlModifier);
1837 QApplication::sendEvent(view.viewport(), &event);
1839 QVERIFY(!item1->isSelected());
1840 QVERIFY(!item2->isSelected());
1844 QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1846 QVERIFY(item1->isSelected());
1847 QVERIFY(!item2->isSelected());
1849 item1->setFlag(QGraphicsItem::ItemIsMovable);
1850 item1->setSelected(false);
1852 // Ctrl-press on item1
1853 QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1855 QVERIFY(!item1->isSelected());
1856 QVERIFY(!item2->isSelected());
1859 // Ctrl-move on item1
1860 QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item1->scenePos()) + QPoint(1, 0), Qt::LeftButton, Qt::LeftButton, Qt::ControlModifier);
1861 QApplication::sendEvent(view.viewport(), &event);
1863 QVERIFY(item1->isSelected());
1864 QVERIFY(!item2->isSelected());
1868 QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1870 QVERIFY(item1->isSelected());
1871 QVERIFY(!item2->isSelected());
1874 void tst_QGraphicsItem::acceptedMouseButtons()
1876 QGraphicsScene scene;
1877 QGraphicsRectItem *item1 = scene.addRect(QRectF(-10, -10, 20, 20));
1878 QGraphicsRectItem *item2 = scene.addRect(QRectF(-10, -10, 20, 20));
1879 item2->setZValue(1);
1881 item1->setFlag(QGraphicsItem::ItemIsMovable);
1882 item2->setFlag(QGraphicsItem::ItemIsMovable);
1884 QCOMPARE(item1->acceptedMouseButtons(), Qt::MouseButtons(0x1f));
1885 QCOMPARE(item2->acceptedMouseButtons(), Qt::MouseButtons(0x1f));
1887 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
1888 event.setButton(Qt::LeftButton);
1889 event.setScenePos(QPointF(0, 0));
1890 QApplication::sendEvent(&scene, &event);
1891 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item2);
1892 item2->setAcceptedMouseButtons(0);
1893 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1894 QApplication::sendEvent(&scene, &event);
1895 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item1);
1898 class HoverItem : public QGraphicsRectItem
1901 HoverItem(const QRectF &rect)
1902 : QGraphicsRectItem(rect), hoverInCount(0),
1903 hoverMoveCount(0), hoverOutCount(0)
1910 void hoverEnterEvent(QGraphicsSceneHoverEvent *)
1913 void hoverMoveEvent(QGraphicsSceneHoverEvent *)
1914 { ++hoverMoveCount; }
1916 void hoverLeaveEvent(QGraphicsSceneHoverEvent *)
1917 { ++hoverOutCount; }
1920 void tst_QGraphicsItem::acceptsHoverEvents()
1922 QGraphicsScene scene;
1923 HoverItem *item1 = new HoverItem(QRectF(-10, -10, 20, 20));
1924 HoverItem *item2 = new HoverItem(QRectF(-5, -5, 10, 10));
1925 scene.addItem(item1);
1926 scene.addItem(item2);
1927 item2->setZValue(1);
1929 QVERIFY(!item1->acceptsHoverEvents());
1930 QVERIFY(!item2->acceptsHoverEvents());
1931 item1->setAcceptsHoverEvents(true);
1932 item2->setAcceptsHoverEvents(true);
1934 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
1935 event.setScenePos(QPointF(-100, -100));
1936 QApplication::sendEvent(&scene, &event);
1937 event.setScenePos(QPointF(-2.5, -2.5));
1938 QApplication::sendEvent(&scene, &event);
1940 QCOMPARE(item1->hoverInCount, 0);
1941 QCOMPARE(item2->hoverInCount, 1);
1943 item1->setAcceptsHoverEvents(false);
1944 item2->setAcceptsHoverEvents(false);
1946 event.setScenePos(QPointF(-100, -100));
1947 QApplication::sendEvent(&scene, &event);
1948 event.setScenePos(QPointF(-2.5, -2.5));
1949 QApplication::sendEvent(&scene, &event);
1951 QCOMPARE(item1->hoverInCount, 0);
1952 QCOMPARE(item2->hoverInCount, 1);
1954 item1->setAcceptsHoverEvents(true);
1955 item2->setAcceptsHoverEvents(false);
1957 event.setScenePos(QPointF(-100, -100));
1958 QApplication::sendEvent(&scene, &event);
1959 event.setScenePos(QPointF(-2.5, -2.5));
1960 QApplication::sendEvent(&scene, &event);
1962 QCOMPARE(item1->hoverInCount, 1);
1963 QCOMPARE(item2->hoverInCount, 1);
1966 void tst_QGraphicsItem::childAcceptsHoverEvents()
1968 QGraphicsScene scene;
1969 HoverItem *item1 = new HoverItem(QRectF(-10, -10, 20, 20));
1970 HoverItem *item2 = new HoverItem(QRectF(-5, -5, 10, 10));
1972 scene.addItem(item1);
1973 scene.addItem(item2);
1974 item2->setParentItem(item1);
1975 item2->setAcceptHoverEvents(true);
1977 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
1978 event.setScenePos(QPointF(-100, -100));
1979 QApplication::sendEvent(&scene, &event);
1980 QCOMPARE(item2->hoverInCount, 0);
1981 QCOMPARE(item2->hoverMoveCount, 0);
1982 QCOMPARE(item2->hoverOutCount, 0);
1983 QCOMPARE(item1->hoverInCount, 0);
1984 QCOMPARE(item1->hoverMoveCount, 0);
1985 QCOMPARE(item1->hoverOutCount, 0);
1987 event.setScenePos(QPointF(-2.5, -2.5));
1988 QApplication::sendEvent(&scene, &event);
1990 QCOMPARE(item2->hoverInCount, 1);
1991 QCOMPARE(item2->hoverMoveCount, 1);
1992 QCOMPARE(item2->hoverOutCount, 0);
1993 QCOMPARE(item1->hoverInCount, 0);
1994 QCOMPARE(item1->hoverMoveCount, 0);
1995 QCOMPARE(item1->hoverOutCount, 0);
1997 event.setScenePos(QPointF(0, 0));
1998 QApplication::sendEvent(&scene, &event);
2000 QCOMPARE(item2->hoverInCount, 1);
2001 QCOMPARE(item2->hoverMoveCount, 2);
2002 QCOMPARE(item2->hoverOutCount, 0);
2003 QCOMPARE(item1->hoverInCount, 0);
2004 QCOMPARE(item1->hoverMoveCount, 0);
2005 QCOMPARE(item1->hoverOutCount, 0);
2007 event.setScenePos(QPointF(-7, -7));
2008 QApplication::sendEvent(&scene, &event);
2010 QCOMPARE(item2->hoverInCount, 1);
2011 QCOMPARE(item2->hoverMoveCount, 2);
2012 QCOMPARE(item2->hoverOutCount, 1);
2013 QCOMPARE(item1->hoverInCount, 0);
2014 QCOMPARE(item1->hoverMoveCount, 0);
2015 QCOMPARE(item1->hoverOutCount, 0);
2017 event.setScenePos(QPointF(0, 0));
2018 QApplication::sendEvent(&scene, &event);
2020 QCOMPARE(item2->hoverInCount, 2);
2021 QCOMPARE(item2->hoverMoveCount, 3);
2022 QCOMPARE(item2->hoverOutCount, 1);
2023 QCOMPARE(item1->hoverInCount, 0);
2024 QCOMPARE(item1->hoverMoveCount, 0);
2025 QCOMPARE(item1->hoverOutCount, 0);
2027 HoverItem *item0 = new HoverItem(QRectF(-20, -20, 20, 20));
2028 scene.addItem(item0);
2029 item1->setParentItem(item0);
2030 item0->setAcceptHoverEvents(true);
2032 event.setScenePos(QPointF(-100, -100));
2033 QApplication::sendEvent(&scene, &event);
2035 event.setScenePos(QPointF(-15, -15));
2036 QApplication::sendEvent(&scene, &event);
2038 QCOMPARE(item2->hoverInCount, 2);
2039 QCOMPARE(item2->hoverMoveCount, 3);
2040 QCOMPARE(item2->hoverOutCount, 2);
2041 QCOMPARE(item1->hoverInCount, 0);
2042 QCOMPARE(item1->hoverMoveCount, 0);
2043 QCOMPARE(item1->hoverOutCount, 0);
2044 QCOMPARE(item0->hoverInCount, 1);
2045 QCOMPARE(item0->hoverMoveCount, 1);
2046 QCOMPARE(item0->hoverOutCount, 0);
2049 void tst_QGraphicsItem::hasFocus()
2051 QGraphicsLineItem *line = new QGraphicsLineItem;
2052 QVERIFY(!line->hasFocus());
2054 QVERIFY(!line->hasFocus());
2056 QGraphicsScene scene;
2057 QEvent activate(QEvent::WindowActivate);
2058 QApplication::sendEvent(&scene, &activate);
2060 scene.addItem(line);
2063 QVERIFY(!line->hasFocus());
2064 line->setFlag(QGraphicsItem::ItemIsFocusable);
2066 QVERIFY(line->hasFocus());
2068 QGraphicsScene scene2;
2069 QApplication::sendEvent(&scene2, &activate);
2071 scene2.addItem(line);
2072 QVERIFY(!line->hasFocus());
2074 QCOMPARE(scene.focusItem(), (QGraphicsItem *)0);
2075 QCOMPARE(scene2.focusItem(), (QGraphicsItem *)0);
2078 QVERIFY(line->hasFocus());
2080 QVERIFY(!line->hasFocus());
2082 QGraphicsLineItem *line2 = new QGraphicsLineItem;
2083 line2->setFlag(QGraphicsItem::ItemIsFocusable);
2084 scene2.addItem(line2);
2087 QVERIFY(!line->hasFocus());
2088 QVERIFY(line2->hasFocus());
2090 QVERIFY(line->hasFocus());
2091 QVERIFY(!line2->hasFocus());
2094 void tst_QGraphicsItem::pos()
2096 QGraphicsItem *child = new QGraphicsLineItem;
2097 QGraphicsItem *parent = new QGraphicsLineItem;
2099 QCOMPARE(child->pos(), QPointF());
2100 QCOMPARE(parent->pos(), QPointF());
2102 child->setParentItem(parent);
2103 child->setPos(10, 10);
2105 QCOMPARE(child->pos(), QPointF(10, 10));
2107 parent->setPos(10, 10);
2109 QCOMPARE(parent->pos(), QPointF(10, 10));
2110 QCOMPARE(child->pos(), QPointF(10, 10));
2116 void tst_QGraphicsItem::scenePos()
2118 QGraphicsItem *child = new QGraphicsLineItem;
2119 QGraphicsItem *parent = new QGraphicsLineItem;
2121 QCOMPARE(child->scenePos(), QPointF());
2122 QCOMPARE(parent->scenePos(), QPointF());
2124 child->setParentItem(parent);
2125 child->setPos(10, 10);
2127 QCOMPARE(child->scenePos(), QPointF(10, 10));
2129 parent->setPos(10, 10);
2131 QCOMPARE(parent->scenePos(), QPointF(10, 10));
2132 QCOMPARE(child->scenePos(), QPointF(20, 20));
2134 parent->setPos(20, 20);
2136 QCOMPARE(parent->scenePos(), QPointF(20, 20));
2137 QCOMPARE(child->scenePos(), QPointF(30, 30));
2143 void tst_QGraphicsItem::matrix()
2145 QGraphicsLineItem line;
2146 QCOMPARE(line.matrix(), QMatrix());
2147 line.setMatrix(QMatrix().rotate(90));
2148 QCOMPARE(line.matrix(), QMatrix().rotate(90));
2149 line.setMatrix(QMatrix().rotate(90));
2150 QCOMPARE(line.matrix(), QMatrix().rotate(90));
2151 line.setMatrix(QMatrix().rotate(90), true);
2152 QCOMPARE(line.matrix(), QMatrix().rotate(180));
2153 line.setMatrix(QMatrix().rotate(-90), true);
2154 QCOMPARE(line.matrix(), QMatrix().rotate(90));
2156 QCOMPARE(line.matrix(), QMatrix());
2159 QCOMPARE(line.matrix(), QMatrix().rotate(90));
2161 QCOMPARE(line.matrix(), QMatrix().rotate(90).rotate(90));
2165 QCOMPARE(line.matrix(), QMatrix().scale(2, 4));
2167 QCOMPARE(line.matrix(), QMatrix().scale(2, 4).scale(2, 4));
2171 QCOMPARE(line.matrix(), QMatrix().shear(2, 4));
2173 QCOMPARE(line.matrix(), QMatrix().shear(2, 4).shear(2, 4));
2176 line.translate(10, 10);
2177 QCOMPARE(line.matrix(), QMatrix().translate(10, 10));
2178 line.translate(10, 10);
2179 QCOMPARE(line.matrix(), QMatrix().translate(10, 10).translate(10, 10));
2183 void tst_QGraphicsItem::sceneMatrix()
2185 QGraphicsLineItem *parent = new QGraphicsLineItem;
2186 QGraphicsLineItem *child = new QGraphicsLineItem(QLineF(), parent);
2188 QCOMPARE(parent->sceneMatrix(), QMatrix());
2189 QCOMPARE(child->sceneMatrix(), QMatrix());
2191 parent->translate(10, 10);
2192 QCOMPARE(parent->sceneMatrix(), QMatrix().translate(10, 10));
2193 QCOMPARE(child->sceneMatrix(), QMatrix().translate(10, 10));
2195 child->translate(10, 10);
2196 QCOMPARE(parent->sceneMatrix(), QMatrix().translate(10, 10));
2197 QCOMPARE(child->sceneMatrix(), QMatrix().translate(20, 20));
2200 QCOMPARE(parent->sceneMatrix(), QMatrix().translate(10, 10).rotate(90));
2201 QCOMPARE(child->sceneMatrix(), QMatrix().translate(10, 10).rotate(90).translate(10, 10));
2207 void tst_QGraphicsItem::setMatrix()
2209 QGraphicsScene scene;
2210 qRegisterMetaType<QList<QRectF> >("QList<QRectF>");
2211 QSignalSpy spy(&scene, SIGNAL(changed(QList<QRectF>)));
2212 QRectF unrotatedRect(-12, -34, 56, 78);
2213 QGraphicsRectItem item(unrotatedRect, 0);
2214 item.setPen(QPen(Qt::black, 0));
2215 scene.addItem(&item);
2216 scene.update(scene.sceneRect());
2217 QApplication::instance()->processEvents();
2219 QCOMPARE(spy.count(), 1);
2221 item.setMatrix(QMatrix().rotate(qreal(12.34)));
2222 QRectF rotatedRect = scene.sceneRect();
2223 QVERIFY(unrotatedRect != rotatedRect);
2224 scene.update(scene.sceneRect());
2225 QApplication::instance()->processEvents();
2227 QCOMPARE(spy.count(), 2);
2229 item.setMatrix(QMatrix());
2231 scene.update(scene.sceneRect());
2232 QApplication::instance()->processEvents();
2234 QCOMPARE(spy.count(), 3);
2235 QList<QRectF> rlist = qvariant_cast<QList<QRectF> >(spy.last().at(0));
2237 QCOMPARE(rlist.size(), 3);
2238 QCOMPARE(rlist.at(0), rotatedRect); // From item.setMatrix() (clearing rotated rect)
2239 QCOMPARE(rlist.at(1), rotatedRect); // From scene.update() (updating scene rect)
2240 QCOMPARE(rlist.at(2), unrotatedRect); // From post-update (update current state)
2243 static QList<QGraphicsItem *> _paintedItems;
2244 class PainterItem : public QGraphicsItem
2247 QRectF boundingRect() const
2248 { return QRectF(-10, -10, 20, 20); }
2250 void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
2251 { _paintedItems << this; painter->fillRect(boundingRect(), Qt::red); }
2254 void tst_QGraphicsItem::zValue()
2258 QGraphicsScene scene;
2260 QGraphicsItem *item1 = new PainterItem;
2261 QGraphicsItem *item2 = new PainterItem;
2262 QGraphicsItem *item3 = new PainterItem;
2263 QGraphicsItem *item4 = new PainterItem;
2264 scene.addItem(item1);
2265 scene.addItem(item2);
2266 scene.addItem(item3);
2267 scene.addItem(item4);
2268 item2->setZValue(-3);
2269 item4->setZValue(-2);
2270 item1->setZValue(-1);
2271 item3->setZValue(0);
2273 QGraphicsView view(&scene);
2275 QVERIFY(QTest::qWaitForWindowExposed(&view));
2277 QApplication::processEvents();
2279 QTRY_VERIFY(!_paintedItems.isEmpty());
2280 QVERIFY((_paintedItems.size() % 4) == 0);
2281 for (int i = 0; i < 3; ++i)
2282 QVERIFY(_paintedItems.at(i)->zValue() < _paintedItems.at(i + 1)->zValue());
2285 void tst_QGraphicsItem::shape()
2287 QGraphicsLineItem line(QLineF(-10, -10, 20, 20));
2288 line.setPen(QPen(Qt::black, 0));
2290 // We unfortunately need this hack as QPainterPathStroker will set a width of 1.0
2291 // if we pass a value of 0.0 to QPainterPathStroker::setWidth()
2292 const qreal penWidthZero = qreal(0.00000001);
2294 QPainterPathStroker ps;
2295 ps.setWidth(penWidthZero);
2297 QPainterPath path(line.line().p1());
2298 path.lineTo(line.line().p2());
2299 QPainterPath p = ps.createStroke(path);
2301 QCOMPARE(line.shape(), p);
2304 linePen.setWidthF(5.0);
2305 linePen.setCapStyle(Qt::RoundCap);
2306 line.setPen(linePen);
2308 ps.setCapStyle(line.pen().capStyle());
2309 ps.setWidth(line.pen().widthF());
2310 p = ps.createStroke(path);
2312 QCOMPARE(line.shape(), p);
2314 linePen.setCapStyle(Qt::FlatCap);
2315 line.setPen(linePen);
2316 ps.setCapStyle(line.pen().capStyle());
2317 p = ps.createStroke(path);
2319 QCOMPARE(line.shape(), p);
2321 linePen.setCapStyle(Qt::SquareCap);
2322 line.setPen(linePen);
2323 ps.setCapStyle(line.pen().capStyle());
2324 p = ps.createStroke(path);
2326 QCOMPARE(line.shape(), p);
2328 QGraphicsRectItem rect(QRectF(-10, -10, 20, 20));
2329 rect.setPen(QPen(Qt::black, 0));
2330 QPainterPathStroker ps1;
2331 ps1.setWidth(penWidthZero);
2332 path = QPainterPath();
2333 path.addRect(rect.rect());
2334 p = ps1.createStroke(path);
2336 QCOMPARE(rect.shape(), p);
2338 QGraphicsEllipseItem ellipse(QRectF(-10, -10, 20, 20));
2339 ellipse.setPen(QPen(Qt::black, 0));
2340 QPainterPathStroker ps2;
2341 ps2.setWidth(ellipse.pen().widthF() <= 0.0 ? penWidthZero : ellipse.pen().widthF());
2342 path = QPainterPath();
2343 path.addEllipse(ellipse.rect());
2344 p = ps2.createStroke(path);
2346 QCOMPARE(ellipse.shape(), p);
2348 QPainterPathStroker ps3;
2349 ps3.setWidth(penWidthZero);
2350 p = ps3.createStroke(path);
2352 QGraphicsPathItem pathItem(path);
2353 pathItem.setPen(QPen(Qt::black, 0));
2354 QCOMPARE(pathItem.shape(), p);
2356 QRegion region(QRect(0, 0, 300, 200));
2357 region = region.subtracted(QRect(50, 50, 200, 100));
2359 QImage image(300, 200, QImage::Format_ARGB32_Premultiplied);
2361 QPainter painter(&image);
2362 painter.setClipRegion(region);
2363 painter.fillRect(0, 0, 300, 200, Qt::green);
2365 QPixmap pixmap = QPixmap::fromImage(image);
2367 QGraphicsPixmapItem pixmapItem(pixmap);
2368 path = QPainterPath();
2369 path.addRegion(region);
2372 QBitmap bitmap(300, 200);
2374 QPainter painter(&bitmap);
2375 painter.setClipRegion(region);
2376 painter.fillRect(0, 0, 300, 200, Qt::color1);
2379 QBitmap bitmap2(300, 200);
2381 painter.begin(&bitmap2);
2382 painter.setClipPath(pixmapItem.shape());
2383 painter.fillRect(0, 0, 300, 200, Qt::color1);
2386 QCOMPARE(bitmap.toImage(), bitmap2.toImage());
2390 poly << QPointF(0, 0) << QPointF(10, 0) << QPointF(0, 10);
2391 QGraphicsPolygonItem polygon(poly);
2392 polygon.setPen(QPen(Qt::black, 0));
2393 path = QPainterPath();
2394 path.addPolygon(poly);
2396 QPainterPathStroker ps4;
2397 ps4.setWidth(penWidthZero);
2398 p = ps4.createStroke(path);
2400 QCOMPARE(polygon.shape(), p);
2403 void tst_QGraphicsItem::contains()
2405 if (sizeof(qreal) != sizeof(double))
2406 QSKIP("Skipped due to rounding errors");
2409 QGraphicsRectItem rect(QRectF(-10, -10, 20, 20));
2410 QVERIFY(!rect.contains(QPointF(-11, -10)));
2411 QVERIFY(rect.contains(QPointF(-10, -10)));
2412 QVERIFY(!rect.contains(QPointF(-11, 0)));
2413 QVERIFY(rect.contains(QPointF(-10, 0)));
2414 QVERIFY(rect.contains(QPointF(0, -10)));
2415 QVERIFY(rect.contains(QPointF(0, 0)));
2416 QVERIFY(rect.contains(QPointF(9, 9)));
2419 QGraphicsEllipseItem ellipse(QRectF(-10, -10, 20, 20));
2420 QVERIFY(!ellipse.contains(QPointF(-10, -10)));
2421 QVERIFY(ellipse.contains(QPointF(-9, 0)));
2422 QVERIFY(ellipse.contains(QPointF(0, -9)));
2423 QVERIFY(ellipse.contains(QPointF(0, 0)));
2424 QVERIFY(!ellipse.contains(QPointF(9, 9)));
2427 QGraphicsLineItem line(QLineF(-10, -10, 20, 20));
2428 QVERIFY(!line.contains(QPointF(-10, 0)));
2429 QVERIFY(!line.contains(QPointF(0, -10)));
2430 QVERIFY(!line.contains(QPointF(10, 0)));
2431 QVERIFY(!line.contains(QPointF(0, 10)));
2432 QVERIFY(line.contains(QPointF(0, 0)));
2433 QVERIFY(line.contains(QPointF(-9, -9)));
2434 QVERIFY(line.contains(QPointF(9, 9)));
2437 QGraphicsPolygonItem polygon(QPolygonF()
2441 QVERIFY(polygon.contains(QPointF(1, 1)));
2442 QVERIFY(polygon.contains(QPointF(4, 4)));
2443 QVERIFY(polygon.contains(QPointF(1, 4)));
2444 QVERIFY(polygon.contains(QPointF(4, 1)));
2445 QVERIFY(!polygon.contains(QPointF(8, 8)));
2446 QVERIFY(polygon.contains(QPointF(1, 8)));
2447 QVERIFY(polygon.contains(QPointF(8, 1)));
2450 void tst_QGraphicsItem::collidesWith_item()
2453 QGraphicsRectItem rect(QRectF(-10, -10, 20, 20));
2454 QGraphicsRectItem rect2(QRectF(-10, -10, 20, 20));
2455 QVERIFY(rect.collidesWithItem(&rect2));
2456 QVERIFY(rect2.collidesWithItem(&rect));
2457 rect2.setPos(21, 21);
2458 QVERIFY(!rect.collidesWithItem(&rect2));
2459 QVERIFY(!rect2.collidesWithItem(&rect));
2460 rect2.setPos(-21, -21);
2461 QVERIFY(!rect.collidesWithItem(&rect2));
2462 QVERIFY(!rect2.collidesWithItem(&rect));
2463 rect2.setPos(-17, -17);
2464 QVERIFY(rect.collidesWithItem(&rect2));
2465 QVERIFY(rect2.collidesWithItem(&rect));
2467 QGraphicsEllipseItem ellipse(QRectF(-10, -10, 20, 20));
2468 QGraphicsEllipseItem ellipse2(QRectF(-10, -10, 20, 20));
2469 QVERIFY(ellipse.collidesWithItem(&ellipse2));
2470 QVERIFY(ellipse2.collidesWithItem(&ellipse));
2471 ellipse2.setPos(21, 21);
2472 QVERIFY(!ellipse.collidesWithItem(&ellipse2));
2473 QVERIFY(!ellipse2.collidesWithItem(&ellipse));
2474 ellipse2.setPos(-21, -21);
2475 QVERIFY(!ellipse.collidesWithItem(&ellipse2));
2476 QVERIFY(!ellipse2.collidesWithItem(&ellipse));
2478 ellipse2.setPos(-17, -17);
2479 QVERIFY(!ellipse.collidesWithItem(&ellipse2));
2480 QVERIFY(!ellipse2.collidesWithItem(&ellipse));
2483 QGraphicsScene scene;
2484 QGraphicsRectItem rect(20, 20, 100, 100, 0);
2485 scene.addItem(&rect);
2486 QGraphicsRectItem rect2(40, 40, 50, 50, 0);
2487 scene.addItem(&rect2);
2489 QGraphicsLineItem line(0, 0, 200, 200, 0);
2490 scene.addItem(&line);
2493 QCOMPARE(scene.items().size(), 3);
2495 QList<QGraphicsItem *> col1 = rect.collidingItems();
2496 QCOMPARE(col1.size(), 2);
2497 QCOMPARE(col1.first(), static_cast<QGraphicsItem *>(&line));
2498 QCOMPARE(col1.last(), static_cast<QGraphicsItem *>(&rect2));
2500 QList<QGraphicsItem *> col2 = rect2.collidingItems();
2501 QCOMPARE(col2.size(), 2);
2502 QCOMPARE(col2.first(), static_cast<QGraphicsItem *>(&line));
2503 QCOMPARE(col2.last(), static_cast<QGraphicsItem *>(&rect));
2505 QList<QGraphicsItem *> col3 = line.collidingItems();
2506 QCOMPARE(col3.size(), 2);
2507 QCOMPARE(col3.first(), static_cast<QGraphicsItem *>(&rect2));
2508 QCOMPARE(col3.last(), static_cast<QGraphicsItem *>(&rect));
2512 void tst_QGraphicsItem::collidesWith_path_data()
2514 QTest::addColumn<QPointF>("pos");
2515 QTest::addColumn<QMatrix>("matrix");
2516 QTest::addColumn<QPainterPath>("shape");
2517 QTest::addColumn<bool>("rectCollides");
2518 QTest::addColumn<bool>("ellipseCollides");
2520 QTest::newRow("nothing") << QPointF(0, 0) << QMatrix() << QPainterPath() << false << false;
2523 rect.addRect(0, 0, 20, 20);
2525 QTest::newRow("rect1") << QPointF(0, 0) << QMatrix() << rect << true << true;
2526 QTest::newRow("rect2") << QPointF(0, 0) << QMatrix().translate(21, 21) << rect << false << false;
2527 QTest::newRow("rect3") << QPointF(21, 21) << QMatrix() << rect << false << false;
2530 void tst_QGraphicsItem::collidesWith_path()
2532 QFETCH(QPointF, pos);
2533 QFETCH(QMatrix, matrix);
2534 QFETCH(QPainterPath, shape);
2535 QFETCH(bool, rectCollides);
2536 QFETCH(bool, ellipseCollides);
2538 QGraphicsRectItem rect(QRectF(0, 0, 20, 20));
2539 QGraphicsEllipseItem ellipse(QRectF(0, 0, 20, 20));
2542 rect.setMatrix(matrix);
2544 ellipse.setPos(pos);
2545 ellipse.setMatrix(matrix);
2547 QPainterPath mappedShape = rect.sceneMatrix().inverted().map(shape);
2550 QVERIFY(rect.collidesWithPath(mappedShape));
2552 QVERIFY(!rect.collidesWithPath(mappedShape));
2554 if (ellipseCollides)
2555 QVERIFY(ellipse.collidesWithPath(mappedShape));
2557 QVERIFY(!ellipse.collidesWithPath(mappedShape));
2560 void tst_QGraphicsItem::collidesWithItemWithClip()
2562 QGraphicsScene scene;
2564 QGraphicsEllipseItem *ellipse = scene.addEllipse(0, 0, 100, 100);
2565 ellipse->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
2566 QGraphicsEllipseItem *ellipse2 = scene.addEllipse(0, 0, 10, 10);
2567 ellipse2->setParentItem(ellipse);
2568 QGraphicsEllipseItem *ellipse3 = scene.addEllipse(0, 0, 10, 10);
2569 ellipse3->setParentItem(ellipse);
2570 QGraphicsEllipseItem *ellipse5 = scene.addEllipse(50, 50, 10, 10);
2571 ellipse5->setParentItem(ellipse);
2572 QGraphicsEllipseItem *ellipse4 = scene.addEllipse(0, 0, 10, 10);
2574 QVERIFY(ellipse2->collidesWithItem(ellipse3));
2575 QVERIFY(ellipse3->collidesWithItem(ellipse2));
2576 QVERIFY(!ellipse2->collidesWithItem(ellipse));
2577 QVERIFY(!ellipse->collidesWithItem(ellipse2));
2578 QVERIFY(!ellipse4->collidesWithItem(ellipse));
2579 QVERIFY(!ellipse4->collidesWithItem(ellipse2));
2580 QVERIFY(!ellipse4->collidesWithItem(ellipse3));
2581 QVERIFY(!ellipse->collidesWithItem(ellipse4));
2582 QVERIFY(!ellipse2->collidesWithItem(ellipse4));
2583 QVERIFY(!ellipse3->collidesWithItem(ellipse4));
2584 QVERIFY(ellipse->collidesWithItem(ellipse5));
2585 QVERIFY(ellipse5->collidesWithItem(ellipse));
2588 class MyItem : public QGraphicsEllipseItem
2591 bool isObscuredBy(const QGraphicsItem *item) const
2593 const MyItem *myItem = qgraphicsitem_cast<const MyItem *>(item);
2595 if (item->zValue() > zValue()) {
2597 QPointF topMid = (r.topRight()+r.topLeft())/2;
2598 QPointF botMid = (r.bottomRight()+r.bottomLeft())/2;
2599 QPointF leftMid = (r.topLeft()+r.bottomLeft())/2;
2600 QPointF rightMid = (r.topRight()+r.bottomRight())/2;
2602 QPainterPath mappedShape = item->mapToItem(this, item->opaqueArea());
2604 if (mappedShape.contains(topMid) &&
2605 mappedShape.contains(botMid) &&
2606 mappedShape.contains(leftMid) &&
2607 mappedShape.contains(rightMid))
2615 return QGraphicsItem::isObscuredBy(item);
2618 QPainterPath opaqueArea() const
2626 int type() const { return Type; }
2629 void tst_QGraphicsItem::isObscuredBy()
2631 QGraphicsScene scene;
2633 MyItem myitem1, myitem2;
2635 myitem1.setRect(QRectF(50, 50, 40, 200));
2638 myitem2.setRect(QRectF(25, 25, 20, 20));
2639 myitem2.setZValue(-1.0);
2640 scene.addItem(&myitem1);
2641 scene.addItem(&myitem2);
2643 QVERIFY(!myitem2.isObscuredBy(&myitem1));
2644 QVERIFY(!myitem1.isObscuredBy(&myitem2));
2646 myitem2.setRect(QRectF(-50, 85, 20, 20));
2647 QVERIFY(myitem2.isObscuredBy(&myitem1));
2648 QVERIFY(!myitem1.isObscuredBy(&myitem2));
2650 myitem2.setRect(QRectF(-30, 70, 20, 20));
2651 QVERIFY(!myitem2.isObscuredBy(&myitem1));
2652 QVERIFY(!myitem1.isObscuredBy(&myitem2));
2654 QGraphicsRectItem rect1, rect2;
2656 rect1.setRect(QRectF(-40, -40, 50, 50));
2657 rect1.setBrush(QBrush(Qt::red));
2658 rect2.setRect(QRectF(-30, -20, 20, 20));
2659 rect2.setZValue(-1.0);
2660 rect2.setBrush(QBrush(Qt::blue));
2662 QVERIFY(rect2.isObscuredBy(&rect1));
2663 QVERIFY(!rect1.isObscuredBy(&rect2));
2665 rect2.setPos(QPointF(-20, -25));
2667 QVERIFY(!rect2.isObscuredBy(&rect1));
2668 QVERIFY(!rect1.isObscuredBy(&rect2));
2670 rect2.setPos(QPointF(-100, -100));
2672 QVERIFY(!rect2.isObscuredBy(&rect1));
2673 QVERIFY(!rect1.isObscuredBy(&rect2));
2676 class OpaqueItem : public QGraphicsRectItem
2679 QPainterPath opaqueArea() const
2685 void tst_QGraphicsItem::isObscured()
2687 if (sizeof(qreal) != sizeof(double))
2688 QSKIP("Skipped due to rounding errors");
2690 OpaqueItem *item1 = new OpaqueItem;
2691 item1->setRect(0, 0, 100, 100);
2692 item1->setZValue(0);
2694 OpaqueItem *item2 = new OpaqueItem;
2695 item2->setZValue(1);
2696 item2->setRect(0, 0, 100, 100);
2698 QGraphicsScene scene;
2699 scene.addItem(item1);
2700 scene.addItem(item2);
2702 QVERIFY(item1->isObscured());
2703 QVERIFY(item1->isObscuredBy(item2));
2704 QVERIFY(item1->isObscured(QRectF(0, 0, 50, 50)));
2705 QVERIFY(item1->isObscured(QRectF(50, 0, 50, 50)));
2706 QVERIFY(item1->isObscured(QRectF(50, 50, 50, 50)));
2707 QVERIFY(item1->isObscured(QRectF(0, 50, 50, 50)));
2708 QVERIFY(item1->isObscured(0, 0, 50, 50));
2709 QVERIFY(item1->isObscured(50, 0, 50, 50));
2710 QVERIFY(item1->isObscured(50, 50, 50, 50));
2711 QVERIFY(item1->isObscured(0, 50, 50, 50));
2712 QVERIFY(!item2->isObscured());
2713 QVERIFY(!item2->isObscuredBy(item1));
2714 QVERIFY(!item2->isObscured(QRectF(0, 0, 50, 50)));
2715 QVERIFY(!item2->isObscured(QRectF(50, 0, 50, 50)));
2716 QVERIFY(!item2->isObscured(QRectF(50, 50, 50, 50)));
2717 QVERIFY(!item2->isObscured(QRectF(0, 50, 50, 50)));
2718 QVERIFY(!item2->isObscured(0, 0, 50, 50));
2719 QVERIFY(!item2->isObscured(50, 0, 50, 50));
2720 QVERIFY(!item2->isObscured(50, 50, 50, 50));
2721 QVERIFY(!item2->isObscured(0, 50, 50, 50));
2723 item2->moveBy(50, 0);
2725 QVERIFY(!item1->isObscured());
2726 QVERIFY(!item1->isObscuredBy(item2));
2727 QVERIFY(!item1->isObscured(QRectF(0, 0, 50, 50)));
2728 QVERIFY(item1->isObscured(QRectF(50, 0, 50, 50)));
2729 QVERIFY(item1->isObscured(QRectF(50, 50, 50, 50)));
2730 QVERIFY(!item1->isObscured(QRectF(0, 50, 50, 50)));
2731 QVERIFY(!item1->isObscured(0, 0, 50, 50));
2732 QVERIFY(item1->isObscured(50, 0, 50, 50));
2733 QVERIFY(item1->isObscured(50, 50, 50, 50));
2734 QVERIFY(!item1->isObscured(0, 50, 50, 50));
2735 QVERIFY(!item2->isObscured());
2736 QVERIFY(!item2->isObscuredBy(item1));
2737 QVERIFY(!item2->isObscured(QRectF(0, 0, 50, 50)));
2738 QVERIFY(!item2->isObscured(QRectF(50, 0, 50, 50)));
2739 QVERIFY(!item2->isObscured(QRectF(50, 50, 50, 50)));
2740 QVERIFY(!item2->isObscured(QRectF(0, 50, 50, 50)));
2741 QVERIFY(!item2->isObscured(0, 0, 50, 50));
2742 QVERIFY(!item2->isObscured(50, 0, 50, 50));
2743 QVERIFY(!item2->isObscured(50, 50, 50, 50));
2744 QVERIFY(!item2->isObscured(0, 50, 50, 50));
2747 void tst_QGraphicsItem::mapFromToParent()
2750 path1.addRect(0, 0, 200, 200);
2753 path2.addRect(0, 0, 100, 100);
2756 path3.addRect(0, 0, 50, 50);
2759 path4.addRect(0, 0, 25, 25);
2761 QGraphicsItem *item1 = new QGraphicsPathItem(path1);
2762 QGraphicsItem *item2 = new QGraphicsPathItem(path2, item1);
2763 QGraphicsItem *item3 = new QGraphicsPathItem(path3, item2);
2764 QGraphicsItem *item4 = new QGraphicsPathItem(path4, item3);
2766 item1->setPos(10, 10);
2767 item2->setPos(10, 10);
2768 item3->setPos(10, 10);
2769 item4->setPos(10, 10);
2771 for (int i = 0; i < 4; ++i) {
2773 matrix.rotate(i * 90);
2774 matrix.translate(i * 100, -i * 100);
2776 item1->setMatrix(matrix);
2778 QCOMPARE(item1->mapToParent(QPointF(0, 0)), item1->pos() + matrix.map(QPointF(0, 0)));
2779 QCOMPARE(item2->mapToParent(QPointF(0, 0)), item2->pos());
2780 QCOMPARE(item3->mapToParent(QPointF(0, 0)), item3->pos());
2781 QCOMPARE(item4->mapToParent(QPointF(0, 0)), item4->pos());
2782 QCOMPARE(item1->mapToParent(QPointF(10, -10)), item1->pos() + matrix.map(QPointF(10, -10)));
2783 QCOMPARE(item2->mapToParent(QPointF(10, -10)), item2->pos() + QPointF(10, -10));
2784 QCOMPARE(item3->mapToParent(QPointF(10, -10)), item3->pos() + QPointF(10, -10));
2785 QCOMPARE(item4->mapToParent(QPointF(10, -10)), item4->pos() + QPointF(10, -10));
2786 QCOMPARE(item1->mapToParent(QPointF(-10, 10)), item1->pos() + matrix.map(QPointF(-10, 10)));
2787 QCOMPARE(item2->mapToParent(QPointF(-10, 10)), item2->pos() + QPointF(-10, 10));
2788 QCOMPARE(item3->mapToParent(QPointF(-10, 10)), item3->pos() + QPointF(-10, 10));
2789 QCOMPARE(item4->mapToParent(QPointF(-10, 10)), item4->pos() + QPointF(-10, 10));
2790 QCOMPARE(item1->mapFromParent(item1->pos()), matrix.inverted().map(QPointF(0, 0)));
2791 QCOMPARE(item2->mapFromParent(item2->pos()), QPointF(0, 0));
2792 QCOMPARE(item3->mapFromParent(item3->pos()), QPointF(0, 0));
2793 QCOMPARE(item4->mapFromParent(item4->pos()), QPointF(0, 0));
2794 QCOMPARE(item1->mapFromParent(item1->pos() + QPointF(10, -10)),
2795 matrix.inverted().map(QPointF(10, -10)));
2796 QCOMPARE(item2->mapFromParent(item2->pos() + QPointF(10, -10)), QPointF(10, -10));
2797 QCOMPARE(item3->mapFromParent(item3->pos() + QPointF(10, -10)), QPointF(10, -10));
2798 QCOMPARE(item4->mapFromParent(item4->pos() + QPointF(10, -10)), QPointF(10, -10));
2799 QCOMPARE(item1->mapFromParent(item1->pos() + QPointF(-10, 10)),
2800 matrix.inverted().map(QPointF(-10, 10)));
2801 QCOMPARE(item2->mapFromParent(item2->pos() + QPointF(-10, 10)), QPointF(-10, 10));
2802 QCOMPARE(item3->mapFromParent(item3->pos() + QPointF(-10, 10)), QPointF(-10, 10));
2803 QCOMPARE(item4->mapFromParent(item4->pos() + QPointF(-10, 10)), QPointF(-10, 10));
2809 void tst_QGraphicsItem::mapFromToScene()
2811 QGraphicsItem *item1 = new QGraphicsPathItem(QPainterPath());
2812 QGraphicsItem *item2 = new QGraphicsPathItem(QPainterPath(), item1);
2813 QGraphicsItem *item3 = new QGraphicsPathItem(QPainterPath(), item2);
2814 QGraphicsItem *item4 = new QGraphicsPathItem(QPainterPath(), item3);
2816 item1->setPos(100, 100);
2817 item2->setPos(100, 100);
2818 item3->setPos(100, 100);
2819 item4->setPos(100, 100);
2820 QCOMPARE(item1->pos(), QPointF(100, 100));
2821 QCOMPARE(item2->pos(), QPointF(100, 100));
2822 QCOMPARE(item3->pos(), QPointF(100, 100));
2823 QCOMPARE(item4->pos(), QPointF(100, 100));
2824 QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
2825 QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
2826 QCOMPARE(item3->pos(), item3->mapToParent(0, 0));
2827 QCOMPARE(item4->pos(), item4->mapToParent(0, 0));
2828 QCOMPARE(item1->mapToParent(10, 10), QPointF(110, 110));
2829 QCOMPARE(item2->mapToParent(10, 10), QPointF(110, 110));
2830 QCOMPARE(item3->mapToParent(10, 10), QPointF(110, 110));
2831 QCOMPARE(item4->mapToParent(10, 10), QPointF(110, 110));
2832 QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100));
2833 QCOMPARE(item2->mapToScene(0, 0), QPointF(200, 200));
2834 QCOMPARE(item3->mapToScene(0, 0), QPointF(300, 300));
2835 QCOMPARE(item4->mapToScene(0, 0), QPointF(400, 400));
2836 QCOMPARE(item1->mapToScene(10, 0), QPointF(110, 100));
2837 QCOMPARE(item2->mapToScene(10, 0), QPointF(210, 200));
2838 QCOMPARE(item3->mapToScene(10, 0), QPointF(310, 300));
2839 QCOMPARE(item4->mapToScene(10, 0), QPointF(410, 400));
2840 QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0));
2841 QCOMPARE(item2->mapFromScene(200, 200), QPointF(0, 0));
2842 QCOMPARE(item3->mapFromScene(300, 300), QPointF(0, 0));
2843 QCOMPARE(item4->mapFromScene(400, 400), QPointF(0, 0));
2844 QCOMPARE(item1->mapFromScene(110, 100), QPointF(10, 0));
2845 QCOMPARE(item2->mapFromScene(210, 200), QPointF(10, 0));
2846 QCOMPARE(item3->mapFromScene(310, 300), QPointF(10, 0));
2847 QCOMPARE(item4->mapFromScene(410, 400), QPointF(10, 0));
2849 // Rotate item1 90 degrees clockwise
2850 QMatrix matrix; matrix.rotate(90);
2851 item1->setMatrix(matrix);
2852 QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
2853 QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
2854 QCOMPARE(item3->pos(), item3->mapToParent(0, 0));
2855 QCOMPARE(item4->pos(), item4->mapToParent(0, 0));
2856 QCOMPARE(item1->mapToParent(10, 0), QPointF(100, 110));
2857 QCOMPARE(item2->mapToParent(10, 0), QPointF(110, 100));
2858 QCOMPARE(item3->mapToParent(10, 0), QPointF(110, 100));
2859 QCOMPARE(item4->mapToParent(10, 0), QPointF(110, 100));
2860 QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100));
2861 QCOMPARE(item2->mapToScene(0, 0), QPointF(0, 200));
2862 QCOMPARE(item3->mapToScene(0, 0), QPointF(-100, 300));
2863 QCOMPARE(item4->mapToScene(0, 0), QPointF(-200, 400));
2864 QCOMPARE(item1->mapToScene(10, 0), QPointF(100, 110));
2865 QCOMPARE(item2->mapToScene(10, 0), QPointF(0, 210));
2866 QCOMPARE(item3->mapToScene(10, 0), QPointF(-100, 310));
2867 QCOMPARE(item4->mapToScene(10, 0), QPointF(-200, 410));
2868 QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0));
2869 QCOMPARE(item2->mapFromScene(0, 200), QPointF(0, 0));
2870 QCOMPARE(item3->mapFromScene(-100, 300), QPointF(0, 0));
2871 QCOMPARE(item4->mapFromScene(-200, 400), QPointF(0, 0));
2872 QCOMPARE(item1->mapFromScene(100, 110), QPointF(10, 0));
2873 QCOMPARE(item2->mapFromScene(0, 210), QPointF(10, 0));
2874 QCOMPARE(item3->mapFromScene(-100, 310), QPointF(10, 0));
2875 QCOMPARE(item4->mapFromScene(-200, 410), QPointF(10, 0));
2877 // Rotate item2 90 degrees clockwise
2878 item2->setMatrix(matrix);
2879 QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
2880 QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
2881 QCOMPARE(item3->pos(), item3->mapToParent(0, 0));
2882 QCOMPARE(item4->pos(), item4->mapToParent(0, 0));
2883 QCOMPARE(item1->mapToParent(10, 0), QPointF(100, 110));
2884 QCOMPARE(item2->mapToParent(10, 0), QPointF(100, 110));
2885 QCOMPARE(item3->mapToParent(10, 0), QPointF(110, 100));
2886 QCOMPARE(item4->mapToParent(10, 0), QPointF(110, 100));
2887 QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100));
2888 QCOMPARE(item2->mapToScene(0, 0), QPointF(0, 200));
2889 QCOMPARE(item3->mapToScene(0, 0), QPointF(-100, 100));
2890 QCOMPARE(item4->mapToScene(0, 0), QPointF(-200, 0));
2891 QCOMPARE(item1->mapToScene(10, 0), QPointF(100, 110));
2892 QCOMPARE(item2->mapToScene(10, 0), QPointF(-10, 200));
2893 QCOMPARE(item3->mapToScene(10, 0), QPointF(-110, 100));
2894 QCOMPARE(item4->mapToScene(10, 0), QPointF(-210, 0));
2895 QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0));
2896 QCOMPARE(item2->mapFromScene(0, 200), QPointF(0, 0));
2897 QCOMPARE(item3->mapFromScene(-100, 100), QPointF(0, 0));
2898 QCOMPARE(item4->mapFromScene(-200, 0), QPointF(0, 0));
2899 QCOMPARE(item1->mapFromScene(100, 110), QPointF(10, 0));
2900 QCOMPARE(item2->mapFromScene(-10, 200), QPointF(10, 0));
2901 QCOMPARE(item3->mapFromScene(-110, 100), QPointF(10, 0));
2902 QCOMPARE(item4->mapFromScene(-210, 0), QPointF(10, 0));
2904 // Translate item3 50 points, then rotate 90 degrees counterclockwise
2906 matrix2.translate(50, 0);
2907 matrix2.rotate(-90);
2908 item3->setMatrix(matrix2);
2909 QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
2910 QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
2911 QCOMPARE(item3->pos(), item3->mapToParent(0, 0) - QPointF(50, 0));
2912 QCOMPARE(item4->pos(), item4->mapToParent(0, 0));
2913 QCOMPARE(item1->mapToParent(10, 0), QPointF(100, 110));
2914 QCOMPARE(item2->mapToParent(10, 0), QPointF(100, 110));
2915 QCOMPARE(item3->mapToParent(10, 0), QPointF(150, 90));
2916 QCOMPARE(item4->mapToParent(10, 0), QPointF(110, 100));
2917 QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100));
2918 QCOMPARE(item2->mapToScene(0, 0), QPointF(0, 200));
2919 QCOMPARE(item3->mapToScene(0, 0), QPointF(-150, 100));
2920 QCOMPARE(item4->mapToScene(0, 0), QPointF(-250, 200));
2921 QCOMPARE(item1->mapToScene(10, 0), QPointF(100, 110));
2922 QCOMPARE(item2->mapToScene(10, 0), QPointF(-10, 200));
2923 QCOMPARE(item3->mapToScene(10, 0), QPointF(-150, 110));
2924 QCOMPARE(item4->mapToScene(10, 0), QPointF(-250, 210));
2925 QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0));
2926 QCOMPARE(item2->mapFromScene(0, 200), QPointF(0, 0));
2927 QCOMPARE(item3->mapFromScene(-150, 100), QPointF(0, 0));
2928 QCOMPARE(item4->mapFromScene(-250, 200), QPointF(0, 0));
2929 QCOMPARE(item1->mapFromScene(100, 110), QPointF(10, 0));
2930 QCOMPARE(item2->mapFromScene(-10, 200), QPointF(10, 0));
2931 QCOMPARE(item3->mapFromScene(-150, 110), QPointF(10, 0));
2932 QCOMPARE(item4->mapFromScene(-250, 210), QPointF(10, 0));
2937 void tst_QGraphicsItem::mapFromToItem()
2939 QGraphicsItem *item1 = new QGraphicsPathItem;
2940 QGraphicsItem *item2 = new QGraphicsPathItem;
2941 QGraphicsItem *item3 = new QGraphicsPathItem;
2942 QGraphicsItem *item4 = new QGraphicsPathItem;
2944 item1->setPos(-100, -100);
2945 item2->setPos(100, -100);
2946 item3->setPos(100, 100);
2947 item4->setPos(-100, 100);
2949 QCOMPARE(item1->mapFromItem(item2, 0, 0), QPointF(200, 0));
2950 QCOMPARE(item2->mapFromItem(item3, 0, 0), QPointF(0, 200));
2951 QCOMPARE(item3->mapFromItem(item4, 0, 0), QPointF(-200, 0));
2952 QCOMPARE(item4->mapFromItem(item1, 0, 0), QPointF(0, -200));
2953 QCOMPARE(item1->mapFromItem(item4, 0, 0), QPointF(0, 200));
2954 QCOMPARE(item2->mapFromItem(item1, 0, 0), QPointF(-200, 0));
2955 QCOMPARE(item3->mapFromItem(item2, 0, 0), QPointF(0, -200));
2956 QCOMPARE(item4->mapFromItem(item3, 0, 0), QPointF(200, 0));
2959 matrix.translate(100, 100);
2960 item1->setMatrix(matrix);
2962 QCOMPARE(item1->mapFromItem(item2, 0, 0), QPointF(100, -100));
2963 QCOMPARE(item2->mapFromItem(item3, 0, 0), QPointF(0, 200));
2964 QCOMPARE(item3->mapFromItem(item4, 0, 0), QPointF(-200, 0));
2965 QCOMPARE(item4->mapFromItem(item1, 0, 0), QPointF(100, -100));
2966 QCOMPARE(item1->mapFromItem(item4, 0, 0), QPointF(-100, 100));
2967 QCOMPARE(item2->mapFromItem(item1, 0, 0), QPointF(-100, 100));
2968 QCOMPARE(item3->mapFromItem(item2, 0, 0), QPointF(0, -200));
2969 QCOMPARE(item4->mapFromItem(item3, 0, 0), QPointF(200, 0));
2972 item1->setMatrix(matrix);
2973 item2->setMatrix(matrix);
2974 item3->setMatrix(matrix);
2975 item4->setMatrix(matrix);
2977 QCOMPARE(item1->mapFromItem(item2, 0, 0), QPointF(0, -200));
2978 QCOMPARE(item2->mapFromItem(item3, 0, 0), QPointF(200, 0));
2979 QCOMPARE(item3->mapFromItem(item4, 0, 0), QPointF(0, 200));
2980 QCOMPARE(item4->mapFromItem(item1, 0, 0), QPointF(-200, 0));
2981 QCOMPARE(item1->mapFromItem(item4, 0, 0), QPointF(200, 0));
2982 QCOMPARE(item2->mapFromItem(item1, 0, 0), QPointF(0, 200));
2983 QCOMPARE(item3->mapFromItem(item2, 0, 0), QPointF(-200, 0));
2984 QCOMPARE(item4->mapFromItem(item3, 0, 0), QPointF(0, -200));
2985 QCOMPARE(item1->mapFromItem(item2, 10, -5), QPointF(10, -205));
2986 QCOMPARE(item2->mapFromItem(item3, 10, -5), QPointF(210, -5));
2987 QCOMPARE(item3->mapFromItem(item4, 10, -5), QPointF(10, 195));
2988 QCOMPARE(item4->mapFromItem(item1, 10, -5), QPointF(-190, -5));
2989 QCOMPARE(item1->mapFromItem(item4, 10, -5), QPointF(210, -5));
2990 QCOMPARE(item2->mapFromItem(item1, 10, -5), QPointF(10, 195));
2991 QCOMPARE(item3->mapFromItem(item2, 10, -5), QPointF(-190, -5));
2992 QCOMPARE(item4->mapFromItem(item3, 10, -5), QPointF(10, -205));
2994 QCOMPARE(item1->mapFromItem(0, 10, -5), item1->mapFromScene(10, -5));
2995 QCOMPARE(item2->mapFromItem(0, 10, -5), item2->mapFromScene(10, -5));
2996 QCOMPARE(item3->mapFromItem(0, 10, -5), item3->mapFromScene(10, -5));
2997 QCOMPARE(item4->mapFromItem(0, 10, -5), item4->mapFromScene(10, -5));
2998 QCOMPARE(item1->mapToItem(0, 10, -5), item1->mapToScene(10, -5));
2999 QCOMPARE(item2->mapToItem(0, 10, -5), item2->mapToScene(10, -5));
3000 QCOMPARE(item3->mapToItem(0, 10, -5), item3->mapToScene(10, -5));
3001 QCOMPARE(item4->mapToItem(0, 10, -5), item4->mapToScene(10, -5));
3009 void tst_QGraphicsItem::mapRectFromToParent_data()
3011 QTest::addColumn<bool>("parent");
3012 QTest::addColumn<QPointF>("parentPos");
3013 QTest::addColumn<QTransform>("parentTransform");
3014 QTest::addColumn<QPointF>("pos");
3015 QTest::addColumn<QTransform>("transform");
3016 QTest::addColumn<QRectF>("inputRect");
3017 QTest::addColumn<QRectF>("outputRect");
3019 QTest::newRow("nil") << false << QPointF() << QTransform() << QPointF() << QTransform() << QRectF() << QRectF();
3020 QTest::newRow("simple") << false << QPointF() << QTransform() << QPointF() << QTransform()
3021 << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10);
3022 QTest::newRow("simple w/parent") << true
3023 << QPointF() << QTransform()
3024 << QPointF() << QTransform()
3025 << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10);
3026 QTest::newRow("simple w/parent parentPos") << true
3027 << QPointF(50, 50) << QTransform()
3028 << QPointF() << QTransform()
3029 << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10);
3030 QTest::newRow("simple w/parent parentPos parentRotation") << true
3031 << QPointF(50, 50) << QTransform().rotate(45)
3032 << QPointF() << QTransform()
3033 << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10);
3034 QTest::newRow("pos w/parent") << true
3035 << QPointF() << QTransform()
3036 << QPointF(50, 50) << QTransform()
3037 << QRectF(0, 0, 10, 10) << QRectF(50, 50, 10, 10);
3038 QTest::newRow("rotation w/parent") << true
3039 << QPointF() << QTransform()
3040 << QPointF() << QTransform().rotate(90)
3041 << QRectF(0, 0, 10, 10) << QRectF(-10, 0, 10, 10);
3042 QTest::newRow("pos rotation w/parent") << true
3043 << QPointF() << QTransform()
3044 << QPointF(50, 50) << QTransform().rotate(90)
3045 << QRectF(0, 0, 10, 10) << QRectF(40, 50, 10, 10);
3046 QTest::newRow("pos rotation w/parent parentPos parentRotation") << true
3047 << QPointF(-170, -190) << QTransform().rotate(90)
3048 << QPointF(50, 50) << QTransform().rotate(90)
3049 << QRectF(0, 0, 10, 10) << QRectF(40, 50, 10, 10);
3052 void tst_QGraphicsItem::mapRectFromToParent()
3054 QFETCH(bool, parent);
3055 QFETCH(QPointF, parentPos);
3056 QFETCH(QTransform, parentTransform);
3057 QFETCH(QPointF, pos);
3058 QFETCH(QTransform, transform);
3059 QFETCH(QRectF, inputRect);
3060 QFETCH(QRectF, outputRect);
3062 QGraphicsRectItem *rect = new QGraphicsRectItem;
3064 rect->setTransform(transform);
3067 QGraphicsRectItem *rectParent = new QGraphicsRectItem;
3068 rect->setParentItem(rectParent);
3069 rectParent->setPos(parentPos);
3070 rectParent->setTransform(parentTransform);
3073 // Make sure we use non-destructive transform operations (e.g., 90 degree
3075 QCOMPARE(rect->mapRectToParent(inputRect), outputRect);
3076 QCOMPARE(rect->mapRectFromParent(outputRect), inputRect);
3077 QCOMPARE(rect->itemTransform(rect->parentItem()).mapRect(inputRect), outputRect);
3078 QCOMPARE(rect->mapToParent(inputRect).boundingRect(), outputRect);
3079 QCOMPARE(rect->mapToParent(QPolygonF(inputRect)).boundingRect(), outputRect);
3080 QCOMPARE(rect->mapFromParent(outputRect).boundingRect(), inputRect);
3081 QCOMPARE(rect->mapFromParent(QPolygonF(outputRect)).boundingRect(), inputRect);
3082 QPainterPath inputPath;
3083 inputPath.addRect(inputRect);
3084 QPainterPath outputPath;
3085 outputPath.addRect(outputRect);
3086 QCOMPARE(rect->mapToParent(inputPath).boundingRect(), outputPath.boundingRect());
3087 QCOMPARE(rect->mapFromParent(outputPath).boundingRect(), inputPath.boundingRect());
3090 void tst_QGraphicsItem::isAncestorOf()
3092 QGraphicsItem *grandPa = new QGraphicsRectItem;
3093 QGraphicsItem *parent = new QGraphicsRectItem;
3094 QGraphicsItem *child = new QGraphicsRectItem;
3096 QVERIFY(!parent->isAncestorOf(0));
3097 QVERIFY(!child->isAncestorOf(0));
3098 QVERIFY(!parent->isAncestorOf(child));
3099 QVERIFY(!child->isAncestorOf(parent));
3100 QVERIFY(!parent->isAncestorOf(parent));
3102 child->setParentItem(parent);
3103 parent->setParentItem(grandPa);
3105 QVERIFY(parent->isAncestorOf(child));
3106 QVERIFY(grandPa->isAncestorOf(parent));
3107 QVERIFY(grandPa->isAncestorOf(child));
3108 QVERIFY(!child->isAncestorOf(parent));
3109 QVERIFY(!parent->isAncestorOf(grandPa));
3110 QVERIFY(!child->isAncestorOf(grandPa));
3111 QVERIFY(!child->isAncestorOf(child));
3112 QVERIFY(!parent->isAncestorOf(parent));
3113 QVERIFY(!grandPa->isAncestorOf(grandPa));
3115 parent->setParentItem(0);
3122 void tst_QGraphicsItem::commonAncestorItem()
3124 QGraphicsItem *ancestor = new QGraphicsRectItem;
3125 QGraphicsItem *grandMa = new QGraphicsRectItem;
3126 QGraphicsItem *grandPa = new QGraphicsRectItem;
3127 QGraphicsItem *brotherInLaw = new QGraphicsRectItem;
3128 QGraphicsItem *cousin = new QGraphicsRectItem;
3129 QGraphicsItem *husband = new QGraphicsRectItem;
3130 QGraphicsItem *child = new QGraphicsRectItem;
3131 QGraphicsItem *wife = new QGraphicsRectItem;
3133 child->setParentItem(husband);
3134 husband->setParentItem(grandPa);
3135 brotherInLaw->setParentItem(grandPa);
3136 cousin->setParentItem(brotherInLaw);
3137 wife->setParentItem(grandMa);
3138 grandMa->setParentItem(ancestor);
3139 grandPa->setParentItem(ancestor);
3141 QCOMPARE(grandMa->commonAncestorItem(grandMa), grandMa);
3142 QCOMPARE(grandMa->commonAncestorItem(0), (QGraphicsItem *)0);
3143 QCOMPARE(grandMa->commonAncestorItem(grandPa), ancestor);
3144 QCOMPARE(grandPa->commonAncestorItem(grandMa), ancestor);
3145 QCOMPARE(grandPa->commonAncestorItem(husband), grandPa);
3146 QCOMPARE(grandPa->commonAncestorItem(wife), ancestor);
3147 QCOMPARE(grandMa->commonAncestorItem(husband), ancestor);
3148 QCOMPARE(grandMa->commonAncestorItem(wife), grandMa);
3149 QCOMPARE(wife->commonAncestorItem(grandMa), grandMa);
3150 QCOMPARE(child->commonAncestorItem(cousin), grandPa);
3151 QCOMPARE(cousin->commonAncestorItem(child), grandPa);
3152 QCOMPARE(wife->commonAncestorItem(child), ancestor);
3153 QCOMPARE(child->commonAncestorItem(wife), ancestor);
3156 void tst_QGraphicsItem::data()
3158 QGraphicsTextItem text;
3160 QCOMPARE(text.data(0), QVariant());
3161 text.setData(0, "TextItem");
3162 QCOMPARE(text.data(0), QVariant(QString("TextItem")));
3163 text.setData(0, QVariant());
3164 QCOMPARE(text.data(0), QVariant());
3167 void tst_QGraphicsItem::type()
3169 QCOMPARE(int(QGraphicsItem::Type), 1);
3170 QCOMPARE(int(QGraphicsPathItem::Type), 2);
3171 QCOMPARE(int(QGraphicsRectItem::Type), 3);
3172 QCOMPARE(int(QGraphicsEllipseItem::Type), 4);
3173 QCOMPARE(int(QGraphicsPolygonItem::Type), 5);
3174 QCOMPARE(int(QGraphicsLineItem::Type), 6);
3175 QCOMPARE(int(QGraphicsPixmapItem::Type), 7);
3176 QCOMPARE(int(QGraphicsTextItem::Type), 8);
3178 QCOMPARE(QGraphicsPathItem().type(), 2);
3179 QCOMPARE(QGraphicsRectItem().type(), 3);
3180 QCOMPARE(QGraphicsEllipseItem().type(), 4);
3181 QCOMPARE(QGraphicsPolygonItem().type(), 5);
3182 QCOMPARE(QGraphicsLineItem().type(), 6);
3183 QCOMPARE(QGraphicsPixmapItem().type(), 7);
3184 QCOMPARE(QGraphicsTextItem().type(), 8);
3187 void tst_QGraphicsItem::graphicsitem_cast()
3189 QGraphicsPathItem pathItem;
3190 const QGraphicsPathItem *pPathItem = &pathItem;
3191 QGraphicsRectItem rectItem;
3192 const QGraphicsRectItem *pRectItem = &rectItem;
3193 QGraphicsEllipseItem ellipseItem;
3194 const QGraphicsEllipseItem *pEllipseItem = &ellipseItem;
3195 QGraphicsPolygonItem polygonItem;
3196 const QGraphicsPolygonItem *pPolygonItem = &polygonItem;
3197 QGraphicsLineItem lineItem;
3198 const QGraphicsLineItem *pLineItem = &lineItem;
3199 QGraphicsPixmapItem pixmapItem;
3200 const QGraphicsPixmapItem *pPixmapItem = &pixmapItem;
3201 QGraphicsTextItem textItem;
3202 const QGraphicsTextItem *pTextItem = &textItem;
3204 QVERIFY(qgraphicsitem_cast<QGraphicsPathItem *>(&pathItem));
3205 //QVERIFY(qgraphicsitem_cast<QAbstractGraphicsPathItem *>(&pathItem));
3206 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&pathItem));
3207 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pPathItem));
3208 QVERIFY(qgraphicsitem_cast<const QGraphicsPathItem *>(pPathItem));
3210 QVERIFY(qgraphicsitem_cast<QGraphicsRectItem *>(&rectItem));
3211 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&rectItem));
3212 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pRectItem));
3213 QVERIFY(qgraphicsitem_cast<const QGraphicsRectItem *>(pRectItem));
3215 QVERIFY(qgraphicsitem_cast<QGraphicsEllipseItem *>(&ellipseItem));
3216 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&ellipseItem));
3217 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pEllipseItem));
3218 QVERIFY(qgraphicsitem_cast<const QGraphicsEllipseItem *>(pEllipseItem));
3220 QVERIFY(qgraphicsitem_cast<QGraphicsPolygonItem *>(&polygonItem));
3221 //QVERIFY(qgraphicsitem_cast<QAbstractGraphicsPathItem *>(&polygonItem));
3222 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&polygonItem));
3223 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pPolygonItem));
3224 QVERIFY(qgraphicsitem_cast<const QGraphicsPolygonItem *>(pPolygonItem));
3226 QVERIFY(qgraphicsitem_cast<QGraphicsLineItem *>(&lineItem));
3227 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&lineItem));
3228 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pLineItem));
3229 QVERIFY(qgraphicsitem_cast<const QGraphicsLineItem *>(pLineItem));
3231 QVERIFY(qgraphicsitem_cast<QGraphicsPixmapItem *>(&pixmapItem));
3232 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&pixmapItem));
3233 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pPixmapItem));
3234 QVERIFY(qgraphicsitem_cast<const QGraphicsPixmapItem *>(pPixmapItem));
3236 QVERIFY(qgraphicsitem_cast<QGraphicsTextItem *>(&textItem));
3237 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&textItem));
3238 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pTextItem));
3239 QVERIFY(qgraphicsitem_cast<const QGraphicsTextItem *>(pTextItem));
3241 // and some casts that _should_ fail:
3242 QVERIFY(!qgraphicsitem_cast<QGraphicsEllipseItem *>(&pathItem));
3243 QVERIFY(!qgraphicsitem_cast<const QGraphicsTextItem *>(pPolygonItem));
3245 // and this shouldn't crash
3246 QGraphicsItem *ptr = 0;
3247 QVERIFY(!qgraphicsitem_cast<QGraphicsTextItem *>(ptr));
3248 QVERIFY(!qgraphicsitem_cast<QGraphicsItem *>(ptr));
3251 void tst_QGraphicsItem::hoverEventsGenerateRepaints()
3255 QGraphicsScene scene;
3256 QGraphicsView view(&scene);
3258 QVERIFY(QTest::qWaitForWindowActive(&view));
3260 EventTester *tester = new EventTester;
3261 scene.addItem(tester);
3262 tester->setAcceptsHoverEvents(true);
3264 QTRY_COMPARE(tester->repaints, 1);
3266 // Send a hover enter event
3267 QGraphicsSceneHoverEvent hoverEnterEvent(QEvent::GraphicsSceneHoverEnter);
3268 hoverEnterEvent.setScenePos(QPointF(0, 0));
3269 hoverEnterEvent.setPos(QPointF(0, 0));
3270 QApplication::sendEvent(&scene, &hoverEnterEvent);
3272 // Check that we get a repaint
3273 int npaints = tester->repaints;
3274 qApp->processEvents();
3275 qApp->processEvents();
3276 QCOMPARE(tester->events.size(), 2); // enter + move
3277 QCOMPARE(tester->repaints, npaints + 1);
3278 QCOMPARE(tester->events.last(), QEvent::GraphicsSceneHoverMove);
3280 // Send a hover move event
3281 QGraphicsSceneHoverEvent hoverMoveEvent(QEvent::GraphicsSceneHoverMove);
3282 hoverMoveEvent.setScenePos(QPointF(0, 0));
3283 hoverMoveEvent.setPos(QPointF(0, 0));
3284 QApplication::sendEvent(&scene, &hoverMoveEvent);
3286 // Check that we don't get a repaint
3287 qApp->processEvents();
3288 qApp->processEvents();
3290 QCOMPARE(tester->events.size(), 3);
3291 QCOMPARE(tester->repaints, npaints + 1);
3292 QCOMPARE(tester->events.last(), QEvent::GraphicsSceneHoverMove);
3294 // Send a hover leave event
3295 QGraphicsSceneHoverEvent hoverLeaveEvent(QEvent::GraphicsSceneHoverLeave);
3296 hoverLeaveEvent.setScenePos(QPointF(-100, -100));
3297 hoverLeaveEvent.setPos(QPointF(0, 0));
3298 QApplication::sendEvent(&scene, &hoverLeaveEvent);
3300 // Check that we get a repaint
3301 qApp->processEvents();
3302 qApp->processEvents();
3304 QCOMPARE(tester->events.size(), 4);
3305 QCOMPARE(tester->repaints, npaints + 2);
3306 QCOMPARE(tester->events.last(), QEvent::GraphicsSceneHoverLeave);
3309 void tst_QGraphicsItem::boundingRects_data()
3311 QTest::addColumn<QGraphicsItem *>("item");
3312 QTest::addColumn<QRectF>("boundingRect");
3314 QRectF rect(0, 0, 100, 100);
3318 QRectF adjustedRect(-0.5, -0.5, 101, 101);
3320 QTest::newRow("path") << (QGraphicsItem *)new QGraphicsPathItem(path) << adjustedRect;
3321 QTest::newRow("rect") << (QGraphicsItem *)new QGraphicsRectItem(rect) << adjustedRect;
3322 QTest::newRow("ellipse") << (QGraphicsItem *)new QGraphicsEllipseItem(rect) << adjustedRect;
3323 QTest::newRow("polygon") << (QGraphicsItem *)new QGraphicsPolygonItem(rect) << adjustedRect;
3326 void tst_QGraphicsItem::boundingRects()
3328 QFETCH(QGraphicsItem *, item);
3329 QFETCH(QRectF, boundingRect);
3331 ((QAbstractGraphicsShapeItem *)item)->setPen(QPen(Qt::black, 1));
3332 QCOMPARE(item->boundingRect(), boundingRect);
3335 void tst_QGraphicsItem::boundingRects2()
3337 QGraphicsPixmapItem pixmap(QPixmap::fromImage(QImage(100, 100, QImage::Format_ARGB32_Premultiplied)));
3338 QCOMPARE(pixmap.boundingRect(), QRectF(0, 0, 100, 100));
3340 QGraphicsLineItem line(0, 0, 100, 0);
3341 line.setPen(QPen(Qt::black, 1));
3342 QCOMPARE(line.boundingRect(), QRectF(-0.5, -0.5, 101, 1));
3345 void tst_QGraphicsItem::sceneBoundingRect()
3347 QGraphicsScene scene;
3348 QGraphicsRectItem *item = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
3349 item->setPos(100, 100);
3351 QCOMPARE(item->boundingRect(), QRectF(0, 0, 100, 100));
3352 QCOMPARE(item->sceneBoundingRect(), QRectF(100, 100, 100, 100));
3356 QCOMPARE(item->boundingRect(), QRectF(0, 0, 100, 100));
3357 QCOMPARE(item->sceneBoundingRect(), QRectF(0, 100, 100, 100));
3360 void tst_QGraphicsItem::childrenBoundingRect()
3362 QGraphicsScene scene;
3363 QGraphicsRectItem *parent = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
3364 QGraphicsRectItem *child = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
3365 child->setParentItem(parent);
3366 parent->setPos(100, 100);
3367 child->setPos(100, 100);
3369 QCOMPARE(parent->boundingRect(), QRectF(0, 0, 100, 100));
3370 QCOMPARE(child->boundingRect(), QRectF(0, 0, 100, 100));
3371 QCOMPARE(child->childrenBoundingRect(), QRectF());
3372 QCOMPARE(parent->childrenBoundingRect(), QRectF(100, 100, 100, 100));
3374 QGraphicsRectItem *child2 = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
3375 child2->setParentItem(parent);
3376 child2->setPos(-100, -100);
3377 QCOMPARE(parent->childrenBoundingRect(), QRectF(-100, -100, 300, 300));
3379 QGraphicsRectItem *childChild = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
3380 childChild->setParentItem(child);
3381 childChild->setPos(500, 500);
3384 scene.addPolygon(parent->mapToScene(parent->boundingRect() | parent->childrenBoundingRect()))->setPen(QPen(Qt::red));;
3386 QGraphicsView view(&scene);
3389 QVERIFY(QTest::qWaitForWindowExposed(&view));
3392 QCOMPARE(parent->childrenBoundingRect(), QRectF(-500, -100, 600, 800));
3395 void tst_QGraphicsItem::childrenBoundingRectTransformed()
3397 QGraphicsScene scene;
3399 QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100));
3400 QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 100, 100));
3401 QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 100, 100));
3402 QGraphicsRectItem *rect4 = scene.addRect(QRectF(0, 0, 100, 100));
3403 QGraphicsRectItem *rect5 = scene.addRect(QRectF(0, 0, 100, 100));
3404 rect2->setParentItem(rect);
3405 rect3->setParentItem(rect2);
3406 rect4->setParentItem(rect3);
3407 rect5->setParentItem(rect4);
3409 rect->setPen(QPen(Qt::black, 0));
3410 rect2->setPen(QPen(Qt::black, 0));
3411 rect3->setPen(QPen(Qt::black, 0));
3412 rect4->setPen(QPen(Qt::black, 0));
3413 rect5->setPen(QPen(Qt::black, 0));
3415 rect2->setTransform(QTransform().translate(50, 50).rotate(45));
3416 rect2->setPos(25, 25);
3417 rect3->setTransform(QTransform().translate(50, 50).rotate(45));
3418 rect3->setPos(25, 25);
3419 rect4->setTransform(QTransform().translate(50, 50).rotate(45));
3420 rect4->setPos(25, 25);
3421 rect5->setTransform(QTransform().translate(50, 50).rotate(45));
3422 rect5->setPos(25, 25);
3424 QRectF subTreeRect = rect->childrenBoundingRect();
3425 QCOMPARE(subTreeRect.left(), qreal(-206.0660171779821));
3426 QCOMPARE(subTreeRect.top(), qreal(75.0));
3427 QCOMPARE(subTreeRect.width(), qreal(351.7766952966369));
3428 QCOMPARE(subTreeRect.height(), qreal(251.7766952966369));
3436 subTreeRect = rect->childrenBoundingRect();
3437 QCOMPARE(rect->childrenBoundingRect(), QRectF(-100, 75, 275, 250));
3440 void tst_QGraphicsItem::childrenBoundingRect2()
3442 QGraphicsItemGroup box;
3443 QGraphicsLineItem l1(0, 0, 100, 0, &box);
3444 QGraphicsLineItem l2(100, 0, 100, 100, &box);
3445 QGraphicsLineItem l3(0, 0, 0, 100, &box);
3446 // Make sure lines (zero with/height) are included in the childrenBoundingRect.
3447 l1.setPen(QPen(Qt::black, 0));
3448 l2.setPen(QPen(Qt::black, 0));
3449 l3.setPen(QPen(Qt::black, 0));
3450 QCOMPARE(box.childrenBoundingRect(), QRectF(0, 0, 100, 100));
3453 void tst_QGraphicsItem::childrenBoundingRect3()
3455 QGraphicsScene scene;
3457 QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100));
3458 QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 100, 100));
3459 QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 100, 100));
3460 QGraphicsRectItem *rect4 = scene.addRect(QRectF(0, 0, 100, 100));
3461 QGraphicsRectItem *rect5 = scene.addRect(QRectF(0, 0, 100, 100));
3462 rect2->setParentItem(rect);
3463 rect3->setParentItem(rect2);
3464 rect4->setParentItem(rect3);
3465 rect5->setParentItem(rect4);
3467 rect->setPen(QPen(Qt::black, 0));
3468 rect2->setPen(QPen(Qt::black, 0));
3469 rect3->setPen(QPen(Qt::black, 0));
3470 rect4->setPen(QPen(Qt::black, 0));
3471 rect5->setPen(QPen(Qt::black, 0));
3473 rect2->setTransform(QTransform().translate(50, 50).rotate(45));
3474 rect2->setPos(25, 25);
3475 rect3->setTransform(QTransform().translate(50, 50).rotate(45));
3476 rect3->setPos(25, 25);
3477 rect4->setTransform(QTransform().translate(50, 50).rotate(45));
3478 rect4->setPos(25, 25);
3479 rect5->setTransform(QTransform().translate(50, 50).rotate(45));
3480 rect5->setPos(25, 25);
3482 // Try to mess up the cached bounding rect.
3483 (void)rect2->childrenBoundingRect();
3485 QRectF subTreeRect = rect->childrenBoundingRect();
3486 QCOMPARE(subTreeRect.left(), qreal(-206.0660171779821));
3487 QCOMPARE(subTreeRect.top(), qreal(75.0));
3488 QCOMPARE(subTreeRect.width(), qreal(351.7766952966369));
3489 QCOMPARE(subTreeRect.height(), qreal(251.7766952966369));
3492 void tst_QGraphicsItem::childrenBoundingRect4()
3494 QGraphicsScene scene;
3496 QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 10, 10));
3497 QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 20, 20));
3498 QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 30, 30));
3499 rect2->setParentItem(rect);
3500 rect3->setParentItem(rect);
3502 QGraphicsView view(&scene);
3505 QVERIFY(QTest::qWaitForWindowExposed(&view));
3507 // Try to mess up the cached bounding rect.
3508 rect->childrenBoundingRect();
3509 rect2->childrenBoundingRect();
3511 rect3->setOpacity(0.0);
3512 rect3->setParentItem(rect2);
3514 QCOMPARE(rect->childrenBoundingRect(), rect3->boundingRect());
3515 QCOMPARE(rect2->childrenBoundingRect(), rect3->boundingRect());
3518 void tst_QGraphicsItem::childrenBoundingRect5()
3520 QGraphicsScene scene;
3522 QGraphicsRectItem *parent = scene.addRect(QRectF(0, 0, 100, 100));
3523 QGraphicsRectItem *child = scene.addRect(QRectF(0, 0, 100, 100));
3524 child->setParentItem(parent);
3526 parent->setPen(QPen(Qt::black, 0));
3527 child->setPen(QPen(Qt::black, 0));
3529 QGraphicsView view(&scene);
3532 QVERIFY(QTest::qWaitForWindowExposed(&view));
3534 // Try to mess up the cached bounding rect.
3535 QRectF expectedChildrenBoundingRect = parent->boundingRect();
3536 QCOMPARE(parent->childrenBoundingRect(), expectedChildrenBoundingRect);
3538 // Apply some effects.
3539 QGraphicsDropShadowEffect *dropShadow = new QGraphicsDropShadowEffect;
3540 dropShadow->setOffset(25, 25);
3541 child->setGraphicsEffect(dropShadow);
3542 parent->setGraphicsEffect(new QGraphicsOpacityEffect);
3544 QVERIFY(parent->childrenBoundingRect() != expectedChildrenBoundingRect);
3545 expectedChildrenBoundingRect |= dropShadow->boundingRect();
3546 QCOMPARE(parent->childrenBoundingRect(), expectedChildrenBoundingRect);
3549 void tst_QGraphicsItem::group()
3551 QGraphicsScene scene;
3552 QGraphicsRectItem *parent = scene.addRect(QRectF(0, 0, 50, 50), QPen(Qt::black, 0), QBrush(Qt::green));
3553 QGraphicsRectItem *child = scene.addRect(QRectF(0, 0, 50, 50), QPen(Qt::black, 0), QBrush(Qt::blue));
3554 QGraphicsRectItem *parent2 = scene.addRect(QRectF(0, 0, 50, 50), QPen(Qt::black, 0), QBrush(Qt::red));
3555 parent2->setPos(-50, 50);
3557 child->setParentItem(parent);
3558 parent->setPos(25, 25);
3559 child->setPos(25, 25);
3561 QCOMPARE(parent->group(), (QGraphicsItemGroup *)0);
3562 QCOMPARE(parent2->group(), (QGraphicsItemGroup *)0);
3563 QCOMPARE(child->group(), (QGraphicsItemGroup *)0);
3565 QGraphicsView view(&scene);
3567 QVERIFY(QTest::qWaitForWindowExposed(&view));
3569 QGraphicsItemGroup *group = new QGraphicsItemGroup;
3570 group->setSelected(true);
3571 scene.addItem(group);
3573 QRectF parentSceneBoundingRect = parent->sceneBoundingRect();
3574 group->addToGroup(parent);
3575 QCOMPARE(parent->group(), group);
3576 QCOMPARE(parent->sceneBoundingRect(), parentSceneBoundingRect);
3578 QCOMPARE(parent->parentItem(), (QGraphicsItem *)group);
3579 QCOMPARE(group->children().size(), 1);
3580 QCOMPARE(scene.items().size(), 4);
3581 QCOMPARE(scene.items(group->sceneBoundingRect()).size(), 3);
3585 QRectF parent2SceneBoundingRect = parent2->sceneBoundingRect();
3586 group->addToGroup(parent2);
3587 QCOMPARE(parent2->group(), group);
3588 QCOMPARE(parent2->sceneBoundingRect(), parent2SceneBoundingRect);
3590 QCOMPARE(parent2->parentItem(), (QGraphicsItem *)group);
3591 QCOMPARE(group->children().size(), 2);
3592 QCOMPARE(scene.items().size(), 4);
3593 QCOMPARE(scene.items(group->sceneBoundingRect()).size(), 4);
3597 QList<QGraphicsItem *> newItems;
3598 for (int i = 0; i < 100; ++i) {
3599 QGraphicsItem *item = scene.addRect(QRectF(-25, -25, 50, 50), QPen(Qt::black, 0),
3600 QBrush(QColor(rand() % 255, rand() % 255,
3601 rand() % 255, rand() % 255)));
3603 item->setPos(-1000 + rand() % 2000,
3604 -1000 + rand() % 2000);
3605 item->rotate(rand() % 90);
3608 view.fitInView(scene.itemsBoundingRect());
3611 foreach (QGraphicsItem *item, newItems) {
3612 group->addToGroup(item);
3613 QCOMPARE(item->group(), group);
3614 if ((n++ % 100) == 0)
3619 void tst_QGraphicsItem::setGroup()
3621 QGraphicsItemGroup group1;
3622 QGraphicsItemGroup group2;
3624 QGraphicsRectItem *rect = new QGraphicsRectItem;
3625 QCOMPARE(rect->group(), (QGraphicsItemGroup *)0);
3626 QCOMPARE(rect->parentItem(), (QGraphicsItem *)0);
3627 rect->setGroup(&group1);
3628 QCOMPARE(rect->group(), &group1);
3629 QCOMPARE(rect->parentItem(), (QGraphicsItem *)&group1);
3630 rect->setGroup(&group2);
3631 QCOMPARE(rect->group(), &group2);
3632 QCOMPARE(rect->parentItem(), (QGraphicsItem *)&group2);
3634 QCOMPARE(rect->group(), (QGraphicsItemGroup *)0);
3635 QCOMPARE(rect->parentItem(), (QGraphicsItem *)0);
3638 void tst_QGraphicsItem::setGroup2()
3640 QGraphicsScene scene;
3641 QGraphicsItemGroup group;
3642 scene.addItem(&group);
3644 QGraphicsRectItem *rect = scene.addRect(50,50,50,50,Qt::NoPen,Qt::black);
3645 rect->setTransformOriginPoint(50,50);
3646 rect->setRotation(45);
3647 rect->setScale(1.5);
3648 rect->translate(20,20);
3649 group.translate(-30,-40);
3650 group.setRotation(180);
3651 group.setScale(0.5);
3653 QTransform oldSceneTransform = rect->sceneTransform();
3654 rect->setGroup(&group);
3655 QCOMPARE(rect->sceneTransform(), oldSceneTransform);
3657 group.setRotation(20);
3659 rect->setRotation(90);
3660 rect->setScale(0.8);
3662 oldSceneTransform = rect->sceneTransform();
3664 QCOMPARE(rect->sceneTransform(), oldSceneTransform);
3667 void tst_QGraphicsItem::nestedGroups()
3669 QGraphicsItemGroup *group1 = new QGraphicsItemGroup;
3670 QGraphicsItemGroup *group2 = new QGraphicsItemGroup;
3672 QGraphicsRectItem *rect = new QGraphicsRectItem;
3673 QGraphicsRectItem *rect2 = new QGraphicsRectItem;
3674 rect2->setParentItem(rect);
3676 group1->addToGroup(rect);
3677 QCOMPARE(rect->group(), group1);
3678 QCOMPARE(rect2->group(), group1);
3680 group2->addToGroup(group1);
3681 QCOMPARE(rect->group(), group1);
3682 QCOMPARE(rect2->group(), group1);
3683 QCOMPARE(group1->group(), group2);
3684 QCOMPARE(group2->group(), (QGraphicsItemGroup *)0);
3686 QGraphicsScene scene;
3687 scene.addItem(group1);
3689 QCOMPARE(rect->group(), group1);
3690 QCOMPARE(rect2->group(), group1);
3691 QCOMPARE(group1->group(), (QGraphicsItemGroup *)0);
3692 QVERIFY(group2->children().isEmpty());
3697 void tst_QGraphicsItem::warpChildrenIntoGroup()
3699 QGraphicsScene scene;
3700 QGraphicsRectItem *parentRectItem = scene.addRect(QRectF(0, 0, 100, 100));
3701 QGraphicsRectItem *childRectItem = scene.addRect(QRectF(0, 0, 100, 100));
3702 parentRectItem->rotate(90);
3703 childRectItem->setPos(-50, -25);
3704 childRectItem->setParentItem(parentRectItem);
3706 QCOMPARE(childRectItem->mapToScene(50, 0), QPointF(25, 0));
3707 QCOMPARE(childRectItem->scenePos(), QPointF(25, -50));
3709 QGraphicsRectItem *parentOfGroup = scene.addRect(QRectF(0, 0, 100, 100));
3710 parentOfGroup->setPos(-200, -200);
3711 parentOfGroup->scale(2, 2);
3713 QGraphicsItemGroup *group = new QGraphicsItemGroup;
3714 group->setPos(50, 50);
3715 group->setParentItem(parentOfGroup);
3717 QCOMPARE(group->scenePos(), QPointF(-100, -100));
3719 group->addToGroup(childRectItem);
3721 QCOMPARE(childRectItem->mapToScene(50, 0), QPointF(25, 0));
3722 QCOMPARE(childRectItem->scenePos(), QPointF(25, -50));
3725 void tst_QGraphicsItem::removeFromGroup()
3727 QGraphicsScene scene;
3728 QGraphicsRectItem *rect1 = scene.addRect(QRectF(-100, -100, 200, 200));
3729 QGraphicsRectItem *rect2 = scene.addRect(QRectF(100, 100, 200, 200));
3730 rect1->setFlag(QGraphicsItem::ItemIsSelectable);
3731 rect2->setFlag(QGraphicsItem::ItemIsSelectable);
3732 rect1->setSelected(true);
3733 rect2->setSelected(true);
3735 QGraphicsView view(&scene);
3738 qApp->processEvents(); // index items
3739 qApp->processEvents(); // emit changed
3741 QGraphicsItemGroup *group = scene.createItemGroup(scene.selectedItems());
3743 QCOMPARE(group->children().size(), 2);
3744 qApp->processEvents(); // index items
3745 qApp->processEvents(); // emit changed
3747 scene.destroyItemGroup(group); // calls removeFromGroup.
3749 qApp->processEvents(); // index items
3750 qApp->processEvents(); // emit changed
3752 QCOMPARE(scene.items().size(), 2);
3753 QVERIFY(!rect1->group());
3754 QVERIFY(!rect2->group());
3757 class ChildEventTester : public QGraphicsRectItem
3760 ChildEventTester(const QRectF &rect, QGraphicsItem *parent = 0)
3761 : QGraphicsRectItem(rect, parent), counter(0)
3767 void focusInEvent(QFocusEvent *event)
3768 { ++counter; QGraphicsRectItem::focusInEvent(event); }
3769 void mousePressEvent(QGraphicsSceneMouseEvent *)
3771 void mouseMoveEvent(QGraphicsSceneMouseEvent *)
3773 void mouseReleaseEvent(QGraphicsSceneMouseEvent *)
3777 void tst_QGraphicsItem::handlesChildEvents()
3779 ChildEventTester *blue = new ChildEventTester(QRectF(0, 0, 100, 100));
3780 ChildEventTester *red = new ChildEventTester(QRectF(0, 0, 50, 50));
3781 ChildEventTester *green = new ChildEventTester(QRectF(0, 0, 25, 25));
3782 ChildEventTester *gray = new ChildEventTester(QRectF(0, 0, 25, 25));
3783 ChildEventTester *yellow = new ChildEventTester(QRectF(0, 0, 50, 50));
3785 blue->setBrush(QBrush(Qt::blue));
3786 red->setBrush(QBrush(Qt::red));
3787 yellow->setBrush(QBrush(Qt::yellow));
3788 green->setBrush(QBrush(Qt::green));
3789 gray->setBrush(QBrush(Qt::gray));
3791 yellow->setPos(50, 50);
3792 green->setPos(25, 0);
3793 gray->setPos(25, 25);
3794 red->setParentItem(blue);
3795 yellow->setParentItem(blue);
3796 green->setParentItem(red);
3797 gray->setParentItem(red);
3799 QGraphicsScene scene;
3800 scene.addItem(blue);
3802 QGraphicsView view(&scene);
3804 QVERIFY(QTest::qWaitForWindowExposed(&view));
3807 // Pull out the items, closest item first
3808 QList<QGraphicsItem *> items = scene.items(scene.itemsBoundingRect());
3809 QCOMPARE(items.at(0), (QGraphicsItem *)yellow);
3810 QCOMPARE(items.at(1), (QGraphicsItem *)gray);
3811 QCOMPARE(items.at(2), (QGraphicsItem *)green);
3812 QCOMPARE(items.at(3), (QGraphicsItem *)red);
3813 QCOMPARE(items.at(4), (QGraphicsItem *)blue);
3815 QCOMPARE(blue->counter, 0);
3817 // Send events to the toplevel item
3818 QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
3819 QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
3821 pressEvent.setButton(Qt::LeftButton);
3822 pressEvent.setScenePos(blue->mapToScene(5, 5));
3823 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3824 releaseEvent.setButton(Qt::LeftButton);
3825 releaseEvent.setScenePos(blue->mapToScene(5, 5));
3826 releaseEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3827 QApplication::sendEvent(&scene, &pressEvent);
3828 QApplication::sendEvent(&scene, &releaseEvent);
3830 QCOMPARE(blue->counter, 2);
3832 // Send events to a level1 item
3833 pressEvent.setScenePos(red->mapToScene(5, 5));
3834 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3835 releaseEvent.setScenePos(red->mapToScene(5, 5));
3836 releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
3837 QApplication::sendEvent(&scene, &pressEvent);
3838 QApplication::sendEvent(&scene, &releaseEvent);
3840 QCOMPARE(blue->counter, 2);
3841 QCOMPARE(red->counter, 2);
3843 // Send events to a level2 item
3844 pressEvent.setScenePos(green->mapToScene(5, 5));
3845 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3846 releaseEvent.setScenePos(green->mapToScene(5, 5));
3847 releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
3848 QApplication::sendEvent(&scene, &pressEvent);
3849 QApplication::sendEvent(&scene, &releaseEvent);
3851 QCOMPARE(blue->counter, 2);
3852 QCOMPARE(red->counter, 2);
3853 QCOMPARE(green->counter, 2);
3855 blue->setHandlesChildEvents(true);
3857 // Send events to a level1 item
3858 pressEvent.setScenePos(red->mapToScene(5, 5));
3859 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3860 releaseEvent.setScenePos(red->mapToScene(5, 5));
3861 releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
3862 QApplication::sendEvent(&scene, &pressEvent);
3863 QApplication::sendEvent(&scene, &releaseEvent);
3865 QCOMPARE(blue->counter, 4);
3866 QCOMPARE(red->counter, 2);
3868 // Send events to a level2 item
3869 pressEvent.setScenePos(green->mapToScene(5, 5));
3870 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3871 releaseEvent.setScenePos(green->mapToScene(5, 5));
3872 releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
3873 QApplication::sendEvent(&scene, &pressEvent);
3874 QApplication::sendEvent(&scene, &releaseEvent);
3876 QCOMPARE(blue->counter, 6);
3877 QCOMPARE(red->counter, 2);
3878 QCOMPARE(green->counter, 2);
3880 blue->setHandlesChildEvents(false);
3882 // Send events to a level1 item
3883 pressEvent.setScenePos(red->mapToScene(5, 5));
3884 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3885 releaseEvent.setScenePos(red->mapToScene(5, 5));
3886 releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
3887 QApplication::sendEvent(&scene, &pressEvent);
3888 QApplication::sendEvent(&scene, &releaseEvent);
3890 QCOMPARE(blue->counter, 6);
3891 QCOMPARE(red->counter, 4);
3893 // Send events to a level2 item
3894 pressEvent.setScenePos(green->mapToScene(5, 5));
3895 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3896 releaseEvent.setScenePos(green->mapToScene(5, 5));
3897 releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
3898 QApplication::sendEvent(&scene, &pressEvent);
3899 QApplication::sendEvent(&scene, &releaseEvent);
3901 QCOMPARE(blue->counter, 6);
3902 QCOMPARE(red->counter, 4);
3903 QCOMPARE(green->counter, 4);
3906 void tst_QGraphicsItem::handlesChildEvents2()
3908 ChildEventTester *root = new ChildEventTester(QRectF(0, 0, 10, 10));
3909 root->setHandlesChildEvents(true);
3910 QVERIFY(root->handlesChildEvents());
3912 ChildEventTester *child = new ChildEventTester(QRectF(0, 0, 10, 10), root);
3913 QVERIFY(!child->handlesChildEvents());
3915 ChildEventTester *child2 = new ChildEventTester(QRectF(0, 0, 10, 10));
3916 ChildEventTester *child3 = new ChildEventTester(QRectF(0, 0, 10, 10), child2);
3917 ChildEventTester *child4 = new ChildEventTester(QRectF(0, 0, 10, 10), child3);
3918 child2->setParentItem(root);
3919 QVERIFY(!child2->handlesChildEvents());
3920 QVERIFY(!child3->handlesChildEvents());
3921 QVERIFY(!child4->handlesChildEvents());
3923 QGraphicsScene scene;
3924 scene.addItem(root);
3926 QGraphicsView view(&scene);
3928 QVERIFY(QTest::qWaitForWindowExposed(&view));
3929 QApplication::processEvents();
3931 QMouseEvent event(QEvent::MouseButtonPress, view.mapFromScene(5, 5),
3932 view.viewport()->mapToGlobal(view.mapFromScene(5, 5)), Qt::LeftButton, 0, 0);
3933 QApplication::sendEvent(view.viewport(), &event);
3935 QTRY_COMPARE(root->counter, 1);
3938 void tst_QGraphicsItem::handlesChildEvents3()
3940 QGraphicsScene scene;
3941 QEvent activate(QEvent::WindowActivate);
3942 QApplication::sendEvent(&scene, &activate);
3944 ChildEventTester *group2 = new ChildEventTester(QRectF(), 0);
3945 ChildEventTester *group1 = new ChildEventTester(QRectF(), group2);
3946 ChildEventTester *leaf = new ChildEventTester(QRectF(), group1);
3947 scene.addItem(group2);
3949 leaf->setFlag(QGraphicsItem::ItemIsFocusable);
3950 group1->setFlag(QGraphicsItem::ItemIsFocusable);
3951 group1->setHandlesChildEvents(true);
3952 group2->setFlag(QGraphicsItem::ItemIsFocusable);
3953 group2->setHandlesChildEvents(true);
3956 QVERIFY(leaf->hasFocus()); // group2 stole the event, but leaf still got focus
3957 QVERIFY(!group1->hasFocus());
3958 QVERIFY(!group2->hasFocus());
3959 QCOMPARE(leaf->counter, 0);
3960 QCOMPARE(group1->counter, 0);
3961 QCOMPARE(group2->counter, 1);
3964 QVERIFY(group1->hasFocus()); // group2 stole the event, but group1 still got focus
3965 QVERIFY(!leaf->hasFocus());
3966 QVERIFY(!group2->hasFocus());
3967 QCOMPARE(leaf->counter, 0);
3968 QCOMPARE(group1->counter, 0);
3969 QCOMPARE(group2->counter, 2);
3972 QVERIFY(group2->hasFocus()); // group2 stole the event, and now group2 also has focus
3973 QVERIFY(!leaf->hasFocus());
3974 QVERIFY(!group1->hasFocus());
3975 QCOMPARE(leaf->counter, 0);
3976 QCOMPARE(group1->counter, 0);
3977 QCOMPARE(group2->counter, 3);
3981 class ChildEventFilterTester : public ChildEventTester
3984 ChildEventFilterTester(const QRectF &rect, QGraphicsItem *parent = 0)
3985 : ChildEventTester(rect, parent), filter(QEvent::None)
3988 QEvent::Type filter;
3991 bool sceneEventFilter(QGraphicsItem *item, QEvent *event)
3994 if (event->type() == filter) {
4002 void tst_QGraphicsItem::filtersChildEvents()
4004 QGraphicsScene scene;
4005 ChildEventFilterTester *root = new ChildEventFilterTester(QRectF(0, 0, 10, 10));
4006 ChildEventFilterTester *filter = new ChildEventFilterTester(QRectF(10, 10, 10, 10), root);
4007 ChildEventTester *child = new ChildEventTester(QRectF(20, 20, 10, 10), filter);
4010 filter->setFiltersChildEvents(true);
4011 filter->filter = QEvent::GraphicsSceneMousePress;
4013 scene.addItem(root);
4015 QGraphicsView view(&scene);
4017 QVERIFY(QTest::qWaitForWindowExposed(&view));
4020 QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
4021 QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
4023 // send event to child
4024 pressEvent.setButton(Qt::LeftButton);
4025 pressEvent.setScenePos(QPointF(25, 25));//child->mapToScene(5, 5));
4026 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
4027 releaseEvent.setButton(Qt::LeftButton);
4028 releaseEvent.setScenePos(QPointF(25, 25));//child->mapToScene(5, 5));
4029 releaseEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
4030 QApplication::sendEvent(&scene, &pressEvent);
4031 QApplication::sendEvent(&scene, &releaseEvent);
4033 QTRY_COMPARE(child->counter, 1); // mouse release is not filtered
4034 QCOMPARE(filter->counter, 1); // mouse press is filtered
4035 QCOMPARE(root->counter, 0);
4037 // add another filter
4038 root->setFiltersChildEvents(true);
4039 root->filter = QEvent::GraphicsSceneMouseRelease;
4041 // send event to child
4042 QApplication::sendEvent(&scene, &pressEvent);
4043 QApplication::sendEvent(&scene, &releaseEvent);
4045 QCOMPARE(child->counter, 1);
4046 QCOMPARE(filter->counter, 2); // mouse press is filtered
4047 QCOMPARE(root->counter, 1); // mouse release is filtered
4049 // reparent to another sub-graph
4050 ChildEventTester *parent = new ChildEventTester(QRectF(10, 10, 10, 10), root);
4051 child->setParentItem(parent);
4053 // send event to child
4054 QApplication::sendEvent(&scene, &pressEvent);
4055 QApplication::sendEvent(&scene, &releaseEvent);
4057 QCOMPARE(child->counter, 2); // mouse press is _not_ filtered
4058 QCOMPARE(parent->counter, 0);
4059 QCOMPARE(filter->counter, 2);
4060 QCOMPARE(root->counter, 2); // mouse release is filtered
4063 void tst_QGraphicsItem::filtersChildEvents2()
4065 ChildEventFilterTester *root = new ChildEventFilterTester(QRectF(0, 0, 10, 10));
4066 root->setFiltersChildEvents(true);
4067 root->filter = QEvent::GraphicsSceneMousePress;
4068 QVERIFY(root->filtersChildEvents());
4070 ChildEventTester *child = new ChildEventTester(QRectF(0, 0, 10, 10), root);
4071 QVERIFY(!child->filtersChildEvents());
4073 ChildEventTester *child2 = new ChildEventTester(QRectF(0, 0, 10, 10));
4074 ChildEventTester *child3 = new ChildEventTester(QRectF(0, 0, 10, 10), child2);
4075 ChildEventTester *child4 = new ChildEventTester(QRectF(0, 0, 10, 10), child3);
4077 child2->setParentItem(root);
4078 QVERIFY(!child2->filtersChildEvents());
4079 QVERIFY(!child3->filtersChildEvents());
4080 QVERIFY(!child4->filtersChildEvents());
4082 QGraphicsScene scene;
4083 scene.addItem(root);
4085 QGraphicsView view(&scene);
4088 QVERIFY(QTest::qWaitForWindowExposed(&view));
4089 QApplication::processEvents();
4091 QMouseEvent event(QEvent::MouseButtonPress, view.mapFromScene(5, 5),
4092 view.viewport()->mapToGlobal(view.mapFromScene(5, 5)), Qt::LeftButton, 0, 0);
4093 QApplication::sendEvent(view.viewport(), &event);
4095 QTRY_COMPARE(root->counter, 1);
4096 QCOMPARE(child->counter, 0);
4097 QCOMPARE(child2->counter, 0);
4098 QCOMPARE(child3->counter, 0);
4099 QCOMPARE(child4->counter, 0);
4102 class CustomItem : public QGraphicsItem
4105 QRectF boundingRect() const
4106 { return QRectF(-110, -110, 220, 220); }
4108 void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
4110 for (int x = -100; x <= 100; x += 25)
4111 painter->drawLine(x, -100, x, 100);
4112 for (int y = -100; y <= 100; y += 25)
4113 painter->drawLine(-100, y, 100, y);
4115 QFont font = painter->font();
4116 font.setPointSize(4);
4117 painter->setFont(font);
4118 for (int x = -100; x < 100; x += 25) {
4119 for (int y = -100; y < 100; y += 25) {
4120 painter->drawText(QRectF(x, y, 25, 25), Qt::AlignCenter, QString("%1x%2").arg(x).arg(y));
4126 void tst_QGraphicsItem::ensureVisible()
4128 QGraphicsScene scene;
4129 scene.setSceneRect(-200, -200, 400, 400);
4130 QGraphicsItem *item = new CustomItem;
4131 scene.addItem(item);
4133 QGraphicsView view(&scene);
4134 view.setFixedSize(300, 300);
4136 QVERIFY(QTest::qWaitForWindowExposed(&view));
4138 for (int i = 0; i < 25; ++i) {
4139 view.scale(qreal(1.06), qreal(1.06));
4140 QApplication::processEvents();
4143 item->ensureVisible(-100, -100, 25, 25);
4146 for (int x = -100; x < 100; x += 25) {
4147 for (int y = -100; y < 100; y += 25) {
4148 int xmargin = rand() % 75;
4149 int ymargin = rand() % 75;
4150 item->ensureVisible(x, y, 25, 25, xmargin, ymargin);
4151 QApplication::processEvents();
4153 QPolygonF viewScenePoly;
4154 viewScenePoly << view.mapToScene(view.rect().topLeft())
4155 << view.mapToScene(view.rect().topRight())
4156 << view.mapToScene(view.rect().bottomRight())
4157 << view.mapToScene(view.rect().bottomLeft());
4159 QVERIFY(scene.items(viewScenePoly).contains(item));
4162 path.addPolygon(viewScenePoly);
4163 QVERIFY(path.contains(item->mapToScene(x + 12, y + 12)));
4165 QPolygonF viewScenePolyMinusMargins;
4166 viewScenePolyMinusMargins << view.mapToScene(view.rect().topLeft() + QPoint(xmargin, ymargin))
4167 << view.mapToScene(view.rect().topRight() + QPoint(-xmargin, ymargin))
4168 << view.mapToScene(view.rect().bottomRight() + QPoint(-xmargin, -ymargin))
4169 << view.mapToScene(view.rect().bottomLeft() + QPoint(xmargin, -ymargin));
4172 path2.addPolygon(viewScenePolyMinusMargins);
4173 QVERIFY(path2.contains(item->mapToScene(x + 12, y + 12)));
4177 item->ensureVisible(100, 100, 25, 25);
4181 #ifndef QTEST_NO_CURSOR
4182 void tst_QGraphicsItem::cursor()
4184 QGraphicsScene scene;
4185 QGraphicsRectItem *item1 = scene.addRect(QRectF(0, 0, 50, 50));
4186 QGraphicsRectItem *item2 = scene.addRect(QRectF(0, 0, 50, 50));
4187 item1->setPos(-100, 0);
4188 item2->setPos(50, 0);
4190 QVERIFY(!item1->hasCursor());
4191 QVERIFY(!item2->hasCursor());
4193 item1->setCursor(Qt::IBeamCursor);
4194 item2->setCursor(Qt::PointingHandCursor);
4196 QVERIFY(item1->hasCursor());
4197 QVERIFY(item2->hasCursor());
4199 item1->setCursor(QCursor());
4200 item2->setCursor(QCursor());
4202 QVERIFY(item1->hasCursor());
4203 QVERIFY(item2->hasCursor());
4205 item1->unsetCursor();
4206 item2->unsetCursor();
4208 QVERIFY(!item1->hasCursor());
4209 QVERIFY(!item2->hasCursor());
4211 item1->setCursor(Qt::IBeamCursor);
4212 item2->setCursor(Qt::PointingHandCursor);
4215 QGraphicsView view(&scene,&topLevel);
4216 view.setFixedSize(200, 100);
4218 QTest::mouseMove(&view, view.rect().center());
4222 QCursor cursor = view.viewport()->cursor();
4225 QMouseEvent event(QEvent::MouseMove, QPoint(100, 50), Qt::NoButton, 0, 0);
4226 QApplication::sendEvent(view.viewport(), &event);
4231 QCOMPARE(view.viewport()->cursor().shape(), cursor.shape());
4234 QTest::mouseMove(view.viewport(), view.mapFromScene(item1->sceneBoundingRect().center()));
4235 QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item1->sceneBoundingRect().center()), Qt::NoButton, 0, 0);
4236 QApplication::sendEvent(view.viewport(), &event);
4239 QCOMPARE(view.viewport()->cursor().shape(), item1->cursor().shape());
4242 QTest::mouseMove(view.viewport(), view.mapFromScene(item2->sceneBoundingRect().center()));
4243 QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item2->sceneBoundingRect().center()), Qt::NoButton, 0, 0);
4244 QApplication::sendEvent(view.viewport(), &event);
4249 QCOMPARE(view.viewport()->cursor().shape(), item2->cursor().shape());
4252 QTest::mouseMove(view.viewport(), view.rect().center());
4253 QMouseEvent event(QEvent::MouseMove, QPoint(100, 25), Qt::NoButton, 0, 0);
4254 QApplication::sendEvent(view.viewport(), &event);
4259 QCOMPARE(view.viewport()->cursor().shape(), cursor.shape());
4263 void tst_QGraphicsItem::textControlGetterSetter()
4265 QGraphicsTextItem *item = new QGraphicsTextItem;
4266 QVERIFY(item->textControl()->parent() == item);
4267 QPointer<QWidgetTextControl> control = item->textControl();
4271 item = new QGraphicsTextItem;
4273 QPointer<QWidgetTextControl> oldControl = control;
4274 control = new QWidgetTextControl;
4276 item->setTextControl(control);
4277 QVERIFY(item->textControl() == control);
4278 QVERIFY(!control->parent());
4279 QVERIFY(!oldControl);
4281 // set some text to give it a size, to test that
4282 // setTextControl (re)connects signals
4283 const QRectF oldBoundingRect = item->boundingRect();
4284 QVERIFY(oldBoundingRect.isValid());
4285 item->setPlainText("Some text");
4287 QVERIFY(item->boundingRect().isValid());
4288 QVERIFY(item->boundingRect() != oldBoundingRect);
4290 // test that on setting a control the item size
4292 oldControl = control;
4293 control = new QWidgetTextControl;
4294 control->setPlainText("foo!");
4295 item->setTextControl(control);
4296 QCOMPARE(item->boundingRect().size(), control->document()->documentLayout()->documentSize());
4298 QVERIFY(oldControl);
4307 void tst_QGraphicsItem::defaultItemTest_QGraphicsLineItem()
4309 QGraphicsLineItem item;
4310 QCOMPARE(item.line(), QLineF());
4311 QCOMPARE(item.pen(), QPen());
4312 QCOMPARE(item.shape(), QPainterPath());
4314 item.setPen(QPen(Qt::black, 1));
4315 QCOMPARE(item.pen(), QPen(Qt::black, 1));
4316 item.setLine(QLineF(0, 0, 10, 0));
4317 QCOMPARE(item.line(), QLineF(0, 0, 10, 0));
4318 QCOMPARE(item.boundingRect(), QRectF(-0.5, -0.5, 11, 1));
4319 QCOMPARE(item.shape().elementCount(), 11);
4322 path.moveTo(0, -0.5);
4323 path.lineTo(10, -0.5);
4324 path.lineTo(10.5, -0.5);
4325 path.lineTo(10.5, 0.5);
4326 path.lineTo(10, 0.5);
4327 path.lineTo(0, 0.5);
4328 path.lineTo(-0.5, 0.5);
4329 path.lineTo(-0.5, -0.5);
4330 path.lineTo(0, -0.5);
4333 path.closeSubpath();
4335 for (int i = 0; i < 11; ++i)
4336 QCOMPARE(QPointF(item.shape().elementAt(i)), QPointF(path.elementAt(i)));
4339 void tst_QGraphicsItem::defaultItemTest_QGraphicsPixmapItem()
4341 QGraphicsPixmapItem item;
4342 QVERIFY(item.pixmap().isNull());
4343 QCOMPARE(item.offset(), QPointF());
4344 QCOMPARE(item.transformationMode(), Qt::FastTransformation);
4346 QPixmap pixmap(300, 200);
4347 pixmap.fill(Qt::red);
4348 item.setPixmap(pixmap);
4349 QCOMPARE(item.pixmap(), pixmap);
4351 item.setTransformationMode(Qt::FastTransformation);
4352 QCOMPARE(item.transformationMode(), Qt::FastTransformation);
4353 item.setTransformationMode(Qt::SmoothTransformation);
4354 QCOMPARE(item.transformationMode(), Qt::SmoothTransformation);
4356 item.setOffset(-15, -15);
4357 QCOMPARE(item.offset(), QPointF(-15, -15));
4358 item.setOffset(QPointF(-10, -10));
4359 QCOMPARE(item.offset(), QPointF(-10, -10));
4361 QCOMPARE(item.boundingRect(), QRectF(-10, -10, 300, 200));
4364 void tst_QGraphicsItem::defaultItemTest_QGraphicsTextItem()
4366 QGraphicsTextItem *text = new QGraphicsTextItem;
4367 QVERIFY(!text->openExternalLinks());
4368 QVERIFY(text->textCursor().isNull());
4369 QCOMPARE(text->defaultTextColor(), QPalette().color(QPalette::Text));
4370 QVERIFY(text->document() != 0);
4371 QCOMPARE(text->font(), QApplication::font());
4372 QCOMPARE(text->textInteractionFlags(), Qt::TextInteractionFlags(Qt::NoTextInteraction));
4373 QCOMPARE(text->textWidth(), -1.0);
4374 QCOMPARE(text->toPlainText(), QString(""));
4376 QGraphicsScene scene;
4377 scene.addItem(text);
4378 text->setPlainText("Hello world");
4379 text->setFlag(QGraphicsItem::ItemIsMovable);
4382 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
4383 event.setScenePos(QPointF(1, 1));
4384 event.setButton(Qt::LeftButton);
4385 event.setButtons(Qt::LeftButton);
4386 QApplication::sendEvent(&scene, &event);
4387 QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove);
4388 event2.setScenePos(QPointF(11, 11));
4389 event2.setButton(Qt::LeftButton);
4390 event2.setButtons(Qt::LeftButton);
4391 QApplication::sendEvent(&scene, &event2);
4394 QCOMPARE(text->pos(), QPointF(10, 10));
4396 text->setTextInteractionFlags(Qt::NoTextInteraction);
4397 QVERIFY(!(text->flags() & QGraphicsItem::ItemAcceptsInputMethod));
4398 text->setTextInteractionFlags(Qt::TextEditorInteraction);
4399 QCOMPARE(text->textInteractionFlags(), Qt::TextInteractionFlags(Qt::TextEditorInteraction));
4400 QVERIFY(text->flags() & QGraphicsItem::ItemAcceptsInputMethod);
4403 QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove);
4404 event2.setScenePos(QPointF(21, 21));
4405 event2.setButton(Qt::LeftButton);
4406 event2.setButtons(Qt::LeftButton);
4407 QApplication::sendEvent(&scene, &event2);
4410 QCOMPARE(text->pos(), QPointF(20, 20)); // clicked on edge, item moved
4413 void tst_QGraphicsItem::defaultItemTest_QGraphicsEllipseItem()
4415 QGraphicsEllipseItem item;
4416 item.setPen(QPen(Qt::black, 0));
4417 QVERIFY(item.rect().isNull());
4418 QVERIFY(item.boundingRect().isNull());
4419 QVERIFY(item.shape().isEmpty());
4420 QCOMPARE(item.spanAngle(), 360 * 16);
4421 QCOMPARE(item.startAngle(), 0);
4423 item.setRect(0, 0, 100, 100);
4424 QCOMPARE(item.boundingRect(), QRectF(0, 0, 100, 100));
4426 item.setSpanAngle(90 * 16);
4427 qFuzzyCompare(item.boundingRect().left(), qreal(50.0));
4428 qFuzzyCompare(item.boundingRect().top(), qreal(0.0));
4429 qFuzzyCompare(item.boundingRect().width(), qreal(50.0));
4430 qFuzzyCompare(item.boundingRect().height(), qreal(50.0));
4432 item.setPen(QPen(Qt::black, 1));
4433 QCOMPARE(item.boundingRect(), QRectF(49.5, -0.5, 51, 51));
4435 item.setSpanAngle(180 * 16);
4436 QCOMPARE(item.boundingRect(), QRectF(-0.5, -0.5, 101, 51));
4438 item.setSpanAngle(360 * 16);
4439 QCOMPARE(item.boundingRect(), QRectF(-0.5, -0.5, 101, 101));
4442 class ItemChangeTester : public QGraphicsRectItem
4446 { setFlag(ItemSendsGeometryChanges); clear(); }
4447 ItemChangeTester(QGraphicsItem *parent) : QGraphicsRectItem(parent)
4448 { setFlag(ItemSendsGeometryChanges); clear(); }
4452 itemChangeReturnValue = QVariant();
4453 itemSceneChangeTargetScene = 0;
4459 QVariant itemChangeReturnValue;
4460 QGraphicsScene *itemSceneChangeTargetScene;
4462 QList<GraphicsItemChange> changes;
4463 QList<QVariant> values;
4464 QList<QVariant> oldValues;
4466 QVariant itemChange(GraphicsItemChange change, const QVariant &value)
4471 case QGraphicsItem::ItemPositionChange:
4474 case QGraphicsItem::ItemPositionHasChanged:
4476 case QGraphicsItem::ItemMatrixChange: {
4478 variant.setValue<QMatrix>(matrix());
4479 oldValues << variant;
4482 case QGraphicsItem::ItemTransformChange: {
4484 variant.setValue<QTransform>(transform());
4485 oldValues << variant;
4488 case QGraphicsItem::ItemTransformHasChanged:
4490 case QGraphicsItem::ItemVisibleChange:
4491 oldValues << isVisible();
4493 case QGraphicsItem::ItemVisibleHasChanged:
4495 case QGraphicsItem::ItemEnabledChange:
4496 oldValues << isEnabled();
4498 case QGraphicsItem::ItemEnabledHasChanged:
4500 case QGraphicsItem::ItemSelectedChange:
4501 oldValues << isSelected();
4503 case QGraphicsItem::ItemSelectedHasChanged:
4505 case QGraphicsItem::ItemParentChange:
4506 oldValues << QVariant::fromValue<void *>(parentItem());
4508 case QGraphicsItem::ItemParentHasChanged:
4510 case QGraphicsItem::ItemChildAddedChange:
4511 oldValues << children().size();
4513 case QGraphicsItem::ItemChildRemovedChange:
4514 oldValues << children().size();
4516 case QGraphicsItem::ItemSceneChange:
4517 oldValues << QVariant::fromValue<QGraphicsScene *>(scene());
4518 if (itemSceneChangeTargetScene
4519 && qvariant_cast<QGraphicsScene *>(value)
4520 && itemSceneChangeTargetScene != qvariant_cast<QGraphicsScene *>(value)) {
4521 return QVariant::fromValue<QGraphicsScene *>(itemSceneChangeTargetScene);
4524 case QGraphicsItem::ItemSceneHasChanged:
4526 case QGraphicsItem::ItemCursorChange:
4527 #ifndef QTEST_NO_CURSOR
4528 oldValues << cursor();
4531 case QGraphicsItem::ItemCursorHasChanged:
4533 case QGraphicsItem::ItemToolTipChange:
4534 oldValues << toolTip();
4536 case QGraphicsItem::ItemToolTipHasChanged:
4538 case QGraphicsItem::ItemFlagsChange:
4539 oldValues << quint32(flags());
4541 case QGraphicsItem::ItemFlagsHaveChanged:
4543 case QGraphicsItem::ItemZValueChange:
4544 oldValues << zValue();
4546 case QGraphicsItem::ItemZValueHasChanged:
4548 case QGraphicsItem::ItemOpacityChange:
4549 oldValues << opacity();
4551 case QGraphicsItem::ItemOpacityHasChanged:
4553 case QGraphicsItem::ItemScenePositionHasChanged:
4555 case QGraphicsItem::ItemRotationChange:
4556 oldValues << rotation();
4558 case QGraphicsItem::ItemRotationHasChanged:
4560 case QGraphicsItem::ItemScaleChange:
4561 oldValues << scale();
4563 case QGraphicsItem::ItemScaleHasChanged:
4565 case QGraphicsItem::ItemTransformOriginPointChange:
4566 oldValues << transformOriginPoint();
4568 case QGraphicsItem::ItemTransformOriginPointHasChanged:
4571 return itemChangeReturnValue.isValid() ? itemChangeReturnValue : value;
4575 void tst_QGraphicsItem::itemChange()
4577 ItemChangeTester tester;
4578 tester.itemSceneChangeTargetScene = 0;
4580 ItemChangeTester testerHelper;
4581 QVERIFY(tester.changes.isEmpty());
4582 QVERIFY(tester.values.isEmpty());
4584 int changeCount = 0;
4586 // ItemEnabledChange
4587 tester.itemChangeReturnValue = true;
4588 tester.setEnabled(false);
4590 ++changeCount; // HasChanged
4591 QCOMPARE(tester.changes.size(), changeCount);
4592 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemEnabledChange);
4593 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemEnabledHasChanged);
4594 QCOMPARE(tester.values.at(tester.values.size() - 2), QVariant(false));
4595 QCOMPARE(tester.values.at(tester.values.size() - 1), QVariant(true));
4596 QCOMPARE(tester.oldValues.last(), QVariant(true));
4597 QCOMPARE(tester.isEnabled(), true);
4600 // ItemMatrixChange / ItemTransformHasChanged
4601 tester.itemChangeReturnValue.setValue<QMatrix>(QMatrix().rotate(90));
4602 tester.setMatrix(QMatrix().translate(50, 0), true);
4603 ++changeCount; // notification sent too
4604 QCOMPARE(tester.changes.size(), ++changeCount);
4605 QCOMPARE(int(tester.changes.at(tester.changes.size() - 2)), int(QGraphicsItem::ItemMatrixChange));
4606 QCOMPARE(int(tester.changes.last()), int(QGraphicsItem::ItemTransformHasChanged));
4607 QCOMPARE(qvariant_cast<QMatrix>(tester.values.at(tester.values.size() - 2)),
4608 QMatrix().translate(50, 0));
4609 QCOMPARE(tester.values.last(), QVariant(QTransform(QMatrix().rotate(90))));
4611 variant.setValue<QMatrix>(QMatrix());
4612 QCOMPARE(tester.oldValues.last(), variant);
4613 QCOMPARE(tester.matrix(), QMatrix().rotate(90));
4616 tester.resetTransform();
4618 ++changeCount; // notification sent too
4620 // ItemTransformChange / ItemTransformHasChanged
4621 tester.itemChangeReturnValue.setValue<QTransform>(QTransform().rotate(90));
4622 tester.translate(50, 0);
4623 ++changeCount; // notification sent too
4625 QCOMPARE(tester.changes.size(), changeCount);
4626 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemTransformChange);
4627 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemTransformHasChanged);
4628 QCOMPARE(qvariant_cast<QTransform>(tester.values.at(tester.values.size() - 2)),
4629 QTransform().translate(50, 0));
4630 QCOMPARE(qvariant_cast<QTransform>(tester.values.at(tester.values.size() - 1)),
4631 QTransform().rotate(90));
4633 variant.setValue<QTransform>(QTransform());
4634 QCOMPARE(tester.oldValues.last(), variant);
4635 QCOMPARE(tester.transform(), QTransform().rotate(90));
4638 // ItemPositionChange / ItemPositionHasChanged
4639 tester.itemChangeReturnValue = QPointF(42, 0);
4640 tester.setPos(0, 42);
4641 ++changeCount; // notification sent too
4643 QCOMPARE(tester.changes.size(), changeCount);
4644 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemPositionChange);
4645 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemPositionHasChanged);
4646 QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(QPointF(0, 42)));
4647 QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(QPointF(42, 0)));
4648 QCOMPARE(tester.oldValues.last(), QVariant(QPointF()));
4649 QCOMPARE(tester.pos(), QPointF(42, 0));
4652 // ItemZValueChange / ItemZValueHasChanged
4653 tester.itemChangeReturnValue = qreal(2.0);
4654 tester.setZValue(1.0);
4655 ++changeCount; // notification sent too
4657 QCOMPARE(tester.changes.size(), changeCount);
4658 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemZValueChange);
4659 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemZValueHasChanged);
4660 QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(qreal(1.0)));
4661 QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(qreal(2.0)));
4662 QCOMPARE(tester.oldValues.last(), QVariant(qreal(0.0)));
4663 QCOMPARE(tester.zValue(), qreal(2.0));
4666 // ItemRotationChange / ItemRotationHasChanged
4667 tester.itemChangeReturnValue = qreal(15.0);
4668 tester.setRotation(10.0);
4669 ++changeCount; // notification sent too
4671 QCOMPARE(tester.changes.size(), changeCount);
4672 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemRotationChange);
4673 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemRotationHasChanged);
4674 QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(qreal(10.0)));
4675 QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(qreal(15.0)));
4676 QCOMPARE(tester.oldValues.last(), QVariant(qreal(0.0)));
4677 QCOMPARE(tester.rotation(), qreal(15.0));
4680 // ItemScaleChange / ItemScaleHasChanged
4681 tester.itemChangeReturnValue = qreal(2.0);
4682 tester.setScale(1.5);
4683 ++changeCount; // notification sent too
4685 QCOMPARE(tester.changes.size(), changeCount);
4686 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemScaleChange);
4687 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemScaleHasChanged);
4688 QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(qreal(1.5)));
4689 QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(qreal(2.0)));
4690 QCOMPARE(tester.oldValues.last(), QVariant(qreal(1.0)));
4691 QCOMPARE(tester.scale(), qreal(2.0));
4694 // ItemTransformOriginPointChange / ItemTransformOriginPointHasChanged
4695 tester.itemChangeReturnValue = QPointF(2.0, 2.0);
4696 tester.setTransformOriginPoint(1.0, 1.0);
4697 ++changeCount; // notification sent too
4699 QCOMPARE(tester.changes.size(), changeCount);
4700 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemTransformOriginPointChange);
4701 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemTransformOriginPointHasChanged);
4702 QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(QPointF(1.0, 1.0)));
4703 QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(QPointF(2.0, 2.0)));
4704 QCOMPARE(tester.oldValues.last(), QVariant(QPointF(0.0, 0.0)));
4705 QCOMPARE(tester.transformOriginPoint(), QPointF(2.0, 2.0));
4709 tester.itemChangeReturnValue = QGraphicsItem::ItemIsSelectable;
4710 tester.setFlag(QGraphicsItem::ItemIsSelectable, false);
4711 QCOMPARE(tester.changes.size(), changeCount); // No change
4712 tester.setFlag(QGraphicsItem::ItemIsSelectable, true);
4714 ++changeCount; // ItemFlagsHasChanged
4715 QCOMPARE(tester.changes.size(), changeCount);
4716 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemFlagsChange);
4717 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemFlagsHaveChanged);
4718 QVariant expectedFlags = QVariant::fromValue<quint32>(QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges));
4719 QCOMPARE(tester.values.at(tester.values.size() - 2), expectedFlags);
4720 QCOMPARE(tester.values.at(tester.values.size() - 1), QVariant::fromValue<quint32>((quint32)QGraphicsItem::ItemIsSelectable));
4723 // ItemSelectedChange
4724 tester.setSelected(false);
4725 QCOMPARE(tester.changes.size(), changeCount); // No change :-)
4726 tester.itemChangeReturnValue = true;
4727 tester.setSelected(true);
4729 ++changeCount; // ItemSelectedHasChanged
4730 QCOMPARE(tester.changes.size(), changeCount);
4731 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSelectedChange);
4732 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSelectedHasChanged);
4733 QCOMPARE(tester.values.at(tester.values.size() - 2), QVariant(true));
4734 QCOMPARE(tester.values.at(tester.values.size() - 1), QVariant(true));
4735 QCOMPARE(tester.oldValues.last(), QVariant(false));
4736 QCOMPARE(tester.isSelected(), true);
4738 tester.itemChangeReturnValue = false;
4739 tester.setSelected(true);
4741 // the value hasn't changed to the itemChange return value
4742 // bacause itemChange is never called (true -> true is a noop).
4743 QCOMPARE(tester.isSelected(), true);
4746 // ItemVisibleChange
4747 tester.itemChangeReturnValue = false;
4748 QVERIFY(tester.isVisible());
4749 tester.setVisible(false);
4750 ++changeCount; // ItemVisibleChange
4751 ++changeCount; // ItemSelectedChange
4752 ++changeCount; // ItemSelectedHasChanged
4753 ++changeCount; // ItemVisibleHasChanged
4754 QCOMPARE(tester.changes.size(), changeCount);
4755 QCOMPARE(tester.changes.at(tester.changes.size() - 4), QGraphicsItem::ItemVisibleChange);
4756 QCOMPARE(tester.changes.at(tester.changes.size() - 3), QGraphicsItem::ItemSelectedChange);
4757 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSelectedHasChanged);
4758 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemVisibleHasChanged);
4759 QCOMPARE(tester.values.at(tester.values.size() - 4), QVariant(false));
4760 QCOMPARE(tester.values.at(tester.values.size() - 3), QVariant(false));
4761 QCOMPARE(tester.values.at(tester.values.size() - 2), QVariant(false));
4762 QCOMPARE(tester.values.at(tester.values.size() - 1), QVariant(false));
4763 QCOMPARE(tester.isVisible(), false);
4767 tester.itemChangeReturnValue.setValue<QGraphicsItem *>(0);
4768 tester.setParentItem(&testerHelper);
4769 QCOMPARE(tester.changes.size(), ++changeCount);
4770 QCOMPARE(tester.changes.last(), QGraphicsItem::ItemParentChange);
4771 QCOMPARE(qvariant_cast<QGraphicsItem *>(tester.values.last()), (QGraphicsItem *)&testerHelper);
4772 QCOMPARE(qvariant_cast<QGraphicsItem *>(tester.oldValues.last()), (QGraphicsItem *)0);
4773 QCOMPARE(tester.parentItem(), (QGraphicsItem *)0);
4776 // ItemOpacityChange
4777 tester.itemChangeReturnValue = 1.0;
4778 tester.setOpacity(0.7);
4779 QCOMPARE(tester.changes.size(), ++changeCount);
4780 QCOMPARE(tester.changes.last(), QGraphicsItem::ItemOpacityChange);
4781 QVERIFY(qFuzzyCompare(qreal(tester.values.last().toDouble()), qreal(0.7)));
4782 QCOMPARE(tester.oldValues.last().toDouble(), double(1.0));
4783 QCOMPARE(tester.opacity(), qreal(1.0));
4784 tester.itemChangeReturnValue = 0.7;
4785 tester.setOpacity(0.7);
4786 ++changeCount; // ItemOpacityChange
4787 ++changeCount; // ItemOpacityHasChanged
4788 QCOMPARE(tester.changes.size(), changeCount);
4789 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemOpacityChange);
4790 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemOpacityHasChanged);
4791 QCOMPARE(tester.opacity(), qreal(0.7));
4794 // ItemChildAddedChange
4795 tester.itemChangeReturnValue.clear();
4796 testerHelper.setParentItem(&tester);
4797 QCOMPARE(tester.changes.size(), ++changeCount);
4798 QCOMPARE(tester.changes.last(), QGraphicsItem::ItemChildAddedChange);
4799 QCOMPARE(qvariant_cast<QGraphicsItem *>(tester.values.last()), (QGraphicsItem *)&testerHelper);
4802 // ItemChildRemovedChange 1
4803 testerHelper.setParentItem(0);
4804 QCOMPARE(tester.changes.size(), ++changeCount);
4805 QCOMPARE(tester.changes.last(), QGraphicsItem::ItemChildRemovedChange);
4806 QCOMPARE(qvariant_cast<QGraphicsItem *>(tester.values.last()), (QGraphicsItem *)&testerHelper);
4808 // ItemChildRemovedChange 1
4809 ItemChangeTester *test = new ItemChangeTester;
4810 test->itemSceneChangeTargetScene = 0;
4812 QGraphicsScene *scene = new QGraphicsScene;
4813 scene->addItem(test);
4814 count = test->changes.size();
4815 //We test here the fact that when a child is deleted the parent receive only one ItemChildRemovedChange
4816 QGraphicsRectItem *child = new QGraphicsRectItem(test);
4817 //We received ItemChildAddedChange
4818 QCOMPARE(test->changes.size(), ++count);
4819 QCOMPARE(test->changes.last(), QGraphicsItem::ItemChildAddedChange);
4822 QCOMPARE(test->changes.size(), ++count);
4823 QCOMPARE(test->changes.last(), QGraphicsItem::ItemChildRemovedChange);
4825 ItemChangeTester *childTester = new ItemChangeTester(test);
4826 //Changes contains all sceneHasChanged and so on, we don't want to test that
4827 int childCount = childTester->changes.size();
4828 //We received ItemChildAddedChange
4829 QCOMPARE(test->changes.size(), ++count);
4830 child = new QGraphicsRectItem(childTester);
4831 //We received ItemChildAddedChange
4832 QCOMPARE(childTester->changes.size(), ++childCount);
4833 QCOMPARE(childTester->changes.last(), QGraphicsItem::ItemChildAddedChange);
4834 //Delete the child of the top level with all its children
4837 QCOMPARE(test->changes.size(), ++count);
4838 QCOMPARE(test->changes.last(), QGraphicsItem::ItemChildRemovedChange);
4842 // ItemChildRemovedChange 2
4843 ItemChangeTester parent;
4844 ItemChangeTester *child = new ItemChangeTester;
4845 child->setParentItem(&parent);
4846 QCOMPARE(parent.changes.last(), QGraphicsItem::ItemChildAddedChange);
4847 QCOMPARE(qvariant_cast<QGraphicsItem *>(parent.values.last()), (QGraphicsItem *)child);
4849 QCOMPARE(parent.changes.last(), QGraphicsItem::ItemChildRemovedChange);
4850 QCOMPARE(qvariant_cast<QGraphicsItem *>(parent.values.last()), (QGraphicsItem *)child);
4853 // !!! Note: If this test crashes because of double-deletion, there's
4854 // a bug somewhere in QGraphicsScene or QGraphicsItem.
4857 QGraphicsScene scene;
4858 QGraphicsScene scene2;
4859 scene.addItem(&tester);
4860 ++changeCount; // ItemSceneChange (scene)
4861 ++changeCount; // ItemSceneHasChanged (scene)
4862 QCOMPARE(tester.changes.size(), changeCount);
4864 QCOMPARE(tester.scene(), &scene);
4865 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSceneChange);
4866 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSceneHasChanged);
4867 // Item's old value was 0
4868 // Item's current value is scene
4869 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.oldValues.last()), (QGraphicsScene *)0);
4870 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.last()), (QGraphicsScene *)&scene);
4871 scene2.addItem(&tester);
4872 ++changeCount; // ItemSceneChange (0) was: (scene)
4873 ++changeCount; // ItemSceneHasChanged (0)
4874 ++changeCount; // ItemSceneChange (scene2) was: (0)
4875 ++changeCount; // ItemSceneHasChanged (scene2)
4876 QCOMPARE(tester.changes.size(), changeCount);
4878 QCOMPARE(tester.scene(), &scene2);
4879 QCOMPARE(tester.changes.at(tester.changes.size() - 4), QGraphicsItem::ItemSceneChange);
4880 QCOMPARE(tester.changes.at(tester.changes.size() - 3), QGraphicsItem::ItemSceneHasChanged);
4881 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSceneChange);
4882 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSceneHasChanged);
4883 // Item's last old value was scene
4884 // Item's last current value is 0
4886 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.oldValues.at(tester.oldValues.size() - 2)), (QGraphicsScene *)&scene);
4887 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.oldValues.at(tester.oldValues.size() - 1)), (QGraphicsScene *)0);
4888 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 4)), (QGraphicsScene *)0);
4889 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 3)), (QGraphicsScene *)0);
4890 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)&scene2);
4891 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 1)), (QGraphicsScene *)&scene2);
4892 // Item's last old value was 0
4893 // Item's last current value is scene2
4894 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.oldValues.last()), (QGraphicsScene *)0);
4895 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.last()), (QGraphicsScene *)&scene2);
4897 scene2.removeItem(&tester);
4898 ++changeCount; // ItemSceneChange (0) was: (scene2)
4899 ++changeCount; // ItemSceneHasChanged (0)
4900 QCOMPARE(tester.changes.size(), changeCount);
4902 QCOMPARE(tester.scene(), (QGraphicsScene *)0);
4903 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSceneChange);
4904 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSceneHasChanged);
4905 // Item's last old value was scene2
4906 // Item's last current value is 0
4907 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.oldValues.last()), (QGraphicsScene *)&scene2);
4908 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)0);
4909 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 1)), (QGraphicsScene *)0);
4911 tester.itemSceneChangeTargetScene = &scene;
4912 scene2.addItem(&tester);
4913 ++changeCount; // ItemSceneChange (scene2) was: (0)
4914 ++changeCount; // ItemSceneChange (scene) was: (0)
4915 ++changeCount; // ItemSceneHasChanged (scene)
4916 QCOMPARE(tester.values.size(), changeCount);
4918 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 3)), (QGraphicsScene *)&scene2);
4919 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)&scene);
4920 QCOMPARE(qvariant_cast<QGraphicsScene *>(tester.values.at(tester.values.size() - 1)), (QGraphicsScene *)&scene);
4922 QCOMPARE(tester.scene(), &scene);
4923 tester.itemSceneChangeTargetScene = 0;
4924 tester.itemChangeReturnValue = QVariant();
4925 scene.removeItem(&tester);
4926 ++changeCount; // ItemSceneChange
4927 ++changeCount; // ItemSceneHasChanged
4928 QCOMPARE(tester.scene(), (QGraphicsScene *)0);
4931 // ItemToolTipChange/ItemToolTipHasChanged
4932 const QString toolTip(QLatin1String("I'm soo cool"));
4933 const QString overridenToolTip(QLatin1String("No, you are not soo cool"));
4934 tester.itemChangeReturnValue = overridenToolTip;
4935 tester.setToolTip(toolTip);
4936 ++changeCount; // ItemToolTipChange
4937 ++changeCount; // ItemToolTipHasChanged
4938 QCOMPARE(tester.changes.size(), changeCount);
4939 QCOMPARE(tester.changes.at(changeCount - 2), QGraphicsItem::ItemToolTipChange);
4940 QCOMPARE(tester.values.at(changeCount - 2).toString(), toolTip);
4941 QCOMPARE(tester.changes.at(changeCount - 1), QGraphicsItem::ItemToolTipHasChanged);
4942 QCOMPARE(tester.values.at(changeCount - 1).toString(), overridenToolTip);
4943 QCOMPARE(tester.toolTip(), overridenToolTip);
4944 tester.itemChangeReturnValue = QVariant();
4948 class EventFilterTesterItem : public QGraphicsLineItem
4951 QList<QEvent::Type> filteredEvents;
4952 QList<QGraphicsItem *> filteredEventReceivers;
4953 bool handlesSceneEvents;
4955 QList<QEvent::Type> receivedEvents;
4957 EventFilterTesterItem() : handlesSceneEvents(false) {}
4960 bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
4962 filteredEvents << event->type();
4963 filteredEventReceivers << watched;
4964 return handlesSceneEvents;
4967 bool sceneEvent(QEvent *event)
4969 return QGraphicsLineItem::sceneEvent(event);
4973 void tst_QGraphicsItem::sceneEventFilter()
4975 QGraphicsScene scene;
4977 QGraphicsView view(&scene);
4979 QApplication::setActiveWindow(&view);
4980 QVERIFY(QTest::qWaitForWindowActive(&view));
4982 QGraphicsTextItem *text1 = scene.addText(QLatin1String("Text1"));
4983 QGraphicsTextItem *text2 = scene.addText(QLatin1String("Text2"));
4984 QGraphicsTextItem *text3 = scene.addText(QLatin1String("Text3"));
4985 text1->setFlag(QGraphicsItem::ItemIsFocusable);
4986 text2->setFlag(QGraphicsItem::ItemIsFocusable);
4987 text3->setFlag(QGraphicsItem::ItemIsFocusable);
4989 EventFilterTesterItem *tester = new EventFilterTesterItem;
4990 scene.addItem(tester);
4992 QTRY_VERIFY(!text1->hasFocus());
4993 text1->installSceneEventFilter(tester);
4995 QTRY_VERIFY(text1->hasFocus());
4997 QCOMPARE(tester->filteredEvents.size(), 1);
4998 QCOMPARE(tester->filteredEvents.at(0), QEvent::FocusIn);
4999 QCOMPARE(tester->filteredEventReceivers.at(0), static_cast<QGraphicsItem *>(text1));
5001 text2->installSceneEventFilter(tester);
5002 text3->installSceneEventFilter(tester);
5007 QCOMPARE(tester->filteredEvents.size(), 5);
5008 QCOMPARE(tester->filteredEvents.at(1), QEvent::FocusOut);
5009 QCOMPARE(tester->filteredEventReceivers.at(1), static_cast<QGraphicsItem *>(text1));
5010 QCOMPARE(tester->filteredEvents.at(2), QEvent::FocusIn);
5011 QCOMPARE(tester->filteredEventReceivers.at(2), static_cast<QGraphicsItem *>(text2));
5012 QCOMPARE(tester->filteredEvents.at(3), QEvent::FocusOut);
5013 QCOMPARE(tester->filteredEventReceivers.at(3), static_cast<QGraphicsItem *>(text2));
5014 QCOMPARE(tester->filteredEvents.at(4), QEvent::FocusIn);
5015 QCOMPARE(tester->filteredEventReceivers.at(4), static_cast<QGraphicsItem *>(text3));
5017 text1->removeSceneEventFilter(tester);
5020 QCOMPARE(tester->filteredEvents.size(), 6);
5021 QCOMPARE(tester->filteredEvents.at(5), QEvent::FocusOut);
5022 QCOMPARE(tester->filteredEventReceivers.at(5), static_cast<QGraphicsItem *>(text3));
5024 tester->handlesSceneEvents = true;
5027 QCOMPARE(tester->filteredEvents.size(), 7);
5028 QCOMPARE(tester->filteredEvents.at(6), QEvent::FocusIn);
5029 QCOMPARE(tester->filteredEventReceivers.at(6), static_cast<QGraphicsItem *>(text2));
5031 QVERIFY(text2->hasFocus());
5033 //Let check if the items are correctly removed from the sceneEventFilters array
5034 //to avoid stale pointers.
5036 QGraphicsScene *anotherScene = new QGraphicsScene;
5037 QGraphicsTextItem *ti = anotherScene->addText("This is a test #1");
5039 QGraphicsTextItem *ti2 = anotherScene->addText("This is a test #2");
5040 QGraphicsTextItem *ti3 = anotherScene->addText("This is a test #3");
5041 gv.setScene(anotherScene);
5043 QVERIFY(QTest::qWaitForWindowExposed(&gv));
5045 ti->installSceneEventFilter(ti2);
5046 ti3->installSceneEventFilter(ti);
5049 QTest::mouseMove(gv.viewport(), gv.mapFromScene(ti->scenePos()));
5054 class GeometryChanger : public QGraphicsItem
5057 void changeGeometry()
5058 { prepareGeometryChange(); }
5061 void tst_QGraphicsItem::prepareGeometryChange()
5064 QGraphicsScene scene;
5065 QGraphicsItem *item = scene.addRect(QRectF(0, 0, 100, 100));
5066 QVERIFY(scene.items(QRectF(0, 0, 100, 100)).contains(item));
5067 ((GeometryChanger *)item)->changeGeometry();
5068 QVERIFY(scene.items(QRectF(0, 0, 100, 100)).contains(item));
5073 class PaintTester : public QGraphicsRectItem
5076 PaintTester() : widget(NULL), painted(0) { setRect(QRectF(10, 10, 20, 20));}
5078 void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *w)
5088 void tst_QGraphicsItem::paint()
5090 QGraphicsScene scene;
5092 PaintTester paintTester;
5093 scene.addItem(&paintTester);
5095 QGraphicsView view(&scene);
5097 QVERIFY(QTest::qWaitForWindowExposed(&view));
5098 QApplication::processEvents();
5100 //we try to switch the desktop: if it fails, we skip the test
5101 if (::SwitchDesktop( ::GetThreadDesktop( ::GetCurrentThreadId() ) ) == 0) {
5102 QSKIP("The Graphics View doesn't get the paint events");
5106 QTRY_COMPARE(paintTester.widget, view.viewport());
5110 QGraphicsScene scene2;
5111 QGraphicsView view2(&scene2);
5113 QVERIFY(QTest::qWaitForWindowExposed(&view2));
5116 PaintTester tester2;
5117 scene2.addItem(&tester2);
5118 qApp->processEvents();
5120 //First show one paint
5121 QTRY_COMPARE(tester2.painted, 1);
5123 //nominal case, update call paint
5125 qApp->processEvents();
5126 QTRY_VERIFY(tester2.painted == 2);
5128 //we remove the item from the scene, number of updates is still the same
5130 scene2.removeItem(&tester2);
5131 qApp->processEvents();
5132 QTRY_VERIFY(tester2.painted == 2);
5134 //We re-add the item, the number of paint should increase
5135 scene2.addItem(&tester2);
5137 qApp->processEvents();
5138 QTRY_VERIFY(tester2.painted == 3);
5141 class HarakiriItem : public QGraphicsRectItem
5144 HarakiriItem(int harakiriPoint)
5145 : QGraphicsRectItem(QRectF(0, 0, 100, 100)), harakiri(harakiriPoint)
5150 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
5152 QGraphicsRectItem::paint(painter, option, widget);
5153 if (harakiri == 0) {
5154 // delete unsupported since 4.5
5164 if (harakiri == 1 && n == 0) {
5165 // delete unsupported
5171 if (harakiri == 2 && n == 1) {
5178 void contextMenuEvent(QGraphicsSceneContextMenuEvent *)
5180 if (harakiri == 3) {
5186 void dragEnterEvent(QGraphicsSceneDragDropEvent *event)
5189 QGraphicsRectItem::dragEnterEvent(event);
5192 void dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
5195 QGraphicsRectItem::dragLeaveEvent(event);
5198 void dragMoveEvent(QGraphicsSceneDragDropEvent *event)
5201 QGraphicsRectItem::dragMoveEvent(event);
5204 void dropEvent(QGraphicsSceneDragDropEvent *event)
5207 QGraphicsRectItem::dropEvent(event);
5210 void focusInEvent(QFocusEvent *)
5212 if (harakiri == 4) {
5218 void focusOutEvent(QFocusEvent *)
5220 if (harakiri == 5) {
5226 void hoverEnterEvent(QGraphicsSceneHoverEvent *)
5228 if (harakiri == 6) {
5234 void hoverLeaveEvent(QGraphicsSceneHoverEvent *)
5236 if (harakiri == 7) {
5242 void hoverMoveEvent(QGraphicsSceneHoverEvent *)
5244 if (harakiri == 8) {
5250 void inputMethodEvent(QInputMethodEvent *event)
5253 QGraphicsRectItem::inputMethodEvent(event);
5256 QVariant inputMethodQuery(Qt::InputMethodQuery query) const
5259 return QGraphicsRectItem::inputMethodQuery(query);
5262 QVariant itemChange(GraphicsItemChange change, const QVariant &value)
5264 // deletion not supported
5265 return QGraphicsRectItem::itemChange(change, value);
5268 void keyPressEvent(QKeyEvent *)
5270 if (harakiri == 9) {
5276 void keyReleaseEvent(QKeyEvent *)
5278 if (harakiri == 10) {
5284 void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *)
5286 if (harakiri == 11) {
5292 void mouseMoveEvent(QGraphicsSceneMouseEvent *)
5294 if (harakiri == 12) {
5300 void mousePressEvent(QGraphicsSceneMouseEvent *)
5302 if (harakiri == 13) {
5308 void mouseReleaseEvent(QGraphicsSceneMouseEvent *)
5310 if (harakiri == 14) {
5316 bool sceneEvent(QEvent *event)
5318 // deletion not supported
5319 return QGraphicsRectItem::sceneEvent(event);
5322 bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
5324 // deletion not supported
5325 return QGraphicsRectItem::sceneEventFilter(watched, event);
5328 void wheelEvent(QGraphicsSceneWheelEvent *)
5330 if (harakiri == 16) {
5340 int HarakiriItem::dead;
5342 void tst_QGraphicsItem::deleteItemInEventHandlers()
5344 for (int i = 0; i < 17; ++i) {
5345 QGraphicsScene scene;
5346 HarakiriItem *item = new HarakiriItem(i);
5347 item->setAcceptsHoverEvents(true);
5348 item->setFlag(QGraphicsItem::ItemIsFocusable);
5350 scene.addItem(item);
5352 item->installSceneEventFilter(item); // <- ehey!
5354 QGraphicsView view(&scene);
5357 qApp->processEvents();
5358 qApp->processEvents();
5364 QContextMenuEvent event(QContextMenuEvent::Other,
5365 view.mapFromScene(item->scenePos()));
5366 QCoreApplication::sendEvent(view.viewport(), &event);
5369 QTest::mouseMove(view.viewport(), view.mapFromScene(item->scenePos()));
5371 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos()));
5373 QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos()));
5375 QTest::mouseClick(view.viewport(), Qt::RightButton, 0, view.mapFromScene(item->scenePos()));
5377 QTest::mouseMove(view.viewport(), view.mapFromScene(item->scenePos() + QPointF(20, -20)));
5385 QTest::keyPress(view.viewport(), Qt::Key_A);
5387 QTest::keyRelease(view.viewport(), Qt::Key_A);
5389 QTest::keyPress(view.viewport(), Qt::Key_A);
5391 QTest::keyRelease(view.viewport(), Qt::Key_A);
5395 class ItemPaintsOutsideShape : public QGraphicsItem
5398 QRectF boundingRect() const
5400 return QRectF(0, 0, 100, 100);
5403 void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
5405 painter->fillRect(-50, -50, 200, 200, Qt::red);
5406 painter->fillRect(0, 0, 100, 100, Qt::blue);
5410 void tst_QGraphicsItem::itemClipsToShape()
5412 QGraphicsItem *clippedItem = new ItemPaintsOutsideShape;
5413 clippedItem->setFlag(QGraphicsItem::ItemClipsToShape);
5415 QGraphicsItem *unclippedItem = new ItemPaintsOutsideShape;
5416 unclippedItem->setPos(200, 0);
5418 QGraphicsScene scene(-50, -50, 400, 200);
5419 scene.addItem(clippedItem);
5420 scene.addItem(unclippedItem);
5422 QImage image(400, 200, QImage::Format_ARGB32_Premultiplied);
5424 QPainter painter(&image);
5425 painter.setRenderHint(QPainter::Antialiasing);
5426 scene.render(&painter);
5429 QCOMPARE(image.pixel(45, 100), QRgb(0));
5430 QCOMPARE(image.pixel(100, 45), QRgb(0));
5431 QCOMPARE(image.pixel(155, 100), QRgb(0));
5432 QCOMPARE(image.pixel(45, 155), QRgb(0));
5433 QCOMPARE(image.pixel(55, 100), QColor(Qt::blue).rgba());
5434 QCOMPARE(image.pixel(100, 55), QColor(Qt::blue).rgba());
5435 QCOMPARE(image.pixel(145, 100), QColor(Qt::blue).rgba());
5436 QCOMPARE(image.pixel(55, 145), QColor(Qt::blue).rgba());
5437 QCOMPARE(image.pixel(245, 100), QColor(Qt::red).rgba());
5438 QCOMPARE(image.pixel(300, 45), QColor(Qt::red).rgba());
5439 QCOMPARE(image.pixel(355, 100), QColor(Qt::red).rgba());
5440 QCOMPARE(image.pixel(245, 155), QColor(Qt::red).rgba());
5441 QCOMPARE(image.pixel(255, 100), QColor(Qt::blue).rgba());
5442 QCOMPARE(image.pixel(300, 55), QColor(Qt::blue).rgba());
5443 QCOMPARE(image.pixel(345, 100), QColor(Qt::blue).rgba());
5444 QCOMPARE(image.pixel(255, 145), QColor(Qt::blue).rgba());
5447 void tst_QGraphicsItem::itemClipsChildrenToShape()
5449 QGraphicsScene scene;
5450 QGraphicsItem *rect = scene.addRect(0, 0, 50, 50, QPen(Qt::NoPen), QBrush(Qt::yellow));
5452 QGraphicsItem *ellipse = scene.addEllipse(0, 0, 100, 100, QPen(Qt::NoPen), QBrush(Qt::green));
5453 ellipse->setParentItem(rect);
5455 QGraphicsItem *clippedEllipse = scene.addEllipse(0, 0, 50, 50, QPen(Qt::NoPen), QBrush(Qt::blue));
5456 clippedEllipse->setParentItem(ellipse);
5458 QGraphicsItem *clippedEllipse2 = scene.addEllipse(0, 0, 25, 25, QPen(Qt::NoPen), QBrush(Qt::red));
5459 clippedEllipse2->setParentItem(clippedEllipse);
5461 QGraphicsItem *clippedEllipse3 = scene.addEllipse(50, 50, 25, 25, QPen(Qt::NoPen), QBrush(Qt::red));
5462 clippedEllipse3->setParentItem(clippedEllipse);
5464 QVERIFY(!(ellipse->flags() & QGraphicsItem::ItemClipsChildrenToShape));
5465 ellipse->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5466 QVERIFY((ellipse->flags() & QGraphicsItem::ItemClipsChildrenToShape));
5468 QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
5470 QPainter painter(&image);
5471 painter.setRenderHint(QPainter::Antialiasing);
5472 scene.render(&painter);
5475 QCOMPARE(image.pixel(16, 16), QColor(255, 0, 0).rgba());
5476 QCOMPARE(image.pixel(32, 32), QColor(0, 0, 255).rgba());
5477 QCOMPARE(image.pixel(50, 50), QColor(0, 255, 0).rgba());
5478 QCOMPARE(image.pixel(12, 12), QColor(255, 255, 0).rgba());
5479 QCOMPARE(image.pixel(60, 60), QColor(255, 0, 0).rgba());
5482 void tst_QGraphicsItem::itemClipsChildrenToShape2()
5484 QGraphicsRectItem *parent = new QGraphicsRectItem(QRectF(0, 0, 10, 10));
5485 QGraphicsEllipseItem *child1 = new QGraphicsEllipseItem(QRectF(50, 50, 100, 100));
5486 QGraphicsRectItem *child2 = new QGraphicsRectItem(QRectF(15, 15, 80, 80));
5488 child1->setParentItem(parent);
5489 child1->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5490 child2->setParentItem(child1);
5492 parent->setBrush(Qt::blue);
5493 child1->setBrush(Qt::green);
5494 child2->setBrush(Qt::red);
5496 QGraphicsScene scene;
5497 scene.addItem(parent);
5499 QCOMPARE(scene.itemAt(5, 5), (QGraphicsItem *)parent);
5500 QCOMPARE(scene.itemAt(15, 5), (QGraphicsItem *)0);
5501 QCOMPARE(scene.itemAt(5, 15), (QGraphicsItem *)0);
5502 QCOMPARE(scene.itemAt(60, 60), (QGraphicsItem *)0);
5503 QCOMPARE(scene.itemAt(140, 60), (QGraphicsItem *)0);
5504 QCOMPARE(scene.itemAt(60, 140), (QGraphicsItem *)0);
5505 QCOMPARE(scene.itemAt(140, 140), (QGraphicsItem *)0);
5506 QCOMPARE(scene.itemAt(75, 75), (QGraphicsItem *)child2);
5507 QCOMPARE(scene.itemAt(75, 100), (QGraphicsItem *)child1);
5508 QCOMPARE(scene.itemAt(100, 75), (QGraphicsItem *)child1);
5510 QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
5512 QPainter painter(&image);
5513 scene.render(&painter);
5516 QCOMPARE(image.pixel(5, 5), QColor(0, 0, 255).rgba());
5517 QCOMPARE(image.pixel(5, 10), QRgb(0));
5518 QCOMPARE(image.pixel(10, 5), QRgb(0));
5519 QCOMPARE(image.pixel(40, 40), QRgb(0));
5520 QCOMPARE(image.pixel(90, 40), QRgb(0));
5521 QCOMPARE(image.pixel(40, 90), QRgb(0));
5522 QCOMPARE(image.pixel(95, 95), QRgb(0));
5523 QCOMPARE(image.pixel(50, 70), QColor(0, 255, 0).rgba());
5524 QCOMPARE(image.pixel(70, 50), QColor(0, 255, 0).rgba());
5525 QCOMPARE(image.pixel(50, 60), QColor(255, 0, 0).rgba());
5526 QCOMPARE(image.pixel(60, 50), QColor(255, 0, 0).rgba());
5529 void tst_QGraphicsItem::itemClipsChildrenToShape3()
5531 // Construct a scene with nested children, each 50 pixels offset from the elder.
5532 // Set a top-level clipping flag
5533 QGraphicsScene scene;
5534 QGraphicsRectItem *parent = scene.addRect( 0, 0, 150, 150 );
5535 QGraphicsRectItem *child = scene.addRect( 0, 0, 150, 150 );
5536 QGraphicsRectItem *grandchild = scene.addRect( 0, 0, 150, 150 );
5537 child->setParentItem(parent);
5538 grandchild->setParentItem(child);
5539 child->setPos( 50, 50 );
5540 grandchild->setPos( 50, 50 );
5541 parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5543 QCOMPARE(scene.itemAt(25,25), (QGraphicsItem *)parent);
5544 QCOMPARE(scene.itemAt(75,75), (QGraphicsItem *)child);
5545 QCOMPARE(scene.itemAt(125,125), (QGraphicsItem *)grandchild);
5546 QCOMPARE(scene.itemAt(175,175), (QGraphicsItem *)0);
5548 // Move child to fully overlap the parent. The grandchild should
5549 // now occupy two-thirds of the scene
5550 child->prepareGeometryChange();
5551 child->setPos( 0, 0 );
5553 QCOMPARE(scene.itemAt(25,25), (QGraphicsItem *)child);
5554 QCOMPARE(scene.itemAt(75,75), (QGraphicsItem *)grandchild);
5555 QCOMPARE(scene.itemAt(125,125), (QGraphicsItem *)grandchild);
5556 QCOMPARE(scene.itemAt(175,175), (QGraphicsItem *)0);
5559 class MyProxyWidget : public QGraphicsProxyWidget
5562 MyProxyWidget(QGraphicsItem *parent) : QGraphicsProxyWidget(parent)
5567 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
5569 QGraphicsProxyWidget::paint(painter, option, widget);
5575 void tst_QGraphicsItem::itemClipsChildrenToShape4()
5577 QGraphicsScene scene;
5578 QGraphicsView view(&scene);
5580 QGraphicsWidget * outerWidget = new QGraphicsWidget();
5581 outerWidget->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
5582 MyProxyWidget * innerWidget = new MyProxyWidget(outerWidget);
5583 QLabel * label = new QLabel();
5584 label->setText("Welcome back my friends to the show that never ends...");
5585 innerWidget->setWidget(label);
5586 view.resize(300, 300);
5587 scene.addItem(outerWidget);
5588 outerWidget->resize( 200, 100 );
5589 scene.addEllipse( 100, 100, 100, 50 ); // <-- this is important to trigger the right codepath*
5590 //now the label is shown
5591 outerWidget->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false );
5592 QApplication::setActiveWindow(&view);
5594 QTRY_COMPARE(QApplication::activeWindow(), (QWidget *)&view);
5595 QTRY_COMPARE(innerWidget->painted, true);
5598 //#define DEBUG_ITEM_CLIPS_CHILDREN_TO_SHAPE_5
5599 static inline void renderSceneToImage(QGraphicsScene *scene, QImage *image, const QString &filename)
5602 QPainter painter(image);
5603 scene->render(&painter);
5605 #ifdef DEBUG_ITEM_CLIPS_CHILDREN_TO_SHAPE_5
5606 image->save(filename);
5612 void tst_QGraphicsItem::itemClipsChildrenToShape5()
5614 class ParentItem : public QGraphicsRectItem
5617 ParentItem(qreal x, qreal y, qreal width, qreal height)
5618 : QGraphicsRectItem(x, y, width, height) {}
5620 QPainterPath shape() const
5623 path.addRect(50, 50, 200, 200);
5628 ParentItem *parent = new ParentItem(0, 0, 300, 300);
5629 parent->setBrush(Qt::blue);
5630 parent->setOpacity(0.5);
5632 const QRegion parentRegion(0, 0, 300, 300);
5633 const QRegion clippedParentRegion = parentRegion & QRect(50, 50, 200, 200);
5634 QRegion childRegion;
5635 QRegion grandChildRegion;
5637 QGraphicsRectItem *topLeftChild = new QGraphicsRectItem(0, 0, 100, 100);
5638 topLeftChild->setBrush(Qt::red);
5639 topLeftChild->setParentItem(parent);
5640 childRegion += QRect(0, 0, 100, 100);
5642 QGraphicsRectItem *topRightChild = new QGraphicsRectItem(0, 0, 100, 100);
5643 topRightChild->setBrush(Qt::red);
5644 topRightChild->setParentItem(parent);
5645 topRightChild->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5646 topRightChild->setPos(200, 0);
5647 childRegion += QRect(200, 0, 100, 100);
5649 QGraphicsRectItem *topRightGrandChild = new QGraphicsRectItem(0, 0, 100, 100);
5650 topRightGrandChild->setBrush(Qt::green);
5651 topRightGrandChild->setParentItem(topRightChild);
5652 topRightGrandChild->setPos(-40, 40);
5653 grandChildRegion += QRect(200 - 40, 0 + 40, 100, 100) & QRect(200, 0, 100, 100);
5655 QGraphicsRectItem *bottomLeftChild = new QGraphicsRectItem(0, 0, 100, 100);
5656 bottomLeftChild->setBrush(Qt::red);
5657 bottomLeftChild->setParentItem(parent);
5658 bottomLeftChild->setFlag(QGraphicsItem::ItemClipsToShape);
5659 bottomLeftChild->setPos(0, 200);
5660 childRegion += QRect(0, 200, 100, 100);
5662 QGraphicsRectItem *bottomLeftGrandChild = new QGraphicsRectItem(0, 0, 160, 160);
5663 bottomLeftGrandChild->setBrush(Qt::green);
5664 bottomLeftGrandChild->setParentItem(bottomLeftChild);
5665 bottomLeftGrandChild->setFlag(QGraphicsItem::ItemClipsToShape);
5666 bottomLeftGrandChild->setPos(0, -60);
5667 grandChildRegion += QRect(0, 200 - 60, 160, 160);
5669 QGraphicsRectItem *bottomRightChild = new QGraphicsRectItem(0, 0, 100, 100);
5670 bottomRightChild->setBrush(Qt::red);
5671 bottomRightChild->setParentItem(parent);
5672 bottomRightChild->setPos(200, 200);
5673 childRegion += QRect(200, 200, 100, 100);
5675 QPoint controlPoints[17] = {
5676 QPoint(5, 5) , QPoint(95, 5) , QPoint(205, 5) , QPoint(295, 5) ,
5677 QPoint(5, 95) , QPoint(95, 95) , QPoint(205, 95) , QPoint(295, 95) ,
5679 QPoint(5, 205), QPoint(95, 205), QPoint(205, 205), QPoint(295, 205),
5680 QPoint(5, 295), QPoint(95, 295), QPoint(205, 295), QPoint(295, 295),
5683 const QRegion clippedChildRegion = childRegion & QRect(50, 50, 200, 200);
5684 const QRegion clippedGrandChildRegion = grandChildRegion & QRect(50, 50, 200, 200);
5686 QGraphicsScene scene;
5687 scene.addItem(parent);
5688 QImage sceneImage(300, 300, QImage::Format_ARGB32);
5690 #define VERIFY_CONTROL_POINTS(pRegion, cRegion, gRegion) \
5691 for (int i = 0; i < 17; ++i) { \
5692 QPoint controlPoint = controlPoints[i]; \
5693 QRgb pixel = sceneImage.pixel(controlPoint.x(), controlPoint.y()); \
5694 if (pRegion.contains(controlPoint)) \
5695 QVERIFY(qBlue(pixel) != 0); \
5697 QVERIFY(qBlue(pixel) == 0); \
5698 if (cRegion.contains(controlPoint)) \
5699 QVERIFY(qRed(pixel) != 0); \
5701 QVERIFY(qRed(pixel) == 0); \
5702 if (gRegion.contains(controlPoint)) \
5703 QVERIFY(qGreen(pixel) != 0); \
5705 QVERIFY(qGreen(pixel) == 0); \
5708 const QList<QGraphicsItem *> children = parent->childItems();
5709 const int childrenCount = children.count();
5711 for (int i = 0; i < 5; ++i) {
5713 QString childString;
5716 // All children stacked in front.
5717 childString = QLatin1String("ChildrenInFront.png");
5718 foreach (QGraphicsItem *child, children)
5719 child->setFlag(QGraphicsItem::ItemStacksBehindParent, false);
5722 // All children stacked behind.
5723 childString = QLatin1String("ChildrenBehind.png");
5724 foreach (QGraphicsItem *child, children)
5725 child->setFlag(QGraphicsItem::ItemStacksBehindParent, true);
5728 // First half of the children behind, second half in front.
5729 childString = QLatin1String("FirstHalfBehind_SecondHalfInFront.png");
5730 for (int j = 0; j < childrenCount; ++j) {
5731 QGraphicsItem *child = children.at(j);
5732 child->setFlag(QGraphicsItem::ItemStacksBehindParent, (j < childrenCount / 2));
5736 // First half of the children in front, second half behind.
5737 childString = QLatin1String("FirstHalfInFront_SecondHalfBehind.png");
5738 for (int j = 0; j < childrenCount; ++j) {
5739 QGraphicsItem *child = children.at(j);
5740 child->setFlag(QGraphicsItem::ItemStacksBehindParent, (j >= childrenCount / 2));
5744 // Child2 and child4 behind, rest in front.
5745 childString = QLatin1String("Child2And4Behind_RestInFront.png");
5746 for (int j = 0; j < childrenCount; ++j) {
5747 QGraphicsItem *child = children.at(j);
5748 if (j == 1 || j == 3)
5749 child->setFlag(QGraphicsItem::ItemStacksBehindParent, true);
5751 child->setFlag(QGraphicsItem::ItemStacksBehindParent, false);
5755 qFatal("internal error");
5758 // Nothing is clipped.
5759 parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
5760 parent->setFlag(QGraphicsItem::ItemClipsToShape, false);
5761 clipString = QLatin1String("nothingClipped_");
5762 renderSceneToImage(&scene, &sceneImage, clipString + childString);
5763 VERIFY_CONTROL_POINTS(parentRegion, childRegion, grandChildRegion);
5765 // Parent clips children to shape.
5766 parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5767 clipString = QLatin1String("parentClipsChildrenToShape_");
5768 renderSceneToImage(&scene, &sceneImage, clipString + childString);
5769 VERIFY_CONTROL_POINTS(parentRegion, clippedChildRegion, clippedGrandChildRegion);
5771 // Parent clips itself and children to shape.
5772 parent->setFlag(QGraphicsItem::ItemClipsToShape);
5773 clipString = QLatin1String("parentClipsItselfAndChildrenToShape_");
5774 renderSceneToImage(&scene, &sceneImage, clipString + childString);
5775 VERIFY_CONTROL_POINTS(clippedParentRegion, clippedChildRegion, clippedGrandChildRegion);
5777 // Parent clips itself to shape.
5778 parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
5779 clipString = QLatin1String("parentClipsItselfToShape_");
5780 renderSceneToImage(&scene, &sceneImage, clipString + childString);
5781 VERIFY_CONTROL_POINTS(clippedParentRegion, childRegion, grandChildRegion);
5785 void tst_QGraphicsItem::itemClipsTextChildToShape()
5787 // Construct a scene with a rect that clips its children, with one text
5788 // child that has text that exceeds the size of the rect.
5789 QGraphicsScene scene;
5790 QGraphicsItem *rect = scene.addRect(0, 0, 50, 50, QPen(Qt::black), Qt::black);
5791 rect->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5792 QGraphicsTextItem *text = new QGraphicsTextItem("This is a long sentence that's wider than 50 pixels.");
5793 text->setParentItem(rect);
5795 // Render this scene to a transparent image.
5796 QRectF sr = scene.itemsBoundingRect();
5797 QImage image(sr.size().toSize(), QImage::Format_ARGB32_Premultiplied);
5799 QPainter painter(&image);
5800 scene.render(&painter);
5802 // Erase the area immediately underneath the rect.
5803 painter.setCompositionMode(QPainter::CompositionMode_Source);
5804 painter.fillRect(rect->sceneBoundingRect().translated(-sr.topLeft()).adjusted(-0.5, -0.5, 0.5, 0.5),
5808 // Check that you get a truly transparent image back (i.e., the text was
5809 // clipped away, so there should be no trails left after erasing only the
5811 QImage emptyImage(scene.itemsBoundingRect().size().toSize(), QImage::Format_ARGB32_Premultiplied);
5813 QCOMPARE(image, emptyImage);
5816 void tst_QGraphicsItem::itemClippingDiscovery()
5818 // A simple scene with an ellipse parent and two rect children, one a
5819 // child of the other.
5820 QGraphicsScene scene;
5821 QGraphicsEllipseItem *clipItem = scene.addEllipse(0, 0, 100, 100);
5822 QGraphicsRectItem *leftRectItem = scene.addRect(0, 0, 50, 100);
5823 QGraphicsRectItem *rightRectItem = scene.addRect(50, 0, 50, 100);
5824 leftRectItem->setParentItem(clipItem);
5825 rightRectItem->setParentItem(clipItem);
5827 // The rects item are both visible at these points.
5828 QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)leftRectItem);
5829 QCOMPARE(scene.itemAt(90, 90), (QGraphicsItem *)rightRectItem);
5831 // The ellipse clips the rects now.
5832 clipItem->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5834 // The rect items are no longer visible at these points.
5835 QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0);
5836 if (sizeof(qreal) != sizeof(double))
5837 QSKIP("This fails due to internal rounding errors");
5838 QCOMPARE(scene.itemAt(90, 90), (QGraphicsItem *)0);
5841 void tst_QGraphicsItem::ancestorFlags()
5843 QGraphicsItem *level1 = new QGraphicsRectItem;
5844 QGraphicsItem *level21 = new QGraphicsRectItem;
5845 level21->setParentItem(level1);
5846 QGraphicsItem *level22 = new QGraphicsRectItem;
5847 level22->setParentItem(level1);
5848 QGraphicsItem *level31 = new QGraphicsRectItem;
5849 level31->setParentItem(level21);
5850 QGraphicsItem *level32 = new QGraphicsRectItem;
5851 level32->setParentItem(level21);
5853 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5854 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5855 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5856 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
5857 QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
5859 // HandlesChildEvents: 1) Root level sets a flag
5860 level1->setHandlesChildEvents(true);
5861 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5862 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5863 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5864 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5865 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5867 // HandlesChildEvents: 2) Root level set it again
5868 level1->setHandlesChildEvents(true);
5869 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5870 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5871 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5872 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5873 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5875 // HandlesChildEvents: 3) Root level unsets a flag
5876 level1->setHandlesChildEvents(false);
5877 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5878 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5879 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5880 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
5881 QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
5883 // HandlesChildEvents: 4) Child item sets a flag
5884 level21->setHandlesChildEvents(true);
5885 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5886 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5887 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5888 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5889 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5891 // HandlesChildEvents: 5) Parent item sets a flag
5892 level1->setHandlesChildEvents(true);
5893 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5894 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5895 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5896 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5897 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5899 // HandlesChildEvents: 6) Child item unsets a flag
5900 level21->setHandlesChildEvents(false);
5901 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5902 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5903 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5904 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5905 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5907 // HandlesChildEvents: 7) Parent item unsets a flag
5908 level21->setHandlesChildEvents(true);
5909 level1->setHandlesChildEvents(false);
5910 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5911 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5912 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5913 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5914 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5916 // Reparent the child to root
5917 level21->setParentItem(0);
5918 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5919 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5920 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5921 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5923 // Reparent the child to level1 again.
5924 level1->setHandlesChildEvents(true);
5925 level21->setParentItem(level1);
5926 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5927 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5928 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5929 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5930 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5932 // Reparenting level31 back to level1.
5933 level31->setParentItem(level1);
5934 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5935 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5936 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5937 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5938 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5940 // Reparenting level31 back to level21.
5941 level31->setParentItem(0);
5942 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
5943 level31->setParentItem(level21);
5944 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5945 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5946 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5947 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5948 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5950 // Level1 doesn't handle child events
5951 level1->setHandlesChildEvents(false);
5952 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5953 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5954 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5955 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5956 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5958 // Nobody handles child events
5959 level21->setHandlesChildEvents(false);
5961 for (int i = 0; i < 2; ++i) {
5962 QGraphicsItem::GraphicsItemFlag flag = !i ? QGraphicsItem::ItemClipsChildrenToShape
5963 : QGraphicsItem::ItemIgnoresTransformations;
5964 int ancestorFlag = !i ? QGraphicsItemPrivate::AncestorClipsChildren
5965 : QGraphicsItemPrivate::AncestorIgnoresTransformations;
5967 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5968 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5969 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5970 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
5971 QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
5973 // HandlesChildEvents: 1) Root level sets a flag
5974 level1->setFlag(flag, true);
5975 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5976 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
5977 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
5978 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
5979 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
5981 // HandlesChildEvents: 2) Root level set it again
5982 level1->setFlag(flag, true);
5983 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5984 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
5985 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
5986 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
5987 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
5989 // HandlesChildEvents: 3) Root level unsets a flag
5990 level1->setFlag(flag, false);
5991 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5992 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5993 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5994 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
5995 QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
5997 // HandlesChildEvents: 4) Child item sets a flag
5998 level21->setFlag(flag, true);
5999 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6000 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
6001 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
6002 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6003 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6005 // HandlesChildEvents: 5) Parent item sets a flag
6006 level1->setFlag(flag, true);
6007 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6008 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
6009 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
6010 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6011 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6013 // HandlesChildEvents: 6) Child item unsets a flag
6014 level21->setFlag(flag, false);
6015 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6016 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
6017 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
6018 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6019 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6021 // HandlesChildEvents: 7) Parent item unsets a flag
6022 level21->setFlag(flag, true);
6023 level1->setFlag(flag, false);
6024 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6025 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
6026 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
6027 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6028 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6030 // Reparent the child to root
6031 level21->setParentItem(0);
6032 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
6033 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
6034 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6035 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6037 // Reparent the child to level1 again.
6038 level1->setFlag(flag, true);
6039 level21->setParentItem(level1);
6040 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6041 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
6042 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
6043 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6044 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6046 // Reparenting level31 back to level1.
6047 level31->setParentItem(level1);
6048 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6049 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
6050 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
6051 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6052 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6054 // Reparenting level31 back to level21.
6055 level31->setParentItem(0);
6056 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
6057 level31->setParentItem(level21);
6058 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6059 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
6060 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
6061 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6062 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6064 // Level1 doesn't handle child events
6065 level1->setFlag(flag, false);
6066 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6067 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
6068 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
6069 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6070 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6072 // Nobody handles child events
6073 level21->setFlag(flag, false);
6074 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6075 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
6076 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
6077 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
6078 QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
6084 void tst_QGraphicsItem::untransformable()
6086 QGraphicsItem *item1 = new QGraphicsEllipseItem(QRectF(-50, -50, 100, 100));
6087 item1->setZValue(1);
6088 item1->setFlag(QGraphicsItem::ItemIgnoresTransformations);
6090 ((QGraphicsEllipseItem *)item1)->setBrush(Qt::red);
6092 QGraphicsItem *item2 = new QGraphicsEllipseItem(QRectF(-50, -50, 100, 100));
6093 item2->setParentItem(item1);
6095 item2->setPos(100, 0);
6096 ((QGraphicsEllipseItem *)item2)->setBrush(Qt::green);
6098 QGraphicsItem *item3 = new QGraphicsEllipseItem(QRectF(-50, -50, 100, 100));
6099 item3->setParentItem(item2);
6100 item3->setPos(100, 0);
6101 ((QGraphicsEllipseItem *)item3)->setBrush(Qt::blue);
6103 QGraphicsScene scene(-500, -500, 1000, 1000);
6104 scene.addItem(item1);
6107 QGraphicsView view(&scene,&topLevel);
6108 view.resize(300, 300);
6111 view.centerOn(0, 0);
6113 // Painting with the DiagCrossPattern is really slow on Mac
6114 // when zoomed out. (The test times out). Task to fix is 155567.
6115 #if !defined(Q_OS_MAC) || 1
6116 view.setBackgroundBrush(QBrush(Qt::black, Qt::DiagCrossPattern));
6119 QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
6121 for (int i = 0; i < 10; ++i) {
6122 QPoint center = view.viewport()->rect().center();
6123 QCOMPARE(view.itemAt(center), item1);
6124 QCOMPARE(view.itemAt(center - QPoint(40, 0)), item1);
6125 QCOMPARE(view.itemAt(center - QPoint(-40, 0)), item1);
6126 QCOMPARE(view.itemAt(center - QPoint(0, 40)), item1);
6127 QCOMPARE(view.itemAt(center - QPoint(0, -40)), item1);
6129 center += QPoint(70, 70);
6130 QCOMPARE(view.itemAt(center - QPoint(40, 0)), item2);
6131 QCOMPARE(view.itemAt(center - QPoint(-40, 0)), item2);
6132 QCOMPARE(view.itemAt(center - QPoint(0, 40)), item2);
6133 QCOMPARE(view.itemAt(center - QPoint(0, -40)), item2);
6135 center += QPoint(0, 100);
6136 QCOMPARE(view.itemAt(center - QPoint(40, 0)), item3);
6137 QCOMPARE(view.itemAt(center - QPoint(-40, 0)), item3);
6138 QCOMPARE(view.itemAt(center - QPoint(0, 40)), item3);
6139 QCOMPARE(view.itemAt(center - QPoint(0, -40)), item3);
6141 view.scale(0.5, 0.5);
6143 view.shear(qreal(0.01), qreal(0.01));
6144 view.translate(10, 10);
6149 class ContextMenuItem : public QGraphicsRectItem
6153 : ignoreEvent(true), gotEvent(false), eventWasAccepted(false)
6157 bool eventWasAccepted;
6159 void contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
6162 eventWasAccepted = event->isAccepted();
6168 void tst_QGraphicsItem::contextMenuEventPropagation()
6170 ContextMenuItem *bottomItem = new ContextMenuItem;
6171 bottomItem->setRect(0, 0, 100, 100);
6172 ContextMenuItem *topItem = new ContextMenuItem;
6173 topItem->setParentItem(bottomItem);
6174 topItem->setRect(0, 0, 100, 100);
6176 QGraphicsScene scene;
6178 QGraphicsView view(&scene);
6179 view.setAlignment(Qt::AlignLeft | Qt::AlignTop);
6181 view.resize(200, 200);
6182 QVERIFY(QTest::qWaitForWindowExposed(&view));
6185 QContextMenuEvent event(QContextMenuEvent::Mouse, QPoint(10, 10),
6186 view.viewport()->mapToGlobal(QPoint(10, 10)));
6188 QApplication::sendEvent(view.viewport(), &event);
6189 QVERIFY(!event.isAccepted());
6191 scene.addItem(bottomItem);
6192 topItem->ignoreEvent = true;
6193 bottomItem->ignoreEvent = true;
6195 QApplication::sendEvent(view.viewport(), &event);
6196 QVERIFY(!event.isAccepted());
6197 QCOMPARE(topItem->gotEvent, true);
6198 QCOMPARE(topItem->eventWasAccepted, true);
6199 QCOMPARE(bottomItem->gotEvent, true);
6200 QCOMPARE(bottomItem->eventWasAccepted, true);
6202 topItem->ignoreEvent = false;
6203 topItem->gotEvent = false;
6204 bottomItem->gotEvent = false;
6206 QApplication::sendEvent(view.viewport(), &event);
6207 QVERIFY(event.isAccepted());
6208 QCOMPARE(topItem->gotEvent, true);
6209 QCOMPARE(bottomItem->gotEvent, false);
6210 QCOMPARE(topItem->eventWasAccepted, true);
6213 void tst_QGraphicsItem::itemIsMovable()
6215 QGraphicsRectItem *rect = new QGraphicsRectItem(-50, -50, 100, 100);
6216 rect->setFlag(QGraphicsItem::ItemIsMovable);
6218 QGraphicsScene scene;
6219 scene.addItem(rect);
6222 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
6223 event.setButton(Qt::LeftButton);
6224 event.setButtons(Qt::LeftButton);
6225 qApp->sendEvent(&scene, &event);
6228 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
6229 event.setButton(Qt::LeftButton);
6230 event.setButtons(Qt::LeftButton);
6231 qApp->sendEvent(&scene, &event);
6233 QCOMPARE(rect->pos(), QPointF(0, 0));
6235 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
6236 event.setButtons(Qt::LeftButton);
6237 event.setScenePos(QPointF(10, 10));
6238 qApp->sendEvent(&scene, &event);
6240 QCOMPARE(rect->pos(), QPointF(10, 10));
6242 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
6243 event.setButtons(Qt::RightButton);
6244 event.setScenePos(QPointF(20, 20));
6245 qApp->sendEvent(&scene, &event);
6247 QCOMPARE(rect->pos(), QPointF(10, 10));
6249 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
6250 event.setButtons(Qt::LeftButton);
6251 event.setScenePos(QPointF(30, 30));
6252 qApp->sendEvent(&scene, &event);
6254 QCOMPARE(rect->pos(), QPointF(30, 30));
6257 class ItemAddScene : public QGraphicsScene
6263 QTimer::singleShot(500, this, SLOT(newTextItem()));
6270 QGraphicsItem *item = new QGraphicsTextItem("This item will not ensure that it's visible", 0);
6271 item->setPos(.0, .0);
6276 void tst_QGraphicsItem::task141694_textItemEnsureVisible()
6279 scene.setSceneRect(-1000, -1000, 2000, 2000);
6281 QGraphicsView view(&scene);
6282 view.setFixedSize(200, 200);
6284 QVERIFY(QTest::qWaitForWindowExposed(&view));
6286 view.ensureVisible(-1000, -1000, 5, 5);
6287 int hscroll = view.horizontalScrollBar()->value();
6288 int vscroll = view.verticalScrollBar()->value();
6292 // This should not cause the view to scroll
6293 QTRY_COMPARE(view.horizontalScrollBar()->value(), hscroll);
6294 QCOMPARE(view.verticalScrollBar()->value(), vscroll);
6297 void tst_QGraphicsItem::task128696_textItemEnsureMovable()
6299 QGraphicsTextItem *item = new QGraphicsTextItem;
6300 item->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
6301 item->setTextInteractionFlags(Qt::TextEditorInteraction);
6302 item->setPlainText("abc de\nf ghi\n j k l");
6304 QGraphicsScene scene;
6305 scene.setSceneRect(-100, -100, 200, 200);
6306 scene.addItem(item);
6308 QGraphicsView view(&scene);
6309 view.setFixedSize(200, 200);
6312 QGraphicsSceneMouseEvent event1(QEvent::GraphicsSceneMousePress);
6313 event1.setScenePos(QPointF(0, 0));
6314 event1.setButton(Qt::LeftButton);
6315 event1.setButtons(Qt::LeftButton);
6316 QApplication::sendEvent(&scene, &event1);
6317 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
6319 QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove);
6320 event2.setScenePos(QPointF(10, 10));
6321 event2.setButton(Qt::LeftButton);
6322 event2.setButtons(Qt::LeftButton);
6323 QApplication::sendEvent(&scene, &event2);
6324 QCOMPARE(item->pos(), QPointF(10, 10));
6327 void tst_QGraphicsItem::task177918_lineItemUndetected()
6329 QGraphicsScene scene;
6330 QGraphicsLineItem *line = scene.addLine(10, 10, 10, 10);
6331 QCOMPARE(line->boundingRect(), QRectF(10, 10, 0, 0));
6333 QVERIFY(!scene.items(9, 9, 2, 2, Qt::IntersectsItemShape).isEmpty());
6334 QVERIFY(!scene.items(9, 9, 2, 2, Qt::ContainsItemShape).isEmpty());
6335 QVERIFY(!scene.items(9, 9, 2, 2, Qt::IntersectsItemBoundingRect).isEmpty());
6336 QVERIFY(!scene.items(9, 9, 2, 2, Qt::ContainsItemBoundingRect).isEmpty());
6339 void tst_QGraphicsItem::task240400_clickOnTextItem_data()
6341 QTest::addColumn<int>("flags");
6342 QTest::addColumn<int>("textFlags");
6343 QTest::newRow("editor, noflags") << 0 << int(Qt::TextEditorInteraction);
6344 QTest::newRow("editor, movable") << int(QGraphicsItem::ItemIsMovable) << int(Qt::TextEditorInteraction);
6345 QTest::newRow("editor, selectable") << int(QGraphicsItem::ItemIsSelectable) << int(Qt::TextEditorInteraction);
6346 QTest::newRow("editor, movable | selectable") << int(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable)
6347 << int(Qt::TextEditorInteraction);
6348 QTest::newRow("noninteractive, noflags") << 0 << int(Qt::NoTextInteraction);
6349 QTest::newRow("noninteractive, movable") << int(QGraphicsItem::ItemIsMovable) << int(Qt::NoTextInteraction);
6350 QTest::newRow("noninteractive, selectable") << int(QGraphicsItem::ItemIsSelectable) << int(Qt::NoTextInteraction);
6351 QTest::newRow("noninteractive, movable | selectable") << int(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable)
6352 << int(Qt::NoTextInteraction);
6355 void tst_QGraphicsItem::task240400_clickOnTextItem()
6358 QFETCH(int, textFlags);
6360 QGraphicsScene scene;
6361 QEvent activate(QEvent::WindowActivate);
6362 QApplication::sendEvent(&scene, &activate);
6364 QGraphicsTextItem *item = scene.addText("Hello");
6365 item->setFlags(QGraphicsItem::GraphicsItemFlags(flags));
6366 item->setTextInteractionFlags(Qt::TextInteractionFlags(textFlags));
6367 bool focusable = (item->flags() & QGraphicsItem::ItemIsFocusable);
6368 QVERIFY(textFlags ? focusable : !focusable);
6370 int column = item->textCursor().columnNumber();
6371 QCOMPARE(column, 0);
6373 QVERIFY(!item->hasFocus());
6375 // Click in the top-left corner of the item
6377 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
6378 event.setScenePos(item->sceneBoundingRect().topLeft() + QPointF(0.1, 0.1));
6379 event.setButton(Qt::LeftButton);
6380 event.setButtons(Qt::LeftButton);
6381 QApplication::sendEvent(&scene, &event);
6383 if (flags || textFlags)
6384 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
6386 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
6388 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
6389 event.setScenePos(item->sceneBoundingRect().topLeft() + QPointF(0.1, 0.1));
6390 event.setButton(Qt::LeftButton);
6391 event.setButtons(0);
6392 QApplication::sendEvent(&scene, &event);
6395 QVERIFY(item->hasFocus());
6397 QVERIFY(!item->hasFocus());
6398 QVERIFY(!scene.mouseGrabberItem());
6399 bool selectable = (flags & QGraphicsItem::ItemIsSelectable);
6400 QVERIFY(selectable ? item->isSelected() : !item->isSelected());
6402 // Now click in the middle and check that the cursor moved.
6404 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
6405 event.setScenePos(item->sceneBoundingRect().center());
6406 event.setButton(Qt::LeftButton);
6407 event.setButtons(Qt::LeftButton);
6408 QApplication::sendEvent(&scene, &event);
6410 if (flags || textFlags)
6411 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
6413 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
6415 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
6416 event.setScenePos(item->sceneBoundingRect().center());
6417 event.setButton(Qt::LeftButton);
6418 event.setButtons(0);
6419 QApplication::sendEvent(&scene, &event);
6422 QVERIFY(item->hasFocus());
6424 QVERIFY(!item->hasFocus());
6425 QVERIFY(!scene.mouseGrabberItem());
6427 QVERIFY(selectable ? item->isSelected() : !item->isSelected());
6430 if (textFlags & Qt::TextEditorInteraction)
6431 QVERIFY(item->textCursor().columnNumber() > column);
6433 QCOMPARE(item->textCursor().columnNumber(), 0);
6436 class TextItem : public QGraphicsSimpleTextItem
6439 TextItem(const QString& text) : QGraphicsSimpleTextItem(text)
6444 void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget)
6447 QGraphicsSimpleTextItem::paint(painter, option, widget);
6453 void tst_QGraphicsItem::ensureUpdateOnTextItem()
6455 QGraphicsScene scene;
6456 QGraphicsView view(&scene);
6458 QVERIFY(QTest::qWaitForWindowExposed(&view));
6460 TextItem *text1 = new TextItem(QLatin1String("123"));
6461 scene.addItem(text1);
6462 qApp->processEvents();
6463 QTRY_COMPARE(text1->updates,1);
6465 //same bouding rect but we have to update
6466 text1->setText(QLatin1String("321"));
6467 qApp->processEvents();
6468 QTRY_COMPARE(text1->updates,2);
6471 void tst_QGraphicsItem::task243707_addChildBeforeParent()
6473 // Task reports that adding the child before the parent leads to an
6474 // inconsistent internal state that can cause a crash. This test shows
6476 QGraphicsScene scene;
6477 QGraphicsWidget *widget = new QGraphicsWidget;
6478 QGraphicsWidget *widget2 = new QGraphicsWidget(widget);
6479 scene.addItem(widget2);
6480 QVERIFY(!widget2->parentItem());
6481 scene.addItem(widget);
6482 QVERIFY(!widget->commonAncestorItem(widget2));
6483 QVERIFY(!widget2->commonAncestorItem(widget));
6486 void tst_QGraphicsItem::task197802_childrenVisibility()
6488 QGraphicsScene scene;
6489 QGraphicsRectItem item(QRectF(0,0,20,20));
6491 QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(0,0,10,10), &item);
6492 scene.addItem(&item);
6494 //freshly created: both visible
6495 QVERIFY(item.isVisible());
6496 QVERIFY(item2->isVisible());
6498 //hide child: parent visible, child not
6500 QVERIFY(item.isVisible());
6501 QVERIFY(!item2->isVisible());
6503 //hide parent: parent and child invisible
6505 QVERIFY(!item.isVisible());
6506 QVERIFY(!item2->isVisible());
6508 //ask to show the child: parent and child invisible anyways
6510 QVERIFY(!item.isVisible());
6511 QVERIFY(!item2->isVisible());
6513 //show the parent: both parent and child visible
6515 QVERIFY(item.isVisible());
6516 QVERIFY(item2->isVisible());
6521 void tst_QGraphicsItem::boundingRegion_data()
6523 QTest::addColumn<QLineF>("line");
6524 QTest::addColumn<qreal>("granularity");
6525 QTest::addColumn<QTransform>("transform");
6526 QTest::addColumn<QRegion>("expectedRegion");
6528 QTest::newRow("(0, 0, 10, 10) | 0.0 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 10, 10) << qreal(0.0) << QTransform()
6529 << QRegion(QRect(0, 0, 10, 10));
6530 QTest::newRow("(0, 0, 10, 0) | 0.0 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 10, 0) << qreal(0.0) << QTransform()
6531 << QRegion(QRect(0, 0, 10, 1));
6532 QTest::newRow("(0, 0, 10, 0) | 0.5 | identity | {(0, 0, 10, 1)}") << QLineF(0, 0, 10, 0) << qreal(0.5) << QTransform()
6533 << QRegion(QRect(0, 0, 10, 1));
6534 QTest::newRow("(0, 0, 10, 0) | 1.0 | identity | {(0, 0, 10, 1)}") << QLineF(0, 0, 10, 0) << qreal(1.0) << QTransform()
6535 << QRegion(QRect(0, 0, 10, 1));
6536 QTest::newRow("(0, 0, 0, 10) | 0.0 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 0, 10) << qreal(0.0) << QTransform()
6537 << QRegion(QRect(0, 0, 1, 10));
6538 QTest::newRow("(0, 0, 0, 10) | 0.5 | identity | {(0, 0, 1, 10)}") << QLineF(0, 0, 0, 10) << qreal(0.5) << QTransform()
6539 << QRegion(QRect(0, 0, 1, 10));
6540 QTest::newRow("(0, 0, 0, 10) | 1.0 | identity | {(0, 0, 1, 10)}") << QLineF(0, 0, 0, 10) << qreal(1.0) << QTransform()
6541 << QRegion(QRect(0, 0, 1, 10));
6544 void tst_QGraphicsItem::boundingRegion()
6546 QFETCH(QLineF, line);
6547 QFETCH(qreal, granularity);
6548 QFETCH(QTransform, transform);
6549 QFETCH(QRegion, expectedRegion);
6551 QGraphicsLineItem item(line);
6552 item.setPen(QPen(Qt::black, 0));
6553 QCOMPARE(item.boundingRegionGranularity(), qreal(0.0));
6554 item.setBoundingRegionGranularity(granularity);
6555 QCOMPARE(item.boundingRegionGranularity(), granularity);
6556 QCOMPARE(item.boundingRegion(transform), expectedRegion);
6559 void tst_QGraphicsItem::itemTransform_parentChild()
6561 QGraphicsScene scene;
6562 QGraphicsItem *parent = scene.addRect(0, 0, 100, 100);
6563 QGraphicsItem *child = scene.addRect(0, 0, 100, 100);
6564 child->setParentItem(parent);
6565 child->setPos(10, 10);
6569 QCOMPARE(child->itemTransform(parent).map(QPointF(10, 10)), QPointF(-10, 30));
6570 QCOMPARE(parent->itemTransform(child).map(QPointF(-10, 30)), QPointF(10, 10));
6573 void tst_QGraphicsItem::itemTransform_siblings()
6575 QGraphicsScene scene;
6576 QGraphicsItem *parent = scene.addRect(0, 0, 100, 100);
6577 QGraphicsItem *brother = scene.addRect(0, 0, 100, 100);
6578 QGraphicsItem *sister = scene.addRect(0, 0, 100, 100);
6579 parent->scale(10, 5);
6580 parent->rotate(-180);
6581 parent->shear(2, 3);
6583 brother->setParentItem(parent);
6584 sister->setParentItem(parent);
6586 brother->setPos(10, 10);
6587 brother->scale(2, 2);
6588 brother->rotate(90);
6589 sister->setPos(10, 10);
6590 sister->scale(2, 2);
6593 QCOMPARE(brother->itemTransform(sister).map(QPointF(10, 10)), QPointF(10, 10));
6594 QCOMPARE(sister->itemTransform(brother).map(QPointF(10, 10)), QPointF(10, 10));
6597 void tst_QGraphicsItem::itemTransform_unrelated()
6599 QGraphicsScene scene;
6600 QGraphicsItem *stranger1 = scene.addRect(0, 0, 100, 100);
6601 QGraphicsItem *stranger2 = scene.addRect(0, 0, 100, 100);
6602 stranger1->setPos(10, 10);
6603 stranger1->scale(2, 2);
6604 stranger1->rotate(90);
6605 stranger2->setPos(10, 10);
6606 stranger2->scale(2, 2);
6607 stranger2->rotate(90);
6609 QCOMPARE(stranger1->itemTransform(stranger2).map(QPointF(10, 10)), QPointF(10, 10));
6610 QCOMPARE(stranger2->itemTransform(stranger1).map(QPointF(10, 10)), QPointF(10, 10));
6613 void tst_QGraphicsItem::opacity_data()
6615 QTest::addColumn<qreal>("p_opacity");
6616 QTest::addColumn<int>("p_opacityFlags");
6617 QTest::addColumn<qreal>("c1_opacity");
6618 QTest::addColumn<int>("c1_opacityFlags");
6619 QTest::addColumn<qreal>("c2_opacity");
6620 QTest::addColumn<int>("c2_opacityFlags");
6621 QTest::addColumn<qreal>("p_effectiveOpacity");
6622 QTest::addColumn<qreal>("c1_effectiveOpacity");
6623 QTest::addColumn<qreal>("c2_effectiveOpacity");
6624 QTest::addColumn<qreal>("c3_effectiveOpacity");
6626 // Modify the opacity and see how it propagates
6627 QTest::newRow("A: 1.0 0 1.0 0 1.0 1.0 1.0 1.0 1.0") << qreal(1.0) << 0 << qreal(1.0) << 0 << qreal(1.0) << 0
6628 << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6629 QTest::newRow("B: 0.5 0 1.0 0 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 << qreal(1.0) << 0 << qreal(1.0) << 0
6630 << qreal(0.5) << qreal(0.5) << qreal(0.5) << qreal(0.5);
6631 QTest::newRow("C: 0.5 0 0.1 0 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 << qreal(0.1) << 0 << qreal(1.0) << 0
6632 << qreal(0.5) << qreal(0.05) << qreal(0.05) << qreal(0.05);
6633 QTest::newRow("D: 0.0 0 1.0 0 1.0 1.0 1.0 1.0 1.0") << qreal(0.0) << 0 << qreal(1.0) << 0 << qreal(1.0) << 0
6634 << qreal(0.0) << qreal(0.0) << qreal(0.0) << qreal(0.0);
6636 // Parent doesn't propagate to children - now modify the opacity and see how it propagates
6637 int flags = QGraphicsItem::ItemDoesntPropagateOpacityToChildren;
6638 QTest::newRow("E: 1.0 2 1.0 0 1.0 1.0 1.0 1.0 1.0") << qreal(1.0) << flags << qreal(1.0) << 0 << qreal(1.0) << 0
6639 << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6640 QTest::newRow("F: 0.5 2 1.0 0 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << flags << qreal(1.0) << 0 << qreal(1.0) << 0
6641 << qreal(0.5) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6642 QTest::newRow("G: 0.5 2 0.1 0 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << flags << qreal(0.1) << 0 << qreal(1.0) << 0
6643 << qreal(0.5) << qreal(0.1) << qreal(0.1) << qreal(0.1);
6644 QTest::newRow("H: 0.0 2 1.0 0 1.0 1.0 1.0 1.0 1.0") << qreal(0.0) << flags << qreal(1.0) << 0 << qreal(1.0) << 0
6645 << qreal(0.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6647 // Child ignores parent - now modify the opacity and see how it propagates
6648 flags = QGraphicsItem::ItemIgnoresParentOpacity;
6649 QTest::newRow("I: 1.0 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(1.0) << 0 << qreal(1.0) << flags << qreal(1.0) << 0
6650 << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6651 QTest::newRow("J: 1.0 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 << qreal(0.5) << flags << qreal(0.5) << 0
6652 << qreal(0.5) << qreal(0.5) << qreal(0.25) << qreal(0.25);
6653 QTest::newRow("K: 1.0 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.2) << 0 << qreal(0.2) << flags << qreal(0.2) << 0
6654 << qreal(0.2) << qreal(0.2) << qreal(0.04) << qreal(0.04);
6655 QTest::newRow("L: 1.0 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.0) << 0 << qreal(0.0) << flags << qreal(0.0) << 0
6656 << qreal(0.0) << qreal(0.0) << qreal(0.0) << qreal(0.0);
6658 // Child ignores parent and doesn't propagate - now modify the opacity and see how it propagates
6659 flags = QGraphicsItem::ItemIgnoresParentOpacity | QGraphicsItem::ItemDoesntPropagateOpacityToChildren;
6660 QTest::newRow("M: 1.0 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(1.0) << 0 // p
6661 << qreal(1.0) << flags // c1 (no prop)
6662 << qreal(1.0) << 0 // c2
6663 << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6664 QTest::newRow("M: 0.5 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 // p
6665 << qreal(1.0) << flags // c1 (no prop)
6666 << qreal(1.0) << 0 // c2
6667 << qreal(0.5) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6668 QTest::newRow("M: 0.5 0 0.5 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 // p
6669 << qreal(0.5) << flags // c1 (no prop)
6670 << qreal(1.0) << 0 // c2
6671 << qreal(0.5) << qreal(0.5) << qreal(1.0) << qreal(1.0);
6672 QTest::newRow("M: 0.5 0 0.5 1 0.5 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 // p
6673 << qreal(0.5) << flags // c1 (no prop)
6674 << qreal(0.5) << 0 // c2
6675 << qreal(0.5) << qreal(0.5) << qreal(0.5) << qreal(0.5);
6676 QTest::newRow("M: 1.0 0 0.5 1 0.5 1.0 1.0 1.0 1.0") << qreal(1.0) << 0 // p
6677 << qreal(0.5) << flags // c1 (no prop)
6678 << qreal(0.5) << 0 // c2
6679 << qreal(1.0) << qreal(0.5) << qreal(0.5) << qreal(0.5);
6682 void tst_QGraphicsItem::opacity()
6684 QFETCH(qreal, p_opacity);
6685 QFETCH(int, p_opacityFlags);
6686 QFETCH(qreal, p_effectiveOpacity);
6687 QFETCH(qreal, c1_opacity);
6688 QFETCH(int, c1_opacityFlags);
6689 QFETCH(qreal, c1_effectiveOpacity);
6690 QFETCH(qreal, c2_opacity);
6691 QFETCH(int, c2_opacityFlags);
6692 QFETCH(qreal, c2_effectiveOpacity);
6693 QFETCH(qreal, c3_effectiveOpacity);
6695 QGraphicsRectItem *p = new QGraphicsRectItem;
6696 QGraphicsRectItem *c1 = new QGraphicsRectItem(p);
6697 QGraphicsRectItem *c2 = new QGraphicsRectItem(c1);
6698 QGraphicsRectItem *c3 = new QGraphicsRectItem(c2);
6700 QCOMPARE(p->opacity(), qreal(1.0));
6701 QCOMPARE(p->effectiveOpacity(), qreal(1.0));
6702 int opacityMask = QGraphicsItem::ItemIgnoresParentOpacity | QGraphicsItem::ItemDoesntPropagateOpacityToChildren;
6703 QVERIFY(!(p->flags() & opacityMask));
6705 p->setOpacity(p_opacity);
6706 c1->setOpacity(c1_opacity);
6707 c2->setOpacity(c2_opacity);
6708 p->setFlags(QGraphicsItem::GraphicsItemFlags(p->flags() | p_opacityFlags));
6709 c1->setFlags(QGraphicsItem::GraphicsItemFlags(c1->flags() | c1_opacityFlags));
6710 c2->setFlags(QGraphicsItem::GraphicsItemFlags(c2->flags() | c2_opacityFlags));
6712 QCOMPARE(int(p->flags() & opacityMask), p_opacityFlags);
6713 QCOMPARE(int(c1->flags() & opacityMask), c1_opacityFlags);
6714 QCOMPARE(int(c2->flags() & opacityMask), c2_opacityFlags);
6715 QCOMPARE(p->opacity(), p_opacity);
6716 QCOMPARE(p->effectiveOpacity(), p_effectiveOpacity);
6717 QCOMPARE(c1->effectiveOpacity(), c1_effectiveOpacity);
6718 QCOMPARE(c2->effectiveOpacity(), c2_effectiveOpacity);
6719 QCOMPARE(c3->effectiveOpacity(), c3_effectiveOpacity);
6722 void tst_QGraphicsItem::opacity2()
6724 EventTester *parent = new EventTester;
6725 EventTester *child = new EventTester(parent);
6726 EventTester *grandChild = new EventTester(child);
6728 QGraphicsScene scene;
6729 scene.addItem(parent);
6731 MyGraphicsView view(&scene);
6733 QVERIFY(QTest::qWaitForWindowActive(&view));
6734 QTRY_VERIFY(view.repaints >= 1);
6736 #define RESET_REPAINT_COUNTERS \
6737 parent->repaints = 0; \
6738 child->repaints = 0; \
6739 grandChild->repaints = 0; \
6742 RESET_REPAINT_COUNTERS
6744 child->setOpacity(0.0);
6746 QTRY_COMPARE(view.repaints, 1);
6747 QCOMPARE(parent->repaints, 1);
6748 QCOMPARE(child->repaints, 0);
6749 QCOMPARE(grandChild->repaints, 0);
6751 RESET_REPAINT_COUNTERS
6753 child->setOpacity(1.0);
6755 QTRY_COMPARE(view.repaints, 1);
6756 QCOMPARE(parent->repaints, 1);
6757 QCOMPARE(child->repaints, 1);
6758 QCOMPARE(grandChild->repaints, 1);
6760 RESET_REPAINT_COUNTERS
6762 parent->setOpacity(0.0);
6764 QTRY_COMPARE(view.repaints, 1);
6765 QCOMPARE(parent->repaints, 0);
6766 QCOMPARE(child->repaints, 0);
6767 QCOMPARE(grandChild->repaints, 0);
6769 RESET_REPAINT_COUNTERS
6771 parent->setOpacity(1.0);
6773 QTRY_COMPARE(view.repaints, 1);
6774 QCOMPARE(parent->repaints, 1);
6775 QCOMPARE(child->repaints, 1);
6776 QCOMPARE(grandChild->repaints, 1);
6778 grandChild->setFlag(QGraphicsItem::ItemIgnoresParentOpacity);
6779 RESET_REPAINT_COUNTERS
6781 child->setOpacity(0.0);
6783 QTRY_COMPARE(view.repaints, 1);
6784 QCOMPARE(parent->repaints, 1);
6785 QCOMPARE(child->repaints, 0);
6786 QCOMPARE(grandChild->repaints, 1);
6788 RESET_REPAINT_COUNTERS
6790 child->setOpacity(0.0); // Already 0.0; no change.
6792 QTRY_COMPARE(view.repaints, 0);
6793 QCOMPARE(parent->repaints, 0);
6794 QCOMPARE(child->repaints, 0);
6795 QCOMPARE(grandChild->repaints, 0);
6798 void tst_QGraphicsItem::opacityZeroUpdates()
6800 EventTester *parent = new EventTester;
6801 EventTester *child = new EventTester(parent);
6803 child->setPos(10, 10);
6805 QGraphicsScene scene;
6806 scene.addItem(parent);
6808 MyGraphicsView view(&scene);
6810 QVERIFY(QTest::qWaitForWindowActive(&view));
6811 QTRY_VERIFY(view.repaints > 0);
6814 parent->setOpacity(0.0);
6818 // transforming items bounding rect to view coordinates
6819 const QRect childDeviceBoundingRect = child->deviceTransform(view.viewportTransform())
6820 .mapRect(child->boundingRect()).toRect();
6821 const QRect parentDeviceBoundingRect = parent->deviceTransform(view.viewportTransform())
6822 .mapRect(parent->boundingRect()).toRect();
6824 QRegion expectedRegion = parentDeviceBoundingRect.adjusted(-2, -2, 2, 2);
6825 expectedRegion += childDeviceBoundingRect.adjusted(-2, -2, 2, 2);
6827 COMPARE_REGIONS(view.paintedRegion, expectedRegion);
6830 class StacksBehindParentHelper : public QGraphicsRectItem
6833 StacksBehindParentHelper(QList<QGraphicsItem *> *paintedItems, const QRectF &rect, QGraphicsItem *parent = 0)
6834 : QGraphicsRectItem(rect, parent), paintedItems(paintedItems)
6837 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
6839 QGraphicsRectItem::paint(painter, option, widget);
6840 paintedItems->append(this);
6844 QList<QGraphicsItem *> *paintedItems;
6847 void tst_QGraphicsItem::itemStacksBehindParent()
6849 StacksBehindParentHelper *parent1 = new StacksBehindParentHelper(&paintedItems, QRectF(0, 0, 100, 50));
6850 StacksBehindParentHelper *child11 = new StacksBehindParentHelper(&paintedItems, QRectF(-10, 10, 50, 50), parent1);
6851 StacksBehindParentHelper *grandChild111 = new StacksBehindParentHelper(&paintedItems, QRectF(-20, 20, 50, 50), child11);
6852 StacksBehindParentHelper *child12 = new StacksBehindParentHelper(&paintedItems, QRectF(60, 10, 50, 50), parent1);
6853 StacksBehindParentHelper *grandChild121 = new StacksBehindParentHelper(&paintedItems, QRectF(70, 20, 50, 50), child12);
6855 StacksBehindParentHelper *parent2 = new StacksBehindParentHelper(&paintedItems, QRectF(0, 0, 100, 50));
6856 StacksBehindParentHelper *child21 = new StacksBehindParentHelper(&paintedItems, QRectF(-10, 10, 50, 50), parent2);
6857 StacksBehindParentHelper *grandChild211 = new StacksBehindParentHelper(&paintedItems, QRectF(-20, 20, 50, 50), child21);
6858 StacksBehindParentHelper *child22 = new StacksBehindParentHelper(&paintedItems, QRectF(60, 10, 50, 50), parent2);
6859 StacksBehindParentHelper *grandChild221 = new StacksBehindParentHelper(&paintedItems, QRectF(70, 20, 50, 50), child22);
6861 parent1->setData(0, "parent1");
6862 child11->setData(0, "child11");
6863 grandChild111->setData(0, "grandChild111");
6864 child12->setData(0, "child12");
6865 grandChild121->setData(0, "grandChild121");
6866 parent2->setData(0, "parent2");
6867 child21->setData(0, "child21");
6868 grandChild211->setData(0, "grandChild211");
6869 child22->setData(0, "child22");
6870 grandChild221->setData(0, "grandChild221");
6872 // Disambiguate siblings
6873 parent1->setZValue(1);
6874 child11->setZValue(1);
6875 child21->setZValue(1);
6877 QGraphicsScene scene;
6878 scene.addItem(parent1);
6879 scene.addItem(parent2);
6881 QGraphicsView view(&scene);
6883 QVERIFY(QTest::qWaitForWindowExposed(&view));
6884 QTRY_VERIFY(!paintedItems.isEmpty());
6886 paintedItems.clear();
6887 view.viewport()->update();
6888 QApplication::processEvents();
6889 QTRY_COMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
6890 << grandChild111 << child11
6891 << grandChild121 << child12 << parent1
6892 << grandChild211 << child21
6893 << grandChild221 << child22 << parent2));
6894 QTRY_COMPARE(paintedItems, QList<QGraphicsItem *>()
6895 << parent2 << child22 << grandChild221
6896 << child21 << grandChild211
6897 << parent1 << child12 << grandChild121
6898 << child11 << grandChild111);
6900 child11->setFlag(QGraphicsItem::ItemStacksBehindParent);
6902 paintedItems.clear();
6903 QApplication::processEvents();
6905 QTRY_COMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
6906 << grandChild121 << child12 << parent1
6907 << grandChild111 << child11
6908 << grandChild211 << child21
6909 << grandChild221 << child22 << parent2));
6910 QCOMPARE(paintedItems, QList<QGraphicsItem *>()
6911 << parent2 << child22 << grandChild221
6912 << child21 << grandChild211
6913 << child11 << grandChild111
6914 << parent1 << child12 << grandChild121);
6916 child12->setFlag(QGraphicsItem::ItemStacksBehindParent);
6917 paintedItems.clear();
6919 QApplication::processEvents();
6921 QTRY_COMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
6922 << parent1 << grandChild111 << child11
6923 << grandChild121 << child12
6924 << grandChild211 << child21
6925 << grandChild221 << child22 << parent2));
6926 QCOMPARE(paintedItems, QList<QGraphicsItem *>()
6927 << parent2 << child22 << grandChild221
6928 << child21 << grandChild211
6929 << child12 << grandChild121
6930 << child11 << grandChild111 << parent1);
6933 class ClippingAndTransformsScene : public QGraphicsScene
6936 QList<QGraphicsItem *> drawnItems;
6938 void drawItems(QPainter *painter, int numItems, QGraphicsItem *items[],
6939 const QStyleOptionGraphicsItem options[], QWidget *widget = 0)
6942 for (int i = 0; i < numItems; ++i)
6943 drawnItems << items[i];
6944 QGraphicsScene::drawItems(painter, numItems, items, options, widget);
6948 void tst_QGraphicsItem::nestedClipping()
6950 ClippingAndTransformsScene scene;
6951 scene.setSceneRect(-50, -50, 200, 200);
6953 QGraphicsRectItem *root = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
6954 root->setBrush(QColor(0, 0, 255));
6955 root->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
6956 QGraphicsRectItem *l1 = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
6957 l1->setParentItem(root);
6959 l1->setBrush(QColor(255, 0, 0));
6960 l1->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
6961 QGraphicsEllipseItem *l2 = new QGraphicsEllipseItem(QRectF(0, 0, 100, 100));
6962 l2->setParentItem(l1);
6964 l2->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
6965 l2->setBrush(QColor(255, 255, 0));
6966 QGraphicsRectItem *l3 = new QGraphicsRectItem(QRectF(0, 0, 25, 25));
6967 l3->setParentItem(l2);
6968 l3->setBrush(QColor(0, 255, 0));
6969 l3->setPos(50 - 12, -12);
6971 scene.addItem(root);
6973 root->setData(0, "root");
6974 l1->setData(0, "l1");
6975 l2->setData(0, "l2");
6976 l3->setData(0, "l3");
6978 QGraphicsView view(&scene);
6979 view.setOptimizationFlag(QGraphicsView::IndirectPainting);
6981 QVERIFY(QTest::qWaitForWindowExposed(&view));
6984 QList<QGraphicsItem *> expected;
6985 expected << root << l1 << l2 << l3;
6986 QTRY_COMPARE(scene.drawnItems, expected);
6988 QImage image(200, 200, QImage::Format_ARGB32_Premultiplied);
6991 QPainter painter(&image);
6992 scene.render(&painter);
6995 // Check transparent areas
6996 QCOMPARE(image.pixel(100, 25), qRgba(0, 0, 0, 0));
6997 QCOMPARE(image.pixel(100, 175), qRgba(0, 0, 0, 0));
6998 QCOMPARE(image.pixel(25, 100), qRgba(0, 0, 0, 0));
6999 QCOMPARE(image.pixel(175, 100), qRgba(0, 0, 0, 0));
7000 QCOMPARE(image.pixel(70, 80), qRgba(255, 0, 0, 255));
7001 QCOMPARE(image.pixel(80, 130), qRgba(255, 255, 0, 255));
7002 QCOMPARE(image.pixel(92, 105), qRgba(0, 255, 0, 255));
7003 QCOMPARE(image.pixel(105, 105), qRgba(0, 0, 255, 255));
7005 // Enable this to compare if the test starts failing.
7006 image.save("nestedClipping_reference.png");
7010 class TransformDebugItem : public QGraphicsRectItem
7013 TransformDebugItem()
7014 : QGraphicsRectItem(QRectF(-10, -10, 20, 20))
7016 setPen(QPen(Qt::black, 0));
7017 setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
7022 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
7023 QWidget *widget = 0)
7025 x = painter->worldTransform();
7026 QGraphicsRectItem::paint(painter, option, widget);
7030 void tst_QGraphicsItem::nestedClippingTransforms()
7032 TransformDebugItem *rootClipper = new TransformDebugItem;
7033 rootClipper->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
7034 TransformDebugItem *child = new TransformDebugItem;
7035 child->setParentItem(rootClipper);
7036 child->setPos(2, 2);
7037 TransformDebugItem *grandChildClipper = new TransformDebugItem;
7038 grandChildClipper->setParentItem(child);
7039 grandChildClipper->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
7040 grandChildClipper->setPos(4, 4);
7041 TransformDebugItem *greatGrandChild = new TransformDebugItem;
7042 greatGrandChild->setPos(2, 2);
7043 greatGrandChild->setParentItem(grandChildClipper);
7044 TransformDebugItem *grandChildClipper2 = new TransformDebugItem;
7045 grandChildClipper2->setParentItem(child);
7046 grandChildClipper2->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
7047 grandChildClipper2->setPos(8, 8);
7048 TransformDebugItem *greatGrandChild2 = new TransformDebugItem;
7049 greatGrandChild2->setPos(2, 2);
7050 greatGrandChild2->setParentItem(grandChildClipper2);
7051 TransformDebugItem *grandChildClipper3 = new TransformDebugItem;
7052 grandChildClipper3->setParentItem(child);
7053 grandChildClipper3->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
7054 grandChildClipper3->setPos(12, 12);
7055 TransformDebugItem *greatGrandChild3 = new TransformDebugItem;
7056 greatGrandChild3->setPos(2, 2);
7057 greatGrandChild3->setParentItem(grandChildClipper3);
7059 QGraphicsScene scene;
7060 scene.addItem(rootClipper);
7062 QImage image(scene.itemsBoundingRect().size().toSize(), QImage::Format_ARGB32_Premultiplied);
7068 QCOMPARE(rootClipper->x, QTransform(1, 0, 0, 0, 1, 0, 10, 10, 1));
7069 QCOMPARE(child->x, QTransform(1, 0, 0, 0, 1, 0, 12, 12, 1));
7070 QCOMPARE(grandChildClipper->x, QTransform(1, 0, 0, 0, 1, 0, 16, 16, 1));
7071 QCOMPARE(greatGrandChild->x, QTransform(1, 0, 0, 0, 1, 0, 18, 18, 1));
7072 QCOMPARE(grandChildClipper2->x, QTransform(1, 0, 0, 0, 1, 0, 20, 20, 1));
7073 QCOMPARE(greatGrandChild2->x, QTransform(1, 0, 0, 0, 1, 0, 22, 22, 1));
7074 QCOMPARE(grandChildClipper3->x, QTransform(1, 0, 0, 0, 1, 0, 24, 24, 1));
7075 QCOMPARE(greatGrandChild3->x, QTransform(1, 0, 0, 0, 1, 0, 26, 26, 1));
7078 void tst_QGraphicsItem::sceneTransformCache()
7080 // Test that an item's scene transform is updated correctly when the
7081 // parent is transformed.
7082 QGraphicsScene scene;
7083 QGraphicsRectItem *rect = scene.addRect(0, 0, 100, 100);
7084 rect->setPen(QPen(Qt::black, 0));
7085 QGraphicsRectItem *rect2 = scene.addRect(0, 0, 100, 100);
7086 rect2->setPen(QPen(Qt::black, 0));
7087 rect2->setParentItem(rect);
7089 rect->translate(0, 50);
7090 QGraphicsView view(&scene);
7092 QVERIFY(QTest::qWaitForWindowExposed(&view));
7093 rect->translate(0, 100);
7095 x.translate(0, 150);
7097 QCOMPARE(rect2->sceneTransform(), x);
7099 scene.removeItem(rect);
7101 //Crazy use case : rect4 child of rect3 so the transformation of rect4 will be cached.Good!
7102 //We remove rect4 from the scene, then the validTransform bit flag is set to 0 and the index of the cache
7103 //add to the freeTransformSlots. The problem was that sceneTransformIndex was not set to -1 so if a new item arrive
7104 //with a child (rect6) that will be cached then it will take the freeSlot (ex rect4) and put it his transform. But if rect4 is
7105 //added back to the scene then it will set the transform to his old sceneTransformIndex value that will erase the new
7106 //value of rect6 so rect6 transform will be wrong.
7107 QGraphicsRectItem *rect3 = scene.addRect(0, 0, 100, 100);
7108 QGraphicsRectItem *rect4 = scene.addRect(0, 0, 100, 100);
7109 rect3->setPos(QPointF(10,10));
7110 rect3->setPen(QPen(Qt::black, 0));
7112 rect4->setParentItem(rect3);
7113 rect4->setPos(QPointF(10,10));
7114 rect4->setPen(QPen(Qt::black, 0));
7116 QCOMPARE(rect4->mapToScene(rect4->boundingRect().topLeft()), QPointF(20,20));
7118 scene.removeItem(rect4);
7119 //rect4 transform is local only
7120 QCOMPARE(rect4->mapToScene(rect4->boundingRect().topLeft()), QPointF(10,10));
7122 QGraphicsRectItem *rect5 = scene.addRect(0, 0, 100, 100);
7123 QGraphicsRectItem *rect6 = scene.addRect(0, 0, 100, 100);
7124 rect5->setPos(QPointF(20,20));
7125 rect5->setPen(QPen(Qt::black, 0));
7127 rect6->setParentItem(rect5);
7128 rect6->setPos(QPointF(10,10));
7129 rect6->setPen(QPen(Qt::black, 0));
7130 //test if rect6 transform is ok
7131 QCOMPARE(rect6->mapToScene(rect6->boundingRect().topLeft()), QPointF(30,30));
7133 scene.addItem(rect4);
7135 QCOMPARE(rect4->mapToScene(rect4->boundingRect().topLeft()), QPointF(10,10));
7136 //test if rect6 transform is still correct
7137 QCOMPARE(rect6->mapToScene(rect6->boundingRect().topLeft()), QPointF(30,30));
7140 void tst_QGraphicsItem::tabChangesFocus_data()
7142 QTest::addColumn<bool>("tabChangesFocus");
7143 QTest::newRow("tab changes focus") << true;
7144 QTest::newRow("tab doesn't change focus") << false;
7147 void tst_QGraphicsItem::tabChangesFocus()
7149 QFETCH(bool, tabChangesFocus);
7151 QGraphicsScene scene;
7152 QGraphicsTextItem *item = scene.addText("Hello");
7153 item->setTabChangesFocus(tabChangesFocus);
7154 item->setTextInteractionFlags(Qt::TextEditorInteraction);
7157 QDial *dial1 = new QDial;
7158 QGraphicsView *view = new QGraphicsView(&scene);
7160 QDial *dial2 = new QDial;
7161 QVBoxLayout *layout = new QVBoxLayout;
7162 layout->addWidget(dial1);
7163 layout->addWidget(view);
7164 layout->addWidget(dial2);
7167 widget.setLayout(layout);
7169 QVERIFY(QTest::qWaitForWindowActive(&widget));
7171 QTRY_VERIFY(scene.isActive());
7175 QTRY_VERIFY(dial1->hasFocus());
7177 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
7179 QTRY_VERIFY(view->hasFocus());
7180 QTRY_VERIFY(item->hasFocus());
7182 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
7185 if (tabChangesFocus) {
7186 QTRY_VERIFY(!view->hasFocus());
7187 QTRY_VERIFY(!item->hasFocus());
7188 QTRY_VERIFY(dial2->hasFocus());
7190 QTRY_VERIFY(view->hasFocus());
7191 QTRY_VERIFY(item->hasFocus());
7192 QCOMPARE(item->toPlainText(), QString("\tHello"));
7196 void tst_QGraphicsItem::cacheMode()
7198 QGraphicsScene scene(0, 0, 100, 100);
7199 QGraphicsView view(&scene);
7200 view.resize(150, 150);
7202 QApplication::setActiveWindow(&view);
7203 QVERIFY(QTest::qWaitForWindowActive(&view));
7205 // Increase the probability of window activation
7206 // not causing another repaint of test items.
7209 EventTester *tester = new EventTester;
7210 EventTester *testerChild = new EventTester;
7211 testerChild->setParentItem(tester);
7212 EventTester *testerChild2 = new EventTester;
7213 testerChild2->setParentItem(testerChild);
7214 testerChild2->setFlag(QGraphicsItem::ItemIgnoresTransformations);
7216 scene.addItem(tester);
7219 for (int i = 0; i < 2; ++i) {
7220 // No visual change.
7221 QTRY_COMPARE(tester->repaints, 1);
7222 QCOMPARE(testerChild->repaints, 1);
7223 QCOMPARE(testerChild2->repaints, 1);
7224 tester->setCacheMode(QGraphicsItem::NoCache);
7225 testerChild->setCacheMode(QGraphicsItem::NoCache);
7226 testerChild2->setCacheMode(QGraphicsItem::NoCache);
7228 QTRY_COMPARE(tester->repaints, 1);
7229 QCOMPARE(testerChild->repaints, 1);
7230 QCOMPARE(testerChild2->repaints, 1);
7231 tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7232 testerChild->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7233 testerChild2->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7237 // The first move causes a repaint as the item is painted into its pixmap.
7238 // (Only occurs if the item has previously been painted without cache).
7239 tester->setPos(10, 10);
7240 testerChild->setPos(10, 10);
7241 testerChild2->setPos(10, 10);
7243 QTRY_COMPARE(tester->repaints, 2);
7244 QCOMPARE(testerChild->repaints, 2);
7245 QCOMPARE(testerChild2->repaints, 2);
7247 // Consecutive moves should not repaint.
7248 tester->setPos(20, 20);
7249 testerChild->setPos(20, 20);
7250 testerChild2->setPos(20, 20);
7252 QCOMPARE(tester->repaints, 2);
7253 QCOMPARE(testerChild->repaints, 2);
7254 QCOMPARE(testerChild2->repaints, 2);
7256 // Translating does not result in a repaint.
7257 tester->translate(10, 10);
7259 QTRY_COMPARE(tester->repaints, 2);
7260 QCOMPARE(testerChild->repaints, 2);
7261 QCOMPARE(testerChild2->repaints, 2);
7263 // Rotating results in a repaint.
7266 QTRY_COMPARE(tester->repaints, 3);
7267 QCOMPARE(testerChild->repaints, 3);
7268 QCOMPARE(testerChild2->repaints, 2);
7270 // Change to ItemCoordinateCache (triggers repaint).
7271 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache); // autosize
7272 testerChild->setCacheMode(QGraphicsItem::ItemCoordinateCache); // autosize
7273 testerChild2->setCacheMode(QGraphicsItem::ItemCoordinateCache); // autosize
7275 QTRY_COMPARE(tester->repaints, 4);
7276 QCOMPARE(testerChild->repaints, 4);
7277 QCOMPARE(testerChild2->repaints, 3);
7279 // Rotating items with ItemCoordinateCache doesn't cause a repaint.
7281 testerChild->rotate(22);
7282 testerChild2->rotate(22);
7284 QTRY_COMPARE(tester->repaints, 4);
7285 QTRY_COMPARE(testerChild->repaints, 4);
7286 QTRY_COMPARE(testerChild2->repaints, 3);
7287 tester->resetTransform();
7288 testerChild->resetTransform();
7289 testerChild2->resetTransform();
7291 // Explicit update causes a repaint.
7292 tester->update(0, 0, 5, 5);
7294 QTRY_COMPARE(tester->repaints, 5);
7295 QCOMPARE(testerChild->repaints, 4);
7296 QCOMPARE(testerChild2->repaints, 3);
7298 // Updating outside the item's bounds does not cause a repaint.
7299 tester->update(10, 10, 5, 5);
7301 QTRY_COMPARE(tester->repaints, 5);
7302 QCOMPARE(testerChild->repaints, 4);
7303 QCOMPARE(testerChild2->repaints, 3);
7305 // Resizing an item should cause a repaint of that item. (because of
7307 tester->setGeometry(QRectF(-15, -15, 30, 30));
7309 QTRY_COMPARE(tester->repaints, 6);
7310 QCOMPARE(testerChild->repaints, 4);
7311 QCOMPARE(testerChild2->repaints, 3);
7314 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(30, 30));
7315 testerChild->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(30, 30));
7316 testerChild2->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(30, 30));
7318 QTRY_COMPARE(tester->repaints, 7);
7319 QCOMPARE(testerChild->repaints, 5);
7320 QCOMPARE(testerChild2->repaints, 4);
7322 // Resizing the item should cause a repaint.
7323 testerChild->setGeometry(QRectF(-15, -15, 30, 30));
7325 QTRY_COMPARE(tester->repaints, 7);
7326 QCOMPARE(testerChild->repaints, 6);
7327 QCOMPARE(testerChild2->repaints, 4);
7329 // Scaling the view does not cause a repaint.
7330 view.scale(0.7, 0.7);
7332 QTRY_COMPARE(tester->repaints, 7);
7333 QCOMPARE(testerChild->repaints, 6);
7334 QCOMPARE(testerChild2->repaints, 4);
7336 // Switch to device coordinate cache.
7337 tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7338 testerChild->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7339 testerChild2->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7341 QTRY_COMPARE(tester->repaints, 8);
7342 QCOMPARE(testerChild->repaints, 7);
7343 QCOMPARE(testerChild2->repaints, 5);
7345 // Scaling the view back should cause repaints for two of the items.
7346 view.setTransform(QTransform());
7348 QTRY_COMPARE(tester->repaints, 9);
7349 QCOMPARE(testerChild->repaints, 8);
7350 QCOMPARE(testerChild2->repaints, 5);
7352 // Rotating the base item (perspective) should repaint two items.
7353 tester->setTransform(QTransform().rotate(10, Qt::XAxis));
7355 QTRY_COMPARE(tester->repaints, 10);
7356 QCOMPARE(testerChild->repaints, 9);
7357 QCOMPARE(testerChild2->repaints, 5);
7359 // Moving the middle item should case a repaint even if it's a move,
7360 // because the parent is rotated with a perspective.
7361 testerChild->setPos(1, 1);
7363 QTRY_COMPARE(tester->repaints, 11);
7364 QTRY_COMPARE(testerChild->repaints, 10);
7365 QTRY_COMPARE(testerChild2->repaints, 5);
7366 tester->resetTransform();
7369 tester->setGeometry(QRectF(-4000, -4000, 8000, 8000));
7370 QTRY_COMPARE(tester->repaints, 12);
7371 QTRY_COMPARE(testerChild->repaints, 11);
7372 QTRY_COMPARE(testerChild2->repaints, 5);
7374 // Move the large item - will cause a repaint as the
7375 // cache is clipped.
7376 tester->setPos(5, 0);
7377 QTRY_COMPARE(tester->repaints, 13);
7378 QTRY_COMPARE(testerChild->repaints, 11);
7379 QTRY_COMPARE(testerChild2->repaints, 5);
7381 // Hiding and showing should invalidate the cache
7385 QTRY_COMPARE(tester->repaints, 14);
7386 QTRY_COMPARE(testerChild->repaints, 12);
7387 QTRY_COMPARE(testerChild2->repaints, 6);
7390 void tst_QGraphicsItem::cacheMode2()
7392 QGraphicsScene scene(0, 0, 100, 100);
7393 QGraphicsView view(&scene);
7394 view.resize(150, 150);
7396 QApplication::setActiveWindow(&view);
7397 QVERIFY(QTest::qWaitForWindowActive(&view));
7399 // Increase the probability of window activation
7400 // not causing another repaint of test items.
7403 EventTester *tester = new EventTester;
7404 scene.addItem(tester);
7406 QTRY_COMPARE(tester->repaints, 1);
7408 // Switching from NoCache to NoCache (no repaint)
7409 tester->setCacheMode(QGraphicsItem::NoCache);
7411 QTRY_COMPARE(tester->repaints, 1);
7413 // Switching from NoCache to DeviceCoordinateCache (no repaint)
7414 tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7416 QTRY_COMPARE(tester->repaints, 1);
7418 // Switching from DeviceCoordinateCache to DeviceCoordinateCache (no repaint)
7419 tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7421 QTRY_COMPARE(tester->repaints, 1);
7423 // Switching from DeviceCoordinateCache to NoCache (no repaint)
7424 tester->setCacheMode(QGraphicsItem::NoCache);
7426 QTRY_COMPARE(tester->repaints, 1);
7428 // Switching from NoCache to ItemCoordinateCache (repaint)
7429 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
7431 QTRY_COMPARE(tester->repaints, 2);
7433 // Switching from ItemCoordinateCache to ItemCoordinateCache (no repaint)
7434 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
7436 QTRY_COMPARE(tester->repaints, 2);
7438 // Switching from ItemCoordinateCache to ItemCoordinateCache with different size (repaint)
7439 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(100, 100));
7441 QTRY_COMPARE(tester->repaints, 3);
7443 // Switching from ItemCoordinateCache to NoCache (repaint)
7444 tester->setCacheMode(QGraphicsItem::NoCache);
7446 QTRY_COMPARE(tester->repaints, 4);
7448 // Switching from DeviceCoordinateCache to ItemCoordinateCache (repaint)
7449 tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7451 QTRY_COMPARE(tester->repaints, 4);
7452 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
7454 QTRY_COMPARE(tester->repaints, 5);
7456 // Switching from ItemCoordinateCache to DeviceCoordinateCache (repaint)
7457 tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7459 QTRY_COMPARE(tester->repaints, 6);
7462 void tst_QGraphicsItem::updateCachedItemAfterMove()
7464 // A simple item that uses ItemCoordinateCache
7465 EventTester *tester = new EventTester;
7466 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
7468 // Add to a scene, show in a view, ensure it's painted and reset its
7470 QGraphicsScene scene;
7471 scene.addItem(tester);
7472 QGraphicsView view(&scene);
7474 QVERIFY(QTest::qWaitForWindowExposed(&view));
7477 QTRY_VERIFY(tester->repaints > 0);
7478 tester->repaints = 0;
7480 // Move the item, should not cause repaints
7481 tester->setPos(10, 0);
7483 QCOMPARE(tester->repaints, 0);
7485 // Move then update, should cause one repaint
7486 tester->setPos(20, 0);
7489 QCOMPARE(tester->repaints, 1);
7491 // Hiding the item doesn't cause a repaint
7494 QCOMPARE(tester->repaints, 1);
7496 // Moving a hidden item doesn't cause a repaint
7497 tester->setPos(30, 0);
7500 QCOMPARE(tester->repaints, 1);
7503 class Track : public QGraphicsRectItem
7506 Track(const QRectF &rect)
7507 : QGraphicsRectItem(rect)
7509 setAcceptHoverEvents(true);
7512 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
7514 QGraphicsRectItem::paint(painter, option, widget);
7515 painter->drawText(boundingRect(), Qt::AlignCenter, QString("%1x%2\n%3x%4").arg(p.x()).arg(p.y()).arg(sp.x()).arg(sp.y()));
7519 void hoverMoveEvent(QGraphicsSceneHoverEvent *event)
7522 sp = event->widget()->mapFromGlobal(event->screenPos());
7530 void tst_QGraphicsItem::deviceTransform_data()
7532 QTest::addColumn<bool>("untransformable1");
7533 QTest::addColumn<bool>("untransformable2");
7534 QTest::addColumn<bool>("untransformable3");
7535 QTest::addColumn<qreal>("rotation1");
7536 QTest::addColumn<qreal>("rotation2");
7537 QTest::addColumn<qreal>("rotation3");
7538 QTest::addColumn<QTransform>("deviceX");
7539 QTest::addColumn<QPointF>("mapResult1");
7540 QTest::addColumn<QPointF>("mapResult2");
7541 QTest::addColumn<QPointF>("mapResult3");
7543 QTest::newRow("nil") << false << false << false
7544 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7546 << QPointF(150, 150) << QPointF(250, 250) << QPointF(350, 350);
7547 QTest::newRow("deviceX rot 90") << false << false << false
7548 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7549 << QTransform().rotate(90)
7550 << QPointF(-150, 150) << QPointF(-250, 250) << QPointF(-350, 350);
7551 QTest::newRow("deviceX rot 90 100") << true << false << false
7552 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7553 << QTransform().rotate(90)
7554 << QPointF(-50, 150) << QPointF(50, 250) << QPointF(150, 350);
7555 QTest::newRow("deviceX rot 90 010") << false << true << false
7556 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7557 << QTransform().rotate(90)
7558 << QPointF(-150, 150) << QPointF(-150, 250) << QPointF(-50, 350);
7559 QTest::newRow("deviceX rot 90 001") << false << false << true
7560 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7561 << QTransform().rotate(90)
7562 << QPointF(-150, 150) << QPointF(-250, 250) << QPointF(-250, 350);
7563 QTest::newRow("deviceX rot 90 111") << true << true << true
7564 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7565 << QTransform().rotate(90)
7566 << QPointF(-50, 150) << QPointF(50, 250) << QPointF(150, 350);
7567 QTest::newRow("deviceX rot 90 101") << true << false << true
7568 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7569 << QTransform().rotate(90)
7570 << QPointF(-50, 150) << QPointF(50, 250) << QPointF(150, 350);
7573 void tst_QGraphicsItem::deviceTransform()
7575 QFETCH(bool, untransformable1);
7576 QFETCH(bool, untransformable2);
7577 QFETCH(bool, untransformable3);
7578 QFETCH(qreal, rotation1);
7579 QFETCH(qreal, rotation2);
7580 QFETCH(qreal, rotation3);
7581 QFETCH(QTransform, deviceX);
7582 QFETCH(QPointF, mapResult1);
7583 QFETCH(QPointF, mapResult2);
7584 QFETCH(QPointF, mapResult3);
7586 QGraphicsScene scene;
7587 Track *rect1 = new Track(QRectF(0, 0, 100, 100));
7588 Track *rect2 = new Track(QRectF(0, 0, 100, 100));
7589 Track *rect3 = new Track(QRectF(0, 0, 100, 100));
7590 rect2->setParentItem(rect1);
7591 rect3->setParentItem(rect2);
7592 rect1->setPos(100, 100);
7593 rect2->setPos(100, 100);
7594 rect3->setPos(100, 100);
7595 rect1->rotate(rotation1);
7596 rect2->rotate(rotation2);
7597 rect3->rotate(rotation3);
7598 rect1->setFlag(QGraphicsItem::ItemIgnoresTransformations, untransformable1);
7599 rect2->setFlag(QGraphicsItem::ItemIgnoresTransformations, untransformable2);
7600 rect3->setFlag(QGraphicsItem::ItemIgnoresTransformations, untransformable3);
7601 rect1->setBrush(Qt::red);
7602 rect2->setBrush(Qt::green);
7603 rect3->setBrush(Qt::blue);
7604 scene.addItem(rect1);
7606 QCOMPARE(rect1->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult1);
7607 QCOMPARE(rect2->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult2);
7608 QCOMPARE(rect3->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult3);
7611 void tst_QGraphicsItem::update()
7613 QGraphicsScene scene;
7614 scene.setSceneRect(-100, -100, 200, 200);
7616 MyGraphicsView view(&scene,&topLevel);
7618 topLevel.resize(300, 300);
7620 QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
7622 EventTester *item = new EventTester;
7623 scene.addItem(item);
7624 QTest::qWait(100); // Make sure all pending updates are processed.
7627 item->update(); // Item marked as dirty
7628 scene.update(); // Entire scene marked as dirty
7629 qApp->processEvents();
7630 QCOMPARE(item->repaints, 1);
7632 // Make sure the dirty state from the previous update is reset so that
7633 // the item don't think it is already dirty and discards this update.
7635 qApp->processEvents();
7636 QCOMPARE(item->repaints, 2);
7638 // Make sure a partial update doesn't cause a full update to be discarded.
7641 item->update(QRectF(0, 0, 5, 5));
7643 qApp->processEvents();
7644 QCOMPARE(item->repaints, 1);
7645 QCOMPARE(view.repaints, 1);
7646 QRect itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform())
7647 .mapRect(item->boundingRect()).toAlignedRect();
7648 QRegion expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2);
7649 // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
7650 QCOMPARE(view.paintedRegion, expectedRegion);
7652 // Make sure update requests outside the bounding rect are discarded.
7655 item->update(-15, -15, 5, 5); // Item's brect: (-10, -10, 20, 20)
7656 qApp->processEvents();
7657 QCOMPARE(item->repaints, 0);
7658 QCOMPARE(view.repaints, 0);
7660 // Make sure the area occupied by an item is repainted when hiding it.
7663 item->update(); // Full update; all sub-sequent update requests are discarded.
7664 item->hide(); // visible set to 0. ignoreVisible must be set to 1; the item won't be processed otherwise.
7665 qApp->processEvents();
7666 QCOMPARE(item->repaints, 0);
7667 QCOMPARE(view.repaints, 1);
7668 // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
7669 QCOMPARE(view.paintedRegion, expectedRegion);
7671 // Make sure item is repainted when shown (after being hidden).
7675 qApp->processEvents();
7676 QCOMPARE(item->repaints, 1);
7677 QCOMPARE(view.repaints, 1);
7678 // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
7679 QCOMPARE(view.paintedRegion, expectedRegion);
7683 qApp->processEvents();
7685 const QPointF originalPos = item->pos();
7686 item->setPos(5000, 5000);
7687 qApp->processEvents();
7688 QCOMPARE(item->repaints, 0);
7689 QCOMPARE(view.repaints, 0);
7690 qApp->processEvents();
7692 item->setPos(originalPos);
7693 qApp->processEvents();
7694 QCOMPARE(item->repaints, 0);
7695 QCOMPARE(view.repaints, 0);
7697 qApp->processEvents();
7698 QCOMPARE(item->repaints, 1);
7699 QCOMPARE(view.repaints, 1);
7700 // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
7701 QCOMPARE(view.paintedRegion, expectedRegion);
7703 QGraphicsViewPrivate *viewPrivate = static_cast<QGraphicsViewPrivate *>(qt_widget_private(&view));
7704 item->setPos(originalPos + QPoint(50, 50));
7705 viewPrivate->updateAll();
7706 QVERIFY(viewPrivate->fullUpdatePending);
7710 item->setPos(originalPos);
7712 qApp->processEvents();
7713 QCOMPARE(item->repaints, 1);
7714 QCOMPARE(view.repaints, 1);
7715 COMPARE_REGIONS(view.paintedRegion, expectedRegion + expectedRegion.translated(50, 50));
7717 // Make sure moving a parent item triggers an update on the children
7718 // (even though the parent itself is outside the viewport).
7719 QGraphicsRectItem *parent = new QGraphicsRectItem(0, 0, 10, 10);
7720 parent->setPos(-400, 0);
7721 item->setParentItem(parent);
7722 item->setPos(400, 0);
7723 scene.addItem(parent);
7725 itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform())
7726 .mapRect(item->boundingRect()).toAlignedRect();
7727 expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2);
7730 parent->translate(-400, 0);
7731 qApp->processEvents();
7732 QCOMPARE(item->repaints, 0);
7733 QCOMPARE(view.repaints, 1);
7734 QCOMPARE(view.paintedRegion, expectedRegion);
7737 parent->translate(400, 0);
7738 qApp->processEvents();
7739 QCOMPARE(item->repaints, 1);
7740 QCOMPARE(view.repaints, 1);
7741 QCOMPARE(view.paintedRegion, expectedRegion);
7742 QCOMPARE(view.paintedRegion, expectedRegion);
7745 void tst_QGraphicsItem::setTransformProperties_data()
7747 QTest::addColumn<QPointF>("origin");
7748 QTest::addColumn<qreal>("rotation");
7749 QTest::addColumn<qreal>("scale");
7751 QTest::newRow("nothing") << QPointF() << qreal(0.0) << qreal(1.0);
7753 QTest::newRow("rotation") << QPointF() << qreal(42.2) << qreal(1.0);
7755 QTest::newRow("rotation dicentred") << QPointF(qreal(22.3), qreal(-56.2))
7759 QTest::newRow("Scale") << QPointF() << qreal(0.0)
7762 QTest::newRow("Everything dicentred") << QPointF(qreal(22.3), qreal(-56.2)) << qreal(-175) << qreal(196);
7766 * the normal QCOMPARE doesn't work because it doesn't use qFuzzyCompare
7768 #define QCOMPARE_TRANSFORM(X1, X2) QVERIFY(((X1)*(X2).inverted()).isIdentity())
7770 void tst_QGraphicsItem::setTransformProperties()
7772 QFETCH(QPointF,origin);
7773 QFETCH(qreal,rotation);
7774 QFETCH(qreal,scale);
7777 result.translate(origin.x(), origin.y());
7778 result.rotate(rotation, Qt::ZAxis);
7779 result.scale(scale, scale);
7780 result.translate(-origin.x(), -origin.y());
7782 QGraphicsScene scene;
7783 QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
7784 scene.addItem(item);
7786 item->setRotation(rotation);
7787 item->setScale(scale);
7788 item->setTransformOriginPoint(origin);
7790 QCOMPARE(item->rotation(), rotation);
7791 QCOMPARE(item->scale(), scale);
7792 QCOMPARE(item->transformOriginPoint(), origin);
7794 QCOMPARE(QTransform(), item->transform());
7795 QCOMPARE(result, item->sceneTransform());
7797 //-----------------------------------------------------------------
7798 //Change the rotation Z
7799 item->setRotation(45);
7801 result2.translate(origin.x(), origin.y());
7803 result2.scale(scale, scale);
7804 result2.translate(-origin.x(), -origin.y());
7806 QCOMPARE(item->rotation(), 45.);
7807 QCOMPARE(item->scale(), scale);
7808 QCOMPARE(item->transformOriginPoint(), origin);
7810 QCOMPARE(QTransform(), item->transform());
7811 QCOMPARE(result2, item->sceneTransform());
7813 //-----------------------------------------------------------------
7814 // calling setTransform() and setPos should change the sceneTransform
7815 item->setTransform(result);
7816 item->setPos(100, -150.5);
7818 QCOMPARE(item->rotation(), 45.);
7819 QCOMPARE(item->scale(), scale);
7820 QCOMPARE(item->transformOriginPoint(), origin);
7821 QCOMPARE(result, item->transform());
7823 QTransform result3(result);
7825 result3.translate(origin.x(), origin.y());
7827 result3.scale(scale, scale);
7828 result3.translate(-origin.x(), -origin.y());
7830 result3 *= QTransform::fromTranslate(100, -150.5); //the pos;
7832 QCOMPARE(result3, item->sceneTransform());
7834 //-----------------------------------------------------
7835 // setting the propertiees should be the same as setting a transform
7836 {//with center origin on the matrix
7837 QGraphicsRectItem *item1 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119));
7838 scene.addItem(item1);
7839 QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119));
7840 scene.addItem(item2);
7842 item1->setPos(12.3, -5);
7843 item2->setPos(12.3, -5);
7844 item1->setRotation(rotation);
7845 item1->setScale(scale);
7846 item1->setTransformOriginPoint(origin);
7848 item2->setTransform(result);
7850 QCOMPARE_TRANSFORM(item1->sceneTransform(), item2->sceneTransform());
7852 QCOMPARE_TRANSFORM(item1->itemTransform(item2), QTransform());
7853 QCOMPARE_TRANSFORM(item2->itemTransform(item1), QTransform());
7857 class MyStyleOptionTester : public QGraphicsRectItem
7860 MyStyleOptionTester(const QRectF &rect)
7861 : QGraphicsRectItem(rect), startTrack(false)
7864 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
7867 //Doesn't use the extended style option so the exposed rect is the boundingRect
7868 if (!(flags() & QGraphicsItem::ItemUsesExtendedStyleOption)) {
7869 QCOMPARE(option->exposedRect, boundingRect());
7870 QCOMPARE(option->matrix, QMatrix());
7872 QVERIFY(option->exposedRect != QRect());
7873 QVERIFY(option->exposedRect != boundingRect());
7874 QCOMPARE(option->matrix, sceneTransform().toAffine());
7877 QGraphicsRectItem::paint(painter, option, widget);
7882 void tst_QGraphicsItem::itemUsesExtendedStyleOption()
7884 QGraphicsScene scene(0, 0, 300, 300);
7885 QGraphicsPixmapItem item;
7886 item.setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
7887 QCOMPARE(item.flags(), QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemUsesExtendedStyleOption));
7888 item.setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, false);
7889 QCOMPARE(item.flags(), 0);
7891 //We now test the content of the style option
7892 MyStyleOptionTester *rect = new MyStyleOptionTester(QRect(0, 0, 100, 100));
7893 scene.addItem(rect);
7894 rect->setPos(200, 200);
7896 QGraphicsView view(&scene, &topLevel);
7897 topLevel.setWindowFlags(Qt::X11BypassWindowManagerHint);
7898 rect->startTrack = false;
7900 QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
7902 rect->startTrack = true;
7903 rect->update(10, 10, 10, 10);
7905 rect->startTrack = false;
7906 rect->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
7907 QVERIFY((rect->flags() & QGraphicsItem::ItemUsesExtendedStyleOption));
7909 rect->startTrack = true;
7910 rect->update(10, 10, 10, 10);
7914 void tst_QGraphicsItem::itemSendsGeometryChanges()
7916 ItemChangeTester item;
7920 QTransform x = QTransform().rotate(45);
7921 QPointF pos(10, 10);
7925 QPointF origin(1.0, 1.0);
7926 item.setTransform(x);
7928 item.setRotation(r);
7930 item.setTransformOriginPoint(origin);
7931 QCOMPARE(item.transform(), x);
7932 QCOMPARE(item.pos(), pos);
7933 QCOMPARE(item.rotation(), r);
7934 QCOMPARE(item.scale(), s);
7935 QCOMPARE(item.transformOriginPoint(), origin);
7936 QCOMPARE(item.changes.size(), 0);
7939 QCOMPARE(item.changes.size(), 2); // opacity
7941 item.setFlag(QGraphicsItem::ItemSendsGeometryChanges);
7942 QCOMPARE(item.changes.size(), 4); // flags
7943 item.setTransform(QTransform());
7944 item.setPos(QPointF());
7945 QCOMPARE(item.changes.size(), 8); // transform + pos
7946 QCOMPARE(item.transform(), QTransform());
7947 QCOMPARE(item.pos(), QPointF());
7948 QCOMPARE(item.opacity(), o);
7949 item.setRotation(0.0);
7951 item.setTransformOriginPoint(0.0, 0.0);
7952 QCOMPARE(item.changes.size(), 14); // rotation + scale + origin
7953 QCOMPARE(item.rotation(), qreal(0.0));
7954 QCOMPARE(item.scale(), qreal(1.0));
7955 QCOMPARE(item.transformOriginPoint(), QPointF(0.0, 0.0));
7957 QCOMPARE(item.changes, QList<QGraphicsItem::GraphicsItemChange>()
7958 << QGraphicsItem::ItemOpacityChange
7959 << QGraphicsItem::ItemOpacityHasChanged
7960 << QGraphicsItem::ItemFlagsChange
7961 << QGraphicsItem::ItemFlagsHaveChanged
7962 << QGraphicsItem::ItemTransformChange
7963 << QGraphicsItem::ItemTransformHasChanged
7964 << QGraphicsItem::ItemPositionChange
7965 << QGraphicsItem::ItemPositionHasChanged
7966 << QGraphicsItem::ItemRotationChange
7967 << QGraphicsItem::ItemRotationHasChanged
7968 << QGraphicsItem::ItemScaleChange
7969 << QGraphicsItem::ItemScaleHasChanged
7970 << QGraphicsItem::ItemTransformOriginPointChange
7971 << QGraphicsItem::ItemTransformOriginPointHasChanged);
7974 // Make sure we update moved items correctly.
7975 void tst_QGraphicsItem::moveItem()
7977 QGraphicsScene scene;
7978 scene.setSceneRect(-50, -50, 200, 200);
7980 MyGraphicsView view(&scene);
7982 QVERIFY(QTest::qWaitForWindowExposed(&view));
7984 EventTester *parent = new EventTester;
7985 EventTester *child = new EventTester(parent);
7986 EventTester *grandChild = new EventTester(child);
7988 #define RESET_COUNTERS \
7989 parent->repaints = 0; \
7990 child->repaints = 0; \
7991 grandChild->repaints = 0; \
7994 scene.addItem(parent);
7999 // Item's boundingRect: (-10, -10, 20, 20).
8000 QRect parentDeviceBoundingRect = parent->deviceTransform(view.viewportTransform())
8001 .mapRect(parent->boundingRect()).toAlignedRect()
8002 .adjusted(-2, -2, 2, 2); // Adjusted for antialiasing.
8004 parent->setPos(20, 20);
8005 qApp->processEvents();
8006 QCOMPARE(parent->repaints, 1);
8007 QCOMPARE(view.repaints, 1);
8008 QRegion expectedParentRegion = parentDeviceBoundingRect; // old position
8009 parentDeviceBoundingRect.translate(20, 20);
8010 expectedParentRegion += parentDeviceBoundingRect; // new position
8011 COMPARE_REGIONS(view.paintedRegion, expectedParentRegion);
8015 child->setPos(20, 20);
8016 qApp->processEvents();
8017 QCOMPARE(parent->repaints, 1);
8018 QCOMPARE(child->repaints, 1);
8019 QCOMPARE(view.repaints, 1);
8020 const QRegion expectedChildRegion = expectedParentRegion.translated(20, 20);
8021 COMPARE_REGIONS(view.paintedRegion, expectedChildRegion);
8025 grandChild->setPos(20, 20);
8026 qApp->processEvents();
8027 QCOMPARE(parent->repaints, 1);
8028 QCOMPARE(child->repaints, 1);
8029 QCOMPARE(grandChild->repaints, 1);
8030 QCOMPARE(view.repaints, 1);
8031 const QRegion expectedGrandChildRegion = expectedParentRegion.translated(40, 40);
8032 COMPARE_REGIONS(view.paintedRegion, expectedGrandChildRegion);
8036 parent->translate(20, 20);
8037 qApp->processEvents();
8038 QCOMPARE(parent->repaints, 1);
8039 QCOMPARE(child->repaints, 1);
8040 QCOMPARE(grandChild->repaints, 1);
8041 QCOMPARE(view.repaints, 1);
8042 expectedParentRegion.translate(20, 20);
8043 expectedParentRegion += expectedChildRegion.translated(20, 20);
8044 expectedParentRegion += expectedGrandChildRegion.translated(20, 20);
8045 COMPARE_REGIONS(view.paintedRegion, expectedParentRegion);
8048 void tst_QGraphicsItem::moveLineItem()
8050 QGraphicsScene scene;
8051 scene.setSceneRect(0, 0, 200, 200);
8052 QGraphicsLineItem *item = new QGraphicsLineItem(0, 0, 100, 0);
8053 item->setPos(50, 50);
8054 scene.addItem(item);
8056 MyGraphicsView view(&scene);
8058 QVERIFY(QTest::qWaitForWindowActive(&view));
8061 QRectF brect = item->boundingRect();
8062 // Do same adjustments as in qgraphicsscene.cpp
8064 brect.adjust(qreal(-0.00001), 0, qreal(0.00001), 0);
8065 if (!brect.height())
8066 brect.adjust(0, qreal(-0.00001), 0, qreal(0.00001));
8067 const QRect itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform())
8068 .mapRect(brect).toAlignedRect();
8069 QRegion expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2); // antialiasing
8071 // Make sure the calculated region is correct.
8074 QTRY_COMPARE(view.paintedRegion, expectedRegion);
8077 // Old position: (50, 50)
8078 item->setPos(50, 100);
8079 expectedRegion += expectedRegion.translated(0, 50);
8081 QCOMPARE(view.paintedRegion, expectedRegion);
8084 void tst_QGraphicsItem::sorting_data()
8086 QTest::addColumn<int>("index");
8088 QTest::newRow("NoIndex") << int(QGraphicsScene::NoIndex);
8089 QTest::newRow("BspTreeIndex") << int(QGraphicsScene::BspTreeIndex);
8092 void tst_QGraphicsItem::sorting()
8094 if (qGuiApp->styleHints()->showIsFullScreen())
8095 QSKIP("Skipped because Platform is auto maximizing");
8097 _paintedItems.clear();
8099 QGraphicsScene scene;
8100 QGraphicsItem *grid[100][100];
8101 for (int x = 0; x < 100; ++x) {
8102 for (int y = 0; y < 100; ++y) {
8103 PainterItem *item = new PainterItem;
8104 item->setPos(x * 25, y * 25);
8105 item->setData(0, QString("%1x%2").arg(x).arg(y));
8107 scene.addItem(item);
8111 PainterItem *item1 = new PainterItem;
8112 PainterItem *item2 = new PainterItem;
8113 item1->setData(0, "item1");
8114 item2->setData(0, "item2");
8115 scene.addItem(item1);
8116 scene.addItem(item2);
8118 QGraphicsView view(&scene);
8119 // Use Qt::Tool as fully decorated windows have a minimum width of 160 on Windows.
8120 view.setWindowFlags(view.windowFlags() | Qt::Tool);
8121 view.setResizeAnchor(QGraphicsView::NoAnchor);
8122 view.setTransformationAnchor(QGraphicsView::NoAnchor);
8123 view.resize(120, 100);
8124 view.setFrameStyle(0);
8126 qApp->setActiveWindow(&view);
8127 QVERIFY(QTest::qWaitForWindowActive(&view));
8130 _paintedItems.clear();
8132 view.viewport()->repaint();
8133 #if defined(Q_OS_MAC)
8134 // There's no difference between repaint and update on the Mac,
8135 // so we have to process events here to make sure we get the event.
8139 QCOMPARE(_paintedItems, QList<QGraphicsItem *>()
8140 << grid[0][0] << grid[0][1] << grid[0][2] << grid[0][3]
8141 << grid[1][0] << grid[1][1] << grid[1][2] << grid[1][3]
8142 << grid[2][0] << grid[2][1] << grid[2][2] << grid[2][3]
8143 << grid[3][0] << grid[3][1] << grid[3][2] << grid[3][3]
8144 << grid[4][0] << grid[4][1] << grid[4][2] << grid[4][3]
8148 void tst_QGraphicsItem::itemHasNoContents()
8150 PainterItem *item1 = new PainterItem;
8151 PainterItem *item2 = new PainterItem;
8152 item2->setParentItem(item1);
8153 item2->setPos(50, 50);
8154 item1->setFlag(QGraphicsItem::ItemHasNoContents);
8155 item1->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
8157 QGraphicsScene scene;
8158 scene.addItem(item1);
8160 QGraphicsView view(&scene);
8162 qApp->setActiveWindow(&view);
8163 QVERIFY(QTest::qWaitForWindowActive(&view));
8164 QTRY_VERIFY(!_paintedItems.isEmpty());
8166 _paintedItems.clear();
8168 view.viewport()->repaint();
8170 // There's no difference between update() and repaint() on the Mac,
8171 // so we have to process events here to make sure we get the event.
8175 QTRY_COMPARE(_paintedItems, QList<QGraphicsItem *>() << item2);
8178 void tst_QGraphicsItem::hitTestUntransformableItem()
8180 QGraphicsScene scene;
8181 scene.setSceneRect(-100, -100, 200, 200);
8183 QGraphicsView view(&scene);
8185 QVERIFY(QTest::qWaitForWindowExposed(&view));
8187 // Confuse the BSP with dummy items.
8188 QGraphicsRectItem *dummy = new QGraphicsRectItem(0, 0, 20, 20);
8189 dummy->setPos(-100, -100);
8190 scene.addItem(dummy);
8191 for (int i = 0; i < 100; ++i) {
8192 QGraphicsItem *parent = dummy;
8193 dummy = new QGraphicsRectItem(0, 0, 20, 20);
8194 dummy->setPos(-100 + i, -100 + i);
8195 dummy->setParentItem(parent);
8198 QGraphicsRectItem *item1 = new QGraphicsRectItem(0, 0, 20, 20);
8199 item1->setPos(-200, -200);
8201 QGraphicsRectItem *item2 = new QGraphicsRectItem(0, 0, 20, 20);
8202 item2->setFlag(QGraphicsItem::ItemIgnoresTransformations);
8203 item2->setParentItem(item1);
8204 item2->setPos(200, 200);
8206 QGraphicsRectItem *item3 = new QGraphicsRectItem(0, 0, 20, 20);
8207 item3->setParentItem(item2);
8208 item3->setPos(80, 80);
8210 scene.addItem(item1);
8213 QList<QGraphicsItem *> items = scene.items(QPointF(80, 80));
8214 QCOMPARE(items.size(), 1);
8215 QCOMPARE(items.at(0), static_cast<QGraphicsItem*>(item3));
8217 scene.setItemIndexMethod(QGraphicsScene::NoIndex);
8220 items = scene.items(QPointF(80, 80));
8221 QCOMPARE(items.size(), 1);
8222 QCOMPARE(items.at(0), static_cast<QGraphicsItem*>(item3));
8225 void tst_QGraphicsItem::hitTestGraphicsEffectItem()
8227 QGraphicsScene scene;
8228 scene.setSceneRect(-100, -100, 200, 200);
8232 QGraphicsView view(&scene, &toplevel);
8233 toplevel.resize(300, 300);
8235 QVERIFY(QTest::qWaitForWindowExposed(&toplevel));
8237 // Confuse the BSP with dummy items.
8238 QGraphicsRectItem *dummy = new QGraphicsRectItem(0, 0, 20, 20);
8239 dummy->setPos(-100, -100);
8240 scene.addItem(dummy);
8241 for (int i = 0; i < 100; ++i) {
8242 QGraphicsItem *parent = dummy;
8243 dummy = new QGraphicsRectItem(0, 0, 20, 20);
8244 dummy->setPos(-100 + i, -100 + i);
8245 dummy->setParentItem(parent);
8248 const QRectF itemBoundingRect(0, 0, 20, 20);
8249 EventTester *item1 = new EventTester;
8250 item1->br = itemBoundingRect;
8251 item1->setPos(-200, -200);
8252 item1->brush = Qt::red;
8254 EventTester *item2 = new EventTester;
8255 item2->br = itemBoundingRect;
8256 item2->setFlag(QGraphicsItem::ItemIgnoresTransformations);
8257 item2->setParentItem(item1);
8258 item2->setPos(200, 200);
8259 item2->brush = Qt::green;
8261 EventTester *item3 = new EventTester;
8262 item3->br = itemBoundingRect;
8263 item3->setParentItem(item2);
8264 item3->setPos(80, 80);
8265 item3->brush = Qt::blue;
8267 scene.addItem(item1);
8270 item1->repaints = 0;
8271 item2->repaints = 0;
8272 item3->repaints = 0;
8274 // Apply shadow effect to the entire sub-tree.
8275 QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect;
8276 shadow->setOffset(-20, -20);
8277 item1->setGraphicsEffect(shadow);
8280 // Make sure all visible items are repainted.
8281 QCOMPARE(item1->repaints, 1);
8282 QCOMPARE(item2->repaints, 1);
8283 QCOMPARE(item3->repaints, 1);
8285 // Make sure an item doesn't respond to a click on its shadow.
8286 QList<QGraphicsItem *> items = scene.items(QPointF(75, 75));
8287 QVERIFY(items.isEmpty());
8288 items = scene.items(QPointF(80, 80));
8289 QCOMPARE(items.size(), 1);
8290 QCOMPARE(items.at(0), static_cast<QGraphicsItem *>(item3));
8292 scene.setItemIndexMethod(QGraphicsScene::NoIndex);
8295 items = scene.items(QPointF(75, 75));
8296 QVERIFY(items.isEmpty());
8297 items = scene.items(QPointF(80, 80));
8298 QCOMPARE(items.size(), 1);
8299 QCOMPARE(items.at(0), static_cast<QGraphicsItem *>(item3));
8302 void tst_QGraphicsItem::focusProxy()
8304 QGraphicsScene scene;
8305 QEvent activate(QEvent::WindowActivate);
8306 QApplication::sendEvent(&scene, &activate);
8308 QGraphicsItem *item = scene.addRect(0, 0, 10, 10);
8309 item->setFlag(QGraphicsItem::ItemIsFocusable);
8310 QVERIFY(!item->focusProxy());
8312 QGraphicsItem *item2 = scene.addRect(0, 0, 10, 10);
8313 item2->setFlag(QGraphicsItem::ItemIsFocusable);
8314 item->setFocusProxy(item2);
8315 QCOMPARE(item->focusProxy(), item2);
8318 QVERIFY(item->hasFocus());
8319 QVERIFY(item2->hasFocus());
8321 // Try to make a focus chain loop
8323 QTextStream stream(&err);
8324 stream << "QGraphicsItem::setFocusProxy: "
8325 << (void*)item << " is already in the focus proxy chain" << flush;
8326 QTest::ignoreMessage(QtWarningMsg, err.toLatin1().constData());
8327 item2->setFocusProxy(item); // fails
8328 QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2);
8329 QCOMPARE(item2->focusProxy(), (QGraphicsItem *)0);
8331 // Try to assign self as focus proxy
8332 QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::setFocusProxy: cannot assign self as focus proxy");
8333 item->setFocusProxy(item); // fails
8334 QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2);
8335 QCOMPARE(item2->focusProxy(), (QGraphicsItem *)0);
8337 // Reset the focus proxy
8338 item->setFocusProxy(0);
8339 QCOMPARE(item->focusProxy(), (QGraphicsItem *)0);
8340 QVERIFY(!item->hasFocus());
8341 QVERIFY(item2->hasFocus());
8344 item->setFocusProxy(item2);
8345 QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2);
8347 QCOMPARE(item->focusProxy(), (QGraphicsItem *)0);
8349 // Test event delivery
8350 item2 = scene.addRect(0, 0, 10, 10);
8351 item2->setFlag(QGraphicsItem::ItemIsFocusable);
8352 item->setFocusProxy(item2);
8355 EventSpy focusInSpy(&scene, item, QEvent::FocusIn);
8356 EventSpy focusOutSpy(&scene, item, QEvent::FocusOut);
8357 EventSpy focusInSpy2(&scene, item2, QEvent::FocusIn);
8358 EventSpy focusOutSpy2(&scene, item2, QEvent::FocusOut);
8359 QCOMPARE(focusInSpy.count(), 0);
8360 QCOMPARE(focusOutSpy.count(), 0);
8361 QCOMPARE(focusInSpy2.count(), 0);
8362 QCOMPARE(focusOutSpy2.count(), 0);
8365 QCOMPARE(focusInSpy.count(), 0);
8366 QCOMPARE(focusInSpy2.count(), 1);
8368 QCOMPARE(focusOutSpy.count(), 0);
8369 QCOMPARE(focusOutSpy2.count(), 1);
8371 // Test two items proxying one item.
8372 QGraphicsItem *item3 = scene.addRect(0, 0, 10, 10);
8373 item3->setFlag(QGraphicsItem::ItemIsFocusable);
8374 item3->setFocusProxy(item2); // item and item3 use item2 as proxy
8376 QCOMPARE(item->focusProxy(), item2);
8377 QCOMPARE(item2->focusProxy(), (QGraphicsItem *)0);
8378 QCOMPARE(item3->focusProxy(), item2);
8380 QCOMPARE(item->focusProxy(), (QGraphicsItem *)0);
8381 QCOMPARE(item3->focusProxy(), (QGraphicsItem *)0);
8384 void tst_QGraphicsItem::subFocus()
8386 // Construct a text item that's not part of a scene (yet)
8387 // and has no parent. Setting focus on it will not make
8388 // the item gain input focus; that requires a scene. But
8389 // it does set subfocus, indicating that the item wishes
8390 // to gain focus later.
8391 QGraphicsTextItem *text = new QGraphicsTextItem("Hello");
8392 text->setTextInteractionFlags(Qt::TextEditorInteraction);
8393 QVERIFY(!text->hasFocus());
8395 QVERIFY(!text->hasFocus());
8396 QCOMPARE(text->focusItem(), (QGraphicsItem *)text);
8399 QGraphicsTextItem *text2 = new QGraphicsTextItem("Hi");
8400 text2->setTextInteractionFlags(Qt::TextEditorInteraction);
8401 text2->setPos(30, 30);
8403 // Add both items to a scene and check that it's text that
8405 QGraphicsScene scene;
8406 QEvent activate(QEvent::WindowActivate);
8407 QApplication::sendEvent(&scene, &activate);
8409 scene.addItem(text);
8410 scene.addItem(text2);
8411 QVERIFY(text->hasFocus());
8413 text->setData(0, "text");
8414 text2->setData(0, "text2");
8416 // Remove text2 and set subfocus on it. Then readd. Reparent it onto the
8417 // other item and see that it gains input focus.
8418 scene.removeItem(text2);
8420 scene.addItem(text2);
8421 QCOMPARE(text2->focusItem(), (QGraphicsItem *)text2);
8422 text2->setParentItem(text);
8423 QCOMPARE(text->focusItem(), (QGraphicsItem *)text2);
8424 QCOMPARE(text2->focusItem(), (QGraphicsItem *)text2);
8425 QVERIFY(!text->hasFocus());
8426 QVERIFY(text2->hasFocus());
8428 // Remove both items from the scene, restore subfocus and
8429 // readd them. Now the subfocus should kick in and give
8431 scene.removeItem(text);
8432 QCOMPARE(text->focusItem(), (QGraphicsItem *)0);
8433 QCOMPARE(text2->focusItem(), (QGraphicsItem *)0);
8435 QCOMPARE(text->focusItem(), (QGraphicsItem *)text2);
8436 QCOMPARE(text2->focusItem(), (QGraphicsItem *)text2);
8437 scene.addItem(text);
8439 // Hiding and showing text should pass focus to text2.
8440 QCOMPARE(text->focusItem(), (QGraphicsItem *)text2);
8441 QVERIFY(text2->hasFocus());
8443 // Subfocus should repropagate to root when reparenting.
8444 QGraphicsRectItem *rect = new QGraphicsRectItem;
8445 QGraphicsRectItem *rect2 = new QGraphicsRectItem(rect);
8446 QGraphicsRectItem *rect3 = new QGraphicsRectItem(rect2);
8447 rect3->setFlag(QGraphicsItem::ItemIsFocusable);
8449 text->setData(0, "text");
8450 text2->setData(0, "text2");
8451 rect->setData(0, "rect");
8452 rect2->setData(0, "rect2");
8453 rect3->setData(0, "rect3");
8456 QVERIFY(!rect3->hasFocus());
8457 QCOMPARE(rect->focusItem(), (QGraphicsItem *)rect3);
8458 QCOMPARE(rect2->focusItem(), (QGraphicsItem *)rect3);
8459 QCOMPARE(rect3->focusItem(), (QGraphicsItem *)rect3);
8460 rect->setParentItem(text2);
8461 QCOMPARE(text->focusItem(), (QGraphicsItem *)rect3);
8462 QCOMPARE(text2->focusItem(), (QGraphicsItem *)rect3);
8463 QCOMPARE(rect->focusItem(), (QGraphicsItem *)rect3);
8464 QCOMPARE(rect2->focusItem(), (QGraphicsItem *)rect3);
8465 QCOMPARE(rect3->focusItem(), (QGraphicsItem *)rect3);
8466 QVERIFY(!rect->hasFocus());
8467 QVERIFY(!rect2->hasFocus());
8468 QVERIFY(rect3->hasFocus());
8471 QCOMPARE(text->focusItem(), (QGraphicsItem *)0);
8472 QCOMPARE(text2->focusItem(), (QGraphicsItem *)0);
8473 QCOMPARE(rect->focusItem(), (QGraphicsItem *)0);
8476 void tst_QGraphicsItem::focusProxyDeletion()
8478 QGraphicsRectItem *rect = new QGraphicsRectItem;
8479 QGraphicsRectItem *rect2 = new QGraphicsRectItem;
8480 rect->setFocusProxy(rect2);
8481 QCOMPARE(rect->focusProxy(), (QGraphicsItem *)rect2);
8484 QCOMPARE(rect->focusProxy(), (QGraphicsItem *)0);
8486 rect2 = new QGraphicsRectItem;
8487 rect->setFocusProxy(rect2);
8488 delete rect; // don't crash
8490 rect = new QGraphicsRectItem;
8491 rect->setFocusProxy(rect2);
8492 QGraphicsScene *scene = new QGraphicsScene;
8493 scene->addItem(rect);
8494 scene->addItem(rect2);
8496 QCOMPARE(rect->focusProxy(), (QGraphicsItem *)0);
8498 rect2 = new QGraphicsRectItem;
8499 QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::setFocusProxy: focus proxy must be in same scene");
8500 rect->setFocusProxy(rect2);
8501 QCOMPARE(rect->focusProxy(), (QGraphicsItem *)0);
8502 scene->addItem(rect2);
8503 rect->setFocusProxy(rect2);
8504 QCOMPARE(rect->focusProxy(), (QGraphicsItem *)rect2);
8505 delete rect; // don't crash
8507 rect = new QGraphicsRectItem;
8508 rect2 = new QGraphicsRectItem;
8509 rect->setFocusProxy(rect2);
8510 QCOMPARE(rect->focusProxy(), (QGraphicsItem *)rect2);
8511 scene->addItem(rect);
8512 scene->addItem(rect2);
8513 rect->setFocusProxy(rect2);
8514 delete scene; // don't crash
8517 void tst_QGraphicsItem::negativeZStacksBehindParent()
8519 QGraphicsRectItem rect;
8520 QCOMPARE(rect.zValue(), qreal(0.0));
8521 QVERIFY(!(rect.flags() & QGraphicsItem::ItemNegativeZStacksBehindParent));
8522 QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
8524 QCOMPARE(rect.zValue(), qreal(-1.0));
8525 QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
8527 rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent);
8528 QVERIFY(rect.flags() & QGraphicsItem::ItemNegativeZStacksBehindParent);
8529 QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
8531 QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent);
8533 QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
8534 rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, false);
8536 rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, true);
8537 QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent);
8538 rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, false);
8539 QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent);
8542 void tst_QGraphicsItem::setGraphicsEffect()
8544 // Check that we don't have any effect by default.
8545 QGraphicsItem *item = new QGraphicsRectItem(0, 0, 10, 10);
8546 QVERIFY(!item->graphicsEffect());
8549 QPointer<QGraphicsEffect> blurEffect = new QGraphicsBlurEffect;
8550 item->setGraphicsEffect(blurEffect);
8551 QCOMPARE(item->graphicsEffect(), static_cast<QGraphicsEffect *>(blurEffect));
8553 // Ensure the existing effect is deleted when setting a new one.
8554 QPointer<QGraphicsEffect> shadowEffect = new QGraphicsDropShadowEffect;
8555 item->setGraphicsEffect(shadowEffect);
8556 QVERIFY(!blurEffect);
8557 QCOMPARE(item->graphicsEffect(), static_cast<QGraphicsEffect *>(shadowEffect));
8558 blurEffect = new QGraphicsBlurEffect;
8560 // Ensure the effect is uninstalled when setting it on a new target.
8561 QGraphicsItem *anotherItem = new QGraphicsRectItem(0, 0, 10, 10);
8562 anotherItem->setGraphicsEffect(blurEffect);
8563 item->setGraphicsEffect(blurEffect);
8564 QVERIFY(!anotherItem->graphicsEffect());
8565 QVERIFY(!shadowEffect);
8567 // Ensure the existing effect is deleted when deleting the item.
8569 QVERIFY(!blurEffect);
8572 // Ensure the effect is uninstalled when deleting it
8573 item = new QGraphicsRectItem(0, 0, 10, 10);
8574 blurEffect = new QGraphicsBlurEffect;
8575 item->setGraphicsEffect(blurEffect);
8577 QVERIFY(!item->graphicsEffect());
8579 // Ensure the existing effect is uninstalled and deleted when setting a null effect
8580 blurEffect = new QGraphicsBlurEffect;
8581 item->setGraphicsEffect(blurEffect);
8582 item->setGraphicsEffect(0);
8583 QVERIFY(!item->graphicsEffect());
8584 QVERIFY(!blurEffect);
8589 void tst_QGraphicsItem::panel()
8591 QGraphicsScene scene;
8593 QGraphicsRectItem *panel1 = new QGraphicsRectItem;
8594 QGraphicsRectItem *panel2 = new QGraphicsRectItem;
8595 QGraphicsRectItem *panel3 = new QGraphicsRectItem;
8596 QGraphicsRectItem *panel4 = new QGraphicsRectItem;
8597 QGraphicsRectItem *notPanel1 = new QGraphicsRectItem;
8598 QGraphicsRectItem *notPanel2 = new QGraphicsRectItem;
8599 panel1->setFlag(QGraphicsItem::ItemIsPanel);
8600 panel2->setFlag(QGraphicsItem::ItemIsPanel);
8601 panel3->setFlag(QGraphicsItem::ItemIsPanel);
8602 panel4->setFlag(QGraphicsItem::ItemIsPanel);
8603 scene.addItem(panel1);
8604 scene.addItem(panel2);
8605 scene.addItem(panel3);
8606 scene.addItem(panel4);
8607 scene.addItem(notPanel1);
8608 scene.addItem(notPanel2);
8610 EventSpy spy_activate_panel1(&scene, panel1, QEvent::WindowActivate);
8611 EventSpy spy_deactivate_panel1(&scene, panel1, QEvent::WindowDeactivate);
8612 EventSpy spy_activate_panel2(&scene, panel2, QEvent::WindowActivate);
8613 EventSpy spy_deactivate_panel2(&scene, panel2, QEvent::WindowDeactivate);
8614 EventSpy spy_activate_panel3(&scene, panel3, QEvent::WindowActivate);
8615 EventSpy spy_deactivate_panel3(&scene, panel3, QEvent::WindowDeactivate);
8616 EventSpy spy_activate_panel4(&scene, panel4, QEvent::WindowActivate);
8617 EventSpy spy_deactivate_panel4(&scene, panel4, QEvent::WindowDeactivate);
8618 EventSpy spy_activate_notPanel1(&scene, notPanel1, QEvent::WindowActivate);
8619 EventSpy spy_deactivate_notPanel1(&scene, notPanel1, QEvent::WindowDeactivate);
8620 EventSpy spy_activate_notPanel2(&scene, notPanel1, QEvent::WindowActivate);
8621 EventSpy spy_deactivate_notPanel2(&scene, notPanel1, QEvent::WindowDeactivate);
8623 QCOMPARE(spy_activate_panel1.count(), 0);
8624 QCOMPARE(spy_deactivate_panel1.count(), 0);
8625 QCOMPARE(spy_activate_panel2.count(), 0);
8626 QCOMPARE(spy_deactivate_panel2.count(), 0);
8627 QCOMPARE(spy_activate_panel3.count(), 0);
8628 QCOMPARE(spy_deactivate_panel3.count(), 0);
8629 QCOMPARE(spy_activate_panel4.count(), 0);
8630 QCOMPARE(spy_deactivate_panel4.count(), 0);
8631 QCOMPARE(spy_activate_notPanel1.count(), 0);
8632 QCOMPARE(spy_deactivate_notPanel1.count(), 0);
8633 QCOMPARE(spy_activate_notPanel2.count(), 0);
8634 QCOMPARE(spy_deactivate_notPanel2.count(), 0);
8636 QVERIFY(!scene.activePanel());
8637 QVERIFY(!scene.isActive());
8639 QEvent activate(QEvent::WindowActivate);
8640 QEvent deactivate(QEvent::WindowDeactivate);
8642 QApplication::sendEvent(&scene, &activate);
8644 // No previous activation, so the scene is active.
8645 QVERIFY(scene.isActive());
8646 QCOMPARE(scene.activePanel(), (QGraphicsItem *)panel1);
8647 QVERIFY(panel1->isActive());
8648 QVERIFY(!panel2->isActive());
8649 QVERIFY(!panel3->isActive());
8650 QVERIFY(!panel4->isActive());
8651 QVERIFY(!notPanel1->isActive());
8652 QVERIFY(!notPanel2->isActive());
8653 QCOMPARE(spy_deactivate_notPanel1.count(), 0);
8654 QCOMPARE(spy_deactivate_notPanel2.count(), 0);
8655 QCOMPARE(spy_activate_panel1.count(), 1);
8656 QCOMPARE(spy_activate_panel2.count(), 0);
8657 QCOMPARE(spy_activate_panel3.count(), 0);
8658 QCOMPARE(spy_activate_panel4.count(), 0);
8660 // Switch back to scene.
8661 scene.setActivePanel(0);
8662 QVERIFY(!scene.activePanel());
8663 QVERIFY(!panel1->isActive());
8664 QVERIFY(!panel2->isActive());
8665 QVERIFY(!panel3->isActive());
8666 QVERIFY(!panel4->isActive());
8667 QVERIFY(notPanel1->isActive());
8668 QVERIFY(notPanel2->isActive());
8669 QCOMPARE(spy_activate_notPanel1.count(), 1);
8670 QCOMPARE(spy_activate_notPanel2.count(), 1);
8672 // Deactivate the scene
8673 QApplication::sendEvent(&scene, &deactivate);
8674 QVERIFY(!scene.activePanel());
8675 QVERIFY(!panel1->isActive());
8676 QVERIFY(!panel2->isActive());
8677 QVERIFY(!panel3->isActive());
8678 QVERIFY(!panel4->isActive());
8679 QVERIFY(!notPanel1->isActive());
8680 QVERIFY(!notPanel2->isActive());
8681 QCOMPARE(spy_deactivate_notPanel1.count(), 1);
8682 QCOMPARE(spy_deactivate_notPanel2.count(), 1);
8684 // Reactivate the scene
8685 QApplication::sendEvent(&scene, &activate);
8686 QVERIFY(!scene.activePanel());
8687 QVERIFY(!panel1->isActive());
8688 QVERIFY(!panel2->isActive());
8689 QVERIFY(!panel3->isActive());
8690 QVERIFY(!panel4->isActive());
8691 QVERIFY(notPanel1->isActive());
8692 QVERIFY(notPanel2->isActive());
8693 QCOMPARE(spy_activate_notPanel1.count(), 2);
8694 QCOMPARE(spy_activate_notPanel2.count(), 2);
8697 scene.setActivePanel(panel1);
8698 QVERIFY(panel1->isActive());
8699 QCOMPARE(spy_deactivate_notPanel1.count(), 2);
8700 QCOMPARE(spy_deactivate_notPanel2.count(), 2);
8701 QCOMPARE(spy_activate_panel1.count(), 2);
8703 // Deactivate the scene
8704 QApplication::sendEvent(&scene, &deactivate);
8705 QVERIFY(!panel1->isActive());
8706 QCOMPARE(spy_deactivate_panel1.count(), 2);
8708 // Reactivate the scene
8709 QApplication::sendEvent(&scene, &activate);
8710 QVERIFY(panel1->isActive());
8711 QCOMPARE(spy_activate_panel1.count(), 3);
8713 // Deactivate the scene
8714 QApplication::sendEvent(&scene, &deactivate);
8715 QVERIFY(!panel1->isActive());
8716 QVERIFY(!scene.activePanel());
8717 scene.setActivePanel(0);
8719 // Reactivate the scene
8720 QApplication::sendEvent(&scene, &activate);
8721 QVERIFY(!panel1->isActive());
8724 void tst_QGraphicsItem::panelWithFocusItem()
8726 QGraphicsScene scene;
8727 QEvent activate(QEvent::WindowActivate);
8728 QApplication::sendEvent(&scene, &activate);
8730 QGraphicsRectItem *parentPanel = new QGraphicsRectItem;
8731 QGraphicsRectItem *parentPanelFocusItem = new QGraphicsRectItem(parentPanel);
8732 parentPanel->setFlag(QGraphicsItem::ItemIsPanel);
8733 parentPanelFocusItem->setFlag(QGraphicsItem::ItemIsFocusable);
8734 parentPanelFocusItem->setFocus();
8735 scene.addItem(parentPanel);
8737 QVERIFY(parentPanel->isActive());
8738 QVERIFY(parentPanelFocusItem->hasFocus());
8739 QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
8740 QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
8742 QGraphicsRectItem *childPanel = new QGraphicsRectItem;
8743 QGraphicsRectItem *childPanelFocusItem = new QGraphicsRectItem(childPanel);
8744 childPanel->setFlag(QGraphicsItem::ItemIsPanel);
8745 childPanelFocusItem->setFlag(QGraphicsItem::ItemIsFocusable);
8746 childPanelFocusItem->setFocus();
8748 QVERIFY(!childPanelFocusItem->hasFocus());
8749 QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)childPanelFocusItem);
8750 QCOMPARE(childPanelFocusItem->focusItem(), (QGraphicsItem *)childPanelFocusItem);
8752 childPanel->setParentItem(parentPanel);
8754 QVERIFY(!parentPanel->isActive());
8755 QVERIFY(!parentPanelFocusItem->hasFocus());
8756 QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
8757 QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
8759 QVERIFY(childPanel->isActive());
8760 QVERIFY(childPanelFocusItem->hasFocus());
8761 QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)childPanelFocusItem);
8762 QCOMPARE(childPanelFocusItem->focusItem(), (QGraphicsItem *)childPanelFocusItem);
8766 QVERIFY(parentPanel->isActive());
8767 QVERIFY(parentPanelFocusItem->hasFocus());
8768 QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
8769 QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
8772 void tst_QGraphicsItem::addPanelToActiveScene()
8774 QGraphicsScene scene;
8775 QVERIFY(!scene.isActive());
8777 QGraphicsRectItem *rect = new QGraphicsRectItem;
8778 scene.addItem(rect);
8779 QVERIFY(!rect->isActive());
8780 scene.removeItem(rect);
8782 QEvent activate(QEvent::WindowActivate);
8783 QEvent deactivate(QEvent::WindowDeactivate);
8785 QApplication::sendEvent(&scene, &activate);
8786 QVERIFY(scene.isActive());
8787 scene.addItem(rect);
8788 QVERIFY(rect->isActive());
8789 scene.removeItem(rect);
8791 rect->setFlag(QGraphicsItem::ItemIsPanel);
8792 scene.addItem(rect);
8793 QVERIFY(rect->isActive());
8794 QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect);
8796 QGraphicsRectItem *rect2 = new QGraphicsRectItem;
8797 scene.addItem(rect2);
8798 QVERIFY(rect->isActive());
8799 QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect);
8802 void tst_QGraphicsItem::activate()
8804 QGraphicsScene scene;
8805 QGraphicsRectItem *rect = scene.addRect(-10, -10, 20, 20);
8806 QVERIFY(!rect->isActive());
8808 QEvent activate(QEvent::WindowActivate);
8809 QEvent deactivate(QEvent::WindowDeactivate);
8811 QApplication::sendEvent(&scene, &activate);
8813 // Non-panel item (active when scene is active).
8814 QVERIFY(rect->isActive());
8816 QGraphicsRectItem *rect2 = new QGraphicsRectItem;
8817 rect2->setFlag(QGraphicsItem::ItemIsPanel);
8818 QGraphicsRectItem *rect3 = new QGraphicsRectItem;
8819 rect3->setFlag(QGraphicsItem::ItemIsPanel);
8821 // Test normal activation.
8822 QVERIFY(!rect2->isActive());
8823 scene.addItem(rect2);
8824 QVERIFY(rect2->isActive()); // first panel item is activated
8825 scene.addItem(rect3);
8826 QVERIFY(!rect3->isActive()); // second panel item is _not_ activated
8827 rect3->setActive(true);
8828 QVERIFY(rect3->isActive());
8829 scene.removeItem(rect3);
8830 QVERIFY(!rect3->isActive()); // no panel is active anymore
8831 QCOMPARE(scene.activePanel(), (QGraphicsItem *)0);
8832 scene.addItem(rect3);
8833 QVERIFY(rect3->isActive()); // second panel item is activated
8835 // Test pending activation.
8836 scene.removeItem(rect3);
8837 rect2->setActive(true);
8838 QVERIFY(rect2->isActive()); // first panel item is activated
8839 rect3->setActive(true);
8840 QVERIFY(!rect3->isActive()); // not active (yet)
8841 scene.addItem(rect3);
8842 QVERIFY(rect3->isActive()); // now becomes active
8844 // Test pending deactivation.
8845 scene.removeItem(rect3);
8846 rect3->setActive(false);
8847 scene.addItem(rect3);
8848 QVERIFY(!rect3->isActive()); // doesn't become active
8850 // Child of panel activation.
8851 rect3->setActive(true);
8852 QGraphicsRectItem *rect4 = new QGraphicsRectItem;
8853 rect4->setFlag(QGraphicsItem::ItemIsPanel);
8854 QGraphicsRectItem *rect5 = new QGraphicsRectItem(rect4);
8855 QGraphicsRectItem *rect6 = new QGraphicsRectItem(rect5);
8856 scene.addItem(rect4);
8857 QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect3);
8858 scene.removeItem(rect4);
8859 rect6->setActive(true);
8860 scene.addItem(rect4);
8861 QVERIFY(rect4->isActive());
8862 QVERIFY(rect5->isActive());
8863 QVERIFY(rect6->isActive());
8864 QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect4);
8865 scene.removeItem(rect4); // no active panel
8866 rect6->setActive(false);
8867 scene.addItem(rect4);
8868 QVERIFY(!rect4->isActive());
8869 QVERIFY(!rect5->isActive());
8870 QVERIFY(!rect6->isActive());
8871 QCOMPARE(scene.activePanel(), (QGraphicsItem *)0);
8873 // Controlling auto-activation when the scene changes activation.
8874 rect4->setActive(true);
8875 QApplication::sendEvent(&scene, &deactivate);
8876 QVERIFY(!scene.isActive());
8877 QVERIFY(!rect4->isActive());
8878 rect4->setActive(false);
8879 QApplication::sendEvent(&scene, &activate);
8880 QVERIFY(scene.isActive());
8881 QVERIFY(!scene.activePanel());
8882 QVERIFY(!rect4->isActive());
8885 void tst_QGraphicsItem::setActivePanelOnInactiveScene()
8887 QGraphicsScene scene;
8888 QGraphicsRectItem *item = scene.addRect(QRectF());
8889 QGraphicsRectItem *panel = scene.addRect(QRectF());
8890 panel->setFlag(QGraphicsItem::ItemIsPanel);
8892 EventSpy itemActivateSpy(&scene, item, QEvent::WindowActivate);
8893 EventSpy itemDeactivateSpy(&scene, item, QEvent::WindowDeactivate);
8894 EventSpy panelActivateSpy(&scene, panel, QEvent::WindowActivate);
8895 EventSpy panelDeactivateSpy(&scene, panel, QEvent::WindowDeactivate);
8896 EventSpy sceneActivationChangeSpy(&scene, QEvent::ActivationChange);
8898 scene.setActivePanel(panel);
8899 QCOMPARE(scene.activePanel(), (QGraphicsItem *)0);
8900 QCOMPARE(itemActivateSpy.count(), 0);
8901 QCOMPARE(itemDeactivateSpy.count(), 0);
8902 QCOMPARE(panelActivateSpy.count(), 0);
8903 QCOMPARE(panelDeactivateSpy.count(), 0);
8904 QCOMPARE(sceneActivationChangeSpy.count(), 0);
8907 void tst_QGraphicsItem::activationOnShowHide()
8909 QGraphicsScene scene;
8910 QEvent activate(QEvent::WindowActivate);
8911 QApplication::sendEvent(&scene, &activate);
8913 QGraphicsRectItem *rootPanel = scene.addRect(QRectF());
8914 rootPanel->setFlag(QGraphicsItem::ItemIsPanel);
8915 rootPanel->setActive(true);
8917 QGraphicsRectItem *subPanel = new QGraphicsRectItem;
8918 subPanel->setFlag(QGraphicsItem::ItemIsPanel);
8920 // Reparenting onto an active panel auto-activates the child panel.
8921 subPanel->setParentItem(rootPanel);
8922 QVERIFY(subPanel->isActive());
8923 QVERIFY(!rootPanel->isActive());
8925 // Hiding an active child panel will reactivate the parent panel.
8927 QVERIFY(rootPanel->isActive());
8929 // Showing a child panel will auto-activate it.
8931 QVERIFY(subPanel->isActive());
8932 QVERIFY(!rootPanel->isActive());
8934 // Adding an unrelated panel doesn't affect activation.
8935 QGraphicsRectItem *otherPanel = new QGraphicsRectItem;
8936 otherPanel->setFlag(QGraphicsItem::ItemIsPanel);
8937 scene.addItem(otherPanel);
8938 QVERIFY(subPanel->isActive());
8940 // Showing an unrelated panel doesn't affect activation.
8943 QVERIFY(subPanel->isActive());
8945 // Add a non-panel item.
8946 QGraphicsRectItem *otherItem = new QGraphicsRectItem;
8947 scene.addItem(otherItem);
8948 otherItem->setActive(true);
8949 QVERIFY(otherItem->isActive());
8951 // Reparent a panel onto an active non-panel item.
8952 subPanel->setParentItem(otherItem);
8953 QVERIFY(subPanel->isActive());
8955 // Showing a child panel of a non-panel item will activate it.
8957 QVERIFY(!subPanel->isActive());
8958 QVERIFY(otherItem->isActive());
8960 QVERIFY(subPanel->isActive());
8962 // Hiding a toplevel active panel will pass activation back
8963 // to the non-panel items.
8964 rootPanel->setActive(true);
8966 QVERIFY(!rootPanel->isActive());
8967 QVERIFY(otherItem->isActive());
8970 class MoveWhileDying : public QGraphicsRectItem
8973 MoveWhileDying(QGraphicsItem *parent = 0)
8974 : QGraphicsRectItem(parent)
8978 foreach (QGraphicsItem *c, childItems()) {
8979 foreach (QGraphicsItem *cc, c->childItems()) {
8984 if (QGraphicsItem *p = parentItem()) { p->moveBy(10, 10); }
8988 void tst_QGraphicsItem::moveWhileDeleting()
8990 QGraphicsScene scene;
8991 QGraphicsRectItem *rect = new QGraphicsRectItem;
8992 MoveWhileDying *silly = new MoveWhileDying(rect);
8993 QGraphicsRectItem *child = new QGraphicsRectItem(silly);
8994 scene.addItem(rect);
8995 delete rect; // don't crash!
8997 rect = new QGraphicsRectItem;
8998 silly = new MoveWhileDying(rect);
8999 child = new QGraphicsRectItem(silly);
9001 QGraphicsView view(&scene);
9003 QVERIFY(QTest::qWaitForWindowExposed(&view));
9007 rect = new QGraphicsRectItem;
9008 rect->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
9009 silly = new MoveWhileDying(rect);
9010 child = new QGraphicsRectItem(silly);
9016 rect = new MoveWhileDying;
9017 rect->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
9018 child = new QGraphicsRectItem(rect);
9019 silly = new MoveWhileDying(child);
9026 class MyRectItem : public QGraphicsWidget
9030 MyRectItem(QGraphicsItem *parent = 0) : QGraphicsWidget(parent)
9035 void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
9037 painter->setBrush(brush);
9038 painter->drawRect(boundingRect());
9043 topLevel->collidingItems(Qt::IntersectsItemBoundingRect);
9046 QGraphicsItem *topLevel;
9051 void tst_QGraphicsItem::ensureDirtySceneTransform()
9053 QGraphicsScene scene;
9055 MyRectItem *topLevel = new MyRectItem;
9056 topLevel->setGeometry(0, 0, 100, 100);
9057 topLevel->setPos(-50, -50);
9058 topLevel->brush = QBrush(QColor(Qt::black));
9059 scene.addItem(topLevel);
9061 MyRectItem *parent = new MyRectItem;
9062 parent->topLevel = topLevel;
9063 parent->setGeometry(0, 0, 100, 100);
9064 parent->setPos(0, 0);
9065 parent->brush = QBrush(QColor(Qt::magenta));
9066 parent->setObjectName("parent");
9067 scene.addItem(parent);
9069 MyRectItem *child = new MyRectItem(parent);
9070 child->setGeometry(0, 0, 80, 80);
9071 child->setPos(10, 10);
9072 child->setObjectName("child");
9073 child->brush = QBrush(QColor(Qt::blue));
9075 MyRectItem *child2 = new MyRectItem(parent);
9076 child2->setGeometry(0, 0, 80, 80);
9077 child2->setPos(15, 15);
9078 child2->setObjectName("child2");
9079 child2->brush = QBrush(QColor(Qt::green));
9081 MyRectItem *child3 = new MyRectItem(parent);
9082 child3->setGeometry(0, 0, 80, 80);
9083 child3->setPos(20, 20);
9084 child3->setObjectName("child3");
9085 child3->brush = QBrush(QColor(Qt::gray));
9087 QGraphicsView view(&scene);
9089 QApplication::setActiveWindow(&view);
9090 QVERIFY(QTest::qWaitForWindowActive(&view));
9091 QCOMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
9093 //We move the parent
9095 QApplication::processEvents();
9097 //We check if all items moved
9098 QCOMPARE(child->pos(), QPointF(10, 10));
9099 QCOMPARE(child2->pos(), QPointF(15, 15));
9100 QCOMPARE(child3->pos(), QPointF(20, 20));
9102 QCOMPARE(child->sceneBoundingRect(), QRectF(-90, -90, 80, 80));
9103 QCOMPARE(child2->sceneBoundingRect(), QRectF(-85, -85, 80, 80));
9104 QCOMPARE(child3->sceneBoundingRect(), QRectF(-80, -80, 80, 80));
9106 QCOMPARE(child->sceneTransform(), QTransform::fromTranslate(-90, -90));
9107 QCOMPARE(child2->sceneTransform(), QTransform::fromTranslate(-85, -85));
9108 QCOMPARE(child3->sceneTransform(), QTransform::fromTranslate(-80, -80));
9111 void tst_QGraphicsItem::focusScope()
9113 // ItemIsFocusScope is an internal feature (for now).
9114 QGraphicsScene scene;
9116 QGraphicsRectItem *scope3 = new QGraphicsRectItem;
9117 scope3->setData(0, "scope3");
9118 scope3->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9120 QVERIFY(!scope3->focusScopeItem());
9121 QCOMPARE(scope3->focusItem(), (QGraphicsItem *)scope3);
9123 QGraphicsRectItem *scope2 = new QGraphicsRectItem;
9124 scope2->setData(0, "scope2");
9125 scope2->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9127 QVERIFY(!scope2->focusScopeItem());
9128 scope3->setParentItem(scope2);
9129 QCOMPARE(scope2->focusScopeItem(), (QGraphicsItem *)scope3);
9130 QCOMPARE(scope2->focusItem(), (QGraphicsItem *)scope3);
9132 QGraphicsRectItem *scope1 = new QGraphicsRectItem;
9133 scope1->setData(0, "scope1");
9134 scope1->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9136 QVERIFY(!scope1->focusScopeItem());
9137 scope2->setParentItem(scope1);
9139 QCOMPARE(scope1->focusItem(), (QGraphicsItem *)scope3);
9140 QCOMPARE(scope2->focusItem(), (QGraphicsItem *)scope3);
9141 QCOMPARE(scope3->focusItem(), (QGraphicsItem *)scope3);
9142 QCOMPARE(scope1->focusScopeItem(), (QGraphicsItem *)scope2);
9143 QCOMPARE(scope2->focusScopeItem(), (QGraphicsItem *)scope3);
9144 QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)0);
9146 scene.addItem(scope1);
9148 QEvent windowActivate(QEvent::WindowActivate);
9149 qApp->sendEvent(&scene, &windowActivate);
9152 QCOMPARE(scope1->focusItem(), (QGraphicsItem *)scope3);
9153 QCOMPARE(scope2->focusItem(), (QGraphicsItem *)scope3);
9154 QCOMPARE(scope3->focusItem(), (QGraphicsItem *)scope3);
9155 QCOMPARE(scope1->focusScopeItem(), (QGraphicsItem *)scope2);
9156 QCOMPARE(scope2->focusScopeItem(), (QGraphicsItem *)scope3);
9157 QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)0);
9159 QVERIFY(scope3->hasFocus());
9162 QVERIFY(scope2->hasFocus());
9164 QVERIFY(scope1->hasFocus());
9166 QVERIFY(scope2->hasFocus());
9168 QVERIFY(scope3->hasFocus());
9170 QVERIFY(!scope3->hasFocus());
9172 QVERIFY(scope3->hasFocus());
9173 scope3->clearFocus();
9174 QVERIFY(scope2->hasFocus());
9175 scope2->clearFocus();
9176 QVERIFY(scope1->hasFocus());
9179 QVERIFY(!scope2->hasFocus());
9180 QVERIFY(scope1->hasFocus());
9182 QVERIFY(scope2->hasFocus());
9184 QVERIFY(scope3->hasFocus());
9186 QGraphicsRectItem *rect4 = new QGraphicsRectItem;
9187 rect4->setData(0, "rect4");
9188 rect4->setParentItem(scope3);
9190 QGraphicsRectItem *rect5 = new QGraphicsRectItem;
9191 rect5->setData(0, "rect5");
9192 rect5->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9194 rect5->setParentItem(rect4);
9195 QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)rect5);
9196 QVERIFY(rect5->hasFocus());
9198 rect4->setParentItem(0);
9199 QVERIFY(rect5->hasFocus());
9200 QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)0);
9201 QCOMPARE(scope3->focusItem(), (QGraphicsItem *)0);
9202 QVERIFY(!scope3->hasFocus());
9204 QGraphicsRectItem *rectA = new QGraphicsRectItem;
9205 QGraphicsRectItem *scopeA = new QGraphicsRectItem(rectA);
9206 scopeA->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9208 QGraphicsRectItem *scopeB = new QGraphicsRectItem(scopeA);
9209 scopeB->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9212 scene.addItem(rectA);
9213 QVERIFY(rect5->hasFocus());
9214 QVERIFY(!scopeB->hasFocus());
9217 QVERIFY(scopeB->hasFocus());
9218 QCOMPARE(scopeB->focusItem(), (QGraphicsItem *)scopeB);
9221 void tst_QGraphicsItem::focusScope2()
9223 QGraphicsRectItem *child1 = new QGraphicsRectItem;
9224 child1->setFlags(QGraphicsItem::ItemIsFocusable);
9226 QCOMPARE(child1->focusItem(), (QGraphicsItem *)child1);
9228 QGraphicsRectItem *child2 = new QGraphicsRectItem;
9229 child2->setFlags(QGraphicsItem::ItemIsFocusable);
9231 QGraphicsRectItem *rootFocusScope = new QGraphicsRectItem;
9232 rootFocusScope->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9233 rootFocusScope->setFocus();
9234 QCOMPARE(rootFocusScope->focusItem(), (QGraphicsItem *)rootFocusScope);
9236 child1->setParentItem(rootFocusScope);
9237 child2->setParentItem(rootFocusScope);
9239 QCOMPARE(rootFocusScope->focusScopeItem(), (QGraphicsItem *)child1);
9240 QCOMPARE(rootFocusScope->focusItem(), (QGraphicsItem *)child1);
9242 QGraphicsRectItem *siblingChild1 = new QGraphicsRectItem;
9243 siblingChild1->setFlags(QGraphicsItem::ItemIsFocusable);
9244 siblingChild1->setFocus();
9246 QGraphicsRectItem *siblingChild2 = new QGraphicsRectItem;
9247 siblingChild2->setFlags(QGraphicsItem::ItemIsFocusable);
9249 QGraphicsRectItem *siblingFocusScope = new QGraphicsRectItem;
9250 siblingFocusScope->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9252 siblingChild1->setParentItem(siblingFocusScope);
9253 siblingChild2->setParentItem(siblingFocusScope);
9255 QCOMPARE(siblingFocusScope->focusScopeItem(), (QGraphicsItem *)siblingChild1);
9256 QCOMPARE(siblingFocusScope->focusItem(), (QGraphicsItem *)0);
9258 QGraphicsItem *root = new QGraphicsRectItem;
9259 rootFocusScope->setParentItem(root);
9260 siblingFocusScope->setParentItem(root);
9262 QCOMPARE(root->focusItem(), (QGraphicsItem *)child1);
9264 QGraphicsScene scene;
9265 scene.addItem(root);
9267 QEvent activate(QEvent::WindowActivate);
9268 qApp->sendEvent(&scene, &activate);
9271 QCOMPARE(scene.focusItem(), (QGraphicsItem *)child1);
9273 // You cannot set focus on a descendant of a focus scope directly;
9274 // this will only change the scope's focus scope item pointer. If
9275 // you want to give true input focus, you must set it directly on
9277 siblingChild2->setFocus();
9278 QVERIFY(!siblingChild2->hasFocus());
9279 QVERIFY(!siblingChild2->focusItem());
9280 QCOMPARE(siblingFocusScope->focusScopeItem(), (QGraphicsItem *)siblingChild2);
9281 QCOMPARE(siblingFocusScope->focusItem(), (QGraphicsItem *)0);
9283 // Set focus on the scope; focus is forwarded to the focus scope item.
9284 siblingFocusScope->setFocus();
9285 QVERIFY(siblingChild2->hasFocus());
9286 QVERIFY(siblingChild2->focusItem());
9287 QCOMPARE(siblingFocusScope->focusScopeItem(), (QGraphicsItem *)siblingChild2);
9288 QCOMPARE(siblingFocusScope->focusItem(), (QGraphicsItem *)siblingChild2);
9291 void tst_QGraphicsItem::stackBefore()
9293 QGraphicsRectItem parent;
9294 QGraphicsRectItem *child1 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
9295 QGraphicsRectItem *child2 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
9296 QGraphicsRectItem *child3 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
9297 QGraphicsRectItem *child4 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
9298 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
9299 child1->setData(0, "child1");
9300 child2->setData(0, "child2");
9301 child3->setData(0, "child3");
9302 child4->setData(0, "child4");
9304 // Remove and append
9305 child2->setParentItem(0);
9306 child2->setParentItem(&parent);
9307 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child3 << child4 << child2));
9309 // Move child2 before child1
9310 child2->stackBefore(child1); // 2134
9311 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
9312 child2->stackBefore(child2); // 2134
9313 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
9314 child1->setZValue(1); // 2341
9315 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
9316 child1->stackBefore(child2); // 2341
9317 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
9318 child1->setZValue(0); // 1234
9319 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
9320 child4->stackBefore(child1); // 4123
9321 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child4 << child1 << child2 << child3));
9322 child4->setZValue(1); // 1234 (4123)
9323 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
9324 child3->stackBefore(child1); // 3124 (4312)
9325 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child3 << child1 << child2 << child4));
9326 child4->setZValue(0); // 4312
9327 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child4 << child3 << child1 << child2));
9329 // Make them all toplevels
9330 child1->setParentItem(0);
9331 child2->setParentItem(0);
9332 child3->setParentItem(0);
9333 child4->setParentItem(0);
9335 QGraphicsScene scene;
9336 scene.addItem(child1);
9337 scene.addItem(child2);
9338 scene.addItem(child3);
9339 scene.addItem(child4);
9340 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder),
9341 (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
9343 // Remove and append
9344 scene.removeItem(child2);
9345 scene.addItem(child2);
9346 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child1 << child3 << child4 << child2));
9348 // Move child2 before child1
9349 child2->stackBefore(child1); // 2134
9350 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
9351 child2->stackBefore(child2); // 2134
9352 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
9353 child1->setZValue(1); // 2341
9354 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
9355 child1->stackBefore(child2); // 2341
9356 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
9357 child1->setZValue(0); // 1234
9358 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
9359 child4->stackBefore(child1); // 4123
9360 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child4 << child1 << child2 << child3));
9361 child4->setZValue(1); // 1234 (4123)
9362 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
9363 child3->stackBefore(child1); // 3124 (4312)
9364 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child3 << child1 << child2 << child4));
9365 child4->setZValue(0); // 4312
9366 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child4 << child3 << child1 << child2));
9369 void tst_QGraphicsItem::QTBUG_4233_updateCachedWithSceneRect()
9371 EventTester *tester = new EventTester;
9372 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
9374 QGraphicsScene scene;
9375 scene.addItem(tester);
9376 scene.setSceneRect(-100, -100, 200, 200); // contains the tester item
9378 QGraphicsView view(&scene);
9380 QApplication::setActiveWindow(&view);
9381 QVERIFY(QTest::qWaitForWindowActive(&view));
9382 QCOMPARE(QApplication::activeWindow(), (QWidget *)&view);
9384 QTRY_COMPARE(tester->repaints, 1);
9386 scene.update(); // triggers "updateAll" optimization
9387 qApp->processEvents();
9388 qApp->processEvents(); // in 4.6 only one processEvents is necessary
9390 QCOMPARE(tester->repaints, 1);
9392 scene.update(); // triggers "updateAll" optimization
9394 qApp->processEvents();
9395 qApp->processEvents(); // in 4.6 only one processEvents is necessary
9397 QCOMPARE(tester->repaints, 2);
9400 void tst_QGraphicsItem::sceneModality()
9402 // 1) Test mouse events (delivery/propagation/redirection)
9403 // 2) Test hover events (incl. leave on block, enter on unblock)
9404 // 3) Test cursor stuff (incl. unset on block, set on unblock)
9405 // 4) Test clickfocus
9406 // 5) Test grab/ungrab events (possibly ungrab on block, regrab on unblock)
9407 // 6) ### modality for non-panels is unsupported for now
9408 QGraphicsScene scene;
9410 QGraphicsRectItem *bottomItem = scene.addRect(-150, -100, 300, 200);
9411 bottomItem->setFlag(QGraphicsItem::ItemIsFocusable);
9412 bottomItem->setBrush(Qt::yellow);
9414 QGraphicsRectItem *leftParent = scene.addRect(-50, -50, 100, 100);
9415 leftParent->setFlag(QGraphicsItem::ItemIsPanel);
9416 leftParent->setBrush(Qt::blue);
9418 QGraphicsRectItem *leftChild = scene.addRect(-25, -25, 50, 50);
9419 leftChild->setFlag(QGraphicsItem::ItemIsPanel);
9420 leftChild->setBrush(Qt::green);
9421 leftChild->setParentItem(leftParent);
9423 QGraphicsRectItem *rightParent = scene.addRect(-50, -50, 100, 100);
9424 rightParent->setFlag(QGraphicsItem::ItemIsPanel);
9425 rightParent->setBrush(Qt::red);
9426 QGraphicsRectItem *rightChild = scene.addRect(-25, -25, 50, 50);
9427 rightChild->setFlag(QGraphicsItem::ItemIsPanel);
9428 rightChild->setBrush(Qt::gray);
9429 rightChild->setParentItem(rightParent);
9431 leftParent->setPos(-75, 0);
9432 rightParent->setPos(75, 0);
9434 bottomItem->setData(0, "bottomItem");
9435 leftParent->setData(0, "leftParent");
9436 leftChild->setData(0, "leftChild");
9437 rightParent->setData(0, "rightParent");
9438 rightChild->setData(0, "rightChild");
9440 scene.setSceneRect(scene.itemsBoundingRect().adjusted(-50, -50, 50, 50));
9442 EventSpy2 leftParentSpy(&scene, leftParent);
9443 EventSpy2 leftChildSpy(&scene, leftChild);
9444 EventSpy2 rightParentSpy(&scene, rightParent);
9445 EventSpy2 rightChildSpy(&scene, rightChild);
9446 EventSpy2 bottomItemSpy(&scene, bottomItem);
9448 // Scene modality, also test multiple scene modal items
9449 leftChild->setPanelModality(QGraphicsItem::SceneModal);
9450 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9451 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9452 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9453 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9454 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0); // not a panel
9456 // Click inside left child
9457 sendMouseClick(&scene, leftChild->scenePos(), Qt::LeftButton);
9458 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
9459 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
9460 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9461 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9462 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9463 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9465 // Click on left parent, event goes to modal child
9466 sendMouseClick(&scene, leftParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
9467 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 2);
9468 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
9469 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9470 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9471 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9472 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9474 // Click on all other items and outside the items
9475 sendMouseClick(&scene, rightParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
9476 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 3);
9477 sendMouseClick(&scene, rightChild->scenePos(), Qt::LeftButton);
9478 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 4);
9479 sendMouseClick(&scene, bottomItem->scenePos(), Qt::LeftButton);
9480 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 5);
9481 sendMouseClick(&scene, QPointF(10000, 10000), Qt::LeftButton);
9482 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 6);
9483 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
9484 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9485 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9486 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9487 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9489 leftChildSpy.counts.clear();
9490 rightChildSpy.counts.clear();
9491 leftParentSpy.counts.clear();
9492 rightParentSpy.counts.clear();
9493 bottomItemSpy.counts.clear();
9495 leftChild->setPanelModality(QGraphicsItem::NonModal);
9496 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
9497 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
9498 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 1);
9499 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 1);
9500 QCOMPARE(bottomItemSpy.counts[QEvent::WindowUnblocked], 0);
9502 // Left parent enters scene modality.
9503 leftParent->setPanelModality(QGraphicsItem::SceneModal);
9504 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9505 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9506 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
9507 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9508 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
9510 // Click inside left child.
9511 sendMouseClick(&scene, leftChild->scenePos(), Qt::LeftButton);
9512 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
9513 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9514 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // panel stops propagation
9515 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9516 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9517 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9519 // Click on left parent.
9520 sendMouseClick(&scene, leftParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
9521 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
9522 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9523 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 1);
9524 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9525 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9526 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9528 // Click on all other items and outside the items
9529 sendMouseClick(&scene, rightParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
9530 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 2);
9531 sendMouseClick(&scene, rightChild->scenePos(), Qt::LeftButton);
9532 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 3);
9533 sendMouseClick(&scene, bottomItem->scenePos(), Qt::LeftButton);
9534 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 4);
9535 sendMouseClick(&scene, QPointF(10000, 10000), Qt::LeftButton);
9536 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 5);
9537 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9538 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
9539 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9540 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9541 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9543 leftChildSpy.counts.clear();
9544 rightChildSpy.counts.clear();
9545 leftParentSpy.counts.clear();
9546 rightParentSpy.counts.clear();
9547 bottomItemSpy.counts.clear();
9549 // Now both left parent and child are scene modal. Left parent is blocked.
9550 leftChild->setPanelModality(QGraphicsItem::SceneModal);
9551 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9552 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
9553 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9554 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
9555 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
9557 // Click inside left child
9558 sendMouseClick(&scene, leftChild->scenePos(), Qt::LeftButton);
9559 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
9560 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
9561 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9562 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9563 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9564 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9566 // Click on left parent, event goes to modal child
9567 sendMouseClick(&scene, leftParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
9568 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 2);
9569 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
9570 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9571 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9572 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9573 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9575 // Click on all other items and outside the items
9576 sendMouseClick(&scene, rightParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
9577 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 3);
9578 sendMouseClick(&scene, rightChild->scenePos(), Qt::LeftButton);
9579 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 4);
9580 sendMouseClick(&scene, bottomItem->scenePos(), Qt::LeftButton);
9581 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 5);
9582 sendMouseClick(&scene, QPointF(10000, 10000), Qt::LeftButton);
9583 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 6);
9584 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
9585 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9586 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9587 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9588 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9590 leftChildSpy.counts.clear();
9591 rightChildSpy.counts.clear();
9592 leftParentSpy.counts.clear();
9593 rightParentSpy.counts.clear();
9594 bottomItemSpy.counts.clear();
9596 // Right child enters scene modality, only left child is blocked.
9597 rightChild->setPanelModality(QGraphicsItem::SceneModal);
9598 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 1);
9599 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
9600 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
9601 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
9602 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
9605 void tst_QGraphicsItem::panelModality()
9607 // 1) Test mouse events (delivery/propagation/redirection)
9608 // 2) Test hover events (incl. leave on block, enter on unblock)
9609 // 3) Test cursor stuff (incl. unset on block, set on unblock)
9610 // 4) Test clickfocus
9611 // 5) Test grab/ungrab events (possibly ungrab on block, regrab on unblock)
9612 // 6) ### modality for non-panels is unsupported for now
9613 QGraphicsScene scene;
9615 QGraphicsRectItem *bottomItem = scene.addRect(-150, -100, 300, 200);
9616 bottomItem->setFlag(QGraphicsItem::ItemIsFocusable);
9617 bottomItem->setBrush(Qt::yellow);
9619 QGraphicsRectItem *leftParent = scene.addRect(-50, -50, 100, 100);
9620 leftParent->setFlag(QGraphicsItem::ItemIsPanel);
9621 leftParent->setBrush(Qt::blue);
9623 QGraphicsRectItem *leftChild = scene.addRect(-25, -25, 50, 50);
9624 leftChild->setFlag(QGraphicsItem::ItemIsPanel);
9625 leftChild->setBrush(Qt::green);
9626 leftChild->setParentItem(leftParent);
9628 QGraphicsRectItem *rightParent = scene.addRect(-50, -50, 100, 100);
9629 rightParent->setFlag(QGraphicsItem::ItemIsPanel);
9630 rightParent->setBrush(Qt::red);
9631 QGraphicsRectItem *rightChild = scene.addRect(-25, -25, 50, 50);
9632 rightChild->setFlag(QGraphicsItem::ItemIsPanel);
9633 rightChild->setBrush(Qt::gray);
9634 rightChild->setParentItem(rightParent);
9636 leftParent->setPos(-75, 0);
9637 rightParent->setPos(75, 0);
9639 bottomItem->setData(0, "bottomItem");
9640 leftParent->setData(0, "leftParent");
9641 leftChild->setData(0, "leftChild");
9642 rightParent->setData(0, "rightParent");
9643 rightChild->setData(0, "rightChild");
9645 scene.setSceneRect(scene.itemsBoundingRect().adjusted(-50, -50, 50, 50));
9647 EventSpy2 leftParentSpy(&scene, leftParent);
9648 EventSpy2 leftChildSpy(&scene, leftChild);
9649 EventSpy2 rightParentSpy(&scene, rightParent);
9650 EventSpy2 rightChildSpy(&scene, rightChild);
9651 EventSpy2 bottomItemSpy(&scene, bottomItem);
9653 // Left Child enters panel modality, only left parent is blocked.
9654 leftChild->setPanelModality(QGraphicsItem::PanelModal);
9655 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9656 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
9657 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9658 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
9659 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
9661 leftChild->setPanelModality(QGraphicsItem::NonModal);
9662 leftChildSpy.counts.clear();
9663 rightChildSpy.counts.clear();
9664 leftParentSpy.counts.clear();
9665 rightParentSpy.counts.clear();
9666 bottomItemSpy.counts.clear();
9668 // Left parent enter panel modality, nothing is blocked.
9669 leftParent->setPanelModality(QGraphicsItem::PanelModal);
9670 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9671 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
9672 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
9673 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
9674 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
9676 // Left child enters panel modality, left parent is blocked again.
9677 leftChild->setPanelModality(QGraphicsItem::PanelModal);
9678 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9679 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
9680 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9681 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
9682 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
9684 leftChildSpy.counts.clear();
9685 rightChildSpy.counts.clear();
9686 leftParentSpy.counts.clear();
9687 rightParentSpy.counts.clear();
9688 bottomItemSpy.counts.clear();
9690 leftChild->setPanelModality(QGraphicsItem::NonModal);
9691 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 1);
9692 leftParent->setPanelModality(QGraphicsItem::NonModal);
9693 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
9694 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 0);
9695 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 1);
9696 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
9697 QCOMPARE(bottomItemSpy.counts[QEvent::WindowUnblocked], 0);
9699 leftChildSpy.counts.clear();
9700 rightChildSpy.counts.clear();
9701 leftParentSpy.counts.clear();
9702 rightParentSpy.counts.clear();
9703 bottomItemSpy.counts.clear();
9705 // Left and right child enter panel modality, both parents are blocked.
9706 rightChild->setPanelModality(QGraphicsItem::PanelModal);
9707 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
9708 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9709 leftChild->setPanelModality(QGraphicsItem::PanelModal);
9710 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9711 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9714 void tst_QGraphicsItem::mixedModality()
9716 // 1) Test mouse events (delivery/propagation/redirection)
9717 // 2) Test hover events (incl. leave on block, enter on unblock)
9718 // 3) Test cursor stuff (incl. unset on block, set on unblock)
9719 // 4) Test clickfocus
9720 // 5) Test grab/ungrab events (possibly ungrab on block, regrab on unblock)
9721 // 6) ### modality for non-panels is unsupported for now
9722 QGraphicsScene scene;
9724 QGraphicsRectItem *bottomItem = scene.addRect(-150, -100, 300, 200);
9725 bottomItem->setFlag(QGraphicsItem::ItemIsFocusable);
9726 bottomItem->setBrush(Qt::yellow);
9728 QGraphicsRectItem *leftParent = scene.addRect(-50, -50, 100, 100);
9729 leftParent->setFlag(QGraphicsItem::ItemIsPanel);
9730 leftParent->setBrush(Qt::blue);
9732 QGraphicsRectItem *leftChild = scene.addRect(-25, -25, 50, 50);
9733 leftChild->setFlag(QGraphicsItem::ItemIsPanel);
9734 leftChild->setBrush(Qt::green);
9735 leftChild->setParentItem(leftParent);
9737 QGraphicsRectItem *rightParent = scene.addRect(-50, -50, 100, 100);
9738 rightParent->setFlag(QGraphicsItem::ItemIsPanel);
9739 rightParent->setBrush(Qt::red);
9740 QGraphicsRectItem *rightChild = scene.addRect(-25, -25, 50, 50);
9741 rightChild->setFlag(QGraphicsItem::ItemIsPanel);
9742 rightChild->setBrush(Qt::gray);
9743 rightChild->setParentItem(rightParent);
9745 leftParent->setPos(-75, 0);
9746 rightParent->setPos(75, 0);
9748 bottomItem->setData(0, "bottomItem");
9749 leftParent->setData(0, "leftParent");
9750 leftChild->setData(0, "leftChild");
9751 rightParent->setData(0, "rightParent");
9752 rightChild->setData(0, "rightChild");
9754 scene.setSceneRect(scene.itemsBoundingRect().adjusted(-50, -50, 50, 50));
9756 EventSpy2 leftParentSpy(&scene, leftParent);
9757 EventSpy2 leftChildSpy(&scene, leftChild);
9758 EventSpy2 rightParentSpy(&scene, rightParent);
9759 EventSpy2 rightChildSpy(&scene, rightChild);
9760 EventSpy2 bottomItemSpy(&scene, bottomItem);
9762 // Left Child enters panel modality, only left parent is blocked.
9763 leftChild->setPanelModality(QGraphicsItem::PanelModal);
9764 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9765 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
9766 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9767 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
9769 // Left parent enters scene modality, which blocks everything except the child.
9770 leftParent->setPanelModality(QGraphicsItem::SceneModal);
9771 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9772 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
9773 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9774 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 0);
9775 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9776 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
9777 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9778 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
9780 // Right child enters panel modality (changes nothing).
9781 rightChild->setPanelModality(QGraphicsItem::PanelModal);
9782 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9783 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
9784 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9785 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 0);
9786 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9787 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
9788 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9789 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
9791 // Left parent leaves modality. Right child is unblocked.
9792 leftParent->setPanelModality(QGraphicsItem::NonModal);
9793 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9794 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
9795 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9796 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
9797 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9798 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
9799 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9800 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
9802 // Right child "upgrades" its modality to scene modal. Left child is blocked.
9803 // Right parent is unaffected.
9804 rightChild->setPanelModality(QGraphicsItem::SceneModal);
9805 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 1);
9806 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
9807 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9808 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
9809 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9810 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
9811 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9812 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
9814 // "downgrade" right child back to panel modal, left child is unblocked
9815 rightChild->setPanelModality(QGraphicsItem::PanelModal);
9816 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 1);
9817 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 1);
9818 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9819 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
9820 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9821 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
9822 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9823 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
9826 void tst_QGraphicsItem::modality_hover()
9828 QGraphicsScene scene;
9829 QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
9830 rect1->setFlag(QGraphicsItem::ItemIsPanel);
9831 rect1->setAcceptHoverEvents(true);
9832 rect1->setData(0, "rect1");
9834 QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
9835 rect2->setParentItem(rect1);
9836 rect2->setFlag(QGraphicsItem::ItemIsPanel);
9837 rect2->setAcceptHoverEvents(true);
9838 rect2->setPos(50, 50);
9839 rect2->setPanelModality(QGraphicsItem::SceneModal);
9840 rect2->setData(0, "rect2");
9842 EventSpy2 rect1Spy(&scene, rect1);
9843 EventSpy2 rect2Spy(&scene, rect2);
9845 sendMouseMove(&scene, QPointF(-25, -25));
9847 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 0);
9848 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 0);
9849 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
9851 sendMouseMove(&scene, QPointF(75, 75));
9853 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 0);
9854 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 0);
9855 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
9856 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
9857 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
9858 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
9860 sendMouseMove(&scene, QPointF(-25, -25));
9862 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
9863 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 0);
9864 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 0);
9865 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
9867 rect2->setPanelModality(QGraphicsItem::NonModal);
9869 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
9870 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
9872 sendMouseMove(&scene, QPointF(75, 75));
9874 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
9875 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 2);
9877 rect2->setPanelModality(QGraphicsItem::SceneModal);
9879 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
9880 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
9881 // changing modality causes a spurious GraphicsSceneHoveMove, even though the mouse didn't
9883 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 3);
9885 sendMouseMove(&scene, QPointF(-25, -25));
9887 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 2);
9888 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
9889 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
9890 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
9892 rect2->setPanelModality(QGraphicsItem::PanelModal);
9894 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
9895 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
9896 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
9897 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
9898 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 3);
9899 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 2);
9901 rect2->setPanelModality(QGraphicsItem::NonModal);
9903 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
9904 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 2);
9905 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
9906 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 3);
9907 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 2);
9910 void tst_QGraphicsItem::modality_mouseGrabber()
9912 QGraphicsScene scene;
9913 QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
9914 rect1->setFlag(QGraphicsItem::ItemIsPanel);
9915 rect1->setFlag(QGraphicsItem::ItemIsMovable);
9916 rect1->setData(0, "rect1");
9918 QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
9919 rect2->setParentItem(rect1);
9920 rect2->setFlag(QGraphicsItem::ItemIsPanel);
9921 rect2->setFlag(QGraphicsItem::ItemIsMovable);
9922 rect2->setPos(50, 50);
9923 rect2->setData(0, "rect2");
9925 EventSpy2 rect1Spy(&scene, rect1);
9926 EventSpy2 rect2Spy(&scene, rect2);
9929 // pressing mouse on rect1 starts implicit grab
9930 sendMousePress(&scene, QPoint(-25, -25));
9931 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
9932 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
9933 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
9934 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
9935 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
9936 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
9938 // grab lost when rect1 is modally shadowed
9939 rect2->setPanelModality(QGraphicsItem::SceneModal);
9940 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
9941 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
9942 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
9943 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
9944 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
9946 // releasing goes nowhere
9947 sendMouseRelease(&scene, QPoint(-25, -25));
9948 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
9949 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9950 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
9951 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
9952 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9953 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
9954 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
9956 // pressing mouse on rect1 starts implicit grab on rect2 (since it is modal)
9957 sendMouseClick(&scene, QPoint(-25, -25));
9958 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
9959 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
9960 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9961 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
9962 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
9963 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMousePress], 1);
9964 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 1);
9965 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
9967 rect2->setPanelModality(QGraphicsItem::NonModal);
9969 // pressing mouse on rect1 starts implicit grab
9970 sendMousePress(&scene, QPoint(-25, -25));
9971 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
9972 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 2);
9973 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
9974 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
9975 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
9976 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
9978 // grab lost to rect2 when rect1 is modally shadowed
9979 rect2->setPanelModality(QGraphicsItem::SceneModal);
9980 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
9981 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
9982 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
9983 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
9984 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
9986 // rect1 does *not* re-grab when rect2 is no longer modal
9987 rect2->setPanelModality(QGraphicsItem::NonModal);
9988 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
9989 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
9990 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
9991 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
9992 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
9994 // release goes nowhere
9995 sendMouseRelease(&scene, QPoint(-25, -25));
9996 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
9997 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9998 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
9999 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
10000 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
10001 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10004 // repeat the test using PanelModal
10005 rect2->setPanelModality(QGraphicsItem::NonModal);
10006 rect1Spy.counts.clear();
10007 rect2Spy.counts.clear();
10009 // pressing mouse on rect1 starts implicit grab
10010 sendMousePress(&scene, QPoint(-25, -25));
10011 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
10012 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
10013 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10014 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10015 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10016 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
10018 // grab lost when rect1 is modally shadowed
10019 rect2->setPanelModality(QGraphicsItem::PanelModal);
10020 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
10021 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
10022 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10023 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10024 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10026 // releasing goes nowhere
10027 sendMouseRelease(&scene, QPoint(-25, -25));
10028 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
10029 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
10030 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
10031 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10032 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
10033 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10034 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10036 // pressing mouse on rect1 starts implicit grab on rect2 (since it is modal)
10037 sendMouseClick(&scene, QPoint(-25, -25));
10038 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
10039 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
10040 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
10041 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
10042 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
10043 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMousePress], 1);
10044 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 1);
10045 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
10047 rect2->setPanelModality(QGraphicsItem::NonModal);
10049 // pressing mouse on rect1 starts implicit grab
10050 sendMousePress(&scene, QPoint(-25, -25));
10051 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
10052 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 2);
10053 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
10054 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
10055 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
10056 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
10058 // grab lost to rect2 when rect1 is modally shadowed
10059 rect2->setPanelModality(QGraphicsItem::PanelModal);
10060 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
10061 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
10062 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
10063 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
10064 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10066 // rect1 does *not* re-grab when rect2 is no longer modal
10067 rect2->setPanelModality(QGraphicsItem::NonModal);
10068 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
10069 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
10070 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
10071 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
10072 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10074 // release goes nowhere
10075 sendMouseRelease(&scene, QPoint(-25, -25));
10076 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
10077 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
10078 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
10079 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
10080 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
10081 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10085 // repeat the PanelModal tests, but this time the mouse events will be on a non-modal item,
10086 // meaning normal grabbing should work
10087 rect2->setPanelModality(QGraphicsItem::NonModal);
10088 rect1Spy.counts.clear();
10089 rect2Spy.counts.clear();
10091 QGraphicsRectItem *rect3 = scene.addRect(-50, -50, 100, 100);
10092 rect3->setFlag(QGraphicsItem::ItemIsPanel);
10093 rect3->setFlag(QGraphicsItem::ItemIsMovable);
10094 rect3->setPos(150, 50);
10095 rect3->setData(0, "rect3");
10097 EventSpy2 rect3Spy(&scene, rect3);
10099 // pressing mouse on rect3 starts implicit grab
10100 sendMousePress(&scene, QPoint(150, 50));
10101 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
10102 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10103 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10104 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10105 QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 1);
10106 QCOMPARE(rect3Spy.counts[QEvent::GraphicsSceneMousePress], 1);
10107 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 0);
10108 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
10110 // grab is *not* lost when rect1 is modally shadowed by rect2
10111 rect2->setPanelModality(QGraphicsItem::PanelModal);
10112 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
10113 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10114 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10115 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10116 QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 1);
10117 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 0);
10118 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
10120 // releasing goes to rect3
10121 sendMouseRelease(&scene, QPoint(150, 50));
10122 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
10123 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10124 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10125 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10126 QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 1);
10127 QCOMPARE(rect3Spy.counts[QEvent::GraphicsSceneMouseRelease], 1);
10128 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
10129 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10131 rect2->setPanelModality(QGraphicsItem::NonModal);
10133 // pressing mouse on rect3 starts implicit grab
10134 sendMousePress(&scene, QPoint(150, 50));
10135 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
10136 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10137 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10138 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10139 QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
10140 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
10141 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
10143 // grab is not lost
10144 rect2->setPanelModality(QGraphicsItem::PanelModal);
10145 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
10146 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10147 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10148 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10149 QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
10150 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
10151 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
10153 // grab stays on rect3
10154 rect2->setPanelModality(QGraphicsItem::NonModal);
10155 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
10156 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10157 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10158 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10159 QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
10160 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
10161 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
10163 // release goes to rect3
10164 sendMouseRelease(&scene, QPoint(150, 50));
10165 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
10166 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10167 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10168 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10169 QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
10170 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 2);
10171 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10175 void tst_QGraphicsItem::modality_clickFocus()
10177 QGraphicsScene scene;
10178 QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
10179 rect1->setFlag(QGraphicsItem::ItemIsPanel);
10180 rect1->setFlag(QGraphicsItem::ItemIsFocusable);
10181 rect1->setData(0, "rect1");
10183 QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
10184 rect2->setParentItem(rect1);
10185 rect2->setFlag(QGraphicsItem::ItemIsPanel);
10186 rect2->setFlag(QGraphicsItem::ItemIsFocusable);
10187 rect2->setPos(50, 50);
10188 rect2->setData(0, "rect2");
10190 QEvent windowActivateEvent(QEvent::WindowActivate);
10191 QApplication::sendEvent(&scene, &windowActivateEvent);
10193 EventSpy2 rect1Spy(&scene, rect1);
10194 EventSpy2 rect2Spy(&scene, rect2);
10196 // activate rect1, it should not get focus
10197 rect1->setActive(true);
10198 QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
10200 // focus stays unset when rect2 becomes modal
10201 rect2->setPanelModality(QGraphicsItem::SceneModal);
10202 QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
10203 QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
10204 QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
10205 QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 0);
10206 QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0);
10208 // clicking on rect1 should not set it's focus item
10209 sendMouseClick(&scene, QPointF(-25, -25));
10210 QCOMPARE(rect1->focusItem(), (QGraphicsItem *) 0);
10211 QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
10212 QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
10213 QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 0);
10214 QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0);
10216 // clicking on rect2 gives it focus
10217 rect2->setActive(true);
10218 sendMouseClick(&scene, QPointF(75, 75));
10219 QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect2);
10220 QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
10221 QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
10222 QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
10223 QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0);
10225 // clicking on rect1 does *not* give it focus
10226 rect1->setActive(true);
10227 sendMouseClick(&scene, QPointF(-25, -25));
10228 QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
10229 QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
10230 QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
10231 QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
10232 QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1);
10234 // focus doesn't change when leaving modality either
10235 rect2->setPanelModality(QGraphicsItem::NonModal);
10236 QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
10237 QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
10238 QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
10239 QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
10240 QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1);
10242 // click on rect1, it should get focus now
10243 sendMouseClick(&scene, QPointF(-25, -25));
10244 QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1);
10245 QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 1);
10246 QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
10247 QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
10248 QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1);
10251 void tst_QGraphicsItem::modality_keyEvents()
10253 QGraphicsScene scene;
10254 QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
10255 rect1->setFlag(QGraphicsItem::ItemIsPanel);
10256 rect1->setFlag(QGraphicsItem::ItemIsFocusable);
10257 rect1->setData(0, "rect1");
10259 QGraphicsRectItem *rect1child = scene.addRect(-10, -10, 20, 20);
10260 rect1child->setParentItem(rect1);
10261 rect1child->setFlag(QGraphicsItem::ItemIsFocusable);
10262 rect1child->setData(0, "rect1child1");
10264 QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
10265 rect2->setParentItem(rect1);
10266 rect2->setFlag(QGraphicsItem::ItemIsPanel);
10267 rect2->setFlag(QGraphicsItem::ItemIsFocusable);
10268 rect2->setPos(50, 50);
10269 rect2->setData(0, "rect2");
10271 QGraphicsRectItem *rect2child = scene.addRect(-10, -10, 20, 20);
10272 rect2child->setParentItem(rect2);
10273 rect2child->setFlag(QGraphicsItem::ItemIsFocusable);
10274 rect2child->setData(0, "rect2child1");
10276 QEvent windowActivateEvent(QEvent::WindowActivate);
10277 QApplication::sendEvent(&scene, &windowActivateEvent);
10279 EventSpy2 rect1Spy(&scene, rect1);
10280 EventSpy2 rect1childSpy(&scene, rect1child);
10281 EventSpy2 rect2Spy(&scene, rect2);
10282 EventSpy2 rect2childSpy(&scene, rect2child);
10284 // activate rect1 and give it rect1child focus
10285 rect1->setActive(true);
10286 rect1child->setFocus();
10287 QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1child);
10289 // focus stays on rect1child when rect2 becomes modal
10290 rect2->setPanelModality(QGraphicsItem::SceneModal);
10291 QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1child);
10293 // but key events to rect1child should be neither delivered nor propagated
10294 sendKeyClick(&scene, Qt::Key_A);
10295 sendKeyClick(&scene, Qt::Key_S);
10296 sendKeyClick(&scene, Qt::Key_D);
10297 sendKeyClick(&scene, Qt::Key_F);
10298 QCOMPARE(rect1childSpy.counts[QEvent::KeyPress], 0);
10299 QCOMPARE(rect1childSpy.counts[QEvent::KeyRelease], 0);
10300 QCOMPARE(rect1Spy.counts[QEvent::KeyPress], 0);
10301 QCOMPARE(rect1Spy.counts[QEvent::KeyRelease], 0);
10303 // change to panel modality, rect1child1 keeps focus
10304 rect2->setPanelModality(QGraphicsItem::PanelModal);
10305 QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1child);
10307 // still no key events
10308 sendKeyClick(&scene, Qt::Key_J);
10309 sendKeyClick(&scene, Qt::Key_K);
10310 sendKeyClick(&scene, Qt::Key_L);
10311 sendKeyClick(&scene, Qt::Key_Semicolon);
10312 QCOMPARE(rect1childSpy.counts[QEvent::KeyPress], 0);
10313 QCOMPARE(rect1childSpy.counts[QEvent::KeyRelease], 0);
10314 QCOMPARE(rect1Spy.counts[QEvent::KeyPress], 0);
10315 QCOMPARE(rect1Spy.counts[QEvent::KeyRelease], 0);
10318 void tst_QGraphicsItem::itemIsInFront()
10320 QGraphicsScene scene;
10321 QGraphicsRectItem *rect1 = new QGraphicsRectItem;
10322 rect1->setData(0, "rect1");
10323 scene.addItem(rect1);
10325 QGraphicsRectItem *rect1child1 = new QGraphicsRectItem(rect1);
10326 rect1child1->setZValue(1);
10327 rect1child1->setData(0, "rect1child1");
10329 QGraphicsRectItem *rect1child2 = new QGraphicsRectItem(rect1);
10330 rect1child2->setParentItem(rect1);
10331 rect1child2->setData(0, "rect1child2");
10333 QGraphicsRectItem *rect1child1_1 = new QGraphicsRectItem(rect1child1);
10334 rect1child1_1->setData(0, "rect1child1_1");
10336 QGraphicsRectItem *rect1child1_2 = new QGraphicsRectItem(rect1child1);
10337 rect1child1_2->setFlag(QGraphicsItem::ItemStacksBehindParent);
10338 rect1child1_2->setData(0, "rect1child1_2");
10340 QGraphicsRectItem *rect2 = new QGraphicsRectItem;
10341 rect2->setData(0, "rect2");
10342 scene.addItem(rect2);
10344 QGraphicsRectItem *rect2child1 = new QGraphicsRectItem(rect2);
10345 rect2child1->setData(0, "rect2child1");
10347 QCOMPARE(qt_closestItemFirst(rect1, rect1), false);
10348 QCOMPARE(qt_closestItemFirst(rect1, rect2), false);
10349 QCOMPARE(qt_closestItemFirst(rect1child1, rect2child1), false);
10350 QCOMPARE(qt_closestItemFirst(rect1child1, rect1child2), true);
10351 QCOMPARE(qt_closestItemFirst(rect1child1_1, rect1child2), true);
10352 QCOMPARE(qt_closestItemFirst(rect1child1_1, rect1child1), true);
10353 QCOMPARE(qt_closestItemFirst(rect1child1_2, rect1child2), true);
10354 QCOMPARE(qt_closestItemFirst(rect1child1_2, rect1child1), false);
10355 QCOMPARE(qt_closestItemFirst(rect1child1_2, rect1), true);
10356 QCOMPARE(qt_closestItemFirst(rect1child1_2, rect2), false);
10357 QCOMPARE(qt_closestItemFirst(rect1child1_2, rect2child1), false);
10360 class ScenePosChangeTester : public ItemChangeTester
10363 ScenePosChangeTester()
10365 ScenePosChangeTester(QGraphicsItem *parent) : ItemChangeTester(parent)
10369 void tst_QGraphicsItem::scenePosChange()
10371 ScenePosChangeTester* root = new ScenePosChangeTester;
10372 ScenePosChangeTester* child1 = new ScenePosChangeTester(root);
10373 ScenePosChangeTester* grandChild1 = new ScenePosChangeTester(child1);
10374 ScenePosChangeTester* child2 = new ScenePosChangeTester(root);
10375 ScenePosChangeTester* grandChild2 = new ScenePosChangeTester(child2);
10377 child1->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
10378 grandChild2->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
10380 QVERIFY(child1->flags() & QGraphicsItem::ItemSendsScenePositionChanges);
10381 QVERIFY(grandChild2->flags() & QGraphicsItem::ItemSendsScenePositionChanges);
10383 QGraphicsScene scene;
10384 scene.addItem(root);
10386 // ignore uninteresting changes
10389 grandChild1->clear();
10390 grandChild2->clear();
10393 root->moveBy(1.0, 1.0);
10394 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10395 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10396 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10397 QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10400 child2->moveBy(1.0, 1.0);
10401 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10402 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10403 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10404 QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 2);
10407 grandChild2->setParentItem(child1);
10408 child1->moveBy(1.0, 1.0);
10409 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 2);
10410 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10411 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10412 QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 3);
10415 grandChild1->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
10416 grandChild2->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, false);
10417 QCoreApplication::processEvents(); // QGraphicsScenePrivate::_q_updateScenePosDescendants()
10418 child1->moveBy(1.0, 1.0);
10419 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 3);
10420 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10421 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10422 QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 3);
10425 scene.removeItem(grandChild1);
10426 delete grandChild2; grandChild2 = 0;
10427 QCoreApplication::processEvents(); // QGraphicsScenePrivate::_q_updateScenePosDescendants()
10428 root->moveBy(1.0, 1.0);
10429 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 4);
10430 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10431 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10434 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 5);
10435 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10436 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10439 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 6);
10440 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10441 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10444 void tst_QGraphicsItem::textItem_shortcuts()
10449 QGraphicsScene scene;
10450 QGraphicsView view(&scene);
10451 l.addWidget(&view);
10452 QPushButton b("Push Me");
10455 QGraphicsTextItem *item = scene.addText("Troll Text");
10456 item->setFlag(QGraphicsItem::ItemIsFocusable);
10457 item->setTextInteractionFlags(Qt::TextEditorInteraction);
10459 QVERIFY(QTest::qWaitForWindowExposed(&w));
10462 QTRY_VERIFY(item->hasFocus());
10463 QVERIFY(item->textCursor().selectedText().isEmpty());
10465 // Shortcut should work (select all)
10466 QTest::keyClick(&view, Qt::Key_A, Qt::ControlModifier);
10467 QTRY_COMPARE(item->textCursor().selectedText(), item->toPlainText());
10468 QTextCursor tc = item->textCursor();
10469 tc.clearSelection();
10470 item->setTextCursor(tc);
10471 QVERIFY(item->textCursor().selectedText().isEmpty());
10473 // Shortcut should also work if the text item has the focus and another widget
10474 // has the same shortcut.
10475 b.setShortcut(QKeySequence("CTRL+A"));
10476 QTest::keyClick(&view, Qt::Key_A, Qt::ControlModifier);
10477 QTRY_COMPARE(item->textCursor().selectedText(), item->toPlainText());
10480 void tst_QGraphicsItem::scroll()
10482 // Create two overlapping rectangles in the scene:
10487 // +---| | <- item2
10491 EventTester *item1 = new EventTester;
10492 item1->br = QRectF(0, 0, 200, 200);
10493 item1->brush = Qt::red;
10494 item1->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption);
10496 EventTester *item2 = new EventTester;
10497 item2->br = QRectF(0, 0, 200, 200);
10498 item2->brush = Qt::blue;
10499 item2->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption);
10500 item2->setPos(100, 100);
10502 QGraphicsScene scene(0, 0, 300, 300);
10503 scene.addItem(item1);
10504 scene.addItem(item2);
10506 MyGraphicsView view(&scene);
10507 view.setFrameStyle(0);
10509 QVERIFY(QTest::qWaitForWindowActive(&view));
10510 QTRY_VERIFY(view.repaints > 0);
10516 const QRectF item1BoundingRect = item1->boundingRect();
10517 const QRectF item2BoundingRect = item2->boundingRect();
10520 // Item1 should get full exposure
10521 // Item2 should get exposure for the part that overlaps item1.
10522 item1->scroll(0, -10);
10523 QTRY_VERIFY(view.repaints > 0);
10524 QCOMPARE(item1->lastExposedRect, item1BoundingRect);
10526 QRectF expectedItem2Expose = item2BoundingRect;
10527 // NB! Adjusted by 2 pixels for antialiasing
10528 expectedItem2Expose &= item1->mapRectToItem(item2, item1BoundingRect.adjusted(-2, -2, 2, 2));
10529 QCOMPARE(item2->lastExposedRect, expectedItem2Expose);
10531 // Enable ItemCoordinateCache on item1.
10533 item1->setCacheMode(QGraphicsItem::ItemCoordinateCache);
10534 QTRY_VERIFY(view.repaints > 0);
10540 // Item1 should only get expose for the newly exposed area (accelerated scroll).
10541 // Item2 should get exposure for the part that overlaps item1.
10542 item1->scroll(0, -10, QRectF(50, 50, 100, 100));
10543 QTRY_VERIFY(view.repaints > 0);
10544 QCOMPARE(item1->lastExposedRect, QRectF(50, 140, 100, 10));
10546 expectedItem2Expose = item2BoundingRect;
10547 // NB! Adjusted by 2 pixels for antialiasing
10548 expectedItem2Expose &= item1->mapRectToItem(item2, QRectF(50, 50, 100, 100).adjusted(-2, -2, 2, 2));
10549 QCOMPARE(item2->lastExposedRect, expectedItem2Expose);
10552 Q_DECLARE_METATYPE(QGraphicsItem::GraphicsItemFlag);
10554 void tst_QGraphicsItem::focusHandling_data()
10556 QTest::addColumn<QGraphicsItem::GraphicsItemFlag>("focusFlag");
10557 QTest::addColumn<bool>("useStickyFocus");
10558 QTest::addColumn<int>("expectedFocusItem"); // 0: none, 1: focusableUnder, 2: itemWithFocus
10560 QTest::newRow("Focus goes through.")
10561 << static_cast<QGraphicsItem::GraphicsItemFlag>(0x0) << false << 1;
10563 QTest::newRow("Focus goes through, even with sticky scene.")
10564 << static_cast<QGraphicsItem::GraphicsItemFlag>(0x0) << true << 1;
10566 QTest::newRow("With ItemStopsClickFocusPropagation, we cannot focus the item beneath the flagged one (but can still focus-out).")
10567 << QGraphicsItem::ItemStopsClickFocusPropagation << false << 0;
10569 QTest::newRow("With ItemStopsClickFocusPropagation, we cannot focus the item beneath the flagged one (and cannot focus-out if scene is sticky).")
10570 << QGraphicsItem::ItemStopsClickFocusPropagation << true << 2;
10572 QTest::newRow("With ItemStopsFocusHandling, focus cannot be changed by presses.")
10573 << QGraphicsItem::ItemStopsFocusHandling << false << 2;
10575 QTest::newRow("With ItemStopsFocusHandling, focus cannot be changed by presses (even if scene is sticky).")
10576 << QGraphicsItem::ItemStopsFocusHandling << true << 2;
10579 void tst_QGraphicsItem::focusHandling()
10581 QFETCH(QGraphicsItem::GraphicsItemFlag, focusFlag);
10582 QFETCH(bool, useStickyFocus);
10583 QFETCH(int, expectedFocusItem);
10585 class MyItem : public QGraphicsRectItem
10588 MyItem() : QGraphicsRectItem(0, 0, 100, 100) {}
10589 void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
10591 painter->fillRect(boundingRect(), hasFocus() ? QBrush(Qt::red) : brush());
10595 QGraphicsRectItem *noFocusOnTop = new MyItem;
10596 noFocusOnTop->setFlag(QGraphicsItem::ItemIsFocusable, false);
10597 noFocusOnTop->setBrush(Qt::yellow);
10599 QGraphicsRectItem *focusableUnder = new MyItem;
10600 focusableUnder->setBrush(Qt::blue);
10601 focusableUnder->setFlag(QGraphicsItem::ItemIsFocusable);
10602 focusableUnder->setPos(50, 50);
10604 QGraphicsRectItem *itemWithFocus = new MyItem;
10605 itemWithFocus->setBrush(Qt::black);
10606 itemWithFocus->setFlag(QGraphicsItem::ItemIsFocusable);
10607 itemWithFocus->setPos(250, 10);
10609 QGraphicsScene scene(-50, -50, 400, 400);
10610 scene.addItem(noFocusOnTop);
10611 scene.addItem(focusableUnder);
10612 scene.addItem(itemWithFocus);
10613 scene.setStickyFocus(useStickyFocus);
10615 noFocusOnTop->setFlag(focusFlag);
10616 focusableUnder->stackBefore(noFocusOnTop);
10617 itemWithFocus->setFocus();
10619 QGraphicsView view(&scene);
10621 QVERIFY(QTest::qWaitForWindowExposed(&view));
10623 QApplication::setActiveWindow(&view);
10624 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
10625 QVERIFY(itemWithFocus->hasFocus());
10627 const QPointF mousePressPoint = noFocusOnTop->mapToScene(noFocusOnTop->boundingRect().center());
10628 const QList<QGraphicsItem *> itemsAtMousePressPosition = scene.items(mousePressPoint);
10629 QVERIFY(itemsAtMousePressPosition.contains(noFocusOnTop));
10631 sendMousePress(&scene, mousePressPoint);
10633 switch (expectedFocusItem) {
10635 QCOMPARE(scene.focusItem(), static_cast<QGraphicsRectItem *>(0));
10638 QCOMPARE(scene.focusItem(), focusableUnder);
10641 QCOMPARE(scene.focusItem(), itemWithFocus);
10645 // Sanity check - manually setting the focus must work regardless of our
10646 // focus handling flags:
10647 focusableUnder->setFocus();
10648 QCOMPARE(scene.focusItem(), focusableUnder);
10651 void tst_QGraphicsItem::touchEventPropagation_data()
10653 QTest::addColumn<QGraphicsItem::GraphicsItemFlag>("flag");
10654 QTest::addColumn<int>("expectedCount");
10656 QTest::newRow("ItemIsPanel")
10657 << QGraphicsItem::ItemIsPanel << 0;
10658 QTest::newRow("ItemStopsClickFocusPropagation")
10659 << QGraphicsItem::ItemStopsClickFocusPropagation << 1;
10660 QTest::newRow("ItemStopsFocusHandling")
10661 << QGraphicsItem::ItemStopsFocusHandling << 1;
10664 void tst_QGraphicsItem::touchEventPropagation()
10666 QFETCH(QGraphicsItem::GraphicsItemFlag, flag);
10667 QFETCH(int, expectedCount);
10669 class Testee : public QGraphicsRectItem
10672 int touchBeginEventCount;
10675 : QGraphicsRectItem(0, 0, 100, 100)
10676 , touchBeginEventCount(0)
10678 setAcceptTouchEvents(true);
10679 setFlag(QGraphicsItem::ItemIsFocusable, false);
10682 bool sceneEvent(QEvent *ev)
10684 if (ev->type() == QEvent::TouchBegin)
10685 ++touchBeginEventCount;
10687 return QGraphicsRectItem::sceneEvent(ev);
10691 Testee *touchEventReceiver = new Testee;
10692 QGraphicsItem *topMost = new QGraphicsRectItem(touchEventReceiver->boundingRect());
10694 QGraphicsScene scene;
10695 scene.addItem(topMost);
10696 scene.addItem(touchEventReceiver);
10698 topMost->setAcceptTouchEvents(true);
10699 topMost->setZValue(FLT_MAX);
10700 topMost->setFlag(QGraphicsItem::ItemIsFocusable, false);
10701 topMost->setFlag(flag, true);
10703 QGraphicsView view(&scene);
10704 view.setSceneRect(touchEventReceiver->boundingRect());
10706 QVERIFY(QTest::qWaitForWindowExposed(&view));
10708 QCOMPARE(touchEventReceiver->touchBeginEventCount, 0);
10710 QTouchEvent::TouchPoint tp(0);
10711 tp.setState(Qt::TouchPointPressed);
10712 tp.setScenePos(view.sceneRect().center());
10713 tp.setLastScenePos(view.sceneRect().center());
10715 QList<QTouchEvent::TouchPoint> touchPoints;
10718 sendMousePress(&scene, tp.scenePos());
10719 QTouchDevice *device = new QTouchDevice;
10720 device->setType(QTouchDevice::TouchScreen);
10721 QWindowSystemInterface::registerTouchDevice(device);
10722 QTouchEvent touchBegin(QEvent::TouchBegin, device, Qt::NoModifier, Qt::TouchPointPressed, touchPoints);
10724 qApp->sendEvent(&scene, &touchBegin);
10725 QCOMPARE(touchEventReceiver->touchBeginEventCount, expectedCount);
10728 void tst_QGraphicsItem::deviceCoordinateCache_simpleRotations()
10730 // Make sure we don't invalidate the cache when applying simple
10731 // (90, 180, 270, 360) rotation transforms to the item.
10732 QGraphicsRectItem *item = new QGraphicsRectItem(0, 0, 300, 200);
10733 item->setBrush(Qt::red);
10734 item->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
10736 QGraphicsScene scene;
10737 scene.setSceneRect(0, 0, 300, 200);
10738 scene.addItem(item);
10740 MyGraphicsView view(&scene);
10742 QVERIFY(QTest::qWaitForWindowExposed(&view));
10743 QTRY_VERIFY(view.repaints > 0);
10745 QGraphicsItemCache *itemCache = QGraphicsItemPrivate::get(item)->extraItemCache();
10746 QVERIFY(itemCache);
10747 QPixmapCache::Key currentKey = itemCache->deviceData.value(view.viewport()).key;
10749 // Trigger an update and verify that the cache is unchanged.
10750 QPixmapCache::Key oldKey = currentKey;
10752 view.viewport()->update();
10753 QTRY_VERIFY(view.repaints > 0);
10754 currentKey = itemCache->deviceData.value(view.viewport()).key;
10755 QCOMPARE(currentKey, oldKey);
10757 // Check 90, 180, 270 and 360 degree rotations.
10758 for (int angle = 90; angle <= 360; angle += 90) {
10759 // Rotate item and verify that the cache was invalidated.
10760 oldKey = currentKey;
10762 QTransform transform;
10763 transform.translate(150, 100);
10764 transform.rotate(angle);
10765 transform.translate(-150, -100);
10766 item->setTransform(transform);
10767 QTRY_VERIFY(view.repaints > 0);
10768 currentKey = itemCache->deviceData.value(view.viewport()).key;
10769 QVERIFY(currentKey != oldKey);
10772 // Trigger an update and verify that the cache is unchanged.
10773 oldKey = currentKey;
10775 view.viewport()->update();
10776 QTRY_VERIFY(view.repaints > 0);
10777 currentKey = itemCache->deviceData.value(view.viewport()).key;
10778 QCOMPARE(currentKey, oldKey);
10781 // 45 degree rotation.
10782 oldKey = currentKey;
10784 QTransform transform;
10785 transform.translate(150, 100);
10786 transform.rotate(45);
10787 transform.translate(-150, -100);
10788 item->setTransform(transform);
10789 QTRY_VERIFY(view.repaints > 0);
10790 currentKey = itemCache->deviceData.value(view.viewport()).key;
10791 QVERIFY(currentKey != oldKey);
10793 // Trigger an update and verify that the cache was invalidated.
10794 // We should always invalidate the cache for non-trivial transforms.
10795 oldKey = currentKey;
10797 view.viewport()->update();
10798 QTRY_VERIFY(view.repaints > 0);
10799 currentKey = itemCache->deviceData.value(view.viewport()).key;
10800 QVERIFY(currentKey != oldKey);
10803 void tst_QGraphicsItem::QTBUG_5418_textItemSetDefaultColor()
10805 struct Item : public QGraphicsTextItem
10808 void paint(QPainter *painter, const QStyleOptionGraphicsItem *opt, QWidget *wid)
10811 QGraphicsTextItem::paint(painter, opt, wid);
10815 Item *i = new Item;
10817 i->setPlainText("I AM A TROLL");
10819 QGraphicsScene scene;
10820 QGraphicsView view(&scene);
10822 QVERIFY(QTest::qWaitForWindowExposed(&view));
10824 QApplication::processEvents();
10825 QTRY_VERIFY(i->painted);
10826 QApplication::processEvents();
10829 QColor col(Qt::red);
10830 i->setDefaultTextColor(col);
10831 QApplication::processEvents();
10832 QTRY_COMPARE(i->painted, 1); //check that changing the color force an update
10834 i->painted = false;
10835 QImage image(400, 200, QImage::Format_RGB32);
10837 QPainter painter(&image);
10838 scene.render(&painter);
10840 QCOMPARE(i->painted, 1);
10842 int numRedPixel = 0;
10843 QRgb rgb = col.rgb();
10844 for (int y = 0; y < image.height(); ++y) {
10845 for (int x = 0; x < image.width(); ++x) {
10846 // Because of antialiasing we allow a certain range of errors here.
10847 QRgb pixel = image.pixel(x, y);
10848 if (qAbs((int)(pixel & 0xff) - (int)(rgb & 0xff)) +
10849 qAbs((int)((pixel & 0xff00) >> 8) - (int)((rgb & 0xff00) >> 8)) +
10850 qAbs((int)((pixel & 0xff0000) >> 16) - (int)((rgb & 0xff0000) >> 16)) <= 50) {
10851 if (++numRedPixel >= 10) {
10857 QCOMPARE(numRedPixel, -1); //color not found, FAIL!
10860 i->setDefaultTextColor(col);
10861 QApplication::processEvents();
10862 QCOMPARE(i->painted, 0); //same color as before should not trigger an update (QTBUG-6242)
10865 void tst_QGraphicsItem::QTBUG_6738_missingUpdateWithSetParent()
10867 // In all 3 test cases below the reparented item should disappear
10868 EventTester *parent = new EventTester;
10869 EventTester *child = new EventTester(parent);
10870 EventTester *child2 = new EventTester(parent);
10871 EventTester *child3 = new EventTester(parent);
10872 EventTester *child4 = new EventTester(parent);
10874 child->setPos(10, 10);
10875 child2->setPos(20, 20);
10876 child3->setPos(30, 30);
10877 child4->setPos(40, 40);
10879 QGraphicsScene scene;
10880 scene.addItem(parent);
10882 MyGraphicsView view(&scene);
10884 qApp->setActiveWindow(&view);
10885 QVERIFY(QTest::qWaitForWindowActive(&view));
10886 QTRY_VERIFY(view.repaints > 0);
10890 child2->setVisible(false);
10891 child2->setParentItem(child);
10893 QTRY_VERIFY(view.repaints == 1);
10897 child3->setOpacity(0.0);
10898 child3->setParentItem(child);
10900 QTRY_VERIFY(view.repaints == 1);
10904 child4->setParentItem(child);
10905 child4->setVisible(false);
10907 QTRY_VERIFY(view.repaints == 1);
10910 void tst_QGraphicsItem::QT_2653_fullUpdateDiscardingOpacityUpdate()
10912 QGraphicsScene scene(0, 0, 200, 200);
10913 MyGraphicsView view(&scene);
10915 EventTester *parentGreen = new EventTester();
10916 parentGreen->setGeometry(QRectF(20, 20, 100, 100));
10917 parentGreen->brush = Qt::green;
10919 EventTester *childYellow = new EventTester(parentGreen);
10920 childYellow->setGeometry(QRectF(10, 10, 50, 50));
10921 childYellow->brush = Qt::yellow;
10923 scene.addItem(parentGreen);
10925 childYellow->setOpacity(0.0);
10926 parentGreen->setOpacity(0.0);
10928 // set any of the flags below to trigger a fullUpdate to reproduce the bug:
10929 // ItemIgnoresTransformations, ItemClipsChildrenToShape, ItemIsSelectable
10930 parentGreen->setFlag(QGraphicsItem::ItemIgnoresTransformations);
10933 QVERIFY(QTest::qWaitForWindowActive(&view));
10936 parentGreen->setOpacity(1.0);
10938 QTRY_COMPARE(view.repaints, 1);
10941 childYellow->repaints = 0;
10943 childYellow->setOpacity(1.0);
10945 QTRY_COMPARE(view.repaints, 1);
10946 QTRY_COMPARE(childYellow->repaints, 1);
10949 void tst_QGraphicsItem::QTBUG_7714_fullUpdateDiscardingOpacityUpdate2()
10951 QGraphicsScene scene(0, 0, 200, 200);
10952 MyGraphicsView view(&scene);
10953 MyGraphicsView origView(&scene);
10955 EventTester *parentGreen = new EventTester();
10956 parentGreen->setGeometry(QRectF(20, 20, 100, 100));
10957 parentGreen->brush = Qt::green;
10959 EventTester *childYellow = new EventTester(parentGreen);
10960 childYellow->setGeometry(QRectF(10, 10, 50, 50));
10961 childYellow->brush = Qt::yellow;
10963 scene.addItem(parentGreen);
10966 QVERIFY(QTest::qWaitForWindowActive(&origView));
10967 origView.setGeometry(origView.width() + 20, 20,
10968 origView.width(), origView.height());
10970 parentGreen->setFlag(QGraphicsItem::ItemIgnoresTransformations);
10973 childYellow->setOpacity(0.0);
10975 QTRY_COMPARE(origView.repaints, 1);
10978 qApp->setActiveWindow(&view);
10979 QVERIFY(QTest::qWaitForWindowActive(&view));
10983 childYellow->setOpacity(1.0);
10985 QTRY_COMPARE(origView.repaints, 1);
10986 QTRY_COMPARE(view.repaints, 1);
10989 void tst_QGraphicsItem::QT_2649_focusScope()
10991 QGraphicsScene *scene = new QGraphicsScene;
10993 QGraphicsRectItem *subFocusItem = new QGraphicsRectItem;
10994 subFocusItem->setFlags(QGraphicsItem::ItemIsFocusable);
10995 subFocusItem->setFocus();
10996 QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
10998 QGraphicsRectItem *scope = new QGraphicsRectItem;
10999 scope->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
11001 subFocusItem->setParentItem(scope);
11002 QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
11003 QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
11004 QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
11005 QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
11007 QGraphicsRectItem *rootItem = new QGraphicsRectItem;
11008 rootItem->setFlags(QGraphicsItem::ItemIsFocusable);
11009 scope->setParentItem(rootItem);
11010 QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)subFocusItem);
11011 QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
11012 QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
11013 QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
11014 QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
11015 QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
11017 scene->addItem(rootItem);
11019 QEvent windowActivate(QEvent::WindowActivate);
11020 qApp->sendEvent(scene, &windowActivate);
11023 QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)subFocusItem);
11024 QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
11025 QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
11026 QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
11027 QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
11028 QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
11029 QVERIFY(subFocusItem->hasFocus());
11033 QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)0);
11034 QCOMPARE(scope->focusItem(), (QGraphicsItem *)0);
11035 QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)0);
11036 QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
11037 QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
11038 QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
11039 QVERIFY(!subFocusItem->hasFocus());
11043 QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)subFocusItem);
11044 QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
11045 QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
11046 QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
11047 QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
11048 QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
11049 QVERIFY(subFocusItem->hasFocus());
11051 // This should not crash
11056 class MyGraphicsItemWithItemChange : public QGraphicsWidget
11059 MyGraphicsItemWithItemChange(QGraphicsItem *parent = 0) : QGraphicsWidget(parent)
11062 QVariant itemChange(GraphicsItemChange change, const QVariant &value)
11064 if (change == QGraphicsItem::ItemSceneHasChanged) {
11065 foreach (QGraphicsView *view, scene()->views()) {
11066 //We trigger a sort of unindexed items in the BSP
11070 return QGraphicsWidget::itemChange(change, value);
11074 void tst_QGraphicsItem::sortItemsWhileAdding()
11076 QGraphicsScene scene;
11077 QGraphicsView view(&scene);
11078 QGraphicsWidget grandGrandParent;
11079 grandGrandParent.resize(200, 200);
11080 scene.addItem(&grandGrandParent);
11081 QGraphicsWidget grandParent;
11082 grandParent.resize(200, 200);
11083 QGraphicsWidget parent(&grandParent);
11084 parent.resize(200, 200);
11085 MyGraphicsItemWithItemChange item(&parent);
11086 grandParent.setParentItem(&grandGrandParent);
11089 void tst_QGraphicsItem::doNotMarkFullUpdateIfNotInScene()
11091 struct Item : public QGraphicsTextItem
11094 void paint(QPainter *painter, const QStyleOptionGraphicsItem *opt, QWidget *wid)
11097 QGraphicsTextItem::paint(painter, opt, wid);
11100 QGraphicsScene scene;
11101 MyGraphicsView view(&scene);
11102 Item *item = new Item;
11104 item->setPlainText("Grandparent");
11105 Item *item2 = new Item;
11106 item2->setPlainText("parent");
11107 item2->painted = 0;
11108 Item *item3 = new Item;
11109 item3->setPlainText("child");
11110 item3->painted = 0;
11111 QGraphicsOpacityEffect *effect = new QGraphicsOpacityEffect;
11112 effect->setOpacity(0.5);
11113 item2->setGraphicsEffect(effect);
11114 item3->setParentItem(item2);
11115 item2->setParentItem(item);
11116 scene.addItem(item);
11118 QTest::qWaitForWindowActive(view.windowHandle());
11119 view.activateWindow();
11120 QTRY_VERIFY(view.isActiveWindow());
11121 QTRY_VERIFY(view.repaints >= 1);
11122 int count = view.repaints;
11123 QTRY_COMPARE(item->painted, count);
11124 // cached as graphics effects, not painted multiple times
11125 QTRY_COMPARE(item2->painted, 1);
11126 QTRY_COMPARE(item3->painted, 1);
11128 QApplication::processEvents();
11129 QTRY_COMPARE(item->painted, count + 1);
11130 QTRY_COMPARE(item2->painted, 2);
11131 QTRY_COMPARE(item3->painted, 2);
11133 QApplication::processEvents();
11134 QTRY_COMPARE(item->painted, count + 2);
11135 QTRY_COMPARE(item2->painted, 3);
11136 QTRY_COMPARE(item3->painted, 3);
11139 void tst_QGraphicsItem::itemDiesDuringDraggingOperation()
11141 QGraphicsScene scene;
11142 QGraphicsView view(&scene);
11143 QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
11144 item->setFlag(QGraphicsItem::ItemIsMovable);
11145 item->setAcceptDrops(true);
11146 scene.addItem(item);
11148 QApplication::setActiveWindow(&view);
11149 QVERIFY(QTest::qWaitForWindowActive(&view));
11150 QCOMPARE(QApplication::activeWindow(), (QWidget *)&view);
11151 QGraphicsSceneDragDropEvent dragEnter(QEvent::GraphicsSceneDragEnter);
11152 dragEnter.setScenePos(item->boundingRect().center());
11153 QApplication::sendEvent(&scene, &dragEnter);
11154 QGraphicsSceneDragDropEvent event(QEvent::GraphicsSceneDragMove);
11155 event.setScenePos(item->boundingRect().center());
11156 QApplication::sendEvent(&scene, &event);
11157 QVERIFY(QGraphicsScenePrivate::get(&scene)->dragDropItem == item);
11159 QVERIFY(QGraphicsScenePrivate::get(&scene)->dragDropItem == 0);
11162 void tst_QGraphicsItem::QTBUG_12112_focusItem()
11164 QGraphicsScene scene;
11165 QGraphicsView view(&scene);
11166 QGraphicsRectItem *item1 = new QGraphicsRectItem(0, 0, 20, 20);
11167 item1->setFlag(QGraphicsItem::ItemIsFocusable);
11168 QGraphicsRectItem *item2 = new QGraphicsRectItem(20, 20, 20, 20);
11169 item2->setFlag(QGraphicsItem::ItemIsFocusable);
11171 scene.addItem(item2);
11172 scene.addItem(item1);
11175 QApplication::setActiveWindow(&view);
11176 QVERIFY(QTest::qWaitForWindowActive(&view));
11177 QCOMPARE(QApplication::activeWindow(), (QWidget *)&view);
11179 QVERIFY(item1->focusItem());
11180 QVERIFY(!item2->focusItem());
11183 QVERIFY(!item1->focusItem());
11184 QVERIFY(item2->focusItem());
11187 void tst_QGraphicsItem::QTBUG_13473_sceneposchange()
11189 ScenePosChangeTester* parent = new ScenePosChangeTester;
11190 ScenePosChangeTester* child = new ScenePosChangeTester(parent);
11192 // parent's disabled ItemSendsGeometryChanges flag must not affect
11193 // child's scene pos change notifications
11194 parent->setFlag(QGraphicsItem::ItemSendsGeometryChanges, false);
11195 child->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
11197 QGraphicsScene scene;
11198 scene.addItem(parent);
11200 // ignore uninteresting changes
11205 parent->moveBy(1.0, 1.0);
11206 QCOMPARE(child->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
11209 parent->setTransform(QTransform::fromScale(0.5, 0.5));
11210 QCOMPARE(child->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 2);
11213 class MyGraphicsWidget : public QGraphicsWidget {
11217 : QGraphicsWidget(0)
11219 QGraphicsLinearLayout *lay = new QGraphicsLinearLayout(Qt::Vertical);
11220 QLatin1String wiseWords("AZ BUKI VEDI");
11221 QString sentence(wiseWords);
11222 QStringList words = sentence.split(QLatin1Char(' '), QString::SkipEmptyParts);
11223 for (int i = 0; i < words.count(); ++i) {
11224 QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(this);
11225 QLabel *label = new QLabel(words.at(i));
11226 proxy->setWidget(label);
11227 proxy->setFocusPolicy(Qt::StrongFocus);
11228 proxy->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
11230 proxy->setVisible(false);
11232 lay->addItem(proxy);
11239 class MyWidgetWindow : public QGraphicsWidget
11243 : QGraphicsWidget(0, Qt::Window)
11245 QGraphicsLinearLayout *lay = new QGraphicsLinearLayout(Qt::Vertical);
11246 MyGraphicsWidget *widget = new MyGraphicsWidget();
11247 lay->addItem(widget);
11252 void tst_QGraphicsItem::QTBUG_16374_crashInDestructor()
11254 QGraphicsScene scene;
11255 QGraphicsView view(&scene);
11257 MyWidgetWindow win;
11258 scene.addItem(&win);
11261 QVERIFY(QTest::qWaitForWindowExposed(&view));
11264 void tst_QGraphicsItem::QTBUG_20699_focusScopeCrash()
11266 QGraphicsScene scene;
11267 QGraphicsView view(&scene);
11268 QGraphicsPixmapItem fs;
11269 fs.setFlags(QGraphicsItem::ItemIsFocusScope | QGraphicsItem::ItemIsFocusable);
11270 scene.addItem(&fs);
11271 QGraphicsPixmapItem* fs2 = new QGraphicsPixmapItem(&fs);
11272 fs2->setFlags(QGraphicsItem::ItemIsFocusScope | QGraphicsItem::ItemIsFocusable);
11273 QGraphicsPixmapItem* fi2 = new QGraphicsPixmapItem(&fs);
11274 fi2->setFlags(QGraphicsItem::ItemIsFocusable);
11275 QGraphicsPixmapItem* fi = new QGraphicsPixmapItem(fs2);
11276 fi->setFlags(QGraphicsItem::ItemIsFocusable);
11281 QVERIFY(QTest::qWaitForWindowExposed(&view));
11283 fi->setParentItem(fi2);
11286 fi->setParentItem(fs2);
11290 fi->setParentItem(fi2);
11295 QTEST_MAIN(tst_QGraphicsItem)
11296 #include "tst_qgraphicsitem.moc"