1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
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 <QInputContext>
65 #include <QPushButton>
67 #include <QGraphicsLinearLayout>
73 Q_DECLARE_METATYPE(QList<int>)
74 Q_DECLARE_METATYPE(QList<QRectF>)
75 Q_DECLARE_METATYPE(QPainterPath)
76 Q_DECLARE_METATYPE(QPointF)
77 Q_DECLARE_METATYPE(QRectF)
79 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
81 #define Q_CHECK_PAINTEVENTS \
82 if (::SwitchDesktop(::GetThreadDesktop(::GetCurrentThreadId())) == 0) \
83 QSKIP("The Graphics View doesn't get the paint events");
85 #define Q_CHECK_PAINTEVENTS
89 // On mac (cocoa) we always get full update.
90 // So check that the expected region is contained inside the actual
91 #define COMPARE_REGIONS(ACTUAL, EXPECTED) QVERIFY((EXPECTED).subtracted(ACTUAL).isEmpty())
93 #define COMPARE_REGIONS QTRY_COMPARE
96 #include "../../../platformquirks.h"
98 static QGraphicsRectItem staticItem; //QTBUG-7629, we should not crash at exit.
100 static void sendMousePress(QGraphicsScene *scene, const QPointF &point, Qt::MouseButton button = Qt::LeftButton)
102 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
103 event.setScenePos(point);
104 event.setButton(button);
105 event.setButtons(button);
106 QApplication::sendEvent(scene, &event);
109 static void sendMouseMove(QGraphicsScene *scene, const QPointF &point,
110 Qt::MouseButton button = Qt::NoButton, Qt::MouseButtons /* buttons */ = 0)
112 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
113 event.setScenePos(point);
114 event.setButton(button);
115 event.setButtons(button);
116 QApplication::sendEvent(scene, &event);
119 static void sendMouseRelease(QGraphicsScene *scene, const QPointF &point, Qt::MouseButton button = Qt::LeftButton)
121 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
122 event.setScenePos(point);
123 event.setButton(button);
124 QApplication::sendEvent(scene, &event);
127 static void sendMouseClick(QGraphicsScene *scene, const QPointF &point, Qt::MouseButton button = Qt::LeftButton)
129 sendMousePress(scene, point, button);
130 sendMouseRelease(scene, point, button);
133 static void sendKeyPress(QGraphicsScene *scene, Qt::Key key)
135 QKeyEvent keyEvent(QEvent::KeyPress, key, Qt::NoModifier);
136 QApplication::sendEvent(scene, &keyEvent);
139 static void sendKeyRelease(QGraphicsScene *scene, Qt::Key key)
141 QKeyEvent keyEvent(QEvent::KeyRelease, key, Qt::NoModifier);
142 QApplication::sendEvent(scene, &keyEvent);
145 static void sendKeyClick(QGraphicsScene *scene, Qt::Key key)
147 sendKeyPress(scene, key);
148 sendKeyRelease(scene, key);
151 class EventSpy : public QGraphicsWidget
155 EventSpy(QObject *watched, QEvent::Type type)
156 : _count(0), spied(type)
158 watched->installEventFilter(this);
161 EventSpy(QGraphicsScene *scene, QGraphicsItem *watched, QEvent::Type type)
162 : _count(0), spied(type)
164 scene->addItem(this);
165 watched->installSceneEventFilter(this);
168 int count() const { return _count; }
171 bool eventFilter(QObject *watched, QEvent *event)
174 if (event->type() == spied)
179 bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
182 if (event->type() == spied)
191 class EventSpy2 : public QGraphicsWidget
195 EventSpy2(QObject *watched)
197 watched->installEventFilter(this);
200 EventSpy2(QGraphicsScene *scene, QGraphicsItem *watched)
202 scene->addItem(this);
203 watched->installSceneEventFilter(this);
206 QMap<QEvent::Type, int> counts;
209 bool eventFilter(QObject *watched, QEvent *event)
212 ++counts[event->type()];
216 bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
219 ++counts[event->type()];
224 class EventTester : public QGraphicsItem
227 EventTester(QGraphicsItem *parent = 0) : QGraphicsItem(parent), repaints(0)
228 { br = QRectF(-10, -10, 20, 20); }
230 void setGeometry(const QRectF &rect)
232 prepareGeometryChange();
237 QRectF boundingRect() const
240 void paint(QPainter *painter, const QStyleOptionGraphicsItem *o, QWidget *)
242 hints = painter->renderHints();
243 painter->setBrush(brush);
244 painter->drawRect(boundingRect());
245 lastExposedRect = o->exposedRect;
249 bool sceneEvent(QEvent *event)
251 events << event->type();
252 return QGraphicsItem::sceneEvent(event);
258 hints = QPainter::RenderHints(0);
260 lastExposedRect = QRectF();
263 QList<QEvent::Type> events;
264 QPainter::RenderHints hints;
267 QRectF lastExposedRect;
271 class MyGraphicsView : public QGraphicsView
275 QRegion paintedRegion;
276 MyGraphicsView(QGraphicsScene *scene, QWidget *parent=0) : QGraphicsView(scene,parent), repaints(0) {}
277 void paintEvent(QPaintEvent *e)
279 paintedRegion += e->region();
281 QGraphicsView::paintEvent(e);
283 void reset() { repaints = 0; paintedRegion = QRegion(); }
286 class tst_QGraphicsItem : public QObject
295 void constructionWithParent();
297 void deleteChildItem();
300 void setParentItem();
303 void inputMethodHints();
307 void explicitlyVisible();
309 void explicitlyEnabled();
312 void selected_group();
313 void selected_textItem();
314 void selected_multi();
315 void acceptedMouseButtons();
316 void acceptsHoverEvents();
317 void childAcceptsHoverEvents();
327 void collidesWith_item();
328 void collidesWith_path_data();
329 void collidesWith_path();
330 void collidesWithItemWithClip();
333 void mapFromToParent();
334 void mapFromToScene();
335 void mapFromToItem();
336 void mapRectFromToParent_data();
337 void mapRectFromToParent();
339 void commonAncestorItem();
342 void graphicsitem_cast();
343 void hoverEventsGenerateRepaints();
344 void boundingRects_data();
345 void boundingRects();
346 void boundingRects2();
347 void sceneBoundingRect();
348 void childrenBoundingRect();
349 void childrenBoundingRectTransformed();
350 void childrenBoundingRect2();
351 void childrenBoundingRect3();
352 void childrenBoundingRect4();
353 void childrenBoundingRect5();
358 void warpChildrenIntoGroup();
359 void removeFromGroup();
360 void handlesChildEvents();
361 void handlesChildEvents2();
362 void handlesChildEvents3();
363 void filtersChildEvents();
364 void filtersChildEvents2();
365 void ensureVisible();
367 //void textControlGetterSetter();
368 void defaultItemTest_QGraphicsLineItem();
369 void defaultItemTest_QGraphicsPixmapItem();
370 void defaultItemTest_QGraphicsTextItem();
371 void defaultItemTest_QGraphicsEllipseItem();
373 void sceneEventFilter();
374 void prepareGeometryChange();
376 void deleteItemInEventHandlers();
377 void itemClipsToShape();
378 void itemClipsChildrenToShape();
379 void itemClipsChildrenToShape2();
380 void itemClipsChildrenToShape3();
381 void itemClipsChildrenToShape4();
382 void itemClipsChildrenToShape5();
383 void itemClipsTextChildToShape();
384 void itemClippingDiscovery();
385 void ancestorFlags();
386 void untransformable();
387 void contextMenuEventPropagation();
388 void itemIsMovable();
389 void boundingRegion_data();
390 void boundingRegion();
391 void itemTransform_parentChild();
392 void itemTransform_siblings();
393 void itemTransform_unrelated();
397 void opacityZeroUpdates();
398 void itemStacksBehindParent();
399 void nestedClipping();
400 void nestedClippingTransforms();
401 void sceneTransformCache();
402 void tabChangesFocus();
403 void tabChangesFocus_data();
406 void updateCachedItemAfterMove();
407 void deviceTransform_data();
408 void deviceTransform();
410 void setTransformProperties_data();
411 void setTransformProperties();
412 void itemUsesExtendedStyleOption();
413 void itemSendsGeometryChanges();
418 void itemHasNoContents();
419 void hitTestUntransformableItem();
420 void hitTestGraphicsEffectItem();
423 void focusProxyDeletion();
424 void negativeZStacksBehindParent();
425 void setGraphicsEffect();
427 void addPanelToActiveScene();
428 void panelWithFocusItem();
430 void setActivePanelOnInactiveScene();
431 void activationOnShowHide();
432 void moveWhileDeleting();
433 void ensureDirtySceneTransform();
437 void sceneModality();
438 void panelModality();
439 void mixedModality();
440 void modality_hover();
441 void modality_mouseGrabber();
442 void modality_clickFocus();
443 void modality_keyEvents();
444 void itemIsInFront();
445 void scenePosChange();
446 void updateMicroFocus();
447 void textItem_shortcuts();
449 void focusHandling_data();
450 void focusHandling();
451 void touchEventPropagation_data();
452 void touchEventPropagation();
453 void deviceCoordinateCache_simpleRotations();
455 // task specific tests below me
456 void task141694_textItemEnsureVisible();
457 void task128696_textItemEnsureMovable();
458 void ensureUpdateOnTextItem();
459 void task177918_lineItemUndetected();
460 void task240400_clickOnTextItem_data();
461 void task240400_clickOnTextItem();
462 void task243707_addChildBeforeParent();
463 void task197802_childrenVisibility();
464 void QTBUG_4233_updateCachedWithSceneRect();
465 void QTBUG_5418_textItemSetDefaultColor();
466 void QTBUG_6738_missingUpdateWithSetParent();
467 void QTBUG_7714_fullUpdateDiscardingOpacityUpdate2();
468 void QT_2653_fullUpdateDiscardingOpacityUpdate();
469 void QT_2649_focusScope();
470 void sortItemsWhileAdding();
471 void doNotMarkFullUpdateIfNotInScene();
472 void itemDiesDuringDraggingOperation();
473 void QTBUG_12112_focusItem();
474 void QTBUG_13473_sceneposchange();
475 void QTBUG_16374_crashInDestructor();
476 void QTBUG_20699_focusScopeCrash();
479 QList<QGraphicsItem *> paintedItems;
482 void tst_QGraphicsItem::init()
484 #ifdef Q_OS_WINCE //disable magic for WindowsCE
485 qApp->setAutoMaximizeThreshold(-1);
489 void tst_QGraphicsItem::construction()
491 for (int i = 0; i < 7; ++i) {
495 item = new QGraphicsEllipseItem;
496 QCOMPARE(int(item->type()), int(QGraphicsEllipseItem::Type));
497 QCOMPARE(qgraphicsitem_cast<QGraphicsEllipseItem *>(item), (QGraphicsEllipseItem *)item);
498 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
499 QCOMPARE(item->flags(), 0);
502 item = new QGraphicsLineItem;
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 QCOMPARE(int(item->type()), int(QGraphicsPathItem::Type));
511 QCOMPARE(qgraphicsitem_cast<QGraphicsPathItem *>(item), (QGraphicsPathItem *)item);
512 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
513 QCOMPARE(item->flags(), 0);
516 item = new QGraphicsPixmapItem;
517 QCOMPARE(int(item->type()), int(QGraphicsPixmapItem::Type));
518 QCOMPARE(qgraphicsitem_cast<QGraphicsPixmapItem *>(item), (QGraphicsPixmapItem *)item);
519 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
520 QCOMPARE(item->flags(), 0);
523 item = new QGraphicsPolygonItem;
524 QCOMPARE(int(item->type()), int(QGraphicsPolygonItem::Type));
525 QCOMPARE(qgraphicsitem_cast<QGraphicsPolygonItem *>(item), (QGraphicsPolygonItem *)item);
526 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
527 QCOMPARE(item->flags(), 0);
530 item = new QGraphicsRectItem;
531 QCOMPARE(int(item->type()), int(QGraphicsRectItem::Type));
532 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)item);
533 QCOMPARE(qgraphicsitem_cast<QGraphicsLineItem *>(item), (QGraphicsLineItem *)0);
534 QCOMPARE(item->flags(), 0);
537 item = new QGraphicsTextItem;
538 QCOMPARE(int(item->type()), int(QGraphicsTextItem::Type));
539 QCOMPARE(qgraphicsitem_cast<QGraphicsTextItem *>(item), (QGraphicsTextItem *)item);
540 QCOMPARE(qgraphicsitem_cast<QGraphicsRectItem *>(item), (QGraphicsRectItem *)0);
541 // This is the only item that uses an extended style option.
542 QCOMPARE(item->flags(), QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemUsesExtendedStyleOption));
545 qFatal("You broke the logic, please fix!");
549 QCOMPARE(item->scene(), (QGraphicsScene *)0);
550 QCOMPARE(item->parentItem(), (QGraphicsItem *)0);
551 QVERIFY(item->children().isEmpty());
552 QVERIFY(item->isVisible());
553 QVERIFY(item->isEnabled());
554 QVERIFY(!item->isSelected());
555 QCOMPARE(item->acceptedMouseButtons(), Qt::MouseButtons(0x1f));
556 if (item->type() == QGraphicsTextItem::Type)
557 QVERIFY(item->acceptsHoverEvents());
559 QVERIFY(!item->acceptsHoverEvents());
560 QVERIFY(!item->hasFocus());
561 QCOMPARE(item->pos(), QPointF());
562 QCOMPARE(item->matrix(), QMatrix());
563 QCOMPARE(item->sceneMatrix(), QMatrix());
564 QCOMPARE(item->zValue(), qreal(0));
565 QCOMPARE(item->sceneBoundingRect(), QRectF());
566 QCOMPARE(item->shape(), QPainterPath());
567 QVERIFY(!item->contains(QPointF(0, 0)));
568 QVERIFY(!item->collidesWithItem(0));
569 QVERIFY(item->collidesWithItem(item));
570 QVERIFY(!item->collidesWithPath(QPainterPath()));
571 QVERIFY(!item->isAncestorOf(0));
572 QVERIFY(!item->isAncestorOf(item));
573 QCOMPARE(item->data(0), QVariant());
578 class BoundingRectItem : public QGraphicsRectItem
581 BoundingRectItem(QGraphicsItem *parent = 0)
582 : QGraphicsRectItem(0, 0, parent ? 200 : 100, parent ? 200 : 100,
586 QRectF boundingRect() const
588 QRectF tmp = QGraphicsRectItem::boundingRect();
589 foreach (QGraphicsItem *child, children())
590 tmp |= child->boundingRect(); // <- might be pure virtual
595 void tst_QGraphicsItem::constructionWithParent()
597 // This test causes a crash if item1 calls item2's pure virtuals before the
598 // object has been constructed.
599 QGraphicsItem *item0 = new BoundingRectItem;
600 QGraphicsItem *item1 = new BoundingRectItem;
601 QGraphicsScene scene;
602 scene.addItem(item0);
603 scene.addItem(item1);
604 QGraphicsItem *item2 = new BoundingRectItem(item1);
605 QCOMPARE(item1->children(), QList<QGraphicsItem *>() << item2);
606 QCOMPARE(item1->boundingRect(), QRectF(0, 0, 200, 200));
608 item2->setParentItem(item0);
609 QCOMPARE(item0->children(), QList<QGraphicsItem *>() << item2);
610 QCOMPARE(item0->boundingRect(), QRectF(0, 0, 200, 200));
613 static int itemDeleted = 0;
614 class Item : public QGraphicsRectItem
621 void tst_QGraphicsItem::destruction()
623 QCOMPARE(itemDeleted, 0);
625 QGraphicsItem *parent = new QGraphicsRectItem;
626 Item *child = new Item;
627 child->setParentItem(parent);
628 QCOMPARE(child->parentItem(), parent);
630 QCOMPARE(itemDeleted, 1);
633 QGraphicsItem *parent = new QGraphicsRectItem;
634 Item *child = new Item;
635 child->setParentItem(parent);
636 QCOMPARE(parent->children().size(), 1);
638 QCOMPARE(parent->children().size(), 0);
640 QCOMPARE(itemDeleted, 2);
643 QGraphicsScene scene;
644 QGraphicsItem *parent = new QGraphicsRectItem;
645 Item *child = new Item;
646 QCOMPARE(child->parentItem(), (QGraphicsItem *)0);
647 child->setParentItem(parent);
648 QCOMPARE(child->parentItem(), parent);
649 scene.addItem(parent);
650 QCOMPARE(child->parentItem(), parent);
652 QCOMPARE(itemDeleted, 3);
655 QGraphicsScene scene;
656 QGraphicsItem *parent = new QGraphicsRectItem;
657 Item *child = new Item;
658 child->setParentItem(parent);
659 scene.addItem(parent);
660 QCOMPARE(child->scene(), &scene);
661 QCOMPARE(parent->children().size(), 1);
663 QCOMPARE(parent->children().size(), 0);
665 QCOMPARE(itemDeleted, 4);
668 QGraphicsScene scene;
669 QGraphicsItem *parent = new QGraphicsRectItem;
670 Item *child = new Item;
671 child->setParentItem(parent);
672 scene.addItem(parent);
673 QCOMPARE(child->scene(), &scene);
674 scene.removeItem(parent);
675 QCOMPARE(child->scene(), (QGraphicsScene *)0);
677 QCOMPARE(itemDeleted, 5);
680 QGraphicsScene scene;
681 QGraphicsItem *parent = new QGraphicsRectItem;
682 Item *child = new Item;
683 child->setParentItem(parent);
684 QCOMPARE(child->scene(), (QGraphicsScene *)0);
685 QCOMPARE(parent->scene(), (QGraphicsScene *)0);
686 scene.addItem(parent);
687 QCOMPARE(child->scene(), &scene);
688 scene.removeItem(child);
689 QCOMPARE(child->scene(), (QGraphicsScene *)0);
690 QCOMPARE(parent->scene(), &scene);
691 QCOMPARE(child->parentItem(), (QGraphicsItem *)0);
692 QVERIFY(parent->children().isEmpty());
694 QCOMPARE(itemDeleted, 5);
696 QCOMPARE(itemDeleted, 6);
699 QGraphicsScene scene;
700 QGraphicsItem *parent = new QGraphicsRectItem;
701 Item *child = new Item;
702 child->setParentItem(parent);
703 scene.addItem(parent);
704 scene.removeItem(child);
705 scene.removeItem(parent);
708 QCOMPARE(itemDeleted, 7);
711 QGraphicsScene scene;
712 QGraphicsItem *parent = new QGraphicsRectItem;
713 Item *child = new Item;
714 child->setParentItem(parent);
715 scene.addItem(parent);
716 QGraphicsScene scene2;
717 scene2.addItem(parent);
719 QCOMPARE(itemDeleted, 8);
722 QGraphicsScene scene;
723 QGraphicsItem *parent = new QGraphicsRectItem;
724 Item *child = new Item;
725 child->setParentItem(parent);
726 scene.addItem(parent);
727 QCOMPARE(child->scene(), &scene);
728 QGraphicsScene scene2;
729 scene2.addItem(parent);
730 QCOMPARE(child->scene(), &scene2);
731 scene.addItem(parent);
732 QCOMPARE(child->scene(), &scene);
733 scene2.addItem(parent);
734 QCOMPARE(child->scene(), &scene2);
736 QCOMPARE(itemDeleted, 9);
739 QGraphicsScene scene;
740 QGraphicsItem *parent = new QGraphicsRectItem;
741 Item *child = new Item;
742 child->setParentItem(parent);
743 scene.addItem(parent);
744 QCOMPARE(child->scene(), &scene);
745 QGraphicsScene scene2;
746 scene2.addItem(child);
747 QCOMPARE(child->scene(), &scene2);
749 QCOMPARE(itemDeleted, 9);
751 QCOMPARE(itemDeleted, 10);
754 QGraphicsScene scene;
755 QGraphicsItem *root = new QGraphicsRectItem;
756 QGraphicsItem *parent = root;
757 QGraphicsItem *middleItem = 0;
758 for (int i = 0; i < 99; ++i) {
759 Item *child = new Item;
760 child->setParentItem(parent);
767 QCOMPARE(scene.items().size(), 100);
769 QGraphicsScene scene2;
770 scene2.addItem(middleItem);
773 QCOMPARE(itemDeleted, 59);
775 QCOMPARE(itemDeleted, 109);
777 QGraphicsScene *scene = new QGraphicsScene;
778 QGraphicsRectItem *parent = new QGraphicsRectItem;
779 Item *child = new Item;
780 child->setParentItem(parent);
781 parent->setVisible(false);
782 scene->addItem(parent);
783 QCOMPARE(child->parentItem(), static_cast<QGraphicsItem*>(parent));
785 QCOMPARE(itemDeleted, 110);
789 void tst_QGraphicsItem::deleteChildItem()
791 QGraphicsScene scene;
792 QGraphicsItem *rect = scene.addRect(QRectF());
793 QGraphicsItem *child1 = new QGraphicsRectItem(rect);
794 QGraphicsItem *child2 = new QGraphicsRectItem(rect);
795 QGraphicsItem *child3 = new QGraphicsRectItem(rect);
798 child2->setParentItem(0);
802 void tst_QGraphicsItem::scene()
804 QGraphicsRectItem *item = new QGraphicsRectItem;
805 QCOMPARE(item->scene(), (QGraphicsScene *)0);
807 QGraphicsScene scene;
809 QCOMPARE(item->scene(), (QGraphicsScene *)&scene);
811 QGraphicsScene scene2;
812 scene2.addItem(item);
813 QCOMPARE(item->scene(), (QGraphicsScene *)&scene2);
815 scene2.removeItem(item);
816 QCOMPARE(item->scene(), (QGraphicsScene *)0);
821 void tst_QGraphicsItem::parentItem()
823 QGraphicsRectItem item;
824 QCOMPARE(item.parentItem(), (QGraphicsItem *)0);
826 QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(), &item);
827 QCOMPARE(item2->parentItem(), (QGraphicsItem *)&item);
828 item2->setParentItem(&item);
829 QCOMPARE(item2->parentItem(), (QGraphicsItem *)&item);
830 item2->setParentItem(0);
831 QCOMPARE(item2->parentItem(), (QGraphicsItem *)0);
836 void tst_QGraphicsItem::setParentItem()
838 QGraphicsScene scene;
839 QGraphicsItem *item = scene.addRect(QRectF(0, 0, 10, 10));
840 QCOMPARE(item->scene(), &scene);
842 QGraphicsRectItem *child = new QGraphicsRectItem;
843 QCOMPARE(child->scene(), (QGraphicsScene *)0);
845 // This implicitly adds the item to the parent's scene
846 child->setParentItem(item);
847 QCOMPARE(child->scene(), &scene);
849 // This just makes it a toplevel
850 child->setParentItem(0);
851 QCOMPARE(child->scene(), &scene);
853 // Add the child back to the parent, then remove the parent from the scene
854 child->setParentItem(item);
855 scene.removeItem(item);
856 QCOMPARE(child->scene(), (QGraphicsScene *)0);
859 void tst_QGraphicsItem::children()
861 QGraphicsRectItem item;
862 QVERIFY(item.children().isEmpty());
864 QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(), &item);
865 QCOMPARE(item.children().size(), 1);
866 QCOMPARE(item.children().first(), (QGraphicsItem *)item2);
867 QVERIFY(item2->children().isEmpty());
870 QVERIFY(item.children().isEmpty());
873 void tst_QGraphicsItem::flags()
875 QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(-10, -10, 20, 20));
876 QCOMPARE(item->flags(), 0);
878 QGraphicsScene scene;
879 QEvent activate(QEvent::WindowActivate);
880 QApplication::sendEvent(&scene, &activate);
886 item->setFlag(QGraphicsItem::ItemIsFocusable, false);
887 QVERIFY(!item->hasFocus());
889 QVERIFY(!item->hasFocus());
891 item->setFlag(QGraphicsItem::ItemIsFocusable, true);
892 QVERIFY(!item->hasFocus());
894 QVERIFY(item->hasFocus());
895 QVERIFY(scene.hasFocus());
897 item->setFlag(QGraphicsItem::ItemIsFocusable, false);
898 QVERIFY(!item->hasFocus());
899 QVERIFY(scene.hasFocus());
903 item->setFlag(QGraphicsItem::ItemIsSelectable, false);
904 QVERIFY(!item->isSelected());
905 item->setSelected(true);
906 QVERIFY(!item->isSelected());
908 item->setFlag(QGraphicsItem::ItemIsSelectable, true);
909 QVERIFY(!item->isSelected());
910 item->setSelected(true);
911 QVERIFY(item->isSelected());
912 item->setFlag(QGraphicsItem::ItemIsSelectable, false);
913 QVERIFY(!item->isSelected());
917 item->setFlag(QGraphicsItem::ItemIsMovable, false);
918 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
919 event.setScenePos(QPointF(0, 0));
920 event.setButton(Qt::LeftButton);
921 event.setButtons(Qt::LeftButton);
922 QApplication::sendEvent(&scene, &event);
923 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0); // mouse grabber is reset
925 QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove);
926 event2.setScenePos(QPointF(10, 10));
927 event2.setButton(Qt::LeftButton);
928 event2.setButtons(Qt::LeftButton);
929 QApplication::sendEvent(&scene, &event2);
930 QCOMPARE(item->pos(), QPointF());
932 QGraphicsSceneMouseEvent event3(QEvent::GraphicsSceneMouseRelease);
933 event3.setScenePos(QPointF(10, 10));
934 event3.setButtons(0);
935 QApplication::sendEvent(&scene, &event3);
936 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
938 item->setFlag(QGraphicsItem::ItemIsMovable, true);
939 QGraphicsSceneMouseEvent event4(QEvent::GraphicsSceneMousePress);
940 event4.setScenePos(QPointF(0, 0));
941 event4.setButton(Qt::LeftButton);
942 event4.setButtons(Qt::LeftButton);
943 QApplication::sendEvent(&scene, &event4);
944 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
945 QGraphicsSceneMouseEvent event5(QEvent::GraphicsSceneMouseMove);
946 event5.setScenePos(QPointF(10, 10));
947 event5.setButton(Qt::LeftButton);
948 event5.setButtons(Qt::LeftButton);
949 QApplication::sendEvent(&scene, &event5);
950 QCOMPARE(item->pos(), QPointF(10, 10));
953 QGraphicsItem* clippingParent = new QGraphicsRectItem;
954 clippingParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
956 QGraphicsItem* nonClippingParent = new QGraphicsRectItem;
957 nonClippingParent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
959 QGraphicsItem* child = new QGraphicsRectItem(nonClippingParent);
960 QVERIFY(!child->isClipped());
962 child->setParentItem(clippingParent);
963 QVERIFY(child->isClipped());
965 child->setParentItem(nonClippingParent);
966 QVERIFY(!child->isClipped());
970 class ImhTester : public QGraphicsItem
972 QRectF boundingRect() const { return QRectF(); }
973 void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) {}
976 void tst_QGraphicsItem::inputMethodHints()
978 ImhTester *item = new ImhTester;
979 item->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
980 item->setFlag(QGraphicsItem::ItemIsFocusable, true);
981 QCOMPARE(item->inputMethodHints(), Qt::ImhNone);
982 ImhTester *item2 = new ImhTester;
983 item2->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
984 item2->setFlag(QGraphicsItem::ItemIsFocusable, true);
985 Qt::InputMethodHints imHints = item2->inputMethodHints();
986 imHints |= Qt::ImhHiddenText;
987 item2->setInputMethodHints(imHints);
988 QGraphicsScene scene;
990 scene.addItem(item2);
991 QGraphicsView view(&scene);
992 QApplication::setActiveWindow(&view);
994 QTest::qWaitForWindowShown(&view);
996 QTRY_VERIFY(item->hasFocus());
997 QCOMPARE(view.inputMethodHints(), item->inputMethodHints());
999 QTRY_VERIFY(item2->hasFocus());
1000 QCOMPARE(view.inputMethodHints(), item2->inputMethodHints());
1001 item->setFlag(QGraphicsItem::ItemAcceptsInputMethod, false);
1003 QTRY_VERIFY(item->hasFocus());
1004 //Focus has changed but the new item doesn't accept input method, no hints.
1005 QCOMPARE(view.inputMethodHints(), 0);
1007 QTRY_VERIFY(item2->hasFocus());
1008 QCOMPARE(view.inputMethodHints(), item2->inputMethodHints());
1009 imHints = item2->inputMethodHints();
1010 imHints |= (Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
1011 item2->setInputMethodHints(imHints);
1012 QCOMPARE(view.inputMethodHints(), item2->inputMethodHints());
1013 QGraphicsProxyWidget *widget = new QGraphicsProxyWidget;
1014 QLineEdit *edit = new QLineEdit;
1015 edit->setEchoMode(QLineEdit::Password);
1016 scene.addItem(widget);
1018 QTRY_VERIFY(widget->hasFocus());
1019 //No widget on the proxy, so no hints
1020 QCOMPARE(view.inputMethodHints(), 0);
1021 widget->setWidget(edit);
1022 //View should match with the line edit
1023 QCOMPARE(view.inputMethodHints(), edit->inputMethodHints());
1026 void tst_QGraphicsItem::toolTip()
1028 QString toolTip = "Qt rocks!";
1030 QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
1031 item->setPen(QPen(Qt::red, 1));
1032 item->setBrush(QBrush(Qt::blue));
1033 QVERIFY(item->toolTip().isEmpty());
1034 item->setToolTip(toolTip);
1035 QCOMPARE(item->toolTip(), toolTip);
1037 QGraphicsScene scene;
1038 scene.addItem(item);
1040 QGraphicsView view(&scene);
1041 view.setFixedSize(200, 200);
1045 QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().topLeft(),
1046 view.viewport()->mapToGlobal(view.viewport()->rect().topLeft()));
1047 QApplication::sendEvent(view.viewport(), &helpEvent);
1050 bool foundView = false;
1051 bool foundTipLabel = false;
1052 foreach (QWidget *widget, QApplication::topLevelWidgets()) {
1053 if (widget == &view)
1055 if (widget->inherits("QTipLabel"))
1056 foundTipLabel = true;
1059 QVERIFY(!foundTipLabel);
1063 QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().center(),
1064 view.viewport()->mapToGlobal(view.viewport()->rect().center()));
1065 QApplication::sendEvent(view.viewport(), &helpEvent);
1068 bool foundView = false;
1069 bool foundTipLabel = false;
1070 foreach (QWidget *widget, QApplication::topLevelWidgets()) {
1071 if (widget == &view)
1073 if (widget->inherits("QTipLabel"))
1074 foundTipLabel = true;
1077 QVERIFY(foundTipLabel);
1081 QHelpEvent helpEvent(QEvent::ToolTip, view.viewport()->rect().topLeft(),
1082 view.viewport()->mapToGlobal(view.viewport()->rect().topLeft()));
1083 QApplication::sendEvent(view.viewport(), &helpEvent);
1086 bool foundView = false;
1087 bool foundTipLabel = false;
1088 foreach (QWidget *widget, QApplication::topLevelWidgets()) {
1089 if (widget == &view)
1091 if (widget->inherits("QTipLabel") && widget->isVisible())
1092 foundTipLabel = true;
1095 QVERIFY(!foundTipLabel);
1099 void tst_QGraphicsItem::visible()
1101 QGraphicsItem *item = new QGraphicsRectItem(QRectF(-10, -10, 20, 20));
1102 item->setFlag(QGraphicsItem::ItemIsMovable);
1103 QVERIFY(item->isVisible());
1104 item->setVisible(false);
1105 QVERIFY(!item->isVisible());
1106 item->setVisible(true);
1107 QVERIFY(item->isVisible());
1109 QGraphicsScene scene;
1110 QEvent activate(QEvent::WindowActivate);
1111 QApplication::sendEvent(&scene, &activate);
1113 scene.addItem(item);
1114 QVERIFY(item->isVisible());
1115 QCOMPARE(scene.itemAt(0, 0), item);
1116 item->setVisible(false);
1117 QCOMPARE(scene.itemAt(0, 0), (QGraphicsItem *)0);
1118 item->setVisible(true);
1119 QCOMPARE(scene.itemAt(0, 0), item);
1121 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
1122 event.setButton(Qt::LeftButton);
1123 event.setScenePos(QPointF(0, 0));
1124 QApplication::sendEvent(&scene, &event);
1125 QCOMPARE(scene.mouseGrabberItem(), item);
1126 item->setVisible(false);
1127 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1128 item->setVisible(true);
1129 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1131 item->setFlag(QGraphicsItem::ItemIsFocusable);
1133 QVERIFY(item->hasFocus());
1134 item->setVisible(false);
1135 QVERIFY(!item->hasFocus());
1136 item->setVisible(true);
1137 QVERIFY(!item->hasFocus());
1140 void tst_QGraphicsItem::isVisibleTo()
1142 QGraphicsScene scene;
1143 QGraphicsItem *parent = scene.addRect(QRectF(0, 0, 100, 100));
1144 QGraphicsItem *child = scene.addRect(QRectF(25, 25, 50, 50));
1145 QGraphicsItem *grandChild = scene.addRect(QRectF(50, 50, 50, 50));
1146 QGraphicsItem *stranger = scene.addRect(100, 100, 100, 100);
1148 child->setParentItem(parent);
1149 grandChild->setParentItem(child);
1151 QVERIFY(grandChild->isVisible());
1152 QVERIFY(grandChild->isVisibleTo(grandChild));
1153 QVERIFY(grandChild->isVisibleTo(child));
1154 QVERIFY(grandChild->isVisibleTo(parent));
1155 QVERIFY(grandChild->isVisibleTo(0));
1156 QVERIFY(child->isVisible());
1157 QVERIFY(child->isVisibleTo(child));
1158 QVERIFY(child->isVisibleTo(parent));
1159 QVERIFY(child->isVisibleTo(0));
1160 QVERIFY(parent->isVisible());
1161 QVERIFY(parent->isVisibleTo(parent));
1162 QVERIFY(parent->isVisibleTo(0));
1163 QVERIFY(!parent->isVisibleTo(child));
1164 QVERIFY(!child->isVisibleTo(grandChild));
1165 QVERIFY(!grandChild->isVisibleTo(stranger));
1166 QVERIFY(!child->isVisibleTo(stranger));
1167 QVERIFY(!parent->isVisibleTo(stranger));
1168 QVERIFY(!stranger->isVisibleTo(grandChild));
1169 QVERIFY(!stranger->isVisibleTo(child));
1170 QVERIFY(!stranger->isVisibleTo(parent));
1172 // Case 1: only parent is explicitly hidden
1175 QVERIFY(!grandChild->isVisible());
1176 QVERIFY(grandChild->isVisibleTo(grandChild));
1177 QVERIFY(grandChild->isVisibleTo(child));
1178 QVERIFY(grandChild->isVisibleTo(parent));
1179 QVERIFY(!grandChild->isVisibleTo(0));
1180 QVERIFY(!child->isVisible());
1181 QVERIFY(child->isVisibleTo(child));
1182 QVERIFY(child->isVisibleTo(parent));
1183 QVERIFY(!child->isVisibleTo(0));
1184 QVERIFY(!parent->isVisible());
1185 QVERIFY(!parent->isVisibleTo(parent));
1186 QVERIFY(!parent->isVisibleTo(0));
1187 QVERIFY(!parent->isVisibleTo(child));
1188 QVERIFY(!child->isVisibleTo(grandChild));
1189 QVERIFY(!grandChild->isVisibleTo(stranger));
1190 QVERIFY(!child->isVisibleTo(stranger));
1191 QVERIFY(!parent->isVisibleTo(stranger));
1192 QVERIFY(!stranger->isVisibleTo(grandChild));
1193 QVERIFY(!stranger->isVisibleTo(child));
1194 QVERIFY(!stranger->isVisibleTo(parent));
1196 // Case 2: only child is hidden
1200 QVERIFY(!grandChild->isVisible());
1201 QVERIFY(grandChild->isVisibleTo(grandChild));
1202 QVERIFY(grandChild->isVisibleTo(child));
1203 QVERIFY(!grandChild->isVisibleTo(parent));
1204 QVERIFY(!grandChild->isVisibleTo(0));
1205 QVERIFY(!child->isVisible());
1206 QVERIFY(!child->isVisibleTo(child));
1207 QVERIFY(!child->isVisibleTo(parent));
1208 QVERIFY(!child->isVisibleTo(0));
1209 QVERIFY(parent->isVisible());
1210 QVERIFY(parent->isVisibleTo(parent));
1211 QVERIFY(parent->isVisibleTo(0));
1212 QVERIFY(!parent->isVisibleTo(child));
1213 QVERIFY(!child->isVisibleTo(grandChild));
1214 QVERIFY(!grandChild->isVisibleTo(stranger));
1215 QVERIFY(!child->isVisibleTo(stranger));
1216 QVERIFY(!parent->isVisibleTo(stranger));
1217 QVERIFY(!stranger->isVisibleTo(grandChild));
1218 QVERIFY(!stranger->isVisibleTo(child));
1219 QVERIFY(!stranger->isVisibleTo(parent));
1221 // Case 3: only grand child is hidden
1225 QVERIFY(!grandChild->isVisible());
1226 QVERIFY(!grandChild->isVisibleTo(grandChild));
1227 QVERIFY(!grandChild->isVisibleTo(child));
1228 QVERIFY(!grandChild->isVisibleTo(parent));
1229 QVERIFY(!grandChild->isVisibleTo(0));
1230 QVERIFY(child->isVisible());
1231 QVERIFY(child->isVisibleTo(child));
1232 QVERIFY(child->isVisibleTo(parent));
1233 QVERIFY(child->isVisibleTo(0));
1234 QVERIFY(parent->isVisible());
1235 QVERIFY(parent->isVisibleTo(parent));
1236 QVERIFY(parent->isVisibleTo(0));
1237 QVERIFY(!parent->isVisibleTo(child));
1238 QVERIFY(!child->isVisibleTo(grandChild));
1239 QVERIFY(!grandChild->isVisibleTo(stranger));
1240 QVERIFY(!child->isVisibleTo(stranger));
1241 QVERIFY(!parent->isVisibleTo(stranger));
1242 QVERIFY(!stranger->isVisibleTo(grandChild));
1243 QVERIFY(!stranger->isVisibleTo(child));
1244 QVERIFY(!stranger->isVisibleTo(parent));
1247 void tst_QGraphicsItem::explicitlyVisible()
1249 QGraphicsScene scene;
1250 QGraphicsItem *parent = scene.addRect(QRectF(0, 0, 100, 100));
1251 QGraphicsItem *child = scene.addRect(QRectF(25, 25, 50, 50));
1252 child->setParentItem(parent);
1254 QVERIFY(parent->isVisible());
1255 QVERIFY(child->isVisible());
1259 QVERIFY(!parent->isVisible());
1260 QVERIFY(!child->isVisible());
1265 QVERIFY(parent->isVisible());
1266 QVERIFY(!child->isVisible());
1270 QVERIFY(!parent->isVisible());
1271 QVERIFY(!child->isVisible());
1275 QVERIFY(parent->isVisible());
1276 QVERIFY(!child->isVisible()); // <- explicitly hidden
1280 QVERIFY(child->isVisible());
1284 QVERIFY(!parent->isVisible());
1285 QVERIFY(!child->isVisible()); // <- explicit show doesn't work
1289 QVERIFY(parent->isVisible());
1290 QVERIFY(child->isVisible()); // <- no longer explicitly hidden
1292 // ------------------- Reparenting ------------------------------
1294 QGraphicsItem *parent2 = scene.addRect(-50, -50, 200, 200);
1295 QVERIFY(parent2->isVisible());
1297 // Reparent implicitly hidden item to a visible parent.
1299 QVERIFY(!parent->isVisible());
1300 QVERIFY(!child->isVisible());
1301 child->setParentItem(parent2);
1302 QVERIFY(parent2->isVisible());
1303 QVERIFY(child->isVisible());
1305 // Reparent implicitly hidden item to a hidden parent.
1306 child->setParentItem(parent);
1308 child->setParentItem(parent2);
1309 QVERIFY(!parent2->isVisible());
1310 QVERIFY(!child->isVisible());
1312 // Reparent explicitly hidden item to a visible parent.
1315 child->setParentItem(parent);
1316 QVERIFY(parent->isVisible());
1317 QVERIFY(!child->isVisible());
1319 // Reparent explicitly hidden item to a hidden parent.
1320 child->setParentItem(parent2);
1321 QVERIFY(!parent2->isVisible());
1322 QVERIFY(!child->isVisible());
1324 // Reparent explicitly hidden item to a visible parent.
1326 child->setParentItem(parent);
1327 QVERIFY(parent->isVisible());
1328 QVERIFY(!child->isVisible());
1330 // Reparent visible item to a hidden parent.
1333 child->setParentItem(parent2);
1334 QVERIFY(!parent2->isVisible());
1335 QVERIFY(!child->isVisible());
1337 QVERIFY(parent2->isVisible());
1338 QVERIFY(child->isVisible());
1340 // Reparent implicitly hidden child to root.
1342 QVERIFY(!child->isVisible());
1343 child->setParentItem(0);
1344 QVERIFY(child->isVisible());
1346 // Reparent an explicitly hidden child to root.
1348 child->setParentItem(parent2);
1350 QVERIFY(!child->isVisible());
1351 child->setParentItem(0);
1352 QVERIFY(!child->isVisible());
1355 void tst_QGraphicsItem::enabled()
1357 QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(-10, -10, 20, 20));
1358 item->setFlag(QGraphicsItem::ItemIsMovable);
1359 QVERIFY(item->isEnabled());
1360 item->setEnabled(false);
1361 QVERIFY(!item->isEnabled());
1362 item->setEnabled(true);
1363 QVERIFY(item->isEnabled());
1364 item->setEnabled(false);
1365 item->setFlag(QGraphicsItem::ItemIsFocusable);
1366 QGraphicsScene scene;
1367 QEvent activate(QEvent::WindowActivate);
1368 QApplication::sendEvent(&scene, &activate);
1370 scene.addItem(item);
1372 QVERIFY(!item->hasFocus());
1373 item->setEnabled(true);
1375 QVERIFY(item->hasFocus());
1376 item->setEnabled(false);
1377 QVERIFY(!item->hasFocus());
1379 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
1380 event.setButton(Qt::LeftButton);
1381 event.setScenePos(QPointF(0, 0));
1382 QApplication::sendEvent(&scene, &event);
1383 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1384 item->setEnabled(true);
1385 QApplication::sendEvent(&scene, &event);
1386 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
1387 item->setEnabled(false);
1388 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1391 void tst_QGraphicsItem::explicitlyEnabled()
1393 QGraphicsScene scene;
1394 QGraphicsItem *parent = scene.addRect(QRectF(0, 0, 100, 100));
1395 QGraphicsItem *child = scene.addRect(QRectF(25, 25, 50, 50));
1396 child->setParentItem(parent);
1398 QVERIFY(parent->isEnabled());
1399 QVERIFY(child->isEnabled());
1401 parent->setEnabled(false);
1403 QVERIFY(!parent->isEnabled());
1404 QVERIFY(!child->isEnabled());
1406 parent->setEnabled(true);
1407 child->setEnabled(false);
1409 QVERIFY(parent->isEnabled());
1410 QVERIFY(!child->isEnabled());
1412 parent->setEnabled(false);
1414 QVERIFY(!parent->isEnabled());
1415 QVERIFY(!child->isEnabled());
1417 parent->setEnabled(true);
1419 QVERIFY(parent->isEnabled());
1420 QVERIFY(!child->isEnabled()); // <- explicitly disabled
1422 child->setEnabled(true);
1424 QVERIFY(child->isEnabled());
1426 parent->setEnabled(false);
1428 QVERIFY(!parent->isEnabled());
1429 QVERIFY(!child->isEnabled()); // <- explicit enabled doesn't work
1431 parent->setEnabled(true);
1433 QVERIFY(parent->isEnabled());
1434 QVERIFY(child->isEnabled()); // <- no longer explicitly disabled
1436 // ------------------- Reparenting ------------------------------
1438 QGraphicsItem *parent2 = scene.addRect(-50, -50, 200, 200);
1439 QVERIFY(parent2->isEnabled());
1441 // Reparent implicitly hidden item to a enabled parent.
1442 parent->setEnabled(false);
1443 QVERIFY(!parent->isEnabled());
1444 QVERIFY(!child->isEnabled());
1445 child->setParentItem(parent2);
1446 QVERIFY(parent2->isEnabled());
1447 QVERIFY(child->isEnabled());
1449 // Reparent implicitly hidden item to a hidden parent.
1450 child->setParentItem(parent);
1451 parent2->setEnabled(false);
1452 child->setParentItem(parent2);
1453 QVERIFY(!parent2->isEnabled());
1454 QVERIFY(!child->isEnabled());
1456 // Reparent explicitly hidden item to a enabled parent.
1457 child->setEnabled(false);
1458 parent->setEnabled(true);
1459 child->setParentItem(parent);
1460 QVERIFY(parent->isEnabled());
1461 QVERIFY(!child->isEnabled());
1463 // Reparent explicitly hidden item to a hidden parent.
1464 child->setParentItem(parent2);
1465 QVERIFY(!parent2->isEnabled());
1466 QVERIFY(!child->isEnabled());
1468 // Reparent explicitly hidden item to a enabled parent.
1469 parent->setEnabled(true);
1470 child->setParentItem(parent);
1471 QVERIFY(parent->isEnabled());
1472 QVERIFY(!child->isEnabled());
1474 // Reparent enabled item to a hidden parent.
1475 child->setEnabled(true);
1476 parent2->setEnabled(false);
1477 child->setParentItem(parent2);
1478 QVERIFY(!parent2->isEnabled());
1479 QVERIFY(!child->isEnabled());
1480 parent2->setEnabled(true);
1481 QVERIFY(parent2->isEnabled());
1482 QVERIFY(child->isEnabled());
1484 // Reparent implicitly hidden child to root.
1485 parent2->setEnabled(false);
1486 QVERIFY(!child->isEnabled());
1487 child->setParentItem(0);
1488 QVERIFY(child->isEnabled());
1490 // Reparent an explicitly hidden child to root.
1491 child->setEnabled(false);
1492 child->setParentItem(parent2);
1493 parent2->setEnabled(true);
1494 QVERIFY(!child->isEnabled());
1495 child->setParentItem(0);
1496 QVERIFY(!child->isEnabled());
1499 class SelectChangeItem : public QGraphicsRectItem
1502 SelectChangeItem() : QGraphicsRectItem(-50, -50, 100, 100) { setBrush(Qt::blue); }
1506 QVariant itemChange(GraphicsItemChange change, const QVariant &value)
1508 if (change == ItemSelectedChange)
1509 values << value.toBool();
1510 return QGraphicsRectItem::itemChange(change, value);
1514 void tst_QGraphicsItem::selected()
1516 SelectChangeItem *item = new SelectChangeItem;
1517 item->setFlag(QGraphicsItem::ItemIsSelectable);
1518 QVERIFY(!item->isSelected());
1519 QVERIFY(item->values.isEmpty());
1520 item->setSelected(true);
1521 QCOMPARE(item->values.size(), 1);
1522 QCOMPARE(item->values.last(), true);
1523 QVERIFY(item->isSelected());
1524 item->setSelected(false);
1525 QCOMPARE(item->values.size(), 2);
1526 QCOMPARE(item->values.last(), false);
1527 QVERIFY(!item->isSelected());
1528 item->setSelected(true);
1529 QCOMPARE(item->values.size(), 3);
1530 item->setEnabled(false);
1531 QCOMPARE(item->values.size(), 4);
1532 QCOMPARE(item->values.last(), false);
1533 QVERIFY(!item->isSelected());
1534 item->setEnabled(true);
1535 QCOMPARE(item->values.size(), 4);
1536 item->setSelected(true);
1537 QCOMPARE(item->values.size(), 5);
1538 QCOMPARE(item->values.last(), true);
1539 QVERIFY(item->isSelected());
1540 item->setVisible(false);
1541 QCOMPARE(item->values.size(), 6);
1542 QCOMPARE(item->values.last(), false);
1543 QVERIFY(!item->isSelected());
1544 item->setVisible(true);
1545 QCOMPARE(item->values.size(), 6);
1546 item->setSelected(true);
1547 QCOMPARE(item->values.size(), 7);
1548 QCOMPARE(item->values.last(), true);
1549 QVERIFY(item->isSelected());
1551 QGraphicsScene scene(-100, -100, 200, 200);
1552 scene.addItem(item);
1553 QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>() << item);
1554 item->setSelected(false);
1555 QVERIFY(scene.selectedItems().isEmpty());
1556 item->setSelected(true);
1557 QCOMPARE(scene.selectedItems(), QList<QGraphicsItem *>() << item);
1558 item->setSelected(false);
1559 QVERIFY(scene.selectedItems().isEmpty());
1561 // Interactive selection
1562 QGraphicsView view(&scene);
1563 view.setFixedSize(250, 250);
1566 QTest::qWaitForWindowShown(&view);
1567 qApp->processEvents();
1568 qApp->processEvents();
1570 scene.clearSelection();
1571 QCOMPARE(item->values.size(), 10);
1572 QCOMPARE(item->values.last(), false);
1573 QVERIFY(!item->isSelected());
1575 // Click inside and check that it's selected
1576 QTest::mouseMove(view.viewport());
1577 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos()));
1578 QCOMPARE(item->values.size(), 11);
1579 QCOMPARE(item->values.last(), true);
1580 QVERIFY(item->isSelected());
1582 // Click outside and check that it's not selected
1583 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos() + QPointF(item->boundingRect().width(), item->boundingRect().height())));
1584 QCOMPARE(item->values.size(), 12);
1585 QCOMPARE(item->values.last(), false);
1586 QVERIFY(!item->isSelected());
1588 SelectChangeItem *item2 = new SelectChangeItem;
1589 item2->setFlag(QGraphicsItem::ItemIsSelectable);
1590 item2->setPos(100, 0);
1591 scene.addItem(item2);
1593 // Click inside and check that it's selected
1594 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos()));
1595 QCOMPARE(item->values.size(), 13);
1596 QCOMPARE(item->values.last(), true);
1597 QVERIFY(item->isSelected());
1599 // Click inside item2 and check that it's selected, and item is not
1600 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
1601 QCOMPARE(item->values.size(), 14);
1602 QCOMPARE(item->values.last(), false);
1603 QVERIFY(!item->isSelected());
1604 QCOMPARE(item2->values.size(), 1);
1605 QCOMPARE(item2->values.last(), true);
1606 QVERIFY(item2->isSelected());
1609 void tst_QGraphicsItem::selected2()
1611 // Selecting an item, then moving another previously caused a crash.
1612 QGraphicsScene scene;
1613 QGraphicsItem *line1 = scene.addRect(QRectF(0, 0, 100, 100));
1614 line1->setPos(-105, 0);
1615 line1->setFlag(QGraphicsItem::ItemIsSelectable);
1617 QGraphicsItem *line2 = scene.addRect(QRectF(0, 0, 100, 100));
1618 line2->setFlag(QGraphicsItem::ItemIsMovable);
1620 line1->setSelected(true);
1623 QGraphicsSceneMouseEvent mousePress(QEvent::GraphicsSceneMousePress);
1624 mousePress.setScenePos(QPointF(50, 50));
1625 mousePress.setButton(Qt::LeftButton);
1626 QApplication::sendEvent(&scene, &mousePress);
1627 QVERIFY(mousePress.isAccepted());
1630 QGraphicsSceneMouseEvent mouseMove(QEvent::GraphicsSceneMouseMove);
1631 mouseMove.setScenePos(QPointF(60, 60));
1632 mouseMove.setButton(Qt::LeftButton);
1633 mouseMove.setButtons(Qt::LeftButton);
1634 QApplication::sendEvent(&scene, &mouseMove);
1635 QVERIFY(mouseMove.isAccepted());
1639 void tst_QGraphicsItem::selected_group()
1641 QGraphicsScene scene;
1642 QGraphicsItem *item1 = scene.addRect(QRectF());
1643 QGraphicsItem *item2 = scene.addRect(QRectF());
1644 item1->setFlag(QGraphicsItem::ItemIsSelectable);
1645 item2->setFlag(QGraphicsItem::ItemIsSelectable);
1646 scene.addRect(QRectF())->setParentItem(item1);
1647 QGraphicsItem *leaf = scene.addRect(QRectF());
1648 leaf->setFlag(QGraphicsItem::ItemIsSelectable);
1649 leaf->setParentItem(item2);
1651 QGraphicsItemGroup *group = scene.createItemGroup(QList<QGraphicsItem *>() << item1 << item2);
1652 QCOMPARE(group->scene(), &scene);
1653 group->setFlag(QGraphicsItem::ItemIsSelectable);
1654 foreach (QGraphicsItem *item, scene.items()) {
1656 QVERIFY(!item->group());
1658 QCOMPARE(item->group(), group);
1661 QVERIFY(group->handlesChildEvents());
1662 QVERIFY(!group->isSelected());
1663 group->setSelected(false);
1664 QVERIFY(!group->isSelected());
1665 group->setSelected(true);
1666 QVERIFY(group->isSelected());
1667 foreach (QGraphicsItem *item, scene.items())
1668 QVERIFY(item->isSelected());
1669 group->setSelected(false);
1670 QVERIFY(!group->isSelected());
1671 foreach (QGraphicsItem *item, scene.items())
1672 QVERIFY(!item->isSelected());
1673 leaf->setSelected(true);
1674 foreach (QGraphicsItem *item, scene.items())
1675 QVERIFY(item->isSelected());
1676 leaf->setSelected(false);
1677 foreach (QGraphicsItem *item, scene.items())
1678 QVERIFY(!item->isSelected());
1680 leaf->setSelected(true);
1681 QGraphicsScene scene2;
1682 scene2.addItem(item1);
1683 QVERIFY(!item1->isSelected());
1684 QVERIFY(item2->isSelected());
1687 void tst_QGraphicsItem::selected_textItem()
1689 QGraphicsScene scene;
1690 QGraphicsTextItem *text = scene.addText(QLatin1String("Text"));
1691 text->setFlag(QGraphicsItem::ItemIsSelectable);
1693 QGraphicsView view(&scene);
1695 QTest::qWaitForWindowShown(&view);
1698 QTRY_VERIFY(!text->isSelected());
1699 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0,
1700 view.mapFromScene(text->mapToScene(0, 0)));
1701 QTRY_VERIFY(text->isSelected());
1703 text->setSelected(false);
1704 text->setTextInteractionFlags(Qt::TextEditorInteraction);
1706 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0,
1707 view.mapFromScene(text->mapToScene(0, 0)));
1708 QTRY_VERIFY(text->isSelected());
1711 void tst_QGraphicsItem::selected_multi()
1713 // Test multiselection behavior
1714 QGraphicsScene scene;
1716 // Create two disjoint items
1717 QGraphicsItem *item1 = scene.addRect(QRectF(-10, -10, 20, 20));
1718 QGraphicsItem *item2 = scene.addRect(QRectF(-10, -10, 20, 20));
1719 item1->setPos(-15, 0);
1720 item2->setPos(15, 20);
1722 // Make both items selectable
1723 item1->setFlag(QGraphicsItem::ItemIsSelectable);
1724 item2->setFlag(QGraphicsItem::ItemIsSelectable);
1726 // Create and show a view
1727 QGraphicsView view(&scene);
1729 view.fitInView(scene.sceneRect());
1730 qApp->processEvents();
1732 QVERIFY(!item1->isSelected());
1733 QVERIFY(!item2->isSelected());
1739 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
1741 QVERIFY(item1->isSelected());
1742 QVERIFY(!item2->isSelected());
1745 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
1747 QVERIFY(item2->isSelected());
1748 QVERIFY(!item1->isSelected());
1750 // Ctrl-click on item1
1751 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1753 QVERIFY(item2->isSelected());
1754 QVERIFY(item1->isSelected());
1756 // Ctrl-click on item1 again
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 item2
1763 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item2->scenePos()));
1765 QVERIFY(!item2->isSelected());
1766 QVERIFY(!item1->isSelected());
1769 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
1771 QVERIFY(item1->isSelected());
1772 QVERIFY(!item2->isSelected());
1775 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(0, 0));
1777 QVERIFY(!item1->isSelected());
1778 QVERIFY(!item2->isSelected());
1781 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
1783 QVERIFY(item1->isSelected());
1784 QVERIFY(!item2->isSelected());
1786 // Ctrl-click on scene
1787 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(0, 0));
1789 QVERIFY(!item1->isSelected());
1790 QVERIFY(!item2->isSelected());
1793 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
1795 QVERIFY(item1->isSelected());
1796 QVERIFY(!item2->isSelected());
1799 QTest::mousePress(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
1801 QVERIFY(!item1->isSelected());
1802 QVERIFY(item2->isSelected());
1805 QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item2->scenePos()));
1807 QVERIFY(!item1->isSelected());
1808 QVERIFY(item2->isSelected());
1811 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item1->scenePos()));
1813 QVERIFY(item1->isSelected());
1814 QVERIFY(!item2->isSelected());
1816 // Ctrl-click on item1
1817 QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1819 QVERIFY(!item1->isSelected());
1820 QVERIFY(!item2->isSelected());
1822 // Ctrl-press on item1
1823 QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1825 QVERIFY(!item1->isSelected());
1826 QVERIFY(!item2->isSelected());
1829 // Ctrl-move on item1
1830 QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item1->scenePos()) + QPoint(1, 0), Qt::LeftButton, Qt::LeftButton, Qt::ControlModifier);
1831 QApplication::sendEvent(view.viewport(), &event);
1833 QVERIFY(!item1->isSelected());
1834 QVERIFY(!item2->isSelected());
1838 QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1840 QVERIFY(item1->isSelected());
1841 QVERIFY(!item2->isSelected());
1843 item1->setFlag(QGraphicsItem::ItemIsMovable);
1844 item1->setSelected(false);
1846 // Ctrl-press on item1
1847 QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1849 QVERIFY(!item1->isSelected());
1850 QVERIFY(!item2->isSelected());
1853 // Ctrl-move on item1
1854 QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item1->scenePos()) + QPoint(1, 0), Qt::LeftButton, Qt::LeftButton, Qt::ControlModifier);
1855 QApplication::sendEvent(view.viewport(), &event);
1857 QVERIFY(item1->isSelected());
1858 QVERIFY(!item2->isSelected());
1862 QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ControlModifier, view.mapFromScene(item1->scenePos()));
1864 QVERIFY(item1->isSelected());
1865 QVERIFY(!item2->isSelected());
1868 void tst_QGraphicsItem::acceptedMouseButtons()
1870 QGraphicsScene scene;
1871 QGraphicsRectItem *item1 = scene.addRect(QRectF(-10, -10, 20, 20));
1872 QGraphicsRectItem *item2 = scene.addRect(QRectF(-10, -10, 20, 20));
1873 item2->setZValue(1);
1875 item1->setFlag(QGraphicsItem::ItemIsMovable);
1876 item2->setFlag(QGraphicsItem::ItemIsMovable);
1878 QCOMPARE(item1->acceptedMouseButtons(), Qt::MouseButtons(0x1f));
1879 QCOMPARE(item2->acceptedMouseButtons(), Qt::MouseButtons(0x1f));
1881 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
1882 event.setButton(Qt::LeftButton);
1883 event.setScenePos(QPointF(0, 0));
1884 QApplication::sendEvent(&scene, &event);
1885 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item2);
1886 item2->setAcceptedMouseButtons(0);
1887 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
1888 QApplication::sendEvent(&scene, &event);
1889 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item1);
1892 class HoverItem : public QGraphicsRectItem
1895 HoverItem(const QRectF &rect)
1896 : QGraphicsRectItem(rect), hoverInCount(0),
1897 hoverMoveCount(0), hoverOutCount(0)
1904 void hoverEnterEvent(QGraphicsSceneHoverEvent *)
1907 void hoverMoveEvent(QGraphicsSceneHoverEvent *)
1908 { ++hoverMoveCount; }
1910 void hoverLeaveEvent(QGraphicsSceneHoverEvent *)
1911 { ++hoverOutCount; }
1914 void tst_QGraphicsItem::acceptsHoverEvents()
1916 QGraphicsScene scene;
1917 HoverItem *item1 = new HoverItem(QRectF(-10, -10, 20, 20));
1918 HoverItem *item2 = new HoverItem(QRectF(-5, -5, 10, 10));
1919 scene.addItem(item1);
1920 scene.addItem(item2);
1921 item2->setZValue(1);
1923 QVERIFY(!item1->acceptsHoverEvents());
1924 QVERIFY(!item2->acceptsHoverEvents());
1925 item1->setAcceptsHoverEvents(true);
1926 item2->setAcceptsHoverEvents(true);
1928 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
1929 event.setScenePos(QPointF(-100, -100));
1930 QApplication::sendEvent(&scene, &event);
1931 event.setScenePos(QPointF(-2.5, -2.5));
1932 QApplication::sendEvent(&scene, &event);
1934 QCOMPARE(item1->hoverInCount, 0);
1935 QCOMPARE(item2->hoverInCount, 1);
1937 item1->setAcceptsHoverEvents(false);
1938 item2->setAcceptsHoverEvents(false);
1940 event.setScenePos(QPointF(-100, -100));
1941 QApplication::sendEvent(&scene, &event);
1942 event.setScenePos(QPointF(-2.5, -2.5));
1943 QApplication::sendEvent(&scene, &event);
1945 QCOMPARE(item1->hoverInCount, 0);
1946 QCOMPARE(item2->hoverInCount, 1);
1948 item1->setAcceptsHoverEvents(true);
1949 item2->setAcceptsHoverEvents(false);
1951 event.setScenePos(QPointF(-100, -100));
1952 QApplication::sendEvent(&scene, &event);
1953 event.setScenePos(QPointF(-2.5, -2.5));
1954 QApplication::sendEvent(&scene, &event);
1956 QCOMPARE(item1->hoverInCount, 1);
1957 QCOMPARE(item2->hoverInCount, 1);
1960 void tst_QGraphicsItem::childAcceptsHoverEvents()
1962 QGraphicsScene scene;
1963 HoverItem *item1 = new HoverItem(QRectF(-10, -10, 20, 20));
1964 HoverItem *item2 = new HoverItem(QRectF(-5, -5, 10, 10));
1966 scene.addItem(item1);
1967 scene.addItem(item2);
1968 item2->setParentItem(item1);
1969 item2->setAcceptHoverEvents(true);
1971 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
1972 event.setScenePos(QPointF(-100, -100));
1973 QApplication::sendEvent(&scene, &event);
1974 QCOMPARE(item2->hoverInCount, 0);
1975 QCOMPARE(item2->hoverMoveCount, 0);
1976 QCOMPARE(item2->hoverOutCount, 0);
1977 QCOMPARE(item1->hoverInCount, 0);
1978 QCOMPARE(item1->hoverMoveCount, 0);
1979 QCOMPARE(item1->hoverOutCount, 0);
1981 event.setScenePos(QPointF(-2.5, -2.5));
1982 QApplication::sendEvent(&scene, &event);
1984 QCOMPARE(item2->hoverInCount, 1);
1985 QCOMPARE(item2->hoverMoveCount, 1);
1986 QCOMPARE(item2->hoverOutCount, 0);
1987 QCOMPARE(item1->hoverInCount, 0);
1988 QCOMPARE(item1->hoverMoveCount, 0);
1989 QCOMPARE(item1->hoverOutCount, 0);
1991 event.setScenePos(QPointF(0, 0));
1992 QApplication::sendEvent(&scene, &event);
1994 QCOMPARE(item2->hoverInCount, 1);
1995 QCOMPARE(item2->hoverMoveCount, 2);
1996 QCOMPARE(item2->hoverOutCount, 0);
1997 QCOMPARE(item1->hoverInCount, 0);
1998 QCOMPARE(item1->hoverMoveCount, 0);
1999 QCOMPARE(item1->hoverOutCount, 0);
2001 event.setScenePos(QPointF(-7, -7));
2002 QApplication::sendEvent(&scene, &event);
2004 QCOMPARE(item2->hoverInCount, 1);
2005 QCOMPARE(item2->hoverMoveCount, 2);
2006 QCOMPARE(item2->hoverOutCount, 1);
2007 QCOMPARE(item1->hoverInCount, 0);
2008 QCOMPARE(item1->hoverMoveCount, 0);
2009 QCOMPARE(item1->hoverOutCount, 0);
2011 event.setScenePos(QPointF(0, 0));
2012 QApplication::sendEvent(&scene, &event);
2014 QCOMPARE(item2->hoverInCount, 2);
2015 QCOMPARE(item2->hoverMoveCount, 3);
2016 QCOMPARE(item2->hoverOutCount, 1);
2017 QCOMPARE(item1->hoverInCount, 0);
2018 QCOMPARE(item1->hoverMoveCount, 0);
2019 QCOMPARE(item1->hoverOutCount, 0);
2021 HoverItem *item0 = new HoverItem(QRectF(-20, -20, 20, 20));
2022 scene.addItem(item0);
2023 item1->setParentItem(item0);
2024 item0->setAcceptHoverEvents(true);
2026 event.setScenePos(QPointF(-100, -100));
2027 QApplication::sendEvent(&scene, &event);
2029 event.setScenePos(QPointF(-15, -15));
2030 QApplication::sendEvent(&scene, &event);
2032 QCOMPARE(item2->hoverInCount, 2);
2033 QCOMPARE(item2->hoverMoveCount, 3);
2034 QCOMPARE(item2->hoverOutCount, 2);
2035 QCOMPARE(item1->hoverInCount, 0);
2036 QCOMPARE(item1->hoverMoveCount, 0);
2037 QCOMPARE(item1->hoverOutCount, 0);
2038 QCOMPARE(item0->hoverInCount, 1);
2039 QCOMPARE(item0->hoverMoveCount, 1);
2040 QCOMPARE(item0->hoverOutCount, 0);
2043 void tst_QGraphicsItem::hasFocus()
2045 QGraphicsLineItem *line = new QGraphicsLineItem;
2046 QVERIFY(!line->hasFocus());
2048 QVERIFY(!line->hasFocus());
2050 QGraphicsScene scene;
2051 QEvent activate(QEvent::WindowActivate);
2052 QApplication::sendEvent(&scene, &activate);
2054 scene.addItem(line);
2057 QVERIFY(!line->hasFocus());
2058 line->setFlag(QGraphicsItem::ItemIsFocusable);
2060 QVERIFY(line->hasFocus());
2062 QGraphicsScene scene2;
2063 QApplication::sendEvent(&scene2, &activate);
2065 scene2.addItem(line);
2066 QVERIFY(!line->hasFocus());
2068 QCOMPARE(scene.focusItem(), (QGraphicsItem *)0);
2069 QCOMPARE(scene2.focusItem(), (QGraphicsItem *)0);
2072 QVERIFY(line->hasFocus());
2074 QVERIFY(!line->hasFocus());
2076 QGraphicsLineItem *line2 = new QGraphicsLineItem;
2077 line2->setFlag(QGraphicsItem::ItemIsFocusable);
2078 scene2.addItem(line2);
2081 QVERIFY(!line->hasFocus());
2082 QVERIFY(line2->hasFocus());
2084 QVERIFY(line->hasFocus());
2085 QVERIFY(!line2->hasFocus());
2088 void tst_QGraphicsItem::pos()
2090 QGraphicsItem *child = new QGraphicsLineItem;
2091 QGraphicsItem *parent = new QGraphicsLineItem;
2093 QCOMPARE(child->pos(), QPointF());
2094 QCOMPARE(parent->pos(), QPointF());
2096 child->setParentItem(parent);
2097 child->setPos(10, 10);
2099 QCOMPARE(child->pos(), QPointF(10, 10));
2101 parent->setPos(10, 10);
2103 QCOMPARE(parent->pos(), QPointF(10, 10));
2104 QCOMPARE(child->pos(), QPointF(10, 10));
2110 void tst_QGraphicsItem::scenePos()
2112 QGraphicsItem *child = new QGraphicsLineItem;
2113 QGraphicsItem *parent = new QGraphicsLineItem;
2115 QCOMPARE(child->scenePos(), QPointF());
2116 QCOMPARE(parent->scenePos(), QPointF());
2118 child->setParentItem(parent);
2119 child->setPos(10, 10);
2121 QCOMPARE(child->scenePos(), QPointF(10, 10));
2123 parent->setPos(10, 10);
2125 QCOMPARE(parent->scenePos(), QPointF(10, 10));
2126 QCOMPARE(child->scenePos(), QPointF(20, 20));
2128 parent->setPos(20, 20);
2130 QCOMPARE(parent->scenePos(), QPointF(20, 20));
2131 QCOMPARE(child->scenePos(), QPointF(30, 30));
2137 void tst_QGraphicsItem::matrix()
2139 QGraphicsLineItem line;
2140 QCOMPARE(line.matrix(), QMatrix());
2141 line.setMatrix(QMatrix().rotate(90));
2142 QCOMPARE(line.matrix(), QMatrix().rotate(90));
2143 line.setMatrix(QMatrix().rotate(90));
2144 QCOMPARE(line.matrix(), QMatrix().rotate(90));
2145 line.setMatrix(QMatrix().rotate(90), true);
2146 QCOMPARE(line.matrix(), QMatrix().rotate(180));
2147 line.setMatrix(QMatrix().rotate(-90), true);
2148 QCOMPARE(line.matrix(), QMatrix().rotate(90));
2150 QCOMPARE(line.matrix(), QMatrix());
2153 QCOMPARE(line.matrix(), QMatrix().rotate(90));
2155 QCOMPARE(line.matrix(), QMatrix().rotate(90).rotate(90));
2159 QCOMPARE(line.matrix(), QMatrix().scale(2, 4));
2161 QCOMPARE(line.matrix(), QMatrix().scale(2, 4).scale(2, 4));
2165 QCOMPARE(line.matrix(), QMatrix().shear(2, 4));
2167 QCOMPARE(line.matrix(), QMatrix().shear(2, 4).shear(2, 4));
2170 line.translate(10, 10);
2171 QCOMPARE(line.matrix(), QMatrix().translate(10, 10));
2172 line.translate(10, 10);
2173 QCOMPARE(line.matrix(), QMatrix().translate(10, 10).translate(10, 10));
2177 void tst_QGraphicsItem::sceneMatrix()
2179 QGraphicsLineItem *parent = new QGraphicsLineItem;
2180 QGraphicsLineItem *child = new QGraphicsLineItem(QLineF(), parent);
2182 QCOMPARE(parent->sceneMatrix(), QMatrix());
2183 QCOMPARE(child->sceneMatrix(), QMatrix());
2185 parent->translate(10, 10);
2186 QCOMPARE(parent->sceneMatrix(), QMatrix().translate(10, 10));
2187 QCOMPARE(child->sceneMatrix(), QMatrix().translate(10, 10));
2189 child->translate(10, 10);
2190 QCOMPARE(parent->sceneMatrix(), QMatrix().translate(10, 10));
2191 QCOMPARE(child->sceneMatrix(), QMatrix().translate(20, 20));
2194 QCOMPARE(parent->sceneMatrix(), QMatrix().translate(10, 10).rotate(90));
2195 QCOMPARE(child->sceneMatrix(), QMatrix().translate(10, 10).rotate(90).translate(10, 10));
2201 void tst_QGraphicsItem::setMatrix()
2203 QGraphicsScene scene;
2204 qRegisterMetaType<QList<QRectF> >("QList<QRectF>");
2205 QSignalSpy spy(&scene, SIGNAL(changed(QList<QRectF>)));
2206 QRectF unrotatedRect(-12, -34, 56, 78);
2207 QGraphicsRectItem item(unrotatedRect, 0, &scene);
2208 scene.update(scene.sceneRect());
2209 QApplication::instance()->processEvents();
2211 QCOMPARE(spy.count(), 1);
2213 item.setMatrix(QMatrix().rotate(qreal(12.34)));
2214 QRectF rotatedRect = scene.sceneRect();
2215 QVERIFY(unrotatedRect != rotatedRect);
2216 scene.update(scene.sceneRect());
2217 QApplication::instance()->processEvents();
2219 QCOMPARE(spy.count(), 2);
2221 item.setMatrix(QMatrix());
2223 scene.update(scene.sceneRect());
2224 QApplication::instance()->processEvents();
2226 QCOMPARE(spy.count(), 3);
2227 QList<QRectF> rlist = qVariantValue<QList<QRectF> >(spy.last().at(0));
2229 QCOMPARE(rlist.size(), 3);
2230 QCOMPARE(rlist.at(0), rotatedRect); // From item.setMatrix() (clearing rotated rect)
2231 QCOMPARE(rlist.at(1), rotatedRect); // From scene.update() (updating scene rect)
2232 QCOMPARE(rlist.at(2), unrotatedRect); // From post-update (update current state)
2235 static QList<QGraphicsItem *> _paintedItems;
2236 class PainterItem : public QGraphicsItem
2239 QRectF boundingRect() const
2240 { return QRectF(-10, -10, 20, 20); }
2242 void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
2243 { _paintedItems << this; painter->fillRect(boundingRect(), Qt::red); }
2246 void tst_QGraphicsItem::zValue()
2250 QGraphicsScene scene;
2252 QGraphicsItem *item1 = new PainterItem;
2253 QGraphicsItem *item2 = new PainterItem;
2254 QGraphicsItem *item3 = new PainterItem;
2255 QGraphicsItem *item4 = new PainterItem;
2256 scene.addItem(item1);
2257 scene.addItem(item2);
2258 scene.addItem(item3);
2259 scene.addItem(item4);
2260 item2->setZValue(-3);
2261 item4->setZValue(-2);
2262 item1->setZValue(-1);
2263 item3->setZValue(0);
2265 QGraphicsView view(&scene);
2268 qt_x11_wait_for_window_manager(&view);
2270 QApplication::processEvents();
2272 QApplication::sendPostedEvents(); //glib workaround
2275 QTRY_VERIFY(!_paintedItems.isEmpty());
2276 QVERIFY((_paintedItems.size() % 4) == 0);
2277 for (int i = 0; i < 3; ++i)
2278 QVERIFY(_paintedItems.at(i)->zValue() < _paintedItems.at(i + 1)->zValue());
2281 void tst_QGraphicsItem::shape()
2283 QGraphicsLineItem line(QLineF(-10, -10, 20, 20));
2285 // We unfortunately need this hack as QPainterPathStroker will set a width of 1.0
2286 // if we pass a value of 0.0 to QPainterPathStroker::setWidth()
2287 const qreal penWidthZero = qreal(0.00000001);
2289 QPainterPathStroker ps;
2290 ps.setWidth(penWidthZero);
2292 QPainterPath path(line.line().p1());
2293 path.lineTo(line.line().p2());
2294 QPainterPath p = ps.createStroke(path);
2296 QCOMPARE(line.shape(), p);
2299 linePen.setWidthF(5.0);
2300 linePen.setCapStyle(Qt::RoundCap);
2301 line.setPen(linePen);
2303 ps.setCapStyle(line.pen().capStyle());
2304 ps.setWidth(line.pen().widthF());
2305 p = ps.createStroke(path);
2307 QCOMPARE(line.shape(), p);
2309 linePen.setCapStyle(Qt::FlatCap);
2310 line.setPen(linePen);
2311 ps.setCapStyle(line.pen().capStyle());
2312 p = ps.createStroke(path);
2314 QCOMPARE(line.shape(), p);
2316 linePen.setCapStyle(Qt::SquareCap);
2317 line.setPen(linePen);
2318 ps.setCapStyle(line.pen().capStyle());
2319 p = ps.createStroke(path);
2321 QCOMPARE(line.shape(), p);
2323 QGraphicsRectItem rect(QRectF(-10, -10, 20, 20));
2324 QPainterPathStroker ps1;
2325 ps1.setWidth(penWidthZero);
2326 path = QPainterPath();
2327 path.addRect(rect.rect());
2328 p = ps1.createStroke(path);
2330 QCOMPARE(rect.shape(), p);
2332 QGraphicsEllipseItem ellipse(QRectF(-10, -10, 20, 20));
2333 QPainterPathStroker ps2;
2334 ps2.setWidth(ellipse.pen().widthF() <= 0.0 ? penWidthZero : ellipse.pen().widthF());
2335 path = QPainterPath();
2336 path.addEllipse(ellipse.rect());
2337 p = ps2.createStroke(path);
2339 QCOMPARE(ellipse.shape(), p);
2341 QPainterPathStroker ps3;
2342 ps3.setWidth(penWidthZero);
2343 p = ps3.createStroke(path);
2345 QGraphicsPathItem pathItem(path);
2346 QCOMPARE(pathItem.shape(), p);
2348 QRegion region(QRect(0, 0, 300, 200));
2349 region = region.subtracted(QRect(50, 50, 200, 100));
2351 QImage image(300, 200, QImage::Format_ARGB32_Premultiplied);
2353 QPainter painter(&image);
2354 painter.setClipRegion(region);
2355 painter.fillRect(0, 0, 300, 200, Qt::green);
2357 QPixmap pixmap = QPixmap::fromImage(image);
2359 QGraphicsPixmapItem pixmapItem(pixmap);
2360 path = QPainterPath();
2361 path.addRegion(region);
2364 QBitmap bitmap(300, 200);
2366 QPainter painter(&bitmap);
2367 painter.setClipRegion(region);
2368 painter.fillRect(0, 0, 300, 200, Qt::color1);
2371 QBitmap bitmap2(300, 200);
2373 painter.begin(&bitmap2);
2374 painter.setClipPath(pixmapItem.shape());
2375 painter.fillRect(0, 0, 300, 200, Qt::color1);
2378 QCOMPARE(bitmap.toImage(), bitmap2.toImage());
2382 poly << QPointF(0, 0) << QPointF(10, 0) << QPointF(0, 10);
2383 QGraphicsPolygonItem polygon(poly);
2384 path = QPainterPath();
2385 path.addPolygon(poly);
2387 QPainterPathStroker ps4;
2388 ps4.setWidth(penWidthZero);
2389 p = ps4.createStroke(path);
2391 QCOMPARE(polygon.shape(), p);
2394 void tst_QGraphicsItem::contains()
2396 if (sizeof(qreal) != sizeof(double))
2397 QSKIP("Skipped due to rounding errors");
2400 QGraphicsRectItem rect(QRectF(-10, -10, 20, 20));
2401 QVERIFY(!rect.contains(QPointF(-11, -10)));
2402 QVERIFY(rect.contains(QPointF(-10, -10)));
2403 QVERIFY(!rect.contains(QPointF(-11, 0)));
2404 QVERIFY(rect.contains(QPointF(-10, 0)));
2405 QVERIFY(rect.contains(QPointF(0, -10)));
2406 QVERIFY(rect.contains(QPointF(0, 0)));
2407 QVERIFY(rect.contains(QPointF(9, 9)));
2410 QGraphicsEllipseItem ellipse(QRectF(-10, -10, 20, 20));
2411 QVERIFY(!ellipse.contains(QPointF(-10, -10)));
2412 QVERIFY(ellipse.contains(QPointF(-9, 0)));
2413 QVERIFY(ellipse.contains(QPointF(0, -9)));
2414 QVERIFY(ellipse.contains(QPointF(0, 0)));
2415 QVERIFY(!ellipse.contains(QPointF(9, 9)));
2418 QGraphicsLineItem line(QLineF(-10, -10, 20, 20));
2419 QVERIFY(!line.contains(QPointF(-10, 0)));
2420 QVERIFY(!line.contains(QPointF(0, -10)));
2421 QVERIFY(!line.contains(QPointF(10, 0)));
2422 QVERIFY(!line.contains(QPointF(0, 10)));
2423 QVERIFY(line.contains(QPointF(0, 0)));
2424 QVERIFY(line.contains(QPointF(-9, -9)));
2425 QVERIFY(line.contains(QPointF(9, 9)));
2428 QGraphicsPolygonItem polygon(QPolygonF()
2432 QVERIFY(polygon.contains(QPointF(1, 1)));
2433 QVERIFY(polygon.contains(QPointF(4, 4)));
2434 QVERIFY(polygon.contains(QPointF(1, 4)));
2435 QVERIFY(polygon.contains(QPointF(4, 1)));
2436 QVERIFY(!polygon.contains(QPointF(8, 8)));
2437 QVERIFY(polygon.contains(QPointF(1, 8)));
2438 QVERIFY(polygon.contains(QPointF(8, 1)));
2441 void tst_QGraphicsItem::collidesWith_item()
2444 QGraphicsRectItem rect(QRectF(-10, -10, 20, 20));
2445 QGraphicsRectItem rect2(QRectF(-10, -10, 20, 20));
2446 QVERIFY(rect.collidesWithItem(&rect2));
2447 QVERIFY(rect2.collidesWithItem(&rect));
2448 rect2.setPos(21, 21);
2449 QVERIFY(!rect.collidesWithItem(&rect2));
2450 QVERIFY(!rect2.collidesWithItem(&rect));
2451 rect2.setPos(-21, -21);
2452 QVERIFY(!rect.collidesWithItem(&rect2));
2453 QVERIFY(!rect2.collidesWithItem(&rect));
2454 rect2.setPos(-17, -17);
2455 QVERIFY(rect.collidesWithItem(&rect2));
2456 QVERIFY(rect2.collidesWithItem(&rect));
2458 QGraphicsEllipseItem ellipse(QRectF(-10, -10, 20, 20));
2459 QGraphicsEllipseItem ellipse2(QRectF(-10, -10, 20, 20));
2460 QVERIFY(ellipse.collidesWithItem(&ellipse2));
2461 QVERIFY(ellipse2.collidesWithItem(&ellipse));
2462 ellipse2.setPos(21, 21);
2463 QVERIFY(!ellipse.collidesWithItem(&ellipse2));
2464 QVERIFY(!ellipse2.collidesWithItem(&ellipse));
2465 ellipse2.setPos(-21, -21);
2466 QVERIFY(!ellipse.collidesWithItem(&ellipse2));
2467 QVERIFY(!ellipse2.collidesWithItem(&ellipse));
2469 ellipse2.setPos(-17, -17);
2470 QVERIFY(!ellipse.collidesWithItem(&ellipse2));
2471 QVERIFY(!ellipse2.collidesWithItem(&ellipse));
2474 QGraphicsScene scene;
2475 QGraphicsRectItem rect(20, 20, 100, 100, 0, &scene);
2476 QGraphicsRectItem rect2(40, 40, 50, 50, 0, &scene);
2478 QGraphicsLineItem line(0, 0, 200, 200, 0, &scene);
2481 QCOMPARE(scene.items().size(), 3);
2483 QList<QGraphicsItem *> col1 = rect.collidingItems();
2484 QCOMPARE(col1.size(), 2);
2485 QCOMPARE(col1.first(), static_cast<QGraphicsItem *>(&line));
2486 QCOMPARE(col1.last(), static_cast<QGraphicsItem *>(&rect2));
2488 QList<QGraphicsItem *> col2 = rect2.collidingItems();
2489 QCOMPARE(col2.size(), 2);
2490 QCOMPARE(col2.first(), static_cast<QGraphicsItem *>(&line));
2491 QCOMPARE(col2.last(), static_cast<QGraphicsItem *>(&rect));
2493 QList<QGraphicsItem *> col3 = line.collidingItems();
2494 QCOMPARE(col3.size(), 2);
2495 QCOMPARE(col3.first(), static_cast<QGraphicsItem *>(&rect2));
2496 QCOMPARE(col3.last(), static_cast<QGraphicsItem *>(&rect));
2500 void tst_QGraphicsItem::collidesWith_path_data()
2502 QTest::addColumn<QPointF>("pos");
2503 QTest::addColumn<QMatrix>("matrix");
2504 QTest::addColumn<QPainterPath>("shape");
2505 QTest::addColumn<bool>("rectCollides");
2506 QTest::addColumn<bool>("ellipseCollides");
2508 QTest::newRow("nothing") << QPointF(0, 0) << QMatrix() << QPainterPath() << false << false;
2511 rect.addRect(0, 0, 20, 20);
2513 QTest::newRow("rect1") << QPointF(0, 0) << QMatrix() << rect << true << true;
2514 QTest::newRow("rect2") << QPointF(0, 0) << QMatrix().translate(21, 21) << rect << false << false;
2515 QTest::newRow("rect3") << QPointF(21, 21) << QMatrix() << rect << false << false;
2518 void tst_QGraphicsItem::collidesWith_path()
2520 QFETCH(QPointF, pos);
2521 QFETCH(QMatrix, matrix);
2522 QFETCH(QPainterPath, shape);
2523 QFETCH(bool, rectCollides);
2524 QFETCH(bool, ellipseCollides);
2526 QGraphicsRectItem rect(QRectF(0, 0, 20, 20));
2527 QGraphicsEllipseItem ellipse(QRectF(0, 0, 20, 20));
2530 rect.setMatrix(matrix);
2532 ellipse.setPos(pos);
2533 ellipse.setMatrix(matrix);
2535 QPainterPath mappedShape = rect.sceneMatrix().inverted().map(shape);
2538 QVERIFY(rect.collidesWithPath(mappedShape));
2540 QVERIFY(!rect.collidesWithPath(mappedShape));
2542 if (ellipseCollides)
2543 QVERIFY(ellipse.collidesWithPath(mappedShape));
2545 QVERIFY(!ellipse.collidesWithPath(mappedShape));
2548 void tst_QGraphicsItem::collidesWithItemWithClip()
2550 QGraphicsScene scene;
2552 QGraphicsEllipseItem *ellipse = scene.addEllipse(0, 0, 100, 100);
2553 ellipse->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
2554 QGraphicsEllipseItem *ellipse2 = scene.addEllipse(0, 0, 10, 10);
2555 ellipse2->setParentItem(ellipse);
2556 QGraphicsEllipseItem *ellipse3 = scene.addEllipse(0, 0, 10, 10);
2557 ellipse3->setParentItem(ellipse);
2558 QGraphicsEllipseItem *ellipse5 = scene.addEllipse(50, 50, 10, 10);
2559 ellipse5->setParentItem(ellipse);
2560 QGraphicsEllipseItem *ellipse4 = scene.addEllipse(0, 0, 10, 10);
2562 QVERIFY(ellipse2->collidesWithItem(ellipse3));
2563 QVERIFY(ellipse3->collidesWithItem(ellipse2));
2564 QVERIFY(!ellipse2->collidesWithItem(ellipse));
2565 QVERIFY(!ellipse->collidesWithItem(ellipse2));
2566 QVERIFY(!ellipse4->collidesWithItem(ellipse));
2567 QVERIFY(!ellipse4->collidesWithItem(ellipse2));
2568 QVERIFY(!ellipse4->collidesWithItem(ellipse3));
2569 QVERIFY(!ellipse->collidesWithItem(ellipse4));
2570 QVERIFY(!ellipse2->collidesWithItem(ellipse4));
2571 QVERIFY(!ellipse3->collidesWithItem(ellipse4));
2572 QVERIFY(ellipse->collidesWithItem(ellipse5));
2573 QVERIFY(ellipse5->collidesWithItem(ellipse));
2576 class MyItem : public QGraphicsEllipseItem
2579 bool isObscuredBy(const QGraphicsItem *item) const
2581 const MyItem *myItem = qgraphicsitem_cast<const MyItem *>(item);
2583 if (item->zValue() > zValue()) {
2585 QPointF topMid = (r.topRight()+r.topLeft())/2;
2586 QPointF botMid = (r.bottomRight()+r.bottomLeft())/2;
2587 QPointF leftMid = (r.topLeft()+r.bottomLeft())/2;
2588 QPointF rightMid = (r.topRight()+r.bottomRight())/2;
2590 QPainterPath mappedShape = item->mapToItem(this, item->opaqueArea());
2592 if (mappedShape.contains(topMid) &&
2593 mappedShape.contains(botMid) &&
2594 mappedShape.contains(leftMid) &&
2595 mappedShape.contains(rightMid))
2603 return QGraphicsItem::isObscuredBy(item);
2606 QPainterPath opaqueArea() const
2614 int type() const { return Type; }
2617 void tst_QGraphicsItem::isObscuredBy()
2619 QGraphicsScene scene;
2621 MyItem myitem1, myitem2;
2623 myitem1.setRect(QRectF(50, 50, 40, 200));
2626 myitem2.setRect(QRectF(25, 25, 20, 20));
2627 myitem2.setZValue(-1.0);
2628 scene.addItem(&myitem1);
2629 scene.addItem(&myitem2);
2631 QVERIFY(!myitem2.isObscuredBy(&myitem1));
2632 QVERIFY(!myitem1.isObscuredBy(&myitem2));
2634 myitem2.setRect(QRectF(-50, 85, 20, 20));
2635 QVERIFY(myitem2.isObscuredBy(&myitem1));
2636 QVERIFY(!myitem1.isObscuredBy(&myitem2));
2638 myitem2.setRect(QRectF(-30, 70, 20, 20));
2639 QVERIFY(!myitem2.isObscuredBy(&myitem1));
2640 QVERIFY(!myitem1.isObscuredBy(&myitem2));
2642 QGraphicsRectItem rect1, rect2;
2644 rect1.setRect(QRectF(-40, -40, 50, 50));
2645 rect1.setBrush(QBrush(Qt::red));
2646 rect2.setRect(QRectF(-30, -20, 20, 20));
2647 rect2.setZValue(-1.0);
2648 rect2.setBrush(QBrush(Qt::blue));
2650 QVERIFY(rect2.isObscuredBy(&rect1));
2651 QVERIFY(!rect1.isObscuredBy(&rect2));
2653 rect2.setPos(QPointF(-20, -25));
2655 QVERIFY(!rect2.isObscuredBy(&rect1));
2656 QVERIFY(!rect1.isObscuredBy(&rect2));
2658 rect2.setPos(QPointF(-100, -100));
2660 QVERIFY(!rect2.isObscuredBy(&rect1));
2661 QVERIFY(!rect1.isObscuredBy(&rect2));
2664 class OpaqueItem : public QGraphicsRectItem
2667 QPainterPath opaqueArea() const
2673 void tst_QGraphicsItem::isObscured()
2675 if (sizeof(qreal) != sizeof(double))
2676 QSKIP("Skipped due to rounding errors");
2678 OpaqueItem *item1 = new OpaqueItem;
2679 item1->setRect(0, 0, 100, 100);
2680 item1->setZValue(0);
2682 OpaqueItem *item2 = new OpaqueItem;
2683 item2->setZValue(1);
2684 item2->setRect(0, 0, 100, 100);
2686 QGraphicsScene scene;
2687 scene.addItem(item1);
2688 scene.addItem(item2);
2690 QVERIFY(item1->isObscured());
2691 QVERIFY(item1->isObscuredBy(item2));
2692 QVERIFY(item1->isObscured(QRectF(0, 0, 50, 50)));
2693 QVERIFY(item1->isObscured(QRectF(50, 0, 50, 50)));
2694 QVERIFY(item1->isObscured(QRectF(50, 50, 50, 50)));
2695 QVERIFY(item1->isObscured(QRectF(0, 50, 50, 50)));
2696 QVERIFY(item1->isObscured(0, 0, 50, 50));
2697 QVERIFY(item1->isObscured(50, 0, 50, 50));
2698 QVERIFY(item1->isObscured(50, 50, 50, 50));
2699 QVERIFY(item1->isObscured(0, 50, 50, 50));
2700 QVERIFY(!item2->isObscured());
2701 QVERIFY(!item2->isObscuredBy(item1));
2702 QVERIFY(!item2->isObscured(QRectF(0, 0, 50, 50)));
2703 QVERIFY(!item2->isObscured(QRectF(50, 0, 50, 50)));
2704 QVERIFY(!item2->isObscured(QRectF(50, 50, 50, 50)));
2705 QVERIFY(!item2->isObscured(QRectF(0, 50, 50, 50)));
2706 QVERIFY(!item2->isObscured(0, 0, 50, 50));
2707 QVERIFY(!item2->isObscured(50, 0, 50, 50));
2708 QVERIFY(!item2->isObscured(50, 50, 50, 50));
2709 QVERIFY(!item2->isObscured(0, 50, 50, 50));
2711 item2->moveBy(50, 0);
2713 QVERIFY(!item1->isObscured());
2714 QVERIFY(!item1->isObscuredBy(item2));
2715 QVERIFY(!item1->isObscured(QRectF(0, 0, 50, 50)));
2716 QVERIFY(item1->isObscured(QRectF(50, 0, 50, 50)));
2717 QVERIFY(item1->isObscured(QRectF(50, 50, 50, 50)));
2718 QVERIFY(!item1->isObscured(QRectF(0, 50, 50, 50)));
2719 QVERIFY(!item1->isObscured(0, 0, 50, 50));
2720 QVERIFY(item1->isObscured(50, 0, 50, 50));
2721 QVERIFY(item1->isObscured(50, 50, 50, 50));
2722 QVERIFY(!item1->isObscured(0, 50, 50, 50));
2723 QVERIFY(!item2->isObscured());
2724 QVERIFY(!item2->isObscuredBy(item1));
2725 QVERIFY(!item2->isObscured(QRectF(0, 0, 50, 50)));
2726 QVERIFY(!item2->isObscured(QRectF(50, 0, 50, 50)));
2727 QVERIFY(!item2->isObscured(QRectF(50, 50, 50, 50)));
2728 QVERIFY(!item2->isObscured(QRectF(0, 50, 50, 50)));
2729 QVERIFY(!item2->isObscured(0, 0, 50, 50));
2730 QVERIFY(!item2->isObscured(50, 0, 50, 50));
2731 QVERIFY(!item2->isObscured(50, 50, 50, 50));
2732 QVERIFY(!item2->isObscured(0, 50, 50, 50));
2735 void tst_QGraphicsItem::mapFromToParent()
2738 path1.addRect(0, 0, 200, 200);
2741 path2.addRect(0, 0, 100, 100);
2744 path3.addRect(0, 0, 50, 50);
2747 path4.addRect(0, 0, 25, 25);
2749 QGraphicsItem *item1 = new QGraphicsPathItem(path1);
2750 QGraphicsItem *item2 = new QGraphicsPathItem(path2, item1);
2751 QGraphicsItem *item3 = new QGraphicsPathItem(path3, item2);
2752 QGraphicsItem *item4 = new QGraphicsPathItem(path4, item3);
2754 item1->setPos(10, 10);
2755 item2->setPos(10, 10);
2756 item3->setPos(10, 10);
2757 item4->setPos(10, 10);
2759 for (int i = 0; i < 4; ++i) {
2761 matrix.rotate(i * 90);
2762 matrix.translate(i * 100, -i * 100);
2764 item1->setMatrix(matrix);
2766 QCOMPARE(item1->mapToParent(QPointF(0, 0)), item1->pos() + matrix.map(QPointF(0, 0)));
2767 QCOMPARE(item2->mapToParent(QPointF(0, 0)), item2->pos());
2768 QCOMPARE(item3->mapToParent(QPointF(0, 0)), item3->pos());
2769 QCOMPARE(item4->mapToParent(QPointF(0, 0)), item4->pos());
2770 QCOMPARE(item1->mapToParent(QPointF(10, -10)), item1->pos() + matrix.map(QPointF(10, -10)));
2771 QCOMPARE(item2->mapToParent(QPointF(10, -10)), item2->pos() + QPointF(10, -10));
2772 QCOMPARE(item3->mapToParent(QPointF(10, -10)), item3->pos() + QPointF(10, -10));
2773 QCOMPARE(item4->mapToParent(QPointF(10, -10)), item4->pos() + QPointF(10, -10));
2774 QCOMPARE(item1->mapToParent(QPointF(-10, 10)), item1->pos() + matrix.map(QPointF(-10, 10)));
2775 QCOMPARE(item2->mapToParent(QPointF(-10, 10)), item2->pos() + QPointF(-10, 10));
2776 QCOMPARE(item3->mapToParent(QPointF(-10, 10)), item3->pos() + QPointF(-10, 10));
2777 QCOMPARE(item4->mapToParent(QPointF(-10, 10)), item4->pos() + QPointF(-10, 10));
2778 QCOMPARE(item1->mapFromParent(item1->pos()), matrix.inverted().map(QPointF(0, 0)));
2779 QCOMPARE(item2->mapFromParent(item2->pos()), QPointF(0, 0));
2780 QCOMPARE(item3->mapFromParent(item3->pos()), QPointF(0, 0));
2781 QCOMPARE(item4->mapFromParent(item4->pos()), QPointF(0, 0));
2782 QCOMPARE(item1->mapFromParent(item1->pos() + QPointF(10, -10)),
2783 matrix.inverted().map(QPointF(10, -10)));
2784 QCOMPARE(item2->mapFromParent(item2->pos() + QPointF(10, -10)), QPointF(10, -10));
2785 QCOMPARE(item3->mapFromParent(item3->pos() + QPointF(10, -10)), QPointF(10, -10));
2786 QCOMPARE(item4->mapFromParent(item4->pos() + QPointF(10, -10)), QPointF(10, -10));
2787 QCOMPARE(item1->mapFromParent(item1->pos() + QPointF(-10, 10)),
2788 matrix.inverted().map(QPointF(-10, 10)));
2789 QCOMPARE(item2->mapFromParent(item2->pos() + QPointF(-10, 10)), QPointF(-10, 10));
2790 QCOMPARE(item3->mapFromParent(item3->pos() + QPointF(-10, 10)), QPointF(-10, 10));
2791 QCOMPARE(item4->mapFromParent(item4->pos() + QPointF(-10, 10)), QPointF(-10, 10));
2797 void tst_QGraphicsItem::mapFromToScene()
2799 QGraphicsItem *item1 = new QGraphicsPathItem(QPainterPath());
2800 QGraphicsItem *item2 = new QGraphicsPathItem(QPainterPath(), item1);
2801 QGraphicsItem *item3 = new QGraphicsPathItem(QPainterPath(), item2);
2802 QGraphicsItem *item4 = new QGraphicsPathItem(QPainterPath(), item3);
2804 item1->setPos(100, 100);
2805 item2->setPos(100, 100);
2806 item3->setPos(100, 100);
2807 item4->setPos(100, 100);
2808 QCOMPARE(item1->pos(), QPointF(100, 100));
2809 QCOMPARE(item2->pos(), QPointF(100, 100));
2810 QCOMPARE(item3->pos(), QPointF(100, 100));
2811 QCOMPARE(item4->pos(), QPointF(100, 100));
2812 QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
2813 QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
2814 QCOMPARE(item3->pos(), item3->mapToParent(0, 0));
2815 QCOMPARE(item4->pos(), item4->mapToParent(0, 0));
2816 QCOMPARE(item1->mapToParent(10, 10), QPointF(110, 110));
2817 QCOMPARE(item2->mapToParent(10, 10), QPointF(110, 110));
2818 QCOMPARE(item3->mapToParent(10, 10), QPointF(110, 110));
2819 QCOMPARE(item4->mapToParent(10, 10), QPointF(110, 110));
2820 QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100));
2821 QCOMPARE(item2->mapToScene(0, 0), QPointF(200, 200));
2822 QCOMPARE(item3->mapToScene(0, 0), QPointF(300, 300));
2823 QCOMPARE(item4->mapToScene(0, 0), QPointF(400, 400));
2824 QCOMPARE(item1->mapToScene(10, 0), QPointF(110, 100));
2825 QCOMPARE(item2->mapToScene(10, 0), QPointF(210, 200));
2826 QCOMPARE(item3->mapToScene(10, 0), QPointF(310, 300));
2827 QCOMPARE(item4->mapToScene(10, 0), QPointF(410, 400));
2828 QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0));
2829 QCOMPARE(item2->mapFromScene(200, 200), QPointF(0, 0));
2830 QCOMPARE(item3->mapFromScene(300, 300), QPointF(0, 0));
2831 QCOMPARE(item4->mapFromScene(400, 400), QPointF(0, 0));
2832 QCOMPARE(item1->mapFromScene(110, 100), QPointF(10, 0));
2833 QCOMPARE(item2->mapFromScene(210, 200), QPointF(10, 0));
2834 QCOMPARE(item3->mapFromScene(310, 300), QPointF(10, 0));
2835 QCOMPARE(item4->mapFromScene(410, 400), QPointF(10, 0));
2837 // Rotate item1 90 degrees clockwise
2838 QMatrix matrix; matrix.rotate(90);
2839 item1->setMatrix(matrix);
2840 QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
2841 QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
2842 QCOMPARE(item3->pos(), item3->mapToParent(0, 0));
2843 QCOMPARE(item4->pos(), item4->mapToParent(0, 0));
2844 QCOMPARE(item1->mapToParent(10, 0), QPointF(100, 110));
2845 QCOMPARE(item2->mapToParent(10, 0), QPointF(110, 100));
2846 QCOMPARE(item3->mapToParent(10, 0), QPointF(110, 100));
2847 QCOMPARE(item4->mapToParent(10, 0), QPointF(110, 100));
2848 QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100));
2849 QCOMPARE(item2->mapToScene(0, 0), QPointF(0, 200));
2850 QCOMPARE(item3->mapToScene(0, 0), QPointF(-100, 300));
2851 QCOMPARE(item4->mapToScene(0, 0), QPointF(-200, 400));
2852 QCOMPARE(item1->mapToScene(10, 0), QPointF(100, 110));
2853 QCOMPARE(item2->mapToScene(10, 0), QPointF(0, 210));
2854 QCOMPARE(item3->mapToScene(10, 0), QPointF(-100, 310));
2855 QCOMPARE(item4->mapToScene(10, 0), QPointF(-200, 410));
2856 QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0));
2857 QCOMPARE(item2->mapFromScene(0, 200), QPointF(0, 0));
2858 QCOMPARE(item3->mapFromScene(-100, 300), QPointF(0, 0));
2859 QCOMPARE(item4->mapFromScene(-200, 400), QPointF(0, 0));
2860 QCOMPARE(item1->mapFromScene(100, 110), QPointF(10, 0));
2861 QCOMPARE(item2->mapFromScene(0, 210), QPointF(10, 0));
2862 QCOMPARE(item3->mapFromScene(-100, 310), QPointF(10, 0));
2863 QCOMPARE(item4->mapFromScene(-200, 410), QPointF(10, 0));
2865 // Rotate item2 90 degrees clockwise
2866 item2->setMatrix(matrix);
2867 QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
2868 QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
2869 QCOMPARE(item3->pos(), item3->mapToParent(0, 0));
2870 QCOMPARE(item4->pos(), item4->mapToParent(0, 0));
2871 QCOMPARE(item1->mapToParent(10, 0), QPointF(100, 110));
2872 QCOMPARE(item2->mapToParent(10, 0), QPointF(100, 110));
2873 QCOMPARE(item3->mapToParent(10, 0), QPointF(110, 100));
2874 QCOMPARE(item4->mapToParent(10, 0), QPointF(110, 100));
2875 QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100));
2876 QCOMPARE(item2->mapToScene(0, 0), QPointF(0, 200));
2877 QCOMPARE(item3->mapToScene(0, 0), QPointF(-100, 100));
2878 QCOMPARE(item4->mapToScene(0, 0), QPointF(-200, 0));
2879 QCOMPARE(item1->mapToScene(10, 0), QPointF(100, 110));
2880 QCOMPARE(item2->mapToScene(10, 0), QPointF(-10, 200));
2881 QCOMPARE(item3->mapToScene(10, 0), QPointF(-110, 100));
2882 QCOMPARE(item4->mapToScene(10, 0), QPointF(-210, 0));
2883 QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0));
2884 QCOMPARE(item2->mapFromScene(0, 200), QPointF(0, 0));
2885 QCOMPARE(item3->mapFromScene(-100, 100), QPointF(0, 0));
2886 QCOMPARE(item4->mapFromScene(-200, 0), QPointF(0, 0));
2887 QCOMPARE(item1->mapFromScene(100, 110), QPointF(10, 0));
2888 QCOMPARE(item2->mapFromScene(-10, 200), QPointF(10, 0));
2889 QCOMPARE(item3->mapFromScene(-110, 100), QPointF(10, 0));
2890 QCOMPARE(item4->mapFromScene(-210, 0), QPointF(10, 0));
2892 // Translate item3 50 points, then rotate 90 degrees counterclockwise
2894 matrix2.translate(50, 0);
2895 matrix2.rotate(-90);
2896 item3->setMatrix(matrix2);
2897 QCOMPARE(item1->pos(), item1->mapToParent(0, 0));
2898 QCOMPARE(item2->pos(), item2->mapToParent(0, 0));
2899 QCOMPARE(item3->pos(), item3->mapToParent(0, 0) - QPointF(50, 0));
2900 QCOMPARE(item4->pos(), item4->mapToParent(0, 0));
2901 QCOMPARE(item1->mapToParent(10, 0), QPointF(100, 110));
2902 QCOMPARE(item2->mapToParent(10, 0), QPointF(100, 110));
2903 QCOMPARE(item3->mapToParent(10, 0), QPointF(150, 90));
2904 QCOMPARE(item4->mapToParent(10, 0), QPointF(110, 100));
2905 QCOMPARE(item1->mapToScene(0, 0), QPointF(100, 100));
2906 QCOMPARE(item2->mapToScene(0, 0), QPointF(0, 200));
2907 QCOMPARE(item3->mapToScene(0, 0), QPointF(-150, 100));
2908 QCOMPARE(item4->mapToScene(0, 0), QPointF(-250, 200));
2909 QCOMPARE(item1->mapToScene(10, 0), QPointF(100, 110));
2910 QCOMPARE(item2->mapToScene(10, 0), QPointF(-10, 200));
2911 QCOMPARE(item3->mapToScene(10, 0), QPointF(-150, 110));
2912 QCOMPARE(item4->mapToScene(10, 0), QPointF(-250, 210));
2913 QCOMPARE(item1->mapFromScene(100, 100), QPointF(0, 0));
2914 QCOMPARE(item2->mapFromScene(0, 200), QPointF(0, 0));
2915 QCOMPARE(item3->mapFromScene(-150, 100), QPointF(0, 0));
2916 QCOMPARE(item4->mapFromScene(-250, 200), QPointF(0, 0));
2917 QCOMPARE(item1->mapFromScene(100, 110), QPointF(10, 0));
2918 QCOMPARE(item2->mapFromScene(-10, 200), QPointF(10, 0));
2919 QCOMPARE(item3->mapFromScene(-150, 110), QPointF(10, 0));
2920 QCOMPARE(item4->mapFromScene(-250, 210), QPointF(10, 0));
2925 void tst_QGraphicsItem::mapFromToItem()
2927 QGraphicsItem *item1 = new QGraphicsPathItem;
2928 QGraphicsItem *item2 = new QGraphicsPathItem;
2929 QGraphicsItem *item3 = new QGraphicsPathItem;
2930 QGraphicsItem *item4 = new QGraphicsPathItem;
2932 item1->setPos(-100, -100);
2933 item2->setPos(100, -100);
2934 item3->setPos(100, 100);
2935 item4->setPos(-100, 100);
2937 QCOMPARE(item1->mapFromItem(item2, 0, 0), QPointF(200, 0));
2938 QCOMPARE(item2->mapFromItem(item3, 0, 0), QPointF(0, 200));
2939 QCOMPARE(item3->mapFromItem(item4, 0, 0), QPointF(-200, 0));
2940 QCOMPARE(item4->mapFromItem(item1, 0, 0), QPointF(0, -200));
2941 QCOMPARE(item1->mapFromItem(item4, 0, 0), QPointF(0, 200));
2942 QCOMPARE(item2->mapFromItem(item1, 0, 0), QPointF(-200, 0));
2943 QCOMPARE(item3->mapFromItem(item2, 0, 0), QPointF(0, -200));
2944 QCOMPARE(item4->mapFromItem(item3, 0, 0), QPointF(200, 0));
2947 matrix.translate(100, 100);
2948 item1->setMatrix(matrix);
2950 QCOMPARE(item1->mapFromItem(item2, 0, 0), QPointF(100, -100));
2951 QCOMPARE(item2->mapFromItem(item3, 0, 0), QPointF(0, 200));
2952 QCOMPARE(item3->mapFromItem(item4, 0, 0), QPointF(-200, 0));
2953 QCOMPARE(item4->mapFromItem(item1, 0, 0), QPointF(100, -100));
2954 QCOMPARE(item1->mapFromItem(item4, 0, 0), QPointF(-100, 100));
2955 QCOMPARE(item2->mapFromItem(item1, 0, 0), QPointF(-100, 100));
2956 QCOMPARE(item3->mapFromItem(item2, 0, 0), QPointF(0, -200));
2957 QCOMPARE(item4->mapFromItem(item3, 0, 0), QPointF(200, 0));
2960 item1->setMatrix(matrix);
2961 item2->setMatrix(matrix);
2962 item3->setMatrix(matrix);
2963 item4->setMatrix(matrix);
2965 QCOMPARE(item1->mapFromItem(item2, 0, 0), QPointF(0, -200));
2966 QCOMPARE(item2->mapFromItem(item3, 0, 0), QPointF(200, 0));
2967 QCOMPARE(item3->mapFromItem(item4, 0, 0), QPointF(0, 200));
2968 QCOMPARE(item4->mapFromItem(item1, 0, 0), QPointF(-200, 0));
2969 QCOMPARE(item1->mapFromItem(item4, 0, 0), QPointF(200, 0));
2970 QCOMPARE(item2->mapFromItem(item1, 0, 0), QPointF(0, 200));
2971 QCOMPARE(item3->mapFromItem(item2, 0, 0), QPointF(-200, 0));
2972 QCOMPARE(item4->mapFromItem(item3, 0, 0), QPointF(0, -200));
2973 QCOMPARE(item1->mapFromItem(item2, 10, -5), QPointF(10, -205));
2974 QCOMPARE(item2->mapFromItem(item3, 10, -5), QPointF(210, -5));
2975 QCOMPARE(item3->mapFromItem(item4, 10, -5), QPointF(10, 195));
2976 QCOMPARE(item4->mapFromItem(item1, 10, -5), QPointF(-190, -5));
2977 QCOMPARE(item1->mapFromItem(item4, 10, -5), QPointF(210, -5));
2978 QCOMPARE(item2->mapFromItem(item1, 10, -5), QPointF(10, 195));
2979 QCOMPARE(item3->mapFromItem(item2, 10, -5), QPointF(-190, -5));
2980 QCOMPARE(item4->mapFromItem(item3, 10, -5), QPointF(10, -205));
2982 QCOMPARE(item1->mapFromItem(0, 10, -5), item1->mapFromScene(10, -5));
2983 QCOMPARE(item2->mapFromItem(0, 10, -5), item2->mapFromScene(10, -5));
2984 QCOMPARE(item3->mapFromItem(0, 10, -5), item3->mapFromScene(10, -5));
2985 QCOMPARE(item4->mapFromItem(0, 10, -5), item4->mapFromScene(10, -5));
2986 QCOMPARE(item1->mapToItem(0, 10, -5), item1->mapToScene(10, -5));
2987 QCOMPARE(item2->mapToItem(0, 10, -5), item2->mapToScene(10, -5));
2988 QCOMPARE(item3->mapToItem(0, 10, -5), item3->mapToScene(10, -5));
2989 QCOMPARE(item4->mapToItem(0, 10, -5), item4->mapToScene(10, -5));
2997 void tst_QGraphicsItem::mapRectFromToParent_data()
2999 QTest::addColumn<bool>("parent");
3000 QTest::addColumn<QPointF>("parentPos");
3001 QTest::addColumn<QTransform>("parentTransform");
3002 QTest::addColumn<QPointF>("pos");
3003 QTest::addColumn<QTransform>("transform");
3004 QTest::addColumn<QRectF>("inputRect");
3005 QTest::addColumn<QRectF>("outputRect");
3007 QTest::newRow("nil") << false << QPointF() << QTransform() << QPointF() << QTransform() << QRectF() << QRectF();
3008 QTest::newRow("simple") << false << QPointF() << QTransform() << QPointF() << QTransform()
3009 << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10);
3010 QTest::newRow("simple w/parent") << true
3011 << QPointF() << QTransform()
3012 << QPointF() << QTransform()
3013 << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10);
3014 QTest::newRow("simple w/parent parentPos") << true
3015 << QPointF(50, 50) << QTransform()
3016 << QPointF() << QTransform()
3017 << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10);
3018 QTest::newRow("simple w/parent parentPos parentRotation") << true
3019 << QPointF(50, 50) << QTransform().rotate(45)
3020 << QPointF() << QTransform()
3021 << QRectF(0, 0, 10, 10) << QRectF(0, 0, 10, 10);
3022 QTest::newRow("pos w/parent") << true
3023 << QPointF() << QTransform()
3024 << QPointF(50, 50) << QTransform()
3025 << QRectF(0, 0, 10, 10) << QRectF(50, 50, 10, 10);
3026 QTest::newRow("rotation w/parent") << true
3027 << QPointF() << QTransform()
3028 << QPointF() << QTransform().rotate(90)
3029 << QRectF(0, 0, 10, 10) << QRectF(-10, 0, 10, 10);
3030 QTest::newRow("pos rotation w/parent") << true
3031 << QPointF() << QTransform()
3032 << QPointF(50, 50) << QTransform().rotate(90)
3033 << QRectF(0, 0, 10, 10) << QRectF(40, 50, 10, 10);
3034 QTest::newRow("pos rotation w/parent parentPos parentRotation") << true
3035 << QPointF(-170, -190) << QTransform().rotate(90)
3036 << QPointF(50, 50) << QTransform().rotate(90)
3037 << QRectF(0, 0, 10, 10) << QRectF(40, 50, 10, 10);
3040 void tst_QGraphicsItem::mapRectFromToParent()
3042 QFETCH(bool, parent);
3043 QFETCH(QPointF, parentPos);
3044 QFETCH(QTransform, parentTransform);
3045 QFETCH(QPointF, pos);
3046 QFETCH(QTransform, transform);
3047 QFETCH(QRectF, inputRect);
3048 QFETCH(QRectF, outputRect);
3050 QGraphicsRectItem *rect = new QGraphicsRectItem;
3052 rect->setTransform(transform);
3055 QGraphicsRectItem *rectParent = new QGraphicsRectItem;
3056 rect->setParentItem(rectParent);
3057 rectParent->setPos(parentPos);
3058 rectParent->setTransform(parentTransform);
3061 // Make sure we use non-destructive transform operations (e.g., 90 degree
3063 QCOMPARE(rect->mapRectToParent(inputRect), outputRect);
3064 QCOMPARE(rect->mapRectFromParent(outputRect), inputRect);
3065 QCOMPARE(rect->itemTransform(rect->parentItem()).mapRect(inputRect), outputRect);
3066 QCOMPARE(rect->mapToParent(inputRect).boundingRect(), outputRect);
3067 QCOMPARE(rect->mapToParent(QPolygonF(inputRect)).boundingRect(), outputRect);
3068 QCOMPARE(rect->mapFromParent(outputRect).boundingRect(), inputRect);
3069 QCOMPARE(rect->mapFromParent(QPolygonF(outputRect)).boundingRect(), inputRect);
3070 QPainterPath inputPath;
3071 inputPath.addRect(inputRect);
3072 QPainterPath outputPath;
3073 outputPath.addRect(outputRect);
3074 QCOMPARE(rect->mapToParent(inputPath).boundingRect(), outputPath.boundingRect());
3075 QCOMPARE(rect->mapFromParent(outputPath).boundingRect(), inputPath.boundingRect());
3078 void tst_QGraphicsItem::isAncestorOf()
3080 QGraphicsItem *grandPa = new QGraphicsRectItem;
3081 QGraphicsItem *parent = new QGraphicsRectItem;
3082 QGraphicsItem *child = new QGraphicsRectItem;
3084 QVERIFY(!parent->isAncestorOf(0));
3085 QVERIFY(!child->isAncestorOf(0));
3086 QVERIFY(!parent->isAncestorOf(child));
3087 QVERIFY(!child->isAncestorOf(parent));
3088 QVERIFY(!parent->isAncestorOf(parent));
3090 child->setParentItem(parent);
3091 parent->setParentItem(grandPa);
3093 QVERIFY(parent->isAncestorOf(child));
3094 QVERIFY(grandPa->isAncestorOf(parent));
3095 QVERIFY(grandPa->isAncestorOf(child));
3096 QVERIFY(!child->isAncestorOf(parent));
3097 QVERIFY(!parent->isAncestorOf(grandPa));
3098 QVERIFY(!child->isAncestorOf(grandPa));
3099 QVERIFY(!child->isAncestorOf(child));
3100 QVERIFY(!parent->isAncestorOf(parent));
3101 QVERIFY(!grandPa->isAncestorOf(grandPa));
3103 parent->setParentItem(0);
3110 void tst_QGraphicsItem::commonAncestorItem()
3112 QGraphicsItem *ancestor = new QGraphicsRectItem;
3113 QGraphicsItem *grandMa = new QGraphicsRectItem;
3114 QGraphicsItem *grandPa = new QGraphicsRectItem;
3115 QGraphicsItem *brotherInLaw = new QGraphicsRectItem;
3116 QGraphicsItem *cousin = new QGraphicsRectItem;
3117 QGraphicsItem *husband = new QGraphicsRectItem;
3118 QGraphicsItem *child = new QGraphicsRectItem;
3119 QGraphicsItem *wife = new QGraphicsRectItem;
3121 child->setParentItem(husband);
3122 husband->setParentItem(grandPa);
3123 brotherInLaw->setParentItem(grandPa);
3124 cousin->setParentItem(brotherInLaw);
3125 wife->setParentItem(grandMa);
3126 grandMa->setParentItem(ancestor);
3127 grandPa->setParentItem(ancestor);
3129 QCOMPARE(grandMa->commonAncestorItem(grandMa), grandMa);
3130 QCOMPARE(grandMa->commonAncestorItem(0), (QGraphicsItem *)0);
3131 QCOMPARE(grandMa->commonAncestorItem(grandPa), ancestor);
3132 QCOMPARE(grandPa->commonAncestorItem(grandMa), ancestor);
3133 QCOMPARE(grandPa->commonAncestorItem(husband), grandPa);
3134 QCOMPARE(grandPa->commonAncestorItem(wife), ancestor);
3135 QCOMPARE(grandMa->commonAncestorItem(husband), ancestor);
3136 QCOMPARE(grandMa->commonAncestorItem(wife), grandMa);
3137 QCOMPARE(wife->commonAncestorItem(grandMa), grandMa);
3138 QCOMPARE(child->commonAncestorItem(cousin), grandPa);
3139 QCOMPARE(cousin->commonAncestorItem(child), grandPa);
3140 QCOMPARE(wife->commonAncestorItem(child), ancestor);
3141 QCOMPARE(child->commonAncestorItem(wife), ancestor);
3144 void tst_QGraphicsItem::data()
3146 QGraphicsTextItem text;
3148 QCOMPARE(text.data(0), QVariant());
3149 text.setData(0, "TextItem");
3150 QCOMPARE(text.data(0), QVariant(QString("TextItem")));
3151 text.setData(0, QVariant());
3152 QCOMPARE(text.data(0), QVariant());
3155 void tst_QGraphicsItem::type()
3157 QCOMPARE(int(QGraphicsItem::Type), 1);
3158 QCOMPARE(int(QGraphicsPathItem::Type), 2);
3159 QCOMPARE(int(QGraphicsRectItem::Type), 3);
3160 QCOMPARE(int(QGraphicsEllipseItem::Type), 4);
3161 QCOMPARE(int(QGraphicsPolygonItem::Type), 5);
3162 QCOMPARE(int(QGraphicsLineItem::Type), 6);
3163 QCOMPARE(int(QGraphicsPixmapItem::Type), 7);
3164 QCOMPARE(int(QGraphicsTextItem::Type), 8);
3166 QCOMPARE(QGraphicsPathItem().type(), 2);
3167 QCOMPARE(QGraphicsRectItem().type(), 3);
3168 QCOMPARE(QGraphicsEllipseItem().type(), 4);
3169 QCOMPARE(QGraphicsPolygonItem().type(), 5);
3170 QCOMPARE(QGraphicsLineItem().type(), 6);
3171 QCOMPARE(QGraphicsPixmapItem().type(), 7);
3172 QCOMPARE(QGraphicsTextItem().type(), 8);
3175 void tst_QGraphicsItem::graphicsitem_cast()
3177 QGraphicsPathItem pathItem;
3178 const QGraphicsPathItem *pPathItem = &pathItem;
3179 QGraphicsRectItem rectItem;
3180 const QGraphicsRectItem *pRectItem = &rectItem;
3181 QGraphicsEllipseItem ellipseItem;
3182 const QGraphicsEllipseItem *pEllipseItem = &ellipseItem;
3183 QGraphicsPolygonItem polygonItem;
3184 const QGraphicsPolygonItem *pPolygonItem = &polygonItem;
3185 QGraphicsLineItem lineItem;
3186 const QGraphicsLineItem *pLineItem = &lineItem;
3187 QGraphicsPixmapItem pixmapItem;
3188 const QGraphicsPixmapItem *pPixmapItem = &pixmapItem;
3189 QGraphicsTextItem textItem;
3190 const QGraphicsTextItem *pTextItem = &textItem;
3192 QVERIFY(qgraphicsitem_cast<QGraphicsPathItem *>(&pathItem));
3193 //QVERIFY(qgraphicsitem_cast<QAbstractGraphicsPathItem *>(&pathItem));
3194 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&pathItem));
3195 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pPathItem));
3196 QVERIFY(qgraphicsitem_cast<const QGraphicsPathItem *>(pPathItem));
3198 QVERIFY(qgraphicsitem_cast<QGraphicsRectItem *>(&rectItem));
3199 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&rectItem));
3200 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pRectItem));
3201 QVERIFY(qgraphicsitem_cast<const QGraphicsRectItem *>(pRectItem));
3203 QVERIFY(qgraphicsitem_cast<QGraphicsEllipseItem *>(&ellipseItem));
3204 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&ellipseItem));
3205 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pEllipseItem));
3206 QVERIFY(qgraphicsitem_cast<const QGraphicsEllipseItem *>(pEllipseItem));
3208 QVERIFY(qgraphicsitem_cast<QGraphicsPolygonItem *>(&polygonItem));
3209 //QVERIFY(qgraphicsitem_cast<QAbstractGraphicsPathItem *>(&polygonItem));
3210 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&polygonItem));
3211 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pPolygonItem));
3212 QVERIFY(qgraphicsitem_cast<const QGraphicsPolygonItem *>(pPolygonItem));
3214 QVERIFY(qgraphicsitem_cast<QGraphicsLineItem *>(&lineItem));
3215 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&lineItem));
3216 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pLineItem));
3217 QVERIFY(qgraphicsitem_cast<const QGraphicsLineItem *>(pLineItem));
3219 QVERIFY(qgraphicsitem_cast<QGraphicsPixmapItem *>(&pixmapItem));
3220 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&pixmapItem));
3221 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pPixmapItem));
3222 QVERIFY(qgraphicsitem_cast<const QGraphicsPixmapItem *>(pPixmapItem));
3224 QVERIFY(qgraphicsitem_cast<QGraphicsTextItem *>(&textItem));
3225 QVERIFY(qgraphicsitem_cast<QGraphicsItem *>(&textItem));
3226 QVERIFY(qgraphicsitem_cast<const QGraphicsItem *>(pTextItem));
3227 QVERIFY(qgraphicsitem_cast<const QGraphicsTextItem *>(pTextItem));
3229 // and some casts that _should_ fail:
3230 QVERIFY(!qgraphicsitem_cast<QGraphicsEllipseItem *>(&pathItem));
3231 QVERIFY(!qgraphicsitem_cast<const QGraphicsTextItem *>(pPolygonItem));
3233 // and this shouldn't crash
3234 QGraphicsItem *ptr = 0;
3235 QVERIFY(!qgraphicsitem_cast<QGraphicsTextItem *>(ptr));
3236 QVERIFY(!qgraphicsitem_cast<QGraphicsItem *>(ptr));
3239 void tst_QGraphicsItem::hoverEventsGenerateRepaints()
3243 QGraphicsScene scene;
3244 QGraphicsView view(&scene);
3246 QTest::qWaitForWindowShown(&view);
3249 EventTester *tester = new EventTester;
3250 scene.addItem(tester);
3251 tester->setAcceptsHoverEvents(true);
3253 QTRY_COMPARE(tester->repaints, 1);
3255 // Send a hover enter event
3256 QGraphicsSceneHoverEvent hoverEnterEvent(QEvent::GraphicsSceneHoverEnter);
3257 hoverEnterEvent.setScenePos(QPointF(0, 0));
3258 hoverEnterEvent.setPos(QPointF(0, 0));
3259 QApplication::sendEvent(&scene, &hoverEnterEvent);
3261 // Check that we get a repaint
3262 int npaints = tester->repaints;
3263 qApp->processEvents();
3264 qApp->processEvents();
3265 QCOMPARE(tester->events.size(), 2); // enter + move
3266 QCOMPARE(tester->repaints, npaints + 1);
3267 QCOMPARE(tester->events.last(), QEvent::GraphicsSceneHoverMove);
3269 // Send a hover move event
3270 QGraphicsSceneHoverEvent hoverMoveEvent(QEvent::GraphicsSceneHoverMove);
3271 hoverMoveEvent.setScenePos(QPointF(0, 0));
3272 hoverMoveEvent.setPos(QPointF(0, 0));
3273 QApplication::sendEvent(&scene, &hoverMoveEvent);
3275 // Check that we don't get a repaint
3276 qApp->processEvents();
3277 qApp->processEvents();
3279 QCOMPARE(tester->events.size(), 3);
3280 QCOMPARE(tester->repaints, npaints + 1);
3281 QCOMPARE(tester->events.last(), QEvent::GraphicsSceneHoverMove);
3283 // Send a hover leave event
3284 QGraphicsSceneHoverEvent hoverLeaveEvent(QEvent::GraphicsSceneHoverLeave);
3285 hoverLeaveEvent.setScenePos(QPointF(-100, -100));
3286 hoverLeaveEvent.setPos(QPointF(0, 0));
3287 QApplication::sendEvent(&scene, &hoverLeaveEvent);
3289 // Check that we get a repaint
3290 qApp->processEvents();
3291 qApp->processEvents();
3293 QCOMPARE(tester->events.size(), 4);
3294 QCOMPARE(tester->repaints, npaints + 2);
3295 QCOMPARE(tester->events.last(), QEvent::GraphicsSceneHoverLeave);
3298 void tst_QGraphicsItem::boundingRects_data()
3300 QTest::addColumn<QGraphicsItem *>("item");
3301 QTest::addColumn<QRectF>("boundingRect");
3303 QRectF rect(0, 0, 100, 100);
3307 QRectF adjustedRect(-0.5, -0.5, 101, 101);
3309 QTest::newRow("path") << (QGraphicsItem *)new QGraphicsPathItem(path) << adjustedRect;
3310 QTest::newRow("rect") << (QGraphicsItem *)new QGraphicsRectItem(rect) << adjustedRect;
3311 QTest::newRow("ellipse") << (QGraphicsItem *)new QGraphicsEllipseItem(rect) << adjustedRect;
3312 QTest::newRow("polygon") << (QGraphicsItem *)new QGraphicsPolygonItem(rect) << adjustedRect;
3315 void tst_QGraphicsItem::boundingRects()
3317 QFETCH(QGraphicsItem *, item);
3318 QFETCH(QRectF, boundingRect);
3320 ((QAbstractGraphicsShapeItem *)item)->setPen(QPen(Qt::black, 1));
3321 QCOMPARE(item->boundingRect(), boundingRect);
3324 void tst_QGraphicsItem::boundingRects2()
3326 QGraphicsPixmapItem pixmap(QPixmap::fromImage(QImage(100, 100, QImage::Format_ARGB32_Premultiplied)));
3327 QCOMPARE(pixmap.boundingRect(), QRectF(0, 0, 100, 100));
3329 QGraphicsLineItem line(0, 0, 100, 0);
3330 line.setPen(QPen(Qt::black, 1));
3331 QCOMPARE(line.boundingRect(), QRectF(-0.5, -0.5, 101, 1));
3334 void tst_QGraphicsItem::sceneBoundingRect()
3336 QGraphicsScene scene;
3337 QGraphicsRectItem *item = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
3338 item->setPos(100, 100);
3340 QCOMPARE(item->boundingRect(), QRectF(0, 0, 100, 100));
3341 QCOMPARE(item->sceneBoundingRect(), QRectF(100, 100, 100, 100));
3345 QCOMPARE(item->boundingRect(), QRectF(0, 0, 100, 100));
3346 QCOMPARE(item->sceneBoundingRect(), QRectF(0, 100, 100, 100));
3349 void tst_QGraphicsItem::childrenBoundingRect()
3351 QGraphicsScene scene;
3352 QGraphicsRectItem *parent = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
3353 QGraphicsRectItem *child = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
3354 child->setParentItem(parent);
3355 parent->setPos(100, 100);
3356 child->setPos(100, 100);
3358 QCOMPARE(parent->boundingRect(), QRectF(0, 0, 100, 100));
3359 QCOMPARE(child->boundingRect(), QRectF(0, 0, 100, 100));
3360 QCOMPARE(child->childrenBoundingRect(), QRectF());
3361 QCOMPARE(parent->childrenBoundingRect(), QRectF(100, 100, 100, 100));
3363 QGraphicsRectItem *child2 = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
3364 child2->setParentItem(parent);
3365 child2->setPos(-100, -100);
3366 QCOMPARE(parent->childrenBoundingRect(), QRectF(-100, -100, 300, 300));
3368 QGraphicsRectItem *childChild = scene.addRect(QRectF(0, 0, 100, 100), QPen(Qt::black, 0));
3369 childChild->setParentItem(child);
3370 childChild->setPos(500, 500);
3373 scene.addPolygon(parent->mapToScene(parent->boundingRect() | parent->childrenBoundingRect()))->setPen(QPen(Qt::red));;
3375 QGraphicsView view(&scene);
3378 QTest::qWaitForWindowShown(&view);
3381 QCOMPARE(parent->childrenBoundingRect(), QRectF(-500, -100, 600, 800));
3384 void tst_QGraphicsItem::childrenBoundingRectTransformed()
3386 QGraphicsScene scene;
3388 QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100));
3389 QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 100, 100));
3390 QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 100, 100));
3391 QGraphicsRectItem *rect4 = scene.addRect(QRectF(0, 0, 100, 100));
3392 QGraphicsRectItem *rect5 = scene.addRect(QRectF(0, 0, 100, 100));
3393 rect2->setParentItem(rect);
3394 rect3->setParentItem(rect2);
3395 rect4->setParentItem(rect3);
3396 rect5->setParentItem(rect4);
3398 rect2->setTransform(QTransform().translate(50, 50).rotate(45));
3399 rect2->setPos(25, 25);
3400 rect3->setTransform(QTransform().translate(50, 50).rotate(45));
3401 rect3->setPos(25, 25);
3402 rect4->setTransform(QTransform().translate(50, 50).rotate(45));
3403 rect4->setPos(25, 25);
3404 rect5->setTransform(QTransform().translate(50, 50).rotate(45));
3405 rect5->setPos(25, 25);
3407 QRectF subTreeRect = rect->childrenBoundingRect();
3408 QCOMPARE(subTreeRect.left(), qreal(-206.0660171779821));
3409 QCOMPARE(subTreeRect.top(), qreal(75.0));
3410 QCOMPARE(subTreeRect.width(), qreal(351.7766952966369));
3411 QCOMPARE(subTreeRect.height(), qreal(251.7766952966369));
3419 subTreeRect = rect->childrenBoundingRect();
3420 QCOMPARE(rect->childrenBoundingRect(), QRectF(-100, 75, 275, 250));
3423 void tst_QGraphicsItem::childrenBoundingRect2()
3425 QGraphicsItemGroup box;
3426 QGraphicsLineItem l1(0, 0, 100, 0, &box);
3427 QGraphicsLineItem l2(100, 0, 100, 100, &box);
3428 QGraphicsLineItem l3(0, 0, 0, 100, &box);
3429 // Make sure lines (zero with/height) are included in the childrenBoundingRect.
3430 QCOMPARE(box.childrenBoundingRect(), QRectF(0, 0, 100, 100));
3433 void tst_QGraphicsItem::childrenBoundingRect3()
3435 QGraphicsScene scene;
3437 QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100));
3438 QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 100, 100));
3439 QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 100, 100));
3440 QGraphicsRectItem *rect4 = scene.addRect(QRectF(0, 0, 100, 100));
3441 QGraphicsRectItem *rect5 = scene.addRect(QRectF(0, 0, 100, 100));
3442 rect2->setParentItem(rect);
3443 rect3->setParentItem(rect2);
3444 rect4->setParentItem(rect3);
3445 rect5->setParentItem(rect4);
3447 rect2->setTransform(QTransform().translate(50, 50).rotate(45));
3448 rect2->setPos(25, 25);
3449 rect3->setTransform(QTransform().translate(50, 50).rotate(45));
3450 rect3->setPos(25, 25);
3451 rect4->setTransform(QTransform().translate(50, 50).rotate(45));
3452 rect4->setPos(25, 25);
3453 rect5->setTransform(QTransform().translate(50, 50).rotate(45));
3454 rect5->setPos(25, 25);
3456 // Try to mess up the cached bounding rect.
3457 (void)rect2->childrenBoundingRect();
3459 QRectF subTreeRect = rect->childrenBoundingRect();
3460 QCOMPARE(subTreeRect.left(), qreal(-206.0660171779821));
3461 QCOMPARE(subTreeRect.top(), qreal(75.0));
3462 QCOMPARE(subTreeRect.width(), qreal(351.7766952966369));
3463 QCOMPARE(subTreeRect.height(), qreal(251.7766952966369));
3466 void tst_QGraphicsItem::childrenBoundingRect4()
3468 QGraphicsScene scene;
3470 QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 10, 10));
3471 QGraphicsRectItem *rect2 = scene.addRect(QRectF(0, 0, 20, 20));
3472 QGraphicsRectItem *rect3 = scene.addRect(QRectF(0, 0, 30, 30));
3473 rect2->setParentItem(rect);
3474 rect3->setParentItem(rect);
3476 QGraphicsView view(&scene);
3479 QTest::qWaitForWindowShown(&view);
3481 // Try to mess up the cached bounding rect.
3482 rect->childrenBoundingRect();
3483 rect2->childrenBoundingRect();
3485 rect3->setOpacity(0.0);
3486 rect3->setParentItem(rect2);
3488 QCOMPARE(rect->childrenBoundingRect(), rect3->boundingRect());
3489 QCOMPARE(rect2->childrenBoundingRect(), rect3->boundingRect());
3492 void tst_QGraphicsItem::childrenBoundingRect5()
3494 QGraphicsScene scene;
3496 QGraphicsRectItem *parent = scene.addRect(QRectF(0, 0, 100, 100));
3497 QGraphicsRectItem *child = scene.addRect(QRectF(0, 0, 100, 100));
3498 child->setParentItem(parent);
3500 QGraphicsView view(&scene);
3503 QTest::qWaitForWindowShown(&view);
3505 // Try to mess up the cached bounding rect.
3506 QRectF expectedChildrenBoundingRect = parent->boundingRect();
3507 QCOMPARE(parent->childrenBoundingRect(), expectedChildrenBoundingRect);
3509 // Apply some effects.
3510 QGraphicsDropShadowEffect *dropShadow = new QGraphicsDropShadowEffect;
3511 dropShadow->setOffset(25, 25);
3512 child->setGraphicsEffect(dropShadow);
3513 parent->setGraphicsEffect(new QGraphicsOpacityEffect);
3515 QVERIFY(parent->childrenBoundingRect() != expectedChildrenBoundingRect);
3516 expectedChildrenBoundingRect |= dropShadow->boundingRect();
3517 QCOMPARE(parent->childrenBoundingRect(), expectedChildrenBoundingRect);
3520 void tst_QGraphicsItem::group()
3522 QGraphicsScene scene;
3523 QGraphicsRectItem *parent = scene.addRect(QRectF(0, 0, 50, 50), QPen(Qt::black, 0), QBrush(Qt::green));
3524 QGraphicsRectItem *child = scene.addRect(QRectF(0, 0, 50, 50), QPen(Qt::black, 0), QBrush(Qt::blue));
3525 QGraphicsRectItem *parent2 = scene.addRect(QRectF(0, 0, 50, 50), QPen(Qt::black, 0), QBrush(Qt::red));
3526 parent2->setPos(-50, 50);
3528 child->setParentItem(parent);
3529 parent->setPos(25, 25);
3530 child->setPos(25, 25);
3532 QCOMPARE(parent->group(), (QGraphicsItemGroup *)0);
3533 QCOMPARE(parent2->group(), (QGraphicsItemGroup *)0);
3534 QCOMPARE(child->group(), (QGraphicsItemGroup *)0);
3536 QGraphicsView view(&scene);
3538 QTest::qWaitForWindowShown(&view);
3539 QApplication::processEvents();
3541 QGraphicsItemGroup *group = new QGraphicsItemGroup;
3542 group->setSelected(true);
3543 scene.addItem(group);
3545 QRectF parentSceneBoundingRect = parent->sceneBoundingRect();
3546 group->addToGroup(parent);
3547 QCOMPARE(parent->group(), group);
3548 QCOMPARE(parent->sceneBoundingRect(), parentSceneBoundingRect);
3550 QCOMPARE(parent->parentItem(), (QGraphicsItem *)group);
3551 QCOMPARE(group->children().size(), 1);
3552 QCOMPARE(scene.items().size(), 4);
3553 QCOMPARE(scene.items(group->sceneBoundingRect()).size(), 3);
3557 QRectF parent2SceneBoundingRect = parent2->sceneBoundingRect();
3558 group->addToGroup(parent2);
3559 QCOMPARE(parent2->group(), group);
3560 QCOMPARE(parent2->sceneBoundingRect(), parent2SceneBoundingRect);
3562 QCOMPARE(parent2->parentItem(), (QGraphicsItem *)group);
3563 QCOMPARE(group->children().size(), 2);
3564 QCOMPARE(scene.items().size(), 4);
3565 QCOMPARE(scene.items(group->sceneBoundingRect()).size(), 4);
3569 QList<QGraphicsItem *> newItems;
3570 for (int i = 0; i < 100; ++i) {
3571 QGraphicsItem *item = scene.addRect(QRectF(-25, -25, 50, 50), QPen(Qt::black, 0),
3572 QBrush(QColor(rand() % 255, rand() % 255,
3573 rand() % 255, rand() % 255)));
3575 item->setPos(-1000 + rand() % 2000,
3576 -1000 + rand() % 2000);
3577 item->rotate(rand() % 90);
3580 view.fitInView(scene.itemsBoundingRect());
3583 foreach (QGraphicsItem *item, newItems) {
3584 group->addToGroup(item);
3585 QCOMPARE(item->group(), group);
3586 if ((n++ % 100) == 0)
3591 void tst_QGraphicsItem::setGroup()
3593 QGraphicsItemGroup group1;
3594 QGraphicsItemGroup group2;
3596 QGraphicsRectItem *rect = new QGraphicsRectItem;
3597 QCOMPARE(rect->group(), (QGraphicsItemGroup *)0);
3598 QCOMPARE(rect->parentItem(), (QGraphicsItem *)0);
3599 rect->setGroup(&group1);
3600 QCOMPARE(rect->group(), &group1);
3601 QCOMPARE(rect->parentItem(), (QGraphicsItem *)&group1);
3602 rect->setGroup(&group2);
3603 QCOMPARE(rect->group(), &group2);
3604 QCOMPARE(rect->parentItem(), (QGraphicsItem *)&group2);
3606 QCOMPARE(rect->group(), (QGraphicsItemGroup *)0);
3607 QCOMPARE(rect->parentItem(), (QGraphicsItem *)0);
3610 void tst_QGraphicsItem::setGroup2()
3612 QGraphicsScene scene;
3613 QGraphicsItemGroup group;
3614 scene.addItem(&group);
3616 QGraphicsRectItem *rect = scene.addRect(50,50,50,50,Qt::NoPen,Qt::black);
3617 rect->setTransformOriginPoint(50,50);
3618 rect->setRotation(45);
3619 rect->setScale(1.5);
3620 rect->translate(20,20);
3621 group.translate(-30,-40);
3622 group.setRotation(180);
3623 group.setScale(0.5);
3625 QTransform oldSceneTransform = rect->sceneTransform();
3626 rect->setGroup(&group);
3627 QCOMPARE(rect->sceneTransform(), oldSceneTransform);
3629 group.setRotation(20);
3631 rect->setRotation(90);
3632 rect->setScale(0.8);
3634 oldSceneTransform = rect->sceneTransform();
3636 QCOMPARE(rect->sceneTransform(), oldSceneTransform);
3639 void tst_QGraphicsItem::nestedGroups()
3641 QGraphicsItemGroup *group1 = new QGraphicsItemGroup;
3642 QGraphicsItemGroup *group2 = new QGraphicsItemGroup;
3644 QGraphicsRectItem *rect = new QGraphicsRectItem;
3645 QGraphicsRectItem *rect2 = new QGraphicsRectItem;
3646 rect2->setParentItem(rect);
3648 group1->addToGroup(rect);
3649 QCOMPARE(rect->group(), group1);
3650 QCOMPARE(rect2->group(), group1);
3652 group2->addToGroup(group1);
3653 QCOMPARE(rect->group(), group1);
3654 QCOMPARE(rect2->group(), group1);
3655 QCOMPARE(group1->group(), group2);
3656 QCOMPARE(group2->group(), (QGraphicsItemGroup *)0);
3658 QGraphicsScene scene;
3659 scene.addItem(group1);
3661 QCOMPARE(rect->group(), group1);
3662 QCOMPARE(rect2->group(), group1);
3663 QCOMPARE(group1->group(), (QGraphicsItemGroup *)0);
3664 QVERIFY(group2->children().isEmpty());
3669 void tst_QGraphicsItem::warpChildrenIntoGroup()
3671 QGraphicsScene scene;
3672 QGraphicsRectItem *parentRectItem = scene.addRect(QRectF(0, 0, 100, 100));
3673 QGraphicsRectItem *childRectItem = scene.addRect(QRectF(0, 0, 100, 100));
3674 parentRectItem->rotate(90);
3675 childRectItem->setPos(-50, -25);
3676 childRectItem->setParentItem(parentRectItem);
3678 QCOMPARE(childRectItem->mapToScene(50, 0), QPointF(25, 0));
3679 QCOMPARE(childRectItem->scenePos(), QPointF(25, -50));
3681 QGraphicsRectItem *parentOfGroup = scene.addRect(QRectF(0, 0, 100, 100));
3682 parentOfGroup->setPos(-200, -200);
3683 parentOfGroup->scale(2, 2);
3685 QGraphicsItemGroup *group = new QGraphicsItemGroup;
3686 group->setPos(50, 50);
3687 group->setParentItem(parentOfGroup);
3689 QCOMPARE(group->scenePos(), QPointF(-100, -100));
3691 group->addToGroup(childRectItem);
3693 QCOMPARE(childRectItem->mapToScene(50, 0), QPointF(25, 0));
3694 QCOMPARE(childRectItem->scenePos(), QPointF(25, -50));
3697 void tst_QGraphicsItem::removeFromGroup()
3699 QGraphicsScene scene;
3700 QGraphicsRectItem *rect1 = scene.addRect(QRectF(-100, -100, 200, 200));
3701 QGraphicsRectItem *rect2 = scene.addRect(QRectF(100, 100, 200, 200));
3702 rect1->setFlag(QGraphicsItem::ItemIsSelectable);
3703 rect2->setFlag(QGraphicsItem::ItemIsSelectable);
3704 rect1->setSelected(true);
3705 rect2->setSelected(true);
3707 QGraphicsView view(&scene);
3710 qApp->processEvents(); // index items
3711 qApp->processEvents(); // emit changed
3713 QGraphicsItemGroup *group = scene.createItemGroup(scene.selectedItems());
3715 QCOMPARE(group->children().size(), 2);
3716 qApp->processEvents(); // index items
3717 qApp->processEvents(); // emit changed
3719 scene.destroyItemGroup(group); // calls removeFromGroup.
3721 qApp->processEvents(); // index items
3722 qApp->processEvents(); // emit changed
3724 QCOMPARE(scene.items().size(), 2);
3725 QVERIFY(!rect1->group());
3726 QVERIFY(!rect2->group());
3729 class ChildEventTester : public QGraphicsRectItem
3732 ChildEventTester(const QRectF &rect, QGraphicsItem *parent = 0)
3733 : QGraphicsRectItem(rect, parent), counter(0)
3739 void focusInEvent(QFocusEvent *event)
3740 { ++counter; QGraphicsRectItem::focusInEvent(event); }
3741 void mousePressEvent(QGraphicsSceneMouseEvent *)
3743 void mouseMoveEvent(QGraphicsSceneMouseEvent *)
3745 void mouseReleaseEvent(QGraphicsSceneMouseEvent *)
3749 void tst_QGraphicsItem::handlesChildEvents()
3751 ChildEventTester *blue = new ChildEventTester(QRectF(0, 0, 100, 100));
3752 ChildEventTester *red = new ChildEventTester(QRectF(0, 0, 50, 50));
3753 ChildEventTester *green = new ChildEventTester(QRectF(0, 0, 25, 25));
3754 ChildEventTester *gray = new ChildEventTester(QRectF(0, 0, 25, 25));
3755 ChildEventTester *yellow = new ChildEventTester(QRectF(0, 0, 50, 50));
3757 blue->setBrush(QBrush(Qt::blue));
3758 red->setBrush(QBrush(Qt::red));
3759 yellow->setBrush(QBrush(Qt::yellow));
3760 green->setBrush(QBrush(Qt::green));
3761 gray->setBrush(QBrush(Qt::gray));
3763 yellow->setPos(50, 50);
3764 green->setPos(25, 0);
3765 gray->setPos(25, 25);
3766 red->setParentItem(blue);
3767 yellow->setParentItem(blue);
3768 green->setParentItem(red);
3769 gray->setParentItem(red);
3771 QGraphicsScene scene;
3772 scene.addItem(blue);
3774 QGraphicsView view(&scene);
3776 QTest::qWaitForWindowShown(&view);
3779 // Pull out the items, closest item first
3780 QList<QGraphicsItem *> items = scene.items(scene.itemsBoundingRect());
3781 QCOMPARE(items.at(0), (QGraphicsItem *)yellow);
3782 QCOMPARE(items.at(1), (QGraphicsItem *)gray);
3783 QCOMPARE(items.at(2), (QGraphicsItem *)green);
3784 QCOMPARE(items.at(3), (QGraphicsItem *)red);
3785 QCOMPARE(items.at(4), (QGraphicsItem *)blue);
3787 QCOMPARE(blue->counter, 0);
3789 // Send events to the toplevel item
3790 QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
3791 QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
3793 pressEvent.setButton(Qt::LeftButton);
3794 pressEvent.setScenePos(blue->mapToScene(5, 5));
3795 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3796 releaseEvent.setButton(Qt::LeftButton);
3797 releaseEvent.setScenePos(blue->mapToScene(5, 5));
3798 releaseEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3799 QApplication::sendEvent(&scene, &pressEvent);
3800 QApplication::sendEvent(&scene, &releaseEvent);
3802 QCOMPARE(blue->counter, 2);
3804 // Send events to a level1 item
3805 pressEvent.setScenePos(red->mapToScene(5, 5));
3806 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3807 releaseEvent.setScenePos(red->mapToScene(5, 5));
3808 releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
3809 QApplication::sendEvent(&scene, &pressEvent);
3810 QApplication::sendEvent(&scene, &releaseEvent);
3812 QCOMPARE(blue->counter, 2);
3813 QCOMPARE(red->counter, 2);
3815 // Send events to a level2 item
3816 pressEvent.setScenePos(green->mapToScene(5, 5));
3817 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3818 releaseEvent.setScenePos(green->mapToScene(5, 5));
3819 releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
3820 QApplication::sendEvent(&scene, &pressEvent);
3821 QApplication::sendEvent(&scene, &releaseEvent);
3823 QCOMPARE(blue->counter, 2);
3824 QCOMPARE(red->counter, 2);
3825 QCOMPARE(green->counter, 2);
3827 blue->setHandlesChildEvents(true);
3829 // Send events to a level1 item
3830 pressEvent.setScenePos(red->mapToScene(5, 5));
3831 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3832 releaseEvent.setScenePos(red->mapToScene(5, 5));
3833 releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
3834 QApplication::sendEvent(&scene, &pressEvent);
3835 QApplication::sendEvent(&scene, &releaseEvent);
3837 QCOMPARE(blue->counter, 4);
3838 QCOMPARE(red->counter, 2);
3840 // Send events to a level2 item
3841 pressEvent.setScenePos(green->mapToScene(5, 5));
3842 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3843 releaseEvent.setScenePos(green->mapToScene(5, 5));
3844 releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
3845 QApplication::sendEvent(&scene, &pressEvent);
3846 QApplication::sendEvent(&scene, &releaseEvent);
3848 QCOMPARE(blue->counter, 6);
3849 QCOMPARE(red->counter, 2);
3850 QCOMPARE(green->counter, 2);
3852 blue->setHandlesChildEvents(false);
3854 // Send events to a level1 item
3855 pressEvent.setScenePos(red->mapToScene(5, 5));
3856 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3857 releaseEvent.setScenePos(red->mapToScene(5, 5));
3858 releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
3859 QApplication::sendEvent(&scene, &pressEvent);
3860 QApplication::sendEvent(&scene, &releaseEvent);
3862 QCOMPARE(blue->counter, 6);
3863 QCOMPARE(red->counter, 4);
3865 // Send events to a level2 item
3866 pressEvent.setScenePos(green->mapToScene(5, 5));
3867 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3868 releaseEvent.setScenePos(green->mapToScene(5, 5));
3869 releaseEvent.setScreenPos(view.mapFromScene(releaseEvent.scenePos()));
3870 QApplication::sendEvent(&scene, &pressEvent);
3871 QApplication::sendEvent(&scene, &releaseEvent);
3873 QCOMPARE(blue->counter, 6);
3874 QCOMPARE(red->counter, 4);
3875 QCOMPARE(green->counter, 4);
3878 void tst_QGraphicsItem::handlesChildEvents2()
3880 ChildEventTester *root = new ChildEventTester(QRectF(0, 0, 10, 10));
3881 root->setHandlesChildEvents(true);
3882 QVERIFY(root->handlesChildEvents());
3884 ChildEventTester *child = new ChildEventTester(QRectF(0, 0, 10, 10), root);
3885 QVERIFY(!child->handlesChildEvents());
3887 ChildEventTester *child2 = new ChildEventTester(QRectF(0, 0, 10, 10));
3888 ChildEventTester *child3 = new ChildEventTester(QRectF(0, 0, 10, 10), child2);
3889 ChildEventTester *child4 = new ChildEventTester(QRectF(0, 0, 10, 10), child3);
3890 child2->setParentItem(root);
3891 QVERIFY(!child2->handlesChildEvents());
3892 QVERIFY(!child3->handlesChildEvents());
3893 QVERIFY(!child4->handlesChildEvents());
3895 QGraphicsScene scene;
3896 scene.addItem(root);
3898 QGraphicsView view(&scene);
3900 QTest::qWaitForWindowShown(&view);
3901 QApplication::processEvents();
3903 QMouseEvent event(QEvent::MouseButtonPress, view.mapFromScene(5, 5),
3904 view.viewport()->mapToGlobal(view.mapFromScene(5, 5)), Qt::LeftButton, 0, 0);
3905 QApplication::sendEvent(view.viewport(), &event);
3907 QTRY_COMPARE(root->counter, 1);
3910 void tst_QGraphicsItem::handlesChildEvents3()
3912 QGraphicsScene scene;
3913 QEvent activate(QEvent::WindowActivate);
3914 QApplication::sendEvent(&scene, &activate);
3916 ChildEventTester *group2 = new ChildEventTester(QRectF(), 0);
3917 ChildEventTester *group1 = new ChildEventTester(QRectF(), group2);
3918 ChildEventTester *leaf = new ChildEventTester(QRectF(), group1);
3919 scene.addItem(group2);
3921 leaf->setFlag(QGraphicsItem::ItemIsFocusable);
3922 group1->setFlag(QGraphicsItem::ItemIsFocusable);
3923 group1->setHandlesChildEvents(true);
3924 group2->setFlag(QGraphicsItem::ItemIsFocusable);
3925 group2->setHandlesChildEvents(true);
3928 QVERIFY(leaf->hasFocus()); // group2 stole the event, but leaf still got focus
3929 QVERIFY(!group1->hasFocus());
3930 QVERIFY(!group2->hasFocus());
3931 QCOMPARE(leaf->counter, 0);
3932 QCOMPARE(group1->counter, 0);
3933 QCOMPARE(group2->counter, 1);
3936 QVERIFY(group1->hasFocus()); // group2 stole the event, but group1 still got focus
3937 QVERIFY(!leaf->hasFocus());
3938 QVERIFY(!group2->hasFocus());
3939 QCOMPARE(leaf->counter, 0);
3940 QCOMPARE(group1->counter, 0);
3941 QCOMPARE(group2->counter, 2);
3944 QVERIFY(group2->hasFocus()); // group2 stole the event, and now group2 also has focus
3945 QVERIFY(!leaf->hasFocus());
3946 QVERIFY(!group1->hasFocus());
3947 QCOMPARE(leaf->counter, 0);
3948 QCOMPARE(group1->counter, 0);
3949 QCOMPARE(group2->counter, 3);
3953 class ChildEventFilterTester : public ChildEventTester
3956 ChildEventFilterTester(const QRectF &rect, QGraphicsItem *parent = 0)
3957 : ChildEventTester(rect, parent), filter(QEvent::None)
3960 QEvent::Type filter;
3963 bool sceneEventFilter(QGraphicsItem *item, QEvent *event)
3966 if (event->type() == filter) {
3974 void tst_QGraphicsItem::filtersChildEvents()
3976 QGraphicsScene scene;
3977 ChildEventFilterTester *root = new ChildEventFilterTester(QRectF(0, 0, 10, 10));
3978 ChildEventFilterTester *filter = new ChildEventFilterTester(QRectF(10, 10, 10, 10), root);
3979 ChildEventTester *child = new ChildEventTester(QRectF(20, 20, 10, 10), filter);
3982 filter->setFiltersChildEvents(true);
3983 filter->filter = QEvent::GraphicsSceneMousePress;
3985 scene.addItem(root);
3987 QGraphicsView view(&scene);
3989 QTest::qWaitForWindowShown(&view);
3992 QGraphicsSceneMouseEvent pressEvent(QEvent::GraphicsSceneMousePress);
3993 QGraphicsSceneMouseEvent releaseEvent(QEvent::GraphicsSceneMouseRelease);
3995 // send event to child
3996 pressEvent.setButton(Qt::LeftButton);
3997 pressEvent.setScenePos(QPointF(25, 25));//child->mapToScene(5, 5));
3998 pressEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
3999 releaseEvent.setButton(Qt::LeftButton);
4000 releaseEvent.setScenePos(QPointF(25, 25));//child->mapToScene(5, 5));
4001 releaseEvent.setScreenPos(view.mapFromScene(pressEvent.scenePos()));
4002 QApplication::sendEvent(&scene, &pressEvent);
4003 QApplication::sendEvent(&scene, &releaseEvent);
4005 QTRY_COMPARE(child->counter, 1); // mouse release is not filtered
4006 QCOMPARE(filter->counter, 1); // mouse press is filtered
4007 QCOMPARE(root->counter, 0);
4009 // add another filter
4010 root->setFiltersChildEvents(true);
4011 root->filter = QEvent::GraphicsSceneMouseRelease;
4013 // send event to child
4014 QApplication::sendEvent(&scene, &pressEvent);
4015 QApplication::sendEvent(&scene, &releaseEvent);
4017 QCOMPARE(child->counter, 1);
4018 QCOMPARE(filter->counter, 2); // mouse press is filtered
4019 QCOMPARE(root->counter, 1); // mouse release is filtered
4021 // reparent to another sub-graph
4022 ChildEventTester *parent = new ChildEventTester(QRectF(10, 10, 10, 10), root);
4023 child->setParentItem(parent);
4025 // send event to child
4026 QApplication::sendEvent(&scene, &pressEvent);
4027 QApplication::sendEvent(&scene, &releaseEvent);
4029 QCOMPARE(child->counter, 2); // mouse press is _not_ filtered
4030 QCOMPARE(parent->counter, 0);
4031 QCOMPARE(filter->counter, 2);
4032 QCOMPARE(root->counter, 2); // mouse release is filtered
4035 void tst_QGraphicsItem::filtersChildEvents2()
4037 ChildEventFilterTester *root = new ChildEventFilterTester(QRectF(0, 0, 10, 10));
4038 root->setFiltersChildEvents(true);
4039 root->filter = QEvent::GraphicsSceneMousePress;
4040 QVERIFY(root->filtersChildEvents());
4042 ChildEventTester *child = new ChildEventTester(QRectF(0, 0, 10, 10), root);
4043 QVERIFY(!child->filtersChildEvents());
4045 ChildEventTester *child2 = new ChildEventTester(QRectF(0, 0, 10, 10));
4046 ChildEventTester *child3 = new ChildEventTester(QRectF(0, 0, 10, 10), child2);
4047 ChildEventTester *child4 = new ChildEventTester(QRectF(0, 0, 10, 10), child3);
4049 child2->setParentItem(root);
4050 QVERIFY(!child2->filtersChildEvents());
4051 QVERIFY(!child3->filtersChildEvents());
4052 QVERIFY(!child4->filtersChildEvents());
4054 QGraphicsScene scene;
4055 scene.addItem(root);
4057 QGraphicsView view(&scene);
4060 QTest::qWaitForWindowShown(&view);
4061 QApplication::processEvents();
4063 QMouseEvent event(QEvent::MouseButtonPress, view.mapFromScene(5, 5),
4064 view.viewport()->mapToGlobal(view.mapFromScene(5, 5)), Qt::LeftButton, 0, 0);
4065 QApplication::sendEvent(view.viewport(), &event);
4067 QTRY_COMPARE(root->counter, 1);
4068 QCOMPARE(child->counter, 0);
4069 QCOMPARE(child2->counter, 0);
4070 QCOMPARE(child3->counter, 0);
4071 QCOMPARE(child4->counter, 0);
4074 class CustomItem : public QGraphicsItem
4077 QRectF boundingRect() const
4078 { return QRectF(-110, -110, 220, 220); }
4080 void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
4082 for (int x = -100; x <= 100; x += 25)
4083 painter->drawLine(x, -100, x, 100);
4084 for (int y = -100; y <= 100; y += 25)
4085 painter->drawLine(-100, y, 100, y);
4087 QFont font = painter->font();
4088 font.setPointSize(4);
4089 painter->setFont(font);
4090 for (int x = -100; x < 100; x += 25) {
4091 for (int y = -100; y < 100; y += 25) {
4092 painter->drawText(QRectF(x, y, 25, 25), Qt::AlignCenter, QString("%1x%2").arg(x).arg(y));
4098 void tst_QGraphicsItem::ensureVisible()
4100 QGraphicsScene scene;
4101 scene.setSceneRect(-200, -200, 400, 400);
4102 QGraphicsItem *item = new CustomItem;
4103 scene.addItem(item);
4105 QGraphicsView view(&scene);
4106 view.setFixedSize(300, 300);
4108 QTest::qWaitForWindowShown(&view);
4110 for (int i = 0; i < 25; ++i) {
4111 view.scale(qreal(1.06), qreal(1.06));
4112 QApplication::processEvents();
4115 item->ensureVisible(-100, -100, 25, 25);
4118 for (int x = -100; x < 100; x += 25) {
4119 for (int y = -100; y < 100; y += 25) {
4120 int xmargin = rand() % 75;
4121 int ymargin = rand() % 75;
4122 item->ensureVisible(x, y, 25, 25, xmargin, ymargin);
4123 QApplication::processEvents();
4125 QPolygonF viewScenePoly;
4126 viewScenePoly << view.mapToScene(view.rect().topLeft())
4127 << view.mapToScene(view.rect().topRight())
4128 << view.mapToScene(view.rect().bottomRight())
4129 << view.mapToScene(view.rect().bottomLeft());
4131 QVERIFY(scene.items(viewScenePoly).contains(item));
4134 path.addPolygon(viewScenePoly);
4135 QVERIFY(path.contains(item->mapToScene(x + 12, y + 12)));
4137 QPolygonF viewScenePolyMinusMargins;
4138 viewScenePolyMinusMargins << view.mapToScene(view.rect().topLeft() + QPoint(xmargin, ymargin))
4139 << view.mapToScene(view.rect().topRight() + QPoint(-xmargin, ymargin))
4140 << view.mapToScene(view.rect().bottomRight() + QPoint(-xmargin, -ymargin))
4141 << view.mapToScene(view.rect().bottomLeft() + QPoint(xmargin, -ymargin));
4144 path2.addPolygon(viewScenePolyMinusMargins);
4145 QVERIFY(path2.contains(item->mapToScene(x + 12, y + 12)));
4149 item->ensureVisible(100, 100, 25, 25);
4153 void tst_QGraphicsItem::cursor()
4155 #ifndef QT_NO_CURSOR
4156 QGraphicsScene scene;
4157 QGraphicsRectItem *item1 = scene.addRect(QRectF(0, 0, 50, 50));
4158 QGraphicsRectItem *item2 = scene.addRect(QRectF(0, 0, 50, 50));
4159 item1->setPos(-100, 0);
4160 item2->setPos(50, 0);
4162 QVERIFY(!item1->hasCursor());
4163 QVERIFY(!item2->hasCursor());
4165 item1->setCursor(Qt::IBeamCursor);
4166 item2->setCursor(Qt::PointingHandCursor);
4168 QVERIFY(item1->hasCursor());
4169 QVERIFY(item2->hasCursor());
4171 item1->setCursor(QCursor());
4172 item2->setCursor(QCursor());
4174 QVERIFY(item1->hasCursor());
4175 QVERIFY(item2->hasCursor());
4177 item1->unsetCursor();
4178 item2->unsetCursor();
4180 QVERIFY(!item1->hasCursor());
4181 QVERIFY(!item2->hasCursor());
4183 item1->setCursor(Qt::IBeamCursor);
4184 item2->setCursor(Qt::PointingHandCursor);
4187 QGraphicsView view(&scene,&topLevel);
4188 view.setFixedSize(200, 100);
4190 QTest::mouseMove(&view, view.rect().center());
4194 QCursor cursor = view.viewport()->cursor();
4197 QMouseEvent event(QEvent::MouseMove, QPoint(100, 50), Qt::NoButton, 0, 0);
4198 QApplication::sendEvent(view.viewport(), &event);
4203 QCOMPARE(view.viewport()->cursor().shape(), cursor.shape());
4206 QTest::mouseMove(view.viewport(), view.mapFromScene(item1->sceneBoundingRect().center()));
4207 QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item1->sceneBoundingRect().center()), Qt::NoButton, 0, 0);
4208 QApplication::sendEvent(view.viewport(), &event);
4211 if (!PlatformQuirks::haveMouseCursor())
4213 #if !defined(Q_OS_WINCE)
4216 // Test environment does not have any cursor, therefore no shape
4220 QCOMPARE(view.viewport()->cursor().shape(), item1->cursor().shape());
4223 QTest::mouseMove(view.viewport(), view.mapFromScene(item2->sceneBoundingRect().center()));
4224 QMouseEvent event(QEvent::MouseMove, view.mapFromScene(item2->sceneBoundingRect().center()), Qt::NoButton, 0, 0);
4225 QApplication::sendEvent(view.viewport(), &event);
4230 QCOMPARE(view.viewport()->cursor().shape(), item2->cursor().shape());
4233 QTest::mouseMove(view.viewport(), view.rect().center());
4234 QMouseEvent event(QEvent::MouseMove, QPoint(100, 25), Qt::NoButton, 0, 0);
4235 QApplication::sendEvent(view.viewport(), &event);
4240 QCOMPARE(view.viewport()->cursor().shape(), cursor.shape());
4244 void tst_QGraphicsItem::textControlGetterSetter()
4246 QGraphicsTextItem *item = new QGraphicsTextItem;
4247 QVERIFY(item->textControl()->parent() == item);
4248 QPointer<QTextControl> control = item->textControl();
4252 item = new QGraphicsTextItem;
4254 QPointer<QTextControl> oldControl = control;
4255 control = new QTextControl;
4257 item->setTextControl(control);
4258 QVERIFY(item->textControl() == control);
4259 QVERIFY(!control->parent());
4260 QVERIFY(!oldControl);
4262 // set some text to give it a size, to test that
4263 // setTextControl (re)connects signals
4264 const QRectF oldBoundingRect = item->boundingRect();
4265 QVERIFY(oldBoundingRect.isValid());
4266 item->setPlainText("Some text");
4268 QVERIFY(item->boundingRect().isValid());
4269 QVERIFY(item->boundingRect() != oldBoundingRect);
4271 // test that on setting a control the item size
4273 oldControl = control;
4274 control = new QTextControl;
4275 control->setPlainText("foo!");
4276 item->setTextControl(control);
4277 QCOMPARE(item->boundingRect().size(), control->document()->documentLayout()->documentSize());
4279 QVERIFY(oldControl);
4288 void tst_QGraphicsItem::defaultItemTest_QGraphicsLineItem()
4290 QGraphicsLineItem item;
4291 QCOMPARE(item.line(), QLineF());
4292 QCOMPARE(item.pen(), QPen());
4293 QCOMPARE(item.shape(), QPainterPath());
4295 item.setPen(QPen(Qt::black, 1));
4296 QCOMPARE(item.pen(), QPen(Qt::black, 1));
4297 item.setLine(QLineF(0, 0, 10, 0));
4298 QCOMPARE(item.line(), QLineF(0, 0, 10, 0));
4299 QCOMPARE(item.boundingRect(), QRectF(-0.5, -0.5, 11, 1));
4300 QCOMPARE(item.shape().elementCount(), 11);
4303 path.moveTo(0, -0.5);
4304 path.lineTo(10, -0.5);
4305 path.lineTo(10.5, -0.5);
4306 path.lineTo(10.5, 0.5);
4307 path.lineTo(10, 0.5);
4308 path.lineTo(0, 0.5);
4309 path.lineTo(-0.5, 0.5);
4310 path.lineTo(-0.5, -0.5);
4311 path.lineTo(0, -0.5);
4314 path.closeSubpath();
4316 for (int i = 0; i < 11; ++i)
4317 QCOMPARE(QPointF(item.shape().elementAt(i)), QPointF(path.elementAt(i)));
4320 void tst_QGraphicsItem::defaultItemTest_QGraphicsPixmapItem()
4322 QGraphicsPixmapItem item;
4323 QVERIFY(item.pixmap().isNull());
4324 QCOMPARE(item.offset(), QPointF());
4325 QCOMPARE(item.transformationMode(), Qt::FastTransformation);
4327 QPixmap pixmap(300, 200);
4328 pixmap.fill(Qt::red);
4329 item.setPixmap(pixmap);
4330 QCOMPARE(item.pixmap(), pixmap);
4332 item.setTransformationMode(Qt::FastTransformation);
4333 QCOMPARE(item.transformationMode(), Qt::FastTransformation);
4334 item.setTransformationMode(Qt::SmoothTransformation);
4335 QCOMPARE(item.transformationMode(), Qt::SmoothTransformation);
4337 item.setOffset(-15, -15);
4338 QCOMPARE(item.offset(), QPointF(-15, -15));
4339 item.setOffset(QPointF(-10, -10));
4340 QCOMPARE(item.offset(), QPointF(-10, -10));
4342 QCOMPARE(item.boundingRect(), QRectF(-10, -10, 300, 200));
4345 void tst_QGraphicsItem::defaultItemTest_QGraphicsTextItem()
4347 QGraphicsTextItem *text = new QGraphicsTextItem;
4348 QVERIFY(!text->openExternalLinks());
4349 QVERIFY(text->textCursor().isNull());
4350 QCOMPARE(text->defaultTextColor(), QPalette().color(QPalette::Text));
4351 QVERIFY(text->document() != 0);
4352 QCOMPARE(text->font(), QApplication::font());
4353 QCOMPARE(text->textInteractionFlags(), Qt::TextInteractionFlags(Qt::NoTextInteraction));
4354 QCOMPARE(text->textWidth(), -1.0);
4355 QCOMPARE(text->toPlainText(), QString(""));
4357 QGraphicsScene scene;
4358 scene.addItem(text);
4359 text->setPlainText("Hello world");
4360 text->setFlag(QGraphicsItem::ItemIsMovable);
4363 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
4364 event.setScenePos(QPointF(1, 1));
4365 event.setButton(Qt::LeftButton);
4366 event.setButtons(Qt::LeftButton);
4367 QApplication::sendEvent(&scene, &event);
4368 QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove);
4369 event2.setScenePos(QPointF(11, 11));
4370 event2.setButton(Qt::LeftButton);
4371 event2.setButtons(Qt::LeftButton);
4372 QApplication::sendEvent(&scene, &event2);
4375 QCOMPARE(text->pos(), QPointF(10, 10));
4377 text->setTextInteractionFlags(Qt::NoTextInteraction);
4378 QVERIFY(!(text->flags() & QGraphicsItem::ItemAcceptsInputMethod));
4379 text->setTextInteractionFlags(Qt::TextEditorInteraction);
4380 QCOMPARE(text->textInteractionFlags(), Qt::TextInteractionFlags(Qt::TextEditorInteraction));
4381 QVERIFY(text->flags() & QGraphicsItem::ItemAcceptsInputMethod);
4384 QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove);
4385 event2.setScenePos(QPointF(21, 21));
4386 event2.setButton(Qt::LeftButton);
4387 event2.setButtons(Qt::LeftButton);
4388 QApplication::sendEvent(&scene, &event2);
4391 QCOMPARE(text->pos(), QPointF(20, 20)); // clicked on edge, item moved
4394 void tst_QGraphicsItem::defaultItemTest_QGraphicsEllipseItem()
4396 QGraphicsEllipseItem item;
4397 QVERIFY(item.rect().isNull());
4398 QVERIFY(item.boundingRect().isNull());
4399 QVERIFY(item.shape().isEmpty());
4400 QCOMPARE(item.spanAngle(), 360 * 16);
4401 QCOMPARE(item.startAngle(), 0);
4403 item.setRect(0, 0, 100, 100);
4404 QCOMPARE(item.boundingRect(), QRectF(0, 0, 100, 100));
4406 item.setSpanAngle(90 * 16);
4407 qFuzzyCompare(item.boundingRect().left(), qreal(50.0));
4408 qFuzzyCompare(item.boundingRect().top(), qreal(0.0));
4409 qFuzzyCompare(item.boundingRect().width(), qreal(50.0));
4410 qFuzzyCompare(item.boundingRect().height(), qreal(50.0));
4412 item.setPen(QPen(Qt::black, 1));
4413 QCOMPARE(item.boundingRect(), QRectF(49.5, -0.5, 51, 51));
4415 item.setSpanAngle(180 * 16);
4416 QCOMPARE(item.boundingRect(), QRectF(-0.5, -0.5, 101, 51));
4418 item.setSpanAngle(360 * 16);
4419 QCOMPARE(item.boundingRect(), QRectF(-0.5, -0.5, 101, 101));
4422 class ItemChangeTester : public QGraphicsRectItem
4426 { setFlag(ItemSendsGeometryChanges); clear(); }
4427 ItemChangeTester(QGraphicsItem *parent) : QGraphicsRectItem(parent)
4428 { setFlag(ItemSendsGeometryChanges); clear(); }
4432 itemChangeReturnValue = QVariant();
4433 itemSceneChangeTargetScene = 0;
4439 QVariant itemChangeReturnValue;
4440 QGraphicsScene *itemSceneChangeTargetScene;
4442 QList<GraphicsItemChange> changes;
4443 QList<QVariant> values;
4444 QList<QVariant> oldValues;
4446 QVariant itemChange(GraphicsItemChange change, const QVariant &value)
4451 case QGraphicsItem::ItemPositionChange:
4454 case QGraphicsItem::ItemPositionHasChanged:
4456 case QGraphicsItem::ItemMatrixChange: {
4458 qVariantSetValue<QMatrix>(variant, matrix());
4459 oldValues << variant;
4462 case QGraphicsItem::ItemTransformChange: {
4464 qVariantSetValue<QTransform>(variant, transform());
4465 oldValues << variant;
4468 case QGraphicsItem::ItemTransformHasChanged:
4470 case QGraphicsItem::ItemVisibleChange:
4471 oldValues << isVisible();
4473 case QGraphicsItem::ItemVisibleHasChanged:
4475 case QGraphicsItem::ItemEnabledChange:
4476 oldValues << isEnabled();
4478 case QGraphicsItem::ItemEnabledHasChanged:
4480 case QGraphicsItem::ItemSelectedChange:
4481 oldValues << isSelected();
4483 case QGraphicsItem::ItemSelectedHasChanged:
4485 case QGraphicsItem::ItemParentChange:
4486 oldValues << qVariantFromValue<void *>(parentItem());
4488 case QGraphicsItem::ItemParentHasChanged:
4490 case QGraphicsItem::ItemChildAddedChange:
4491 oldValues << children().size();
4493 case QGraphicsItem::ItemChildRemovedChange:
4494 oldValues << children().size();
4496 case QGraphicsItem::ItemSceneChange:
4497 oldValues << qVariantFromValue<QGraphicsScene *>(scene());
4498 if (itemSceneChangeTargetScene
4499 && qVariantValue<QGraphicsScene *>(value)
4500 && itemSceneChangeTargetScene != qVariantValue<QGraphicsScene *>(value)) {
4501 return qVariantFromValue<QGraphicsScene *>(itemSceneChangeTargetScene);
4504 case QGraphicsItem::ItemSceneHasChanged:
4506 case QGraphicsItem::ItemCursorChange:
4507 #ifndef QT_NO_CURSOR
4508 oldValues << cursor();
4511 case QGraphicsItem::ItemCursorHasChanged:
4513 case QGraphicsItem::ItemToolTipChange:
4514 oldValues << toolTip();
4516 case QGraphicsItem::ItemToolTipHasChanged:
4518 case QGraphicsItem::ItemFlagsChange:
4519 oldValues << quint32(flags());
4521 case QGraphicsItem::ItemFlagsHaveChanged:
4523 case QGraphicsItem::ItemZValueChange:
4524 oldValues << zValue();
4526 case QGraphicsItem::ItemZValueHasChanged:
4528 case QGraphicsItem::ItemOpacityChange:
4529 oldValues << opacity();
4531 case QGraphicsItem::ItemOpacityHasChanged:
4533 case QGraphicsItem::ItemScenePositionHasChanged:
4535 case QGraphicsItem::ItemRotationChange:
4536 oldValues << rotation();
4538 case QGraphicsItem::ItemRotationHasChanged:
4540 case QGraphicsItem::ItemScaleChange:
4541 oldValues << scale();
4543 case QGraphicsItem::ItemScaleHasChanged:
4545 case QGraphicsItem::ItemTransformOriginPointChange:
4546 oldValues << transformOriginPoint();
4548 case QGraphicsItem::ItemTransformOriginPointHasChanged:
4551 return itemChangeReturnValue.isValid() ? itemChangeReturnValue : value;
4555 void tst_QGraphicsItem::itemChange()
4557 ItemChangeTester tester;
4558 tester.itemSceneChangeTargetScene = 0;
4560 ItemChangeTester testerHelper;
4561 QVERIFY(tester.changes.isEmpty());
4562 QVERIFY(tester.values.isEmpty());
4564 int changeCount = 0;
4566 // ItemEnabledChange
4567 tester.itemChangeReturnValue = true;
4568 tester.setEnabled(false);
4570 ++changeCount; // HasChanged
4571 QCOMPARE(tester.changes.size(), changeCount);
4572 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemEnabledChange);
4573 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemEnabledHasChanged);
4574 QCOMPARE(tester.values.at(tester.values.size() - 2), QVariant(false));
4575 QCOMPARE(tester.values.at(tester.values.size() - 1), QVariant(true));
4576 QCOMPARE(tester.oldValues.last(), QVariant(true));
4577 QCOMPARE(tester.isEnabled(), true);
4580 // ItemMatrixChange / ItemTransformHasChanged
4581 qVariantSetValue<QMatrix>(tester.itemChangeReturnValue, QMatrix().rotate(90));
4582 tester.setMatrix(QMatrix().translate(50, 0), true);
4583 ++changeCount; // notification sent too
4584 QCOMPARE(tester.changes.size(), ++changeCount);
4585 QCOMPARE(int(tester.changes.at(tester.changes.size() - 2)), int(QGraphicsItem::ItemMatrixChange));
4586 QCOMPARE(int(tester.changes.last()), int(QGraphicsItem::ItemTransformHasChanged));
4587 QCOMPARE(qVariantValue<QMatrix>(tester.values.at(tester.values.size() - 2)),
4588 QMatrix().translate(50, 0));
4589 QCOMPARE(tester.values.last(), QVariant(QTransform(QMatrix().rotate(90))));
4591 qVariantSetValue<QMatrix>(variant, QMatrix());
4592 QCOMPARE(tester.oldValues.last(), variant);
4593 QCOMPARE(tester.matrix(), QMatrix().rotate(90));
4596 tester.resetTransform();
4598 ++changeCount; // notification sent too
4600 // ItemTransformChange / ItemTransformHasChanged
4601 qVariantSetValue<QTransform>(tester.itemChangeReturnValue, QTransform().rotate(90));
4602 tester.translate(50, 0);
4603 ++changeCount; // notification sent too
4605 QCOMPARE(tester.changes.size(), changeCount);
4606 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemTransformChange);
4607 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemTransformHasChanged);
4608 QCOMPARE(qVariantValue<QTransform>(tester.values.at(tester.values.size() - 2)),
4609 QTransform().translate(50, 0));
4610 QCOMPARE(qVariantValue<QTransform>(tester.values.at(tester.values.size() - 1)),
4611 QTransform().rotate(90));
4613 qVariantSetValue<QTransform>(variant, QTransform());
4614 QCOMPARE(tester.oldValues.last(), variant);
4615 QCOMPARE(tester.transform(), QTransform().rotate(90));
4618 // ItemPositionChange / ItemPositionHasChanged
4619 tester.itemChangeReturnValue = QPointF(42, 0);
4620 tester.setPos(0, 42);
4621 ++changeCount; // notification sent too
4623 QCOMPARE(tester.changes.size(), changeCount);
4624 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemPositionChange);
4625 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemPositionHasChanged);
4626 QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(QPointF(0, 42)));
4627 QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(QPointF(42, 0)));
4628 QCOMPARE(tester.oldValues.last(), QVariant(QPointF()));
4629 QCOMPARE(tester.pos(), QPointF(42, 0));
4632 // ItemZValueChange / ItemZValueHasChanged
4633 tester.itemChangeReturnValue = qreal(2.0);
4634 tester.setZValue(1.0);
4635 ++changeCount; // notification sent too
4637 QCOMPARE(tester.changes.size(), changeCount);
4638 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemZValueChange);
4639 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemZValueHasChanged);
4640 QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(qreal(1.0)));
4641 QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(qreal(2.0)));
4642 QCOMPARE(tester.oldValues.last(), QVariant(qreal(0.0)));
4643 QCOMPARE(tester.zValue(), qreal(2.0));
4646 // ItemRotationChange / ItemRotationHasChanged
4647 tester.itemChangeReturnValue = qreal(15.0);
4648 tester.setRotation(10.0);
4649 ++changeCount; // notification sent too
4651 QCOMPARE(tester.changes.size(), changeCount);
4652 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemRotationChange);
4653 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemRotationHasChanged);
4654 QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(qreal(10.0)));
4655 QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(qreal(15.0)));
4656 QCOMPARE(tester.oldValues.last(), QVariant(qreal(0.0)));
4657 QCOMPARE(tester.rotation(), qreal(15.0));
4660 // ItemScaleChange / ItemScaleHasChanged
4661 tester.itemChangeReturnValue = qreal(2.0);
4662 tester.setScale(1.5);
4663 ++changeCount; // notification sent too
4665 QCOMPARE(tester.changes.size(), changeCount);
4666 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemScaleChange);
4667 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemScaleHasChanged);
4668 QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(qreal(1.5)));
4669 QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(qreal(2.0)));
4670 QCOMPARE(tester.oldValues.last(), QVariant(qreal(1.0)));
4671 QCOMPARE(tester.scale(), qreal(2.0));
4674 // ItemTransformOriginPointChange / ItemTransformOriginPointHasChanged
4675 tester.itemChangeReturnValue = QPointF(2.0, 2.0);
4676 tester.setTransformOriginPoint(1.0, 1.0);
4677 ++changeCount; // notification sent too
4679 QCOMPARE(tester.changes.size(), changeCount);
4680 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemTransformOriginPointChange);
4681 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemTransformOriginPointHasChanged);
4682 QCOMPARE(tester.values.at(tester.changes.size() - 2), QVariant(QPointF(1.0, 1.0)));
4683 QCOMPARE(tester.values.at(tester.changes.size() - 1), QVariant(QPointF(2.0, 2.0)));
4684 QCOMPARE(tester.oldValues.last(), QVariant(QPointF(0.0, 0.0)));
4685 QCOMPARE(tester.transformOriginPoint(), QPointF(2.0, 2.0));
4689 tester.itemChangeReturnValue = QGraphicsItem::ItemIsSelectable;
4690 tester.setFlag(QGraphicsItem::ItemIsSelectable, false);
4691 QCOMPARE(tester.changes.size(), changeCount); // No change
4692 tester.setFlag(QGraphicsItem::ItemIsSelectable, true);
4694 ++changeCount; // ItemFlagsHasChanged
4695 QCOMPARE(tester.changes.size(), changeCount);
4696 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemFlagsChange);
4697 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemFlagsHaveChanged);
4698 QVariant expectedFlags = qVariantFromValue<quint32>(QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges));
4699 QCOMPARE(tester.values.at(tester.values.size() - 2), expectedFlags);
4700 QCOMPARE(tester.values.at(tester.values.size() - 1), qVariantFromValue<quint32>((quint32)QGraphicsItem::ItemIsSelectable));
4703 // ItemSelectedChange
4704 tester.setSelected(false);
4705 QCOMPARE(tester.changes.size(), changeCount); // No change :-)
4706 tester.itemChangeReturnValue = true;
4707 tester.setSelected(true);
4709 ++changeCount; // ItemSelectedHasChanged
4710 QCOMPARE(tester.changes.size(), changeCount);
4711 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSelectedChange);
4712 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSelectedHasChanged);
4713 QCOMPARE(tester.values.at(tester.values.size() - 2), QVariant(true));
4714 QCOMPARE(tester.values.at(tester.values.size() - 1), QVariant(true));
4715 QCOMPARE(tester.oldValues.last(), QVariant(false));
4716 QCOMPARE(tester.isSelected(), true);
4718 tester.itemChangeReturnValue = false;
4719 tester.setSelected(true);
4721 // the value hasn't changed to the itemChange return value
4722 // bacause itemChange is never called (true -> true is a noop).
4723 QCOMPARE(tester.isSelected(), true);
4726 // ItemVisibleChange
4727 tester.itemChangeReturnValue = false;
4728 QVERIFY(tester.isVisible());
4729 tester.setVisible(false);
4730 ++changeCount; // ItemVisibleChange
4731 ++changeCount; // ItemSelectedChange
4732 ++changeCount; // ItemSelectedHasChanged
4733 ++changeCount; // ItemVisibleHasChanged
4734 QCOMPARE(tester.changes.size(), changeCount);
4735 QCOMPARE(tester.changes.at(tester.changes.size() - 4), QGraphicsItem::ItemVisibleChange);
4736 QCOMPARE(tester.changes.at(tester.changes.size() - 3), QGraphicsItem::ItemSelectedChange);
4737 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSelectedHasChanged);
4738 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemVisibleHasChanged);
4739 QCOMPARE(tester.values.at(tester.values.size() - 4), QVariant(false));
4740 QCOMPARE(tester.values.at(tester.values.size() - 3), QVariant(false));
4741 QCOMPARE(tester.values.at(tester.values.size() - 2), QVariant(false));
4742 QCOMPARE(tester.values.at(tester.values.size() - 1), QVariant(false));
4743 QCOMPARE(tester.isVisible(), false);
4747 qVariantSetValue<QGraphicsItem *>(tester.itemChangeReturnValue, 0);
4748 tester.setParentItem(&testerHelper);
4749 QCOMPARE(tester.changes.size(), ++changeCount);
4750 QCOMPARE(tester.changes.last(), QGraphicsItem::ItemParentChange);
4751 QCOMPARE(qVariantValue<QGraphicsItem *>(tester.values.last()), (QGraphicsItem *)&testerHelper);
4752 QCOMPARE(qVariantValue<QGraphicsItem *>(tester.oldValues.last()), (QGraphicsItem *)0);
4753 QCOMPARE(tester.parentItem(), (QGraphicsItem *)0);
4756 // ItemOpacityChange
4757 tester.itemChangeReturnValue = 1.0;
4758 tester.setOpacity(0.7);
4759 QCOMPARE(tester.changes.size(), ++changeCount);
4760 QCOMPARE(tester.changes.last(), QGraphicsItem::ItemOpacityChange);
4761 QVERIFY(qFuzzyCompare(qreal(tester.values.last().toDouble()), qreal(0.7)));
4762 QCOMPARE(tester.oldValues.last().toDouble(), double(1.0));
4763 QCOMPARE(tester.opacity(), qreal(1.0));
4764 tester.itemChangeReturnValue = 0.7;
4765 tester.setOpacity(0.7);
4766 ++changeCount; // ItemOpacityChange
4767 ++changeCount; // ItemOpacityHasChanged
4768 QCOMPARE(tester.changes.size(), changeCount);
4769 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemOpacityChange);
4770 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemOpacityHasChanged);
4771 QCOMPARE(tester.opacity(), qreal(0.7));
4774 // ItemChildAddedChange
4775 tester.itemChangeReturnValue.clear();
4776 testerHelper.setParentItem(&tester);
4777 QCOMPARE(tester.changes.size(), ++changeCount);
4778 QCOMPARE(tester.changes.last(), QGraphicsItem::ItemChildAddedChange);
4779 QCOMPARE(qVariantValue<QGraphicsItem *>(tester.values.last()), (QGraphicsItem *)&testerHelper);
4782 // ItemChildRemovedChange 1
4783 testerHelper.setParentItem(0);
4784 QCOMPARE(tester.changes.size(), ++changeCount);
4785 QCOMPARE(tester.changes.last(), QGraphicsItem::ItemChildRemovedChange);
4786 QCOMPARE(qVariantValue<QGraphicsItem *>(tester.values.last()), (QGraphicsItem *)&testerHelper);
4788 // ItemChildRemovedChange 1
4789 ItemChangeTester *test = new ItemChangeTester;
4790 test->itemSceneChangeTargetScene = 0;
4792 QGraphicsScene *scene = new QGraphicsScene;
4793 scene->addItem(test);
4794 count = test->changes.size();
4795 //We test here the fact that when a child is deleted the parent receive only one ItemChildRemovedChange
4796 QGraphicsRectItem *child = new QGraphicsRectItem(test);
4797 //We received ItemChildAddedChange
4798 QCOMPARE(test->changes.size(), ++count);
4799 QCOMPARE(test->changes.last(), QGraphicsItem::ItemChildAddedChange);
4802 QCOMPARE(test->changes.size(), ++count);
4803 QCOMPARE(test->changes.last(), QGraphicsItem::ItemChildRemovedChange);
4805 ItemChangeTester *childTester = new ItemChangeTester(test);
4806 //Changes contains all sceneHasChanged and so on, we don't want to test that
4807 int childCount = childTester->changes.size();
4808 //We received ItemChildAddedChange
4809 QCOMPARE(test->changes.size(), ++count);
4810 child = new QGraphicsRectItem(childTester);
4811 //We received ItemChildAddedChange
4812 QCOMPARE(childTester->changes.size(), ++childCount);
4813 QCOMPARE(childTester->changes.last(), QGraphicsItem::ItemChildAddedChange);
4814 //Delete the child of the top level with all its children
4817 QCOMPARE(test->changes.size(), ++count);
4818 QCOMPARE(test->changes.last(), QGraphicsItem::ItemChildRemovedChange);
4822 // ItemChildRemovedChange 2
4823 ItemChangeTester parent;
4824 ItemChangeTester *child = new ItemChangeTester;
4825 child->setParentItem(&parent);
4826 QCOMPARE(parent.changes.last(), QGraphicsItem::ItemChildAddedChange);
4827 QCOMPARE(qVariantValue<QGraphicsItem *>(parent.values.last()), (QGraphicsItem *)child);
4829 QCOMPARE(parent.changes.last(), QGraphicsItem::ItemChildRemovedChange);
4830 QCOMPARE(qVariantValue<QGraphicsItem *>(parent.values.last()), (QGraphicsItem *)child);
4833 // !!! Note: If this test crashes because of double-deletion, there's
4834 // a bug somewhere in QGraphicsScene or QGraphicsItem.
4837 QGraphicsScene scene;
4838 QGraphicsScene scene2;
4839 scene.addItem(&tester);
4840 ++changeCount; // ItemSceneChange (scene)
4841 ++changeCount; // ItemSceneHasChanged (scene)
4842 QCOMPARE(tester.changes.size(), changeCount);
4844 QCOMPARE(tester.scene(), &scene);
4845 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSceneChange);
4846 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSceneHasChanged);
4847 // Item's old value was 0
4848 // Item's current value is scene
4849 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.oldValues.last()), (QGraphicsScene *)0);
4850 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.last()), (QGraphicsScene *)&scene);
4851 scene2.addItem(&tester);
4852 ++changeCount; // ItemSceneChange (0) was: (scene)
4853 ++changeCount; // ItemSceneHasChanged (0)
4854 ++changeCount; // ItemSceneChange (scene2) was: (0)
4855 ++changeCount; // ItemSceneHasChanged (scene2)
4856 QCOMPARE(tester.changes.size(), changeCount);
4858 QCOMPARE(tester.scene(), &scene2);
4859 QCOMPARE(tester.changes.at(tester.changes.size() - 4), QGraphicsItem::ItemSceneChange);
4860 QCOMPARE(tester.changes.at(tester.changes.size() - 3), QGraphicsItem::ItemSceneHasChanged);
4861 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSceneChange);
4862 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSceneHasChanged);
4863 // Item's last old value was scene
4864 // Item's last current value is 0
4866 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.oldValues.at(tester.oldValues.size() - 2)), (QGraphicsScene *)&scene);
4867 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.oldValues.at(tester.oldValues.size() - 1)), (QGraphicsScene *)0);
4868 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 4)), (QGraphicsScene *)0);
4869 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 3)), (QGraphicsScene *)0);
4870 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)&scene2);
4871 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 1)), (QGraphicsScene *)&scene2);
4872 // Item's last old value was 0
4873 // Item's last current value is scene2
4874 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.oldValues.last()), (QGraphicsScene *)0);
4875 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.last()), (QGraphicsScene *)&scene2);
4877 scene2.removeItem(&tester);
4878 ++changeCount; // ItemSceneChange (0) was: (scene2)
4879 ++changeCount; // ItemSceneHasChanged (0)
4880 QCOMPARE(tester.changes.size(), changeCount);
4882 QCOMPARE(tester.scene(), (QGraphicsScene *)0);
4883 QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemSceneChange);
4884 QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemSceneHasChanged);
4885 // Item's last old value was scene2
4886 // Item's last current value is 0
4887 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.oldValues.last()), (QGraphicsScene *)&scene2);
4888 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)0);
4889 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 1)), (QGraphicsScene *)0);
4891 tester.itemSceneChangeTargetScene = &scene;
4892 scene2.addItem(&tester);
4893 ++changeCount; // ItemSceneChange (scene2) was: (0)
4894 ++changeCount; // ItemSceneChange (scene) was: (0)
4895 ++changeCount; // ItemSceneHasChanged (scene)
4896 QCOMPARE(tester.values.size(), changeCount);
4898 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 3)), (QGraphicsScene *)&scene2);
4899 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 2)), (QGraphicsScene *)&scene);
4900 QCOMPARE(qVariantValue<QGraphicsScene *>(tester.values.at(tester.values.size() - 1)), (QGraphicsScene *)&scene);
4902 QCOMPARE(tester.scene(), &scene);
4903 tester.itemSceneChangeTargetScene = 0;
4904 tester.itemChangeReturnValue = QVariant();
4905 scene.removeItem(&tester);
4906 ++changeCount; // ItemSceneChange
4907 ++changeCount; // ItemSceneHasChanged
4908 QCOMPARE(tester.scene(), (QGraphicsScene *)0);
4911 // ItemToolTipChange/ItemToolTipHasChanged
4912 const QString toolTip(QLatin1String("I'm soo cool"));
4913 const QString overridenToolTip(QLatin1String("No, you are not soo cool"));
4914 tester.itemChangeReturnValue = overridenToolTip;
4915 tester.setToolTip(toolTip);
4916 ++changeCount; // ItemToolTipChange
4917 ++changeCount; // ItemToolTipHasChanged
4918 QCOMPARE(tester.changes.size(), changeCount);
4919 QCOMPARE(tester.changes.at(changeCount - 2), QGraphicsItem::ItemToolTipChange);
4920 QCOMPARE(tester.values.at(changeCount - 2).toString(), toolTip);
4921 QCOMPARE(tester.changes.at(changeCount - 1), QGraphicsItem::ItemToolTipHasChanged);
4922 QCOMPARE(tester.values.at(changeCount - 1).toString(), overridenToolTip);
4923 QCOMPARE(tester.toolTip(), overridenToolTip);
4924 tester.itemChangeReturnValue = QVariant();
4928 class EventFilterTesterItem : public QGraphicsLineItem
4931 QList<QEvent::Type> filteredEvents;
4932 QList<QGraphicsItem *> filteredEventReceivers;
4933 bool handlesSceneEvents;
4935 QList<QEvent::Type> receivedEvents;
4937 EventFilterTesterItem() : handlesSceneEvents(false) {}
4940 bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
4942 filteredEvents << event->type();
4943 filteredEventReceivers << watched;
4944 return handlesSceneEvents;
4947 bool sceneEvent(QEvent *event)
4949 return QGraphicsLineItem::sceneEvent(event);
4953 void tst_QGraphicsItem::sceneEventFilter()
4955 QGraphicsScene scene;
4957 QGraphicsView view(&scene);
4959 QApplication::setActiveWindow(&view);
4960 QTest::qWaitForWindowShown(&view);
4963 QGraphicsTextItem *text1 = scene.addText(QLatin1String("Text1"));
4964 QGraphicsTextItem *text2 = scene.addText(QLatin1String("Text2"));
4965 QGraphicsTextItem *text3 = scene.addText(QLatin1String("Text3"));
4966 text1->setFlag(QGraphicsItem::ItemIsFocusable);
4967 text2->setFlag(QGraphicsItem::ItemIsFocusable);
4968 text3->setFlag(QGraphicsItem::ItemIsFocusable);
4970 EventFilterTesterItem *tester = new EventFilterTesterItem;
4971 scene.addItem(tester);
4973 QTRY_VERIFY(!text1->hasFocus());
4974 text1->installSceneEventFilter(tester);
4976 QTRY_VERIFY(text1->hasFocus());
4978 QCOMPARE(tester->filteredEvents.size(), 1);
4979 QCOMPARE(tester->filteredEvents.at(0), QEvent::FocusIn);
4980 QCOMPARE(tester->filteredEventReceivers.at(0), static_cast<QGraphicsItem *>(text1));
4982 text2->installSceneEventFilter(tester);
4983 text3->installSceneEventFilter(tester);
4988 QCOMPARE(tester->filteredEvents.size(), 5);
4989 QCOMPARE(tester->filteredEvents.at(1), QEvent::FocusOut);
4990 QCOMPARE(tester->filteredEventReceivers.at(1), static_cast<QGraphicsItem *>(text1));
4991 QCOMPARE(tester->filteredEvents.at(2), QEvent::FocusIn);
4992 QCOMPARE(tester->filteredEventReceivers.at(2), static_cast<QGraphicsItem *>(text2));
4993 QCOMPARE(tester->filteredEvents.at(3), QEvent::FocusOut);
4994 QCOMPARE(tester->filteredEventReceivers.at(3), static_cast<QGraphicsItem *>(text2));
4995 QCOMPARE(tester->filteredEvents.at(4), QEvent::FocusIn);
4996 QCOMPARE(tester->filteredEventReceivers.at(4), static_cast<QGraphicsItem *>(text3));
4998 text1->removeSceneEventFilter(tester);
5001 QCOMPARE(tester->filteredEvents.size(), 6);
5002 QCOMPARE(tester->filteredEvents.at(5), QEvent::FocusOut);
5003 QCOMPARE(tester->filteredEventReceivers.at(5), static_cast<QGraphicsItem *>(text3));
5005 tester->handlesSceneEvents = true;
5008 QCOMPARE(tester->filteredEvents.size(), 7);
5009 QCOMPARE(tester->filteredEvents.at(6), QEvent::FocusIn);
5010 QCOMPARE(tester->filteredEventReceivers.at(6), static_cast<QGraphicsItem *>(text2));
5012 QVERIFY(text2->hasFocus());
5014 //Let check if the items are correctly removed from the sceneEventFilters array
5015 //to avoid stale pointers.
5017 QGraphicsScene *anotherScene = new QGraphicsScene;
5018 QGraphicsTextItem *ti = anotherScene->addText("This is a test #1");
5020 QGraphicsTextItem *ti2 = anotherScene->addText("This is a test #2");
5021 QGraphicsTextItem *ti3 = anotherScene->addText("This is a test #3");
5022 gv.setScene(anotherScene);
5024 QTest::qWaitForWindowShown(&gv);
5026 ti->installSceneEventFilter(ti2);
5027 ti3->installSceneEventFilter(ti);
5030 QTest::mouseMove(gv.viewport(), gv.mapFromScene(ti->scenePos()));
5035 class GeometryChanger : public QGraphicsItem
5038 void changeGeometry()
5039 { prepareGeometryChange(); }
5042 void tst_QGraphicsItem::prepareGeometryChange()
5045 QGraphicsScene scene;
5046 QGraphicsItem *item = scene.addRect(QRectF(0, 0, 100, 100));
5047 QVERIFY(scene.items(QRectF(0, 0, 100, 100)).contains(item));
5048 ((GeometryChanger *)item)->changeGeometry();
5049 QVERIFY(scene.items(QRectF(0, 0, 100, 100)).contains(item));
5054 class PaintTester : public QGraphicsRectItem
5057 PaintTester() : widget(NULL), painted(0) { setRect(QRectF(10, 10, 20, 20));}
5059 void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *w)
5069 void tst_QGraphicsItem::paint()
5071 QGraphicsScene scene;
5073 PaintTester paintTester;
5074 scene.addItem(&paintTester);
5076 QGraphicsView view(&scene);
5078 if(PlatformQuirks::isAutoMaximizing())
5079 view.showFullScreen();
5082 QTest::qWaitForWindowShown(&view);
5083 QApplication::processEvents();
5085 //we try to switch the desktop: if it fails, we skip the test
5086 if (::SwitchDesktop( ::GetThreadDesktop( ::GetCurrentThreadId() ) ) == 0) {
5087 QSKIP("The Graphics View doesn't get the paint events");
5091 QTRY_COMPARE(paintTester.widget, view.viewport());
5095 QGraphicsScene scene2;
5096 QGraphicsView view2(&scene2);
5098 QTest::qWaitForWindowShown(&view2);
5101 PaintTester tester2;
5102 scene2.addItem(&tester2);
5103 qApp->processEvents();
5105 //First show one paint
5106 QTRY_COMPARE(tester2.painted, 1);
5108 //nominal case, update call paint
5110 qApp->processEvents();
5111 QTRY_VERIFY(tester2.painted == 2);
5113 //we remove the item from the scene, number of updates is still the same
5115 scene2.removeItem(&tester2);
5116 qApp->processEvents();
5117 QTRY_VERIFY(tester2.painted == 2);
5119 //We re-add the item, the number of paint should increase
5120 scene2.addItem(&tester2);
5122 qApp->processEvents();
5123 QTRY_VERIFY(tester2.painted == 3);
5126 class HarakiriItem : public QGraphicsRectItem
5129 HarakiriItem(int harakiriPoint)
5130 : QGraphicsRectItem(QRectF(0, 0, 100, 100)), harakiri(harakiriPoint)
5135 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
5137 QGraphicsRectItem::paint(painter, option, widget);
5138 if (harakiri == 0) {
5139 // delete unsupported since 4.5
5149 if (harakiri == 1 && n == 0) {
5150 // delete unsupported
5156 if (harakiri == 2 && n == 1) {
5163 void contextMenuEvent(QGraphicsSceneContextMenuEvent *)
5165 if (harakiri == 3) {
5171 void dragEnterEvent(QGraphicsSceneDragDropEvent *event)
5174 QGraphicsRectItem::dragEnterEvent(event);
5177 void dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
5180 QGraphicsRectItem::dragLeaveEvent(event);
5183 void dragMoveEvent(QGraphicsSceneDragDropEvent *event)
5186 QGraphicsRectItem::dragMoveEvent(event);
5189 void dropEvent(QGraphicsSceneDragDropEvent *event)
5192 QGraphicsRectItem::dropEvent(event);
5195 void focusInEvent(QFocusEvent *)
5197 if (harakiri == 4) {
5203 void focusOutEvent(QFocusEvent *)
5205 if (harakiri == 5) {
5211 void hoverEnterEvent(QGraphicsSceneHoverEvent *)
5213 if (harakiri == 6) {
5219 void hoverLeaveEvent(QGraphicsSceneHoverEvent *)
5221 if (harakiri == 7) {
5227 void hoverMoveEvent(QGraphicsSceneHoverEvent *)
5229 if (harakiri == 8) {
5235 void inputMethodEvent(QInputMethodEvent *event)
5238 QGraphicsRectItem::inputMethodEvent(event);
5241 QVariant inputMethodQuery(Qt::InputMethodQuery query) const
5244 return QGraphicsRectItem::inputMethodQuery(query);
5247 QVariant itemChange(GraphicsItemChange change, const QVariant &value)
5249 // deletion not supported
5250 return QGraphicsRectItem::itemChange(change, value);
5253 void keyPressEvent(QKeyEvent *)
5255 if (harakiri == 9) {
5261 void keyReleaseEvent(QKeyEvent *)
5263 if (harakiri == 10) {
5269 void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *)
5271 if (harakiri == 11) {
5277 void mouseMoveEvent(QGraphicsSceneMouseEvent *)
5279 if (harakiri == 12) {
5285 void mousePressEvent(QGraphicsSceneMouseEvent *)
5287 if (harakiri == 13) {
5293 void mouseReleaseEvent(QGraphicsSceneMouseEvent *)
5295 if (harakiri == 14) {
5301 bool sceneEvent(QEvent *event)
5303 // deletion not supported
5304 return QGraphicsRectItem::sceneEvent(event);
5307 bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
5309 // deletion not supported
5310 return QGraphicsRectItem::sceneEventFilter(watched, event);
5313 void wheelEvent(QGraphicsSceneWheelEvent *)
5315 if (harakiri == 16) {
5325 int HarakiriItem::dead;
5327 void tst_QGraphicsItem::deleteItemInEventHandlers()
5329 for (int i = 0; i < 17; ++i) {
5330 QGraphicsScene scene;
5331 HarakiriItem *item = new HarakiriItem(i);
5332 item->setAcceptsHoverEvents(true);
5333 item->setFlag(QGraphicsItem::ItemIsFocusable);
5335 scene.addItem(item);
5337 item->installSceneEventFilter(item); // <- ehey!
5339 QGraphicsView view(&scene);
5342 qApp->processEvents();
5343 qApp->processEvents();
5349 QContextMenuEvent event(QContextMenuEvent::Other,
5350 view.mapFromScene(item->scenePos()));
5351 QCoreApplication::sendEvent(view.viewport(), &event);
5354 QTest::mouseMove(view.viewport(), view.mapFromScene(item->scenePos()));
5356 QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos()));
5358 QTest::mouseDClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(item->scenePos()));
5360 QTest::mouseClick(view.viewport(), Qt::RightButton, 0, view.mapFromScene(item->scenePos()));
5362 QTest::mouseMove(view.viewport(), view.mapFromScene(item->scenePos() + QPointF(20, -20)));
5370 QTest::keyPress(view.viewport(), Qt::Key_A);
5372 QTest::keyRelease(view.viewport(), Qt::Key_A);
5374 QTest::keyPress(view.viewport(), Qt::Key_A);
5376 QTest::keyRelease(view.viewport(), Qt::Key_A);
5380 class ItemPaintsOutsideShape : public QGraphicsItem
5383 QRectF boundingRect() const
5385 return QRectF(0, 0, 100, 100);
5388 void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
5390 painter->fillRect(-50, -50, 200, 200, Qt::red);
5391 painter->fillRect(0, 0, 100, 100, Qt::blue);
5395 void tst_QGraphicsItem::itemClipsToShape()
5397 QGraphicsItem *clippedItem = new ItemPaintsOutsideShape;
5398 clippedItem->setFlag(QGraphicsItem::ItemClipsToShape);
5400 QGraphicsItem *unclippedItem = new ItemPaintsOutsideShape;
5401 unclippedItem->setPos(200, 0);
5403 QGraphicsScene scene(-50, -50, 400, 200);
5404 scene.addItem(clippedItem);
5405 scene.addItem(unclippedItem);
5407 QImage image(400, 200, QImage::Format_ARGB32_Premultiplied);
5409 QPainter painter(&image);
5410 painter.setRenderHint(QPainter::Antialiasing);
5411 scene.render(&painter);
5414 QCOMPARE(image.pixel(45, 100), QRgb(0));
5415 QCOMPARE(image.pixel(100, 45), QRgb(0));
5416 QCOMPARE(image.pixel(155, 100), QRgb(0));
5417 QCOMPARE(image.pixel(45, 155), QRgb(0));
5418 QCOMPARE(image.pixel(55, 100), QColor(Qt::blue).rgba());
5419 QCOMPARE(image.pixel(100, 55), QColor(Qt::blue).rgba());
5420 QCOMPARE(image.pixel(145, 100), QColor(Qt::blue).rgba());
5421 QCOMPARE(image.pixel(55, 145), QColor(Qt::blue).rgba());
5422 QCOMPARE(image.pixel(245, 100), QColor(Qt::red).rgba());
5423 QCOMPARE(image.pixel(300, 45), QColor(Qt::red).rgba());
5424 QCOMPARE(image.pixel(355, 100), QColor(Qt::red).rgba());
5425 QCOMPARE(image.pixel(245, 155), QColor(Qt::red).rgba());
5426 QCOMPARE(image.pixel(255, 100), QColor(Qt::blue).rgba());
5427 QCOMPARE(image.pixel(300, 55), QColor(Qt::blue).rgba());
5428 QCOMPARE(image.pixel(345, 100), QColor(Qt::blue).rgba());
5429 QCOMPARE(image.pixel(255, 145), QColor(Qt::blue).rgba());
5432 void tst_QGraphicsItem::itemClipsChildrenToShape()
5434 QGraphicsScene scene;
5435 QGraphicsItem *rect = scene.addRect(0, 0, 50, 50, QPen(Qt::NoPen), QBrush(Qt::yellow));
5437 QGraphicsItem *ellipse = scene.addEllipse(0, 0, 100, 100, QPen(Qt::NoPen), QBrush(Qt::green));
5438 ellipse->setParentItem(rect);
5440 QGraphicsItem *clippedEllipse = scene.addEllipse(0, 0, 50, 50, QPen(Qt::NoPen), QBrush(Qt::blue));
5441 clippedEllipse->setParentItem(ellipse);
5443 QGraphicsItem *clippedEllipse2 = scene.addEllipse(0, 0, 25, 25, QPen(Qt::NoPen), QBrush(Qt::red));
5444 clippedEllipse2->setParentItem(clippedEllipse);
5446 QGraphicsItem *clippedEllipse3 = scene.addEllipse(50, 50, 25, 25, QPen(Qt::NoPen), QBrush(Qt::red));
5447 clippedEllipse3->setParentItem(clippedEllipse);
5449 QVERIFY(!(ellipse->flags() & QGraphicsItem::ItemClipsChildrenToShape));
5450 ellipse->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5451 QVERIFY((ellipse->flags() & QGraphicsItem::ItemClipsChildrenToShape));
5453 QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
5455 QPainter painter(&image);
5456 painter.setRenderHint(QPainter::Antialiasing);
5457 scene.render(&painter);
5460 QCOMPARE(image.pixel(16, 16), QColor(255, 0, 0).rgba());
5461 QCOMPARE(image.pixel(32, 32), QColor(0, 0, 255).rgba());
5462 QCOMPARE(image.pixel(50, 50), QColor(0, 255, 0).rgba());
5463 QCOMPARE(image.pixel(12, 12), QColor(255, 255, 0).rgba());
5464 QCOMPARE(image.pixel(60, 60), QColor(255, 0, 0).rgba());
5467 void tst_QGraphicsItem::itemClipsChildrenToShape2()
5469 QGraphicsRectItem *parent = new QGraphicsRectItem(QRectF(0, 0, 10, 10));
5470 QGraphicsEllipseItem *child1 = new QGraphicsEllipseItem(QRectF(50, 50, 100, 100));
5471 QGraphicsRectItem *child2 = new QGraphicsRectItem(QRectF(15, 15, 80, 80));
5473 child1->setParentItem(parent);
5474 child1->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5475 child2->setParentItem(child1);
5477 parent->setBrush(Qt::blue);
5478 child1->setBrush(Qt::green);
5479 child2->setBrush(Qt::red);
5481 QGraphicsScene scene;
5482 scene.addItem(parent);
5484 QCOMPARE(scene.itemAt(5, 5), (QGraphicsItem *)parent);
5485 QCOMPARE(scene.itemAt(15, 5), (QGraphicsItem *)0);
5486 QCOMPARE(scene.itemAt(5, 15), (QGraphicsItem *)0);
5487 QCOMPARE(scene.itemAt(60, 60), (QGraphicsItem *)0);
5488 QCOMPARE(scene.itemAt(140, 60), (QGraphicsItem *)0);
5489 QCOMPARE(scene.itemAt(60, 140), (QGraphicsItem *)0);
5490 QCOMPARE(scene.itemAt(140, 140), (QGraphicsItem *)0);
5491 QCOMPARE(scene.itemAt(75, 75), (QGraphicsItem *)child2);
5492 QCOMPARE(scene.itemAt(75, 100), (QGraphicsItem *)child1);
5493 QCOMPARE(scene.itemAt(100, 75), (QGraphicsItem *)child1);
5496 QImage image(100, 100, QImage::Format_ARGB32_Premultiplied);
5498 QPainter painter(&image);
5499 scene.render(&painter);
5502 QCOMPARE(image.pixel(5, 5), QColor(0, 0, 255).rgba());
5503 QCOMPARE(image.pixel(5, 10), QRgb(0));
5504 QCOMPARE(image.pixel(10, 5), QRgb(0));
5505 QCOMPARE(image.pixel(40, 40), QRgb(0));
5506 QCOMPARE(image.pixel(90, 40), QRgb(0));
5507 QCOMPARE(image.pixel(40, 90), QRgb(0));
5508 QCOMPARE(image.pixel(95, 95), QRgb(0));
5509 QCOMPARE(image.pixel(50, 70), QColor(0, 255, 0).rgba());
5510 QCOMPARE(image.pixel(70, 50), QColor(0, 255, 0).rgba());
5511 QCOMPARE(image.pixel(50, 60), QColor(255, 0, 0).rgba());
5512 QCOMPARE(image.pixel(60, 50), QColor(255, 0, 0).rgba());
5514 QGraphicsView view(&scene);
5520 void tst_QGraphicsItem::itemClipsChildrenToShape3()
5522 // Construct a scene with nested children, each 50 pixels offset from the elder.
5523 // Set a top-level clipping flag
5524 QGraphicsScene scene;
5525 QGraphicsRectItem *parent = scene.addRect( 0, 0, 150, 150 );
5526 QGraphicsRectItem *child = scene.addRect( 0, 0, 150, 150 );
5527 QGraphicsRectItem *grandchild = scene.addRect( 0, 0, 150, 150 );
5528 child->setParentItem(parent);
5529 grandchild->setParentItem(child);
5530 child->setPos( 50, 50 );
5531 grandchild->setPos( 50, 50 );
5532 parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5534 QCOMPARE(scene.itemAt(25,25), (QGraphicsItem *)parent);
5535 QCOMPARE(scene.itemAt(75,75), (QGraphicsItem *)child);
5536 QCOMPARE(scene.itemAt(125,125), (QGraphicsItem *)grandchild);
5537 QCOMPARE(scene.itemAt(175,175), (QGraphicsItem *)0);
5539 // Move child to fully overlap the parent. The grandchild should
5540 // now occupy two-thirds of the scene
5541 child->prepareGeometryChange();
5542 child->setPos( 0, 0 );
5544 QCOMPARE(scene.itemAt(25,25), (QGraphicsItem *)child);
5545 QCOMPARE(scene.itemAt(75,75), (QGraphicsItem *)grandchild);
5546 QCOMPARE(scene.itemAt(125,125), (QGraphicsItem *)grandchild);
5547 QCOMPARE(scene.itemAt(175,175), (QGraphicsItem *)0);
5550 class MyProxyWidget : public QGraphicsProxyWidget
5553 MyProxyWidget(QGraphicsItem *parent) : QGraphicsProxyWidget(parent)
5558 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
5560 QGraphicsProxyWidget::paint(painter, option, widget);
5566 void tst_QGraphicsItem::itemClipsChildrenToShape4()
5568 QGraphicsScene scene;
5569 QGraphicsView view(&scene);
5571 QGraphicsWidget * outerWidget = new QGraphicsWidget();
5572 outerWidget->setFlag(QGraphicsItem::ItemClipsChildrenToShape, true);
5573 MyProxyWidget * innerWidget = new MyProxyWidget(outerWidget);
5574 QLabel * label = new QLabel();
5575 label->setText("Welcome back my friends to the show that never ends...");
5576 innerWidget->setWidget(label);
5577 view.resize(300, 300);
5578 scene.addItem(outerWidget);
5579 outerWidget->resize( 200, 100 );
5580 scene.addEllipse( 100, 100, 100, 50 ); // <-- this is important to trigger the right codepath*
5581 //now the label is shown
5582 outerWidget->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false );
5583 QApplication::setActiveWindow(&view);
5585 QTRY_COMPARE(QApplication::activeWindow(), (QWidget *)&view);
5586 QTRY_COMPARE(innerWidget->painted, true);
5589 //#define DEBUG_ITEM_CLIPS_CHILDREN_TO_SHAPE_5
5590 static inline void renderSceneToImage(QGraphicsScene *scene, QImage *image, const QString &filename)
5593 QPainter painter(image);
5594 scene->render(&painter);
5596 #ifdef DEBUG_ITEM_CLIPS_CHILDREN_TO_SHAPE_5
5597 image->save(filename);
5603 void tst_QGraphicsItem::itemClipsChildrenToShape5()
5605 class ParentItem : public QGraphicsRectItem
5608 ParentItem(qreal x, qreal y, qreal width, qreal height)
5609 : QGraphicsRectItem(x, y, width, height) {}
5611 QPainterPath shape() const
5614 path.addRect(50, 50, 200, 200);
5619 ParentItem *parent = new ParentItem(0, 0, 300, 300);
5620 parent->setBrush(Qt::blue);
5621 parent->setOpacity(0.5);
5623 const QRegion parentRegion(0, 0, 300, 300);
5624 const QRegion clippedParentRegion = parentRegion & QRect(50, 50, 200, 200);
5625 QRegion childRegion;
5626 QRegion grandChildRegion;
5628 QGraphicsRectItem *topLeftChild = new QGraphicsRectItem(0, 0, 100, 100);
5629 topLeftChild->setBrush(Qt::red);
5630 topLeftChild->setParentItem(parent);
5631 childRegion += QRect(0, 0, 100, 100);
5633 QGraphicsRectItem *topRightChild = new QGraphicsRectItem(0, 0, 100, 100);
5634 topRightChild->setBrush(Qt::red);
5635 topRightChild->setParentItem(parent);
5636 topRightChild->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5637 topRightChild->setPos(200, 0);
5638 childRegion += QRect(200, 0, 100, 100);
5640 QGraphicsRectItem *topRightGrandChild = new QGraphicsRectItem(0, 0, 100, 100);
5641 topRightGrandChild->setBrush(Qt::green);
5642 topRightGrandChild->setParentItem(topRightChild);
5643 topRightGrandChild->setPos(-40, 40);
5644 grandChildRegion += QRect(200 - 40, 0 + 40, 100, 100) & QRect(200, 0, 100, 100);
5646 QGraphicsRectItem *bottomLeftChild = new QGraphicsRectItem(0, 0, 100, 100);
5647 bottomLeftChild->setBrush(Qt::red);
5648 bottomLeftChild->setParentItem(parent);
5649 bottomLeftChild->setFlag(QGraphicsItem::ItemClipsToShape);
5650 bottomLeftChild->setPos(0, 200);
5651 childRegion += QRect(0, 200, 100, 100);
5653 QGraphicsRectItem *bottomLeftGrandChild = new QGraphicsRectItem(0, 0, 160, 160);
5654 bottomLeftGrandChild->setBrush(Qt::green);
5655 bottomLeftGrandChild->setParentItem(bottomLeftChild);
5656 bottomLeftGrandChild->setFlag(QGraphicsItem::ItemClipsToShape);
5657 bottomLeftGrandChild->setPos(0, -60);
5658 grandChildRegion += QRect(0, 200 - 60, 160, 160);
5660 QGraphicsRectItem *bottomRightChild = new QGraphicsRectItem(0, 0, 100, 100);
5661 bottomRightChild->setBrush(Qt::red);
5662 bottomRightChild->setParentItem(parent);
5663 bottomRightChild->setPos(200, 200);
5664 childRegion += QRect(200, 200, 100, 100);
5666 QPoint controlPoints[17] = {
5667 QPoint(5, 5) , QPoint(95, 5) , QPoint(205, 5) , QPoint(295, 5) ,
5668 QPoint(5, 95) , QPoint(95, 95) , QPoint(205, 95) , QPoint(295, 95) ,
5670 QPoint(5, 205), QPoint(95, 205), QPoint(205, 205), QPoint(295, 205),
5671 QPoint(5, 295), QPoint(95, 295), QPoint(205, 295), QPoint(295, 295),
5674 const QRegion clippedChildRegion = childRegion & QRect(50, 50, 200, 200);
5675 const QRegion clippedGrandChildRegion = grandChildRegion & QRect(50, 50, 200, 200);
5677 QGraphicsScene scene;
5678 scene.addItem(parent);
5679 QImage sceneImage(300, 300, QImage::Format_ARGB32);
5681 #define VERIFY_CONTROL_POINTS(pRegion, cRegion, gRegion) \
5682 for (int i = 0; i < 17; ++i) { \
5683 QPoint controlPoint = controlPoints[i]; \
5684 QRgb pixel = sceneImage.pixel(controlPoint.x(), controlPoint.y()); \
5685 if (pRegion.contains(controlPoint)) \
5686 QVERIFY(qBlue(pixel) != 0); \
5688 QVERIFY(qBlue(pixel) == 0); \
5689 if (cRegion.contains(controlPoint)) \
5690 QVERIFY(qRed(pixel) != 0); \
5692 QVERIFY(qRed(pixel) == 0); \
5693 if (gRegion.contains(controlPoint)) \
5694 QVERIFY(qGreen(pixel) != 0); \
5696 QVERIFY(qGreen(pixel) == 0); \
5699 const QList<QGraphicsItem *> children = parent->childItems();
5700 const int childrenCount = children.count();
5702 for (int i = 0; i < 5; ++i) {
5704 QString childString;
5707 // All children stacked in front.
5708 childString = QLatin1String("ChildrenInFront.png");
5709 foreach (QGraphicsItem *child, children)
5710 child->setFlag(QGraphicsItem::ItemStacksBehindParent, false);
5713 // All children stacked behind.
5714 childString = QLatin1String("ChildrenBehind.png");
5715 foreach (QGraphicsItem *child, children)
5716 child->setFlag(QGraphicsItem::ItemStacksBehindParent, true);
5719 // First half of the children behind, second half in front.
5720 childString = QLatin1String("FirstHalfBehind_SecondHalfInFront.png");
5721 for (int j = 0; j < childrenCount; ++j) {
5722 QGraphicsItem *child = children.at(j);
5723 child->setFlag(QGraphicsItem::ItemStacksBehindParent, (j < childrenCount / 2));
5727 // First half of the children in front, second half behind.
5728 childString = QLatin1String("FirstHalfInFront_SecondHalfBehind.png");
5729 for (int j = 0; j < childrenCount; ++j) {
5730 QGraphicsItem *child = children.at(j);
5731 child->setFlag(QGraphicsItem::ItemStacksBehindParent, (j >= childrenCount / 2));
5735 // Child2 and child4 behind, rest in front.
5736 childString = QLatin1String("Child2And4Behind_RestInFront.png");
5737 for (int j = 0; j < childrenCount; ++j) {
5738 QGraphicsItem *child = children.at(j);
5739 if (j == 1 || j == 3)
5740 child->setFlag(QGraphicsItem::ItemStacksBehindParent, true);
5742 child->setFlag(QGraphicsItem::ItemStacksBehindParent, false);
5746 qFatal("internal error");
5749 // Nothing is clipped.
5750 parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
5751 parent->setFlag(QGraphicsItem::ItemClipsToShape, false);
5752 clipString = QLatin1String("nothingClipped_");
5753 renderSceneToImage(&scene, &sceneImage, clipString + childString);
5754 VERIFY_CONTROL_POINTS(parentRegion, childRegion, grandChildRegion);
5756 // Parent clips children to shape.
5757 parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5758 clipString = QLatin1String("parentClipsChildrenToShape_");
5759 renderSceneToImage(&scene, &sceneImage, clipString + childString);
5760 VERIFY_CONTROL_POINTS(parentRegion, clippedChildRegion, clippedGrandChildRegion);
5762 // Parent clips itself and children to shape.
5763 parent->setFlag(QGraphicsItem::ItemClipsToShape);
5764 clipString = QLatin1String("parentClipsItselfAndChildrenToShape_");
5765 renderSceneToImage(&scene, &sceneImage, clipString + childString);
5766 VERIFY_CONTROL_POINTS(clippedParentRegion, clippedChildRegion, clippedGrandChildRegion);
5768 // Parent clips itself to shape.
5769 parent->setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
5770 clipString = QLatin1String("parentClipsItselfToShape_");
5771 renderSceneToImage(&scene, &sceneImage, clipString + childString);
5772 VERIFY_CONTROL_POINTS(clippedParentRegion, childRegion, grandChildRegion);
5776 void tst_QGraphicsItem::itemClipsTextChildToShape()
5778 // Construct a scene with a rect that clips its children, with one text
5779 // child that has text that exceeds the size of the rect.
5780 QGraphicsScene scene;
5781 QGraphicsItem *rect = scene.addRect(0, 0, 50, 50, QPen(Qt::black), Qt::black);
5782 rect->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5783 QGraphicsTextItem *text = new QGraphicsTextItem("This is a long sentence that's wider than 50 pixels.");
5784 text->setParentItem(rect);
5786 // Render this scene to a transparent image.
5787 QRectF sr = scene.itemsBoundingRect();
5788 QImage image(sr.size().toSize(), QImage::Format_ARGB32_Premultiplied);
5790 QPainter painter(&image);
5791 scene.render(&painter);
5793 // Erase the area immediately underneath the rect.
5794 painter.setCompositionMode(QPainter::CompositionMode_Source);
5795 painter.fillRect(rect->sceneBoundingRect().translated(-sr.topLeft()).adjusted(-0.5, -0.5, 0.5, 0.5),
5799 // Check that you get a truly transparent image back (i.e., the text was
5800 // clipped away, so there should be no trails left after erasing only the
5802 QImage emptyImage(scene.itemsBoundingRect().size().toSize(), QImage::Format_ARGB32_Premultiplied);
5804 QCOMPARE(image, emptyImage);
5807 void tst_QGraphicsItem::itemClippingDiscovery()
5809 // A simple scene with an ellipse parent and two rect children, one a
5810 // child of the other.
5811 QGraphicsScene scene;
5812 QGraphicsEllipseItem *clipItem = scene.addEllipse(0, 0, 100, 100);
5813 QGraphicsRectItem *leftRectItem = scene.addRect(0, 0, 50, 100);
5814 QGraphicsRectItem *rightRectItem = scene.addRect(50, 0, 50, 100);
5815 leftRectItem->setParentItem(clipItem);
5816 rightRectItem->setParentItem(clipItem);
5818 // The rects item are both visible at these points.
5819 QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)leftRectItem);
5820 QCOMPARE(scene.itemAt(90, 90), (QGraphicsItem *)rightRectItem);
5822 // The ellipse clips the rects now.
5823 clipItem->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
5825 // The rect items are no longer visible at these points.
5826 QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0);
5827 if (sizeof(qreal) != sizeof(double))
5828 QSKIP("This fails due to internal rounding errors");
5829 QCOMPARE(scene.itemAt(90, 90), (QGraphicsItem *)0);
5832 void tst_QGraphicsItem::ancestorFlags()
5834 QGraphicsItem *level1 = new QGraphicsRectItem;
5835 QGraphicsItem *level21 = new QGraphicsRectItem;
5836 level21->setParentItem(level1);
5837 QGraphicsItem *level22 = new QGraphicsRectItem;
5838 level22->setParentItem(level1);
5839 QGraphicsItem *level31 = new QGraphicsRectItem;
5840 level31->setParentItem(level21);
5841 QGraphicsItem *level32 = new QGraphicsRectItem;
5842 level32->setParentItem(level21);
5844 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5845 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5846 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5847 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
5848 QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
5850 // HandlesChildEvents: 1) Root level sets a flag
5851 level1->setHandlesChildEvents(true);
5852 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5853 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5854 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5855 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5856 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5858 // HandlesChildEvents: 2) Root level set it again
5859 level1->setHandlesChildEvents(true);
5860 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5861 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5862 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5863 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5864 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5866 // HandlesChildEvents: 3) Root level unsets a flag
5867 level1->setHandlesChildEvents(false);
5868 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5869 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5870 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5871 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
5872 QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
5874 // HandlesChildEvents: 4) Child item sets a flag
5875 level21->setHandlesChildEvents(true);
5876 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5877 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5878 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5879 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5880 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5882 // HandlesChildEvents: 5) Parent item sets a flag
5883 level1->setHandlesChildEvents(true);
5884 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5885 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5886 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5887 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5888 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5890 // HandlesChildEvents: 6) Child item unsets a flag
5891 level21->setHandlesChildEvents(false);
5892 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5893 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5894 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5895 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5896 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5898 // HandlesChildEvents: 7) Parent item unsets a flag
5899 level21->setHandlesChildEvents(true);
5900 level1->setHandlesChildEvents(false);
5901 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5902 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5903 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5904 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5905 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5907 // Reparent the child to root
5908 level21->setParentItem(0);
5909 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5910 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5911 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5912 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5914 // Reparent the child to level1 again.
5915 level1->setHandlesChildEvents(true);
5916 level21->setParentItem(level1);
5917 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5918 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5919 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5920 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5921 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5923 // Reparenting level31 back to level1.
5924 level31->setParentItem(level1);
5925 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5926 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5927 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5928 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5929 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5931 // Reparenting level31 back to level21.
5932 level31->setParentItem(0);
5933 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
5934 level31->setParentItem(level21);
5935 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5936 QCOMPARE(int(level21->d_ptr->ancestorFlags), 1);
5937 QCOMPARE(int(level22->d_ptr->ancestorFlags), 1);
5938 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5939 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5941 // Level1 doesn't handle child events
5942 level1->setHandlesChildEvents(false);
5943 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5944 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5945 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5946 QCOMPARE(int(level31->d_ptr->ancestorFlags), 1);
5947 QCOMPARE(int(level32->d_ptr->ancestorFlags), 1);
5949 // Nobody handles child events
5950 level21->setHandlesChildEvents(false);
5952 for (int i = 0; i < 2; ++i) {
5953 QGraphicsItem::GraphicsItemFlag flag = !i ? QGraphicsItem::ItemClipsChildrenToShape
5954 : QGraphicsItem::ItemIgnoresTransformations;
5955 int ancestorFlag = !i ? QGraphicsItemPrivate::AncestorClipsChildren
5956 : QGraphicsItemPrivate::AncestorIgnoresTransformations;
5958 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5959 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5960 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5961 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
5962 QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
5964 // HandlesChildEvents: 1) Root level sets a flag
5965 level1->setFlag(flag, true);
5966 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5967 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
5968 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
5969 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
5970 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
5972 // HandlesChildEvents: 2) Root level set it again
5973 level1->setFlag(flag, true);
5974 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5975 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
5976 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
5977 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
5978 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
5980 // HandlesChildEvents: 3) Root level unsets a flag
5981 level1->setFlag(flag, false);
5982 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5983 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5984 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5985 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
5986 QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
5988 // HandlesChildEvents: 4) Child item sets a flag
5989 level21->setFlag(flag, true);
5990 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5991 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
5992 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
5993 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
5994 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
5996 // HandlesChildEvents: 5) Parent item sets a flag
5997 level1->setFlag(flag, true);
5998 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
5999 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
6000 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
6001 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6002 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6004 // HandlesChildEvents: 6) Child item unsets a flag
6005 level21->setFlag(flag, false);
6006 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6007 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
6008 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
6009 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6010 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6012 // HandlesChildEvents: 7) Parent item unsets a flag
6013 level21->setFlag(flag, true);
6014 level1->setFlag(flag, false);
6015 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6016 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
6017 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
6018 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6019 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6021 // Reparent the child to root
6022 level21->setParentItem(0);
6023 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
6024 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
6025 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6026 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6028 // Reparent the child to level1 again.
6029 level1->setFlag(flag, true);
6030 level21->setParentItem(level1);
6031 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6032 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
6033 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
6034 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6035 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6037 // Reparenting level31 back to level1.
6038 level31->setParentItem(level1);
6039 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6040 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
6041 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
6042 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6043 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6045 // Reparenting level31 back to level21.
6046 level31->setParentItem(0);
6047 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
6048 level31->setParentItem(level21);
6049 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6050 QCOMPARE(int(level21->d_ptr->ancestorFlags), ancestorFlag);
6051 QCOMPARE(int(level22->d_ptr->ancestorFlags), ancestorFlag);
6052 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6053 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6055 // Level1 doesn't handle child events
6056 level1->setFlag(flag, false);
6057 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6058 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
6059 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
6060 QCOMPARE(int(level31->d_ptr->ancestorFlags), ancestorFlag);
6061 QCOMPARE(int(level32->d_ptr->ancestorFlags), ancestorFlag);
6063 // Nobody handles child events
6064 level21->setFlag(flag, false);
6065 QCOMPARE(int(level1->d_ptr->ancestorFlags), 0);
6066 QCOMPARE(int(level21->d_ptr->ancestorFlags), 0);
6067 QCOMPARE(int(level22->d_ptr->ancestorFlags), 0);
6068 QCOMPARE(int(level31->d_ptr->ancestorFlags), 0);
6069 QCOMPARE(int(level32->d_ptr->ancestorFlags), 0);
6075 void tst_QGraphicsItem::untransformable()
6077 QGraphicsItem *item1 = new QGraphicsEllipseItem(QRectF(-50, -50, 100, 100));
6078 item1->setZValue(1);
6079 item1->setFlag(QGraphicsItem::ItemIgnoresTransformations);
6081 ((QGraphicsEllipseItem *)item1)->setBrush(Qt::red);
6083 QGraphicsItem *item2 = new QGraphicsEllipseItem(QRectF(-50, -50, 100, 100));
6084 item2->setParentItem(item1);
6086 item2->setPos(100, 0);
6087 ((QGraphicsEllipseItem *)item2)->setBrush(Qt::green);
6089 QGraphicsItem *item3 = new QGraphicsEllipseItem(QRectF(-50, -50, 100, 100));
6090 item3->setParentItem(item2);
6091 item3->setPos(100, 0);
6092 ((QGraphicsEllipseItem *)item3)->setBrush(Qt::blue);
6094 QGraphicsScene scene(-500, -500, 1000, 1000);
6095 scene.addItem(item1);
6098 QGraphicsView view(&scene,&topLevel);
6099 view.resize(300, 300);
6102 view.centerOn(0, 0);
6104 // Painting with the DiagCrossPattern is really slow on Mac
6105 // when zoomed out. (The test times out). Task to fix is 155567.
6106 #if !defined(Q_WS_MAC) || 1
6107 view.setBackgroundBrush(QBrush(Qt::black, Qt::DiagCrossPattern));
6110 QTest::qWaitForWindowShown(&view);
6112 for (int i = 0; i < 10; ++i) {
6113 QPoint center = view.viewport()->rect().center();
6114 QCOMPARE(view.itemAt(center), item1);
6115 QCOMPARE(view.itemAt(center - QPoint(40, 0)), item1);
6116 QCOMPARE(view.itemAt(center - QPoint(-40, 0)), item1);
6117 QCOMPARE(view.itemAt(center - QPoint(0, 40)), item1);
6118 QCOMPARE(view.itemAt(center - QPoint(0, -40)), item1);
6120 center += QPoint(70, 70);
6121 QCOMPARE(view.itemAt(center - QPoint(40, 0)), item2);
6122 QCOMPARE(view.itemAt(center - QPoint(-40, 0)), item2);
6123 QCOMPARE(view.itemAt(center - QPoint(0, 40)), item2);
6124 QCOMPARE(view.itemAt(center - QPoint(0, -40)), item2);
6126 center += QPoint(0, 100);
6127 QCOMPARE(view.itemAt(center - QPoint(40, 0)), item3);
6128 QCOMPARE(view.itemAt(center - QPoint(-40, 0)), item3);
6129 QCOMPARE(view.itemAt(center - QPoint(0, 40)), item3);
6130 QCOMPARE(view.itemAt(center - QPoint(0, -40)), item3);
6132 view.scale(0.5, 0.5);
6134 view.shear(qreal(0.01), qreal(0.01));
6135 view.translate(10, 10);
6140 class ContextMenuItem : public QGraphicsRectItem
6144 : ignoreEvent(true), gotEvent(false), eventWasAccepted(false)
6148 bool eventWasAccepted;
6150 void contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
6153 eventWasAccepted = event->isAccepted();
6159 void tst_QGraphicsItem::contextMenuEventPropagation()
6161 ContextMenuItem *bottomItem = new ContextMenuItem;
6162 bottomItem->setRect(0, 0, 100, 100);
6163 ContextMenuItem *topItem = new ContextMenuItem;
6164 topItem->setParentItem(bottomItem);
6165 topItem->setRect(0, 0, 100, 100);
6167 QGraphicsScene scene;
6169 QGraphicsView view(&scene);
6170 view.setAlignment(Qt::AlignLeft | Qt::AlignTop);
6172 view.resize(200, 200);
6173 QTest::qWaitForWindowShown(&view);
6176 QContextMenuEvent event(QContextMenuEvent::Mouse, QPoint(10, 10),
6177 view.viewport()->mapToGlobal(QPoint(10, 10)));
6179 QApplication::sendEvent(view.viewport(), &event);
6180 QVERIFY(!event.isAccepted());
6182 scene.addItem(bottomItem);
6183 topItem->ignoreEvent = true;
6184 bottomItem->ignoreEvent = true;
6186 QApplication::sendEvent(view.viewport(), &event);
6187 QVERIFY(!event.isAccepted());
6188 QCOMPARE(topItem->gotEvent, true);
6189 QCOMPARE(topItem->eventWasAccepted, true);
6190 QCOMPARE(bottomItem->gotEvent, true);
6191 QCOMPARE(bottomItem->eventWasAccepted, true);
6193 topItem->ignoreEvent = false;
6194 topItem->gotEvent = false;
6195 bottomItem->gotEvent = false;
6197 QApplication::sendEvent(view.viewport(), &event);
6198 QVERIFY(event.isAccepted());
6199 QCOMPARE(topItem->gotEvent, true);
6200 QCOMPARE(bottomItem->gotEvent, false);
6201 QCOMPARE(topItem->eventWasAccepted, true);
6204 void tst_QGraphicsItem::itemIsMovable()
6206 QGraphicsRectItem *rect = new QGraphicsRectItem(-50, -50, 100, 100);
6207 rect->setFlag(QGraphicsItem::ItemIsMovable);
6209 QGraphicsScene scene;
6210 scene.addItem(rect);
6213 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
6214 event.setButton(Qt::LeftButton);
6215 event.setButtons(Qt::LeftButton);
6216 qApp->sendEvent(&scene, &event);
6219 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
6220 event.setButton(Qt::LeftButton);
6221 event.setButtons(Qt::LeftButton);
6222 qApp->sendEvent(&scene, &event);
6224 QCOMPARE(rect->pos(), QPointF(0, 0));
6226 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
6227 event.setButtons(Qt::LeftButton);
6228 event.setScenePos(QPointF(10, 10));
6229 qApp->sendEvent(&scene, &event);
6231 QCOMPARE(rect->pos(), QPointF(10, 10));
6233 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
6234 event.setButtons(Qt::RightButton);
6235 event.setScenePos(QPointF(20, 20));
6236 qApp->sendEvent(&scene, &event);
6238 QCOMPARE(rect->pos(), QPointF(10, 10));
6240 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseMove);
6241 event.setButtons(Qt::LeftButton);
6242 event.setScenePos(QPointF(30, 30));
6243 qApp->sendEvent(&scene, &event);
6245 QCOMPARE(rect->pos(), QPointF(30, 30));
6248 class ItemAddScene : public QGraphicsScene
6254 QTimer::singleShot(500, this, SLOT(newTextItem()));
6261 QGraphicsItem *item = new QGraphicsTextItem("This item will not ensure that it's visible", 0, this);
6262 item->setPos(.0, .0);
6267 void tst_QGraphicsItem::task141694_textItemEnsureVisible()
6270 scene.setSceneRect(-1000, -1000, 2000, 2000);
6272 QGraphicsView view(&scene);
6273 view.setFixedSize(200, 200);
6275 QTest::qWaitForWindowShown(&view);
6277 view.ensureVisible(-1000, -1000, 5, 5);
6278 int hscroll = view.horizontalScrollBar()->value();
6279 int vscroll = view.verticalScrollBar()->value();
6283 // This should not cause the view to scroll
6284 QTRY_COMPARE(view.horizontalScrollBar()->value(), hscroll);
6285 QCOMPARE(view.verticalScrollBar()->value(), vscroll);
6288 void tst_QGraphicsItem::task128696_textItemEnsureMovable()
6290 QGraphicsTextItem *item = new QGraphicsTextItem;
6291 item->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
6292 item->setTextInteractionFlags(Qt::TextEditorInteraction);
6293 item->setPlainText("abc de\nf ghi\n j k l");
6295 QGraphicsScene scene;
6296 scene.setSceneRect(-100, -100, 200, 200);
6297 scene.addItem(item);
6299 QGraphicsView view(&scene);
6300 view.setFixedSize(200, 200);
6303 QGraphicsSceneMouseEvent event1(QEvent::GraphicsSceneMousePress);
6304 event1.setScenePos(QPointF(0, 0));
6305 event1.setButton(Qt::LeftButton);
6306 event1.setButtons(Qt::LeftButton);
6307 QApplication::sendEvent(&scene, &event1);
6308 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
6310 QGraphicsSceneMouseEvent event2(QEvent::GraphicsSceneMouseMove);
6311 event2.setScenePos(QPointF(10, 10));
6312 event2.setButton(Qt::LeftButton);
6313 event2.setButtons(Qt::LeftButton);
6314 QApplication::sendEvent(&scene, &event2);
6315 QCOMPARE(item->pos(), QPointF(10, 10));
6318 void tst_QGraphicsItem::task177918_lineItemUndetected()
6320 QGraphicsScene scene;
6321 QGraphicsLineItem *line = scene.addLine(10, 10, 10, 10);
6322 QCOMPARE(line->boundingRect(), QRectF(10, 10, 0, 0));
6324 QVERIFY(!scene.items(9, 9, 2, 2, Qt::IntersectsItemShape).isEmpty());
6325 QVERIFY(!scene.items(9, 9, 2, 2, Qt::ContainsItemShape).isEmpty());
6326 QVERIFY(!scene.items(9, 9, 2, 2, Qt::IntersectsItemBoundingRect).isEmpty());
6327 QVERIFY(!scene.items(9, 9, 2, 2, Qt::ContainsItemBoundingRect).isEmpty());
6330 void tst_QGraphicsItem::task240400_clickOnTextItem_data()
6332 QTest::addColumn<int>("flags");
6333 QTest::addColumn<int>("textFlags");
6334 QTest::newRow("editor, noflags") << 0 << int(Qt::TextEditorInteraction);
6335 QTest::newRow("editor, movable") << int(QGraphicsItem::ItemIsMovable) << int(Qt::TextEditorInteraction);
6336 QTest::newRow("editor, selectable") << int(QGraphicsItem::ItemIsSelectable) << int(Qt::TextEditorInteraction);
6337 QTest::newRow("editor, movable | selectable") << int(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable)
6338 << int(Qt::TextEditorInteraction);
6339 QTest::newRow("noninteractive, noflags") << 0 << int(Qt::NoTextInteraction);
6340 QTest::newRow("noninteractive, movable") << int(QGraphicsItem::ItemIsMovable) << int(Qt::NoTextInteraction);
6341 QTest::newRow("noninteractive, selectable") << int(QGraphicsItem::ItemIsSelectable) << int(Qt::NoTextInteraction);
6342 QTest::newRow("noninteractive, movable | selectable") << int(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable)
6343 << int(Qt::NoTextInteraction);
6346 void tst_QGraphicsItem::task240400_clickOnTextItem()
6349 QFETCH(int, textFlags);
6351 QGraphicsScene scene;
6352 QEvent activate(QEvent::WindowActivate);
6353 QApplication::sendEvent(&scene, &activate);
6355 QGraphicsTextItem *item = scene.addText("Hello");
6356 item->setFlags(QGraphicsItem::GraphicsItemFlags(flags));
6357 item->setTextInteractionFlags(Qt::TextInteractionFlags(textFlags));
6358 bool focusable = (item->flags() & QGraphicsItem::ItemIsFocusable);
6359 QVERIFY(textFlags ? focusable : !focusable);
6361 int column = item->textCursor().columnNumber();
6362 QCOMPARE(column, 0);
6364 QVERIFY(!item->hasFocus());
6366 // Click in the top-left corner of the item
6368 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
6369 event.setScenePos(item->sceneBoundingRect().topLeft() + QPointF(0.1, 0.1));
6370 event.setButton(Qt::LeftButton);
6371 event.setButtons(Qt::LeftButton);
6372 QApplication::sendEvent(&scene, &event);
6374 if (flags || textFlags)
6375 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
6377 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
6379 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
6380 event.setScenePos(item->sceneBoundingRect().topLeft() + QPointF(0.1, 0.1));
6381 event.setButton(Qt::LeftButton);
6382 event.setButtons(0);
6383 QApplication::sendEvent(&scene, &event);
6386 QVERIFY(item->hasFocus());
6388 QVERIFY(!item->hasFocus());
6389 QVERIFY(!scene.mouseGrabberItem());
6390 bool selectable = (flags & QGraphicsItem::ItemIsSelectable);
6391 QVERIFY(selectable ? item->isSelected() : !item->isSelected());
6393 // Now click in the middle and check that the cursor moved.
6395 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress);
6396 event.setScenePos(item->sceneBoundingRect().center());
6397 event.setButton(Qt::LeftButton);
6398 event.setButtons(Qt::LeftButton);
6399 QApplication::sendEvent(&scene, &event);
6401 if (flags || textFlags)
6402 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)item);
6404 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *)0);
6406 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease);
6407 event.setScenePos(item->sceneBoundingRect().center());
6408 event.setButton(Qt::LeftButton);
6409 event.setButtons(0);
6410 QApplication::sendEvent(&scene, &event);
6413 QVERIFY(item->hasFocus());
6415 QVERIFY(!item->hasFocus());
6416 QVERIFY(!scene.mouseGrabberItem());
6418 QVERIFY(selectable ? item->isSelected() : !item->isSelected());
6421 if (textFlags & Qt::TextEditorInteraction)
6422 QVERIFY(item->textCursor().columnNumber() > column);
6424 QCOMPARE(item->textCursor().columnNumber(), 0);
6427 class TextItem : public QGraphicsSimpleTextItem
6430 TextItem(const QString& text) : QGraphicsSimpleTextItem(text)
6435 void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget)
6438 QGraphicsSimpleTextItem::paint(painter, option, widget);
6444 void tst_QGraphicsItem::ensureUpdateOnTextItem()
6446 QGraphicsScene scene;
6447 QGraphicsView view(&scene);
6449 QTest::qWaitForWindowShown(&view);
6451 TextItem *text1 = new TextItem(QLatin1String("123"));
6452 scene.addItem(text1);
6453 qApp->processEvents();
6454 QTRY_COMPARE(text1->updates,1);
6456 //same bouding rect but we have to update
6457 text1->setText(QLatin1String("321"));
6458 qApp->processEvents();
6459 QTRY_COMPARE(text1->updates,2);
6462 void tst_QGraphicsItem::task243707_addChildBeforeParent()
6464 // Task reports that adding the child before the parent leads to an
6465 // inconsistent internal state that can cause a crash. This test shows
6467 QGraphicsScene scene;
6468 QGraphicsWidget *widget = new QGraphicsWidget;
6469 QGraphicsWidget *widget2 = new QGraphicsWidget(widget);
6470 scene.addItem(widget2);
6471 QVERIFY(!widget2->parentItem());
6472 scene.addItem(widget);
6473 QVERIFY(!widget->commonAncestorItem(widget2));
6474 QVERIFY(!widget2->commonAncestorItem(widget));
6477 void tst_QGraphicsItem::task197802_childrenVisibility()
6479 QGraphicsScene scene;
6480 QGraphicsRectItem item(QRectF(0,0,20,20));
6482 QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(0,0,10,10), &item);
6483 scene.addItem(&item);
6485 //freshly created: both visible
6486 QVERIFY(item.isVisible());
6487 QVERIFY(item2->isVisible());
6489 //hide child: parent visible, child not
6491 QVERIFY(item.isVisible());
6492 QVERIFY(!item2->isVisible());
6494 //hide parent: parent and child invisible
6496 QVERIFY(!item.isVisible());
6497 QVERIFY(!item2->isVisible());
6499 //ask to show the child: parent and child invisible anyways
6501 QVERIFY(!item.isVisible());
6502 QVERIFY(!item2->isVisible());
6504 //show the parent: both parent and child visible
6506 QVERIFY(item.isVisible());
6507 QVERIFY(item2->isVisible());
6512 void tst_QGraphicsItem::boundingRegion_data()
6514 QTest::addColumn<QLineF>("line");
6515 QTest::addColumn<qreal>("granularity");
6516 QTest::addColumn<QTransform>("transform");
6517 QTest::addColumn<QRegion>("expectedRegion");
6519 QTest::newRow("(0, 0, 10, 10) | 0.0 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 10, 10) << qreal(0.0) << QTransform()
6520 << QRegion(QRect(0, 0, 10, 10));
6524 r += QRect(0, 0, 6, 2);
6525 r += QRect(0, 2, 8, 2);
6526 r += QRect(0, 4, 10, 2);
6527 r += QRect(2, 6, 8, 2);
6528 r += QRect(4, 8, 6, 2);
6529 QTest::newRow("(0, 0, 10, 10) | 0.5 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 10, 10) << qreal(0.5) << QTransform() << r;
6533 r += QRect(0, 0, 4, 1); r += QRect(0, 1, 5, 1); r += QRect(0, 2, 6, 1);
6534 r += QRect(0, 3, 7, 1); r += QRect(1, 4, 7, 1); r += QRect(2, 5, 7, 1);
6535 r += QRect(3, 6, 7, 1); r += QRect(4, 7, 6, 1); r += QRect(5, 8, 5, 1);
6536 r += QRect(6, 9, 4, 1);
6537 QTest::newRow("(0, 0, 10, 10) | 1.0 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 10, 10) << qreal(1.0) << QTransform() << r;
6540 QTest::newRow("(0, 0, 10, 0) | 0.0 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 10, 0) << qreal(0.0) << QTransform()
6541 << QRegion(QRect(0, 0, 10, 1));
6542 QTest::newRow("(0, 0, 10, 0) | 0.5 | identity | {(0, 0, 10, 1)}") << QLineF(0, 0, 10, 0) << qreal(0.5) << QTransform()
6543 << QRegion(QRect(0, 0, 10, 1));
6544 QTest::newRow("(0, 0, 10, 0) | 1.0 | identity | {(0, 0, 10, 1)}") << QLineF(0, 0, 10, 0) << qreal(1.0) << QTransform()
6545 << QRegion(QRect(0, 0, 10, 1));
6546 QTest::newRow("(0, 0, 0, 10) | 0.0 | identity | {(0, 0, 10, 10)}") << QLineF(0, 0, 0, 10) << qreal(0.0) << QTransform()
6547 << QRegion(QRect(0, 0, 1, 10));
6548 QTest::newRow("(0, 0, 0, 10) | 0.5 | identity | {(0, 0, 1, 10)}") << QLineF(0, 0, 0, 10) << qreal(0.5) << QTransform()
6549 << QRegion(QRect(0, 0, 1, 10));
6550 QTest::newRow("(0, 0, 0, 10) | 1.0 | identity | {(0, 0, 1, 10)}") << QLineF(0, 0, 0, 10) << qreal(1.0) << QTransform()
6551 << QRegion(QRect(0, 0, 1, 10));
6554 void tst_QGraphicsItem::boundingRegion()
6556 QFETCH(QLineF, line);
6557 QFETCH(qreal, granularity);
6558 QFETCH(QTransform, transform);
6559 QFETCH(QRegion, expectedRegion);
6561 QGraphicsLineItem item(line);
6562 QCOMPARE(item.boundingRegionGranularity(), qreal(0.0));
6563 item.setBoundingRegionGranularity(granularity);
6564 QCOMPARE(item.boundingRegionGranularity(), granularity);
6565 QCOMPARE(item.boundingRegion(transform), expectedRegion);
6568 void tst_QGraphicsItem::itemTransform_parentChild()
6570 QGraphicsScene scene;
6571 QGraphicsItem *parent = scene.addRect(0, 0, 100, 100);
6572 QGraphicsItem *child = scene.addRect(0, 0, 100, 100);
6573 child->setParentItem(parent);
6574 child->setPos(10, 10);
6578 QCOMPARE(child->itemTransform(parent).map(QPointF(10, 10)), QPointF(-10, 30));
6579 QCOMPARE(parent->itemTransform(child).map(QPointF(-10, 30)), QPointF(10, 10));
6582 void tst_QGraphicsItem::itemTransform_siblings()
6584 QGraphicsScene scene;
6585 QGraphicsItem *parent = scene.addRect(0, 0, 100, 100);
6586 QGraphicsItem *brother = scene.addRect(0, 0, 100, 100);
6587 QGraphicsItem *sister = scene.addRect(0, 0, 100, 100);
6588 parent->scale(10, 5);
6589 parent->rotate(-180);
6590 parent->shear(2, 3);
6592 brother->setParentItem(parent);
6593 sister->setParentItem(parent);
6595 brother->setPos(10, 10);
6596 brother->scale(2, 2);
6597 brother->rotate(90);
6598 sister->setPos(10, 10);
6599 sister->scale(2, 2);
6602 QCOMPARE(brother->itemTransform(sister).map(QPointF(10, 10)), QPointF(10, 10));
6603 QCOMPARE(sister->itemTransform(brother).map(QPointF(10, 10)), QPointF(10, 10));
6606 void tst_QGraphicsItem::itemTransform_unrelated()
6608 QGraphicsScene scene;
6609 QGraphicsItem *stranger1 = scene.addRect(0, 0, 100, 100);
6610 QGraphicsItem *stranger2 = scene.addRect(0, 0, 100, 100);
6611 stranger1->setPos(10, 10);
6612 stranger1->scale(2, 2);
6613 stranger1->rotate(90);
6614 stranger2->setPos(10, 10);
6615 stranger2->scale(2, 2);
6616 stranger2->rotate(90);
6618 QCOMPARE(stranger1->itemTransform(stranger2).map(QPointF(10, 10)), QPointF(10, 10));
6619 QCOMPARE(stranger2->itemTransform(stranger1).map(QPointF(10, 10)), QPointF(10, 10));
6622 void tst_QGraphicsItem::opacity_data()
6624 QTest::addColumn<qreal>("p_opacity");
6625 QTest::addColumn<int>("p_opacityFlags");
6626 QTest::addColumn<qreal>("c1_opacity");
6627 QTest::addColumn<int>("c1_opacityFlags");
6628 QTest::addColumn<qreal>("c2_opacity");
6629 QTest::addColumn<int>("c2_opacityFlags");
6630 QTest::addColumn<qreal>("p_effectiveOpacity");
6631 QTest::addColumn<qreal>("c1_effectiveOpacity");
6632 QTest::addColumn<qreal>("c2_effectiveOpacity");
6633 QTest::addColumn<qreal>("c3_effectiveOpacity");
6635 // Modify the opacity and see how it propagates
6636 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
6637 << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6638 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
6639 << qreal(0.5) << qreal(0.5) << qreal(0.5) << qreal(0.5);
6640 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
6641 << qreal(0.5) << qreal(0.05) << qreal(0.05) << qreal(0.05);
6642 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
6643 << qreal(0.0) << qreal(0.0) << qreal(0.0) << qreal(0.0);
6645 // Parent doesn't propagate to children - now modify the opacity and see how it propagates
6646 int flags = QGraphicsItem::ItemDoesntPropagateOpacityToChildren;
6647 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
6648 << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6649 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
6650 << qreal(0.5) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6651 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
6652 << qreal(0.5) << qreal(0.1) << qreal(0.1) << qreal(0.1);
6653 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
6654 << qreal(0.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6656 // Child ignores parent - now modify the opacity and see how it propagates
6657 flags = QGraphicsItem::ItemIgnoresParentOpacity;
6658 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
6659 << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6660 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
6661 << qreal(0.5) << qreal(0.5) << qreal(0.25) << qreal(0.25);
6662 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
6663 << qreal(0.2) << qreal(0.2) << qreal(0.04) << qreal(0.04);
6664 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
6665 << qreal(0.0) << qreal(0.0) << qreal(0.0) << qreal(0.0);
6667 // Child ignores parent and doesn't propagate - now modify the opacity and see how it propagates
6668 flags = QGraphicsItem::ItemIgnoresParentOpacity | QGraphicsItem::ItemDoesntPropagateOpacityToChildren;
6669 QTest::newRow("M: 1.0 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(1.0) << 0 // p
6670 << qreal(1.0) << flags // c1 (no prop)
6671 << qreal(1.0) << 0 // c2
6672 << qreal(1.0) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6673 QTest::newRow("M: 0.5 0 1.0 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 // p
6674 << qreal(1.0) << flags // c1 (no prop)
6675 << qreal(1.0) << 0 // c2
6676 << qreal(0.5) << qreal(1.0) << qreal(1.0) << qreal(1.0);
6677 QTest::newRow("M: 0.5 0 0.5 1 1.0 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 // p
6678 << qreal(0.5) << flags // c1 (no prop)
6679 << qreal(1.0) << 0 // c2
6680 << qreal(0.5) << qreal(0.5) << qreal(1.0) << qreal(1.0);
6681 QTest::newRow("M: 0.5 0 0.5 1 0.5 1.0 1.0 1.0 1.0") << qreal(0.5) << 0 // p
6682 << qreal(0.5) << flags // c1 (no prop)
6683 << qreal(0.5) << 0 // c2
6684 << qreal(0.5) << qreal(0.5) << qreal(0.5) << qreal(0.5);
6685 QTest::newRow("M: 1.0 0 0.5 1 0.5 1.0 1.0 1.0 1.0") << qreal(1.0) << 0 // p
6686 << qreal(0.5) << flags // c1 (no prop)
6687 << qreal(0.5) << 0 // c2
6688 << qreal(1.0) << qreal(0.5) << qreal(0.5) << qreal(0.5);
6691 void tst_QGraphicsItem::opacity()
6693 QFETCH(qreal, p_opacity);
6694 QFETCH(int, p_opacityFlags);
6695 QFETCH(qreal, p_effectiveOpacity);
6696 QFETCH(qreal, c1_opacity);
6697 QFETCH(int, c1_opacityFlags);
6698 QFETCH(qreal, c1_effectiveOpacity);
6699 QFETCH(qreal, c2_opacity);
6700 QFETCH(int, c2_opacityFlags);
6701 QFETCH(qreal, c2_effectiveOpacity);
6702 QFETCH(qreal, c3_effectiveOpacity);
6704 QGraphicsRectItem *p = new QGraphicsRectItem;
6705 QGraphicsRectItem *c1 = new QGraphicsRectItem(p);
6706 QGraphicsRectItem *c2 = new QGraphicsRectItem(c1);
6707 QGraphicsRectItem *c3 = new QGraphicsRectItem(c2);
6709 QCOMPARE(p->opacity(), qreal(1.0));
6710 QCOMPARE(p->effectiveOpacity(), qreal(1.0));
6711 int opacityMask = QGraphicsItem::ItemIgnoresParentOpacity | QGraphicsItem::ItemDoesntPropagateOpacityToChildren;
6712 QVERIFY(!(p->flags() & opacityMask));
6714 p->setOpacity(p_opacity);
6715 c1->setOpacity(c1_opacity);
6716 c2->setOpacity(c2_opacity);
6717 p->setFlags(QGraphicsItem::GraphicsItemFlags(p->flags() | p_opacityFlags));
6718 c1->setFlags(QGraphicsItem::GraphicsItemFlags(c1->flags() | c1_opacityFlags));
6719 c2->setFlags(QGraphicsItem::GraphicsItemFlags(c2->flags() | c2_opacityFlags));
6721 QCOMPARE(int(p->flags() & opacityMask), p_opacityFlags);
6722 QCOMPARE(int(c1->flags() & opacityMask), c1_opacityFlags);
6723 QCOMPARE(int(c2->flags() & opacityMask), c2_opacityFlags);
6724 QCOMPARE(p->opacity(), p_opacity);
6725 QCOMPARE(p->effectiveOpacity(), p_effectiveOpacity);
6726 QCOMPARE(c1->effectiveOpacity(), c1_effectiveOpacity);
6727 QCOMPARE(c2->effectiveOpacity(), c2_effectiveOpacity);
6728 QCOMPARE(c3->effectiveOpacity(), c3_effectiveOpacity);
6731 void tst_QGraphicsItem::opacity2()
6733 EventTester *parent = new EventTester;
6734 EventTester *child = new EventTester(parent);
6735 EventTester *grandChild = new EventTester(child);
6737 QGraphicsScene scene;
6738 scene.addItem(parent);
6740 MyGraphicsView view(&scene);
6741 if(PlatformQuirks::isAutoMaximizing())
6742 view.showFullScreen();
6745 QTest::qWaitForWindowShown(&view);
6746 QTRY_VERIFY(view.repaints >= 1);
6748 #define RESET_REPAINT_COUNTERS \
6749 parent->repaints = 0; \
6750 child->repaints = 0; \
6751 grandChild->repaints = 0; \
6754 RESET_REPAINT_COUNTERS
6756 child->setOpacity(0.0);
6758 QTRY_COMPARE(view.repaints, 1);
6759 QCOMPARE(parent->repaints, 1);
6760 QCOMPARE(child->repaints, 0);
6761 QCOMPARE(grandChild->repaints, 0);
6763 RESET_REPAINT_COUNTERS
6765 child->setOpacity(1.0);
6767 QTRY_COMPARE(view.repaints, 1);
6768 QCOMPARE(parent->repaints, 1);
6769 QCOMPARE(child->repaints, 1);
6770 QCOMPARE(grandChild->repaints, 1);
6772 RESET_REPAINT_COUNTERS
6774 parent->setOpacity(0.0);
6776 QTRY_COMPARE(view.repaints, 1);
6777 QCOMPARE(parent->repaints, 0);
6778 QCOMPARE(child->repaints, 0);
6779 QCOMPARE(grandChild->repaints, 0);
6781 RESET_REPAINT_COUNTERS
6783 parent->setOpacity(1.0);
6785 QTRY_COMPARE(view.repaints, 1);
6786 QCOMPARE(parent->repaints, 1);
6787 QCOMPARE(child->repaints, 1);
6788 QCOMPARE(grandChild->repaints, 1);
6790 grandChild->setFlag(QGraphicsItem::ItemIgnoresParentOpacity);
6791 RESET_REPAINT_COUNTERS
6793 child->setOpacity(0.0);
6795 QTRY_COMPARE(view.repaints, 1);
6796 QCOMPARE(parent->repaints, 1);
6797 QCOMPARE(child->repaints, 0);
6798 QCOMPARE(grandChild->repaints, 1);
6800 RESET_REPAINT_COUNTERS
6802 child->setOpacity(0.0); // Already 0.0; no change.
6804 QTRY_COMPARE(view.repaints, 0);
6805 QCOMPARE(parent->repaints, 0);
6806 QCOMPARE(child->repaints, 0);
6807 QCOMPARE(grandChild->repaints, 0);
6810 void tst_QGraphicsItem::opacityZeroUpdates()
6812 EventTester *parent = new EventTester;
6813 EventTester *child = new EventTester(parent);
6815 child->setPos(10, 10);
6817 QGraphicsScene scene;
6818 scene.addItem(parent);
6820 MyGraphicsView view(&scene);
6822 QTest::qWaitForWindowShown(&view);
6823 QTRY_VERIFY(view.repaints > 0);
6826 parent->setOpacity(0.0);
6830 // transforming items bounding rect to view coordinates
6831 const QRect childDeviceBoundingRect = child->deviceTransform(view.viewportTransform())
6832 .mapRect(child->boundingRect()).toRect();
6833 const QRect parentDeviceBoundingRect = parent->deviceTransform(view.viewportTransform())
6834 .mapRect(parent->boundingRect()).toRect();
6836 QRegion expectedRegion = parentDeviceBoundingRect.adjusted(-2, -2, 2, 2);
6837 expectedRegion += childDeviceBoundingRect.adjusted(-2, -2, 2, 2);
6839 COMPARE_REGIONS(view.paintedRegion, expectedRegion);
6842 class StacksBehindParentHelper : public QGraphicsRectItem
6845 StacksBehindParentHelper(QList<QGraphicsItem *> *paintedItems, const QRectF &rect, QGraphicsItem *parent = 0)
6846 : QGraphicsRectItem(rect, parent), paintedItems(paintedItems)
6849 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
6851 QGraphicsRectItem::paint(painter, option, widget);
6852 paintedItems->append(this);
6856 QList<QGraphicsItem *> *paintedItems;
6859 void tst_QGraphicsItem::itemStacksBehindParent()
6861 StacksBehindParentHelper *parent1 = new StacksBehindParentHelper(&paintedItems, QRectF(0, 0, 100, 50));
6862 StacksBehindParentHelper *child11 = new StacksBehindParentHelper(&paintedItems, QRectF(-10, 10, 50, 50), parent1);
6863 StacksBehindParentHelper *grandChild111 = new StacksBehindParentHelper(&paintedItems, QRectF(-20, 20, 50, 50), child11);
6864 StacksBehindParentHelper *child12 = new StacksBehindParentHelper(&paintedItems, QRectF(60, 10, 50, 50), parent1);
6865 StacksBehindParentHelper *grandChild121 = new StacksBehindParentHelper(&paintedItems, QRectF(70, 20, 50, 50), child12);
6867 StacksBehindParentHelper *parent2 = new StacksBehindParentHelper(&paintedItems, QRectF(0, 0, 100, 50));
6868 StacksBehindParentHelper *child21 = new StacksBehindParentHelper(&paintedItems, QRectF(-10, 10, 50, 50), parent2);
6869 StacksBehindParentHelper *grandChild211 = new StacksBehindParentHelper(&paintedItems, QRectF(-20, 20, 50, 50), child21);
6870 StacksBehindParentHelper *child22 = new StacksBehindParentHelper(&paintedItems, QRectF(60, 10, 50, 50), parent2);
6871 StacksBehindParentHelper *grandChild221 = new StacksBehindParentHelper(&paintedItems, QRectF(70, 20, 50, 50), child22);
6873 parent1->setData(0, "parent1");
6874 child11->setData(0, "child11");
6875 grandChild111->setData(0, "grandChild111");
6876 child12->setData(0, "child12");
6877 grandChild121->setData(0, "grandChild121");
6878 parent2->setData(0, "parent2");
6879 child21->setData(0, "child21");
6880 grandChild211->setData(0, "grandChild211");
6881 child22->setData(0, "child22");
6882 grandChild221->setData(0, "grandChild221");
6884 // Disambiguate siblings
6885 parent1->setZValue(1);
6886 child11->setZValue(1);
6887 child21->setZValue(1);
6889 QGraphicsScene scene;
6890 scene.addItem(parent1);
6891 scene.addItem(parent2);
6893 QGraphicsView view(&scene);
6895 QTest::qWaitForWindowShown(&view);
6896 QTRY_VERIFY(!paintedItems.isEmpty());
6898 paintedItems.clear();
6899 view.viewport()->update();
6900 QApplication::processEvents();
6901 QTRY_COMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
6902 << grandChild111 << child11
6903 << grandChild121 << child12 << parent1
6904 << grandChild211 << child21
6905 << grandChild221 << child22 << parent2));
6906 QTRY_COMPARE(paintedItems, QList<QGraphicsItem *>()
6907 << parent2 << child22 << grandChild221
6908 << child21 << grandChild211
6909 << parent1 << child12 << grandChild121
6910 << child11 << grandChild111);
6912 child11->setFlag(QGraphicsItem::ItemStacksBehindParent);
6914 paintedItems.clear();
6915 QApplication::processEvents();
6917 QTRY_COMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
6918 << grandChild121 << child12 << parent1
6919 << grandChild111 << child11
6920 << grandChild211 << child21
6921 << grandChild221 << child22 << parent2));
6922 QCOMPARE(paintedItems, QList<QGraphicsItem *>()
6923 << parent2 << child22 << grandChild221
6924 << child21 << grandChild211
6925 << child11 << grandChild111
6926 << parent1 << child12 << grandChild121);
6928 child12->setFlag(QGraphicsItem::ItemStacksBehindParent);
6929 paintedItems.clear();
6931 QApplication::processEvents();
6933 QTRY_COMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
6934 << parent1 << grandChild111 << child11
6935 << grandChild121 << child12
6936 << grandChild211 << child21
6937 << grandChild221 << child22 << parent2));
6938 QCOMPARE(paintedItems, QList<QGraphicsItem *>()
6939 << parent2 << child22 << grandChild221
6940 << child21 << grandChild211
6941 << child12 << grandChild121
6942 << child11 << grandChild111 << parent1);
6945 class ClippingAndTransformsScene : public QGraphicsScene
6948 QList<QGraphicsItem *> drawnItems;
6950 void drawItems(QPainter *painter, int numItems, QGraphicsItem *items[],
6951 const QStyleOptionGraphicsItem options[], QWidget *widget = 0)
6954 for (int i = 0; i < numItems; ++i)
6955 drawnItems << items[i];
6956 QGraphicsScene::drawItems(painter, numItems, items, options, widget);
6960 void tst_QGraphicsItem::nestedClipping()
6962 ClippingAndTransformsScene scene;
6963 scene.setSceneRect(-50, -50, 200, 200);
6965 QGraphicsRectItem *root = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
6966 root->setBrush(QColor(0, 0, 255));
6967 root->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
6968 QGraphicsRectItem *l1 = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
6969 l1->setParentItem(root);
6971 l1->setBrush(QColor(255, 0, 0));
6972 l1->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
6973 QGraphicsEllipseItem *l2 = new QGraphicsEllipseItem(QRectF(0, 0, 100, 100));
6974 l2->setParentItem(l1);
6976 l2->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
6977 l2->setBrush(QColor(255, 255, 0));
6978 QGraphicsRectItem *l3 = new QGraphicsRectItem(QRectF(0, 0, 25, 25));
6979 l3->setParentItem(l2);
6980 l3->setBrush(QColor(0, 255, 0));
6981 l3->setPos(50 - 12, -12);
6983 scene.addItem(root);
6985 root->setData(0, "root");
6986 l1->setData(0, "l1");
6987 l2->setData(0, "l2");
6988 l3->setData(0, "l3");
6990 QGraphicsView view(&scene);
6991 view.setOptimizationFlag(QGraphicsView::IndirectPainting);
6993 QTest::qWaitForWindowShown(&view);
6996 QList<QGraphicsItem *> expected;
6997 expected << root << l1 << l2 << l3;
6998 QTRY_COMPARE(scene.drawnItems, expected);
7000 QImage image(200, 200, QImage::Format_ARGB32_Premultiplied);
7003 QPainter painter(&image);
7004 scene.render(&painter);
7007 // Check transparent areas
7008 QCOMPARE(image.pixel(100, 25), qRgba(0, 0, 0, 0));
7009 QCOMPARE(image.pixel(100, 175), qRgba(0, 0, 0, 0));
7010 QCOMPARE(image.pixel(25, 100), qRgba(0, 0, 0, 0));
7011 QCOMPARE(image.pixel(175, 100), qRgba(0, 0, 0, 0));
7012 QCOMPARE(image.pixel(70, 80), qRgba(255, 0, 0, 255));
7013 QCOMPARE(image.pixel(80, 130), qRgba(255, 255, 0, 255));
7014 QCOMPARE(image.pixel(92, 105), qRgba(0, 255, 0, 255));
7015 QCOMPARE(image.pixel(105, 105), qRgba(0, 0, 255, 255));
7017 // Enable this to compare if the test starts failing.
7018 image.save("nestedClipping_reference.png");
7022 class TransformDebugItem : public QGraphicsRectItem
7025 TransformDebugItem()
7026 : QGraphicsRectItem(QRectF(-10, -10, 20, 20))
7028 setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
7033 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
7034 QWidget *widget = 0)
7036 x = painter->worldTransform();
7037 QGraphicsRectItem::paint(painter, option, widget);
7041 void tst_QGraphicsItem::nestedClippingTransforms()
7043 TransformDebugItem *rootClipper = new TransformDebugItem;
7044 rootClipper->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
7045 TransformDebugItem *child = new TransformDebugItem;
7046 child->setParentItem(rootClipper);
7047 child->setPos(2, 2);
7048 TransformDebugItem *grandChildClipper = new TransformDebugItem;
7049 grandChildClipper->setParentItem(child);
7050 grandChildClipper->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
7051 grandChildClipper->setPos(4, 4);
7052 TransformDebugItem *greatGrandChild = new TransformDebugItem;
7053 greatGrandChild->setPos(2, 2);
7054 greatGrandChild->setParentItem(grandChildClipper);
7055 TransformDebugItem *grandChildClipper2 = new TransformDebugItem;
7056 grandChildClipper2->setParentItem(child);
7057 grandChildClipper2->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
7058 grandChildClipper2->setPos(8, 8);
7059 TransformDebugItem *greatGrandChild2 = new TransformDebugItem;
7060 greatGrandChild2->setPos(2, 2);
7061 greatGrandChild2->setParentItem(grandChildClipper2);
7062 TransformDebugItem *grandChildClipper3 = new TransformDebugItem;
7063 grandChildClipper3->setParentItem(child);
7064 grandChildClipper3->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
7065 grandChildClipper3->setPos(12, 12);
7066 TransformDebugItem *greatGrandChild3 = new TransformDebugItem;
7067 greatGrandChild3->setPos(2, 2);
7068 greatGrandChild3->setParentItem(grandChildClipper3);
7070 QGraphicsScene scene;
7071 scene.addItem(rootClipper);
7073 QImage image(scene.itemsBoundingRect().size().toSize(), QImage::Format_ARGB32_Premultiplied);
7079 QCOMPARE(rootClipper->x, QTransform(1, 0, 0, 0, 1, 0, 10, 10, 1));
7080 QCOMPARE(child->x, QTransform(1, 0, 0, 0, 1, 0, 12, 12, 1));
7081 QCOMPARE(grandChildClipper->x, QTransform(1, 0, 0, 0, 1, 0, 16, 16, 1));
7082 QCOMPARE(greatGrandChild->x, QTransform(1, 0, 0, 0, 1, 0, 18, 18, 1));
7083 QCOMPARE(grandChildClipper2->x, QTransform(1, 0, 0, 0, 1, 0, 20, 20, 1));
7084 QCOMPARE(greatGrandChild2->x, QTransform(1, 0, 0, 0, 1, 0, 22, 22, 1));
7085 QCOMPARE(grandChildClipper3->x, QTransform(1, 0, 0, 0, 1, 0, 24, 24, 1));
7086 QCOMPARE(greatGrandChild3->x, QTransform(1, 0, 0, 0, 1, 0, 26, 26, 1));
7089 void tst_QGraphicsItem::sceneTransformCache()
7091 // Test that an item's scene transform is updated correctly when the
7092 // parent is transformed.
7093 QGraphicsScene scene;
7094 QGraphicsRectItem *rect = scene.addRect(0, 0, 100, 100);
7095 QGraphicsRectItem *rect2 = scene.addRect(0, 0, 100, 100);
7096 rect2->setParentItem(rect);
7098 rect->translate(0, 50);
7099 QGraphicsView view(&scene);
7102 qt_x11_wait_for_window_manager(&view);
7105 rect->translate(0, 100);
7107 x.translate(0, 150);
7109 QCOMPARE(rect2->sceneTransform(), x);
7111 scene.removeItem(rect);
7113 //Crazy use case : rect4 child of rect3 so the transformation of rect4 will be cached.Good!
7114 //We remove rect4 from the scene, then the validTransform bit flag is set to 0 and the index of the cache
7115 //add to the freeTransformSlots. The problem was that sceneTransformIndex was not set to -1 so if a new item arrive
7116 //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
7117 //added back to the scene then it will set the transform to his old sceneTransformIndex value that will erase the new
7118 //value of rect6 so rect6 transform will be wrong.
7119 QGraphicsRectItem *rect3 = scene.addRect(0, 0, 100, 100);
7120 QGraphicsRectItem *rect4 = scene.addRect(0, 0, 100, 100);
7121 rect3->setPos(QPointF(10,10));
7123 rect4->setParentItem(rect3);
7124 rect4->setPos(QPointF(10,10));
7126 QCOMPARE(rect4->mapToScene(rect4->boundingRect().topLeft()), QPointF(20,20));
7128 scene.removeItem(rect4);
7129 //rect4 transform is local only
7130 QCOMPARE(rect4->mapToScene(rect4->boundingRect().topLeft()), QPointF(10,10));
7132 QGraphicsRectItem *rect5 = scene.addRect(0, 0, 100, 100);
7133 QGraphicsRectItem *rect6 = scene.addRect(0, 0, 100, 100);
7134 rect5->setPos(QPointF(20,20));
7136 rect6->setParentItem(rect5);
7137 rect6->setPos(QPointF(10,10));
7138 //test if rect6 transform is ok
7139 QCOMPARE(rect6->mapToScene(rect6->boundingRect().topLeft()), QPointF(30,30));
7141 scene.addItem(rect4);
7143 QCOMPARE(rect4->mapToScene(rect4->boundingRect().topLeft()), QPointF(10,10));
7144 //test if rect6 transform is still correct
7145 QCOMPARE(rect6->mapToScene(rect6->boundingRect().topLeft()), QPointF(30,30));
7148 void tst_QGraphicsItem::tabChangesFocus_data()
7150 QTest::addColumn<bool>("tabChangesFocus");
7151 QTest::newRow("tab changes focus") << true;
7152 QTest::newRow("tab doesn't change focus") << false;
7155 void tst_QGraphicsItem::tabChangesFocus()
7157 QFETCH(bool, tabChangesFocus);
7159 QGraphicsScene scene;
7160 QGraphicsTextItem *item = scene.addText("Hello");
7161 item->setTabChangesFocus(tabChangesFocus);
7162 item->setTextInteractionFlags(Qt::TextEditorInteraction);
7165 QDial *dial1 = new QDial;
7166 QGraphicsView *view = new QGraphicsView(&scene);
7168 QDial *dial2 = new QDial;
7169 QVBoxLayout *layout = new QVBoxLayout;
7170 layout->addWidget(dial1);
7171 layout->addWidget(view);
7172 layout->addWidget(dial2);
7175 widget.setLayout(layout);
7177 QTest::qWaitForWindowShown(&widget);
7180 QTRY_VERIFY(scene.isActive());
7184 QTRY_VERIFY(dial1->hasFocus());
7186 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
7188 QTRY_VERIFY(view->hasFocus());
7189 QTRY_VERIFY(item->hasFocus());
7191 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab);
7194 if (tabChangesFocus) {
7195 QTRY_VERIFY(!view->hasFocus());
7196 QTRY_VERIFY(!item->hasFocus());
7197 QTRY_VERIFY(dial2->hasFocus());
7199 QTRY_VERIFY(view->hasFocus());
7200 QTRY_VERIFY(item->hasFocus());
7201 QCOMPARE(item->toPlainText(), QString("\tHello"));
7205 void tst_QGraphicsItem::cacheMode()
7207 QGraphicsScene scene(0, 0, 100, 100);
7208 QGraphicsView view(&scene);
7209 view.resize(150, 150);
7211 QApplication::setActiveWindow(&view);
7212 QTest::qWaitForWindowShown(&view);
7214 // Increase the probability of window activation
7215 // not causing another repaint of test items.
7218 EventTester *tester = new EventTester;
7219 EventTester *testerChild = new EventTester;
7220 testerChild->setParentItem(tester);
7221 EventTester *testerChild2 = new EventTester;
7222 testerChild2->setParentItem(testerChild);
7223 testerChild2->setFlag(QGraphicsItem::ItemIgnoresTransformations);
7225 scene.addItem(tester);
7228 for (int i = 0; i < 2; ++i) {
7229 // No visual change.
7230 QTRY_COMPARE(tester->repaints, 1);
7231 QCOMPARE(testerChild->repaints, 1);
7232 QCOMPARE(testerChild2->repaints, 1);
7233 tester->setCacheMode(QGraphicsItem::NoCache);
7234 testerChild->setCacheMode(QGraphicsItem::NoCache);
7235 testerChild2->setCacheMode(QGraphicsItem::NoCache);
7237 QTRY_COMPARE(tester->repaints, 1);
7238 QCOMPARE(testerChild->repaints, 1);
7239 QCOMPARE(testerChild2->repaints, 1);
7240 tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7241 testerChild->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7242 testerChild2->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7246 // The first move causes a repaint as the item is painted into its pixmap.
7247 // (Only occurs if the item has previously been painted without cache).
7248 tester->setPos(10, 10);
7249 testerChild->setPos(10, 10);
7250 testerChild2->setPos(10, 10);
7252 QTRY_COMPARE(tester->repaints, 2);
7253 QCOMPARE(testerChild->repaints, 2);
7254 QCOMPARE(testerChild2->repaints, 2);
7256 // Consecutive moves should not repaint.
7257 tester->setPos(20, 20);
7258 testerChild->setPos(20, 20);
7259 testerChild2->setPos(20, 20);
7261 QCOMPARE(tester->repaints, 2);
7262 QCOMPARE(testerChild->repaints, 2);
7263 QCOMPARE(testerChild2->repaints, 2);
7265 // Translating does not result in a repaint.
7266 tester->translate(10, 10);
7268 QTRY_COMPARE(tester->repaints, 2);
7269 QCOMPARE(testerChild->repaints, 2);
7270 QCOMPARE(testerChild2->repaints, 2);
7272 // Rotating results in a repaint.
7275 QTRY_COMPARE(tester->repaints, 3);
7276 QCOMPARE(testerChild->repaints, 3);
7277 QCOMPARE(testerChild2->repaints, 2);
7279 // Change to ItemCoordinateCache (triggers repaint).
7280 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache); // autosize
7281 testerChild->setCacheMode(QGraphicsItem::ItemCoordinateCache); // autosize
7282 testerChild2->setCacheMode(QGraphicsItem::ItemCoordinateCache); // autosize
7284 QTRY_COMPARE(tester->repaints, 4);
7285 QCOMPARE(testerChild->repaints, 4);
7286 QCOMPARE(testerChild2->repaints, 3);
7288 // Rotating items with ItemCoordinateCache doesn't cause a repaint.
7290 testerChild->rotate(22);
7291 testerChild2->rotate(22);
7293 QTRY_COMPARE(tester->repaints, 4);
7294 QTRY_COMPARE(testerChild->repaints, 4);
7295 QTRY_COMPARE(testerChild2->repaints, 3);
7296 tester->resetTransform();
7297 testerChild->resetTransform();
7298 testerChild2->resetTransform();
7300 // Explicit update causes a repaint.
7301 tester->update(0, 0, 5, 5);
7303 QTRY_COMPARE(tester->repaints, 5);
7304 QCOMPARE(testerChild->repaints, 4);
7305 QCOMPARE(testerChild2->repaints, 3);
7307 // Updating outside the item's bounds does not cause a repaint.
7308 tester->update(10, 10, 5, 5);
7310 QTRY_COMPARE(tester->repaints, 5);
7311 QCOMPARE(testerChild->repaints, 4);
7312 QCOMPARE(testerChild2->repaints, 3);
7314 // Resizing an item should cause a repaint of that item. (because of
7316 tester->setGeometry(QRectF(-15, -15, 30, 30));
7318 QTRY_COMPARE(tester->repaints, 6);
7319 QCOMPARE(testerChild->repaints, 4);
7320 QCOMPARE(testerChild2->repaints, 3);
7323 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(30, 30));
7324 testerChild->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(30, 30));
7325 testerChild2->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(30, 30));
7327 QTRY_COMPARE(tester->repaints, 7);
7328 QCOMPARE(testerChild->repaints, 5);
7329 QCOMPARE(testerChild2->repaints, 4);
7331 // Resizing the item should cause a repaint.
7332 testerChild->setGeometry(QRectF(-15, -15, 30, 30));
7334 QTRY_COMPARE(tester->repaints, 7);
7335 QCOMPARE(testerChild->repaints, 6);
7336 QCOMPARE(testerChild2->repaints, 4);
7338 // Scaling the view does not cause a repaint.
7339 view.scale(0.7, 0.7);
7341 QTRY_COMPARE(tester->repaints, 7);
7342 QCOMPARE(testerChild->repaints, 6);
7343 QCOMPARE(testerChild2->repaints, 4);
7345 // Switch to device coordinate cache.
7346 tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7347 testerChild->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7348 testerChild2->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7350 QTRY_COMPARE(tester->repaints, 8);
7351 QCOMPARE(testerChild->repaints, 7);
7352 QCOMPARE(testerChild2->repaints, 5);
7354 // Scaling the view back should cause repaints for two of the items.
7355 view.setTransform(QTransform());
7357 QTRY_COMPARE(tester->repaints, 9);
7358 QCOMPARE(testerChild->repaints, 8);
7359 QCOMPARE(testerChild2->repaints, 5);
7361 // Rotating the base item (perspective) should repaint two items.
7362 tester->setTransform(QTransform().rotate(10, Qt::XAxis));
7364 QTRY_COMPARE(tester->repaints, 10);
7365 QCOMPARE(testerChild->repaints, 9);
7366 QCOMPARE(testerChild2->repaints, 5);
7368 // Moving the middle item should case a repaint even if it's a move,
7369 // because the parent is rotated with a perspective.
7370 testerChild->setPos(1, 1);
7372 QTRY_COMPARE(tester->repaints, 11);
7373 QTRY_COMPARE(testerChild->repaints, 10);
7374 QTRY_COMPARE(testerChild2->repaints, 5);
7375 tester->resetTransform();
7378 tester->setGeometry(QRectF(-4000, -4000, 8000, 8000));
7379 QTRY_COMPARE(tester->repaints, 12);
7380 QTRY_COMPARE(testerChild->repaints, 11);
7381 QTRY_COMPARE(testerChild2->repaints, 5);
7383 // Move the large item - will cause a repaint as the
7384 // cache is clipped.
7385 tester->setPos(5, 0);
7386 QTRY_COMPARE(tester->repaints, 13);
7387 QTRY_COMPARE(testerChild->repaints, 11);
7388 QTRY_COMPARE(testerChild2->repaints, 5);
7390 // Hiding and showing should invalidate the cache
7394 QTRY_COMPARE(tester->repaints, 14);
7395 QTRY_COMPARE(testerChild->repaints, 12);
7396 QTRY_COMPARE(testerChild2->repaints, 6);
7399 void tst_QGraphicsItem::cacheMode2()
7401 QGraphicsScene scene(0, 0, 100, 100);
7402 QGraphicsView view(&scene);
7403 view.resize(150, 150);
7405 QApplication::setActiveWindow(&view);
7406 QTest::qWaitForWindowShown(&view);
7408 // Increase the probability of window activation
7409 // not causing another repaint of test items.
7412 EventTester *tester = new EventTester;
7413 scene.addItem(tester);
7415 QTRY_COMPARE(tester->repaints, 1);
7417 // Switching from NoCache to NoCache (no repaint)
7418 tester->setCacheMode(QGraphicsItem::NoCache);
7420 QTRY_COMPARE(tester->repaints, 1);
7422 // Switching from NoCache to DeviceCoordinateCache (no repaint)
7423 tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7425 QTRY_COMPARE(tester->repaints, 1);
7427 // Switching from DeviceCoordinateCache to DeviceCoordinateCache (no repaint)
7428 tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7430 QTRY_COMPARE(tester->repaints, 1);
7432 // Switching from DeviceCoordinateCache to NoCache (no repaint)
7433 tester->setCacheMode(QGraphicsItem::NoCache);
7435 QTRY_COMPARE(tester->repaints, 1);
7437 // Switching from NoCache to ItemCoordinateCache (repaint)
7438 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
7440 QTRY_COMPARE(tester->repaints, 2);
7442 // Switching from ItemCoordinateCache to ItemCoordinateCache (no repaint)
7443 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
7445 QTRY_COMPARE(tester->repaints, 2);
7447 // Switching from ItemCoordinateCache to ItemCoordinateCache with different size (repaint)
7448 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache, QSize(100, 100));
7450 QTRY_COMPARE(tester->repaints, 3);
7452 // Switching from ItemCoordinateCache to NoCache (repaint)
7453 tester->setCacheMode(QGraphicsItem::NoCache);
7455 QTRY_COMPARE(tester->repaints, 4);
7457 // Switching from DeviceCoordinateCache to ItemCoordinateCache (repaint)
7458 tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7460 QTRY_COMPARE(tester->repaints, 4);
7461 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
7463 QTRY_COMPARE(tester->repaints, 5);
7465 // Switching from ItemCoordinateCache to DeviceCoordinateCache (repaint)
7466 tester->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
7468 QTRY_COMPARE(tester->repaints, 6);
7471 void tst_QGraphicsItem::updateCachedItemAfterMove()
7473 // A simple item that uses ItemCoordinateCache
7474 EventTester *tester = new EventTester;
7475 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
7477 // Add to a scene, show in a view, ensure it's painted and reset its
7479 QGraphicsScene scene;
7480 scene.addItem(tester);
7481 QGraphicsView view(&scene);
7483 QTest::qWaitForWindowShown(&view);
7486 QTRY_VERIFY(tester->repaints > 0);
7487 tester->repaints = 0;
7489 // Move the item, should not cause repaints
7490 tester->setPos(10, 0);
7492 QCOMPARE(tester->repaints, 0);
7494 // Move then update, should cause one repaint
7495 tester->setPos(20, 0);
7498 QCOMPARE(tester->repaints, 1);
7500 // Hiding the item doesn't cause a repaint
7503 QCOMPARE(tester->repaints, 1);
7505 // Moving a hidden item doesn't cause a repaint
7506 tester->setPos(30, 0);
7509 QCOMPARE(tester->repaints, 1);
7512 class Track : public QGraphicsRectItem
7515 Track(const QRectF &rect)
7516 : QGraphicsRectItem(rect)
7518 setAcceptHoverEvents(true);
7521 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
7523 QGraphicsRectItem::paint(painter, option, widget);
7524 painter->drawText(boundingRect(), Qt::AlignCenter, QString("%1x%2\n%3x%4").arg(p.x()).arg(p.y()).arg(sp.x()).arg(sp.y()));
7528 void hoverMoveEvent(QGraphicsSceneHoverEvent *event)
7531 sp = event->widget()->mapFromGlobal(event->screenPos());
7539 void tst_QGraphicsItem::deviceTransform_data()
7541 QTest::addColumn<bool>("untransformable1");
7542 QTest::addColumn<bool>("untransformable2");
7543 QTest::addColumn<bool>("untransformable3");
7544 QTest::addColumn<qreal>("rotation1");
7545 QTest::addColumn<qreal>("rotation2");
7546 QTest::addColumn<qreal>("rotation3");
7547 QTest::addColumn<QTransform>("deviceX");
7548 QTest::addColumn<QPointF>("mapResult1");
7549 QTest::addColumn<QPointF>("mapResult2");
7550 QTest::addColumn<QPointF>("mapResult3");
7552 QTest::newRow("nil") << false << false << false
7553 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7555 << QPointF(150, 150) << QPointF(250, 250) << QPointF(350, 350);
7556 QTest::newRow("deviceX rot 90") << false << false << false
7557 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7558 << QTransform().rotate(90)
7559 << QPointF(-150, 150) << QPointF(-250, 250) << QPointF(-350, 350);
7560 QTest::newRow("deviceX rot 90 100") << true << false << false
7561 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7562 << QTransform().rotate(90)
7563 << QPointF(-50, 150) << QPointF(50, 250) << QPointF(150, 350);
7564 QTest::newRow("deviceX rot 90 010") << false << true << false
7565 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7566 << QTransform().rotate(90)
7567 << QPointF(-150, 150) << QPointF(-150, 250) << QPointF(-50, 350);
7568 QTest::newRow("deviceX rot 90 001") << false << false << true
7569 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7570 << QTransform().rotate(90)
7571 << QPointF(-150, 150) << QPointF(-250, 250) << QPointF(-250, 350);
7572 QTest::newRow("deviceX rot 90 111") << true << true << true
7573 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7574 << QTransform().rotate(90)
7575 << QPointF(-50, 150) << QPointF(50, 250) << QPointF(150, 350);
7576 QTest::newRow("deviceX rot 90 101") << true << false << true
7577 << qreal(0.0) << qreal(0.0) << qreal(0.0)
7578 << QTransform().rotate(90)
7579 << QPointF(-50, 150) << QPointF(50, 250) << QPointF(150, 350);
7582 void tst_QGraphicsItem::deviceTransform()
7584 QFETCH(bool, untransformable1);
7585 QFETCH(bool, untransformable2);
7586 QFETCH(bool, untransformable3);
7587 QFETCH(qreal, rotation1);
7588 QFETCH(qreal, rotation2);
7589 QFETCH(qreal, rotation3);
7590 QFETCH(QTransform, deviceX);
7591 QFETCH(QPointF, mapResult1);
7592 QFETCH(QPointF, mapResult2);
7593 QFETCH(QPointF, mapResult3);
7595 QGraphicsScene scene;
7596 Track *rect1 = new Track(QRectF(0, 0, 100, 100));
7597 Track *rect2 = new Track(QRectF(0, 0, 100, 100));
7598 Track *rect3 = new Track(QRectF(0, 0, 100, 100));
7599 rect2->setParentItem(rect1);
7600 rect3->setParentItem(rect2);
7601 rect1->setPos(100, 100);
7602 rect2->setPos(100, 100);
7603 rect3->setPos(100, 100);
7604 rect1->rotate(rotation1);
7605 rect2->rotate(rotation2);
7606 rect3->rotate(rotation3);
7607 rect1->setFlag(QGraphicsItem::ItemIgnoresTransformations, untransformable1);
7608 rect2->setFlag(QGraphicsItem::ItemIgnoresTransformations, untransformable2);
7609 rect3->setFlag(QGraphicsItem::ItemIgnoresTransformations, untransformable3);
7610 rect1->setBrush(Qt::red);
7611 rect2->setBrush(Qt::green);
7612 rect3->setBrush(Qt::blue);
7613 scene.addItem(rect1);
7615 QCOMPARE(rect1->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult1);
7616 QCOMPARE(rect2->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult2);
7617 QCOMPARE(rect3->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult3);
7620 void tst_QGraphicsItem::update()
7622 QGraphicsScene scene;
7623 scene.setSceneRect(-100, -100, 200, 200);
7625 MyGraphicsView view(&scene,&topLevel);
7627 topLevel.resize(300, 300);
7630 qt_x11_wait_for_window_manager(&view);
7634 EventTester *item = new EventTester;
7635 scene.addItem(item);
7636 QTest::qWait(100); // Make sure all pending updates are processed.
7639 item->update(); // Item marked as dirty
7640 scene.update(); // Entire scene marked as dirty
7641 qApp->processEvents();
7642 QCOMPARE(item->repaints, 1);
7644 // Make sure the dirty state from the previous update is reset so that
7645 // the item don't think it is already dirty and discards this update.
7647 qApp->processEvents();
7648 QCOMPARE(item->repaints, 2);
7650 // Make sure a partial update doesn't cause a full update to be discarded.
7653 item->update(QRectF(0, 0, 5, 5));
7655 qApp->processEvents();
7656 QCOMPARE(item->repaints, 1);
7657 QCOMPARE(view.repaints, 1);
7658 QRect itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform())
7659 .mapRect(item->boundingRect()).toAlignedRect();
7660 QRegion expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2);
7661 // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
7662 QCOMPARE(view.paintedRegion, expectedRegion);
7664 // Make sure update requests outside the bounding rect are discarded.
7667 item->update(-15, -15, 5, 5); // Item's brect: (-10, -10, 20, 20)
7668 qApp->processEvents();
7669 QCOMPARE(item->repaints, 0);
7670 QCOMPARE(view.repaints, 0);
7672 // Make sure the area occupied by an item is repainted when hiding it.
7675 item->update(); // Full update; all sub-sequent update requests are discarded.
7676 item->hide(); // visible set to 0. ignoreVisible must be set to 1; the item won't be processed otherwise.
7677 qApp->processEvents();
7678 QCOMPARE(item->repaints, 0);
7679 QCOMPARE(view.repaints, 1);
7680 // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
7681 QCOMPARE(view.paintedRegion, expectedRegion);
7683 // Make sure item is repainted when shown (after being hidden).
7687 qApp->processEvents();
7688 QCOMPARE(item->repaints, 1);
7689 QCOMPARE(view.repaints, 1);
7690 // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
7691 QCOMPARE(view.paintedRegion, expectedRegion);
7695 qApp->processEvents();
7697 const QPointF originalPos = item->pos();
7698 item->setPos(5000, 5000);
7699 qApp->processEvents();
7700 QCOMPARE(item->repaints, 0);
7701 QCOMPARE(view.repaints, 0);
7702 qApp->processEvents();
7704 item->setPos(originalPos);
7705 qApp->processEvents();
7706 QCOMPARE(item->repaints, 0);
7707 QCOMPARE(view.repaints, 0);
7709 qApp->processEvents();
7710 QCOMPARE(item->repaints, 1);
7711 QCOMPARE(view.repaints, 1);
7712 // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
7713 QCOMPARE(view.paintedRegion, expectedRegion);
7715 QGraphicsViewPrivate *viewPrivate = static_cast<QGraphicsViewPrivate *>(qt_widget_private(&view));
7716 item->setPos(originalPos + QPoint(50, 50));
7717 viewPrivate->updateAll();
7718 QVERIFY(viewPrivate->fullUpdatePending);
7722 item->setPos(originalPos);
7724 qApp->processEvents();
7725 QCOMPARE(item->repaints, 1);
7726 QCOMPARE(view.repaints, 1);
7727 COMPARE_REGIONS(view.paintedRegion, expectedRegion + expectedRegion.translated(50, 50));
7729 // Make sure moving a parent item triggers an update on the children
7730 // (even though the parent itself is outside the viewport).
7731 QGraphicsRectItem *parent = new QGraphicsRectItem(0, 0, 10, 10);
7732 parent->setPos(-400, 0);
7733 item->setParentItem(parent);
7734 item->setPos(400, 0);
7735 scene.addItem(parent);
7737 itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform())
7738 .mapRect(item->boundingRect()).toAlignedRect();
7739 expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2);
7742 parent->translate(-400, 0);
7743 qApp->processEvents();
7744 QCOMPARE(item->repaints, 0);
7745 QCOMPARE(view.repaints, 1);
7746 QCOMPARE(view.paintedRegion, expectedRegion);
7749 parent->translate(400, 0);
7750 qApp->processEvents();
7751 QCOMPARE(item->repaints, 1);
7752 QCOMPARE(view.repaints, 1);
7753 QCOMPARE(view.paintedRegion, expectedRegion);
7754 QCOMPARE(view.paintedRegion, expectedRegion);
7757 void tst_QGraphicsItem::setTransformProperties_data()
7759 QTest::addColumn<QPointF>("origin");
7760 QTest::addColumn<qreal>("rotation");
7761 QTest::addColumn<qreal>("scale");
7763 QTest::newRow("nothing") << QPointF() << qreal(0.0) << qreal(1.0);
7765 QTest::newRow("rotation") << QPointF() << qreal(42.2) << qreal(1.0);
7767 QTest::newRow("rotation dicentred") << QPointF(qreal(22.3), qreal(-56.2))
7771 QTest::newRow("Scale") << QPointF() << qreal(0.0)
7774 QTest::newRow("Everything dicentred") << QPointF(qreal(22.3), qreal(-56.2)) << qreal(-175) << qreal(196);
7778 * the normal QCOMPARE doesn't work because it doesn't use qFuzzyCompare
7780 #define QCOMPARE_TRANSFORM(X1, X2) QVERIFY(((X1)*(X2).inverted()).isIdentity())
7782 void tst_QGraphicsItem::setTransformProperties()
7784 QFETCH(QPointF,origin);
7785 QFETCH(qreal,rotation);
7786 QFETCH(qreal,scale);
7789 result.translate(origin.x(), origin.y());
7790 result.rotate(rotation, Qt::ZAxis);
7791 result.scale(scale, scale);
7792 result.translate(-origin.x(), -origin.y());
7794 QGraphicsScene scene;
7795 QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
7796 scene.addItem(item);
7798 item->setRotation(rotation);
7799 item->setScale(scale);
7800 item->setTransformOriginPoint(origin);
7802 QCOMPARE(item->rotation(), rotation);
7803 QCOMPARE(item->scale(), scale);
7804 QCOMPARE(item->transformOriginPoint(), origin);
7806 QCOMPARE(QTransform(), item->transform());
7807 QCOMPARE(result, item->sceneTransform());
7809 //-----------------------------------------------------------------
7810 //Change the rotation Z
7811 item->setRotation(45);
7813 result2.translate(origin.x(), origin.y());
7815 result2.scale(scale, scale);
7816 result2.translate(-origin.x(), -origin.y());
7818 QCOMPARE(item->rotation(), 45.);
7819 QCOMPARE(item->scale(), scale);
7820 QCOMPARE(item->transformOriginPoint(), origin);
7822 QCOMPARE(QTransform(), item->transform());
7823 QCOMPARE(result2, item->sceneTransform());
7825 //-----------------------------------------------------------------
7826 // calling setTransform() and setPos should change the sceneTransform
7827 item->setTransform(result);
7828 item->setPos(100, -150.5);
7830 QCOMPARE(item->rotation(), 45.);
7831 QCOMPARE(item->scale(), scale);
7832 QCOMPARE(item->transformOriginPoint(), origin);
7833 QCOMPARE(result, item->transform());
7835 QTransform result3(result);
7837 result3.translate(origin.x(), origin.y());
7839 result3.scale(scale, scale);
7840 result3.translate(-origin.x(), -origin.y());
7842 result3 *= QTransform::fromTranslate(100, -150.5); //the pos;
7844 QCOMPARE(result3, item->sceneTransform());
7846 //-----------------------------------------------------
7847 // setting the propertiees should be the same as setting a transform
7848 {//with center origin on the matrix
7849 QGraphicsRectItem *item1 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119));
7850 scene.addItem(item1);
7851 QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119));
7852 scene.addItem(item2);
7854 item1->setPos(12.3, -5);
7855 item2->setPos(12.3, -5);
7856 item1->setRotation(rotation);
7857 item1->setScale(scale);
7858 item1->setTransformOriginPoint(origin);
7860 item2->setTransform(result);
7862 QCOMPARE_TRANSFORM(item1->sceneTransform(), item2->sceneTransform());
7864 QCOMPARE_TRANSFORM(item1->itemTransform(item2), QTransform());
7865 QCOMPARE_TRANSFORM(item2->itemTransform(item1), QTransform());
7869 class MyStyleOptionTester : public QGraphicsRectItem
7872 MyStyleOptionTester(const QRectF &rect)
7873 : QGraphicsRectItem(rect), startTrack(false)
7876 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
7879 //Doesn't use the extended style option so the exposed rect is the boundingRect
7880 if (!(flags() & QGraphicsItem::ItemUsesExtendedStyleOption)) {
7881 QCOMPARE(option->exposedRect, boundingRect());
7882 QCOMPARE(option->matrix, QMatrix());
7884 QVERIFY(option->exposedRect != QRect());
7885 QVERIFY(option->exposedRect != boundingRect());
7886 QCOMPARE(option->matrix, sceneTransform().toAffine());
7889 QGraphicsRectItem::paint(painter, option, widget);
7894 void tst_QGraphicsItem::itemUsesExtendedStyleOption()
7896 QGraphicsScene scene(0, 0, 300, 300);
7897 QGraphicsPixmapItem item;
7898 item.setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
7899 QCOMPARE(item.flags(), QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemUsesExtendedStyleOption));
7900 item.setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, false);
7901 QCOMPARE(item.flags(), 0);
7903 //We now test the content of the style option
7904 MyStyleOptionTester *rect = new MyStyleOptionTester(QRect(0, 0, 100, 100));
7905 scene.addItem(rect);
7906 rect->setPos(200, 200);
7908 QGraphicsView view(&scene, &topLevel);
7909 topLevel.setWindowFlags(Qt::X11BypassWindowManagerHint);
7910 rect->startTrack = false;
7912 QTest::qWaitForWindowShown(&view);
7914 rect->startTrack = true;
7915 rect->update(10, 10, 10, 10);
7917 rect->startTrack = false;
7918 rect->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
7919 QVERIFY((rect->flags() & QGraphicsItem::ItemUsesExtendedStyleOption));
7921 rect->startTrack = true;
7922 rect->update(10, 10, 10, 10);
7926 void tst_QGraphicsItem::itemSendsGeometryChanges()
7928 ItemChangeTester item;
7932 QTransform x = QTransform().rotate(45);
7933 QPointF pos(10, 10);
7937 QPointF origin(1.0, 1.0);
7938 item.setTransform(x);
7940 item.setRotation(r);
7942 item.setTransformOriginPoint(origin);
7943 QCOMPARE(item.transform(), x);
7944 QCOMPARE(item.pos(), pos);
7945 QCOMPARE(item.rotation(), r);
7946 QCOMPARE(item.scale(), s);
7947 QCOMPARE(item.transformOriginPoint(), origin);
7948 QCOMPARE(item.changes.size(), 0);
7951 QCOMPARE(item.changes.size(), 2); // opacity
7953 item.setFlag(QGraphicsItem::ItemSendsGeometryChanges);
7954 QCOMPARE(item.changes.size(), 4); // flags
7955 item.setTransform(QTransform());
7956 item.setPos(QPointF());
7957 QCOMPARE(item.changes.size(), 8); // transform + pos
7958 QCOMPARE(item.transform(), QTransform());
7959 QCOMPARE(item.pos(), QPointF());
7960 QCOMPARE(item.opacity(), o);
7961 item.setRotation(0.0);
7963 item.setTransformOriginPoint(0.0, 0.0);
7964 QCOMPARE(item.changes.size(), 14); // rotation + scale + origin
7965 QCOMPARE(item.rotation(), qreal(0.0));
7966 QCOMPARE(item.scale(), qreal(1.0));
7967 QCOMPARE(item.transformOriginPoint(), QPointF(0.0, 0.0));
7969 QCOMPARE(item.changes, QList<QGraphicsItem::GraphicsItemChange>()
7970 << QGraphicsItem::ItemOpacityChange
7971 << QGraphicsItem::ItemOpacityHasChanged
7972 << QGraphicsItem::ItemFlagsChange
7973 << QGraphicsItem::ItemFlagsHaveChanged
7974 << QGraphicsItem::ItemTransformChange
7975 << QGraphicsItem::ItemTransformHasChanged
7976 << QGraphicsItem::ItemPositionChange
7977 << QGraphicsItem::ItemPositionHasChanged
7978 << QGraphicsItem::ItemRotationChange
7979 << QGraphicsItem::ItemRotationHasChanged
7980 << QGraphicsItem::ItemScaleChange
7981 << QGraphicsItem::ItemScaleHasChanged
7982 << QGraphicsItem::ItemTransformOriginPointChange
7983 << QGraphicsItem::ItemTransformOriginPointHasChanged);
7986 // Make sure we update moved items correctly.
7987 void tst_QGraphicsItem::moveItem()
7989 QGraphicsScene scene;
7990 scene.setSceneRect(-50, -50, 200, 200);
7992 MyGraphicsView view(&scene);
7995 qt_x11_wait_for_window_manager(&view);
7999 EventTester *parent = new EventTester;
8000 EventTester *child = new EventTester(parent);
8001 EventTester *grandChild = new EventTester(child);
8003 #define RESET_COUNTERS \
8004 parent->repaints = 0; \
8005 child->repaints = 0; \
8006 grandChild->repaints = 0; \
8009 scene.addItem(parent);
8014 // Item's boundingRect: (-10, -10, 20, 20).
8015 QRect parentDeviceBoundingRect = parent->deviceTransform(view.viewportTransform())
8016 .mapRect(parent->boundingRect()).toAlignedRect()
8017 .adjusted(-2, -2, 2, 2); // Adjusted for antialiasing.
8019 parent->setPos(20, 20);
8020 qApp->processEvents();
8021 QCOMPARE(parent->repaints, 1);
8022 QCOMPARE(view.repaints, 1);
8023 QRegion expectedParentRegion = parentDeviceBoundingRect; // old position
8024 parentDeviceBoundingRect.translate(20, 20);
8025 expectedParentRegion += parentDeviceBoundingRect; // new position
8026 COMPARE_REGIONS(view.paintedRegion, expectedParentRegion);
8030 child->setPos(20, 20);
8031 qApp->processEvents();
8032 QCOMPARE(parent->repaints, 1);
8033 QCOMPARE(child->repaints, 1);
8034 QCOMPARE(view.repaints, 1);
8035 const QRegion expectedChildRegion = expectedParentRegion.translated(20, 20);
8036 COMPARE_REGIONS(view.paintedRegion, expectedChildRegion);
8040 grandChild->setPos(20, 20);
8041 qApp->processEvents();
8042 QCOMPARE(parent->repaints, 1);
8043 QCOMPARE(child->repaints, 1);
8044 QCOMPARE(grandChild->repaints, 1);
8045 QCOMPARE(view.repaints, 1);
8046 const QRegion expectedGrandChildRegion = expectedParentRegion.translated(40, 40);
8047 COMPARE_REGIONS(view.paintedRegion, expectedGrandChildRegion);
8051 parent->translate(20, 20);
8052 qApp->processEvents();
8053 QCOMPARE(parent->repaints, 1);
8054 QCOMPARE(child->repaints, 1);
8055 QCOMPARE(grandChild->repaints, 1);
8056 QCOMPARE(view.repaints, 1);
8057 expectedParentRegion.translate(20, 20);
8058 expectedParentRegion += expectedChildRegion.translated(20, 20);
8059 expectedParentRegion += expectedGrandChildRegion.translated(20, 20);
8060 COMPARE_REGIONS(view.paintedRegion, expectedParentRegion);
8063 void tst_QGraphicsItem::moveLineItem()
8065 QGraphicsScene scene;
8066 scene.setSceneRect(0, 0, 200, 200);
8067 QGraphicsLineItem *item = new QGraphicsLineItem(0, 0, 100, 0);
8068 item->setPos(50, 50);
8069 scene.addItem(item);
8071 MyGraphicsView view(&scene);
8074 qt_x11_wait_for_window_manager(&view);
8079 QRectF brect = item->boundingRect();
8080 // Do same adjustments as in qgraphicsscene.cpp
8082 brect.adjust(qreal(-0.00001), 0, qreal(0.00001), 0);
8083 if (!brect.height())
8084 brect.adjust(0, qreal(-0.00001), 0, qreal(0.00001));
8085 const QRect itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform())
8086 .mapRect(brect).toAlignedRect();
8087 QRegion expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2); // antialiasing
8089 // Make sure the calculated region is correct.
8092 QTRY_COMPARE(view.paintedRegion, expectedRegion);
8095 // Old position: (50, 50)
8096 item->setPos(50, 100);
8097 expectedRegion += expectedRegion.translated(0, 50);
8099 QCOMPARE(view.paintedRegion, expectedRegion);
8102 void tst_QGraphicsItem::sorting_data()
8104 QTest::addColumn<int>("index");
8106 QTest::newRow("NoIndex") << int(QGraphicsScene::NoIndex);
8107 QTest::newRow("BspTreeIndex") << int(QGraphicsScene::BspTreeIndex);
8110 void tst_QGraphicsItem::sorting()
8112 if (PlatformQuirks::isAutoMaximizing())
8113 QSKIP("Skipped because Platform is auto maximizing");
8115 _paintedItems.clear();
8117 QGraphicsScene scene;
8118 QGraphicsItem *grid[100][100];
8119 for (int x = 0; x < 100; ++x) {
8120 for (int y = 0; y < 100; ++y) {
8121 PainterItem *item = new PainterItem;
8122 item->setPos(x * 25, y * 25);
8123 item->setData(0, QString("%1x%2").arg(x).arg(y));
8125 scene.addItem(item);
8129 PainterItem *item1 = new PainterItem;
8130 PainterItem *item2 = new PainterItem;
8131 item1->setData(0, "item1");
8132 item2->setData(0, "item2");
8133 scene.addItem(item1);
8134 scene.addItem(item2);
8136 QGraphicsView view(&scene);
8137 view.setResizeAnchor(QGraphicsView::NoAnchor);
8138 view.setTransformationAnchor(QGraphicsView::NoAnchor);
8139 view.resize(120, 100);
8140 view.setFrameStyle(0);
8143 qt_x11_wait_for_window_manager(&view);
8147 _paintedItems.clear();
8149 view.viewport()->repaint();
8150 #if defined(Q_WS_MAC)
8151 // There's no difference between repaint and update on the Mac,
8152 // so we have to process events here to make sure we get the event.
8156 QCOMPARE(_paintedItems, QList<QGraphicsItem *>()
8157 << grid[0][0] << grid[0][1] << grid[0][2] << grid[0][3]
8158 << grid[1][0] << grid[1][1] << grid[1][2] << grid[1][3]
8159 << grid[2][0] << grid[2][1] << grid[2][2] << grid[2][3]
8160 << grid[3][0] << grid[3][1] << grid[3][2] << grid[3][3]
8161 << grid[4][0] << grid[4][1] << grid[4][2] << grid[4][3]
8165 void tst_QGraphicsItem::itemHasNoContents()
8167 PainterItem *item1 = new PainterItem;
8168 PainterItem *item2 = new PainterItem;
8169 item2->setParentItem(item1);
8170 item2->setPos(50, 50);
8171 item1->setFlag(QGraphicsItem::ItemHasNoContents);
8172 item1->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
8174 QGraphicsScene scene;
8175 scene.addItem(item1);
8177 QGraphicsView view(&scene);
8179 QTest::qWaitForWindowShown(&view);
8180 QTRY_VERIFY(!_paintedItems.isEmpty());
8182 _paintedItems.clear();
8184 view.viewport()->repaint();
8186 // There's no difference between update() and repaint() on the Mac,
8187 // so we have to process events here to make sure we get the event.
8191 QTRY_COMPARE(_paintedItems, QList<QGraphicsItem *>() << item2);
8194 void tst_QGraphicsItem::hitTestUntransformableItem()
8196 QGraphicsScene scene;
8197 scene.setSceneRect(-100, -100, 200, 200);
8199 QGraphicsView view(&scene);
8202 qt_x11_wait_for_window_manager(&view);
8206 // Confuse the BSP with dummy items.
8207 QGraphicsRectItem *dummy = new QGraphicsRectItem(0, 0, 20, 20);
8208 dummy->setPos(-100, -100);
8209 scene.addItem(dummy);
8210 for (int i = 0; i < 100; ++i) {
8211 QGraphicsItem *parent = dummy;
8212 dummy = new QGraphicsRectItem(0, 0, 20, 20);
8213 dummy->setPos(-100 + i, -100 + i);
8214 dummy->setParentItem(parent);
8217 QGraphicsRectItem *item1 = new QGraphicsRectItem(0, 0, 20, 20);
8218 item1->setPos(-200, -200);
8220 QGraphicsRectItem *item2 = new QGraphicsRectItem(0, 0, 20, 20);
8221 item2->setFlag(QGraphicsItem::ItemIgnoresTransformations);
8222 item2->setParentItem(item1);
8223 item2->setPos(200, 200);
8225 QGraphicsRectItem *item3 = new QGraphicsRectItem(0, 0, 20, 20);
8226 item3->setParentItem(item2);
8227 item3->setPos(80, 80);
8229 scene.addItem(item1);
8232 QList<QGraphicsItem *> items = scene.items(QPointF(80, 80));
8233 QCOMPARE(items.size(), 1);
8234 QCOMPARE(items.at(0), static_cast<QGraphicsItem*>(item3));
8236 scene.setItemIndexMethod(QGraphicsScene::NoIndex);
8239 items = scene.items(QPointF(80, 80));
8240 QCOMPARE(items.size(), 1);
8241 QCOMPARE(items.at(0), static_cast<QGraphicsItem*>(item3));
8244 void tst_QGraphicsItem::hitTestGraphicsEffectItem()
8246 QGraphicsScene scene;
8247 scene.setSceneRect(-100, -100, 200, 200);
8251 QGraphicsView view(&scene, &toplevel);
8252 toplevel.resize(300, 300);
8255 qt_x11_wait_for_window_manager(&toplevel);
8259 // Confuse the BSP with dummy items.
8260 QGraphicsRectItem *dummy = new QGraphicsRectItem(0, 0, 20, 20);
8261 dummy->setPos(-100, -100);
8262 scene.addItem(dummy);
8263 for (int i = 0; i < 100; ++i) {
8264 QGraphicsItem *parent = dummy;
8265 dummy = new QGraphicsRectItem(0, 0, 20, 20);
8266 dummy->setPos(-100 + i, -100 + i);
8267 dummy->setParentItem(parent);
8270 const QRectF itemBoundingRect(0, 0, 20, 20);
8271 EventTester *item1 = new EventTester;
8272 item1->br = itemBoundingRect;
8273 item1->setPos(-200, -200);
8274 item1->brush = Qt::red;
8276 EventTester *item2 = new EventTester;
8277 item2->br = itemBoundingRect;
8278 item2->setFlag(QGraphicsItem::ItemIgnoresTransformations);
8279 item2->setParentItem(item1);
8280 item2->setPos(200, 200);
8281 item2->brush = Qt::green;
8283 EventTester *item3 = new EventTester;
8284 item3->br = itemBoundingRect;
8285 item3->setParentItem(item2);
8286 item3->setPos(80, 80);
8287 item3->brush = Qt::blue;
8289 scene.addItem(item1);
8292 item1->repaints = 0;
8293 item2->repaints = 0;
8294 item3->repaints = 0;
8296 // Apply shadow effect to the entire sub-tree.
8297 QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect;
8298 shadow->setOffset(-20, -20);
8299 item1->setGraphicsEffect(shadow);
8302 // Make sure all visible items are repainted.
8303 QCOMPARE(item1->repaints, 1);
8304 QCOMPARE(item2->repaints, 1);
8305 QCOMPARE(item3->repaints, 1);
8307 // Make sure an item doesn't respond to a click on its shadow.
8308 QList<QGraphicsItem *> items = scene.items(QPointF(75, 75));
8309 QVERIFY(items.isEmpty());
8310 items = scene.items(QPointF(80, 80));
8311 QCOMPARE(items.size(), 1);
8312 QCOMPARE(items.at(0), static_cast<QGraphicsItem *>(item3));
8314 scene.setItemIndexMethod(QGraphicsScene::NoIndex);
8317 items = scene.items(QPointF(75, 75));
8318 QVERIFY(items.isEmpty());
8319 items = scene.items(QPointF(80, 80));
8320 QCOMPARE(items.size(), 1);
8321 QCOMPARE(items.at(0), static_cast<QGraphicsItem *>(item3));
8324 void tst_QGraphicsItem::focusProxy()
8326 QGraphicsScene scene;
8327 QEvent activate(QEvent::WindowActivate);
8328 QApplication::sendEvent(&scene, &activate);
8330 QGraphicsItem *item = scene.addRect(0, 0, 10, 10);
8331 item->setFlag(QGraphicsItem::ItemIsFocusable);
8332 QVERIFY(!item->focusProxy());
8334 QGraphicsItem *item2 = scene.addRect(0, 0, 10, 10);
8335 item2->setFlag(QGraphicsItem::ItemIsFocusable);
8336 item->setFocusProxy(item2);
8337 QCOMPARE(item->focusProxy(), item2);
8340 QVERIFY(item->hasFocus());
8341 QVERIFY(item2->hasFocus());
8343 // Try to make a focus chain loop
8345 QTextStream stream(&err);
8346 stream << "QGraphicsItem::setFocusProxy: "
8347 << (void*)item << " is already in the focus proxy chain" << flush;
8348 QTest::ignoreMessage(QtWarningMsg, err.toLatin1().constData());
8349 item2->setFocusProxy(item); // fails
8350 QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2);
8351 QCOMPARE(item2->focusProxy(), (QGraphicsItem *)0);
8353 // Try to assign self as focus proxy
8354 QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::setFocusProxy: cannot assign self as focus proxy");
8355 item->setFocusProxy(item); // fails
8356 QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2);
8357 QCOMPARE(item2->focusProxy(), (QGraphicsItem *)0);
8359 // Reset the focus proxy
8360 item->setFocusProxy(0);
8361 QCOMPARE(item->focusProxy(), (QGraphicsItem *)0);
8362 QVERIFY(!item->hasFocus());
8363 QVERIFY(item2->hasFocus());
8366 item->setFocusProxy(item2);
8367 QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2);
8369 QCOMPARE(item->focusProxy(), (QGraphicsItem *)0);
8371 // Test event delivery
8372 item2 = scene.addRect(0, 0, 10, 10);
8373 item2->setFlag(QGraphicsItem::ItemIsFocusable);
8374 item->setFocusProxy(item2);
8377 EventSpy focusInSpy(&scene, item, QEvent::FocusIn);
8378 EventSpy focusOutSpy(&scene, item, QEvent::FocusOut);
8379 EventSpy focusInSpy2(&scene, item2, QEvent::FocusIn);
8380 EventSpy focusOutSpy2(&scene, item2, QEvent::FocusOut);
8381 QCOMPARE(focusInSpy.count(), 0);
8382 QCOMPARE(focusOutSpy.count(), 0);
8383 QCOMPARE(focusInSpy2.count(), 0);
8384 QCOMPARE(focusOutSpy2.count(), 0);
8387 QCOMPARE(focusInSpy.count(), 0);
8388 QCOMPARE(focusInSpy2.count(), 1);
8390 QCOMPARE(focusOutSpy.count(), 0);
8391 QCOMPARE(focusOutSpy2.count(), 1);
8393 // Test two items proxying one item.
8394 QGraphicsItem *item3 = scene.addRect(0, 0, 10, 10);
8395 item3->setFlag(QGraphicsItem::ItemIsFocusable);
8396 item3->setFocusProxy(item2); // item and item3 use item2 as proxy
8398 QCOMPARE(item->focusProxy(), item2);
8399 QCOMPARE(item2->focusProxy(), (QGraphicsItem *)0);
8400 QCOMPARE(item3->focusProxy(), item2);
8402 QCOMPARE(item->focusProxy(), (QGraphicsItem *)0);
8403 QCOMPARE(item3->focusProxy(), (QGraphicsItem *)0);
8406 void tst_QGraphicsItem::subFocus()
8408 // Construct a text item that's not part of a scene (yet)
8409 // and has no parent. Setting focus on it will not make
8410 // the item gain input focus; that requires a scene. But
8411 // it does set subfocus, indicating that the item wishes
8412 // to gain focus later.
8413 QGraphicsTextItem *text = new QGraphicsTextItem("Hello");
8414 text->setTextInteractionFlags(Qt::TextEditorInteraction);
8415 QVERIFY(!text->hasFocus());
8417 QVERIFY(!text->hasFocus());
8418 QCOMPARE(text->focusItem(), (QGraphicsItem *)text);
8421 QGraphicsTextItem *text2 = new QGraphicsTextItem("Hi");
8422 text2->setTextInteractionFlags(Qt::TextEditorInteraction);
8423 text2->setPos(30, 30);
8425 // Add both items to a scene and check that it's text that
8427 QGraphicsScene scene;
8428 QEvent activate(QEvent::WindowActivate);
8429 QApplication::sendEvent(&scene, &activate);
8431 scene.addItem(text);
8432 scene.addItem(text2);
8433 QVERIFY(text->hasFocus());
8435 text->setData(0, "text");
8436 text2->setData(0, "text2");
8438 // Remove text2 and set subfocus on it. Then readd. Reparent it onto the
8439 // other item and see that it gains input focus.
8440 scene.removeItem(text2);
8442 scene.addItem(text2);
8443 QCOMPARE(text2->focusItem(), (QGraphicsItem *)text2);
8444 text2->setParentItem(text);
8445 QCOMPARE(text->focusItem(), (QGraphicsItem *)text2);
8446 QCOMPARE(text2->focusItem(), (QGraphicsItem *)text2);
8447 QVERIFY(!text->hasFocus());
8448 QVERIFY(text2->hasFocus());
8450 // Remove both items from the scene, restore subfocus and
8451 // readd them. Now the subfocus should kick in and give
8453 scene.removeItem(text);
8454 QCOMPARE(text->focusItem(), (QGraphicsItem *)0);
8455 QCOMPARE(text2->focusItem(), (QGraphicsItem *)0);
8457 QCOMPARE(text->focusItem(), (QGraphicsItem *)text2);
8458 QCOMPARE(text2->focusItem(), (QGraphicsItem *)text2);
8459 scene.addItem(text);
8461 // Hiding and showing text should pass focus to text2.
8462 QCOMPARE(text->focusItem(), (QGraphicsItem *)text2);
8463 QVERIFY(text2->hasFocus());
8465 // Subfocus should repropagate to root when reparenting.
8466 QGraphicsRectItem *rect = new QGraphicsRectItem;
8467 QGraphicsRectItem *rect2 = new QGraphicsRectItem(rect);
8468 QGraphicsRectItem *rect3 = new QGraphicsRectItem(rect2);
8469 rect3->setFlag(QGraphicsItem::ItemIsFocusable);
8471 text->setData(0, "text");
8472 text2->setData(0, "text2");
8473 rect->setData(0, "rect");
8474 rect2->setData(0, "rect2");
8475 rect3->setData(0, "rect3");
8478 QVERIFY(!rect3->hasFocus());
8479 QCOMPARE(rect->focusItem(), (QGraphicsItem *)rect3);
8480 QCOMPARE(rect2->focusItem(), (QGraphicsItem *)rect3);
8481 QCOMPARE(rect3->focusItem(), (QGraphicsItem *)rect3);
8482 rect->setParentItem(text2);
8483 QCOMPARE(text->focusItem(), (QGraphicsItem *)rect3);
8484 QCOMPARE(text2->focusItem(), (QGraphicsItem *)rect3);
8485 QCOMPARE(rect->focusItem(), (QGraphicsItem *)rect3);
8486 QCOMPARE(rect2->focusItem(), (QGraphicsItem *)rect3);
8487 QCOMPARE(rect3->focusItem(), (QGraphicsItem *)rect3);
8488 QVERIFY(!rect->hasFocus());
8489 QVERIFY(!rect2->hasFocus());
8490 QVERIFY(rect3->hasFocus());
8493 QCOMPARE(text->focusItem(), (QGraphicsItem *)0);
8494 QCOMPARE(text2->focusItem(), (QGraphicsItem *)0);
8495 QCOMPARE(rect->focusItem(), (QGraphicsItem *)0);
8498 void tst_QGraphicsItem::focusProxyDeletion()
8500 QGraphicsRectItem *rect = new QGraphicsRectItem;
8501 QGraphicsRectItem *rect2 = new QGraphicsRectItem;
8502 rect->setFocusProxy(rect2);
8503 QCOMPARE(rect->focusProxy(), (QGraphicsItem *)rect2);
8506 QCOMPARE(rect->focusProxy(), (QGraphicsItem *)0);
8508 rect2 = new QGraphicsRectItem;
8509 rect->setFocusProxy(rect2);
8510 delete rect; // don't crash
8512 rect = new QGraphicsRectItem;
8513 rect->setFocusProxy(rect2);
8514 QGraphicsScene *scene = new QGraphicsScene;
8515 scene->addItem(rect);
8516 scene->addItem(rect2);
8518 QCOMPARE(rect->focusProxy(), (QGraphicsItem *)0);
8520 rect2 = new QGraphicsRectItem;
8521 QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::setFocusProxy: focus proxy must be in same scene");
8522 rect->setFocusProxy(rect2);
8523 QCOMPARE(rect->focusProxy(), (QGraphicsItem *)0);
8524 scene->addItem(rect2);
8525 rect->setFocusProxy(rect2);
8526 QCOMPARE(rect->focusProxy(), (QGraphicsItem *)rect2);
8527 delete rect; // don't crash
8529 rect = new QGraphicsRectItem;
8530 rect2 = new QGraphicsRectItem;
8531 rect->setFocusProxy(rect2);
8532 QCOMPARE(rect->focusProxy(), (QGraphicsItem *)rect2);
8533 scene->addItem(rect);
8534 scene->addItem(rect2);
8535 rect->setFocusProxy(rect2);
8536 delete scene; // don't crash
8539 void tst_QGraphicsItem::negativeZStacksBehindParent()
8541 QGraphicsRectItem rect;
8542 QCOMPARE(rect.zValue(), qreal(0.0));
8543 QVERIFY(!(rect.flags() & QGraphicsItem::ItemNegativeZStacksBehindParent));
8544 QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
8546 QCOMPARE(rect.zValue(), qreal(-1.0));
8547 QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
8549 rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent);
8550 QVERIFY(rect.flags() & QGraphicsItem::ItemNegativeZStacksBehindParent);
8551 QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
8553 QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent);
8555 QVERIFY(!(rect.flags() & QGraphicsItem::ItemStacksBehindParent));
8556 rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, false);
8558 rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, true);
8559 QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent);
8560 rect.setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, false);
8561 QVERIFY(rect.flags() & QGraphicsItem::ItemStacksBehindParent);
8564 void tst_QGraphicsItem::setGraphicsEffect()
8566 // Check that we don't have any effect by default.
8567 QGraphicsItem *item = new QGraphicsRectItem(0, 0, 10, 10);
8568 QVERIFY(!item->graphicsEffect());
8571 QPointer<QGraphicsEffect> blurEffect = new QGraphicsBlurEffect;
8572 item->setGraphicsEffect(blurEffect);
8573 QCOMPARE(item->graphicsEffect(), static_cast<QGraphicsEffect *>(blurEffect));
8575 // Ensure the existing effect is deleted when setting a new one.
8576 QPointer<QGraphicsEffect> shadowEffect = new QGraphicsDropShadowEffect;
8577 item->setGraphicsEffect(shadowEffect);
8578 QVERIFY(!blurEffect);
8579 QCOMPARE(item->graphicsEffect(), static_cast<QGraphicsEffect *>(shadowEffect));
8580 blurEffect = new QGraphicsBlurEffect;
8582 // Ensure the effect is uninstalled when setting it on a new target.
8583 QGraphicsItem *anotherItem = new QGraphicsRectItem(0, 0, 10, 10);
8584 anotherItem->setGraphicsEffect(blurEffect);
8585 item->setGraphicsEffect(blurEffect);
8586 QVERIFY(!anotherItem->graphicsEffect());
8587 QVERIFY(!shadowEffect);
8589 // Ensure the existing effect is deleted when deleting the item.
8591 QVERIFY(!blurEffect);
8594 // Ensure the effect is uninstalled when deleting it
8595 item = new QGraphicsRectItem(0, 0, 10, 10);
8596 blurEffect = new QGraphicsBlurEffect;
8597 item->setGraphicsEffect(blurEffect);
8599 QVERIFY(!item->graphicsEffect());
8601 // Ensure the existing effect is uninstalled and deleted when setting a null effect
8602 blurEffect = new QGraphicsBlurEffect;
8603 item->setGraphicsEffect(blurEffect);
8604 item->setGraphicsEffect(0);
8605 QVERIFY(!item->graphicsEffect());
8606 QVERIFY(!blurEffect);
8611 void tst_QGraphicsItem::panel()
8613 QGraphicsScene scene;
8615 QGraphicsRectItem *panel1 = new QGraphicsRectItem;
8616 QGraphicsRectItem *panel2 = new QGraphicsRectItem;
8617 QGraphicsRectItem *panel3 = new QGraphicsRectItem;
8618 QGraphicsRectItem *panel4 = new QGraphicsRectItem;
8619 QGraphicsRectItem *notPanel1 = new QGraphicsRectItem;
8620 QGraphicsRectItem *notPanel2 = new QGraphicsRectItem;
8621 panel1->setFlag(QGraphicsItem::ItemIsPanel);
8622 panel2->setFlag(QGraphicsItem::ItemIsPanel);
8623 panel3->setFlag(QGraphicsItem::ItemIsPanel);
8624 panel4->setFlag(QGraphicsItem::ItemIsPanel);
8625 scene.addItem(panel1);
8626 scene.addItem(panel2);
8627 scene.addItem(panel3);
8628 scene.addItem(panel4);
8629 scene.addItem(notPanel1);
8630 scene.addItem(notPanel2);
8632 EventSpy spy_activate_panel1(&scene, panel1, QEvent::WindowActivate);
8633 EventSpy spy_deactivate_panel1(&scene, panel1, QEvent::WindowDeactivate);
8634 EventSpy spy_activate_panel2(&scene, panel2, QEvent::WindowActivate);
8635 EventSpy spy_deactivate_panel2(&scene, panel2, QEvent::WindowDeactivate);
8636 EventSpy spy_activate_panel3(&scene, panel3, QEvent::WindowActivate);
8637 EventSpy spy_deactivate_panel3(&scene, panel3, QEvent::WindowDeactivate);
8638 EventSpy spy_activate_panel4(&scene, panel4, QEvent::WindowActivate);
8639 EventSpy spy_deactivate_panel4(&scene, panel4, QEvent::WindowDeactivate);
8640 EventSpy spy_activate_notPanel1(&scene, notPanel1, QEvent::WindowActivate);
8641 EventSpy spy_deactivate_notPanel1(&scene, notPanel1, QEvent::WindowDeactivate);
8642 EventSpy spy_activate_notPanel2(&scene, notPanel1, QEvent::WindowActivate);
8643 EventSpy spy_deactivate_notPanel2(&scene, notPanel1, QEvent::WindowDeactivate);
8645 QCOMPARE(spy_activate_panel1.count(), 0);
8646 QCOMPARE(spy_deactivate_panel1.count(), 0);
8647 QCOMPARE(spy_activate_panel2.count(), 0);
8648 QCOMPARE(spy_deactivate_panel2.count(), 0);
8649 QCOMPARE(spy_activate_panel3.count(), 0);
8650 QCOMPARE(spy_deactivate_panel3.count(), 0);
8651 QCOMPARE(spy_activate_panel4.count(), 0);
8652 QCOMPARE(spy_deactivate_panel4.count(), 0);
8653 QCOMPARE(spy_activate_notPanel1.count(), 0);
8654 QCOMPARE(spy_deactivate_notPanel1.count(), 0);
8655 QCOMPARE(spy_activate_notPanel2.count(), 0);
8656 QCOMPARE(spy_deactivate_notPanel2.count(), 0);
8658 QVERIFY(!scene.activePanel());
8659 QVERIFY(!scene.isActive());
8661 QEvent activate(QEvent::WindowActivate);
8662 QEvent deactivate(QEvent::WindowDeactivate);
8664 QApplication::sendEvent(&scene, &activate);
8666 // No previous activation, so the scene is active.
8667 QVERIFY(scene.isActive());
8668 QCOMPARE(scene.activePanel(), (QGraphicsItem *)panel1);
8669 QVERIFY(panel1->isActive());
8670 QVERIFY(!panel2->isActive());
8671 QVERIFY(!panel3->isActive());
8672 QVERIFY(!panel4->isActive());
8673 QVERIFY(!notPanel1->isActive());
8674 QVERIFY(!notPanel2->isActive());
8675 QCOMPARE(spy_deactivate_notPanel1.count(), 0);
8676 QCOMPARE(spy_deactivate_notPanel2.count(), 0);
8677 QCOMPARE(spy_activate_panel1.count(), 1);
8678 QCOMPARE(spy_activate_panel2.count(), 0);
8679 QCOMPARE(spy_activate_panel3.count(), 0);
8680 QCOMPARE(spy_activate_panel4.count(), 0);
8682 // Switch back to scene.
8683 scene.setActivePanel(0);
8684 QVERIFY(!scene.activePanel());
8685 QVERIFY(!panel1->isActive());
8686 QVERIFY(!panel2->isActive());
8687 QVERIFY(!panel3->isActive());
8688 QVERIFY(!panel4->isActive());
8689 QVERIFY(notPanel1->isActive());
8690 QVERIFY(notPanel2->isActive());
8691 QCOMPARE(spy_activate_notPanel1.count(), 1);
8692 QCOMPARE(spy_activate_notPanel2.count(), 1);
8694 // Deactivate the scene
8695 QApplication::sendEvent(&scene, &deactivate);
8696 QVERIFY(!scene.activePanel());
8697 QVERIFY(!panel1->isActive());
8698 QVERIFY(!panel2->isActive());
8699 QVERIFY(!panel3->isActive());
8700 QVERIFY(!panel4->isActive());
8701 QVERIFY(!notPanel1->isActive());
8702 QVERIFY(!notPanel2->isActive());
8703 QCOMPARE(spy_deactivate_notPanel1.count(), 1);
8704 QCOMPARE(spy_deactivate_notPanel2.count(), 1);
8706 // Reactivate the scene
8707 QApplication::sendEvent(&scene, &activate);
8708 QVERIFY(!scene.activePanel());
8709 QVERIFY(!panel1->isActive());
8710 QVERIFY(!panel2->isActive());
8711 QVERIFY(!panel3->isActive());
8712 QVERIFY(!panel4->isActive());
8713 QVERIFY(notPanel1->isActive());
8714 QVERIFY(notPanel2->isActive());
8715 QCOMPARE(spy_activate_notPanel1.count(), 2);
8716 QCOMPARE(spy_activate_notPanel2.count(), 2);
8719 scene.setActivePanel(panel1);
8720 QVERIFY(panel1->isActive());
8721 QCOMPARE(spy_deactivate_notPanel1.count(), 2);
8722 QCOMPARE(spy_deactivate_notPanel2.count(), 2);
8723 QCOMPARE(spy_activate_panel1.count(), 2);
8725 // Deactivate the scene
8726 QApplication::sendEvent(&scene, &deactivate);
8727 QVERIFY(!panel1->isActive());
8728 QCOMPARE(spy_deactivate_panel1.count(), 2);
8730 // Reactivate the scene
8731 QApplication::sendEvent(&scene, &activate);
8732 QVERIFY(panel1->isActive());
8733 QCOMPARE(spy_activate_panel1.count(), 3);
8735 // Deactivate the scene
8736 QApplication::sendEvent(&scene, &deactivate);
8737 QVERIFY(!panel1->isActive());
8738 QVERIFY(!scene.activePanel());
8739 scene.setActivePanel(0);
8741 // Reactivate the scene
8742 QApplication::sendEvent(&scene, &activate);
8743 QVERIFY(!panel1->isActive());
8746 void tst_QGraphicsItem::panelWithFocusItem()
8748 QGraphicsScene scene;
8749 QEvent activate(QEvent::WindowActivate);
8750 QApplication::sendEvent(&scene, &activate);
8752 QGraphicsRectItem *parentPanel = new QGraphicsRectItem;
8753 QGraphicsRectItem *parentPanelFocusItem = new QGraphicsRectItem(parentPanel);
8754 parentPanel->setFlag(QGraphicsItem::ItemIsPanel);
8755 parentPanelFocusItem->setFlag(QGraphicsItem::ItemIsFocusable);
8756 parentPanelFocusItem->setFocus();
8757 scene.addItem(parentPanel);
8759 QVERIFY(parentPanel->isActive());
8760 QVERIFY(parentPanelFocusItem->hasFocus());
8761 QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
8762 QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
8764 QGraphicsRectItem *childPanel = new QGraphicsRectItem;
8765 QGraphicsRectItem *childPanelFocusItem = new QGraphicsRectItem(childPanel);
8766 childPanel->setFlag(QGraphicsItem::ItemIsPanel);
8767 childPanelFocusItem->setFlag(QGraphicsItem::ItemIsFocusable);
8768 childPanelFocusItem->setFocus();
8770 QVERIFY(!childPanelFocusItem->hasFocus());
8771 QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)childPanelFocusItem);
8772 QCOMPARE(childPanelFocusItem->focusItem(), (QGraphicsItem *)childPanelFocusItem);
8774 childPanel->setParentItem(parentPanel);
8776 QVERIFY(!parentPanel->isActive());
8777 QVERIFY(!parentPanelFocusItem->hasFocus());
8778 QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
8779 QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
8781 QVERIFY(childPanel->isActive());
8782 QVERIFY(childPanelFocusItem->hasFocus());
8783 QCOMPARE(childPanel->focusItem(), (QGraphicsItem *)childPanelFocusItem);
8784 QCOMPARE(childPanelFocusItem->focusItem(), (QGraphicsItem *)childPanelFocusItem);
8788 QVERIFY(parentPanel->isActive());
8789 QVERIFY(parentPanelFocusItem->hasFocus());
8790 QCOMPARE(parentPanel->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
8791 QCOMPARE(parentPanelFocusItem->focusItem(), (QGraphicsItem *)parentPanelFocusItem);
8794 void tst_QGraphicsItem::addPanelToActiveScene()
8796 QGraphicsScene scene;
8797 QVERIFY(!scene.isActive());
8799 QGraphicsRectItem *rect = new QGraphicsRectItem;
8800 scene.addItem(rect);
8801 QVERIFY(!rect->isActive());
8802 scene.removeItem(rect);
8804 QEvent activate(QEvent::WindowActivate);
8805 QEvent deactivate(QEvent::WindowDeactivate);
8807 QApplication::sendEvent(&scene, &activate);
8808 QVERIFY(scene.isActive());
8809 scene.addItem(rect);
8810 QVERIFY(rect->isActive());
8811 scene.removeItem(rect);
8813 rect->setFlag(QGraphicsItem::ItemIsPanel);
8814 scene.addItem(rect);
8815 QVERIFY(rect->isActive());
8816 QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect);
8818 QGraphicsRectItem *rect2 = new QGraphicsRectItem;
8819 scene.addItem(rect2);
8820 QVERIFY(rect->isActive());
8821 QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect);
8824 void tst_QGraphicsItem::activate()
8826 QGraphicsScene scene;
8827 QGraphicsRectItem *rect = scene.addRect(-10, -10, 20, 20);
8828 QVERIFY(!rect->isActive());
8830 QEvent activate(QEvent::WindowActivate);
8831 QEvent deactivate(QEvent::WindowDeactivate);
8833 QApplication::sendEvent(&scene, &activate);
8835 // Non-panel item (active when scene is active).
8836 QVERIFY(rect->isActive());
8838 QGraphicsRectItem *rect2 = new QGraphicsRectItem;
8839 rect2->setFlag(QGraphicsItem::ItemIsPanel);
8840 QGraphicsRectItem *rect3 = new QGraphicsRectItem;
8841 rect3->setFlag(QGraphicsItem::ItemIsPanel);
8843 // Test normal activation.
8844 QVERIFY(!rect2->isActive());
8845 scene.addItem(rect2);
8846 QVERIFY(rect2->isActive()); // first panel item is activated
8847 scene.addItem(rect3);
8848 QVERIFY(!rect3->isActive()); // second panel item is _not_ activated
8849 rect3->setActive(true);
8850 QVERIFY(rect3->isActive());
8851 scene.removeItem(rect3);
8852 QVERIFY(!rect3->isActive()); // no panel is active anymore
8853 QCOMPARE(scene.activePanel(), (QGraphicsItem *)0);
8854 scene.addItem(rect3);
8855 QVERIFY(rect3->isActive()); // second panel item is activated
8857 // Test pending activation.
8858 scene.removeItem(rect3);
8859 rect2->setActive(true);
8860 QVERIFY(rect2->isActive()); // first panel item is activated
8861 rect3->setActive(true);
8862 QVERIFY(!rect3->isActive()); // not active (yet)
8863 scene.addItem(rect3);
8864 QVERIFY(rect3->isActive()); // now becomes active
8866 // Test pending deactivation.
8867 scene.removeItem(rect3);
8868 rect3->setActive(false);
8869 scene.addItem(rect3);
8870 QVERIFY(!rect3->isActive()); // doesn't become active
8872 // Child of panel activation.
8873 rect3->setActive(true);
8874 QGraphicsRectItem *rect4 = new QGraphicsRectItem;
8875 rect4->setFlag(QGraphicsItem::ItemIsPanel);
8876 QGraphicsRectItem *rect5 = new QGraphicsRectItem(rect4);
8877 QGraphicsRectItem *rect6 = new QGraphicsRectItem(rect5);
8878 scene.addItem(rect4);
8879 QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect3);
8880 scene.removeItem(rect4);
8881 rect6->setActive(true);
8882 scene.addItem(rect4);
8883 QVERIFY(rect4->isActive());
8884 QVERIFY(rect5->isActive());
8885 QVERIFY(rect6->isActive());
8886 QCOMPARE(scene.activePanel(), (QGraphicsItem *)rect4);
8887 scene.removeItem(rect4); // no active panel
8888 rect6->setActive(false);
8889 scene.addItem(rect4);
8890 QVERIFY(!rect4->isActive());
8891 QVERIFY(!rect5->isActive());
8892 QVERIFY(!rect6->isActive());
8893 QCOMPARE(scene.activePanel(), (QGraphicsItem *)0);
8895 // Controlling auto-activation when the scene changes activation.
8896 rect4->setActive(true);
8897 QApplication::sendEvent(&scene, &deactivate);
8898 QVERIFY(!scene.isActive());
8899 QVERIFY(!rect4->isActive());
8900 rect4->setActive(false);
8901 QApplication::sendEvent(&scene, &activate);
8902 QVERIFY(scene.isActive());
8903 QVERIFY(!scene.activePanel());
8904 QVERIFY(!rect4->isActive());
8907 void tst_QGraphicsItem::setActivePanelOnInactiveScene()
8909 QGraphicsScene scene;
8910 QGraphicsRectItem *item = scene.addRect(QRectF());
8911 QGraphicsRectItem *panel = scene.addRect(QRectF());
8912 panel->setFlag(QGraphicsItem::ItemIsPanel);
8914 EventSpy itemActivateSpy(&scene, item, QEvent::WindowActivate);
8915 EventSpy itemDeactivateSpy(&scene, item, QEvent::WindowDeactivate);
8916 EventSpy panelActivateSpy(&scene, panel, QEvent::WindowActivate);
8917 EventSpy panelDeactivateSpy(&scene, panel, QEvent::WindowDeactivate);
8918 EventSpy sceneActivationChangeSpy(&scene, QEvent::ActivationChange);
8920 scene.setActivePanel(panel);
8921 QCOMPARE(scene.activePanel(), (QGraphicsItem *)0);
8922 QCOMPARE(itemActivateSpy.count(), 0);
8923 QCOMPARE(itemDeactivateSpy.count(), 0);
8924 QCOMPARE(panelActivateSpy.count(), 0);
8925 QCOMPARE(panelDeactivateSpy.count(), 0);
8926 QCOMPARE(sceneActivationChangeSpy.count(), 0);
8929 void tst_QGraphicsItem::activationOnShowHide()
8931 QGraphicsScene scene;
8932 QEvent activate(QEvent::WindowActivate);
8933 QApplication::sendEvent(&scene, &activate);
8935 QGraphicsRectItem *rootPanel = scene.addRect(QRectF());
8936 rootPanel->setFlag(QGraphicsItem::ItemIsPanel);
8937 rootPanel->setActive(true);
8939 QGraphicsRectItem *subPanel = new QGraphicsRectItem;
8940 subPanel->setFlag(QGraphicsItem::ItemIsPanel);
8942 // Reparenting onto an active panel auto-activates the child panel.
8943 subPanel->setParentItem(rootPanel);
8944 QVERIFY(subPanel->isActive());
8945 QVERIFY(!rootPanel->isActive());
8947 // Hiding an active child panel will reactivate the parent panel.
8949 QVERIFY(rootPanel->isActive());
8951 // Showing a child panel will auto-activate it.
8953 QVERIFY(subPanel->isActive());
8954 QVERIFY(!rootPanel->isActive());
8956 // Adding an unrelated panel doesn't affect activation.
8957 QGraphicsRectItem *otherPanel = new QGraphicsRectItem;
8958 otherPanel->setFlag(QGraphicsItem::ItemIsPanel);
8959 scene.addItem(otherPanel);
8960 QVERIFY(subPanel->isActive());
8962 // Showing an unrelated panel doesn't affect activation.
8965 QVERIFY(subPanel->isActive());
8967 // Add a non-panel item.
8968 QGraphicsRectItem *otherItem = new QGraphicsRectItem;
8969 scene.addItem(otherItem);
8970 otherItem->setActive(true);
8971 QVERIFY(otherItem->isActive());
8973 // Reparent a panel onto an active non-panel item.
8974 subPanel->setParentItem(otherItem);
8975 QVERIFY(subPanel->isActive());
8977 // Showing a child panel of a non-panel item will activate it.
8979 QVERIFY(!subPanel->isActive());
8980 QVERIFY(otherItem->isActive());
8982 QVERIFY(subPanel->isActive());
8984 // Hiding a toplevel active panel will pass activation back
8985 // to the non-panel items.
8986 rootPanel->setActive(true);
8988 QVERIFY(!rootPanel->isActive());
8989 QVERIFY(otherItem->isActive());
8992 class MoveWhileDying : public QGraphicsRectItem
8995 MoveWhileDying(QGraphicsItem *parent = 0)
8996 : QGraphicsRectItem(parent)
9000 foreach (QGraphicsItem *c, childItems()) {
9001 foreach (QGraphicsItem *cc, c->childItems()) {
9006 if (QGraphicsItem *p = parentItem()) { p->moveBy(10, 10); }
9010 void tst_QGraphicsItem::moveWhileDeleting()
9012 QGraphicsScene scene;
9013 QGraphicsRectItem *rect = new QGraphicsRectItem;
9014 MoveWhileDying *silly = new MoveWhileDying(rect);
9015 QGraphicsRectItem *child = new QGraphicsRectItem(silly);
9016 scene.addItem(rect);
9017 delete rect; // don't crash!
9019 rect = new QGraphicsRectItem;
9020 silly = new MoveWhileDying(rect);
9021 child = new QGraphicsRectItem(silly);
9023 QGraphicsView view(&scene);
9026 qt_x11_wait_for_window_manager(&view);
9032 rect = new QGraphicsRectItem;
9033 rect->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
9034 silly = new MoveWhileDying(rect);
9035 child = new QGraphicsRectItem(silly);
9041 rect = new MoveWhileDying;
9042 rect->setFlag(QGraphicsItem::ItemClipsChildrenToShape);
9043 child = new QGraphicsRectItem(rect);
9044 silly = new MoveWhileDying(child);
9051 class MyRectItem : public QGraphicsWidget
9055 MyRectItem(QGraphicsItem *parent = 0) : QGraphicsWidget(parent)
9060 void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
9062 painter->setBrush(brush);
9063 painter->drawRect(boundingRect());
9068 topLevel->collidingItems(Qt::IntersectsItemBoundingRect);
9071 QGraphicsItem *topLevel;
9076 void tst_QGraphicsItem::ensureDirtySceneTransform()
9078 QGraphicsScene scene;
9080 MyRectItem *topLevel = new MyRectItem;
9081 topLevel->setGeometry(0, 0, 100, 100);
9082 topLevel->setPos(-50, -50);
9083 topLevel->brush = QBrush(QColor(Qt::black));
9084 scene.addItem(topLevel);
9086 MyRectItem *parent = new MyRectItem;
9087 parent->topLevel = topLevel;
9088 parent->setGeometry(0, 0, 100, 100);
9089 parent->setPos(0, 0);
9090 parent->brush = QBrush(QColor(Qt::magenta));
9091 parent->setObjectName("parent");
9092 scene.addItem(parent);
9094 MyRectItem *child = new MyRectItem(parent);
9095 child->setGeometry(0, 0, 80, 80);
9096 child->setPos(10, 10);
9097 child->setObjectName("child");
9098 child->brush = QBrush(QColor(Qt::blue));
9100 MyRectItem *child2 = new MyRectItem(parent);
9101 child2->setGeometry(0, 0, 80, 80);
9102 child2->setPos(15, 15);
9103 child2->setObjectName("child2");
9104 child2->brush = QBrush(QColor(Qt::green));
9106 MyRectItem *child3 = new MyRectItem(parent);
9107 child3->setGeometry(0, 0, 80, 80);
9108 child3->setPos(20, 20);
9109 child3->setObjectName("child3");
9110 child3->brush = QBrush(QColor(Qt::gray));
9112 QGraphicsView view(&scene);
9114 QTest::qWaitForWindowShown(&view);
9115 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
9117 //We move the parent
9119 QApplication::processEvents();
9121 //We check if all items moved
9122 QCOMPARE(child->pos(), QPointF(10, 10));
9123 QCOMPARE(child2->pos(), QPointF(15, 15));
9124 QCOMPARE(child3->pos(), QPointF(20, 20));
9126 QCOMPARE(child->sceneBoundingRect(), QRectF(-90, -90, 80, 80));
9127 QCOMPARE(child2->sceneBoundingRect(), QRectF(-85, -85, 80, 80));
9128 QCOMPARE(child3->sceneBoundingRect(), QRectF(-80, -80, 80, 80));
9130 QCOMPARE(child->sceneTransform(), QTransform::fromTranslate(-90, -90));
9131 QCOMPARE(child2->sceneTransform(), QTransform::fromTranslate(-85, -85));
9132 QCOMPARE(child3->sceneTransform(), QTransform::fromTranslate(-80, -80));
9135 void tst_QGraphicsItem::focusScope()
9137 // ItemIsFocusScope is an internal feature (for now).
9138 QGraphicsScene scene;
9140 QGraphicsRectItem *scope3 = new QGraphicsRectItem;
9141 scope3->setData(0, "scope3");
9142 scope3->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9144 QVERIFY(!scope3->focusScopeItem());
9145 QCOMPARE(scope3->focusItem(), (QGraphicsItem *)scope3);
9147 QGraphicsRectItem *scope2 = new QGraphicsRectItem;
9148 scope2->setData(0, "scope2");
9149 scope2->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9151 QVERIFY(!scope2->focusScopeItem());
9152 scope3->setParentItem(scope2);
9153 QCOMPARE(scope2->focusScopeItem(), (QGraphicsItem *)scope3);
9154 QCOMPARE(scope2->focusItem(), (QGraphicsItem *)scope3);
9156 QGraphicsRectItem *scope1 = new QGraphicsRectItem;
9157 scope1->setData(0, "scope1");
9158 scope1->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9160 QVERIFY(!scope1->focusScopeItem());
9161 scope2->setParentItem(scope1);
9163 QCOMPARE(scope1->focusItem(), (QGraphicsItem *)scope3);
9164 QCOMPARE(scope2->focusItem(), (QGraphicsItem *)scope3);
9165 QCOMPARE(scope3->focusItem(), (QGraphicsItem *)scope3);
9166 QCOMPARE(scope1->focusScopeItem(), (QGraphicsItem *)scope2);
9167 QCOMPARE(scope2->focusScopeItem(), (QGraphicsItem *)scope3);
9168 QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)0);
9170 scene.addItem(scope1);
9172 QEvent windowActivate(QEvent::WindowActivate);
9173 qApp->sendEvent(&scene, &windowActivate);
9176 QCOMPARE(scope1->focusItem(), (QGraphicsItem *)scope3);
9177 QCOMPARE(scope2->focusItem(), (QGraphicsItem *)scope3);
9178 QCOMPARE(scope3->focusItem(), (QGraphicsItem *)scope3);
9179 QCOMPARE(scope1->focusScopeItem(), (QGraphicsItem *)scope2);
9180 QCOMPARE(scope2->focusScopeItem(), (QGraphicsItem *)scope3);
9181 QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)0);
9183 QVERIFY(scope3->hasFocus());
9186 QVERIFY(scope2->hasFocus());
9188 QVERIFY(scope1->hasFocus());
9190 QVERIFY(scope2->hasFocus());
9192 QVERIFY(scope3->hasFocus());
9194 QVERIFY(!scope3->hasFocus());
9196 QVERIFY(scope3->hasFocus());
9197 scope3->clearFocus();
9198 QVERIFY(scope2->hasFocus());
9199 scope2->clearFocus();
9200 QVERIFY(scope1->hasFocus());
9203 QVERIFY(!scope2->hasFocus());
9204 QVERIFY(scope1->hasFocus());
9206 QVERIFY(scope2->hasFocus());
9208 QVERIFY(scope3->hasFocus());
9210 QGraphicsRectItem *rect4 = new QGraphicsRectItem;
9211 rect4->setData(0, "rect4");
9212 rect4->setParentItem(scope3);
9214 QGraphicsRectItem *rect5 = new QGraphicsRectItem;
9215 rect5->setData(0, "rect5");
9216 rect5->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9218 rect5->setParentItem(rect4);
9219 QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)rect5);
9220 QVERIFY(rect5->hasFocus());
9222 rect4->setParentItem(0);
9223 QVERIFY(rect5->hasFocus());
9224 QCOMPARE(scope3->focusScopeItem(), (QGraphicsItem *)0);
9225 QCOMPARE(scope3->focusItem(), (QGraphicsItem *)0);
9226 QVERIFY(!scope3->hasFocus());
9228 QGraphicsRectItem *rectA = new QGraphicsRectItem;
9229 QGraphicsRectItem *scopeA = new QGraphicsRectItem(rectA);
9230 scopeA->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9232 QGraphicsRectItem *scopeB = new QGraphicsRectItem(scopeA);
9233 scopeB->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9236 scene.addItem(rectA);
9237 QVERIFY(rect5->hasFocus());
9238 QVERIFY(!scopeB->hasFocus());
9241 QVERIFY(scopeB->hasFocus());
9242 QCOMPARE(scopeB->focusItem(), (QGraphicsItem *)scopeB);
9245 void tst_QGraphicsItem::focusScope2()
9247 QGraphicsRectItem *child1 = new QGraphicsRectItem;
9248 child1->setFlags(QGraphicsItem::ItemIsFocusable);
9250 QCOMPARE(child1->focusItem(), (QGraphicsItem *)child1);
9252 QGraphicsRectItem *child2 = new QGraphicsRectItem;
9253 child2->setFlags(QGraphicsItem::ItemIsFocusable);
9255 QGraphicsRectItem *rootFocusScope = new QGraphicsRectItem;
9256 rootFocusScope->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9257 rootFocusScope->setFocus();
9258 QCOMPARE(rootFocusScope->focusItem(), (QGraphicsItem *)rootFocusScope);
9260 child1->setParentItem(rootFocusScope);
9261 child2->setParentItem(rootFocusScope);
9263 QCOMPARE(rootFocusScope->focusScopeItem(), (QGraphicsItem *)child1);
9264 QCOMPARE(rootFocusScope->focusItem(), (QGraphicsItem *)child1);
9266 QGraphicsRectItem *siblingChild1 = new QGraphicsRectItem;
9267 siblingChild1->setFlags(QGraphicsItem::ItemIsFocusable);
9268 siblingChild1->setFocus();
9270 QGraphicsRectItem *siblingChild2 = new QGraphicsRectItem;
9271 siblingChild2->setFlags(QGraphicsItem::ItemIsFocusable);
9273 QGraphicsRectItem *siblingFocusScope = new QGraphicsRectItem;
9274 siblingFocusScope->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
9276 siblingChild1->setParentItem(siblingFocusScope);
9277 siblingChild2->setParentItem(siblingFocusScope);
9279 QCOMPARE(siblingFocusScope->focusScopeItem(), (QGraphicsItem *)siblingChild1);
9280 QCOMPARE(siblingFocusScope->focusItem(), (QGraphicsItem *)0);
9282 QGraphicsItem *root = new QGraphicsRectItem;
9283 rootFocusScope->setParentItem(root);
9284 siblingFocusScope->setParentItem(root);
9286 QCOMPARE(root->focusItem(), (QGraphicsItem *)child1);
9288 QGraphicsScene scene;
9289 scene.addItem(root);
9291 QEvent activate(QEvent::WindowActivate);
9292 qApp->sendEvent(&scene, &activate);
9295 QCOMPARE(scene.focusItem(), (QGraphicsItem *)child1);
9297 // You cannot set focus on a descendant of a focus scope directly;
9298 // this will only change the scope's focus scope item pointer. If
9299 // you want to give true input focus, you must set it directly on
9301 siblingChild2->setFocus();
9302 QVERIFY(!siblingChild2->hasFocus());
9303 QVERIFY(!siblingChild2->focusItem());
9304 QCOMPARE(siblingFocusScope->focusScopeItem(), (QGraphicsItem *)siblingChild2);
9305 QCOMPARE(siblingFocusScope->focusItem(), (QGraphicsItem *)0);
9307 // Set focus on the scope; focus is forwarded to the focus scope item.
9308 siblingFocusScope->setFocus();
9309 QVERIFY(siblingChild2->hasFocus());
9310 QVERIFY(siblingChild2->focusItem());
9311 QCOMPARE(siblingFocusScope->focusScopeItem(), (QGraphicsItem *)siblingChild2);
9312 QCOMPARE(siblingFocusScope->focusItem(), (QGraphicsItem *)siblingChild2);
9315 void tst_QGraphicsItem::stackBefore()
9317 QGraphicsRectItem parent;
9318 QGraphicsRectItem *child1 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
9319 QGraphicsRectItem *child2 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
9320 QGraphicsRectItem *child3 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
9321 QGraphicsRectItem *child4 = new QGraphicsRectItem(QRectF(0, 0, 5, 5), &parent);
9322 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
9323 child1->setData(0, "child1");
9324 child2->setData(0, "child2");
9325 child3->setData(0, "child3");
9326 child4->setData(0, "child4");
9328 // Remove and append
9329 child2->setParentItem(0);
9330 child2->setParentItem(&parent);
9331 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child3 << child4 << child2));
9333 // Move child2 before child1
9334 child2->stackBefore(child1); // 2134
9335 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
9336 child2->stackBefore(child2); // 2134
9337 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
9338 child1->setZValue(1); // 2341
9339 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
9340 child1->stackBefore(child2); // 2341
9341 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
9342 child1->setZValue(0); // 1234
9343 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
9344 child4->stackBefore(child1); // 4123
9345 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child4 << child1 << child2 << child3));
9346 child4->setZValue(1); // 1234 (4123)
9347 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
9348 child3->stackBefore(child1); // 3124 (4312)
9349 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child3 << child1 << child2 << child4));
9350 child4->setZValue(0); // 4312
9351 QCOMPARE(parent.childItems(), (QList<QGraphicsItem *>() << child4 << child3 << child1 << child2));
9353 // Make them all toplevels
9354 child1->setParentItem(0);
9355 child2->setParentItem(0);
9356 child3->setParentItem(0);
9357 child4->setParentItem(0);
9359 QGraphicsScene scene;
9360 scene.addItem(child1);
9361 scene.addItem(child2);
9362 scene.addItem(child3);
9363 scene.addItem(child4);
9364 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder),
9365 (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
9367 // Remove and append
9368 scene.removeItem(child2);
9369 scene.addItem(child2);
9370 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child1 << child3 << child4 << child2));
9372 // Move child2 before child1
9373 child2->stackBefore(child1); // 2134
9374 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
9375 child2->stackBefore(child2); // 2134
9376 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child1 << child3 << child4));
9377 child1->setZValue(1); // 2341
9378 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
9379 child1->stackBefore(child2); // 2341
9380 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child2 << child3 << child4 << child1));
9381 child1->setZValue(0); // 1234
9382 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
9383 child4->stackBefore(child1); // 4123
9384 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child4 << child1 << child2 << child3));
9385 child4->setZValue(1); // 1234 (4123)
9386 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child1 << child2 << child3 << child4));
9387 child3->stackBefore(child1); // 3124 (4312)
9388 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child3 << child1 << child2 << child4));
9389 child4->setZValue(0); // 4312
9390 QCOMPARE(scene.items(QPointF(2, 2), Qt::IntersectsItemBoundingRect, Qt::AscendingOrder), (QList<QGraphicsItem *>() << child4 << child3 << child1 << child2));
9393 void tst_QGraphicsItem::QTBUG_4233_updateCachedWithSceneRect()
9395 EventTester *tester = new EventTester;
9396 tester->setCacheMode(QGraphicsItem::ItemCoordinateCache);
9398 QGraphicsScene scene;
9399 scene.addItem(tester);
9400 scene.setSceneRect(-100, -100, 200, 200); // contains the tester item
9402 QGraphicsView view(&scene);
9404 QTest::qWaitForWindowShown(&view);
9405 QTRY_COMPARE(QApplication::activeWindow(), (QWidget *)&view);
9407 QTRY_COMPARE(tester->repaints, 1);
9409 scene.update(); // triggers "updateAll" optimization
9410 qApp->processEvents();
9411 qApp->processEvents(); // in 4.6 only one processEvents is necessary
9413 QCOMPARE(tester->repaints, 1);
9415 scene.update(); // triggers "updateAll" optimization
9417 qApp->processEvents();
9418 qApp->processEvents(); // in 4.6 only one processEvents is necessary
9420 QCOMPARE(tester->repaints, 2);
9423 void tst_QGraphicsItem::sceneModality()
9425 // 1) Test mouse events (delivery/propagation/redirection)
9426 // 2) Test hover events (incl. leave on block, enter on unblock)
9427 // 3) Test cursor stuff (incl. unset on block, set on unblock)
9428 // 4) Test clickfocus
9429 // 5) Test grab/ungrab events (possibly ungrab on block, regrab on unblock)
9430 // 6) ### modality for non-panels is unsupported for now
9431 QGraphicsScene scene;
9433 QGraphicsRectItem *bottomItem = scene.addRect(-150, -100, 300, 200);
9434 bottomItem->setFlag(QGraphicsItem::ItemIsFocusable);
9435 bottomItem->setBrush(Qt::yellow);
9437 QGraphicsRectItem *leftParent = scene.addRect(-50, -50, 100, 100);
9438 leftParent->setFlag(QGraphicsItem::ItemIsPanel);
9439 leftParent->setBrush(Qt::blue);
9441 QGraphicsRectItem *leftChild = scene.addRect(-25, -25, 50, 50);
9442 leftChild->setFlag(QGraphicsItem::ItemIsPanel);
9443 leftChild->setBrush(Qt::green);
9444 leftChild->setParentItem(leftParent);
9446 QGraphicsRectItem *rightParent = scene.addRect(-50, -50, 100, 100);
9447 rightParent->setFlag(QGraphicsItem::ItemIsPanel);
9448 rightParent->setBrush(Qt::red);
9449 QGraphicsRectItem *rightChild = scene.addRect(-25, -25, 50, 50);
9450 rightChild->setFlag(QGraphicsItem::ItemIsPanel);
9451 rightChild->setBrush(Qt::gray);
9452 rightChild->setParentItem(rightParent);
9454 leftParent->setPos(-75, 0);
9455 rightParent->setPos(75, 0);
9457 bottomItem->setData(0, "bottomItem");
9458 leftParent->setData(0, "leftParent");
9459 leftChild->setData(0, "leftChild");
9460 rightParent->setData(0, "rightParent");
9461 rightChild->setData(0, "rightChild");
9463 scene.setSceneRect(scene.itemsBoundingRect().adjusted(-50, -50, 50, 50));
9465 EventSpy2 leftParentSpy(&scene, leftParent);
9466 EventSpy2 leftChildSpy(&scene, leftChild);
9467 EventSpy2 rightParentSpy(&scene, rightParent);
9468 EventSpy2 rightChildSpy(&scene, rightChild);
9469 EventSpy2 bottomItemSpy(&scene, bottomItem);
9471 // Scene modality, also test multiple scene modal items
9472 leftChild->setPanelModality(QGraphicsItem::SceneModal);
9473 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9474 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9475 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9476 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9477 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0); // not a panel
9479 // Click inside left child
9480 sendMouseClick(&scene, leftChild->scenePos(), Qt::LeftButton);
9481 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
9482 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
9483 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9484 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9485 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9486 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9488 // Click on left parent, event goes to modal child
9489 sendMouseClick(&scene, leftParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
9490 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 2);
9491 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
9492 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9493 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9494 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9495 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9497 // Click on all other items and outside the items
9498 sendMouseClick(&scene, rightParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
9499 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 3);
9500 sendMouseClick(&scene, rightChild->scenePos(), Qt::LeftButton);
9501 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 4);
9502 sendMouseClick(&scene, bottomItem->scenePos(), Qt::LeftButton);
9503 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 5);
9504 sendMouseClick(&scene, QPointF(10000, 10000), Qt::LeftButton);
9505 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 6);
9506 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
9507 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9508 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9509 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9510 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9512 leftChildSpy.counts.clear();
9513 rightChildSpy.counts.clear();
9514 leftParentSpy.counts.clear();
9515 rightParentSpy.counts.clear();
9516 bottomItemSpy.counts.clear();
9518 leftChild->setPanelModality(QGraphicsItem::NonModal);
9519 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
9520 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
9521 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 1);
9522 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 1);
9523 QCOMPARE(bottomItemSpy.counts[QEvent::WindowUnblocked], 0);
9525 // Left parent enters scene modality.
9526 leftParent->setPanelModality(QGraphicsItem::SceneModal);
9527 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9528 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9529 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
9530 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9531 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
9533 // Click inside left child.
9534 sendMouseClick(&scene, leftChild->scenePos(), Qt::LeftButton);
9535 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
9536 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9537 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // panel stops propagation
9538 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9539 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9540 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9542 // Click on left parent.
9543 sendMouseClick(&scene, leftParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
9544 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
9545 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9546 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 1);
9547 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9548 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9549 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9551 // Click on all other items and outside the items
9552 sendMouseClick(&scene, rightParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
9553 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 2);
9554 sendMouseClick(&scene, rightChild->scenePos(), Qt::LeftButton);
9555 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 3);
9556 sendMouseClick(&scene, bottomItem->scenePos(), Qt::LeftButton);
9557 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 4);
9558 sendMouseClick(&scene, QPointF(10000, 10000), Qt::LeftButton);
9559 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 5);
9560 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9561 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
9562 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9563 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9564 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0);
9566 leftChildSpy.counts.clear();
9567 rightChildSpy.counts.clear();
9568 leftParentSpy.counts.clear();
9569 rightParentSpy.counts.clear();
9570 bottomItemSpy.counts.clear();
9572 // Now both left parent and child are scene modal. Left parent is blocked.
9573 leftChild->setPanelModality(QGraphicsItem::SceneModal);
9574 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9575 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
9576 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9577 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
9578 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
9580 // Click inside left child
9581 sendMouseClick(&scene, leftChild->scenePos(), Qt::LeftButton);
9582 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 1);
9583 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
9584 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9585 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9586 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9587 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9589 // Click on left parent, event goes to modal child
9590 sendMouseClick(&scene, leftParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
9591 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 2);
9592 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
9593 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9594 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9595 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9596 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9598 // Click on all other items and outside the items
9599 sendMouseClick(&scene, rightParent->sceneBoundingRect().topLeft() + QPointF(5, 5), Qt::LeftButton);
9600 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 3);
9601 sendMouseClick(&scene, rightChild->scenePos(), Qt::LeftButton);
9602 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 4);
9603 sendMouseClick(&scene, bottomItem->scenePos(), Qt::LeftButton);
9604 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 5);
9605 sendMouseClick(&scene, QPointF(10000, 10000), Qt::LeftButton);
9606 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMousePress], 6);
9607 QCOMPARE(leftChildSpy.counts[QEvent::GraphicsSceneMouseRelease], 0); // no grab
9608 QCOMPARE(leftParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9609 QCOMPARE(rightParentSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9610 QCOMPARE(rightChildSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9611 QCOMPARE(bottomItemSpy.counts[QEvent::GraphicsSceneMousePress], 0); // blocked
9613 leftChildSpy.counts.clear();
9614 rightChildSpy.counts.clear();
9615 leftParentSpy.counts.clear();
9616 rightParentSpy.counts.clear();
9617 bottomItemSpy.counts.clear();
9619 // Right child enters scene modality, only left child is blocked.
9620 rightChild->setPanelModality(QGraphicsItem::SceneModal);
9621 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 1);
9622 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
9623 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
9624 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
9625 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
9628 void tst_QGraphicsItem::panelModality()
9630 // 1) Test mouse events (delivery/propagation/redirection)
9631 // 2) Test hover events (incl. leave on block, enter on unblock)
9632 // 3) Test cursor stuff (incl. unset on block, set on unblock)
9633 // 4) Test clickfocus
9634 // 5) Test grab/ungrab events (possibly ungrab on block, regrab on unblock)
9635 // 6) ### modality for non-panels is unsupported for now
9636 QGraphicsScene scene;
9638 QGraphicsRectItem *bottomItem = scene.addRect(-150, -100, 300, 200);
9639 bottomItem->setFlag(QGraphicsItem::ItemIsFocusable);
9640 bottomItem->setBrush(Qt::yellow);
9642 QGraphicsRectItem *leftParent = scene.addRect(-50, -50, 100, 100);
9643 leftParent->setFlag(QGraphicsItem::ItemIsPanel);
9644 leftParent->setBrush(Qt::blue);
9646 QGraphicsRectItem *leftChild = scene.addRect(-25, -25, 50, 50);
9647 leftChild->setFlag(QGraphicsItem::ItemIsPanel);
9648 leftChild->setBrush(Qt::green);
9649 leftChild->setParentItem(leftParent);
9651 QGraphicsRectItem *rightParent = scene.addRect(-50, -50, 100, 100);
9652 rightParent->setFlag(QGraphicsItem::ItemIsPanel);
9653 rightParent->setBrush(Qt::red);
9654 QGraphicsRectItem *rightChild = scene.addRect(-25, -25, 50, 50);
9655 rightChild->setFlag(QGraphicsItem::ItemIsPanel);
9656 rightChild->setBrush(Qt::gray);
9657 rightChild->setParentItem(rightParent);
9659 leftParent->setPos(-75, 0);
9660 rightParent->setPos(75, 0);
9662 bottomItem->setData(0, "bottomItem");
9663 leftParent->setData(0, "leftParent");
9664 leftChild->setData(0, "leftChild");
9665 rightParent->setData(0, "rightParent");
9666 rightChild->setData(0, "rightChild");
9668 scene.setSceneRect(scene.itemsBoundingRect().adjusted(-50, -50, 50, 50));
9670 EventSpy2 leftParentSpy(&scene, leftParent);
9671 EventSpy2 leftChildSpy(&scene, leftChild);
9672 EventSpy2 rightParentSpy(&scene, rightParent);
9673 EventSpy2 rightChildSpy(&scene, rightChild);
9674 EventSpy2 bottomItemSpy(&scene, bottomItem);
9676 // Left Child enters panel modality, only left parent is blocked.
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 leftChild->setPanelModality(QGraphicsItem::NonModal);
9685 leftChildSpy.counts.clear();
9686 rightChildSpy.counts.clear();
9687 leftParentSpy.counts.clear();
9688 rightParentSpy.counts.clear();
9689 bottomItemSpy.counts.clear();
9691 // Left parent enter panel modality, nothing is blocked.
9692 leftParent->setPanelModality(QGraphicsItem::PanelModal);
9693 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9694 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
9695 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
9696 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
9697 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
9699 // Left child enters panel modality, left parent is blocked again.
9700 leftChild->setPanelModality(QGraphicsItem::PanelModal);
9701 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9702 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
9703 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9704 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
9705 QCOMPARE(bottomItemSpy.counts[QEvent::WindowBlocked], 0);
9707 leftChildSpy.counts.clear();
9708 rightChildSpy.counts.clear();
9709 leftParentSpy.counts.clear();
9710 rightParentSpy.counts.clear();
9711 bottomItemSpy.counts.clear();
9713 leftChild->setPanelModality(QGraphicsItem::NonModal);
9714 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 1);
9715 leftParent->setPanelModality(QGraphicsItem::NonModal);
9716 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
9717 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 0);
9718 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 1);
9719 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
9720 QCOMPARE(bottomItemSpy.counts[QEvent::WindowUnblocked], 0);
9722 leftChildSpy.counts.clear();
9723 rightChildSpy.counts.clear();
9724 leftParentSpy.counts.clear();
9725 rightParentSpy.counts.clear();
9726 bottomItemSpy.counts.clear();
9728 // Left and right child enter panel modality, both parents are blocked.
9729 rightChild->setPanelModality(QGraphicsItem::PanelModal);
9730 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 0);
9731 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9732 leftChild->setPanelModality(QGraphicsItem::PanelModal);
9733 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9734 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9737 void tst_QGraphicsItem::mixedModality()
9739 // 1) Test mouse events (delivery/propagation/redirection)
9740 // 2) Test hover events (incl. leave on block, enter on unblock)
9741 // 3) Test cursor stuff (incl. unset on block, set on unblock)
9742 // 4) Test clickfocus
9743 // 5) Test grab/ungrab events (possibly ungrab on block, regrab on unblock)
9744 // 6) ### modality for non-panels is unsupported for now
9745 QGraphicsScene scene;
9747 QGraphicsRectItem *bottomItem = scene.addRect(-150, -100, 300, 200);
9748 bottomItem->setFlag(QGraphicsItem::ItemIsFocusable);
9749 bottomItem->setBrush(Qt::yellow);
9751 QGraphicsRectItem *leftParent = scene.addRect(-50, -50, 100, 100);
9752 leftParent->setFlag(QGraphicsItem::ItemIsPanel);
9753 leftParent->setBrush(Qt::blue);
9755 QGraphicsRectItem *leftChild = scene.addRect(-25, -25, 50, 50);
9756 leftChild->setFlag(QGraphicsItem::ItemIsPanel);
9757 leftChild->setBrush(Qt::green);
9758 leftChild->setParentItem(leftParent);
9760 QGraphicsRectItem *rightParent = scene.addRect(-50, -50, 100, 100);
9761 rightParent->setFlag(QGraphicsItem::ItemIsPanel);
9762 rightParent->setBrush(Qt::red);
9763 QGraphicsRectItem *rightChild = scene.addRect(-25, -25, 50, 50);
9764 rightChild->setFlag(QGraphicsItem::ItemIsPanel);
9765 rightChild->setBrush(Qt::gray);
9766 rightChild->setParentItem(rightParent);
9768 leftParent->setPos(-75, 0);
9769 rightParent->setPos(75, 0);
9771 bottomItem->setData(0, "bottomItem");
9772 leftParent->setData(0, "leftParent");
9773 leftChild->setData(0, "leftChild");
9774 rightParent->setData(0, "rightParent");
9775 rightChild->setData(0, "rightChild");
9777 scene.setSceneRect(scene.itemsBoundingRect().adjusted(-50, -50, 50, 50));
9779 EventSpy2 leftParentSpy(&scene, leftParent);
9780 EventSpy2 leftChildSpy(&scene, leftChild);
9781 EventSpy2 rightParentSpy(&scene, rightParent);
9782 EventSpy2 rightChildSpy(&scene, rightChild);
9783 EventSpy2 bottomItemSpy(&scene, bottomItem);
9785 // Left Child enters panel modality, only left parent is blocked.
9786 leftChild->setPanelModality(QGraphicsItem::PanelModal);
9787 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9788 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 0);
9789 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9790 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 0);
9792 // Left parent enters scene modality, which blocks everything except the child.
9793 leftParent->setPanelModality(QGraphicsItem::SceneModal);
9794 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9795 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
9796 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9797 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 0);
9798 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9799 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
9800 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9801 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
9803 // Right child enters panel modality (changes nothing).
9804 rightChild->setPanelModality(QGraphicsItem::PanelModal);
9805 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9806 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
9807 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9808 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 0);
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 // Left parent leaves modality. Right child is unblocked.
9815 leftParent->setPanelModality(QGraphicsItem::NonModal);
9816 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 0);
9817 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
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);
9825 // Right child "upgrades" its modality to scene modal. Left child is blocked.
9826 // Right parent is unaffected.
9827 rightChild->setPanelModality(QGraphicsItem::SceneModal);
9828 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 1);
9829 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 0);
9830 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9831 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
9832 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9833 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
9834 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9835 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
9837 // "downgrade" right child back to panel modal, left child is unblocked
9838 rightChild->setPanelModality(QGraphicsItem::PanelModal);
9839 QCOMPARE(leftChildSpy.counts[QEvent::WindowBlocked], 1);
9840 QCOMPARE(leftChildSpy.counts[QEvent::WindowUnblocked], 1);
9841 QCOMPARE(rightChildSpy.counts[QEvent::WindowBlocked], 1);
9842 QCOMPARE(rightChildSpy.counts[QEvent::WindowUnblocked], 1);
9843 QCOMPARE(leftParentSpy.counts[QEvent::WindowBlocked], 1);
9844 QCOMPARE(leftParentSpy.counts[QEvent::WindowUnblocked], 0);
9845 QCOMPARE(rightParentSpy.counts[QEvent::WindowBlocked], 1);
9846 QCOMPARE(rightParentSpy.counts[QEvent::WindowUnblocked], 0);
9849 void tst_QGraphicsItem::modality_hover()
9851 QGraphicsScene scene;
9852 QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
9853 rect1->setFlag(QGraphicsItem::ItemIsPanel);
9854 rect1->setAcceptHoverEvents(true);
9855 rect1->setData(0, "rect1");
9857 QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
9858 rect2->setParentItem(rect1);
9859 rect2->setFlag(QGraphicsItem::ItemIsPanel);
9860 rect2->setAcceptHoverEvents(true);
9861 rect2->setPos(50, 50);
9862 rect2->setPanelModality(QGraphicsItem::SceneModal);
9863 rect2->setData(0, "rect2");
9865 EventSpy2 rect1Spy(&scene, rect1);
9866 EventSpy2 rect2Spy(&scene, rect2);
9868 sendMouseMove(&scene, QPointF(-25, -25));
9870 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 0);
9871 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 0);
9872 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
9874 sendMouseMove(&scene, QPointF(75, 75));
9876 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 0);
9877 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 0);
9878 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
9879 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
9880 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
9881 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
9883 sendMouseMove(&scene, QPointF(-25, -25));
9885 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
9886 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 0);
9887 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 0);
9888 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 0);
9890 rect2->setPanelModality(QGraphicsItem::NonModal);
9892 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
9893 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
9895 sendMouseMove(&scene, QPointF(75, 75));
9897 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
9898 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 2);
9900 rect2->setPanelModality(QGraphicsItem::SceneModal);
9902 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
9903 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
9904 // changing modality causes a spurious GraphicsSceneHoveMove, even though the mouse didn't
9906 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 3);
9908 sendMouseMove(&scene, QPointF(-25, -25));
9910 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 2);
9911 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
9912 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
9913 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
9915 rect2->setPanelModality(QGraphicsItem::PanelModal);
9917 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 1);
9918 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 1);
9919 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverLeave], 1);
9920 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
9921 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 3);
9922 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 2);
9924 rect2->setPanelModality(QGraphicsItem::NonModal);
9926 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
9927 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneHoverMove], 2);
9928 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverEnter], 2);
9929 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverMove], 3);
9930 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneHoverLeave], 2);
9933 void tst_QGraphicsItem::modality_mouseGrabber()
9935 QGraphicsScene scene;
9936 QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
9937 rect1->setFlag(QGraphicsItem::ItemIsPanel);
9938 rect1->setFlag(QGraphicsItem::ItemIsMovable);
9939 rect1->setData(0, "rect1");
9941 QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
9942 rect2->setParentItem(rect1);
9943 rect2->setFlag(QGraphicsItem::ItemIsPanel);
9944 rect2->setFlag(QGraphicsItem::ItemIsMovable);
9945 rect2->setPos(50, 50);
9946 rect2->setData(0, "rect2");
9948 EventSpy2 rect1Spy(&scene, rect1);
9949 EventSpy2 rect2Spy(&scene, rect2);
9952 // pressing mouse on rect1 starts implicit grab
9953 sendMousePress(&scene, QPoint(-25, -25));
9954 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
9955 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
9956 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
9957 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
9958 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
9959 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
9961 // grab lost when rect1 is modally shadowed
9962 rect2->setPanelModality(QGraphicsItem::SceneModal);
9963 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
9964 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
9965 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
9966 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
9967 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
9969 // releasing goes nowhere
9970 sendMouseRelease(&scene, QPoint(-25, -25));
9971 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
9972 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9973 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
9974 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
9975 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9976 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
9977 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
9979 // pressing mouse on rect1 starts implicit grab on rect2 (since it is modal)
9980 sendMouseClick(&scene, QPoint(-25, -25));
9981 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
9982 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
9983 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
9984 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
9985 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
9986 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMousePress], 1);
9987 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 1);
9988 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
9990 rect2->setPanelModality(QGraphicsItem::NonModal);
9992 // pressing mouse on rect1 starts implicit grab
9993 sendMousePress(&scene, QPoint(-25, -25));
9994 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
9995 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 2);
9996 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
9997 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
9998 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
9999 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
10001 // grab lost to rect2 when rect1 is modally shadowed
10002 rect2->setPanelModality(QGraphicsItem::SceneModal);
10003 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
10004 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
10005 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
10006 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
10007 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10009 // rect1 does *not* re-grab when rect2 is no longer modal
10010 rect2->setPanelModality(QGraphicsItem::NonModal);
10011 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
10012 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
10013 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
10014 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
10015 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10017 // release goes nowhere
10018 sendMouseRelease(&scene, QPoint(-25, -25));
10019 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
10020 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
10021 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
10022 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
10023 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
10024 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10027 // repeat the test using PanelModal
10028 rect2->setPanelModality(QGraphicsItem::NonModal);
10029 rect1Spy.counts.clear();
10030 rect2Spy.counts.clear();
10032 // pressing mouse on rect1 starts implicit grab
10033 sendMousePress(&scene, QPoint(-25, -25));
10034 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
10035 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
10036 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10037 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10038 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10039 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
10041 // grab lost when rect1 is modally shadowed
10042 rect2->setPanelModality(QGraphicsItem::PanelModal);
10043 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
10044 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
10045 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10046 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10047 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10049 // releasing goes nowhere
10050 sendMouseRelease(&scene, QPoint(-25, -25));
10051 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
10052 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
10053 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
10054 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10055 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
10056 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10057 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10059 // pressing mouse on rect1 starts implicit grab on rect2 (since it is modal)
10060 sendMouseClick(&scene, QPoint(-25, -25));
10061 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 1);
10062 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 1);
10063 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
10064 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
10065 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
10066 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMousePress], 1);
10067 QCOMPARE(rect2Spy.counts[QEvent::GraphicsSceneMouseRelease], 1);
10068 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
10070 rect2->setPanelModality(QGraphicsItem::NonModal);
10072 // pressing mouse on rect1 starts implicit grab
10073 sendMousePress(&scene, QPoint(-25, -25));
10074 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
10075 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMousePress], 2);
10076 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 1);
10077 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
10078 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
10079 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect1);
10081 // grab lost to rect2 when rect1 is modally shadowed
10082 rect2->setPanelModality(QGraphicsItem::PanelModal);
10083 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
10084 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
10085 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
10086 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
10087 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10089 // rect1 does *not* re-grab when rect2 is no longer modal
10090 rect2->setPanelModality(QGraphicsItem::NonModal);
10091 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
10092 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
10093 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
10094 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
10095 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10097 // release goes nowhere
10098 sendMouseRelease(&scene, QPoint(-25, -25));
10099 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 2);
10100 QCOMPARE(rect1Spy.counts[QEvent::GraphicsSceneMouseRelease], 0);
10101 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 2);
10102 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 1);
10103 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 1);
10104 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10108 // repeat the PanelModal tests, but this time the mouse events will be on a non-modal item,
10109 // meaning normal grabbing should work
10110 rect2->setPanelModality(QGraphicsItem::NonModal);
10111 rect1Spy.counts.clear();
10112 rect2Spy.counts.clear();
10114 QGraphicsRectItem *rect3 = scene.addRect(-50, -50, 100, 100);
10115 rect3->setFlag(QGraphicsItem::ItemIsPanel);
10116 rect3->setFlag(QGraphicsItem::ItemIsMovable);
10117 rect3->setPos(150, 50);
10118 rect3->setData(0, "rect3");
10120 EventSpy2 rect3Spy(&scene, rect3);
10122 // pressing mouse on rect3 starts implicit grab
10123 sendMousePress(&scene, QPoint(150, 50));
10124 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
10125 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10126 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10127 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10128 QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 1);
10129 QCOMPARE(rect3Spy.counts[QEvent::GraphicsSceneMousePress], 1);
10130 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 0);
10131 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
10133 // grab is *not* lost when rect1 is modally shadowed by rect2
10134 rect2->setPanelModality(QGraphicsItem::PanelModal);
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], 1);
10140 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 0);
10141 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
10143 // releasing goes to rect3
10144 sendMouseRelease(&scene, QPoint(150, 50));
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], 1);
10150 QCOMPARE(rect3Spy.counts[QEvent::GraphicsSceneMouseRelease], 1);
10151 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
10152 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10154 rect2->setPanelModality(QGraphicsItem::NonModal);
10156 // pressing mouse on rect3 starts implicit grab
10157 sendMousePress(&scene, QPoint(150, 50));
10158 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
10159 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10160 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10161 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10162 QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
10163 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
10164 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
10166 // grab is not lost
10167 rect2->setPanelModality(QGraphicsItem::PanelModal);
10168 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
10169 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10170 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10171 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10172 QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
10173 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
10174 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
10176 // grab stays on rect3
10177 rect2->setPanelModality(QGraphicsItem::NonModal);
10178 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
10179 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10180 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10181 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10182 QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
10183 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 1);
10184 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) rect3);
10186 // release goes to rect3
10187 sendMouseRelease(&scene, QPoint(150, 50));
10188 QCOMPARE(rect1Spy.counts[QEvent::GrabMouse], 0);
10189 QCOMPARE(rect1Spy.counts[QEvent::UngrabMouse], 0);
10190 QCOMPARE(rect2Spy.counts[QEvent::GrabMouse], 0);
10191 QCOMPARE(rect2Spy.counts[QEvent::UngrabMouse], 0);
10192 QCOMPARE(rect3Spy.counts[QEvent::GrabMouse], 2);
10193 QCOMPARE(rect3Spy.counts[QEvent::UngrabMouse], 2);
10194 QCOMPARE(scene.mouseGrabberItem(), (QGraphicsItem *) 0);
10198 void tst_QGraphicsItem::modality_clickFocus()
10200 QGraphicsScene scene;
10201 QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
10202 rect1->setFlag(QGraphicsItem::ItemIsPanel);
10203 rect1->setFlag(QGraphicsItem::ItemIsFocusable);
10204 rect1->setData(0, "rect1");
10206 QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
10207 rect2->setParentItem(rect1);
10208 rect2->setFlag(QGraphicsItem::ItemIsPanel);
10209 rect2->setFlag(QGraphicsItem::ItemIsFocusable);
10210 rect2->setPos(50, 50);
10211 rect2->setData(0, "rect2");
10213 QEvent windowActivateEvent(QEvent::WindowActivate);
10214 QApplication::sendEvent(&scene, &windowActivateEvent);
10216 EventSpy2 rect1Spy(&scene, rect1);
10217 EventSpy2 rect2Spy(&scene, rect2);
10219 // activate rect1, it should not get focus
10220 rect1->setActive(true);
10221 QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
10223 // focus stays unset when rect2 becomes modal
10224 rect2->setPanelModality(QGraphicsItem::SceneModal);
10225 QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
10226 QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
10227 QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
10228 QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 0);
10229 QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0);
10231 // clicking on rect1 should not set it's focus item
10232 sendMouseClick(&scene, QPointF(-25, -25));
10233 QCOMPARE(rect1->focusItem(), (QGraphicsItem *) 0);
10234 QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
10235 QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
10236 QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 0);
10237 QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0);
10239 // clicking on rect2 gives it focus
10240 rect2->setActive(true);
10241 sendMouseClick(&scene, QPointF(75, 75));
10242 QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect2);
10243 QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
10244 QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
10245 QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
10246 QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 0);
10248 // clicking on rect1 does *not* give it focus
10249 rect1->setActive(true);
10250 sendMouseClick(&scene, QPointF(-25, -25));
10251 QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
10252 QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
10253 QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
10254 QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
10255 QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1);
10257 // focus doesn't change when leaving modality either
10258 rect2->setPanelModality(QGraphicsItem::NonModal);
10259 QCOMPARE(scene.focusItem(), (QGraphicsItem *) 0);
10260 QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 0);
10261 QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
10262 QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
10263 QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1);
10265 // click on rect1, it should get focus now
10266 sendMouseClick(&scene, QPointF(-25, -25));
10267 QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1);
10268 QCOMPARE(rect1Spy.counts[QEvent::FocusIn], 1);
10269 QCOMPARE(rect1Spy.counts[QEvent::FocusOut], 0);
10270 QCOMPARE(rect2Spy.counts[QEvent::FocusIn], 1);
10271 QCOMPARE(rect2Spy.counts[QEvent::FocusOut], 1);
10274 void tst_QGraphicsItem::modality_keyEvents()
10276 QGraphicsScene scene;
10277 QGraphicsRectItem *rect1 = scene.addRect(-50, -50, 100, 100);
10278 rect1->setFlag(QGraphicsItem::ItemIsPanel);
10279 rect1->setFlag(QGraphicsItem::ItemIsFocusable);
10280 rect1->setData(0, "rect1");
10282 QGraphicsRectItem *rect1child = scene.addRect(-10, -10, 20, 20);
10283 rect1child->setParentItem(rect1);
10284 rect1child->setFlag(QGraphicsItem::ItemIsFocusable);
10285 rect1child->setData(0, "rect1child1");
10287 QGraphicsRectItem *rect2 = scene.addRect(-50, -50, 100, 100);
10288 rect2->setParentItem(rect1);
10289 rect2->setFlag(QGraphicsItem::ItemIsPanel);
10290 rect2->setFlag(QGraphicsItem::ItemIsFocusable);
10291 rect2->setPos(50, 50);
10292 rect2->setData(0, "rect2");
10294 QGraphicsRectItem *rect2child = scene.addRect(-10, -10, 20, 20);
10295 rect2child->setParentItem(rect2);
10296 rect2child->setFlag(QGraphicsItem::ItemIsFocusable);
10297 rect2child->setData(0, "rect2child1");
10299 QEvent windowActivateEvent(QEvent::WindowActivate);
10300 QApplication::sendEvent(&scene, &windowActivateEvent);
10302 EventSpy2 rect1Spy(&scene, rect1);
10303 EventSpy2 rect1childSpy(&scene, rect1child);
10304 EventSpy2 rect2Spy(&scene, rect2);
10305 EventSpy2 rect2childSpy(&scene, rect2child);
10307 // activate rect1 and give it rect1child focus
10308 rect1->setActive(true);
10309 rect1child->setFocus();
10310 QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1child);
10312 // focus stays on rect1child when rect2 becomes modal
10313 rect2->setPanelModality(QGraphicsItem::SceneModal);
10314 QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1child);
10316 // but key events to rect1child should be neither delivered nor propagated
10317 sendKeyClick(&scene, Qt::Key_A);
10318 sendKeyClick(&scene, Qt::Key_S);
10319 sendKeyClick(&scene, Qt::Key_D);
10320 sendKeyClick(&scene, Qt::Key_F);
10321 QCOMPARE(rect1childSpy.counts[QEvent::KeyPress], 0);
10322 QCOMPARE(rect1childSpy.counts[QEvent::KeyRelease], 0);
10323 QCOMPARE(rect1Spy.counts[QEvent::KeyPress], 0);
10324 QCOMPARE(rect1Spy.counts[QEvent::KeyRelease], 0);
10326 // change to panel modality, rect1child1 keeps focus
10327 rect2->setPanelModality(QGraphicsItem::PanelModal);
10328 QCOMPARE(scene.focusItem(), (QGraphicsItem *) rect1child);
10330 // still no key events
10331 sendKeyClick(&scene, Qt::Key_J);
10332 sendKeyClick(&scene, Qt::Key_K);
10333 sendKeyClick(&scene, Qt::Key_L);
10334 sendKeyClick(&scene, Qt::Key_Semicolon);
10335 QCOMPARE(rect1childSpy.counts[QEvent::KeyPress], 0);
10336 QCOMPARE(rect1childSpy.counts[QEvent::KeyRelease], 0);
10337 QCOMPARE(rect1Spy.counts[QEvent::KeyPress], 0);
10338 QCOMPARE(rect1Spy.counts[QEvent::KeyRelease], 0);
10341 void tst_QGraphicsItem::itemIsInFront()
10343 QGraphicsScene scene;
10344 QGraphicsRectItem *rect1 = new QGraphicsRectItem;
10345 rect1->setData(0, "rect1");
10346 scene.addItem(rect1);
10348 QGraphicsRectItem *rect1child1 = new QGraphicsRectItem(rect1);
10349 rect1child1->setZValue(1);
10350 rect1child1->setData(0, "rect1child1");
10352 QGraphicsRectItem *rect1child2 = new QGraphicsRectItem(rect1);
10353 rect1child2->setParentItem(rect1);
10354 rect1child2->setData(0, "rect1child2");
10356 QGraphicsRectItem *rect1child1_1 = new QGraphicsRectItem(rect1child1);
10357 rect1child1_1->setData(0, "rect1child1_1");
10359 QGraphicsRectItem *rect1child1_2 = new QGraphicsRectItem(rect1child1);
10360 rect1child1_2->setFlag(QGraphicsItem::ItemStacksBehindParent);
10361 rect1child1_2->setData(0, "rect1child1_2");
10363 QGraphicsRectItem *rect2 = new QGraphicsRectItem;
10364 rect2->setData(0, "rect2");
10365 scene.addItem(rect2);
10367 QGraphicsRectItem *rect2child1 = new QGraphicsRectItem(rect2);
10368 rect2child1->setData(0, "rect2child1");
10370 QCOMPARE(qt_closestItemFirst(rect1, rect1), false);
10371 QCOMPARE(qt_closestItemFirst(rect1, rect2), false);
10372 QCOMPARE(qt_closestItemFirst(rect1child1, rect2child1), false);
10373 QCOMPARE(qt_closestItemFirst(rect1child1, rect1child2), true);
10374 QCOMPARE(qt_closestItemFirst(rect1child1_1, rect1child2), true);
10375 QCOMPARE(qt_closestItemFirst(rect1child1_1, rect1child1), true);
10376 QCOMPARE(qt_closestItemFirst(rect1child1_2, rect1child2), true);
10377 QCOMPARE(qt_closestItemFirst(rect1child1_2, rect1child1), false);
10378 QCOMPARE(qt_closestItemFirst(rect1child1_2, rect1), true);
10379 QCOMPARE(qt_closestItemFirst(rect1child1_2, rect2), false);
10380 QCOMPARE(qt_closestItemFirst(rect1child1_2, rect2child1), false);
10383 class ScenePosChangeTester : public ItemChangeTester
10386 ScenePosChangeTester()
10388 ScenePosChangeTester(QGraphicsItem *parent) : ItemChangeTester(parent)
10392 void tst_QGraphicsItem::scenePosChange()
10394 ScenePosChangeTester* root = new ScenePosChangeTester;
10395 ScenePosChangeTester* child1 = new ScenePosChangeTester(root);
10396 ScenePosChangeTester* grandChild1 = new ScenePosChangeTester(child1);
10397 ScenePosChangeTester* child2 = new ScenePosChangeTester(root);
10398 ScenePosChangeTester* grandChild2 = new ScenePosChangeTester(child2);
10400 child1->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
10401 grandChild2->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
10403 QVERIFY(child1->flags() & QGraphicsItem::ItemSendsScenePositionChanges);
10404 QVERIFY(grandChild2->flags() & QGraphicsItem::ItemSendsScenePositionChanges);
10406 QGraphicsScene scene;
10407 scene.addItem(root);
10409 // ignore uninteresting changes
10412 grandChild1->clear();
10413 grandChild2->clear();
10416 root->moveBy(1.0, 1.0);
10417 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10418 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10419 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10420 QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10423 child2->moveBy(1.0, 1.0);
10424 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10425 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10426 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10427 QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 2);
10430 grandChild2->setParentItem(child1);
10431 child1->moveBy(1.0, 1.0);
10432 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 2);
10433 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10434 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10435 QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 3);
10438 grandChild1->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
10439 grandChild2->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, false);
10440 QCoreApplication::processEvents(); // QGraphicsScenePrivate::_q_updateScenePosDescendants()
10441 child1->moveBy(1.0, 1.0);
10442 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 3);
10443 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10444 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10445 QCOMPARE(grandChild2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 3);
10448 scene.removeItem(grandChild1);
10449 delete grandChild2; grandChild2 = 0;
10450 QCoreApplication::processEvents(); // QGraphicsScenePrivate::_q_updateScenePosDescendants()
10451 root->moveBy(1.0, 1.0);
10452 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 4);
10453 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10454 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10457 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 5);
10458 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10459 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10462 QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 6);
10463 QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
10464 QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
10467 class MyInputContext : public QInputContext
10470 MyInputContext() : nbUpdates(0) {}
10471 ~MyInputContext() {}
10473 QString identifierName() { return QString(); }
10474 QString language() { return QString(); }
10478 bool isComposing() const { return false; }
10480 void update() { nbUpdates++; }
10485 class MyInputWidget : public QGraphicsWidget
10490 setFlag(QGraphicsItem::ItemIsFocusable, true);
10491 setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
10493 void mousePressEvent(QGraphicsSceneMouseEvent *event)
10498 void doUpdateMicroFocus()
10500 if (QWidget *fw = QApplication::focusWidget()) {
10502 for (int i = 0 ; i < scene()->views().count() ; ++i) {
10503 if (scene()->views().at(i) == fw) {
10504 if (QInputContext *inputContext = fw->inputContext()) {
10505 inputContext->update();
10514 void tst_QGraphicsItem::updateMicroFocus()
10516 #if defined Q_OS_WIN || defined Q_OS_MAC
10517 QSKIP("QTBUG-9578");
10519 QGraphicsScene scene;
10521 QGridLayout layout;
10522 parent.setLayout(&layout);
10523 QGraphicsView view(&scene);
10524 QGraphicsView view2(&scene);
10525 layout.addWidget(&view, 0, 0);
10526 layout.addWidget(&view2, 0, 1);
10527 MyInputContext *ic = new MyInputContext;
10528 qApp->setInputContext(ic);
10529 MyInputWidget input;
10530 input.setPos(0, 0);
10531 input.resize(150, 150);
10532 scene.addItem(&input);
10536 qApp->setAutoSipEnabled(true);
10537 QApplication::setActiveWindow(&parent);
10538 QTest::qWaitForWindowShown(&parent);
10539 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&parent));
10540 //We reset the number of updates that happened previously (initialisation)
10542 input.doUpdateMicroFocus();
10543 QApplication::processEvents();
10544 QTRY_COMPARE(ic->nbUpdates, 1);
10547 void tst_QGraphicsItem::textItem_shortcuts()
10552 QGraphicsScene scene;
10553 QGraphicsView view(&scene);
10554 l.addWidget(&view);
10555 QPushButton b("Push Me");
10558 QGraphicsTextItem *item = scene.addText("Troll Text");
10559 item->setFlag(QGraphicsItem::ItemIsFocusable);
10560 item->setTextInteractionFlags(Qt::TextEditorInteraction);
10562 QTest::qWaitForWindowShown(&w);
10565 QTRY_VERIFY(item->hasFocus());
10566 QVERIFY(item->textCursor().selectedText().isEmpty());
10568 // Shortcut should work (select all)
10569 QTest::keyClick(&view, Qt::Key_A, Qt::ControlModifier);
10570 QTRY_COMPARE(item->textCursor().selectedText(), item->toPlainText());
10571 QTextCursor tc = item->textCursor();
10572 tc.clearSelection();
10573 item->setTextCursor(tc);
10574 QVERIFY(item->textCursor().selectedText().isEmpty());
10576 // Shortcut should also work if the text item has the focus and another widget
10577 // has the same shortcut.
10578 b.setShortcut(QKeySequence("CTRL+A"));
10579 QTest::keyClick(&view, Qt::Key_A, Qt::ControlModifier);
10580 QTRY_COMPARE(item->textCursor().selectedText(), item->toPlainText());
10583 void tst_QGraphicsItem::scroll()
10585 // Create two overlapping rectangles in the scene:
10590 // +---| | <- item2
10594 EventTester *item1 = new EventTester;
10595 item1->br = QRectF(0, 0, 200, 200);
10596 item1->brush = Qt::red;
10597 item1->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption);
10599 EventTester *item2 = new EventTester;
10600 item2->br = QRectF(0, 0, 200, 200);
10601 item2->brush = Qt::blue;
10602 item2->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption);
10603 item2->setPos(100, 100);
10605 QGraphicsScene scene(0, 0, 300, 300);
10606 scene.addItem(item1);
10607 scene.addItem(item2);
10609 MyGraphicsView view(&scene);
10610 view.setFrameStyle(0);
10612 QTest::qWaitForWindowShown(&view);
10613 QTRY_VERIFY(view.repaints > 0);
10619 const QRectF item1BoundingRect = item1->boundingRect();
10620 const QRectF item2BoundingRect = item2->boundingRect();
10623 // Item1 should get full exposure
10624 // Item2 should get exposure for the part that overlaps item1.
10625 item1->scroll(0, -10);
10626 QTRY_VERIFY(view.repaints > 0);
10627 QCOMPARE(item1->lastExposedRect, item1BoundingRect);
10629 QRectF expectedItem2Expose = item2BoundingRect;
10630 // NB! Adjusted by 2 pixels for antialiasing
10631 expectedItem2Expose &= item1->mapRectToItem(item2, item1BoundingRect.adjusted(-2, -2, 2, 2));
10632 QCOMPARE(item2->lastExposedRect, expectedItem2Expose);
10634 // Enable ItemCoordinateCache on item1.
10636 item1->setCacheMode(QGraphicsItem::ItemCoordinateCache);
10637 QTRY_VERIFY(view.repaints > 0);
10643 // Item1 should only get expose for the newly exposed area (accelerated scroll).
10644 // Item2 should get exposure for the part that overlaps item1.
10645 item1->scroll(0, -10, QRectF(50, 50, 100, 100));
10646 QTRY_VERIFY(view.repaints > 0);
10647 QCOMPARE(item1->lastExposedRect, QRectF(50, 140, 100, 10));
10649 expectedItem2Expose = item2BoundingRect;
10650 // NB! Adjusted by 2 pixels for antialiasing
10651 expectedItem2Expose &= item1->mapRectToItem(item2, QRectF(50, 50, 100, 100).adjusted(-2, -2, 2, 2));
10652 QCOMPARE(item2->lastExposedRect, expectedItem2Expose);
10655 Q_DECLARE_METATYPE(QGraphicsItem::GraphicsItemFlag);
10657 void tst_QGraphicsItem::focusHandling_data()
10659 QTest::addColumn<QGraphicsItem::GraphicsItemFlag>("focusFlag");
10660 QTest::addColumn<bool>("useStickyFocus");
10661 QTest::addColumn<int>("expectedFocusItem"); // 0: none, 1: focusableUnder, 2: itemWithFocus
10663 QTest::newRow("Focus goes through.")
10664 << static_cast<QGraphicsItem::GraphicsItemFlag>(0x0) << false << 1;
10666 QTest::newRow("Focus goes through, even with sticky scene.")
10667 << static_cast<QGraphicsItem::GraphicsItemFlag>(0x0) << true << 1;
10669 QTest::newRow("With ItemStopsClickFocusPropagation, we cannot focus the item beneath the flagged one (but can still focus-out).")
10670 << QGraphicsItem::ItemStopsClickFocusPropagation << false << 0;
10672 QTest::newRow("With ItemStopsClickFocusPropagation, we cannot focus the item beneath the flagged one (and cannot focus-out if scene is sticky).")
10673 << QGraphicsItem::ItemStopsClickFocusPropagation << true << 2;
10675 QTest::newRow("With ItemStopsFocusHandling, focus cannot be changed by presses.")
10676 << QGraphicsItem::ItemStopsFocusHandling << false << 2;
10678 QTest::newRow("With ItemStopsFocusHandling, focus cannot be changed by presses (even if scene is sticky).")
10679 << QGraphicsItem::ItemStopsFocusHandling << true << 2;
10682 void tst_QGraphicsItem::focusHandling()
10684 QFETCH(QGraphicsItem::GraphicsItemFlag, focusFlag);
10685 QFETCH(bool, useStickyFocus);
10686 QFETCH(int, expectedFocusItem);
10688 class MyItem : public QGraphicsRectItem
10691 MyItem() : QGraphicsRectItem(0, 0, 100, 100) {}
10692 void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
10694 painter->fillRect(boundingRect(), hasFocus() ? QBrush(Qt::red) : brush());
10698 QGraphicsRectItem *noFocusOnTop = new MyItem;
10699 noFocusOnTop->setFlag(QGraphicsItem::ItemIsFocusable, false);
10700 noFocusOnTop->setBrush(Qt::yellow);
10702 QGraphicsRectItem *focusableUnder = new MyItem;
10703 focusableUnder->setBrush(Qt::blue);
10704 focusableUnder->setFlag(QGraphicsItem::ItemIsFocusable);
10705 focusableUnder->setPos(50, 50);
10707 QGraphicsRectItem *itemWithFocus = new MyItem;
10708 itemWithFocus->setBrush(Qt::black);
10709 itemWithFocus->setFlag(QGraphicsItem::ItemIsFocusable);
10710 itemWithFocus->setPos(250, 10);
10712 QGraphicsScene scene(-50, -50, 400, 400);
10713 scene.addItem(noFocusOnTop);
10714 scene.addItem(focusableUnder);
10715 scene.addItem(itemWithFocus);
10716 scene.setStickyFocus(useStickyFocus);
10718 noFocusOnTop->setFlag(focusFlag);
10719 focusableUnder->stackBefore(noFocusOnTop);
10720 itemWithFocus->setFocus();
10722 QGraphicsView view(&scene);
10724 QTest::qWaitForWindowShown(&view);
10726 QApplication::setActiveWindow(&view);
10727 QTRY_COMPARE(QApplication::activeWindow(), static_cast<QWidget *>(&view));
10728 QVERIFY(itemWithFocus->hasFocus());
10730 const QPointF mousePressPoint = noFocusOnTop->mapToScene(noFocusOnTop->boundingRect().center());
10731 const QList<QGraphicsItem *> itemsAtMousePressPosition = scene.items(mousePressPoint);
10732 QVERIFY(itemsAtMousePressPosition.contains(noFocusOnTop));
10734 sendMousePress(&scene, mousePressPoint);
10736 switch (expectedFocusItem) {
10738 QCOMPARE(scene.focusItem(), static_cast<QGraphicsRectItem *>(0));
10741 QCOMPARE(scene.focusItem(), focusableUnder);
10744 QCOMPARE(scene.focusItem(), itemWithFocus);
10748 // Sanity check - manually setting the focus must work regardless of our
10749 // focus handling flags:
10750 focusableUnder->setFocus();
10751 QCOMPARE(scene.focusItem(), focusableUnder);
10754 void tst_QGraphicsItem::touchEventPropagation_data()
10756 QTest::addColumn<QGraphicsItem::GraphicsItemFlag>("flag");
10757 QTest::addColumn<int>("expectedCount");
10759 QTest::newRow("ItemIsPanel")
10760 << QGraphicsItem::ItemIsPanel << 0;
10761 QTest::newRow("ItemStopsClickFocusPropagation")
10762 << QGraphicsItem::ItemStopsClickFocusPropagation << 1;
10763 QTest::newRow("ItemStopsFocusHandling")
10764 << QGraphicsItem::ItemStopsFocusHandling << 1;
10767 void tst_QGraphicsItem::touchEventPropagation()
10769 QFETCH(QGraphicsItem::GraphicsItemFlag, flag);
10770 QFETCH(int, expectedCount);
10772 class Testee : public QGraphicsRectItem
10775 int touchBeginEventCount;
10778 : QGraphicsRectItem(0, 0, 100, 100)
10779 , touchBeginEventCount(0)
10781 setAcceptTouchEvents(true);
10782 setFlag(QGraphicsItem::ItemIsFocusable, false);
10785 bool sceneEvent(QEvent *ev)
10787 if (ev->type() == QEvent::TouchBegin)
10788 ++touchBeginEventCount;
10790 return QGraphicsRectItem::sceneEvent(ev);
10794 Testee *touchEventReceiver = new Testee;
10795 QGraphicsItem *topMost = new QGraphicsRectItem(touchEventReceiver->boundingRect());
10797 QGraphicsScene scene;
10798 scene.addItem(topMost);
10799 scene.addItem(touchEventReceiver);
10801 topMost->setAcceptTouchEvents(true);
10802 topMost->setZValue(FLT_MAX);
10803 topMost->setFlag(QGraphicsItem::ItemIsFocusable, false);
10804 topMost->setFlag(flag, true);
10806 QGraphicsView view(&scene);
10807 view.setSceneRect(touchEventReceiver->boundingRect());
10809 QTest::qWaitForWindowShown(&view);
10811 QCOMPARE(touchEventReceiver->touchBeginEventCount, 0);
10813 QTouchEvent::TouchPoint tp(0);
10814 tp.setState(Qt::TouchPointPressed);
10815 tp.setScenePos(view.sceneRect().center());
10816 tp.setLastScenePos(view.sceneRect().center());
10818 QList<QTouchEvent::TouchPoint> touchPoints;
10821 sendMousePress(&scene, tp.scenePos());
10822 QTouchEvent touchBegin(QEvent::TouchBegin, QTouchEvent::TouchScreen, Qt::NoModifier, Qt::TouchPointPressed, touchPoints);
10824 qApp->sendEvent(&scene, &touchBegin);
10825 QCOMPARE(touchEventReceiver->touchBeginEventCount, expectedCount);
10828 void tst_QGraphicsItem::deviceCoordinateCache_simpleRotations()
10830 // Make sure we don't invalidate the cache when applying simple
10831 // (90, 180, 270, 360) rotation transforms to the item.
10832 QGraphicsRectItem *item = new QGraphicsRectItem(0, 0, 300, 200);
10833 item->setBrush(Qt::red);
10834 item->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
10836 QGraphicsScene scene;
10837 scene.setSceneRect(0, 0, 300, 200);
10838 scene.addItem(item);
10840 MyGraphicsView view(&scene);
10842 QTest::qWaitForWindowShown(&view);
10843 QTRY_VERIFY(view.repaints > 0);
10845 QGraphicsItemCache *itemCache = QGraphicsItemPrivate::get(item)->extraItemCache();
10846 QVERIFY(itemCache);
10847 QPixmapCache::Key currentKey = itemCache->deviceData.value(view.viewport()).key;
10849 // Trigger an update and verify that the cache is unchanged.
10850 QPixmapCache::Key oldKey = currentKey;
10852 view.viewport()->update();
10853 QTRY_VERIFY(view.repaints > 0);
10854 currentKey = itemCache->deviceData.value(view.viewport()).key;
10855 QCOMPARE(currentKey, oldKey);
10857 // Check 90, 180, 270 and 360 degree rotations.
10858 for (int angle = 90; angle <= 360; angle += 90) {
10859 // Rotate item and verify that the cache was invalidated.
10860 oldKey = currentKey;
10862 QTransform transform;
10863 transform.translate(150, 100);
10864 transform.rotate(angle);
10865 transform.translate(-150, -100);
10866 item->setTransform(transform);
10867 QTRY_VERIFY(view.repaints > 0);
10868 currentKey = itemCache->deviceData.value(view.viewport()).key;
10869 QVERIFY(currentKey != oldKey);
10872 // Trigger an update and verify that the cache is unchanged.
10873 oldKey = currentKey;
10875 view.viewport()->update();
10876 QTRY_VERIFY(view.repaints > 0);
10877 currentKey = itemCache->deviceData.value(view.viewport()).key;
10878 QCOMPARE(currentKey, oldKey);
10881 // 45 degree rotation.
10882 oldKey = currentKey;
10884 QTransform transform;
10885 transform.translate(150, 100);
10886 transform.rotate(45);
10887 transform.translate(-150, -100);
10888 item->setTransform(transform);
10889 QTRY_VERIFY(view.repaints > 0);
10890 currentKey = itemCache->deviceData.value(view.viewport()).key;
10891 QVERIFY(currentKey != oldKey);
10893 // Trigger an update and verify that the cache was invalidated.
10894 // We should always invalidate the cache for non-trivial transforms.
10895 oldKey = currentKey;
10897 view.viewport()->update();
10898 QTRY_VERIFY(view.repaints > 0);
10899 currentKey = itemCache->deviceData.value(view.viewport()).key;
10900 QVERIFY(currentKey != oldKey);
10903 void tst_QGraphicsItem::QTBUG_5418_textItemSetDefaultColor()
10905 struct Item : public QGraphicsTextItem
10908 void paint(QPainter *painter, const QStyleOptionGraphicsItem *opt, QWidget *wid)
10911 QGraphicsTextItem::paint(painter, opt, wid);
10915 Item *i = new Item;
10917 i->setPlainText("I AM A TROLL");
10919 QGraphicsScene scene;
10920 QGraphicsView view(&scene);
10922 QTest::qWaitForWindowShown(&view);
10924 QApplication::processEvents();
10925 QTRY_VERIFY(i->painted);
10926 QApplication::processEvents();
10929 QColor col(Qt::red);
10930 i->setDefaultTextColor(col);
10931 QApplication::processEvents();
10932 QTRY_COMPARE(i->painted, 1); //check that changing the color force an update
10934 i->painted = false;
10935 QImage image(400, 200, QImage::Format_RGB32);
10937 QPainter painter(&image);
10938 scene.render(&painter);
10940 QCOMPARE(i->painted, 1);
10942 int numRedPixel = 0;
10943 QRgb rgb = col.rgb();
10944 for (int y = 0; y < image.height(); ++y) {
10945 for (int x = 0; x < image.width(); ++x) {
10946 // Because of antialiasing we allow a certain range of errors here.
10947 QRgb pixel = image.pixel(x, y);
10948 if (qAbs((int)(pixel & 0xff) - (int)(rgb & 0xff)) +
10949 qAbs((int)((pixel & 0xff00) >> 8) - (int)((rgb & 0xff00) >> 8)) +
10950 qAbs((int)((pixel & 0xff0000) >> 16) - (int)((rgb & 0xff0000) >> 16)) <= 50) {
10951 if (++numRedPixel >= 10) {
10957 QCOMPARE(numRedPixel, -1); //color not found, FAIL!
10960 i->setDefaultTextColor(col);
10961 QApplication::processEvents();
10962 QCOMPARE(i->painted, 0); //same color as before should not trigger an update (QTBUG-6242)
10965 void tst_QGraphicsItem::QTBUG_6738_missingUpdateWithSetParent()
10967 // In all 3 test cases below the reparented item should disappear
10968 EventTester *parent = new EventTester;
10969 EventTester *child = new EventTester(parent);
10970 EventTester *child2 = new EventTester(parent);
10971 EventTester *child3 = new EventTester(parent);
10972 EventTester *child4 = new EventTester(parent);
10974 child->setPos(10, 10);
10975 child2->setPos(20, 20);
10976 child3->setPos(30, 30);
10977 child4->setPos(40, 40);
10979 QGraphicsScene scene;
10980 scene.addItem(parent);
10982 MyGraphicsView view(&scene);
10983 if(PlatformQuirks::isAutoMaximizing())
10984 view.showFullScreen();
10987 QTest::qWaitForWindowShown(&view);
10988 QTRY_VERIFY(view.repaints > 0);
10992 child2->setVisible(false);
10993 child2->setParentItem(child);
10995 QTRY_VERIFY(view.repaints == 1);
10999 child3->setOpacity(0.0);
11000 child3->setParentItem(child);
11002 QTRY_VERIFY(view.repaints == 1);
11006 child4->setParentItem(child);
11007 child4->setVisible(false);
11009 QTRY_VERIFY(view.repaints == 1);
11012 void tst_QGraphicsItem::QT_2653_fullUpdateDiscardingOpacityUpdate()
11014 QGraphicsScene scene(0, 0, 200, 200);
11015 MyGraphicsView view(&scene);
11017 EventTester *parentGreen = new EventTester();
11018 parentGreen->setGeometry(QRectF(20, 20, 100, 100));
11019 parentGreen->brush = Qt::green;
11021 EventTester *childYellow = new EventTester(parentGreen);
11022 childYellow->setGeometry(QRectF(10, 10, 50, 50));
11023 childYellow->brush = Qt::yellow;
11025 scene.addItem(parentGreen);
11027 childYellow->setOpacity(0.0);
11028 parentGreen->setOpacity(0.0);
11030 // set any of the flags below to trigger a fullUpdate to reproduce the bug:
11031 // ItemIgnoresTransformations, ItemClipsChildrenToShape, ItemIsSelectable
11032 parentGreen->setFlag(QGraphicsItem::ItemIgnoresTransformations);
11034 if (PlatformQuirks::isAutoMaximizing())
11035 view.showFullScreen();
11038 QTest::qWaitForWindowShown(&view);
11041 parentGreen->setOpacity(1.0);
11043 QTRY_COMPARE(view.repaints, 1);
11046 childYellow->repaints = 0;
11048 childYellow->setOpacity(1.0);
11050 QTRY_COMPARE(view.repaints, 1);
11051 QTRY_COMPARE(childYellow->repaints, 1);
11054 void tst_QGraphicsItem::QTBUG_7714_fullUpdateDiscardingOpacityUpdate2()
11056 QGraphicsScene scene(0, 0, 200, 200);
11057 MyGraphicsView view(&scene);
11058 MyGraphicsView origView(&scene);
11060 EventTester *parentGreen = new EventTester();
11061 parentGreen->setGeometry(QRectF(20, 20, 100, 100));
11062 parentGreen->brush = Qt::green;
11064 EventTester *childYellow = new EventTester(parentGreen);
11065 childYellow->setGeometry(QRectF(10, 10, 50, 50));
11066 childYellow->brush = Qt::yellow;
11068 scene.addItem(parentGreen);
11071 QTest::qWaitForWindowShown(&origView);
11072 origView.setGeometry(origView.width() + 20, 20,
11073 origView.width(), origView.height());
11075 parentGreen->setFlag(QGraphicsItem::ItemIgnoresTransformations);
11078 childYellow->setOpacity(0.0);
11080 QTRY_COMPARE(origView.repaints, 1);
11084 QTest::qWaitForWindowShown(&view);
11088 childYellow->setOpacity(1.0);
11090 QTRY_COMPARE(origView.repaints, 1);
11091 QTRY_COMPARE(view.repaints, 1);
11094 void tst_QGraphicsItem::QT_2649_focusScope()
11096 QGraphicsScene *scene = new QGraphicsScene;
11098 QGraphicsRectItem *subFocusItem = new QGraphicsRectItem;
11099 subFocusItem->setFlags(QGraphicsItem::ItemIsFocusable);
11100 subFocusItem->setFocus();
11101 QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
11103 QGraphicsRectItem *scope = new QGraphicsRectItem;
11104 scope->setFlags(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemIsFocusScope);
11106 subFocusItem->setParentItem(scope);
11107 QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
11108 QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
11109 QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
11110 QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
11112 QGraphicsRectItem *rootItem = new QGraphicsRectItem;
11113 rootItem->setFlags(QGraphicsItem::ItemIsFocusable);
11114 scope->setParentItem(rootItem);
11115 QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)subFocusItem);
11116 QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
11117 QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
11118 QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
11119 QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
11120 QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
11122 scene->addItem(rootItem);
11124 QEvent windowActivate(QEvent::WindowActivate);
11125 qApp->sendEvent(scene, &windowActivate);
11128 QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)subFocusItem);
11129 QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
11130 QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
11131 QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
11132 QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
11133 QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
11134 QVERIFY(subFocusItem->hasFocus());
11138 QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)0);
11139 QCOMPARE(scope->focusItem(), (QGraphicsItem *)0);
11140 QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)0);
11141 QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
11142 QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
11143 QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
11144 QVERIFY(!subFocusItem->hasFocus());
11148 QCOMPARE(rootItem->focusItem(), (QGraphicsItem *)subFocusItem);
11149 QCOMPARE(scope->focusItem(), (QGraphicsItem *)subFocusItem);
11150 QCOMPARE(subFocusItem->focusItem(), (QGraphicsItem *)subFocusItem);
11151 QCOMPARE(rootItem->focusScopeItem(), (QGraphicsItem *)0);
11152 QCOMPARE(scope->focusScopeItem(), (QGraphicsItem *)subFocusItem);
11153 QCOMPARE(subFocusItem->focusScopeItem(), (QGraphicsItem *)0);
11154 QVERIFY(subFocusItem->hasFocus());
11156 // This should not crash
11161 class MyGraphicsItemWithItemChange : public QGraphicsWidget
11164 MyGraphicsItemWithItemChange(QGraphicsItem *parent = 0) : QGraphicsWidget(parent)
11167 QVariant itemChange(GraphicsItemChange change, const QVariant &value)
11169 if (change == QGraphicsItem::ItemSceneHasChanged) {
11170 foreach (QGraphicsView *view, scene()->views()) {
11171 //We trigger a sort of unindexed items in the BSP
11175 return QGraphicsWidget::itemChange(change, value);
11179 void tst_QGraphicsItem::sortItemsWhileAdding()
11181 QGraphicsScene scene;
11182 QGraphicsView view(&scene);
11183 QGraphicsWidget grandGrandParent;
11184 grandGrandParent.resize(200, 200);
11185 scene.addItem(&grandGrandParent);
11186 QGraphicsWidget grandParent;
11187 grandParent.resize(200, 200);
11188 QGraphicsWidget parent(&grandParent);
11189 parent.resize(200, 200);
11190 MyGraphicsItemWithItemChange item(&parent);
11191 grandParent.setParentItem(&grandGrandParent);
11194 void tst_QGraphicsItem::doNotMarkFullUpdateIfNotInScene()
11196 struct Item : public QGraphicsTextItem
11199 void paint(QPainter *painter, const QStyleOptionGraphicsItem *opt, QWidget *wid)
11202 QGraphicsTextItem::paint(painter, opt, wid);
11205 QGraphicsScene scene;
11206 MyGraphicsView view(&scene);
11207 Item *item = new Item;
11209 item->setPlainText("Grandparent");
11210 Item *item2 = new Item;
11211 item2->setPlainText("parent");
11212 item2->painted = 0;
11213 Item *item3 = new Item;
11214 item3->setPlainText("child");
11215 item3->painted = 0;
11216 QGraphicsOpacityEffect *effect = new QGraphicsOpacityEffect;
11217 effect->setOpacity(0.5);
11218 item2->setGraphicsEffect(effect);
11219 item3->setParentItem(item2);
11220 item2->setParentItem(item);
11221 scene.addItem(item);
11222 if(PlatformQuirks::isAutoMaximizing())
11223 view.showFullScreen();
11226 QTest::qWaitForWindowShown(&view);
11227 QTRY_COMPARE(view.repaints, 1);
11228 QTRY_COMPARE(item->painted, 1);
11229 QTRY_COMPARE(item2->painted, 1);
11230 QTRY_COMPARE(item3->painted, 1);
11232 QApplication::processEvents();
11233 QTRY_COMPARE(item->painted, 2);
11234 QTRY_COMPARE(item2->painted, 2);
11235 QTRY_COMPARE(item3->painted, 2);
11237 QApplication::processEvents();
11238 QTRY_COMPARE(item->painted, 3);
11239 QTRY_COMPARE(item2->painted, 3);
11240 QTRY_COMPARE(item3->painted, 3);
11243 void tst_QGraphicsItem::itemDiesDuringDraggingOperation()
11245 QGraphicsScene scene;
11246 QGraphicsView view(&scene);
11247 QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
11248 item->setFlag(QGraphicsItem::ItemIsMovable);
11249 item->setAcceptDrops(true);
11250 scene.addItem(item);
11252 QApplication::setActiveWindow(&view);
11253 QTest::qWaitForWindowShown(&view);
11254 QTRY_COMPARE(QApplication::activeWindow(), (QWidget *)&view);
11255 QGraphicsSceneDragDropEvent dragEnter(QEvent::GraphicsSceneDragEnter);
11256 dragEnter.setScenePos(item->boundingRect().center());
11257 QApplication::sendEvent(&scene, &dragEnter);
11258 QGraphicsSceneDragDropEvent event(QEvent::GraphicsSceneDragMove);
11259 event.setScenePos(item->boundingRect().center());
11260 QApplication::sendEvent(&scene, &event);
11261 QVERIFY(QGraphicsScenePrivate::get(&scene)->dragDropItem == item);
11263 QVERIFY(QGraphicsScenePrivate::get(&scene)->dragDropItem == 0);
11266 void tst_QGraphicsItem::QTBUG_12112_focusItem()
11268 QGraphicsScene scene;
11269 QGraphicsView view(&scene);
11270 QGraphicsRectItem *item1 = new QGraphicsRectItem(0, 0, 20, 20);
11271 item1->setFlag(QGraphicsItem::ItemIsFocusable);
11272 QGraphicsRectItem *item2 = new QGraphicsRectItem(20, 20, 20, 20);
11273 item2->setFlag(QGraphicsItem::ItemIsFocusable);
11275 scene.addItem(item2);
11276 scene.addItem(item1);
11279 QApplication::setActiveWindow(&view);
11280 QTest::qWaitForWindowShown(&view);
11281 QTRY_COMPARE(QApplication::activeWindow(), (QWidget *)&view);
11283 QVERIFY(item1->focusItem());
11284 QVERIFY(!item2->focusItem());
11287 QVERIFY(!item1->focusItem());
11288 QVERIFY(item2->focusItem());
11291 void tst_QGraphicsItem::QTBUG_13473_sceneposchange()
11293 ScenePosChangeTester* parent = new ScenePosChangeTester;
11294 ScenePosChangeTester* child = new ScenePosChangeTester(parent);
11296 // parent's disabled ItemSendsGeometryChanges flag must not affect
11297 // child's scene pos change notifications
11298 parent->setFlag(QGraphicsItem::ItemSendsGeometryChanges, false);
11299 child->setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
11301 QGraphicsScene scene;
11302 scene.addItem(parent);
11304 // ignore uninteresting changes
11309 parent->moveBy(1.0, 1.0);
11310 QCOMPARE(child->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1);
11313 parent->setTransform(QTransform::fromScale(0.5, 0.5));
11314 QCOMPARE(child->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 2);
11317 class MyGraphicsWidget : public QGraphicsWidget {
11321 : QGraphicsWidget(0)
11323 QGraphicsLinearLayout *lay = new QGraphicsLinearLayout(Qt::Vertical);
11324 QLatin1String wiseWords("AZ BUKI VEDI");
11325 QString sentence(wiseWords);
11326 QStringList words = sentence.split(QLatin1Char(' '), QString::SkipEmptyParts);
11327 for (int i = 0; i < words.count(); ++i) {
11328 QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(this);
11329 QLabel *label = new QLabel(words.at(i));
11330 proxy->setWidget(label);
11331 proxy->setFocusPolicy(Qt::StrongFocus);
11332 proxy->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true);
11334 proxy->setVisible(false);
11336 lay->addItem(proxy);
11343 class MyWidgetWindow : public QGraphicsWidget
11347 : QGraphicsWidget(0, Qt::Window)
11349 QGraphicsLinearLayout *lay = new QGraphicsLinearLayout(Qt::Vertical);
11350 MyGraphicsWidget *widget = new MyGraphicsWidget();
11351 lay->addItem(widget);
11356 void tst_QGraphicsItem::QTBUG_16374_crashInDestructor()
11358 QGraphicsScene scene;
11359 QGraphicsView view(&scene);
11361 MyWidgetWindow win;
11362 scene.addItem(&win);
11365 QTest::qWaitForWindowShown(&view);
11368 void tst_QGraphicsItem::QTBUG_20699_focusScopeCrash()
11370 QGraphicsScene scene;
11371 QGraphicsView view(&scene);
11372 QGraphicsPixmapItem fs;
11373 fs.setFlags(QGraphicsItem::ItemIsFocusScope | QGraphicsItem::ItemIsFocusable);
11374 scene.addItem(&fs);
11375 QGraphicsPixmapItem* fs2 = new QGraphicsPixmapItem(&fs);
11376 fs2->setFlags(QGraphicsItem::ItemIsFocusScope | QGraphicsItem::ItemIsFocusable);
11377 QGraphicsPixmapItem* fi2 = new QGraphicsPixmapItem(&fs);
11378 fi2->setFlags(QGraphicsItem::ItemIsFocusable);
11379 QGraphicsPixmapItem* fi = new QGraphicsPixmapItem(fs2);
11380 fi->setFlags(QGraphicsItem::ItemIsFocusable);
11385 QTest::qWaitForWindowShown(&view);
11387 fi->setParentItem(fi2);
11390 fi->setParentItem(fs2);
11394 fi->setParentItem(fi2);
11399 QTEST_MAIN(tst_QGraphicsItem)
11400 #include "tst_qgraphicsitem.moc"