src/gui/graphicsview/qgraphicsscene.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 /*!
       
    43     \class QGraphicsScene
       
    44     \brief The QGraphicsScene class provides a surface for managing a large
       
    45     number of 2D graphical items.
       
    46     \since 4.2
       
    47     \ingroup graphicsview-api
       
    48 
       
    49 
       
    50     The class serves as a container for QGraphicsItems. It is used together
       
    51     with QGraphicsView for visualizing graphical items, such as lines,
       
    52     rectangles, text, or even custom items, on a 2D surface. QGraphicsScene is
       
    53     part of \l{The Graphics View Framework}.
       
    54 
       
    55     QGraphicsScene also provides functionality that lets you efficiently
       
    56     determine both the location of items, and for determining what items are
       
    57     visible within an arbitrary area on the scene. With the QGraphicsView
       
    58     widget, you can either visualize the whole scene, or zoom in and view only
       
    59     parts of the scene.
       
    60 
       
    61     Example:
       
    62 
       
    63     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsscene.cpp 0
       
    64 
       
    65     Note that QGraphicsScene has no visual appearance of its own; it only
       
    66     manages the items. You need to create a QGraphicsView widget to visualize
       
    67     the scene.
       
    68 
       
    69     To add items to a scene, you start off by constructing a QGraphicsScene
       
    70     object. Then, you have two options: either add your existing QGraphicsItem
       
    71     objects by calling addItem(), or you can call one of the convenience
       
    72     functions addEllipse(), addLine(), addPath(), addPixmap(), addPolygon(),
       
    73     addRect(), or addText(), which all return a pointer to the newly added item.
       
    74     The dimensions of the items added with these functions are relative to the
       
    75     item's coordinate system, and the items position is initialized to (0,
       
    76     0) in the scene.
       
    77 
       
    78     You can then visualize the scene using QGraphicsView. When the scene
       
    79     changes, (e.g., when an item moves or is transformed) QGraphicsScene
       
    80     emits the changed() signal. To remove an item, call removeItem().
       
    81 
       
    82     QGraphicsScene uses an indexing algorithm to manage the location of items
       
    83     efficiently. By default, a BSP (Binary Space Partitioning) tree is used; an
       
    84     algorithm suitable for large scenes where most items remain static (i.e.,
       
    85     do not move around). You can choose to disable this index by calling
       
    86     setItemIndexMethod(). For more information about the available indexing
       
    87     algorithms, see the itemIndexMethod property.
       
    88 
       
    89     The scene's bounding rect is set by calling setSceneRect(). Items can be
       
    90     placed at any position on the scene, and the size of the scene is by
       
    91     default unlimited. The scene rect is used only for internal bookkeeping,
       
    92     maintaining the scene's item index. If the scene rect is unset,
       
    93     QGraphicsScene will use the bounding area of all items, as returned by
       
    94     itemsBoundingRect(), as the scene rect. However, itemsBoundingRect() is a
       
    95     relatively time consuming function, as it operates by collecting
       
    96     positional information for every item on the scene. Because of this, you
       
    97     should always set the scene rect when operating on large scenes.
       
    98 
       
    99     One of QGraphicsScene's greatest strengths is its ability to efficiently
       
   100     determine the location of items. Even with millions of items on the scene,
       
   101     the items() functions can determine the location of an item within few
       
   102     milliseconds. There are several overloads to items(): one that finds items
       
   103     at a certain position, one that finds items inside or intersecting with a
       
   104     polygon or a rectangle, and more. The list of returned items is sorted by
       
   105     stacking order, with the topmost item being the first item in the list.
       
   106     For convenience, there is also an itemAt() function that returns the
       
   107     topmost item at a given position.
       
   108 
       
   109     QGraphicsScene maintains selection information for the scene. To select
       
   110     items, call setSelectionArea(), and to clear the current selection, call
       
   111     clearSelection(). Call selectedItems() to get the list of all selected
       
   112     items.
       
   113 
       
   114     \section1 Event Handling and Propagation
       
   115 
       
   116     Another responsibility that QGraphicsScene has, is to propagate events
       
   117     from QGraphicsView. To send an event to a scene, you construct an event
       
   118     that inherits QEvent, and then send it using, for example,
       
   119     QApplication::sendEvent(). event() is responsible for dispatching
       
   120     the event to the individual items. Some common events are handled by
       
   121     convenience event handlers. For example, key press events are handled by
       
   122     keyPressEvent(), and mouse press events are handled by mousePressEvent().
       
   123 
       
   124     Key events are delivered to the \e {focus item}. To set the focus item,
       
   125     you can either call setFocusItem(), passing an item that accepts focus, or
       
   126     the item itself can call QGraphicsItem::setFocus().  Call focusItem() to
       
   127     get the current focus item. For compatibility with widgets, the scene also
       
   128     maintains its own focus information. By default, the scene does not have
       
   129     focus, and all key events are discarded. If setFocus() is called, or if an
       
   130     item on the scene gains focus, the scene automatically gains focus. If the
       
   131     scene has focus, hasFocus() will return true, and key events will be
       
   132     forwarded to the focus item, if any. If the scene loses focus, (i.e.,
       
   133     someone calls clearFocus(),) while an item has focus, the scene will
       
   134     maintain its item focus information, and once the scene regains focus, it
       
   135     will make sure the last focus item regains focus.
       
   136 
       
   137     For mouse-over effects, QGraphicsScene dispatches \e {hover
       
   138     events}. If an item accepts hover events (see
       
   139     QGraphicsItem::acceptHoverEvents()), it will receive a \l
       
   140     {QEvent::}{GraphicsSceneHoverEnter} event when the mouse enters
       
   141     its area. As the mouse continues moving inside the item's area,
       
   142     QGraphicsScene will send it \l {QEvent::}{GraphicsSceneHoverMove}
       
   143     events. When the mouse leaves the item's area, the item will
       
   144     receive a \l {QEvent::}{GraphicsSceneHoverLeave} event.
       
   145 
       
   146     All mouse events are delivered to the current \e {mouse grabber}
       
   147     item. An item becomes the scene's mouse grabber if it accepts
       
   148     mouse events (see QGraphicsItem::acceptedMouseButtons()) and it
       
   149     receives a mouse press. It stays the mouse grabber until it
       
   150     receives a mouse release when no other mouse buttons are
       
   151     pressed. You can call mouseGrabberItem() to determine what item is
       
   152     currently grabbing the mouse.
       
   153 
       
   154     \sa QGraphicsItem, QGraphicsView
       
   155 */
       
   156 
       
   157 /*!
       
   158     \enum QGraphicsScene::SceneLayer
       
   159     \since 4.3
       
   160 
       
   161     This enum describes the rendering layers in a QGraphicsScene. When
       
   162     QGraphicsScene draws the scene contents, it renders each of these layers
       
   163     separately, in order.
       
   164 
       
   165     Each layer represents a flag that can be OR'ed together when calling
       
   166     functions such as invalidate() or QGraphicsView::invalidateScene().
       
   167 
       
   168     \value ItemLayer The item layer. QGraphicsScene renders all items are in
       
   169     this layer by calling the virtual function drawItems(). The item layer is
       
   170     drawn after the background layer, but before the foreground layer.
       
   171 
       
   172     \value BackgroundLayer The background layer. QGraphicsScene renders the
       
   173     scene's background in this layer by calling the virtual function
       
   174     drawBackground(). The background layer is drawn first of all layers.
       
   175 
       
   176     \value ForegroundLayer The foreground layer. QGraphicsScene renders the
       
   177     scene's foreground in this layer by calling the virtual function
       
   178     drawForeground().  The foreground layer is drawn last of all layers.
       
   179 
       
   180     \value AllLayers All layers; this value represents a combination of all
       
   181     three layers.
       
   182 
       
   183     \sa invalidate(), QGraphicsView::invalidateScene()
       
   184 */
       
   185 
       
   186 /*!
       
   187     \enum QGraphicsScene::ItemIndexMethod
       
   188 
       
   189     This enum describes the indexing algorithms QGraphicsScene provides for
       
   190     managing positional information about items on the scene.
       
   191 
       
   192     \value BspTreeIndex A Binary Space Partitioning tree is applied. All
       
   193     QGraphicsScene's item location algorithms are of an order close to
       
   194     logarithmic complexity, by making use of binary search. Adding, moving and
       
   195     removing items is logarithmic. This approach is best for static scenes
       
   196     (i.e., scenes where most items do not move).
       
   197 
       
   198     \value NoIndex No index is applied. Item location is of linear complexity,
       
   199     as all items on the scene are searched. Adding, moving and removing items,
       
   200     however, is done in constant time. This approach is ideal for dynamic
       
   201     scenes, where many items are added, moved or removed continuously.
       
   202 
       
   203     \sa setItemIndexMethod(), bspTreeDepth
       
   204 */
       
   205 
       
   206 #include "qgraphicsscene.h"
       
   207 
       
   208 #ifndef QT_NO_GRAPHICSVIEW
       
   209 
       
   210 #include "qgraphicsitem.h"
       
   211 #include "qgraphicsitem_p.h"
       
   212 #include "qgraphicslayout.h"
       
   213 #include "qgraphicsscene_p.h"
       
   214 #include "qgraphicssceneevent.h"
       
   215 #include "qgraphicsview.h"
       
   216 #include "qgraphicsview_p.h"
       
   217 #include "qgraphicswidget.h"
       
   218 #include "qgraphicswidget_p.h"
       
   219 #include "qgraphicssceneindex_p.h"
       
   220 #include "qgraphicsscenebsptreeindex_p.h"
       
   221 #include "qgraphicsscenelinearindex_p.h"
       
   222 
       
   223 #include <QtCore/qdebug.h>
       
   224 #include <QtCore/qlist.h>
       
   225 #include <QtCore/qmath.h>
       
   226 #include <QtCore/qrect.h>
       
   227 #include <QtCore/qset.h>
       
   228 #include <QtCore/qstack.h>
       
   229 #include <QtCore/qtimer.h>
       
   230 #include <QtCore/qvarlengtharray.h>
       
   231 #include <QtGui/qapplication.h>
       
   232 #include <QtGui/qdesktopwidget.h>
       
   233 #include <QtGui/qevent.h>
       
   234 #include <QtGui/qgraphicslayout.h>
       
   235 #include <QtGui/qgraphicsproxywidget.h>
       
   236 #include <QtGui/qgraphicswidget.h>
       
   237 #include <QtGui/qmatrix.h>
       
   238 #include <QtGui/qpaintengine.h>
       
   239 #include <QtGui/qpainter.h>
       
   240 #include <QtGui/qpixmapcache.h>
       
   241 #include <QtGui/qpolygon.h>
       
   242 #include <QtGui/qstyleoption.h>
       
   243 #include <QtGui/qtooltip.h>
       
   244 #include <QtGui/qtransform.h>
       
   245 #include <QtGui/qinputcontext.h>
       
   246 #include <QtGui/qgraphicseffect.h>
       
   247 #include <private/qapplication_p.h>
       
   248 #include <private/qobject_p.h>
       
   249 #ifdef Q_WS_X11
       
   250 #include <private/qt_x11_p.h>
       
   251 #endif
       
   252 #include <private/qgraphicseffect_p.h>
       
   253 #include <private/qgesturemanager_p.h>
       
   254 
       
   255 // #define GESTURE_DEBUG
       
   256 #ifndef GESTURE_DEBUG
       
   257 # define DEBUG if (0) qDebug
       
   258 #else
       
   259 # define DEBUG qDebug
       
   260 #endif
       
   261 
       
   262 QT_BEGIN_NAMESPACE
       
   263 
       
   264 bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event);
       
   265 
       
   266 static void _q_hoverFromMouseEvent(QGraphicsSceneHoverEvent *hover, const QGraphicsSceneMouseEvent *mouseEvent)
       
   267 {
       
   268     hover->setWidget(mouseEvent->widget());
       
   269     hover->setPos(mouseEvent->pos());
       
   270     hover->setScenePos(mouseEvent->scenePos());
       
   271     hover->setScreenPos(mouseEvent->screenPos());
       
   272     hover->setLastPos(mouseEvent->lastPos());
       
   273     hover->setLastScenePos(mouseEvent->lastScenePos());
       
   274     hover->setLastScreenPos(mouseEvent->lastScreenPos());
       
   275     hover->setModifiers(mouseEvent->modifiers());
       
   276     hover->setAccepted(mouseEvent->isAccepted());
       
   277 }
       
   278 
       
   279 int QGraphicsScenePrivate::changedSignalIndex;
       
   280 
       
   281 /*!
       
   282     \internal
       
   283 */
       
   284 QGraphicsScenePrivate::QGraphicsScenePrivate()
       
   285     : indexMethod(QGraphicsScene::BspTreeIndex),
       
   286       index(0),
       
   287       lastItemCount(0),
       
   288       hasSceneRect(false),
       
   289       dirtyGrowingItemsBoundingRect(true),
       
   290       updateAll(false),
       
   291       calledEmitUpdated(false),
       
   292       processDirtyItemsEmitted(false),
       
   293       selectionChanging(0),
       
   294       needSortTopLevelItems(true),
       
   295       holesInTopLevelSiblingIndex(false),
       
   296       topLevelSequentialOrdering(true),
       
   297       stickyFocus(false),
       
   298       hasFocus(false),
       
   299       focusItem(0),
       
   300       lastFocusItem(0),
       
   301       tabFocusFirst(0),
       
   302       activePanel(0),
       
   303       lastActivePanel(0),
       
   304       activationRefCount(0),
       
   305       childExplicitActivation(0),
       
   306       lastMouseGrabberItem(0),
       
   307       lastMouseGrabberItemHasImplicitMouseGrab(false),
       
   308       dragDropItem(0),
       
   309       enterWidget(0),
       
   310       lastDropAction(Qt::IgnoreAction),
       
   311       allItemsIgnoreHoverEvents(true),
       
   312       allItemsUseDefaultCursor(true),
       
   313       painterStateProtection(true),
       
   314       sortCacheEnabled(false),
       
   315       style(0),
       
   316       allItemsIgnoreTouchEvents(true)
       
   317 {
       
   318 }
       
   319 
       
   320 /*!
       
   321     \internal
       
   322 */
       
   323 void QGraphicsScenePrivate::init()
       
   324 {
       
   325     Q_Q(QGraphicsScene);
       
   326 
       
   327     index = new QGraphicsSceneBspTreeIndex(q);
       
   328 
       
   329     // Keep this index so we can check for connected slots later on.
       
   330     if (!changedSignalIndex) {
       
   331         changedSignalIndex = signalIndex("changed(QList<QRectF>)");
       
   332     }
       
   333     qApp->d_func()->scene_list.append(q);
       
   334     q->update();
       
   335 }
       
   336 
       
   337 /*!
       
   338     \internal
       
   339 */
       
   340 QGraphicsScenePrivate *QGraphicsScenePrivate::get(QGraphicsScene *q)
       
   341 {
       
   342     return q->d_func();
       
   343 }
       
   344 
       
   345 void QGraphicsScenePrivate::_q_emitUpdated()
       
   346 {
       
   347     Q_Q(QGraphicsScene);
       
   348     calledEmitUpdated = false;
       
   349 
       
   350     if (dirtyGrowingItemsBoundingRect) {
       
   351         if (!hasSceneRect) {
       
   352             const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect;
       
   353             growingItemsBoundingRect |= q->itemsBoundingRect();
       
   354             if (oldGrowingItemsBoundingRect != growingItemsBoundingRect)
       
   355                 emit q->sceneRectChanged(growingItemsBoundingRect);
       
   356         }
       
   357         dirtyGrowingItemsBoundingRect = false;
       
   358     }
       
   359 
       
   360     // Ensure all views are connected if anything is connected. This disables
       
   361     // the optimization that items send updates directly to the views, but it
       
   362     // needs to happen in order to keep compatibility with the behavior from
       
   363     // Qt 4.4 and backward.
       
   364     if (isSignalConnected(changedSignalIndex)) {
       
   365         for (int i = 0; i < views.size(); ++i) {
       
   366             QGraphicsView *view = views.at(i);
       
   367             if (!view->d_func()->connectedToScene) {
       
   368                 view->d_func()->connectedToScene = true;
       
   369                 q->connect(q, SIGNAL(changed(QList<QRectF>)),
       
   370                            views.at(i), SLOT(updateScene(QList<QRectF>)));
       
   371             }
       
   372         }
       
   373     } else {
       
   374         updateAll = false;
       
   375         for (int i = 0; i < views.size(); ++i)
       
   376             views.at(i)->d_func()->processPendingUpdates();
       
   377         // It's important that we update all views before we dispatch, hence two for-loops.
       
   378         for (int i = 0; i < views.size(); ++i)
       
   379             views.at(i)->d_func()->dispatchPendingUpdateRequests();
       
   380         return;
       
   381     }
       
   382 
       
   383     // Notify the changes to anybody interested.
       
   384     QList<QRectF> oldUpdatedRects;
       
   385     oldUpdatedRects = updateAll ? (QList<QRectF>() << q->sceneRect()) : updatedRects;
       
   386     updateAll = false;
       
   387     updatedRects.clear();
       
   388     emit q->changed(oldUpdatedRects);
       
   389 }
       
   390 
       
   391 /*!
       
   392     \internal
       
   393 
       
   394     ### This function is almost identical to QGraphicsItemPrivate::addChild().
       
   395 */
       
   396 void QGraphicsScenePrivate::registerTopLevelItem(QGraphicsItem *item)
       
   397 {
       
   398     item->d_ptr->ensureSequentialSiblingIndex();
       
   399     needSortTopLevelItems = true; // ### maybe false
       
   400     item->d_ptr->siblingIndex = topLevelItems.size();
       
   401     topLevelItems.append(item);
       
   402 }
       
   403 
       
   404 /*!
       
   405     \internal
       
   406 
       
   407     ### This function is almost identical to QGraphicsItemPrivate::removeChild().
       
   408 */
       
   409 void QGraphicsScenePrivate::unregisterTopLevelItem(QGraphicsItem *item)
       
   410 {
       
   411     if (!holesInTopLevelSiblingIndex)
       
   412         holesInTopLevelSiblingIndex = item->d_ptr->siblingIndex != topLevelItems.size() - 1;
       
   413     if (topLevelSequentialOrdering && !holesInTopLevelSiblingIndex)
       
   414         topLevelItems.removeAt(item->d_ptr->siblingIndex);
       
   415     else
       
   416         topLevelItems.removeOne(item);
       
   417     // NB! Do not use topLevelItems.removeAt(item->d_ptr->siblingIndex) because
       
   418     // the item is not guaranteed to be at the index after the list is sorted
       
   419     // (see ensureSortedTopLevelItems()).
       
   420     item->d_ptr->siblingIndex = -1;
       
   421     if (topLevelSequentialOrdering)
       
   422         topLevelSequentialOrdering = !holesInTopLevelSiblingIndex;
       
   423 }
       
   424 
       
   425 /*!
       
   426     \internal
       
   427 */
       
   428 void QGraphicsScenePrivate::_q_polishItems()
       
   429 {
       
   430     QSet<QGraphicsItem *>::Iterator it;
       
   431     const QVariant booleanTrueVariant(true);
       
   432     while (!unpolishedItems.isEmpty()) {
       
   433         it = unpolishedItems.begin();
       
   434         QGraphicsItem *item = *it;
       
   435         unpolishedItems.erase(it);
       
   436         if (!item->d_ptr->explicitlyHidden) {
       
   437             item->itemChange(QGraphicsItem::ItemVisibleChange, booleanTrueVariant);
       
   438             item->itemChange(QGraphicsItem::ItemVisibleHasChanged, booleanTrueVariant);
       
   439         }
       
   440         if (item->isWidget()) {
       
   441             QEvent event(QEvent::Polish);
       
   442             QApplication::sendEvent((QGraphicsWidget *)item, &event);
       
   443         }
       
   444     }
       
   445 }
       
   446 
       
   447 void QGraphicsScenePrivate::_q_processDirtyItems()
       
   448 {
       
   449     processDirtyItemsEmitted = false;
       
   450 
       
   451     if (updateAll) {
       
   452         Q_ASSERT(calledEmitUpdated);
       
   453         // No need for further processing (except resetting the dirty states).
       
   454         // The growingItemsBoundingRect is updated in _q_emitUpdated.
       
   455         for (int i = 0; i < topLevelItems.size(); ++i)
       
   456             resetDirtyItem(topLevelItems.at(i), /*recursive=*/true);
       
   457         return;
       
   458     }
       
   459 
       
   460     const bool wasPendingSceneUpdate = calledEmitUpdated;
       
   461     const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect;
       
   462 
       
   463     // Process items recursively.
       
   464     for (int i = 0; i < topLevelItems.size(); ++i)
       
   465         processDirtyItemsRecursive(topLevelItems.at(i));
       
   466 
       
   467     dirtyGrowingItemsBoundingRect = false;
       
   468     if (!hasSceneRect && oldGrowingItemsBoundingRect != growingItemsBoundingRect)
       
   469         emit q_func()->sceneRectChanged(growingItemsBoundingRect);
       
   470 
       
   471     if (wasPendingSceneUpdate)
       
   472         return;
       
   473 
       
   474     for (int i = 0; i < views.size(); ++i)
       
   475         views.at(i)->d_func()->processPendingUpdates();
       
   476 
       
   477     if (calledEmitUpdated) {
       
   478         // We did a compatibility QGraphicsScene::update in processDirtyItemsRecursive
       
   479         // and we cannot wait for the control to reach the eventloop before the
       
   480         // changed signal is emitted, so we emit it now.
       
   481         _q_emitUpdated();
       
   482     }
       
   483 
       
   484     // Immediately dispatch all pending update requests on the views.
       
   485     for (int i = 0; i < views.size(); ++i)
       
   486         views.at(i)->d_func()->dispatchPendingUpdateRequests();
       
   487 }
       
   488 
       
   489 /*!
       
   490     \internal
       
   491 
       
   492     Schedules an item for removal. This function leaves some stale indexes
       
   493     around in the BSP tree if called from the item's destructor; these will
       
   494     be cleaned up the next time someone triggers purgeRemovedItems().
       
   495 
       
   496     Note: This function might get called from QGraphicsItem's destructor. \a item is
       
   497     being destroyed, so we cannot call any pure virtual functions on it (such
       
   498     as boundingRect()). Also, it is unnecessary to update the item's own state
       
   499     in any way.
       
   500 */
       
   501 void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item)
       
   502 {
       
   503     Q_Q(QGraphicsScene);
       
   504 
       
   505     // Clear focus on the item to remove any reference in the focusWidget chain.
       
   506     item->clearFocus();
       
   507 
       
   508     markDirty(item, QRectF(), false, false, false, false, /*removingItemFromScene=*/true);
       
   509 
       
   510     if (item->d_ptr->inDestructor) {
       
   511         // The item is actually in its destructor, we call the special method in the index.
       
   512         index->deleteItem(item);
       
   513     } else {
       
   514         // Can potentially call item->boundingRect() (virtual function), that's why
       
   515         // we only can call this function if the item is not in its destructor.
       
   516         index->removeItem(item);
       
   517     }
       
   518 
       
   519     item->d_ptr->clearSubFocus();
       
   520 
       
   521     if (!item->d_ptr->inDestructor && item == tabFocusFirst) {
       
   522         QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
       
   523         widget->d_func()->fixFocusChainBeforeReparenting(0, 0);
       
   524     }
       
   525 
       
   526     item->d_func()->scene = 0;
       
   527 
       
   528     // Unregister focus proxy.
       
   529     item->d_ptr->resetFocusProxy();
       
   530 
       
   531     // Remove from parent, or unregister from toplevels.
       
   532     if (QGraphicsItem *parentItem = item->parentItem()) {
       
   533         if (parentItem->scene()) {
       
   534             Q_ASSERT_X(parentItem->scene() == q, "QGraphicsScene::removeItem",
       
   535                        "Parent item's scene is different from this item's scene");
       
   536             item->d_ptr->setParentItemHelper(0);
       
   537         }
       
   538     } else {
       
   539         unregisterTopLevelItem(item);
       
   540     }
       
   541 
       
   542     // Reset the mouse grabber and focus item data.
       
   543     if (item == focusItem)
       
   544         focusItem = 0;
       
   545     if (item == lastFocusItem)
       
   546         lastFocusItem = 0;
       
   547     if (item == activePanel) {
       
   548         // ### deactivate...
       
   549         activePanel = 0;
       
   550     }
       
   551     if (item == lastActivePanel)
       
   552         lastActivePanel = 0;
       
   553 
       
   554     // Disable selectionChanged() for individual items
       
   555     ++selectionChanging;
       
   556     int oldSelectedItemsSize = selectedItems.size();
       
   557 
       
   558     // Update selected & hovered item bookkeeping
       
   559     selectedItems.remove(item);
       
   560     hoverItems.removeAll(item);
       
   561     cachedItemsUnderMouse.removeAll(item);
       
   562     unpolishedItems.remove(item);
       
   563     resetDirtyItem(item);
       
   564 
       
   565     //We remove all references of item from the sceneEventFilter arrays
       
   566     QMultiMap<QGraphicsItem*, QGraphicsItem*>::iterator iterator = sceneEventFilters.begin();
       
   567     while (iterator != sceneEventFilters.end()) {
       
   568         if (iterator.value() == item || iterator.key() == item)
       
   569             iterator = sceneEventFilters.erase(iterator);
       
   570         else
       
   571             ++iterator;
       
   572     }
       
   573 
       
   574     if (!item->d_ptr->inDestructor) {
       
   575         // Remove all children recursively
       
   576         for (int i = 0; i < item->d_ptr->children.size(); ++i)
       
   577             q->removeItem(item->d_ptr->children.at(i));
       
   578     }
       
   579 
       
   580     if (item->isPanel() && item->isVisible() && item->panelModality() != QGraphicsItem::NonModal)
       
   581         leaveModal(item);
       
   582 
       
   583     // Reset the mouse grabber and focus item data.
       
   584     if (mouseGrabberItems.contains(item))
       
   585         ungrabMouse(item, /* item is dying */ item->d_ptr->inDestructor);
       
   586 
       
   587     // Reset the keyboard grabber
       
   588     if (keyboardGrabberItems.contains(item))
       
   589         ungrabKeyboard(item, /* item is dying */ item->d_ptr->inDestructor);
       
   590 
       
   591     // Reset the last mouse grabber item
       
   592     if (item == lastMouseGrabberItem)
       
   593         lastMouseGrabberItem = 0;
       
   594 
       
   595     // Reenable selectionChanged() for individual items
       
   596     --selectionChanging;
       
   597     if (!selectionChanging && selectedItems.size() != oldSelectedItemsSize)
       
   598         emit q->selectionChanged();
       
   599 }
       
   600 
       
   601 /*!
       
   602     \internal
       
   603 */
       
   604 void QGraphicsScenePrivate::setActivePanelHelper(QGraphicsItem *item, bool duringActivationEvent)
       
   605 {
       
   606     Q_Q(QGraphicsScene);
       
   607     if (item && item->scene() != q) {
       
   608         qWarning("QGraphicsScene::setActivePanel: item %p must be part of this scene",
       
   609                  item);
       
   610         return;
       
   611     }
       
   612 
       
   613     // Ensure the scene has focus when we change panel activation.
       
   614     q->setFocus(Qt::ActiveWindowFocusReason);
       
   615 
       
   616     // Find the item's panel.
       
   617     QGraphicsItem *panel = item ? item->panel() : 0;
       
   618     lastActivePanel = panel ? activePanel : 0;
       
   619     if (panel == activePanel || (!q->isActive() && !duringActivationEvent))
       
   620         return;
       
   621 
       
   622     // Deactivate the last active panel.
       
   623     if (activePanel) {
       
   624         if (QGraphicsItem *fi = activePanel->focusItem()) {
       
   625             // Remove focus from the current focus item.
       
   626             if (fi == q->focusItem())
       
   627                 q->setFocusItem(0, Qt::ActiveWindowFocusReason);
       
   628         }
       
   629 
       
   630         QEvent event(QEvent::WindowDeactivate);
       
   631         q->sendEvent(activePanel, &event);
       
   632     } else if (panel && !duringActivationEvent) {
       
   633         // Deactivate the scene if changing activation to a panel.
       
   634         QEvent event(QEvent::WindowDeactivate);
       
   635         foreach (QGraphicsItem *item, q->items()) {
       
   636             if (item->isVisible() && !item->isPanel() && !item->parentItem())
       
   637                 q->sendEvent(item, &event);
       
   638         }
       
   639     }
       
   640 
       
   641     // Update activate state.
       
   642     activePanel = panel;
       
   643     QEvent event(QEvent::ActivationChange);
       
   644     QApplication::sendEvent(q, &event);
       
   645 
       
   646     // Activate
       
   647     if (panel) {
       
   648         QEvent event(QEvent::WindowActivate);
       
   649         q->sendEvent(panel, &event);
       
   650 
       
   651         // Set focus on the panel's focus item.
       
   652         if (QGraphicsItem *focusItem = panel->focusItem())
       
   653             focusItem->setFocus(Qt::ActiveWindowFocusReason);
       
   654     } else if (q->isActive()) {
       
   655         // Activate the scene
       
   656         QEvent event(QEvent::WindowActivate);
       
   657         foreach (QGraphicsItem *item, q->items()) {
       
   658             if (item->isVisible() && !item->isPanel() && !item->parentItem())
       
   659                 q->sendEvent(item, &event);
       
   660         }
       
   661     }
       
   662 }
       
   663 
       
   664 /*!
       
   665     \internal
       
   666 */
       
   667 void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item,
       
   668                                                Qt::FocusReason focusReason)
       
   669 {
       
   670     Q_Q(QGraphicsScene);
       
   671     if (item == focusItem)
       
   672         return;
       
   673 
       
   674     // Clear focus if asked to set focus on something that can't
       
   675     // accept input focus.
       
   676     if (item && (!(item->flags() & QGraphicsItem::ItemIsFocusable)
       
   677                  || !item->isVisible() || !item->isEnabled())) {
       
   678         item = 0;
       
   679     }
       
   680 
       
   681     // Set focus on the scene if an item requests focus.
       
   682     if (item) {
       
   683         q->setFocus(focusReason);
       
   684         if (item == focusItem)
       
   685             return;
       
   686     }
       
   687 
       
   688     if (focusItem) {
       
   689         QFocusEvent event(QEvent::FocusOut, focusReason);
       
   690         lastFocusItem = focusItem;
       
   691         focusItem = 0;
       
   692         sendEvent(lastFocusItem, &event);
       
   693 
       
   694         if (lastFocusItem
       
   695             && (lastFocusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) {
       
   696             // Reset any visible preedit text
       
   697             QInputMethodEvent imEvent;
       
   698             sendEvent(lastFocusItem, &imEvent);
       
   699 
       
   700             // Close any external input method panel. This happens
       
   701             // automatically by removing WA_InputMethodEnabled on
       
   702             // the views, but if we are changing focus, we have to
       
   703             // do it ourselves.
       
   704             if (item) {
       
   705                 for (int i = 0; i < views.size(); ++i)
       
   706                     views.at(i)->inputContext()->reset();
       
   707             }
       
   708         }
       
   709     }
       
   710 
       
   711     if (item) {
       
   712         focusItem = item;
       
   713         QFocusEvent event(QEvent::FocusIn, focusReason);
       
   714         sendEvent(item, &event);
       
   715     }
       
   716 
       
   717     updateInputMethodSensitivityInViews();
       
   718 }
       
   719 
       
   720 /*!
       
   721     \internal
       
   722 */
       
   723 void QGraphicsScenePrivate::addPopup(QGraphicsWidget *widget)
       
   724 {
       
   725     Q_ASSERT(widget);
       
   726     Q_ASSERT(!popupWidgets.contains(widget));
       
   727     popupWidgets << widget;
       
   728     if (QGraphicsWidget *focusWidget = widget->focusWidget()) {
       
   729         focusWidget->setFocus(Qt::PopupFocusReason);
       
   730     } else {
       
   731         grabKeyboard((QGraphicsItem *)widget);
       
   732         if (focusItem && popupWidgets.size() == 1) {
       
   733             QFocusEvent event(QEvent::FocusOut, Qt::PopupFocusReason);
       
   734             sendEvent(focusItem, &event);
       
   735         }
       
   736     }
       
   737     grabMouse((QGraphicsItem *)widget);
       
   738 }
       
   739 
       
   740 /*!
       
   741     \internal
       
   742 
       
   743     Remove \a widget from the popup list. Important notes:
       
   744 
       
   745     \a widget is guaranteed to be in the list of popups, but it might not be
       
   746     the last entry; you can hide any item in the pop list before the others,
       
   747     and this must cause all later mouse grabbers to lose the grab.
       
   748 */
       
   749 void QGraphicsScenePrivate::removePopup(QGraphicsWidget *widget, bool itemIsDying)
       
   750 {
       
   751     Q_ASSERT(widget);
       
   752     int index = popupWidgets.indexOf(widget);
       
   753     Q_ASSERT(index != -1);
       
   754 
       
   755     for (int i = popupWidgets.size() - 1; i >= index; --i) {
       
   756         QGraphicsWidget *widget = popupWidgets.takeLast();
       
   757         ungrabMouse(widget, itemIsDying);
       
   758         if (focusItem && popupWidgets.isEmpty()) {
       
   759             QFocusEvent event(QEvent::FocusIn, Qt::PopupFocusReason);
       
   760             sendEvent(focusItem, &event);
       
   761         } else if (keyboardGrabberItems.contains(static_cast<QGraphicsItem *>(widget))) {
       
   762             ungrabKeyboard(static_cast<QGraphicsItem *>(widget), itemIsDying);
       
   763         }
       
   764         if (!itemIsDying && widget->isVisible()) {
       
   765             widget->hide();
       
   766             widget->QGraphicsItem::d_ptr->explicitlyHidden = 0;
       
   767         }
       
   768     }
       
   769 }
       
   770 
       
   771 /*!
       
   772     \internal
       
   773 */
       
   774 void QGraphicsScenePrivate::grabMouse(QGraphicsItem *item, bool implicit)
       
   775 {
       
   776     // Append to list of mouse grabber items, and send a mouse grab event.
       
   777     if (mouseGrabberItems.contains(item)) {
       
   778         if (mouseGrabberItems.last() == item) {
       
   779             Q_ASSERT(!implicit);
       
   780             if (!lastMouseGrabberItemHasImplicitMouseGrab) {
       
   781                 qWarning("QGraphicsItem::grabMouse: already a mouse grabber");
       
   782             } else {
       
   783                 // Upgrade to an explicit mouse grab
       
   784                 lastMouseGrabberItemHasImplicitMouseGrab = false;
       
   785             }
       
   786         } else {
       
   787             qWarning("QGraphicsItem::grabMouse: already blocked by mouse grabber: %p",
       
   788                      mouseGrabberItems.last());
       
   789         }
       
   790         return;
       
   791     }
       
   792 
       
   793     // Send ungrab event to the last grabber.
       
   794     if (!mouseGrabberItems.isEmpty()) {
       
   795         QGraphicsItem *last = mouseGrabberItems.last();
       
   796         if (lastMouseGrabberItemHasImplicitMouseGrab) {
       
   797             // Implicit mouse grab is immediately lost.
       
   798             last->ungrabMouse();
       
   799         } else {
       
   800             // Just send ungrab event to current grabber.
       
   801             QEvent ungrabEvent(QEvent::UngrabMouse);
       
   802             sendEvent(last, &ungrabEvent);
       
   803         }
       
   804     }
       
   805 
       
   806     mouseGrabberItems << item;
       
   807     lastMouseGrabberItemHasImplicitMouseGrab = implicit;
       
   808 
       
   809     // Send grab event to current grabber.
       
   810     QEvent grabEvent(QEvent::GrabMouse);
       
   811     sendEvent(item, &grabEvent);
       
   812 }
       
   813 
       
   814 /*!
       
   815     \internal
       
   816 */
       
   817 void QGraphicsScenePrivate::ungrabMouse(QGraphicsItem *item, bool itemIsDying)
       
   818 {
       
   819     int index = mouseGrabberItems.indexOf(item);
       
   820     if (index == -1) {
       
   821         qWarning("QGraphicsItem::ungrabMouse: not a mouse grabber");
       
   822         return;
       
   823     }
       
   824 
       
   825     if (item != mouseGrabberItems.last()) {
       
   826         // Recursively ungrab the next mouse grabber until we reach this item
       
   827         // to ensure state consistency.
       
   828         ungrabMouse(mouseGrabberItems.at(index + 1), itemIsDying);
       
   829     }
       
   830     if (!popupWidgets.isEmpty() && item == popupWidgets.last()) {
       
   831         // If the item is a popup, go via removePopup to ensure state
       
   832         // consistency and that it gets hidden correctly - beware that
       
   833         // removePopup() reenters this function to continue removing the grab.
       
   834         removePopup((QGraphicsWidget *)item, itemIsDying);
       
   835         return;
       
   836     }
       
   837 
       
   838     // Send notification about mouse ungrab.
       
   839     if (!itemIsDying) {
       
   840         QEvent event(QEvent::UngrabMouse);
       
   841         sendEvent(item, &event);
       
   842     }
       
   843 
       
   844     // Remove the item from the list of grabbers. Whenever this happens, we
       
   845     // reset the implicitGrab (there can be only ever be one implicit grabber
       
   846     // in a scene, and it is always the latest grabber; if the implicit grab
       
   847     // is lost, it is not automatically regained.
       
   848     mouseGrabberItems.takeLast();
       
   849     lastMouseGrabberItemHasImplicitMouseGrab = false;
       
   850 
       
   851     // Send notification about mouse regrab. ### It's unfortunate that all the
       
   852     // items get a GrabMouse event, but this is a rare case with a simple
       
   853     // implementation and it does ensure a consistent state.
       
   854     if (!itemIsDying && !mouseGrabberItems.isEmpty()) {
       
   855         QGraphicsItem *last = mouseGrabberItems.last();
       
   856         QEvent event(QEvent::GrabMouse);
       
   857         sendEvent(last, &event);
       
   858     }
       
   859 }
       
   860 
       
   861 /*!
       
   862     \internal
       
   863 */
       
   864 void QGraphicsScenePrivate::clearMouseGrabber()
       
   865 {
       
   866     if (!mouseGrabberItems.isEmpty())
       
   867         mouseGrabberItems.first()->ungrabMouse();
       
   868     lastMouseGrabberItem = 0;
       
   869 }
       
   870 
       
   871 /*!
       
   872     \internal
       
   873 */
       
   874 void QGraphicsScenePrivate::grabKeyboard(QGraphicsItem *item)
       
   875 {
       
   876     if (keyboardGrabberItems.contains(item)) {
       
   877         if (keyboardGrabberItems.last() == item)
       
   878             qWarning("QGraphicsItem::grabKeyboard: already a keyboard grabber");
       
   879         else
       
   880             qWarning("QGraphicsItem::grabKeyboard: already blocked by keyboard grabber: %p",
       
   881                      keyboardGrabberItems.last());
       
   882         return;
       
   883     }
       
   884 
       
   885     // Send ungrab event to the last grabber.
       
   886     if (!keyboardGrabberItems.isEmpty()) {
       
   887         // Just send ungrab event to current grabber.
       
   888         QEvent ungrabEvent(QEvent::UngrabKeyboard);
       
   889         sendEvent(keyboardGrabberItems.last(), &ungrabEvent);
       
   890     }
       
   891 
       
   892     keyboardGrabberItems << item;
       
   893 
       
   894     // Send grab event to current grabber.
       
   895     QEvent grabEvent(QEvent::GrabKeyboard);
       
   896     sendEvent(item, &grabEvent);
       
   897 }
       
   898 
       
   899 /*!
       
   900     \internal
       
   901 */
       
   902 void QGraphicsScenePrivate::ungrabKeyboard(QGraphicsItem *item, bool itemIsDying)
       
   903 {
       
   904     int index = keyboardGrabberItems.lastIndexOf(item);
       
   905     if (index == -1) {
       
   906         qWarning("QGraphicsItem::ungrabKeyboard: not a keyboard grabber");
       
   907         return;
       
   908     }
       
   909     if (item != keyboardGrabberItems.last()) {
       
   910         // Recursively ungrab the topmost keyboard grabber until we reach this
       
   911         // item to ensure state consistency.
       
   912         ungrabKeyboard(keyboardGrabberItems.at(index + 1), itemIsDying);
       
   913     }
       
   914 
       
   915     // Send notification about keyboard ungrab.
       
   916     if (!itemIsDying) {
       
   917         QEvent event(QEvent::UngrabKeyboard);
       
   918         sendEvent(item, &event);
       
   919     }
       
   920 
       
   921     // Remove the item from the list of grabbers.
       
   922     keyboardGrabberItems.takeLast();
       
   923 
       
   924     // Send notification about mouse regrab.
       
   925     if (!itemIsDying && !keyboardGrabberItems.isEmpty()) {
       
   926         QGraphicsItem *last = keyboardGrabberItems.last();
       
   927         QEvent event(QEvent::GrabKeyboard);
       
   928         sendEvent(last, &event);
       
   929     }
       
   930 }
       
   931 
       
   932 /*!
       
   933     \internal
       
   934 */
       
   935 void QGraphicsScenePrivate::clearKeyboardGrabber()
       
   936 {
       
   937     if (!keyboardGrabberItems.isEmpty())
       
   938         ungrabKeyboard(keyboardGrabberItems.first());
       
   939 }
       
   940 
       
   941 void QGraphicsScenePrivate::enableMouseTrackingOnViews()
       
   942 {
       
   943     foreach (QGraphicsView *view, views)
       
   944         view->viewport()->setMouseTracking(true);
       
   945 }
       
   946 
       
   947 /*!
       
   948     Returns all items for the screen position in \a event.
       
   949 */
       
   950 QList<QGraphicsItem *> QGraphicsScenePrivate::itemsAtPosition(const QPoint &screenPos,
       
   951                                                               const QPointF &scenePos,
       
   952                                                               QWidget *widget) const
       
   953 {
       
   954     Q_Q(const QGraphicsScene);
       
   955     QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0;
       
   956     if (!view)
       
   957         return q->items(scenePos, Qt::IntersectsItemShape, Qt::DescendingOrder, QTransform());
       
   958 
       
   959     const QRectF pointRect(QPointF(widget->mapFromGlobal(screenPos)), QSizeF(1, 1));
       
   960     if (!view->isTransformed())
       
   961         return q->items(pointRect, Qt::IntersectsItemShape, Qt::DescendingOrder);
       
   962 
       
   963     const QTransform viewTransform = view->viewportTransform();
       
   964     if (viewTransform.type() <= QTransform::TxScale) {
       
   965         return q->items(viewTransform.inverted().mapRect(pointRect), Qt::IntersectsItemShape,
       
   966                         Qt::DescendingOrder, viewTransform);
       
   967     }
       
   968     return q->items(viewTransform.inverted().map(pointRect), Qt::IntersectsItemShape,
       
   969                     Qt::DescendingOrder, viewTransform);
       
   970 }
       
   971 
       
   972 /*!
       
   973     \internal
       
   974 */
       
   975 void QGraphicsScenePrivate::storeMouseButtonsForMouseGrabber(QGraphicsSceneMouseEvent *event)
       
   976 {
       
   977     for (int i = 0x1; i <= 0x10; i <<= 1) {
       
   978         if (event->buttons() & i) {
       
   979             mouseGrabberButtonDownPos.insert(Qt::MouseButton(i),
       
   980                                              mouseGrabberItems.last()->d_ptr->genericMapFromScene(event->scenePos(),
       
   981                                                                                                   event->widget()));
       
   982             mouseGrabberButtonDownScenePos.insert(Qt::MouseButton(i), event->scenePos());
       
   983             mouseGrabberButtonDownScreenPos.insert(Qt::MouseButton(i), event->screenPos());
       
   984         }
       
   985     }
       
   986 }
       
   987 
       
   988 /*!
       
   989     \internal
       
   990 */
       
   991 void QGraphicsScenePrivate::installSceneEventFilter(QGraphicsItem *watched, QGraphicsItem *filter)
       
   992 {
       
   993     sceneEventFilters.insert(watched, filter);
       
   994 }
       
   995 
       
   996 /*!
       
   997     \internal
       
   998 */
       
   999 void QGraphicsScenePrivate::removeSceneEventFilter(QGraphicsItem *watched, QGraphicsItem *filter)
       
  1000 {
       
  1001     if (!sceneEventFilters.contains(watched))
       
  1002         return;
       
  1003 
       
  1004     QMultiMap<QGraphicsItem *, QGraphicsItem *>::Iterator it = sceneEventFilters.lowerBound(watched);
       
  1005     QMultiMap<QGraphicsItem *, QGraphicsItem *>::Iterator end = sceneEventFilters.upperBound(watched);
       
  1006     do {
       
  1007         if (it.value() == filter)
       
  1008             it = sceneEventFilters.erase(it);
       
  1009         else
       
  1010             ++it;
       
  1011     } while (it != end);
       
  1012 }
       
  1013 
       
  1014 /*!
       
  1015   \internal
       
  1016 */
       
  1017 bool QGraphicsScenePrivate::filterDescendantEvent(QGraphicsItem *item, QEvent *event)
       
  1018 {
       
  1019     if (item && (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorFiltersChildEvents)) {
       
  1020         QGraphicsItem *parent = item->parentItem();
       
  1021         while (parent) {
       
  1022             if (parent->d_ptr->filtersDescendantEvents && parent->sceneEventFilter(item, event))
       
  1023                 return true;
       
  1024             if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorFiltersChildEvents))
       
  1025                 return false;
       
  1026             parent = parent->parentItem();
       
  1027         }
       
  1028     }
       
  1029     return false;
       
  1030 }
       
  1031 
       
  1032 /*!
       
  1033     \internal
       
  1034 */
       
  1035 bool QGraphicsScenePrivate::filterEvent(QGraphicsItem *item, QEvent *event)
       
  1036 {
       
  1037     if (item && !sceneEventFilters.contains(item))
       
  1038         return false;
       
  1039 
       
  1040     QMultiMap<QGraphicsItem *, QGraphicsItem *>::Iterator it = sceneEventFilters.lowerBound(item);
       
  1041     QMultiMap<QGraphicsItem *, QGraphicsItem *>::Iterator end = sceneEventFilters.upperBound(item);
       
  1042     while (it != end) {
       
  1043         // ### The filterer and filteree might both be deleted.
       
  1044         if (it.value()->sceneEventFilter(it.key(), event))
       
  1045             return true;
       
  1046         ++it;
       
  1047     }
       
  1048     return false;
       
  1049 }
       
  1050 
       
  1051 /*!
       
  1052     \internal
       
  1053 
       
  1054     This is the final dispatch point for any events from the scene to the
       
  1055     item. It filters the event first - if the filter returns true, the event
       
  1056     is considered to have been eaten by the filter, and is therefore stopped
       
  1057     (the default filter returns false). Then/otherwise, if the item is
       
  1058     enabled, the event is sent; otherwise it is stopped.
       
  1059 */
       
  1060 bool QGraphicsScenePrivate::sendEvent(QGraphicsItem *item, QEvent *event)
       
  1061 {
       
  1062     if (QGraphicsObject *object = item->toGraphicsObject()) {
       
  1063         QApplicationPrivate *qAppPriv = QApplicationPrivate::instance();
       
  1064         if (qAppPriv->gestureManager) {
       
  1065             if (qAppPriv->gestureManager->filterEvent(object, event))
       
  1066                 return true;
       
  1067         }
       
  1068     }
       
  1069 
       
  1070     if (filterEvent(item, event))
       
  1071         return false;
       
  1072     if (filterDescendantEvent(item, event))
       
  1073         return false;
       
  1074     if (!item || !item->isEnabled())
       
  1075         return false;
       
  1076     if (QGraphicsObject *o = item->toGraphicsObject()) {
       
  1077         bool spont = event->spontaneous();
       
  1078         if (spont ? qt_sendSpontaneousEvent(o, event) : QApplication::sendEvent(o, event))
       
  1079             return true;
       
  1080         event->spont = spont;
       
  1081     }
       
  1082     return item->sceneEvent(event);
       
  1083 }
       
  1084 
       
  1085 /*!
       
  1086     \internal
       
  1087 */
       
  1088 void QGraphicsScenePrivate::cloneDragDropEvent(QGraphicsSceneDragDropEvent *dest,
       
  1089                                                QGraphicsSceneDragDropEvent *source)
       
  1090 {
       
  1091     dest->setWidget(source->widget());
       
  1092     dest->setPos(source->pos());
       
  1093     dest->setScenePos(source->scenePos());
       
  1094     dest->setScreenPos(source->screenPos());
       
  1095     dest->setButtons(source->buttons());
       
  1096     dest->setModifiers(source->modifiers());
       
  1097     dest->setPossibleActions(source->possibleActions());
       
  1098     dest->setProposedAction(source->proposedAction());
       
  1099     dest->setDropAction(source->dropAction());
       
  1100     dest->setSource(source->source());
       
  1101     dest->setMimeData(source->mimeData());
       
  1102 }
       
  1103 
       
  1104 /*!
       
  1105     \internal
       
  1106 */
       
  1107 void QGraphicsScenePrivate::sendDragDropEvent(QGraphicsItem *item,
       
  1108                                               QGraphicsSceneDragDropEvent *dragDropEvent)
       
  1109 {
       
  1110     dragDropEvent->setPos(item->d_ptr->genericMapFromScene(dragDropEvent->scenePos(), dragDropEvent->widget()));
       
  1111     sendEvent(item, dragDropEvent);
       
  1112 }
       
  1113 
       
  1114 /*!
       
  1115     \internal
       
  1116 */
       
  1117 void QGraphicsScenePrivate::sendHoverEvent(QEvent::Type type, QGraphicsItem *item,
       
  1118                                            QGraphicsSceneHoverEvent *hoverEvent)
       
  1119 {
       
  1120     QGraphicsSceneHoverEvent event(type);
       
  1121     event.setWidget(hoverEvent->widget());
       
  1122     event.setPos(item->d_ptr->genericMapFromScene(hoverEvent->scenePos(), hoverEvent->widget()));
       
  1123     event.setScenePos(hoverEvent->scenePos());
       
  1124     event.setScreenPos(hoverEvent->screenPos());
       
  1125     event.setLastPos(item->d_ptr->genericMapFromScene(hoverEvent->lastScenePos(), hoverEvent->widget()));
       
  1126     event.setLastScenePos(hoverEvent->lastScenePos());
       
  1127     event.setLastScreenPos(hoverEvent->lastScreenPos());
       
  1128     event.setModifiers(hoverEvent->modifiers());
       
  1129     sendEvent(item, &event);
       
  1130 }
       
  1131 
       
  1132 /*!
       
  1133     \internal
       
  1134 */
       
  1135 void QGraphicsScenePrivate::sendMouseEvent(QGraphicsSceneMouseEvent *mouseEvent)
       
  1136 {
       
  1137     if (mouseEvent->button() == 0 && mouseEvent->buttons() == 0 && lastMouseGrabberItemHasImplicitMouseGrab) {
       
  1138         // ### This is a temporary fix for until we get proper mouse
       
  1139         // grab events.
       
  1140         clearMouseGrabber();
       
  1141         return;
       
  1142     }
       
  1143 
       
  1144     QGraphicsItem *item = mouseGrabberItems.last();
       
  1145     if (item->isBlockedByModalPanel())
       
  1146         return;
       
  1147 
       
  1148     for (int i = 0x1; i <= 0x10; i <<= 1) {
       
  1149         Qt::MouseButton button = Qt::MouseButton(i);
       
  1150         mouseEvent->setButtonDownPos(button, mouseGrabberButtonDownPos.value(button, item->d_ptr->genericMapFromScene(mouseEvent->scenePos(), mouseEvent->widget())));
       
  1151         mouseEvent->setButtonDownScenePos(button, mouseGrabberButtonDownScenePos.value(button, mouseEvent->scenePos()));
       
  1152         mouseEvent->setButtonDownScreenPos(button, mouseGrabberButtonDownScreenPos.value(button, mouseEvent->screenPos()));
       
  1153     }
       
  1154     mouseEvent->setPos(item->d_ptr->genericMapFromScene(mouseEvent->scenePos(), mouseEvent->widget()));
       
  1155     mouseEvent->setLastPos(item->d_ptr->genericMapFromScene(mouseEvent->lastScenePos(), mouseEvent->widget()));
       
  1156     sendEvent(item, mouseEvent);
       
  1157 }
       
  1158 
       
  1159 /*!
       
  1160     \internal
       
  1161 */
       
  1162 void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent)
       
  1163 {
       
  1164     Q_Q(QGraphicsScene);
       
  1165 
       
  1166     // Ignore by default, unless we find a mouse grabber that accepts it.
       
  1167     mouseEvent->ignore();
       
  1168 
       
  1169     // Deliver to any existing mouse grabber.
       
  1170     if (!mouseGrabberItems.isEmpty()) {
       
  1171         if (mouseGrabberItems.last()->isBlockedByModalPanel())
       
  1172             return;
       
  1173         // The event is ignored by default, but we disregard the event's
       
  1174         // accepted state after delivery; the mouse is grabbed, after all.
       
  1175         sendMouseEvent(mouseEvent);
       
  1176         return;
       
  1177     }
       
  1178 
       
  1179     // Start by determining the number of items at the current position.
       
  1180     // Reuse value from earlier calculations if possible.
       
  1181     if (cachedItemsUnderMouse.isEmpty()) {
       
  1182         cachedItemsUnderMouse = itemsAtPosition(mouseEvent->screenPos(),
       
  1183                                                 mouseEvent->scenePos(),
       
  1184                                                 mouseEvent->widget());
       
  1185     }
       
  1186 
       
  1187     // Update window activation.
       
  1188     QGraphicsItem *topItem = cachedItemsUnderMouse.value(0);
       
  1189     QGraphicsWidget *newActiveWindow = topItem ? topItem->window() : 0;
       
  1190     if (newActiveWindow && newActiveWindow->isBlockedByModalPanel(&topItem)) {
       
  1191         // pass activation to the blocking modal window
       
  1192         newActiveWindow = topItem ? topItem->window() : 0;
       
  1193     }
       
  1194 
       
  1195     if (newActiveWindow != q->activeWindow())
       
  1196         q->setActiveWindow(newActiveWindow);
       
  1197 
       
  1198     // Set focus on the topmost enabled item that can take focus.
       
  1199     bool setFocus = false;
       
  1200     foreach (QGraphicsItem *item, cachedItemsUnderMouse) {
       
  1201         if (item->isBlockedByModalPanel()) {
       
  1202             // Make sure we don't clear focus.
       
  1203             setFocus = true;
       
  1204             break;
       
  1205         }
       
  1206         if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) {
       
  1207             if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) {
       
  1208                 setFocus = true;
       
  1209                 if (item != q->focusItem())
       
  1210                     q->setFocusItem(item, Qt::MouseFocusReason);
       
  1211                 break;
       
  1212             }
       
  1213         }
       
  1214         if (item->isPanel())
       
  1215             break;
       
  1216     }
       
  1217 
       
  1218     // Check for scene modality.
       
  1219     bool sceneModality = false;
       
  1220     for (int i = 0; i < modalPanels.size(); ++i) {
       
  1221         if (modalPanels.at(i)->panelModality() == QGraphicsItem::SceneModal) {
       
  1222             sceneModality = true;
       
  1223             break;
       
  1224         }
       
  1225     }
       
  1226 
       
  1227     // If nobody could take focus, clear it.
       
  1228     if (!stickyFocus && !setFocus && !sceneModality)
       
  1229         q->setFocusItem(0, Qt::MouseFocusReason);
       
  1230 
       
  1231     // Any item will do.
       
  1232     if (sceneModality && cachedItemsUnderMouse.isEmpty())
       
  1233         cachedItemsUnderMouse << modalPanels.first();
       
  1234 
       
  1235     // Find a mouse grabber by sending mouse press events to all mouse grabber
       
  1236     // candidates one at a time, until the event is accepted. It's accepted by
       
  1237     // default, so the receiver has to explicitly ignore it for it to pass
       
  1238     // through.
       
  1239     foreach (QGraphicsItem *item, cachedItemsUnderMouse) {
       
  1240         if (!(item->acceptedMouseButtons() & mouseEvent->button())) {
       
  1241             // Skip items that don't accept the event's mouse button.
       
  1242             continue;
       
  1243         }
       
  1244 
       
  1245         // Check if this item is blocked by a modal panel and deliver the mouse event to the
       
  1246         // blocking panel instead of this item if blocked.
       
  1247         (void) item->isBlockedByModalPanel(&item);
       
  1248 
       
  1249         grabMouse(item, /* implicit = */ true);
       
  1250         mouseEvent->accept();
       
  1251 
       
  1252         // check if the item we are sending to are disabled (before we send the event)
       
  1253         bool disabled = !item->isEnabled();
       
  1254         bool isPanel = item->isPanel();
       
  1255         if (mouseEvent->type() == QEvent::GraphicsSceneMouseDoubleClick
       
  1256             && item != lastMouseGrabberItem && lastMouseGrabberItem) {
       
  1257             // If this item is different from the item that received the last
       
  1258             // mouse event, and mouseEvent is a doubleclick event, then the
       
  1259             // event is converted to a press. Known limitation:
       
  1260             // Triple-clicking will not generate a doubleclick, though.
       
  1261             QGraphicsSceneMouseEvent mousePress(QEvent::GraphicsSceneMousePress);
       
  1262             mousePress.spont = mouseEvent->spont;
       
  1263             mousePress.accept();
       
  1264             mousePress.setButton(mouseEvent->button());
       
  1265             mousePress.setButtons(mouseEvent->buttons());
       
  1266             mousePress.setScreenPos(mouseEvent->screenPos());
       
  1267             mousePress.setScenePos(mouseEvent->scenePos());
       
  1268             mousePress.setModifiers(mouseEvent->modifiers());
       
  1269             mousePress.setWidget(mouseEvent->widget());
       
  1270             mousePress.setButtonDownPos(mouseEvent->button(),
       
  1271                                         mouseEvent->buttonDownPos(mouseEvent->button()));
       
  1272             mousePress.setButtonDownScenePos(mouseEvent->button(),
       
  1273                                              mouseEvent->buttonDownScenePos(mouseEvent->button()));
       
  1274             mousePress.setButtonDownScreenPos(mouseEvent->button(),
       
  1275                                               mouseEvent->buttonDownScreenPos(mouseEvent->button()));
       
  1276             sendMouseEvent(&mousePress);
       
  1277             mouseEvent->setAccepted(mousePress.isAccepted());
       
  1278         } else {
       
  1279             sendMouseEvent(mouseEvent);
       
  1280         }
       
  1281 
       
  1282         bool dontSendUngrabEvents = mouseGrabberItems.isEmpty() || mouseGrabberItems.last() != item;
       
  1283         if (disabled) {
       
  1284             ungrabMouse(item, /* itemIsDying = */ dontSendUngrabEvents);
       
  1285             break;
       
  1286         }
       
  1287         if (mouseEvent->isAccepted()) {
       
  1288             if (!mouseGrabberItems.isEmpty())
       
  1289                 storeMouseButtonsForMouseGrabber(mouseEvent);
       
  1290             lastMouseGrabberItem = item;
       
  1291             return;
       
  1292         }
       
  1293         ungrabMouse(item, /* itemIsDying = */ dontSendUngrabEvents);
       
  1294 
       
  1295         // Don't propagate through panels.
       
  1296         if (isPanel)
       
  1297             break;
       
  1298     }
       
  1299 
       
  1300     // Is the event still ignored? Then the mouse press goes to the scene.
       
  1301     // Reset the mouse grabber, clear the selection, clear focus, and leave
       
  1302     // the event ignored so that it can propagate through the originating
       
  1303     // view.
       
  1304     if (!mouseEvent->isAccepted()) {
       
  1305         clearMouseGrabber();
       
  1306 
       
  1307         QGraphicsView *view = mouseEvent->widget() ? qobject_cast<QGraphicsView *>(mouseEvent->widget()->parentWidget()) : 0;
       
  1308         bool dontClearSelection = view && view->dragMode() == QGraphicsView::ScrollHandDrag;
       
  1309         if (!dontClearSelection) {
       
  1310             // Clear the selection if the originating view isn't in scroll
       
  1311             // hand drag mode. The view will clear the selection if no drag
       
  1312             // happened.
       
  1313             q->clearSelection();
       
  1314         }
       
  1315     }
       
  1316 }
       
  1317 
       
  1318 /*!
       
  1319     \internal
       
  1320 
       
  1321     Ensures that the list of toplevels is sorted by insertion order, and that
       
  1322     the siblingIndexes are packed (no gaps), and start at 0.
       
  1323 
       
  1324     ### This function is almost identical to
       
  1325     QGraphicsItemPrivate::ensureSequentialSiblingIndex().
       
  1326 */
       
  1327 void QGraphicsScenePrivate::ensureSequentialTopLevelSiblingIndexes()
       
  1328 {
       
  1329     if (!topLevelSequentialOrdering) {
       
  1330         qSort(topLevelItems.begin(), topLevelItems.end(), QGraphicsItemPrivate::insertionOrder);
       
  1331         topLevelSequentialOrdering = true;
       
  1332         needSortTopLevelItems = 1;
       
  1333     }
       
  1334     if (holesInTopLevelSiblingIndex) {
       
  1335         holesInTopLevelSiblingIndex = 0;
       
  1336         for (int i = 0; i < topLevelItems.size(); ++i)
       
  1337             topLevelItems[i]->d_ptr->siblingIndex = i;
       
  1338     }
       
  1339 }
       
  1340 
       
  1341 /*!
       
  1342     \internal
       
  1343 
       
  1344     Set the font and propagate the changes if the font is different from the
       
  1345     current font.
       
  1346 */
       
  1347 void QGraphicsScenePrivate::setFont_helper(const QFont &font)
       
  1348 {
       
  1349     if (this->font == font && this->font.resolve() == font.resolve())
       
  1350         return;
       
  1351     updateFont(font);
       
  1352 }
       
  1353 
       
  1354 /*!
       
  1355     \internal
       
  1356 
       
  1357     Resolve the scene's font against the application font, and propagate the
       
  1358     changes too all items in the scene.
       
  1359 */
       
  1360 void QGraphicsScenePrivate::resolveFont()
       
  1361 {
       
  1362     QFont naturalFont = QApplication::font();
       
  1363     naturalFont.resolve(0);
       
  1364     QFont resolvedFont = font.resolve(naturalFont);
       
  1365     updateFont(resolvedFont);
       
  1366 }
       
  1367 
       
  1368 /*!
       
  1369     \internal
       
  1370 
       
  1371     Update the font, and whether or not it has changed, reresolve all fonts in
       
  1372     the scene.
       
  1373 */
       
  1374 void QGraphicsScenePrivate::updateFont(const QFont &font)
       
  1375 {
       
  1376     Q_Q(QGraphicsScene);
       
  1377 
       
  1378     // Update local font setting.
       
  1379     this->font = font;
       
  1380 
       
  1381     // Resolve the fonts of all top-level widget items, or widget items
       
  1382     // whose parent is not a widget.
       
  1383     foreach (QGraphicsItem *item, q->items()) {
       
  1384         if (!item->parentItem()) {
       
  1385             // Resolvefont for an item is a noop operation, but
       
  1386             // every item can be a widget, or can have a widget
       
  1387             // childre.
       
  1388             item->d_ptr->resolveFont(font.resolve());
       
  1389         }
       
  1390     }
       
  1391 
       
  1392     // Send the scene a FontChange event.
       
  1393     QEvent event(QEvent::FontChange);
       
  1394     QApplication::sendEvent(q, &event);
       
  1395 }
       
  1396 
       
  1397 /*!
       
  1398     \internal
       
  1399 
       
  1400     Set the palette and propagate the changes if the palette is different from
       
  1401     the current palette.
       
  1402 */
       
  1403 void QGraphicsScenePrivate::setPalette_helper(const QPalette &palette)
       
  1404 {
       
  1405     if (this->palette == palette && this->palette.resolve() == palette.resolve())
       
  1406         return;
       
  1407     updatePalette(palette);
       
  1408 }
       
  1409 
       
  1410 /*!
       
  1411     \internal
       
  1412 
       
  1413     Resolve the scene's palette against the application palette, and propagate
       
  1414     the changes too all items in the scene.
       
  1415 */
       
  1416 void QGraphicsScenePrivate::resolvePalette()
       
  1417 {
       
  1418     QPalette naturalPalette = QApplication::palette();
       
  1419     naturalPalette.resolve(0);
       
  1420     QPalette resolvedPalette = palette.resolve(naturalPalette);
       
  1421     updatePalette(resolvedPalette);
       
  1422 }
       
  1423 
       
  1424 /*!
       
  1425     \internal
       
  1426 
       
  1427     Update the palette, and whether or not it has changed, reresolve all
       
  1428     palettes in the scene.
       
  1429 */
       
  1430 void QGraphicsScenePrivate::updatePalette(const QPalette &palette)
       
  1431 {
       
  1432     Q_Q(QGraphicsScene);
       
  1433 
       
  1434     // Update local palette setting.
       
  1435     this->palette = palette;
       
  1436 
       
  1437     // Resolve the palettes of all top-level widget items, or widget items
       
  1438     // whose parent is not a widget.
       
  1439     foreach (QGraphicsItem *item, q->items()) {
       
  1440         if (!item->parentItem()) {
       
  1441             // Resolvefont for an item is a noop operation, but
       
  1442             // every item can be a widget, or can have a widget
       
  1443             // childre.
       
  1444             item->d_ptr->resolvePalette(palette.resolve());
       
  1445         }
       
  1446     }
       
  1447 
       
  1448     // Send the scene a PaletteChange event.
       
  1449     QEvent event(QEvent::PaletteChange);
       
  1450     QApplication::sendEvent(q, &event);
       
  1451 }
       
  1452 
       
  1453 /*!
       
  1454     Constructs a QGraphicsScene object. The \a parent parameter is
       
  1455     passed to QObject's constructor.
       
  1456 */
       
  1457 QGraphicsScene::QGraphicsScene(QObject *parent)
       
  1458     : QObject(*new QGraphicsScenePrivate, parent)
       
  1459 {
       
  1460     d_func()->init();
       
  1461 }
       
  1462 
       
  1463 /*!
       
  1464     Constructs a QGraphicsScene object, using \a sceneRect for its
       
  1465     scene rectangle. The \a parent parameter is passed to QObject's
       
  1466     constructor.
       
  1467 
       
  1468     \sa sceneRect
       
  1469 */
       
  1470 QGraphicsScene::QGraphicsScene(const QRectF &sceneRect, QObject *parent)
       
  1471     : QObject(*new QGraphicsScenePrivate, parent)
       
  1472 {
       
  1473     d_func()->init();
       
  1474     setSceneRect(sceneRect);
       
  1475 }
       
  1476 
       
  1477 /*!
       
  1478     Constructs a QGraphicsScene object, using the rectangle specified
       
  1479     by (\a x, \a y), and the given \a width and \a height for its
       
  1480     scene rectangle. The \a parent parameter is passed to QObject's
       
  1481     constructor.
       
  1482 
       
  1483     \sa sceneRect
       
  1484 */
       
  1485 QGraphicsScene::QGraphicsScene(qreal x, qreal y, qreal width, qreal height, QObject *parent)
       
  1486     : QObject(*new QGraphicsScenePrivate, parent)
       
  1487 {
       
  1488     d_func()->init();
       
  1489     setSceneRect(x, y, width, height);
       
  1490 }
       
  1491 
       
  1492 /*!
       
  1493     Destroys the QGraphicsScene object.
       
  1494 */
       
  1495 QGraphicsScene::~QGraphicsScene()
       
  1496 {
       
  1497     Q_D(QGraphicsScene);
       
  1498 
       
  1499     // Remove this scene from qApp's global scene list.
       
  1500     qApp->d_func()->scene_list.removeAll(this);
       
  1501 
       
  1502     clear();
       
  1503 
       
  1504     // Remove this scene from all associated views.
       
  1505     for (int j = 0; j < d->views.size(); ++j)
       
  1506         d->views.at(j)->setScene(0);
       
  1507 }
       
  1508 
       
  1509 /*!
       
  1510     \property QGraphicsScene::sceneRect
       
  1511     \brief the scene rectangle; the bounding rectangle of the scene
       
  1512 
       
  1513     The scene rectangle defines the extent of the scene. It is
       
  1514     primarily used by QGraphicsView to determine the view's default
       
  1515     scrollable area, and by QGraphicsScene to manage item indexing.
       
  1516 
       
  1517     If unset, or if set to a null QRectF, sceneRect() will return the largest
       
  1518     bounding rect of all items on the scene since the scene was created (i.e.,
       
  1519     a rectangle that grows when items are added to or moved in the scene, but
       
  1520     never shrinks).
       
  1521 
       
  1522     \sa width(), height(), QGraphicsView::sceneRect
       
  1523 */
       
  1524 QRectF QGraphicsScene::sceneRect() const
       
  1525 {
       
  1526     Q_D(const QGraphicsScene);
       
  1527     if (d->hasSceneRect)
       
  1528         return d->sceneRect;
       
  1529 
       
  1530     if (d->dirtyGrowingItemsBoundingRect) {
       
  1531         // Lazily update the growing items bounding rect
       
  1532         QGraphicsScenePrivate *thatd = const_cast<QGraphicsScenePrivate *>(d);
       
  1533         QRectF oldGrowingBoundingRect = thatd->growingItemsBoundingRect;
       
  1534         thatd->growingItemsBoundingRect |= itemsBoundingRect();
       
  1535         thatd->dirtyGrowingItemsBoundingRect = false;
       
  1536         if (oldGrowingBoundingRect != thatd->growingItemsBoundingRect)
       
  1537             emit const_cast<QGraphicsScene *>(this)->sceneRectChanged(thatd->growingItemsBoundingRect);
       
  1538     }
       
  1539     return d->growingItemsBoundingRect;
       
  1540 }
       
  1541 void QGraphicsScene::setSceneRect(const QRectF &rect)
       
  1542 {
       
  1543     Q_D(QGraphicsScene);
       
  1544     if (rect != d->sceneRect) {
       
  1545         d->hasSceneRect = !rect.isNull();
       
  1546         d->sceneRect = rect;
       
  1547         emit sceneRectChanged(d->hasSceneRect ? rect : d->growingItemsBoundingRect);
       
  1548     }
       
  1549 }
       
  1550 
       
  1551 /*!
       
  1552      \fn qreal QGraphicsScene::width() const
       
  1553 
       
  1554      This convenience function is equivalent to calling sceneRect().width().
       
  1555 
       
  1556      \sa height()
       
  1557 */
       
  1558 
       
  1559 /*!
       
  1560      \fn qreal QGraphicsScene::height() const
       
  1561 
       
  1562      This convenience function is equivalent to calling \c sceneRect().height().
       
  1563 
       
  1564      \sa width()
       
  1565 */
       
  1566 
       
  1567 /*!
       
  1568     Renders the \a source rect from scene into \a target, using \a painter. This
       
  1569     function is useful for capturing the contents of the scene onto a paint
       
  1570     device, such as a QImage (e.g., to take a screenshot), or for printing
       
  1571     with QPrinter. For example:
       
  1572 
       
  1573     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsscene.cpp 1
       
  1574 
       
  1575     If \a source is a null rect, this function will use sceneRect() to
       
  1576     determine what to render. If \a target is a null rect, the dimensions of \a
       
  1577     painter's paint device will be used.
       
  1578 
       
  1579     The source rect contents will be transformed according to \a
       
  1580     aspectRatioMode to fit into the target rect. By default, the aspect ratio
       
  1581     is kept, and \a source is scaled to fit in \a target.
       
  1582 
       
  1583     \sa QGraphicsView::render()
       
  1584 */
       
  1585 void QGraphicsScene::render(QPainter *painter, const QRectF &target, const QRectF &source,
       
  1586                             Qt::AspectRatioMode aspectRatioMode)
       
  1587 {
       
  1588     // ### Switch to using the recursive rendering algorithm instead.
       
  1589 
       
  1590     // Default source rect = scene rect
       
  1591     QRectF sourceRect = source;
       
  1592     if (sourceRect.isNull())
       
  1593         sourceRect = sceneRect();
       
  1594 
       
  1595     // Default target rect = device rect
       
  1596     QRectF targetRect = target;
       
  1597     if (targetRect.isNull()) {
       
  1598         if (painter->device()->devType() == QInternal::Picture)
       
  1599             targetRect = sourceRect;
       
  1600         else
       
  1601             targetRect.setRect(0, 0, painter->device()->width(), painter->device()->height());
       
  1602     }
       
  1603 
       
  1604     // Find the ideal x / y scaling ratio to fit \a source into \a target.
       
  1605     qreal xratio = targetRect.width() / sourceRect.width();
       
  1606     qreal yratio = targetRect.height() / sourceRect.height();
       
  1607 
       
  1608     // Scale according to the aspect ratio mode.
       
  1609     switch (aspectRatioMode) {
       
  1610     case Qt::KeepAspectRatio:
       
  1611         xratio = yratio = qMin(xratio, yratio);
       
  1612         break;
       
  1613     case Qt::KeepAspectRatioByExpanding:
       
  1614         xratio = yratio = qMax(xratio, yratio);
       
  1615         break;
       
  1616     case Qt::IgnoreAspectRatio:
       
  1617         break;
       
  1618     }
       
  1619 
       
  1620     // Find all items to draw, and reverse the list (we want to draw
       
  1621     // in reverse order).
       
  1622     QList<QGraphicsItem *> itemList = items(sourceRect, Qt::IntersectsItemBoundingRect);
       
  1623     QGraphicsItem **itemArray = new QGraphicsItem *[itemList.size()];
       
  1624     int numItems = itemList.size();
       
  1625     for (int i = 0; i < numItems; ++i)
       
  1626         itemArray[numItems - i - 1] = itemList.at(i);
       
  1627     itemList.clear();
       
  1628 
       
  1629     painter->save();
       
  1630 
       
  1631     // Transform the painter.
       
  1632     painter->setClipRect(targetRect);
       
  1633     QTransform painterTransform;
       
  1634     painterTransform *= QTransform()
       
  1635                         .translate(targetRect.left(), targetRect.top())
       
  1636                         .scale(xratio, yratio)
       
  1637                         .translate(-sourceRect.left(), -sourceRect.top());
       
  1638     painter->setWorldTransform(painterTransform, true);
       
  1639 
       
  1640     // Two unit vectors.
       
  1641     QLineF v1(0, 0, 1, 0);
       
  1642     QLineF v2(0, 0, 0, 1);
       
  1643 
       
  1644     // Generate the style options
       
  1645     QStyleOptionGraphicsItem *styleOptionArray = new QStyleOptionGraphicsItem[numItems];
       
  1646     for (int i = 0; i < numItems; ++i)
       
  1647         itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], painterTransform, targetRect.toRect());
       
  1648 
       
  1649     // Render the scene.
       
  1650     drawBackground(painter, sourceRect);
       
  1651     drawItems(painter, numItems, itemArray, styleOptionArray);
       
  1652     drawForeground(painter, sourceRect);
       
  1653 
       
  1654     delete [] itemArray;
       
  1655     delete [] styleOptionArray;
       
  1656 
       
  1657     painter->restore();
       
  1658 }
       
  1659 
       
  1660 /*!
       
  1661     \property QGraphicsScene::itemIndexMethod
       
  1662     \brief the item indexing method.
       
  1663 
       
  1664     QGraphicsScene applies an indexing algorithm to the scene, to speed up
       
  1665     item discovery functions like items() and itemAt(). Indexing is most
       
  1666     efficient for static scenes (i.e., where items don't move around). For
       
  1667     dynamic scenes, or scenes with many animated items, the index bookkeeping
       
  1668     can outweight the fast lookup speeds.
       
  1669 
       
  1670     For the common case, the default index method BspTreeIndex works fine.  If
       
  1671     your scene uses many animations and you are experiencing slowness, you can
       
  1672     disable indexing by calling \c setItemIndexMethod(NoIndex).
       
  1673 
       
  1674     \sa bspTreeDepth
       
  1675 */
       
  1676 QGraphicsScene::ItemIndexMethod QGraphicsScene::itemIndexMethod() const
       
  1677 {
       
  1678     Q_D(const QGraphicsScene);
       
  1679     return d->indexMethod;
       
  1680 }
       
  1681 void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method)
       
  1682 {
       
  1683     Q_D(QGraphicsScene);
       
  1684     if (d->indexMethod == method)
       
  1685         return;
       
  1686 
       
  1687     d->indexMethod = method;
       
  1688 
       
  1689     QList<QGraphicsItem *> oldItems = d->index->items(Qt::DescendingOrder);
       
  1690     delete d->index;
       
  1691     if (method == BspTreeIndex)
       
  1692         d->index = new QGraphicsSceneBspTreeIndex(this);
       
  1693     else
       
  1694         d->index = new QGraphicsSceneLinearIndex(this);
       
  1695     for (int i = oldItems.size() - 1; i >= 0; --i)
       
  1696         d->index->addItem(oldItems.at(i));
       
  1697 }
       
  1698 
       
  1699 /*!
       
  1700     \property QGraphicsScene::bspTreeDepth
       
  1701     \brief the depth of QGraphicsScene's BSP index tree
       
  1702     \since 4.3
       
  1703 
       
  1704     This property has no effect when NoIndex is used.
       
  1705 
       
  1706     This value determines the depth of QGraphicsScene's BSP tree. The depth
       
  1707     directly affects QGraphicsScene's performance and memory usage; the latter
       
  1708     growing exponentially with the depth of the tree. With an optimal tree
       
  1709     depth, QGraphicsScene can instantly determine the locality of items, even
       
  1710     for scenes with thousands or millions of items. This also greatly improves
       
  1711     rendering performance.
       
  1712 
       
  1713     By default, the value is 0, in which case Qt will guess a reasonable
       
  1714     default depth based on the size, location and number of items in the
       
  1715     scene. If these parameters change frequently, however, you may experience
       
  1716     slowdowns as QGraphicsScene retunes the depth internally. You can avoid
       
  1717     potential slowdowns by fixating the tree depth through setting this
       
  1718     property.
       
  1719 
       
  1720     The depth of the tree and the size of the scene rectangle decide the
       
  1721     granularity of the scene's partitioning. The size of each scene segment is
       
  1722     determined by the following algorithm:
       
  1723 
       
  1724     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsscene.cpp 2
       
  1725 
       
  1726     The BSP tree has an optimal size when each segment contains between 0 and
       
  1727     10 items.
       
  1728 
       
  1729     \sa itemIndexMethod
       
  1730 */
       
  1731 int QGraphicsScene::bspTreeDepth() const
       
  1732 {
       
  1733     Q_D(const QGraphicsScene);
       
  1734     QGraphicsSceneBspTreeIndex *bspTree = qobject_cast<QGraphicsSceneBspTreeIndex *>(d->index);
       
  1735     return bspTree ? bspTree->bspTreeDepth() : 0;
       
  1736 }
       
  1737 void QGraphicsScene::setBspTreeDepth(int depth)
       
  1738 {
       
  1739     Q_D(QGraphicsScene);
       
  1740     if (depth < 0) {
       
  1741         qWarning("QGraphicsScene::setBspTreeDepth: invalid depth %d ignored; must be >= 0", depth);
       
  1742         return;
       
  1743     }
       
  1744 
       
  1745     QGraphicsSceneBspTreeIndex *bspTree = qobject_cast<QGraphicsSceneBspTreeIndex *>(d->index);
       
  1746     if (!bspTree) {
       
  1747         qWarning("QGraphicsScene::setBspTreeDepth: can not apply if indexing method is not BSP");
       
  1748         return;
       
  1749     }
       
  1750     bspTree->setBspTreeDepth(depth);
       
  1751 }
       
  1752 
       
  1753 /*!
       
  1754     \property QGraphicsScene::sortCacheEnabled
       
  1755     \brief whether sort caching is enabled
       
  1756     \since 4.5
       
  1757     \obsolete
       
  1758 
       
  1759     Since Qt 4.6, this property has no effect.
       
  1760 */
       
  1761 bool QGraphicsScene::isSortCacheEnabled() const
       
  1762 {
       
  1763     Q_D(const QGraphicsScene);
       
  1764     return d->sortCacheEnabled;
       
  1765 }
       
  1766 void QGraphicsScene::setSortCacheEnabled(bool enabled)
       
  1767 {
       
  1768     Q_D(QGraphicsScene);
       
  1769     if (d->sortCacheEnabled == enabled)
       
  1770         return;
       
  1771     d->sortCacheEnabled = enabled;
       
  1772 }
       
  1773 
       
  1774 /*!
       
  1775     Calculates and returns the bounding rect of all items on the scene. This
       
  1776     function works by iterating over all items, and because if this, it can
       
  1777     be slow for large scenes.
       
  1778 
       
  1779     \sa sceneRect()
       
  1780 */
       
  1781 QRectF QGraphicsScene::itemsBoundingRect() const
       
  1782 {
       
  1783     // Does not take untransformable items into account.
       
  1784     QRectF boundingRect;
       
  1785     foreach (QGraphicsItem *item, items())
       
  1786         boundingRect |= item->sceneBoundingRect();
       
  1787     return boundingRect;
       
  1788 }
       
  1789 
       
  1790 /*!
       
  1791     Returns a list of all items in the scene in descending stacking order.
       
  1792 
       
  1793     \sa addItem(), removeItem(), {QGraphicsItem#Sorting}{Sorting}
       
  1794 */
       
  1795 QList<QGraphicsItem *> QGraphicsScene::items() const
       
  1796 {
       
  1797     Q_D(const QGraphicsScene);
       
  1798     return d->index->items(Qt::DescendingOrder);
       
  1799 }
       
  1800 
       
  1801 /*!
       
  1802     Returns an ordered list of all items on the scene. \a order decides the
       
  1803     stacking order.
       
  1804 
       
  1805     \sa addItem(), removeItem(), {QGraphicsItem#Sorting}{Sorting}
       
  1806 */
       
  1807 QList<QGraphicsItem *> QGraphicsScene::items(Qt::SortOrder order) const
       
  1808 {
       
  1809     Q_D(const QGraphicsScene);
       
  1810     return d->index->items(order);
       
  1811 }
       
  1812 
       
  1813 /*!
       
  1814     \obsolete
       
  1815 
       
  1816     Returns all visible items at position \a pos in the scene. The items are
       
  1817     listed in descending stacking order (i.e., the first item in the list is the
       
  1818     top-most item, and the last item is the bottom-most item).
       
  1819 
       
  1820     This function is deprecated and returns incorrect results if the scene
       
  1821     contains items that ignore transformations. Use the overload that takes
       
  1822     a QTransform instead.
       
  1823 
       
  1824     \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
       
  1825 */
       
  1826 QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const
       
  1827 {
       
  1828     Q_D(const QGraphicsScene);
       
  1829     return d->index->items(pos, Qt::IntersectsItemShape, Qt::DescendingOrder);
       
  1830 }
       
  1831 
       
  1832 /*!
       
  1833     \overload
       
  1834     \obsolete
       
  1835 
       
  1836     Returns all visible items that, depending on \a mode, are either inside or
       
  1837     intersect with the specified \a rectangle.
       
  1838 
       
  1839     The default value for \a mode is Qt::IntersectsItemShape; all items whose
       
  1840     exact shape intersects with or is contained by \a rectangle are returned.
       
  1841 
       
  1842     This function is deprecated and returns incorrect results if the scene
       
  1843     contains items that ignore transformations. Use the overload that takes
       
  1844     a QTransform instead.
       
  1845 
       
  1846     \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
       
  1847 */
       
  1848 QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSelectionMode mode) const
       
  1849 {
       
  1850     Q_D(const QGraphicsScene);
       
  1851     return d->index->items(rectangle, mode, Qt::DescendingOrder);
       
  1852 }
       
  1853 
       
  1854 /*!
       
  1855     \fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode) const
       
  1856     \obsolete
       
  1857     \since 4.3
       
  1858 
       
  1859     This convenience function is equivalent to calling items(QRectF(\a x, \a y, \a w, \a h), \a mode).
       
  1860     
       
  1861     This function is deprecated and returns incorrect results if the scene
       
  1862     contains items that ignore transformations. Use the overload that takes
       
  1863     a QTransform instead.
       
  1864 */
       
  1865 
       
  1866 /*!
       
  1867     \fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const
       
  1868     \overload
       
  1869     \since 4.6
       
  1870 
       
  1871     \brief Returns all visible items that, depending on \a mode, are
       
  1872     either inside or intersect with the rectangle defined by \a x, \a y,
       
  1873     \a w and \a h, in a list sorted using \a order.
       
  1874 
       
  1875     \a deviceTransform is the transformation that applies to the view, and needs to
       
  1876     be provided if the scene contains items that ignore transformations.
       
  1877 */
       
  1878 
       
  1879 /*!
       
  1880     \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode) const
       
  1881     \overload
       
  1882     \obsolete
       
  1883 
       
  1884     Returns all visible items that, depending on \a mode, are either inside or
       
  1885     intersect with the polygon \a polygon.
       
  1886 
       
  1887     The default value for \a mode is Qt::IntersectsItemShape; all items whose
       
  1888     exact shape intersects with or is contained by \a polygon are returned.
       
  1889 
       
  1890     This function is deprecated and returns incorrect results if the scene
       
  1891     contains items that ignore transformations. Use the overload that takes
       
  1892     a QTransform instead.
       
  1893 
       
  1894     \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
       
  1895 */
       
  1896 QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode) const
       
  1897 {
       
  1898     Q_D(const QGraphicsScene);
       
  1899     return d->index->items(polygon, mode, Qt::DescendingOrder);
       
  1900 }
       
  1901 
       
  1902 /*!
       
  1903     \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const
       
  1904     \overload
       
  1905     \obsolete
       
  1906 
       
  1907     Returns all visible items that, depending on \a path, are either inside or
       
  1908     intersect with the path \a path.
       
  1909 
       
  1910     The default value for \a mode is Qt::IntersectsItemShape; all items whose
       
  1911     exact shape intersects with or is contained by \a path are returned.
       
  1912 
       
  1913     This function is deprecated and returns incorrect results if the scene
       
  1914     contains items that ignore transformations. Use the overload that takes
       
  1915     a QTransform instead.
       
  1916 
       
  1917     \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
       
  1918 */
       
  1919 QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const
       
  1920 {
       
  1921     Q_D(const QGraphicsScene);
       
  1922     return d->index->items(path, mode, Qt::DescendingOrder);
       
  1923 }
       
  1924 
       
  1925 /*!
       
  1926     \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const
       
  1927     \since 4.6
       
  1928 
       
  1929     \brief Returns all visible items that, depending on \a mode, are at
       
  1930     the specified \a pos in a list sorted using \a order.
       
  1931 
       
  1932     The default value for \a mode is Qt::IntersectsItemShape; all items whose
       
  1933     exact shape intersects with \a pos are returned.
       
  1934 
       
  1935     \a deviceTransform is the transformation that applies to the view, and needs to
       
  1936     be provided if the scene contains items that ignore transformations.
       
  1937 
       
  1938     \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
       
  1939 */
       
  1940 QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos, Qt::ItemSelectionMode mode,
       
  1941                                              Qt::SortOrder order, const QTransform &deviceTransform) const
       
  1942 {
       
  1943     Q_D(const QGraphicsScene);
       
  1944     return d->index->items(pos, mode, order, deviceTransform);
       
  1945 }
       
  1946 
       
  1947 /*!
       
  1948     \fn QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const
       
  1949     \overload
       
  1950     \since 4.6
       
  1951 
       
  1952     \brief Returns all visible items that, depending on \a mode, are
       
  1953     either inside or intersect with the specified \a rect and return a
       
  1954     list sorted using \a order.
       
  1955 
       
  1956     The default value for \a mode is Qt::IntersectsItemShape; all items whose
       
  1957     exact shape intersects with or is contained by \a rect are returned.
       
  1958 
       
  1959     \a deviceTransform is the transformation that applies to the view, and needs to
       
  1960     be provided if the scene contains items that ignore transformations.
       
  1961 
       
  1962     \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
       
  1963 */
       
  1964 QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode,
       
  1965                                              Qt::SortOrder order, const QTransform &deviceTransform) const
       
  1966 {
       
  1967     Q_D(const QGraphicsScene);
       
  1968     return d->index->items(rect, mode, order, deviceTransform);
       
  1969 }
       
  1970 
       
  1971 /*!
       
  1972     \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const
       
  1973     \overload
       
  1974     \since 4.6
       
  1975 
       
  1976     \brief Returns all visible items that, depending on \a mode, are
       
  1977     either inside or intersect with the specified \a polygon and return
       
  1978     a list sorted using \a order.
       
  1979 
       
  1980     The default value for \a mode is Qt::IntersectsItemShape; all items whose
       
  1981     exact shape intersects with or is contained by \a polygon are returned.
       
  1982 
       
  1983     \a deviceTransform is the transformation that applies to the view, and needs to
       
  1984     be provided if the scene contains items that ignore transformations.
       
  1985 
       
  1986     \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
       
  1987 */
       
  1988 QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode,
       
  1989                                              Qt::SortOrder order, const QTransform &deviceTransform) const
       
  1990 {
       
  1991     Q_D(const QGraphicsScene);
       
  1992     return d->index->items(polygon, mode, order, deviceTransform);
       
  1993 }
       
  1994 
       
  1995 /*!
       
  1996     \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const
       
  1997     \overload
       
  1998     \since 4.6
       
  1999 
       
  2000     \brief Returns all visible items that, depending on \a mode, are
       
  2001     either inside or intersect with the specified \a path and return a
       
  2002     list sorted using \a order.
       
  2003 
       
  2004     The default value for \a mode is Qt::IntersectsItemShape; all items whose
       
  2005     exact shape intersects with or is contained by \a path are returned.
       
  2006 
       
  2007     \a deviceTransform is the transformation that applies to the view, and needs to
       
  2008     be provided if the scene contains items that ignore transformations.
       
  2009 
       
  2010     \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
       
  2011 */
       
  2012 QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode,
       
  2013                                              Qt::SortOrder order, const QTransform &deviceTransform) const
       
  2014 {
       
  2015     Q_D(const QGraphicsScene);
       
  2016     return d->index->items(path, mode, order, deviceTransform);
       
  2017 }
       
  2018 
       
  2019 /*!
       
  2020     Returns a list of all items that collide with \a item. Collisions are
       
  2021     determined by calling QGraphicsItem::collidesWithItem(); the collision
       
  2022     detection is determined by \a mode. By default, all items whose shape
       
  2023     intersects \a item or is contained inside \a item's shape are returned.
       
  2024 
       
  2025     The items are returned in descending stacking order (i.e., the first item
       
  2026     in the list is the uppermost item, and the last item is the lowermost
       
  2027     item).
       
  2028 
       
  2029     \sa items(), itemAt(), QGraphicsItem::collidesWithItem(), {QGraphicsItem#Sorting}{Sorting}
       
  2030 */
       
  2031 QList<QGraphicsItem *> QGraphicsScene::collidingItems(const QGraphicsItem *item,
       
  2032                                                       Qt::ItemSelectionMode mode) const
       
  2033 {
       
  2034     Q_D(const QGraphicsScene);
       
  2035     if (!item) {
       
  2036         qWarning("QGraphicsScene::collidingItems: cannot find collisions for null item");
       
  2037         return QList<QGraphicsItem *>();
       
  2038     }
       
  2039 
       
  2040     // Does not support ItemIgnoresTransformations.
       
  2041     QList<QGraphicsItem *> tmp;
       
  2042     foreach (QGraphicsItem *itemInVicinity, d->index->estimateItems(item->sceneBoundingRect(), Qt::DescendingOrder)) {
       
  2043         if (item != itemInVicinity && item->collidesWithItem(itemInVicinity, mode))
       
  2044             tmp << itemInVicinity;
       
  2045     }
       
  2046     return tmp;
       
  2047 }
       
  2048 
       
  2049 /*!
       
  2050     \overload
       
  2051     \obsolete
       
  2052 
       
  2053     Returns the topmost visible item at the specified \a position, or 0 if
       
  2054     there are no items at this position.
       
  2055 
       
  2056     This function is deprecated and returns incorrect results if the scene
       
  2057     contains items that ignore transformations. Use the overload that takes
       
  2058     a QTransform instead.
       
  2059 
       
  2060     \sa items(), collidingItems(), {QGraphicsItem#Sorting}{Sorting}
       
  2061 */
       
  2062 QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position) const
       
  2063 {
       
  2064     QList<QGraphicsItem *> itemsAtPoint = items(position);
       
  2065     return itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first();
       
  2066 }
       
  2067 
       
  2068 /*!
       
  2069     \since 4.6
       
  2070 
       
  2071     Returns the topmost visible item at the specified \a position, or 0
       
  2072     if there are no items at this position.
       
  2073 
       
  2074     \a deviceTransform is the transformation that applies to the view, and needs to
       
  2075     be provided if the scene contains items that ignore transformations.
       
  2076 
       
  2077     \sa items(), collidingItems(), {QGraphicsItem#Sorting}{Sorting}
       
  2078 */
       
  2079 QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position, const QTransform &deviceTransform) const
       
  2080 {
       
  2081     QList<QGraphicsItem *> itemsAtPoint = items(position, Qt::IntersectsItemShape,
       
  2082                                                 Qt::DescendingOrder, deviceTransform);
       
  2083     return itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first();
       
  2084 }
       
  2085 
       
  2086 /*!
       
  2087     \fn QGraphicsScene::itemAt(qreal x, qreal y, const QTransform &deviceTransform) const
       
  2088     \overload
       
  2089     \since 4.6
       
  2090 
       
  2091     Returns the topmost item at the position specified by (\a x, \a
       
  2092     y), or 0 if there are no items at this position.
       
  2093 
       
  2094     \a deviceTransform is the transformation that applies to the view, and needs to
       
  2095     be provided if the scene contains items that ignore transformations.
       
  2096 
       
  2097     This convenience function is equivalent to calling \c
       
  2098     {itemAt(QPointF(x, y), deviceTransform)}.
       
  2099 */
       
  2100 
       
  2101 /*!
       
  2102     \fn QGraphicsScene::itemAt(qreal x, qreal y) const
       
  2103     \overload
       
  2104     \obsolete
       
  2105 
       
  2106     Returns the topmost item at the position specified by (\a x, \a
       
  2107     y), or 0 if there are no items at this position.
       
  2108 
       
  2109     This convenience function is equivalent to calling \c
       
  2110     {itemAt(QPointF(x, y))}.
       
  2111 
       
  2112     This function is deprecated and returns incorrect results if the scene
       
  2113     contains items that ignore transformations. Use the overload that takes
       
  2114     a QTransform instead.
       
  2115 */
       
  2116 
       
  2117 /*!
       
  2118     Returns a list of all currently selected items. The items are
       
  2119     returned in no particular order.
       
  2120 
       
  2121     \sa setSelectionArea()
       
  2122 */
       
  2123 QList<QGraphicsItem *> QGraphicsScene::selectedItems() const
       
  2124 {
       
  2125     Q_D(const QGraphicsScene);
       
  2126 
       
  2127     // Optimization: Lazily removes items that are not selected.
       
  2128     QGraphicsScene *that = const_cast<QGraphicsScene *>(this);
       
  2129     QSet<QGraphicsItem *> actuallySelectedSet;
       
  2130     foreach (QGraphicsItem *item, that->d_func()->selectedItems) {
       
  2131         if (item->isSelected())
       
  2132             actuallySelectedSet << item;
       
  2133     }
       
  2134 
       
  2135     that->d_func()->selectedItems = actuallySelectedSet;
       
  2136 
       
  2137     return d->selectedItems.values();
       
  2138 }
       
  2139 
       
  2140 /*!
       
  2141     Returns the selection area that was previously set with
       
  2142     setSelectionArea(), or an empty QPainterPath if no selection area has been
       
  2143     set.
       
  2144 
       
  2145     \sa setSelectionArea()
       
  2146 */
       
  2147 QPainterPath QGraphicsScene::selectionArea() const
       
  2148 {
       
  2149     Q_D(const QGraphicsScene);
       
  2150     return d->selectionArea;
       
  2151 }
       
  2152 
       
  2153 /*!
       
  2154     \since 4.6
       
  2155 
       
  2156     Sets the selection area to \a path. All items within this area are
       
  2157     immediately selected, and all items outside are unselected. You can get
       
  2158     the list of all selected items by calling selectedItems().
       
  2159 
       
  2160     \a deviceTransform is the transformation that applies to the view, and needs to
       
  2161     be provided if the scene contains items that ignore transformations.
       
  2162 
       
  2163     For an item to be selected, it must be marked as \e selectable
       
  2164     (QGraphicsItem::ItemIsSelectable).
       
  2165 
       
  2166     \sa clearSelection(), selectionArea()
       
  2167 */
       
  2168 void QGraphicsScene::setSelectionArea(const QPainterPath &path, const QTransform &deviceTransform)
       
  2169 {
       
  2170     setSelectionArea(path, Qt::IntersectsItemShape, deviceTransform);
       
  2171 }
       
  2172 
       
  2173 /*!
       
  2174     \obsolete
       
  2175     \overload
       
  2176 
       
  2177     Sets the selection area to \a path.
       
  2178 
       
  2179     This function is deprecated and leads to incorrect results if the scene
       
  2180     contains items that ignore transformations. Use the overload that takes
       
  2181     a QTransform instead.
       
  2182 */
       
  2183 void QGraphicsScene::setSelectionArea(const QPainterPath &path)
       
  2184 {
       
  2185     setSelectionArea(path, Qt::IntersectsItemShape, QTransform());
       
  2186 }
       
  2187 
       
  2188 /*!
       
  2189     \obsolete
       
  2190     \overload
       
  2191     \since 4.3
       
  2192 
       
  2193     Sets the selection area to \a path using \a mode to determine if items are
       
  2194     included in the selection area.
       
  2195 
       
  2196     \sa clearSelection(), selectionArea()
       
  2197 */
       
  2198 void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode)
       
  2199 {
       
  2200     setSelectionArea(path, mode, QTransform());
       
  2201 }
       
  2202 
       
  2203 /*!
       
  2204     \overload
       
  2205     \since 4.6
       
  2206 
       
  2207     Sets the selection area to \a path using \a mode to determine if items are
       
  2208     included in the selection area.
       
  2209 
       
  2210     \a deviceTransform is the transformation that applies to the view, and needs to
       
  2211     be provided if the scene contains items that ignore transformations.
       
  2212 
       
  2213     \sa clearSelection(), selectionArea()
       
  2214 */
       
  2215 void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode,
       
  2216                                       const QTransform &deviceTransform)
       
  2217 {
       
  2218     Q_D(QGraphicsScene);
       
  2219 
       
  2220     // Note: with boolean path operations, we can improve performance here
       
  2221     // quite a lot by "growing" the old path instead of replacing it. That
       
  2222     // allows us to only check the intersect area for changes, instead of
       
  2223     // reevaluating the whole path over again.
       
  2224     d->selectionArea = path;
       
  2225 
       
  2226     QSet<QGraphicsItem *> unselectItems = d->selectedItems;
       
  2227 
       
  2228     // Disable emitting selectionChanged() for individual items.
       
  2229     ++d->selectionChanging;
       
  2230     bool changed = false;
       
  2231 
       
  2232     // Set all items in path to selected.
       
  2233     foreach (QGraphicsItem *item, items(path, mode, Qt::DescendingOrder, deviceTransform)) {
       
  2234         if (item->flags() & QGraphicsItem::ItemIsSelectable) {
       
  2235             if (!item->isSelected())
       
  2236                 changed = true;
       
  2237             unselectItems.remove(item);
       
  2238             item->setSelected(true);
       
  2239         }
       
  2240     }
       
  2241 
       
  2242     // Unselect all items outside path.
       
  2243     foreach (QGraphicsItem *item, unselectItems) {
       
  2244         item->setSelected(false);
       
  2245         changed = true;
       
  2246     }
       
  2247 
       
  2248     // Reenable emitting selectionChanged() for individual items.
       
  2249     --d->selectionChanging;
       
  2250 
       
  2251     if (!d->selectionChanging && changed)
       
  2252         emit selectionChanged();
       
  2253 }
       
  2254 
       
  2255 /*!
       
  2256    Clears the current selection.
       
  2257 
       
  2258    \sa setSelectionArea(), selectedItems()
       
  2259 */
       
  2260 void QGraphicsScene::clearSelection()
       
  2261 {
       
  2262     Q_D(QGraphicsScene);
       
  2263 
       
  2264     // Disable emitting selectionChanged
       
  2265     ++d->selectionChanging;
       
  2266     bool changed = !d->selectedItems.isEmpty();
       
  2267 
       
  2268     foreach (QGraphicsItem *item, d->selectedItems)
       
  2269         item->setSelected(false);
       
  2270     d->selectedItems.clear();
       
  2271 
       
  2272     // Reenable emitting selectionChanged() for individual items.
       
  2273     --d->selectionChanging;
       
  2274 
       
  2275     if (!d->selectionChanging && changed)
       
  2276         emit selectionChanged();
       
  2277 }
       
  2278 
       
  2279 /*!
       
  2280     \since 4.4
       
  2281 
       
  2282     Removes and deletes all items from the scene, but otherwise leaves the
       
  2283     state of the scene unchanged.
       
  2284 
       
  2285     \sa addItem()
       
  2286 */
       
  2287 void QGraphicsScene::clear()
       
  2288 {
       
  2289     Q_D(QGraphicsScene);
       
  2290     // NB! We have to clear the index before deleting items; otherwise the
       
  2291     // index might try to access dangling item pointers.
       
  2292     d->index->clear();
       
  2293     const QList<QGraphicsItem *> items = d->topLevelItems;
       
  2294     qDeleteAll(items);
       
  2295     Q_ASSERT(d->topLevelItems.isEmpty());
       
  2296     d->lastItemCount = 0;
       
  2297     d->allItemsIgnoreHoverEvents = true;
       
  2298     d->allItemsUseDefaultCursor = true;
       
  2299     d->allItemsIgnoreTouchEvents = true;
       
  2300 }
       
  2301 
       
  2302 /*!
       
  2303     Groups all items in \a items into a new QGraphicsItemGroup, and returns a
       
  2304     pointer to the group. The group is created with the common ancestor of \a
       
  2305     items as its parent, and with position (0, 0). The items are all
       
  2306     reparented to the group, and their positions and transformations are
       
  2307     mapped to the group. If \a items is empty, this function will return an
       
  2308     empty top-level QGraphicsItemGroup.
       
  2309 
       
  2310     QGraphicsScene has ownership of the group item; you do not need to delete
       
  2311     it. To dismantle (ungroup) a group, call destroyItemGroup().
       
  2312 
       
  2313     \sa destroyItemGroup(), QGraphicsItemGroup::addToGroup()
       
  2314 */
       
  2315 QGraphicsItemGroup *QGraphicsScene::createItemGroup(const QList<QGraphicsItem *> &items)
       
  2316 {
       
  2317     // Build a list of the first item's ancestors
       
  2318     QList<QGraphicsItem *> ancestors;
       
  2319     int n = 0;
       
  2320     if (!items.isEmpty()) {
       
  2321         QGraphicsItem *parent = items.at(n++);
       
  2322         while ((parent = parent->parentItem()))
       
  2323             ancestors.append(parent);
       
  2324     }
       
  2325 
       
  2326     // Find the common ancestor for all items
       
  2327     QGraphicsItem *commonAncestor = 0;
       
  2328     if (!ancestors.isEmpty()) {
       
  2329         while (n < items.size()) {
       
  2330             int commonIndex = -1;
       
  2331             QGraphicsItem *parent = items.at(n++);
       
  2332             do {
       
  2333                 int index = ancestors.indexOf(parent, qMax(0, commonIndex));
       
  2334                 if (index != -1) {
       
  2335                     commonIndex = index;
       
  2336                     break;
       
  2337                 }
       
  2338             } while ((parent = parent->parentItem()));
       
  2339 
       
  2340             if (commonIndex == -1) {
       
  2341                 commonAncestor = 0;
       
  2342                 break;
       
  2343             }
       
  2344 
       
  2345             commonAncestor = ancestors.at(commonIndex);
       
  2346         }
       
  2347     }
       
  2348 
       
  2349     // Create a new group at that level
       
  2350     QGraphicsItemGroup *group = new QGraphicsItemGroup(commonAncestor);
       
  2351     if (!commonAncestor)
       
  2352         addItem(group);
       
  2353     foreach (QGraphicsItem *item, items)
       
  2354         group->addToGroup(item);
       
  2355     return group;
       
  2356 }
       
  2357 
       
  2358 /*!
       
  2359     Reparents all items in \a group to \a group's parent item, then removes \a
       
  2360     group from the scene, and finally deletes it. The items' positions and
       
  2361     transformations are mapped from the group to the group's parent.
       
  2362 
       
  2363     \sa createItemGroup(), QGraphicsItemGroup::removeFromGroup()
       
  2364 */
       
  2365 void QGraphicsScene::destroyItemGroup(QGraphicsItemGroup *group)
       
  2366 {
       
  2367     foreach (QGraphicsItem *item, group->children())
       
  2368         group->removeFromGroup(item);
       
  2369     removeItem(group);
       
  2370     delete group;
       
  2371 }
       
  2372 
       
  2373 /*!
       
  2374     Adds or moves the item \a item and all its childen to the scene.
       
  2375 
       
  2376     If the item is visible (i.e., QGraphicsItem::isVisible() returns
       
  2377     true), QGraphicsScene will emit changed() once control goes back
       
  2378     to the event loop.
       
  2379 
       
  2380     If the item is already in a different scene, it will first be removed from
       
  2381     its old scene, and then added to this scene as a top-level.
       
  2382 
       
  2383     QGraphicsScene will send ItemSceneChange notifications to \a item while
       
  2384     it is added to the scene. If item does not currently belong to a scene, only one
       
  2385     notification is sent. If it does belong to scene already (i.e., it is
       
  2386     moved to this scene), QGraphicsScene will send an addition notification as
       
  2387     the item is removed from its previous scene.
       
  2388 
       
  2389     If the item is a panel, the scene is active, and there is no active panel
       
  2390     in the scene, then the item will be activated.
       
  2391 
       
  2392     \sa removeItem(), addEllipse(), addLine(), addPath(), addPixmap(),
       
  2393     addRect(), addText(), addWidget(), {QGraphicsItem#Sorting}{Sorting}
       
  2394 */
       
  2395 void QGraphicsScene::addItem(QGraphicsItem *item)
       
  2396 {
       
  2397     Q_D(QGraphicsScene);
       
  2398     if (!item) {
       
  2399         qWarning("QGraphicsScene::addItem: cannot add null item");
       
  2400         return;
       
  2401     }
       
  2402     if (item->scene() == this) {
       
  2403         qWarning("QGraphicsScene::addItem: item has already been added to this scene");
       
  2404         return;
       
  2405     }
       
  2406     // Remove this item from its existing scene
       
  2407     if (QGraphicsScene *oldScene = item->scene())
       
  2408         oldScene->removeItem(item);
       
  2409 
       
  2410     // Notify the item that its scene is changing, and allow the item to
       
  2411     // react.
       
  2412     const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange,
       
  2413                                                     qVariantFromValue<QGraphicsScene *>(this)));
       
  2414     QGraphicsScene *targetScene = qVariantValue<QGraphicsScene *>(newSceneVariant);
       
  2415     if (targetScene != this) {
       
  2416         if (targetScene && item->scene() != targetScene)
       
  2417             targetScene->addItem(item);
       
  2418         return;
       
  2419     }
       
  2420 
       
  2421     // Detach this item from its parent if the parent's scene is different
       
  2422     // from this scene.
       
  2423     if (QGraphicsItem *itemParent = item->parentItem()) {
       
  2424         if (itemParent->scene() != this)
       
  2425             item->setParentItem(0);
       
  2426     }
       
  2427 
       
  2428     // Add the item to this scene
       
  2429     item->d_func()->scene = targetScene;
       
  2430 
       
  2431     // Add the item in the index
       
  2432     d->index->addItem(item);
       
  2433 
       
  2434     // Add to list of toplevels if this item is a toplevel.
       
  2435     if (!item->d_ptr->parent)
       
  2436         d->registerTopLevelItem(item);
       
  2437 
       
  2438     // Add to list of items that require an update. We cannot assume that the
       
  2439     // item is fully constructed, so calling item->update() can lead to a pure
       
  2440     // virtual function call to boundingRect().
       
  2441     d->markDirty(item);
       
  2442     d->dirtyGrowingItemsBoundingRect = true;
       
  2443 
       
  2444     // Disable selectionChanged() for individual items
       
  2445     ++d->selectionChanging;
       
  2446     int oldSelectedItemSize = d->selectedItems.size();
       
  2447 
       
  2448     // Enable mouse tracking if the item accepts hover events or has a cursor set.
       
  2449     if (d->allItemsIgnoreHoverEvents && d->itemAcceptsHoverEvents_helper(item)) {
       
  2450         d->allItemsIgnoreHoverEvents = false;
       
  2451         d->enableMouseTrackingOnViews();
       
  2452     }
       
  2453 #ifndef QT_NO_CURSOR
       
  2454     if (d->allItemsUseDefaultCursor && item->hasCursor()) {
       
  2455         d->allItemsUseDefaultCursor = false;
       
  2456         if (d->allItemsIgnoreHoverEvents) // already enabled otherwise
       
  2457             d->enableMouseTrackingOnViews();
       
  2458     }
       
  2459 #endif //QT_NO_CURSOR
       
  2460 
       
  2461     // Enable touch events if the item accepts touch events.
       
  2462     if (d->allItemsIgnoreTouchEvents && item->acceptTouchEvents()) {
       
  2463         d->allItemsIgnoreTouchEvents = false;
       
  2464         d->enableTouchEventsOnViews();
       
  2465     }
       
  2466 
       
  2467     // Update selection lists
       
  2468     if (item->isSelected())
       
  2469         d->selectedItems << item;
       
  2470     if (item->isWidget() && item->isVisible() && static_cast<QGraphicsWidget *>(item)->windowType() == Qt::Popup)
       
  2471         d->addPopup(static_cast<QGraphicsWidget *>(item));
       
  2472     if (item->isPanel() && item->isVisible() && item->panelModality() != QGraphicsItem::NonModal)
       
  2473         d->enterModal(item);
       
  2474 
       
  2475     // Update creation order focus chain. Make sure to leave the widget's
       
  2476     // internal tab order intact.
       
  2477     if (item->isWidget()) {
       
  2478         QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
       
  2479         if (!d->tabFocusFirst) {
       
  2480             // No first tab focus widget - make this the first tab focus
       
  2481             // widget.
       
  2482             d->tabFocusFirst = widget;
       
  2483         } else if (!widget->parentWidget()) {
       
  2484             // Adding a widget that is not part of a tab focus chain.
       
  2485             QGraphicsWidget *last = d->tabFocusFirst->d_func()->focusPrev;
       
  2486             QGraphicsWidget *lastNew = widget->d_func()->focusPrev;
       
  2487             last->d_func()->focusNext = widget;
       
  2488             widget->d_func()->focusPrev = last;
       
  2489             d->tabFocusFirst->d_func()->focusPrev = lastNew;
       
  2490             lastNew->d_func()->focusNext = d->tabFocusFirst;
       
  2491         }
       
  2492     }
       
  2493 
       
  2494     // Add all children recursively
       
  2495     foreach (QGraphicsItem *child, item->children())
       
  2496         addItem(child);
       
  2497 
       
  2498     // Resolve font and palette.
       
  2499     item->d_ptr->resolveFont(d->font.resolve());
       
  2500     item->d_ptr->resolvePalette(d->palette.resolve());
       
  2501 
       
  2502     if (!item->d_ptr->explicitlyHidden) {
       
  2503        if (d->unpolishedItems.isEmpty())
       
  2504            QMetaObject::invokeMethod(this, "_q_polishItems", Qt::QueuedConnection);
       
  2505        d->unpolishedItems.insert(item);
       
  2506     }
       
  2507 
       
  2508     // Reenable selectionChanged() for individual items
       
  2509     --d->selectionChanging;
       
  2510     if (!d->selectionChanging && d->selectedItems.size() != oldSelectedItemSize)
       
  2511         emit selectionChanged();
       
  2512 
       
  2513     // Deliver post-change notification
       
  2514     item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant);
       
  2515 
       
  2516     // Update explicit activation
       
  2517     bool autoActivate = true;
       
  2518     if (!d->childExplicitActivation && item->d_ptr->explicitActivate)
       
  2519         d->childExplicitActivation = item->d_ptr->wantsActive ? 1 : 2;
       
  2520     if (d->childExplicitActivation && item->isPanel()) {
       
  2521         if (d->childExplicitActivation == 1)
       
  2522             setActivePanel(item);
       
  2523         else
       
  2524             autoActivate = false;
       
  2525         d->childExplicitActivation = 0;
       
  2526     } else if (!item->d_ptr->parent) {
       
  2527         d->childExplicitActivation = 0;
       
  2528     }
       
  2529 
       
  2530     // Auto-activate this item's panel if nothing else has been activated
       
  2531     if (autoActivate) {
       
  2532         if (!d->lastActivePanel && !d->activePanel && item->isPanel()) {
       
  2533             if (isActive())
       
  2534                 setActivePanel(item);
       
  2535             else
       
  2536                 d->lastActivePanel = item;
       
  2537         }
       
  2538     }
       
  2539 
       
  2540     // Ensure that newly added items that have subfocus set, gain
       
  2541     // focus automatically if there isn't a focus item already.
       
  2542     if (!d->focusItem && item != d->lastFocusItem && item->focusItem() == item)
       
  2543         item->focusItem()->setFocus();
       
  2544 
       
  2545     d->updateInputMethodSensitivityInViews();
       
  2546 }
       
  2547 
       
  2548 /*!
       
  2549     Creates and adds an ellipse item to the scene, and returns the item
       
  2550     pointer. The geometry of the ellipse is defined by \a rect, and its pen
       
  2551     and brush are initialized to \a pen and \a brush.
       
  2552 
       
  2553     Note that the item's geometry is provided in item coordinates, and its
       
  2554     position is initialized to (0, 0).
       
  2555 
       
  2556     If the item is visible (i.e., QGraphicsItem::isVisible() returns true),
       
  2557     QGraphicsScene will emit changed() once control goes back to the event
       
  2558     loop.
       
  2559 
       
  2560     \sa addLine(), addPath(), addPixmap(), addRect(), addText(), addItem(),
       
  2561     addWidget()
       
  2562 */
       
  2563 QGraphicsEllipseItem *QGraphicsScene::addEllipse(const QRectF &rect, const QPen &pen, const QBrush &brush)
       
  2564 {
       
  2565     QGraphicsEllipseItem *item = new QGraphicsEllipseItem(rect);
       
  2566     item->setPen(pen);
       
  2567     item->setBrush(brush);
       
  2568     addItem(item);
       
  2569     return item;
       
  2570 }
       
  2571 
       
  2572 /*!
       
  2573     \fn QGraphicsEllipseItem *QGraphicsScene::addEllipse(qreal x, qreal y, qreal w, qreal h, const QPen &pen, const QBrush &brush)
       
  2574     \since 4.3
       
  2575 
       
  2576     This convenience function is equivalent to calling addEllipse(QRectF(\a x,
       
  2577     \a y, \a w, \a h), \a pen, \a brush).
       
  2578 */
       
  2579 
       
  2580 /*!
       
  2581     Creates and adds a line item to the scene, and returns the item
       
  2582     pointer. The geometry of the line is defined by \a line, and its pen
       
  2583     is initialized to \a pen.
       
  2584 
       
  2585     Note that the item's geometry is provided in item coordinates, and its
       
  2586     position is initialized to (0, 0).
       
  2587 
       
  2588     If the item is visible (i.e., QGraphicsItem::isVisible() returns true),
       
  2589     QGraphicsScene will emit changed() once control goes back to the event
       
  2590     loop.
       
  2591 
       
  2592     \sa addEllipse(), addPath(), addPixmap(), addRect(), addText(), addItem(),
       
  2593     addWidget()
       
  2594 */
       
  2595 QGraphicsLineItem *QGraphicsScene::addLine(const QLineF &line, const QPen &pen)
       
  2596 {
       
  2597     QGraphicsLineItem *item = new QGraphicsLineItem(line);
       
  2598     item->setPen(pen);
       
  2599     addItem(item);
       
  2600     return item;
       
  2601 }
       
  2602 
       
  2603 /*!
       
  2604     \fn QGraphicsLineItem *QGraphicsScene::addLine(qreal x1, qreal y1, qreal x2, qreal y2, const QPen &pen)
       
  2605     \since 4.3
       
  2606 
       
  2607     This convenience function is equivalent to calling addLine(QLineF(\a x1,
       
  2608     \a y1, \a x2, \a y2), \a pen).
       
  2609 */
       
  2610 
       
  2611 /*!
       
  2612     Creates and adds a path item to the scene, and returns the item
       
  2613     pointer. The geometry of the path is defined by \a path, and its pen and
       
  2614     brush are initialized to \a pen and \a brush.
       
  2615 
       
  2616     Note that the item's geometry is provided in item coordinates, and its
       
  2617     position is initialized to (0, 0).
       
  2618 
       
  2619     If the item is visible (i.e., QGraphicsItem::isVisible() returns true),
       
  2620     QGraphicsScene will emit changed() once control goes back to the event
       
  2621     loop.
       
  2622 
       
  2623     \sa addEllipse(), addLine(), addPixmap(), addRect(), addText(), addItem(),
       
  2624     addWidget()
       
  2625 */
       
  2626 QGraphicsPathItem *QGraphicsScene::addPath(const QPainterPath &path, const QPen &pen, const QBrush &brush)
       
  2627 {
       
  2628     QGraphicsPathItem *item = new QGraphicsPathItem(path);
       
  2629     item->setPen(pen);
       
  2630     item->setBrush(brush);
       
  2631     addItem(item);
       
  2632     return item;
       
  2633 }
       
  2634 
       
  2635 /*!
       
  2636     Creates and adds a pixmap item to the scene, and returns the item
       
  2637     pointer. The pixmap is defined by \a pixmap.
       
  2638 
       
  2639     Note that the item's geometry is provided in item coordinates, and its
       
  2640     position is initialized to (0, 0).
       
  2641 
       
  2642     If the item is visible (i.e., QGraphicsItem::isVisible() returns true),
       
  2643     QGraphicsScene will emit changed() once control goes back to the event
       
  2644     loop.
       
  2645 
       
  2646     \sa addEllipse(), addLine(), addPath(), addRect(), addText(), addItem(),
       
  2647     addWidget()
       
  2648 */
       
  2649 QGraphicsPixmapItem *QGraphicsScene::addPixmap(const QPixmap &pixmap)
       
  2650 {
       
  2651     QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap);
       
  2652     addItem(item);
       
  2653     return item;
       
  2654 }
       
  2655 
       
  2656 /*!
       
  2657     Creates and adds a polygon item to the scene, and returns the item
       
  2658     pointer. The polygon is defined by \a polygon, and its pen and
       
  2659     brush are initialized to \a pen and \a brush.
       
  2660 
       
  2661     Note that the item's geometry is provided in item coordinates, and its
       
  2662     position is initialized to (0, 0).
       
  2663 
       
  2664     If the item is visible (i.e., QGraphicsItem::isVisible() returns true),
       
  2665     QGraphicsScene will emit changed() once control goes back to the event
       
  2666     loop.
       
  2667 
       
  2668     \sa addEllipse(), addLine(), addPath(), addRect(), addText(), addItem(),
       
  2669     addWidget()
       
  2670 */
       
  2671 QGraphicsPolygonItem *QGraphicsScene::addPolygon(const QPolygonF &polygon,
       
  2672                                                  const QPen &pen, const QBrush &brush)
       
  2673 {
       
  2674     QGraphicsPolygonItem *item = new QGraphicsPolygonItem(polygon);
       
  2675     item->setPen(pen);
       
  2676     item->setBrush(brush);
       
  2677     addItem(item);
       
  2678     return item;
       
  2679 }
       
  2680 
       
  2681 /*!
       
  2682     Creates and adds a rectangle item to the scene, and returns the item
       
  2683     pointer. The geometry of the rectangle is defined by \a rect, and its pen
       
  2684     and brush are initialized to \a pen and \a brush.
       
  2685 
       
  2686     Note that the item's geometry is provided in item coordinates, and its
       
  2687     position is initialized to (0, 0). For example, if a QRect(50, 50, 100,
       
  2688     100) is added, its top-left corner will be at (50, 50) relative to the
       
  2689     origin in the items coordinate system.
       
  2690 
       
  2691     If the item is visible (i.e., QGraphicsItem::isVisible() returns true),
       
  2692     QGraphicsScene will emit changed() once control goes back to the event
       
  2693     loop.
       
  2694 
       
  2695     \sa addEllipse(), addLine(), addPixmap(), addPixmap(), addText(),
       
  2696     addItem(), addWidget()
       
  2697 */
       
  2698 QGraphicsRectItem *QGraphicsScene::addRect(const QRectF &rect, const QPen &pen, const QBrush &brush)
       
  2699 {
       
  2700     QGraphicsRectItem *item = new QGraphicsRectItem(rect);
       
  2701     item->setPen(pen);
       
  2702     item->setBrush(brush);
       
  2703     addItem(item);
       
  2704     return item;
       
  2705 }
       
  2706 
       
  2707 /*!
       
  2708     \fn QGraphicsRectItem *QGraphicsScene::addRect(qreal x, qreal y, qreal w, qreal h, const QPen &pen, const QBrush &brush)
       
  2709     \since 4.3
       
  2710 
       
  2711     This convenience function is equivalent to calling addRect(QRectF(\a x,
       
  2712     \a y, \a w, \a h), \a pen, \a brush).
       
  2713 */
       
  2714 
       
  2715 /*!
       
  2716     Creates and adds a text item to the scene, and returns the item
       
  2717     pointer. The text string is initialized to \a text, and its font
       
  2718     is initialized to \a font.
       
  2719 
       
  2720     The item's position is initialized to (0, 0).
       
  2721 
       
  2722     If the item is visible (i.e., QGraphicsItem::isVisible() returns true),
       
  2723     QGraphicsScene will emit changed() once control goes back to the event
       
  2724     loop.
       
  2725 
       
  2726     \sa addEllipse(), addLine(), addPixmap(), addPixmap(), addRect(),
       
  2727     addItem(), addWidget()
       
  2728 */
       
  2729 QGraphicsTextItem *QGraphicsScene::addText(const QString &text, const QFont &font)
       
  2730 {
       
  2731     QGraphicsTextItem *item = new QGraphicsTextItem(text);
       
  2732     item->setFont(font);
       
  2733     addItem(item);
       
  2734     return item;
       
  2735 }
       
  2736 
       
  2737 /*!
       
  2738     Creates and adds a QGraphicsSimpleTextItem to the scene, and returns the
       
  2739     item pointer. The text string is initialized to \a text, and its font is
       
  2740     initialized to \a font.
       
  2741 
       
  2742     The item's position is initialized to (0, 0).
       
  2743 
       
  2744     If the item is visible (i.e., QGraphicsItem::isVisible() returns true),
       
  2745     QGraphicsScene will emit changed() once control goes back to the event
       
  2746     loop.
       
  2747 
       
  2748     \sa addEllipse(), addLine(), addPixmap(), addPixmap(), addRect(),
       
  2749     addItem(), addWidget()
       
  2750 */
       
  2751 QGraphicsSimpleTextItem *QGraphicsScene::addSimpleText(const QString &text, const QFont &font)
       
  2752 {
       
  2753     QGraphicsSimpleTextItem *item = new QGraphicsSimpleTextItem(text);
       
  2754     item->setFont(font);
       
  2755     addItem(item);
       
  2756     return item;
       
  2757 }
       
  2758 
       
  2759 /*!
       
  2760     Creates a new QGraphicsProxyWidget for \a widget, adds it to the scene,
       
  2761     and returns a pointer to the proxy. \a wFlags set the default window flags
       
  2762     for the embedding proxy widget.
       
  2763 
       
  2764     The item's position is initialized to (0, 0).
       
  2765 
       
  2766     If the item is visible (i.e., QGraphicsItem::isVisible() returns true),
       
  2767     QGraphicsScene will emit changed() once control goes back to the event
       
  2768     loop.
       
  2769 
       
  2770     Note that widgets with the Qt::WA_PaintOnScreen widget attribute
       
  2771     set and widgets that wrap an external application or controller
       
  2772     are not supported. Examples are QGLWidget and QAxWidget.
       
  2773 
       
  2774     \sa addEllipse(), addLine(), addPixmap(), addPixmap(), addRect(),
       
  2775     addText(), addSimpleText(), addItem()
       
  2776 */
       
  2777 QGraphicsProxyWidget *QGraphicsScene::addWidget(QWidget *widget, Qt::WindowFlags wFlags)
       
  2778 {
       
  2779     QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(0, wFlags);
       
  2780     proxy->setWidget(widget);
       
  2781     addItem(proxy);
       
  2782     return proxy;
       
  2783 }
       
  2784 
       
  2785 /*!
       
  2786     Removes the item \a item and all its children from the scene.  The
       
  2787     ownership of \a item is passed on to the caller (i.e.,
       
  2788     QGraphicsScene will no longer delete \a item when destroyed).
       
  2789 
       
  2790     \sa addItem()
       
  2791 */
       
  2792 void QGraphicsScene::removeItem(QGraphicsItem *item)
       
  2793 {
       
  2794     // ### Refactoring: This function shares much functionality with _q_removeItemLater()
       
  2795     Q_D(QGraphicsScene);
       
  2796     if (!item) {
       
  2797         qWarning("QGraphicsScene::removeItem: cannot remove 0-item");
       
  2798         return;
       
  2799     }
       
  2800     if (item->scene() != this) {
       
  2801         qWarning("QGraphicsScene::removeItem: item %p's scene (%p)"
       
  2802                  " is different from this scene (%p)",
       
  2803                  item, item->scene(), this);
       
  2804         return;
       
  2805     }
       
  2806 
       
  2807     // Notify the item that it's scene is changing to 0, allowing the item to
       
  2808     // react.
       
  2809     const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange,
       
  2810                                                     qVariantFromValue<QGraphicsScene *>(0)));
       
  2811     QGraphicsScene *targetScene = qVariantValue<QGraphicsScene *>(newSceneVariant);
       
  2812     if (targetScene != 0 && targetScene != this) {
       
  2813         targetScene->addItem(item);
       
  2814         return;
       
  2815     }
       
  2816 
       
  2817     d->removeItemHelper(item);
       
  2818 
       
  2819     // Deliver post-change notification
       
  2820     item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant);
       
  2821 
       
  2822     d->updateInputMethodSensitivityInViews();
       
  2823 }
       
  2824 
       
  2825 /*!
       
  2826     Returns the scene's current focus item, or 0 if no item currently has
       
  2827     focus.
       
  2828 
       
  2829     The focus item receives keyboard input when the scene receives a
       
  2830     key event.
       
  2831 
       
  2832     \sa setFocusItem(), QGraphicsItem::hasFocus()
       
  2833 */
       
  2834 QGraphicsItem *QGraphicsScene::focusItem() const
       
  2835 {
       
  2836     Q_D(const QGraphicsScene);
       
  2837     return d->focusItem;
       
  2838 }
       
  2839 
       
  2840 /*!
       
  2841     Sets the scene's focus item to \a item, with the focus reason \a
       
  2842     focusReason, after removing focus from any previous item that may have had
       
  2843     focus.
       
  2844 
       
  2845     If \a item is 0, or if it either does not accept focus (i.e., it does not
       
  2846     have the QGraphicsItem::ItemIsFocusable flag enabled), or is not visible
       
  2847     or not enabled, this function only removes focus from any previous
       
  2848     focusitem.
       
  2849 
       
  2850     If item is not 0, and the scene does not currently have focus (i.e.,
       
  2851     hasFocus() returns false), this function will call setFocus()
       
  2852     automatically.
       
  2853 
       
  2854     \sa focusItem(), hasFocus(), setFocus()
       
  2855 */
       
  2856 void QGraphicsScene::setFocusItem(QGraphicsItem *item, Qt::FocusReason focusReason)
       
  2857 {
       
  2858     Q_D(QGraphicsScene);
       
  2859     if (item)
       
  2860         item->setFocus(focusReason);
       
  2861     else
       
  2862         d->setFocusItemHelper(item, focusReason);
       
  2863 }
       
  2864 
       
  2865 /*!
       
  2866     Returns true if the scene has focus; otherwise returns false. If the scene
       
  2867     has focus, it will will forward key events from QKeyEvent to any item that
       
  2868     has focus.
       
  2869 
       
  2870     \sa setFocus(), setFocusItem()
       
  2871 */
       
  2872 bool QGraphicsScene::hasFocus() const
       
  2873 {
       
  2874     Q_D(const QGraphicsScene);
       
  2875     return d->hasFocus;
       
  2876 }
       
  2877 
       
  2878 /*!
       
  2879     Sets focus on the scene by sending a QFocusEvent to the scene, passing \a
       
  2880     focusReason as the reason. If the scene regains focus after having
       
  2881     previously lost it while an item had focus, the last focus item will
       
  2882     receive focus with \a focusReason as the reason.
       
  2883 
       
  2884     If the scene already has focus, this function does nothing.
       
  2885 
       
  2886     \sa hasFocus(), clearFocus(), setFocusItem()
       
  2887 */
       
  2888 void QGraphicsScene::setFocus(Qt::FocusReason focusReason)
       
  2889 {
       
  2890     Q_D(QGraphicsScene);
       
  2891     if (d->hasFocus || !isActive())
       
  2892         return;
       
  2893     QFocusEvent event(QEvent::FocusIn, focusReason);
       
  2894     QCoreApplication::sendEvent(this, &event);
       
  2895 }
       
  2896 
       
  2897 /*!
       
  2898     Clears focus from the scene. If any item has focus when this function is
       
  2899     called, it will lose focus, and regain focus again once the scene regains
       
  2900     focus.
       
  2901 
       
  2902     A scene that does not have focus ignores key events.
       
  2903 
       
  2904     \sa hasFocus(), setFocus(), setFocusItem()
       
  2905 */
       
  2906 void QGraphicsScene::clearFocus()
       
  2907 {
       
  2908     Q_D(QGraphicsScene);
       
  2909     if (d->hasFocus) {
       
  2910         d->hasFocus = false;
       
  2911         setFocusItem(0, Qt::OtherFocusReason);
       
  2912     }
       
  2913 }
       
  2914 
       
  2915 /*!
       
  2916     \property QGraphicsScene::stickyFocus
       
  2917     \brief whether clicking into the scene background will clear focus
       
  2918 
       
  2919     \since 4.6
       
  2920 
       
  2921     In a QGraphicsScene with stickyFocus set to true, focus will remain
       
  2922     unchanged when the user clicks into the scene background or on an item
       
  2923     that does not accept focus. Otherwise, focus will be cleared.
       
  2924 
       
  2925     By default, this property is false.
       
  2926 
       
  2927     Focus changes in response to a mouse press. You can reimplement
       
  2928     mousePressEvent() in a subclass of QGraphicsScene to toggle this property
       
  2929     based on where the user has clicked.
       
  2930 
       
  2931     \sa clearFocus(), setFocusItem()
       
  2932 */
       
  2933 void QGraphicsScene::setStickyFocus(bool enabled)
       
  2934 {
       
  2935     Q_D(QGraphicsScene);
       
  2936     d->stickyFocus = enabled;
       
  2937 }
       
  2938 bool QGraphicsScene::stickyFocus() const
       
  2939 {
       
  2940     Q_D(const QGraphicsScene);
       
  2941     return d->stickyFocus;
       
  2942 }
       
  2943 
       
  2944 /*!
       
  2945     Returns the current mouse grabber item, or 0 if no item is currently
       
  2946     grabbing the mouse. The mouse grabber item is the item that receives all
       
  2947     mouse events sent to the scene.
       
  2948 
       
  2949     An item becomes a mouse grabber when it receives and accepts a
       
  2950     mouse press event, and it stays the mouse grabber until either of
       
  2951     the following events occur:
       
  2952 
       
  2953     \list
       
  2954     \o If the item receives a mouse release event when there are no other
       
  2955     buttons pressed, it loses the mouse grab.
       
  2956     \o If the item becomes invisible (i.e., someone calls \c {item->setVisible(false))},
       
  2957     or if it becomes disabled (i.e., someone calls \c {item->setEnabled(false))},
       
  2958     it loses the mouse grab.
       
  2959     \o If the item is removed from the scene, it loses the mouse grab.
       
  2960     \endlist
       
  2961 
       
  2962     If the item loses its mouse grab, the scene will ignore all mouse events
       
  2963     until a new item grabs the mouse (i.e., until a new item receives a mouse
       
  2964     press event).
       
  2965 */
       
  2966 QGraphicsItem *QGraphicsScene::mouseGrabberItem() const
       
  2967 {
       
  2968     Q_D(const QGraphicsScene);
       
  2969     return !d->mouseGrabberItems.isEmpty() ? d->mouseGrabberItems.last() : 0;
       
  2970 }
       
  2971 
       
  2972 /*!
       
  2973     \property QGraphicsScene::backgroundBrush
       
  2974     \brief the background brush of the scene.
       
  2975 
       
  2976     Set this property to changes the scene's background to a different color,
       
  2977     gradient or texture. The default background brush is Qt::NoBrush. The
       
  2978     background is drawn before (behind) the items.
       
  2979 
       
  2980     Example:
       
  2981 
       
  2982     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsscene.cpp 3
       
  2983 
       
  2984     QGraphicsScene::render() calls drawBackground() to draw the scene
       
  2985     background. For more detailed control over how the background is drawn,
       
  2986     you can reimplement drawBackground() in a subclass of QGraphicsScene.
       
  2987 */
       
  2988 QBrush QGraphicsScene::backgroundBrush() const
       
  2989 {
       
  2990     Q_D(const QGraphicsScene);
       
  2991     return d->backgroundBrush;
       
  2992 }
       
  2993 void QGraphicsScene::setBackgroundBrush(const QBrush &brush)
       
  2994 {
       
  2995     Q_D(QGraphicsScene);
       
  2996     d->backgroundBrush = brush;
       
  2997     foreach (QGraphicsView *view, d->views) {
       
  2998         view->resetCachedContent();
       
  2999         view->viewport()->update();
       
  3000     }
       
  3001     update();
       
  3002 }
       
  3003 
       
  3004 /*!
       
  3005     \property QGraphicsScene::foregroundBrush
       
  3006     \brief the foreground brush of the scene.
       
  3007 
       
  3008     Change this property to set the scene's foreground to a different
       
  3009     color, gradient or texture.
       
  3010 
       
  3011     The foreground is drawn after (on top of) the items. The default
       
  3012     foreground brush is Qt::NoBrush ( i.e. the foreground is not
       
  3013     drawn).
       
  3014 
       
  3015     Example:
       
  3016 
       
  3017     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsscene.cpp 4
       
  3018 
       
  3019     QGraphicsScene::render() calls drawForeground() to draw the scene
       
  3020     foreground. For more detailed control over how the foreground is
       
  3021     drawn, you can reimplement the drawForeground() function in a
       
  3022     QGraphicsScene subclass.
       
  3023 */
       
  3024 QBrush QGraphicsScene::foregroundBrush() const
       
  3025 {
       
  3026     Q_D(const QGraphicsScene);
       
  3027     return d->foregroundBrush;
       
  3028 }
       
  3029 void QGraphicsScene::setForegroundBrush(const QBrush &brush)
       
  3030 {
       
  3031     Q_D(QGraphicsScene);
       
  3032     d->foregroundBrush = brush;
       
  3033     foreach (QGraphicsView *view, views())
       
  3034         view->viewport()->update();
       
  3035     update();
       
  3036 }
       
  3037 
       
  3038 /*!
       
  3039     This method is used by input methods to query a set of properties of
       
  3040     the scene to be able to support complex input method operations as support
       
  3041     for surrounding text and reconversions.
       
  3042 
       
  3043     The \a query parameter specifies which property is queried.
       
  3044 
       
  3045     \sa QWidget::inputMethodQuery()
       
  3046 */
       
  3047 QVariant QGraphicsScene::inputMethodQuery(Qt::InputMethodQuery query) const
       
  3048 {
       
  3049     Q_D(const QGraphicsScene);
       
  3050     if (!d->focusItem || !(d->focusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod))
       
  3051         return QVariant();
       
  3052     const QTransform matrix = d->focusItem->sceneTransform();
       
  3053     QVariant value = d->focusItem->inputMethodQuery(query);
       
  3054     if (value.type() == QVariant::RectF)
       
  3055         value = matrix.mapRect(value.toRectF());
       
  3056     else if (value.type() == QVariant::PointF)
       
  3057         value = matrix.map(value.toPointF());
       
  3058     else if (value.type() == QVariant::Rect)
       
  3059         value = matrix.mapRect(value.toRect());
       
  3060     else if (value.type() == QVariant::Point)
       
  3061         value = matrix.map(value.toPoint());
       
  3062     return value;
       
  3063 }
       
  3064 
       
  3065 /*!
       
  3066     \fn void QGraphicsScene::update(const QRectF &rect)
       
  3067     Schedules a redraw of the area \a rect on the scene.
       
  3068 
       
  3069     \sa sceneRect(), changed()
       
  3070 */
       
  3071 void QGraphicsScene::update(const QRectF &rect)
       
  3072 {
       
  3073     Q_D(QGraphicsScene);
       
  3074     if (d->updateAll || (rect.isEmpty() && !rect.isNull()))
       
  3075         return;
       
  3076 
       
  3077     // Check if anyone's connected; if not, we can send updates directly to
       
  3078     // the views. Otherwise or if there are no views, use old behavior.
       
  3079     bool directUpdates = !(d->isSignalConnected(d->changedSignalIndex)) && !d->views.isEmpty();
       
  3080     if (rect.isNull()) {
       
  3081         d->updateAll = true;
       
  3082         d->updatedRects.clear();
       
  3083         if (directUpdates) {
       
  3084             // Update all views.
       
  3085             for (int i = 0; i < d->views.size(); ++i)
       
  3086                 d->views.at(i)->d_func()->fullUpdatePending = true;
       
  3087         }
       
  3088     } else {
       
  3089         if (directUpdates) {
       
  3090             // Update all views.
       
  3091             for (int i = 0; i < d->views.size(); ++i) {
       
  3092                 QGraphicsView *view = d->views.at(i);
       
  3093                 view->d_func()->updateRegion(QRegion(view->mapFromScene(rect).boundingRect()));
       
  3094             }
       
  3095         } else {
       
  3096             d->updatedRects << rect;
       
  3097         }
       
  3098     }
       
  3099 
       
  3100     if (!d->calledEmitUpdated) {
       
  3101         d->calledEmitUpdated = true;
       
  3102         QMetaObject::invokeMethod(this, "_q_emitUpdated", Qt::QueuedConnection);
       
  3103     }
       
  3104 }
       
  3105 
       
  3106 /*!
       
  3107     \fn void QGraphicsScene::update(qreal x, qreal y, qreal w, qreal h)
       
  3108     \overload
       
  3109     \since 4.3
       
  3110 
       
  3111     This function is equivalent to calling update(QRectF(\a x, \a y, \a w,
       
  3112     \a h));
       
  3113 */
       
  3114 
       
  3115 /*!
       
  3116     Invalidates and schedules a redraw of the \a layers in \a rect on the
       
  3117     scene. Any cached content in \a layers is unconditionally invalidated and
       
  3118     redrawn.
       
  3119 
       
  3120     You can use this function overload to notify QGraphicsScene of changes to
       
  3121     the background or the foreground of the scene. This function is commonly
       
  3122     used for scenes with tile-based backgrounds to notify changes when
       
  3123     QGraphicsView has enabled
       
  3124     \l{QGraphicsView::CacheBackground}{CacheBackground}.
       
  3125 
       
  3126     Example:
       
  3127 
       
  3128     \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsscene.cpp 5
       
  3129 
       
  3130     Note that QGraphicsView currently supports background caching only (see
       
  3131     QGraphicsView::CacheBackground). This function is equivalent to calling
       
  3132     update() if any layer but BackgroundLayer is passed.
       
  3133 
       
  3134     \sa QGraphicsView::resetCachedContent()
       
  3135 */
       
  3136 void QGraphicsScene::invalidate(const QRectF &rect, SceneLayers layers)
       
  3137 {
       
  3138     foreach (QGraphicsView *view, views())
       
  3139         view->invalidateScene(rect, layers);
       
  3140     update(rect);
       
  3141 }
       
  3142 
       
  3143 /*!
       
  3144     \fn void QGraphicsScene::invalidate(qreal x, qreal y, qreal w, qreal h, SceneLayers layers)
       
  3145     \overload
       
  3146     \since 4.3
       
  3147 
       
  3148     This convenience function is equivalent to calling invalidate(QRectF(\a x, \a
       
  3149     y, \a w, \a h), \a layers);
       
  3150 */
       
  3151 
       
  3152 /*!
       
  3153     Returns a list of all the views that display this scene.
       
  3154 
       
  3155     \sa QGraphicsView::scene()
       
  3156 */
       
  3157 QList <QGraphicsView *> QGraphicsScene::views() const
       
  3158 {
       
  3159     Q_D(const QGraphicsScene);
       
  3160     return d->views;
       
  3161 }
       
  3162 
       
  3163 /*!
       
  3164     This slot \e advances the scene by one step, by calling
       
  3165     QGraphicsItem::advance() for all items on the scene. This is done in two
       
  3166     phases: in the first phase, all items are notified that the scene is about
       
  3167     to change, and in the second phase all items are notified that they can
       
  3168     move. In the first phase, QGraphicsItem::advance() is called passing a
       
  3169     value of 0 as an argument, and 1 is passed in the second phase.
       
  3170 
       
  3171     \sa QGraphicsItem::advance(), QGraphicsItemAnimation, QTimeLine
       
  3172 */
       
  3173 void QGraphicsScene::advance()
       
  3174 {
       
  3175     for (int i = 0; i < 2; ++i) {
       
  3176         foreach (QGraphicsItem *item, items())
       
  3177             item->advance(i);
       
  3178     }
       
  3179 }
       
  3180 
       
  3181 /*!
       
  3182     Processes the event \a event, and dispatches it to the respective
       
  3183     event handlers.
       
  3184 
       
  3185     In addition to calling the convenience event handlers, this
       
  3186     function is responsible for converting mouse move events to hover
       
  3187     events for when there is no mouse grabber item. Hover events are
       
  3188     delivered directly to items; there is no convenience function for
       
  3189     them.
       
  3190 
       
  3191     Unlike QWidget, QGraphicsScene does not have the convenience functions
       
  3192     \l{QWidget::}{enterEvent()} and \l{QWidget::}{leaveEvent()}. Use this
       
  3193     function to obtain those events instead.
       
  3194 
       
  3195     \sa contextMenuEvent(), keyPressEvent(), keyReleaseEvent(),
       
  3196     mousePressEvent(), mouseMoveEvent(), mouseReleaseEvent(),
       
  3197     mouseDoubleClickEvent(), focusInEvent(), focusOutEvent()
       
  3198 */
       
  3199 bool QGraphicsScene::event(QEvent *event)
       
  3200 {
       
  3201     Q_D(QGraphicsScene);
       
  3202 
       
  3203     switch (event->type()) {
       
  3204     case QEvent::GraphicsSceneMousePress:
       
  3205     case QEvent::GraphicsSceneMouseMove:
       
  3206     case QEvent::GraphicsSceneMouseRelease:
       
  3207     case QEvent::GraphicsSceneMouseDoubleClick:
       
  3208     case QEvent::GraphicsSceneHoverEnter:
       
  3209     case QEvent::GraphicsSceneHoverLeave:
       
  3210     case QEvent::GraphicsSceneHoverMove:
       
  3211     case QEvent::TouchBegin:
       
  3212     case QEvent::TouchUpdate:
       
  3213     case QEvent::TouchEnd:
       
  3214         // Reset the under-mouse list to ensure that this event gets fresh
       
  3215         // item-under-mouse data. Be careful about this list; if people delete
       
  3216         // items from inside event handlers, this list can quickly end up
       
  3217         // having stale pointers in it. We need to clear it before dispatching
       
  3218         // events that use it.
       
  3219         // ### this should only be cleared if we received a new mouse move event,
       
  3220         // which relies on us fixing the replay mechanism in QGraphicsView.
       
  3221         d->cachedItemsUnderMouse.clear();
       
  3222     default:
       
  3223         break;
       
  3224     }
       
  3225 
       
  3226     switch (event->type()) {
       
  3227     case QEvent::GraphicsSceneDragEnter:
       
  3228         dragEnterEvent(static_cast<QGraphicsSceneDragDropEvent *>(event));
       
  3229         break;
       
  3230     case QEvent::GraphicsSceneDragMove:
       
  3231         dragMoveEvent(static_cast<QGraphicsSceneDragDropEvent *>(event));
       
  3232         break;
       
  3233     case QEvent::GraphicsSceneDragLeave:
       
  3234         dragLeaveEvent(static_cast<QGraphicsSceneDragDropEvent *>(event));
       
  3235         break;
       
  3236     case QEvent::GraphicsSceneDrop:
       
  3237         dropEvent(static_cast<QGraphicsSceneDragDropEvent *>(event));
       
  3238         break;
       
  3239     case QEvent::GraphicsSceneContextMenu:
       
  3240         contextMenuEvent(static_cast<QGraphicsSceneContextMenuEvent *>(event));
       
  3241         break;
       
  3242     case QEvent::KeyPress:
       
  3243         if (!d->focusItem) {
       
  3244             QKeyEvent *k = static_cast<QKeyEvent *>(event);
       
  3245             if (k->key() == Qt::Key_Tab || k->key() == Qt::Key_Backtab) {
       
  3246                 if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) {  //### Add MetaModifier?
       
  3247                     bool res = false;
       
  3248                     if (k->key() == Qt::Key_Backtab
       
  3249                         || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier))) {
       
  3250                         res = focusNextPrevChild(false);
       
  3251                     } else if (k->key() == Qt::Key_Tab) {
       
  3252                         res = focusNextPrevChild(true);
       
  3253                     }
       
  3254                     if (!res)
       
  3255                         event->ignore();
       
  3256                     return true;
       
  3257                 }
       
  3258             }
       
  3259         }
       
  3260         keyPressEvent(static_cast<QKeyEvent *>(event));
       
  3261         break;
       
  3262     case QEvent::KeyRelease:
       
  3263         keyReleaseEvent(static_cast<QKeyEvent *>(event));
       
  3264         break;
       
  3265     case QEvent::ShortcutOverride: {
       
  3266             QGraphicsItem *parent = focusItem();
       
  3267             while (parent) {
       
  3268                 d->sendEvent(parent, event);
       
  3269                 if (event->isAccepted())
       
  3270                     return true;
       
  3271                 parent = parent->parentItem();
       
  3272             }
       
  3273         }
       
  3274         return false;
       
  3275     case QEvent::GraphicsSceneMouseMove:
       
  3276     {
       
  3277         QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent *>(event);
       
  3278         d->lastSceneMousePos = mouseEvent->scenePos();
       
  3279         mouseMoveEvent(mouseEvent);
       
  3280         break;
       
  3281     }
       
  3282     case QEvent::GraphicsSceneMousePress:
       
  3283         mousePressEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
       
  3284         break;
       
  3285     case QEvent::GraphicsSceneMouseRelease:
       
  3286         mouseReleaseEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
       
  3287         break;
       
  3288     case QEvent::GraphicsSceneMouseDoubleClick:
       
  3289         mouseDoubleClickEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
       
  3290         break;
       
  3291     case QEvent::GraphicsSceneWheel:
       
  3292         wheelEvent(static_cast<QGraphicsSceneWheelEvent *>(event));
       
  3293         break;
       
  3294     case QEvent::FocusIn:
       
  3295         focusInEvent(static_cast<QFocusEvent *>(event));
       
  3296         break;
       
  3297     case QEvent::FocusOut:
       
  3298         focusOutEvent(static_cast<QFocusEvent *>(event));
       
  3299         break;
       
  3300     case QEvent::GraphicsSceneHoverEnter:
       
  3301     case QEvent::GraphicsSceneHoverLeave:
       
  3302     case QEvent::GraphicsSceneHoverMove:
       
  3303     {
       
  3304         QGraphicsSceneHoverEvent *hoverEvent = static_cast<QGraphicsSceneHoverEvent *>(event);
       
  3305         d->lastSceneMousePos = hoverEvent->scenePos();
       
  3306         d->dispatchHoverEvent(hoverEvent);
       
  3307         break;
       
  3308     }
       
  3309     case QEvent::Leave:
       
  3310         d->leaveScene();
       
  3311         break;
       
  3312     case QEvent::GraphicsSceneHelp:
       
  3313         helpEvent(static_cast<QGraphicsSceneHelpEvent *>(event));
       
  3314         break;
       
  3315     case QEvent::InputMethod:
       
  3316         inputMethodEvent(static_cast<QInputMethodEvent *>(event));
       
  3317         break;
       
  3318     case QEvent::WindowActivate:
       
  3319         if (!d->activationRefCount++) {
       
  3320             if (d->lastActivePanel) {
       
  3321                 // Activate the last panel.
       
  3322                 d->setActivePanelHelper(d->lastActivePanel, true);
       
  3323             } else if (d->tabFocusFirst && d->tabFocusFirst->isPanel()) {
       
  3324                 // Activate the panel of the first item in the tab focus
       
  3325                 // chain.
       
  3326                 d->setActivePanelHelper(d->tabFocusFirst, true);
       
  3327             } else {
       
  3328                 // Activate all toplevel items.
       
  3329                 QEvent event(QEvent::WindowActivate);
       
  3330                 foreach (QGraphicsItem *item, items()) {
       
  3331                     if (item->isVisible() && !item->isPanel() && !item->parentItem())
       
  3332                         sendEvent(item, &event);
       
  3333                 }
       
  3334             }
       
  3335         }
       
  3336         break;
       
  3337     case QEvent::WindowDeactivate:
       
  3338         if (!--d->activationRefCount) {
       
  3339             if (d->activePanel) {
       
  3340                 // Deactivate the active panel (but keep it so we can
       
  3341                 // reactivate it later).
       
  3342                 QGraphicsItem *lastActivePanel = d->activePanel;
       
  3343                 d->setActivePanelHelper(0, true);
       
  3344                 d->lastActivePanel = lastActivePanel;
       
  3345             } else {
       
  3346                 // Activate all toplevel items.
       
  3347                 QEvent event(QEvent::WindowDeactivate);
       
  3348                 foreach (QGraphicsItem *item, items()) {
       
  3349                     if (item->isVisible() && !item->isPanel() && !item->parentItem())
       
  3350                         sendEvent(item, &event);
       
  3351                 }
       
  3352             }
       
  3353         }
       
  3354         break;
       
  3355     case QEvent::ApplicationFontChange: {
       
  3356         // Resolve the existing scene font.
       
  3357         d->resolveFont();
       
  3358         break;
       
  3359     }
       
  3360     case QEvent::FontChange:
       
  3361         // Update the entire scene when the font changes.
       
  3362         update();
       
  3363         break;
       
  3364     case QEvent::ApplicationPaletteChange: {
       
  3365         // Resolve the existing scene palette.
       
  3366         d->resolvePalette();
       
  3367         break;
       
  3368     }
       
  3369     case QEvent::PaletteChange:
       
  3370         // Update the entire scene when the palette changes.
       
  3371         update();
       
  3372         break;
       
  3373     case QEvent::StyleChange:
       
  3374         // Reresolve all widgets' styles. Update all top-level widgets'
       
  3375         // geometries that do not have an explicit style set.
       
  3376         update();
       
  3377         break;
       
  3378     case QEvent::TouchBegin:
       
  3379     case QEvent::TouchUpdate:
       
  3380     case QEvent::TouchEnd:
       
  3381         d->touchEventHandler(static_cast<QTouchEvent *>(event));
       
  3382         break;
       
  3383     case QEvent::Gesture:
       
  3384     case QEvent::GestureOverride:
       
  3385         d->gestureEventHandler(static_cast<QGestureEvent *>(event));
       
  3386         break;
       
  3387     default:
       
  3388         return QObject::event(event);
       
  3389     }
       
  3390     return true;
       
  3391 }
       
  3392 
       
  3393 /*!
       
  3394     \reimp
       
  3395 
       
  3396     QGraphicsScene filters QApplication's events to detect palette and font
       
  3397     changes.
       
  3398 */
       
  3399 bool QGraphicsScene::eventFilter(QObject *watched, QEvent *event)
       
  3400 {
       
  3401     if (watched != qApp)
       
  3402         return false;
       
  3403 
       
  3404     switch (event->type()) {
       
  3405     case QEvent::ApplicationPaletteChange:
       
  3406         QApplication::postEvent(this, new QEvent(QEvent::ApplicationPaletteChange));
       
  3407         break;
       
  3408     case QEvent::ApplicationFontChange:
       
  3409         QApplication::postEvent(this, new QEvent(QEvent::ApplicationFontChange));
       
  3410         break;
       
  3411     default:
       
  3412         break;
       
  3413     }
       
  3414     return false;
       
  3415 }
       
  3416 
       
  3417 /*!
       
  3418     This event handler, for event \a contextMenuEvent, can be reimplemented in
       
  3419     a subclass to receive context menu events. The default implementation
       
  3420     forwards the event to the topmost item that accepts context menu events at
       
  3421     the position of the event. If no items accept context menu events at this
       
  3422     position, the event is ignored.
       
  3423 
       
  3424     \sa QGraphicsItem::contextMenuEvent()
       
  3425 */
       
  3426 void QGraphicsScene::contextMenuEvent(QGraphicsSceneContextMenuEvent *contextMenuEvent)
       
  3427 {
       
  3428     Q_D(QGraphicsScene);
       
  3429     // Ignore by default.
       
  3430     contextMenuEvent->ignore();
       
  3431 
       
  3432     // Send the event to all items at this position until one item accepts the
       
  3433     // event.
       
  3434     foreach (QGraphicsItem *item, d->itemsAtPosition(contextMenuEvent->screenPos(),
       
  3435                                                      contextMenuEvent->scenePos(),
       
  3436                                                      contextMenuEvent->widget())) {
       
  3437         contextMenuEvent->setPos(item->d_ptr->genericMapFromScene(contextMenuEvent->scenePos(),
       
  3438                                                                   contextMenuEvent->widget()));
       
  3439         contextMenuEvent->accept();
       
  3440         if (!d->sendEvent(item, contextMenuEvent))
       
  3441             break;
       
  3442 
       
  3443         if (contextMenuEvent->isAccepted())
       
  3444             break;
       
  3445     }
       
  3446 }
       
  3447 
       
  3448 /*!
       
  3449     This event handler, for event \a event, can be reimplemented in a subclass
       
  3450     to receive drag enter events for the scene.
       
  3451 
       
  3452     The default implementation accepts the event and prepares the scene to
       
  3453     accept drag move events.
       
  3454 
       
  3455     \sa QGraphicsItem::dragEnterEvent(), dragMoveEvent(), dragLeaveEvent(),
       
  3456     dropEvent()
       
  3457 */
       
  3458 void QGraphicsScene::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
       
  3459 {
       
  3460     Q_D(QGraphicsScene);
       
  3461     d->dragDropItem = 0;
       
  3462     d->lastDropAction = Qt::IgnoreAction;
       
  3463     event->accept();
       
  3464 }
       
  3465 
       
  3466 /*!
       
  3467     This event handler, for event \a event, can be reimplemented in a subclass
       
  3468     to receive drag move events for the scene.
       
  3469 
       
  3470     \sa QGraphicsItem::dragMoveEvent(), dragEnterEvent(), dragLeaveEvent(),
       
  3471     dropEvent()
       
  3472 */
       
  3473 void QGraphicsScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
       
  3474 {
       
  3475     Q_D(QGraphicsScene);
       
  3476     event->ignore();
       
  3477 
       
  3478     if (!d->mouseGrabberItems.isEmpty()) {
       
  3479         // Mouse grabbers that start drag events lose the mouse grab.
       
  3480         d->clearMouseGrabber();
       
  3481         d->mouseGrabberButtonDownPos.clear();
       
  3482         d->mouseGrabberButtonDownScenePos.clear();
       
  3483         d->mouseGrabberButtonDownScreenPos.clear();
       
  3484     }
       
  3485 
       
  3486     bool eventDelivered = false;
       
  3487 
       
  3488     // Find the topmost enabled items under the cursor. They are all
       
  3489     // candidates for accepting drag & drop events.
       
  3490     foreach (QGraphicsItem *item, d->itemsAtPosition(event->screenPos(),
       
  3491                                                      event->scenePos(),
       
  3492                                                      event->widget())) {
       
  3493         if (!item->isEnabled() || !item->acceptDrops())
       
  3494             continue;
       
  3495 
       
  3496         if (item != d->dragDropItem) {
       
  3497             // Enter the new drag drop item. If it accepts the event, we send
       
  3498             // the leave to the parent item.
       
  3499             QGraphicsSceneDragDropEvent dragEnter(QEvent::GraphicsSceneDragEnter);
       
  3500             d->cloneDragDropEvent(&dragEnter, event);
       
  3501             dragEnter.setDropAction(event->proposedAction());
       
  3502             d->sendDragDropEvent(item, &dragEnter);
       
  3503             event->setAccepted(dragEnter.isAccepted());
       
  3504             event->setDropAction(dragEnter.dropAction());
       
  3505             if (!event->isAccepted()) {
       
  3506                 // Propagate to the item under
       
  3507                 continue;
       
  3508             }
       
  3509 
       
  3510             d->lastDropAction = event->dropAction();
       
  3511 
       
  3512             if (d->dragDropItem) {
       
  3513                 // Leave the last drag drop item. A perfect implementation
       
  3514                 // would set the position of this event to the point where
       
  3515                 // this event and the last event intersect with the item's
       
  3516                 // shape, but that's not easy to do. :-)
       
  3517                 QGraphicsSceneDragDropEvent dragLeave(QEvent::GraphicsSceneDragLeave);
       
  3518                 d->cloneDragDropEvent(&dragLeave, event);
       
  3519                 d->sendDragDropEvent(d->dragDropItem, &dragLeave);
       
  3520             }
       
  3521 
       
  3522             // We've got a new drag & drop item
       
  3523             d->dragDropItem = item;
       
  3524         }
       
  3525 
       
  3526         // Send the move event.
       
  3527         event->setDropAction(d->lastDropAction);
       
  3528         event->accept();
       
  3529         d->sendDragDropEvent(item, event);
       
  3530         if (event->isAccepted())
       
  3531             d->lastDropAction = event->dropAction();
       
  3532         eventDelivered = true;
       
  3533         break;
       
  3534     }
       
  3535 
       
  3536     if (!eventDelivered) {
       
  3537         if (d->dragDropItem) {
       
  3538             // Leave the last drag drop item
       
  3539             QGraphicsSceneDragDropEvent dragLeave(QEvent::GraphicsSceneDragLeave);
       
  3540             d->cloneDragDropEvent(&dragLeave, event);
       
  3541             d->sendDragDropEvent(d->dragDropItem, &dragLeave);
       
  3542             d->dragDropItem = 0;
       
  3543         }
       
  3544         // Propagate
       
  3545         event->setDropAction(Qt::IgnoreAction);
       
  3546     }
       
  3547 }
       
  3548 
       
  3549 /*!
       
  3550     This event handler, for event \a event, can be reimplemented in a subclass
       
  3551     to receive drag leave events for the scene.
       
  3552 
       
  3553     \sa QGraphicsItem::dragLeaveEvent(), dragEnterEvent(), dragMoveEvent(),
       
  3554     dropEvent()
       
  3555 */
       
  3556 void QGraphicsScene::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
       
  3557 {
       
  3558     Q_D(QGraphicsScene);
       
  3559     if (d->dragDropItem) {
       
  3560         // Leave the last drag drop item
       
  3561         d->sendDragDropEvent(d->dragDropItem, event);
       
  3562         d->dragDropItem = 0;
       
  3563     }
       
  3564 }
       
  3565 
       
  3566 /*!
       
  3567     This event handler, for event \a event, can be reimplemented in a subclass
       
  3568     to receive drop events for the scene.
       
  3569 
       
  3570     \sa QGraphicsItem::dropEvent(), dragEnterEvent(), dragMoveEvent(),
       
  3571     dragLeaveEvent()
       
  3572 */
       
  3573 void QGraphicsScene::dropEvent(QGraphicsSceneDragDropEvent *event)
       
  3574 {
       
  3575     Q_UNUSED(event);
       
  3576     Q_D(QGraphicsScene);
       
  3577     if (d->dragDropItem) {
       
  3578         // Drop on the last drag drop item
       
  3579         d->sendDragDropEvent(d->dragDropItem, event);
       
  3580         d->dragDropItem = 0;
       
  3581     }
       
  3582 }
       
  3583 
       
  3584 /*!
       
  3585     This event handler, for event \a focusEvent, can be reimplemented in a
       
  3586     subclass to receive focus in events.
       
  3587 
       
  3588     The default implementation sets focus on the scene, and then on the last
       
  3589     focus item.
       
  3590 
       
  3591     \sa QGraphicsItem::focusOutEvent()
       
  3592 */
       
  3593 void QGraphicsScene::focusInEvent(QFocusEvent *focusEvent)
       
  3594 {
       
  3595     Q_D(QGraphicsScene);
       
  3596 
       
  3597     d->hasFocus = true;
       
  3598     switch (focusEvent->reason()) {
       
  3599     case Qt::TabFocusReason:
       
  3600         if (!focusNextPrevChild(true))
       
  3601             focusEvent->ignore();
       
  3602         break;
       
  3603     case Qt::BacktabFocusReason:
       
  3604         if (!focusNextPrevChild(false))
       
  3605             focusEvent->ignore();
       
  3606         break;
       
  3607     default:
       
  3608         if (d->lastFocusItem) {
       
  3609             // Set focus on the last focus item
       
  3610             setFocusItem(d->lastFocusItem, focusEvent->reason());
       
  3611         }
       
  3612         break;
       
  3613     }
       
  3614 }
       
  3615 
       
  3616 /*!
       
  3617     This event handler, for event \a focusEvent, can be reimplemented in a
       
  3618     subclass to receive focus out events.
       
  3619 
       
  3620     The default implementation removes focus from any focus item, then removes
       
  3621     focus from the scene.
       
  3622 
       
  3623     \sa QGraphicsItem::focusInEvent()
       
  3624 */
       
  3625 void QGraphicsScene::focusOutEvent(QFocusEvent *focusEvent)
       
  3626 {
       
  3627     Q_D(QGraphicsScene);
       
  3628     d->hasFocus = false;
       
  3629     setFocusItem(0, focusEvent->reason());
       
  3630 
       
  3631     // Remove all popups when the scene loses focus.
       
  3632     if (!d->popupWidgets.isEmpty())
       
  3633         d->removePopup(d->popupWidgets.first());
       
  3634 }
       
  3635 
       
  3636 /*!
       
  3637     This event handler, for event \a helpEvent, can be
       
  3638     reimplemented in a subclass to receive help events. The events
       
  3639     are of type QEvent::ToolTip, which are created when a tooltip is
       
  3640     requested.
       
  3641 
       
  3642     The default implementation shows the tooltip of the topmost
       
  3643     item, i.e., the item with the highest z-value, at the mouse
       
  3644     cursor position. If no item has a tooltip set, this function
       
  3645     does nothing.
       
  3646 
       
  3647    \sa QGraphicsItem::toolTip(), QGraphicsSceneHelpEvent
       
  3648 */
       
  3649 void QGraphicsScene::helpEvent(QGraphicsSceneHelpEvent *helpEvent)
       
  3650 {
       
  3651 #ifdef QT_NO_TOOLTIP
       
  3652     Q_UNUSED(helpEvent);
       
  3653 #else
       
  3654     // Find the first item that does tooltips
       
  3655     Q_D(QGraphicsScene);
       
  3656     QList<QGraphicsItem *> itemsAtPos = d->itemsAtPosition(helpEvent->screenPos(),
       
  3657                                                            helpEvent->scenePos(),
       
  3658                                                            helpEvent->widget());
       
  3659     QGraphicsItem *toolTipItem = 0;
       
  3660     for (int i = 0; i < itemsAtPos.size(); ++i) {
       
  3661         QGraphicsItem *tmp = itemsAtPos.at(i);
       
  3662         if (!tmp->toolTip().isEmpty()) {
       
  3663             toolTipItem = tmp;
       
  3664             break;
       
  3665         }
       
  3666     }
       
  3667 
       
  3668     // Show or hide the tooltip
       
  3669     QString text;
       
  3670     QPoint point;
       
  3671     if (toolTipItem && !toolTipItem->toolTip().isEmpty()) {
       
  3672         text = toolTipItem->toolTip();
       
  3673         point = helpEvent->screenPos();
       
  3674     }
       
  3675     QToolTip::showText(point, text, helpEvent->widget());
       
  3676     helpEvent->setAccepted(!text.isEmpty());
       
  3677 #endif
       
  3678 }
       
  3679 
       
  3680 bool QGraphicsScenePrivate::itemAcceptsHoverEvents_helper(const QGraphicsItem *item) const
       
  3681 {
       
  3682     return (!item->isBlockedByModalPanel() &&
       
  3683             (item->acceptHoverEvents()
       
  3684              || (item->isWidget()
       
  3685                  && static_cast<const QGraphicsWidget *>(item)->d_func()->hasDecoration())));
       
  3686 }
       
  3687 
       
  3688 /*!
       
  3689     This event handler, for event \a hoverEvent, can be reimplemented in a
       
  3690     subclass to receive hover enter events. The default implementation
       
  3691     forwards the event to the topmost item that accepts hover events at the
       
  3692     scene position from the event.
       
  3693 
       
  3694     \sa QGraphicsItem::hoverEvent(), QGraphicsItem::setAcceptHoverEvents()
       
  3695 */
       
  3696 bool QGraphicsScenePrivate::dispatchHoverEvent(QGraphicsSceneHoverEvent *hoverEvent)
       
  3697 {
       
  3698     if (allItemsIgnoreHoverEvents)
       
  3699         return false;
       
  3700 
       
  3701     // Find the first item that accepts hover events, reusing earlier
       
  3702     // calculated data is possible.
       
  3703     if (cachedItemsUnderMouse.isEmpty()) {
       
  3704         cachedItemsUnderMouse = itemsAtPosition(hoverEvent->screenPos(),
       
  3705                                                 hoverEvent->scenePos(),
       
  3706                                                 hoverEvent->widget());
       
  3707     }
       
  3708 
       
  3709     QGraphicsItem *item = 0;
       
  3710     for (int i = 0; i < cachedItemsUnderMouse.size(); ++i) {
       
  3711         QGraphicsItem *tmp = cachedItemsUnderMouse.at(i);
       
  3712         if (itemAcceptsHoverEvents_helper(tmp)) {
       
  3713             item = tmp;
       
  3714             break;
       
  3715         }
       
  3716     }
       
  3717 
       
  3718     // Find the common ancestor item for the new topmost hoverItem and the
       
  3719     // last item in the hoverItem list.
       
  3720     QGraphicsItem *commonAncestorItem = (item && !hoverItems.isEmpty()) ? item->commonAncestorItem(hoverItems.last()) : 0;
       
  3721     while (commonAncestorItem && !itemAcceptsHoverEvents_helper(commonAncestorItem))
       
  3722         commonAncestorItem = commonAncestorItem->parentItem();
       
  3723     if (commonAncestorItem && commonAncestorItem->panel() != item->panel()) {
       
  3724         // The common ancestor isn't in the same panel as the two hovered
       
  3725         // items.
       
  3726         commonAncestorItem = 0;
       
  3727     }
       
  3728 
       
  3729     // Check if the common ancestor item is known.
       
  3730     int index = commonAncestorItem ? hoverItems.indexOf(commonAncestorItem) : -1;
       
  3731     // Send hover leaves to any existing hovered children of the common
       
  3732     // ancestor item.
       
  3733     for (int i = hoverItems.size() - 1; i > index; --i) {
       
  3734         QGraphicsItem *lastItem = hoverItems.takeLast();
       
  3735         if (itemAcceptsHoverEvents_helper(lastItem))
       
  3736             sendHoverEvent(QEvent::GraphicsSceneHoverLeave, lastItem, hoverEvent);
       
  3737     }
       
  3738 
       
  3739     // Item is a child of a known item. Generate enter events for the
       
  3740     // missing links.
       
  3741     QList<QGraphicsItem *> parents;
       
  3742     QGraphicsItem *parent = item;
       
  3743     while (parent && parent != commonAncestorItem) {
       
  3744         parents.prepend(parent);
       
  3745         if (parent->isPanel()) {
       
  3746             // Stop at the panel - we don't deliver beyond this point.
       
  3747             break;
       
  3748         }
       
  3749         parent = parent->parentItem();
       
  3750     }
       
  3751     for (int i = 0; i < parents.size(); ++i) {
       
  3752         parent = parents.at(i);
       
  3753         hoverItems << parent;
       
  3754         if (itemAcceptsHoverEvents_helper(parent))
       
  3755             sendHoverEvent(QEvent::GraphicsSceneHoverEnter, parent, hoverEvent);
       
  3756     }
       
  3757 
       
  3758     // Generate a move event for the item itself
       
  3759     if (item
       
  3760         && !hoverItems.isEmpty()
       
  3761         && item == hoverItems.last()) {
       
  3762         sendHoverEvent(QEvent::GraphicsSceneHoverMove, item, hoverEvent);
       
  3763         return true;
       
  3764     }
       
  3765     return false;
       
  3766 }
       
  3767 
       
  3768 /*!
       
  3769     \internal
       
  3770 
       
  3771     Handles all actions necessary to clean up the scene when the mouse leaves
       
  3772     the view.
       
  3773 */
       
  3774 void QGraphicsScenePrivate::leaveScene()
       
  3775 {
       
  3776     Q_Q(QGraphicsScene);
       
  3777 #ifndef QT_NO_TOOLTIP
       
  3778     QToolTip::hideText();
       
  3779 #endif
       
  3780     // Send HoverLeave events to all existing hover items, topmost first.
       
  3781     QGraphicsView *senderWidget = qobject_cast<QGraphicsView *>(q->sender());
       
  3782     QGraphicsSceneHoverEvent hoverEvent;
       
  3783     hoverEvent.setWidget(senderWidget);
       
  3784 
       
  3785     if (senderWidget) {
       
  3786         QPoint cursorPos = QCursor::pos();
       
  3787         hoverEvent.setScenePos(senderWidget->mapToScene(senderWidget->mapFromGlobal(cursorPos)));
       
  3788         hoverEvent.setLastScenePos(hoverEvent.scenePos());
       
  3789         hoverEvent.setScreenPos(cursorPos);
       
  3790         hoverEvent.setLastScreenPos(hoverEvent.screenPos());
       
  3791     }
       
  3792 
       
  3793     while (!hoverItems.isEmpty()) {
       
  3794         QGraphicsItem *lastItem = hoverItems.takeLast();
       
  3795         if (itemAcceptsHoverEvents_helper(lastItem))
       
  3796             sendHoverEvent(QEvent::GraphicsSceneHoverLeave, lastItem, &hoverEvent);
       
  3797     }
       
  3798 }
       
  3799 
       
  3800 /*!
       
  3801     This event handler, for event \a keyEvent, can be reimplemented in a
       
  3802     subclass to receive keypress events. The default implementation forwards
       
  3803     the event to current focus item.
       
  3804 
       
  3805     \sa QGraphicsItem::keyPressEvent(), focusItem()
       
  3806 */
       
  3807 void QGraphicsScene::keyPressEvent(QKeyEvent *keyEvent)
       
  3808 {
       
  3809     // ### Merge this function with keyReleaseEvent; they are identical
       
  3810     // ### (except this comment).
       
  3811     Q_D(QGraphicsScene);
       
  3812     QGraphicsItem *item = !d->keyboardGrabberItems.isEmpty() ? d->keyboardGrabberItems.last() : 0;
       
  3813     if (!item)
       
  3814         item = focusItem();
       
  3815     if (item) {
       
  3816         QGraphicsItem *p = item;
       
  3817         do {
       
  3818             // Accept the event by default
       
  3819             keyEvent->accept();
       
  3820             // Send it; QGraphicsItem::keyPressEvent ignores it.  If the event
       
  3821             // is filtered out, stop propagating it.
       
  3822             if (p->isBlockedByModalPanel())
       
  3823                 break;
       
  3824             if (!d->sendEvent(p, keyEvent))
       
  3825                 break;
       
  3826         } while (!keyEvent->isAccepted() && !p->isPanel() && (p = p->parentItem()));
       
  3827     } else {
       
  3828         keyEvent->ignore();
       
  3829     }
       
  3830 }
       
  3831 
       
  3832 /*!
       
  3833     This event handler, for event \a keyEvent, can be reimplemented in a
       
  3834     subclass to receive key release events. The default implementation
       
  3835     forwards the event to current focus item.
       
  3836 
       
  3837     \sa QGraphicsItem::keyReleaseEvent(), focusItem()
       
  3838 */
       
  3839 void QGraphicsScene::keyReleaseEvent(QKeyEvent *keyEvent)
       
  3840 {
       
  3841     // ### Merge this function with keyPressEvent; they are identical (except
       
  3842     // ### this comment).
       
  3843     Q_D(QGraphicsScene);
       
  3844     QGraphicsItem *item = !d->keyboardGrabberItems.isEmpty() ? d->keyboardGrabberItems.last() : 0;
       
  3845     if (!item)
       
  3846         item = focusItem();
       
  3847     if (item) {
       
  3848         QGraphicsItem *p = item;
       
  3849         do {
       
  3850             // Accept the event by default
       
  3851             keyEvent->accept();
       
  3852             // Send it; QGraphicsItem::keyPressEvent ignores it.  If the event
       
  3853             // is filtered out, stop propagating it.
       
  3854             if (p->isBlockedByModalPanel())
       
  3855                 break;
       
  3856             if (!d->sendEvent(p, keyEvent))
       
  3857                 break;
       
  3858         } while (!keyEvent->isAccepted() && !p->isPanel() && (p = p->parentItem()));
       
  3859     } else {
       
  3860         keyEvent->ignore();
       
  3861     }
       
  3862 }
       
  3863 
       
  3864 /*!
       
  3865     This event handler, for event \a mouseEvent, can be reimplemented
       
  3866     in a subclass to receive mouse press events for the scene.
       
  3867 
       
  3868     The default implementation depends on the state of the scene. If
       
  3869     there is a mouse grabber item, then the event is sent to the mouse
       
  3870     grabber. Otherwise, it is forwarded to the topmost item that
       
  3871     accepts mouse events at the scene position from the event, and
       
  3872     that item promptly becomes the mouse grabber item.
       
  3873 
       
  3874     If there is no item at the given position on the scene, the
       
  3875     selection area is reset, any focus item loses its input focus, and
       
  3876     the event is then ignored.
       
  3877 
       
  3878     \sa QGraphicsItem::mousePressEvent(),
       
  3879     QGraphicsItem::setAcceptedMouseButtons()
       
  3880 */
       
  3881 void QGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
       
  3882 {
       
  3883     Q_D(QGraphicsScene);
       
  3884     if (d->mouseGrabberItems.isEmpty()) {
       
  3885         // Dispatch hover events
       
  3886         QGraphicsSceneHoverEvent hover;
       
  3887         _q_hoverFromMouseEvent(&hover, mouseEvent);
       
  3888         d->dispatchHoverEvent(&hover);
       
  3889     }
       
  3890 
       
  3891     d->mousePressEventHandler(mouseEvent);
       
  3892 }
       
  3893 
       
  3894 /*!
       
  3895     This event handler, for event \a mouseEvent, can be reimplemented
       
  3896     in a subclass to receive mouse move events for the scene.
       
  3897 
       
  3898     The default implementation depends on the mouse grabber state. If there is
       
  3899     a mouse grabber item, the event is sent to the mouse grabber.  If there
       
  3900     are any items that accept hover events at the current position, the event
       
  3901     is translated into a hover event and accepted; otherwise it's ignored.
       
  3902 
       
  3903     \sa QGraphicsItem::mousePressEvent(), QGraphicsItem::mouseReleaseEvent(),
       
  3904     QGraphicsItem::mouseDoubleClickEvent(), QGraphicsItem::setAcceptedMouseButtons()
       
  3905 */
       
  3906 void QGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
       
  3907 {
       
  3908     Q_D(QGraphicsScene);
       
  3909     if (d->mouseGrabberItems.isEmpty()) {
       
  3910         if (mouseEvent->buttons())
       
  3911             return;
       
  3912         QGraphicsSceneHoverEvent hover;
       
  3913         _q_hoverFromMouseEvent(&hover, mouseEvent);
       
  3914         mouseEvent->setAccepted(d->dispatchHoverEvent(&hover));
       
  3915         return;
       
  3916     }
       
  3917 
       
  3918     // Forward the event to the mouse grabber
       
  3919     d->sendMouseEvent(mouseEvent);
       
  3920     mouseEvent->accept();
       
  3921 }
       
  3922 
       
  3923 /*!
       
  3924     This event handler, for event \a mouseEvent, can be reimplemented
       
  3925     in a subclass to receive mouse release events for the scene.
       
  3926 
       
  3927     The default implementation depends on the mouse grabber state.  If
       
  3928     there is no mouse grabber, the event is ignored.  Otherwise, if
       
  3929     there is a mouse grabber item, the event is sent to the mouse
       
  3930     grabber. If this mouse release represents the last pressed button
       
  3931     on the mouse, the mouse grabber item then loses the mouse grab.
       
  3932 
       
  3933     \sa QGraphicsItem::mousePressEvent(), QGraphicsItem::mouseMoveEvent(),
       
  3934     QGraphicsItem::mouseDoubleClickEvent(), QGraphicsItem::setAcceptedMouseButtons()
       
  3935 */
       
  3936 void QGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
       
  3937 {
       
  3938     Q_D(QGraphicsScene);
       
  3939     if (d->mouseGrabberItems.isEmpty()) {
       
  3940         mouseEvent->ignore();
       
  3941         return;
       
  3942     }
       
  3943 
       
  3944     // Forward the event to the mouse grabber
       
  3945     d->sendMouseEvent(mouseEvent);
       
  3946     mouseEvent->accept();
       
  3947 
       
  3948     // Reset the mouse grabber when the last mouse button has been released.
       
  3949     if (!mouseEvent->buttons()) {
       
  3950         if (!d->mouseGrabberItems.isEmpty()) {
       
  3951             d->lastMouseGrabberItem = d->mouseGrabberItems.last();
       
  3952             if (d->lastMouseGrabberItemHasImplicitMouseGrab)
       
  3953                 d->mouseGrabberItems.last()->ungrabMouse();
       
  3954         } else {
       
  3955             d->lastMouseGrabberItem = 0;
       
  3956         }
       
  3957 
       
  3958         // Generate a hoverevent
       
  3959         QGraphicsSceneHoverEvent hoverEvent;
       
  3960         _q_hoverFromMouseEvent(&hoverEvent, mouseEvent);
       
  3961         d->dispatchHoverEvent(&hoverEvent);
       
  3962     }
       
  3963 }
       
  3964 
       
  3965 /*!
       
  3966     This event handler, for event \a mouseEvent, can be reimplemented
       
  3967     in a subclass to receive mouse doubleclick events for the scene.
       
  3968 
       
  3969     If someone doubleclicks on the scene, the scene will first receive
       
  3970     a mouse press event, followed by a release event (i.e., a click),
       
  3971     then a doubleclick event, and finally a release event. If the
       
  3972     doubleclick event is delivered to a different item than the one
       
  3973     that received the first press and release, it will be delivered as
       
  3974     a press event. However, tripleclick events are not delivered as
       
  3975     doubleclick events in this case.
       
  3976 
       
  3977     The default implementation is similar to mousePressEvent().
       
  3978 
       
  3979     \sa QGraphicsItem::mousePressEvent(), QGraphicsItem::mouseMoveEvent(),
       
  3980     QGraphicsItem::mouseReleaseEvent(), QGraphicsItem::setAcceptedMouseButtons()
       
  3981 */
       
  3982 void QGraphicsScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *mouseEvent)
       
  3983 {
       
  3984     Q_D(QGraphicsScene);
       
  3985     d->mousePressEventHandler(mouseEvent);
       
  3986 }
       
  3987 
       
  3988 /*!
       
  3989     This event handler, for event \a wheelEvent, can be reimplemented in a
       
  3990     subclass to receive mouse wheel events for the scene.
       
  3991 
       
  3992     By default, the event is delivered to the topmost visible item under the
       
  3993     cursor. If ignored, the event propagates to the item beneath, and again
       
  3994     until the event is accepted, or it reaches the scene. If no items accept
       
  3995     the event, it is ignored.
       
  3996 
       
  3997     \sa QGraphicsItem::wheelEvent()
       
  3998 */
       
  3999 void QGraphicsScene::wheelEvent(QGraphicsSceneWheelEvent *wheelEvent)
       
  4000 {
       
  4001     Q_D(QGraphicsScene);
       
  4002     QList<QGraphicsItem *> wheelCandidates = d->itemsAtPosition(wheelEvent->screenPos(),
       
  4003                                                                 wheelEvent->scenePos(),
       
  4004                                                                 wheelEvent->widget());
       
  4005 
       
  4006     bool hasSetFocus = false;
       
  4007     foreach (QGraphicsItem *item, wheelCandidates) {
       
  4008         if (!hasSetFocus && item->isEnabled()
       
  4009             && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) {
       
  4010             if (item->isWidget() && static_cast<QGraphicsWidget *>(item)->focusPolicy() == Qt::WheelFocus) {
       
  4011                 hasSetFocus = true;
       
  4012                 if (item != focusItem())
       
  4013                     setFocusItem(item, Qt::MouseFocusReason);
       
  4014             }
       
  4015         }
       
  4016 
       
  4017         wheelEvent->setPos(item->d_ptr->genericMapFromScene(wheelEvent->scenePos(),
       
  4018                                                             wheelEvent->widget()));
       
  4019         wheelEvent->accept();
       
  4020         bool isPanel = item->isPanel();
       
  4021         d->sendEvent(item, wheelEvent);
       
  4022         if (isPanel || wheelEvent->isAccepted())
       
  4023             break;
       
  4024     }
       
  4025 }
       
  4026 
       
  4027 /*!
       
  4028     This event handler, for event \a event, can be reimplemented in a
       
  4029     subclass to receive input method events for the scene.
       
  4030 
       
  4031     The default implementation forwards the event to the focusItem().
       
  4032     If no item currently has focus or the current focus item does not
       
  4033     accept input methods, this function does nothing.
       
  4034 
       
  4035     \sa QGraphicsItem::inputMethodEvent()
       
  4036 */
       
  4037 void QGraphicsScene::inputMethodEvent(QInputMethodEvent *event)
       
  4038 {
       
  4039     Q_D(QGraphicsScene);
       
  4040     if (d->focusItem && (d->focusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod))
       
  4041         d->sendEvent(d->focusItem, event);
       
  4042 }
       
  4043 
       
  4044 /*!
       
  4045     Draws the background of the scene using \a painter, before any items and
       
  4046     the foreground are drawn. Reimplement this function to provide a custom
       
  4047     background for the scene.
       
  4048 
       
  4049     All painting is done in \e scene coordinates. The \a rect
       
  4050     parameter is the exposed rectangle.
       
  4051 
       
  4052     If all you want is to define a color, texture, or gradient for the
       
  4053     background, you can call setBackgroundBrush() instead.
       
  4054 
       
  4055     \sa drawForeground(), drawItems()
       
  4056 */
       
  4057 void QGraphicsScene::drawBackground(QPainter *painter, const QRectF &rect)
       
  4058 {
       
  4059     Q_D(QGraphicsScene);
       
  4060 
       
  4061     if (d->backgroundBrush.style() != Qt::NoBrush) {
       
  4062         if (d->painterStateProtection)
       
  4063             painter->save();
       
  4064         painter->setBrushOrigin(0, 0);
       
  4065         painter->fillRect(rect, backgroundBrush());
       
  4066         if (d->painterStateProtection)
       
  4067             painter->restore();
       
  4068     }
       
  4069 }
       
  4070 
       
  4071 /*!
       
  4072     Draws the foreground of the scene using \a painter, after the background
       
  4073     and all items have been drawn. Reimplement this function to provide a
       
  4074     custom foreground for the scene.
       
  4075 
       
  4076     All painting is done in \e scene coordinates. The \a rect
       
  4077     parameter is the exposed rectangle.
       
  4078 
       
  4079     If all you want is to define a color, texture or gradient for the
       
  4080     foreground, you can call setForegroundBrush() instead.
       
  4081 
       
  4082     \sa drawBackground(), drawItems()
       
  4083 */
       
  4084 void QGraphicsScene::drawForeground(QPainter *painter, const QRectF &rect)
       
  4085 {
       
  4086     Q_D(QGraphicsScene);
       
  4087 
       
  4088     if (d->foregroundBrush.style() != Qt::NoBrush) {
       
  4089         if (d->painterStateProtection)
       
  4090             painter->save();
       
  4091         painter->setBrushOrigin(0, 0);
       
  4092         painter->fillRect(rect, foregroundBrush());
       
  4093         if (d->painterStateProtection)
       
  4094             painter->restore();
       
  4095     }
       
  4096 }
       
  4097 
       
  4098 static void _q_paintItem(QGraphicsItem *item, QPainter *painter,
       
  4099                          const QStyleOptionGraphicsItem *option, QWidget *widget,
       
  4100                          bool useWindowOpacity, bool painterStateProtection)
       
  4101 {
       
  4102     if (!item->isWidget()) {
       
  4103         item->paint(painter, option, widget);
       
  4104         return;
       
  4105     }
       
  4106     QGraphicsWidget *widgetItem = static_cast<QGraphicsWidget *>(item);
       
  4107     QGraphicsProxyWidget *proxy = qobject_cast<QGraphicsProxyWidget *>(widgetItem);
       
  4108     const qreal windowOpacity = (proxy && proxy->widget() && useWindowOpacity)
       
  4109                                 ? proxy->widget()->windowOpacity() : 1.0;
       
  4110     const qreal oldPainterOpacity = painter->opacity();
       
  4111 
       
  4112     if (qFuzzyIsNull(windowOpacity))
       
  4113         return;
       
  4114     // Set new painter opacity.
       
  4115     if (windowOpacity < 1.0)
       
  4116         painter->setOpacity(oldPainterOpacity * windowOpacity);
       
  4117 
       
  4118     // set layoutdirection on the painter
       
  4119     Qt::LayoutDirection oldLayoutDirection = painter->layoutDirection();
       
  4120     painter->setLayoutDirection(widgetItem->layoutDirection());
       
  4121 
       
  4122     if (widgetItem->isWindow() && widgetItem->windowType() != Qt::Popup && widgetItem->windowType() != Qt::ToolTip
       
  4123         && !(widgetItem->windowFlags() & Qt::FramelessWindowHint)) {
       
  4124         if (painterStateProtection)
       
  4125             painter->save();
       
  4126         widgetItem->paintWindowFrame(painter, option, widget);
       
  4127         if (painterStateProtection)
       
  4128             painter->restore();
       
  4129     }
       
  4130 
       
  4131     widgetItem->paint(painter, option, widget);
       
  4132 
       
  4133     // Restore layoutdirection on the painter.
       
  4134     painter->setLayoutDirection(oldLayoutDirection);
       
  4135     // Restore painter opacity.
       
  4136     if (windowOpacity < 1.0)
       
  4137         painter->setOpacity(oldPainterOpacity);
       
  4138 }
       
  4139 
       
  4140 static void _q_paintIntoCache(QPixmap *pix, QGraphicsItem *item, const QRegion &pixmapExposed,
       
  4141                               const QTransform &itemToPixmap, QPainter::RenderHints renderHints,
       
  4142                               const QStyleOptionGraphicsItem *option, bool painterStateProtection)
       
  4143 {
       
  4144     QPixmap subPix;
       
  4145     QPainter pixmapPainter;
       
  4146     QRect br = pixmapExposed.boundingRect();
       
  4147 
       
  4148     // Don't use subpixmap if we get a full update.
       
  4149     if (pixmapExposed.isEmpty() || (pixmapExposed.numRects() == 1 && br.contains(pix->rect()))) {
       
  4150         pix->fill(Qt::transparent);
       
  4151         pixmapPainter.begin(pix);
       
  4152     } else {
       
  4153         subPix = QPixmap(br.size());
       
  4154         subPix.fill(Qt::transparent);
       
  4155         pixmapPainter.begin(&subPix);
       
  4156         pixmapPainter.translate(-br.topLeft());
       
  4157         if (!pixmapExposed.isEmpty()) {
       
  4158             // Applied to subPix; paint is adjusted to the coordinate space is
       
  4159             // correct.
       
  4160             pixmapPainter.setClipRegion(pixmapExposed);
       
  4161         }
       
  4162     }
       
  4163 
       
  4164     pixmapPainter.setRenderHints(pixmapPainter.renderHints(), false);
       
  4165     pixmapPainter.setRenderHints(renderHints, true);
       
  4166     pixmapPainter.setWorldTransform(itemToPixmap, true);
       
  4167 
       
  4168     // Render.
       
  4169     _q_paintItem(item, &pixmapPainter, option, 0, false, painterStateProtection);
       
  4170     pixmapPainter.end();
       
  4171 
       
  4172     if (!subPix.isNull()) {
       
  4173         // Blit the subpixmap into the main pixmap.
       
  4174         pixmapPainter.begin(pix);
       
  4175         pixmapPainter.setCompositionMode(QPainter::CompositionMode_Source);
       
  4176         pixmapPainter.setClipRegion(pixmapExposed);
       
  4177         pixmapPainter.drawPixmap(br.topLeft(), subPix);
       
  4178         pixmapPainter.end();
       
  4179     }
       
  4180 }
       
  4181 
       
  4182 /*!
       
  4183     \internal
       
  4184 
       
  4185     Draws items directly, or using cache.
       
  4186 */
       
  4187 void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painter,
       
  4188                                            const QStyleOptionGraphicsItem *option, QWidget *widget,
       
  4189                                            bool painterStateProtection)
       
  4190 {
       
  4191     QGraphicsItemPrivate *itemd = item->d_ptr.data();
       
  4192     QGraphicsItem::CacheMode cacheMode = QGraphicsItem::CacheMode(itemd->cacheMode);
       
  4193 
       
  4194     // Render directly, using no cache.
       
  4195     if (cacheMode == QGraphicsItem::NoCache
       
  4196 #ifdef Q_WS_X11
       
  4197         || !X11->use_xrender
       
  4198 #endif
       
  4199         ) {
       
  4200         _q_paintItem(static_cast<QGraphicsWidget *>(item), painter, option, widget, true, painterStateProtection);
       
  4201         return;
       
  4202     }
       
  4203 
       
  4204     const qreal oldPainterOpacity = painter->opacity();
       
  4205     qreal newPainterOpacity = oldPainterOpacity;
       
  4206     QGraphicsProxyWidget *proxy = item->isWidget() ? qobject_cast<QGraphicsProxyWidget *>(static_cast<QGraphicsWidget *>(item)) : 0;
       
  4207     if (proxy && proxy->widget()) {
       
  4208         const qreal windowOpacity = proxy->widget()->windowOpacity();
       
  4209         if (windowOpacity < 1.0)
       
  4210             newPainterOpacity *= windowOpacity;
       
  4211     }
       
  4212 
       
  4213     // Item's (local) bounding rect
       
  4214     QRectF brect = item->boundingRect();
       
  4215     QRectF adjustedBrect(brect);
       
  4216     _q_adjustRect(&adjustedBrect);
       
  4217     if (adjustedBrect.isEmpty())
       
  4218         return;
       
  4219 
       
  4220     // Fetch the off-screen transparent buffer and exposed area info.
       
  4221     QPixmapCache::Key pixmapKey;
       
  4222     QPixmap pix;
       
  4223     bool pixmapFound;
       
  4224     QGraphicsItemCache *itemCache = itemd->extraItemCache();
       
  4225     if (cacheMode == QGraphicsItem::ItemCoordinateCache) {
       
  4226         if (itemCache->boundingRect != brect.toRect()) {
       
  4227             itemCache->boundingRect = brect.toRect();
       
  4228             itemCache->allExposed = true;
       
  4229             itemCache->exposed.clear();
       
  4230         }
       
  4231         pixmapKey = itemCache->key;
       
  4232     } else {
       
  4233         pixmapKey = itemCache->deviceData.value(widget).key;
       
  4234     }
       
  4235 
       
  4236     // Find pixmap in cache.
       
  4237     pixmapFound = QPixmapCache::find(pixmapKey, &pix);
       
  4238 
       
  4239     // Render using item coordinate cache mode.
       
  4240     if (cacheMode == QGraphicsItem::ItemCoordinateCache) {
       
  4241         QSize pixmapSize;
       
  4242         bool fixedCacheSize = false;
       
  4243         QRectF brectAligned = brect.toAlignedRect();
       
  4244         if ((fixedCacheSize = itemCache->fixedSize.isValid())) {
       
  4245             pixmapSize = itemCache->fixedSize;
       
  4246         } else {
       
  4247             pixmapSize = brectAligned.size().toSize();
       
  4248         }
       
  4249 
       
  4250         // Create or recreate the pixmap.
       
  4251         int adjust = itemCache->fixedSize.isValid() ? 0 : 2;
       
  4252         QSize adjustSize(adjust*2, adjust*2);
       
  4253         QRectF br = brectAligned.adjusted(-adjust, -adjust, adjust, adjust);
       
  4254         if (pix.isNull() || (!fixedCacheSize && (pixmapSize + adjustSize) != pix.size())) {
       
  4255             pix = QPixmap(pixmapSize + adjustSize);
       
  4256             itemCache->exposed.clear();
       
  4257             itemCache->allExposed = true;
       
  4258         }
       
  4259 
       
  4260         // Redraw any newly exposed areas.
       
  4261         if (itemCache->allExposed || !itemCache->exposed.isEmpty()) {
       
  4262 
       
  4263             //We know that we will modify the pixmap, removing it from the cache
       
  4264             //will detach the one we have and avoid a deep copy
       
  4265             if (pixmapFound)
       
  4266                 QPixmapCache::remove(pixmapKey);
       
  4267 
       
  4268             // Fit the item's bounding rect into the pixmap's coordinates.
       
  4269             QTransform itemToPixmap;
       
  4270             if (fixedCacheSize) {
       
  4271                 const QPointF scale(pixmapSize.width() / brect.width(), pixmapSize.height() / brect.height());
       
  4272                 itemToPixmap.scale(scale.x(), scale.y());
       
  4273             }
       
  4274             itemToPixmap.translate(-br.x(), -br.y());
       
  4275 
       
  4276             // Generate the item's exposedRect and map its list of expose
       
  4277             // rects to device coordinates.
       
  4278             styleOptionTmp = *option;
       
  4279             QRegion pixmapExposed;
       
  4280             QRectF exposedRect;
       
  4281             if (!itemCache->allExposed) {
       
  4282                 for (int i = 0; i < itemCache->exposed.size(); ++i) {
       
  4283                     QRectF r = itemCache->exposed.at(i);
       
  4284                     exposedRect |= r;
       
  4285                     pixmapExposed += itemToPixmap.mapRect(r).toAlignedRect();
       
  4286                 }
       
  4287             } else {
       
  4288                 exposedRect = brect;
       
  4289             }
       
  4290             styleOptionTmp.exposedRect = exposedRect;
       
  4291 
       
  4292             // Render.
       
  4293             _q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(),
       
  4294                               &styleOptionTmp, painterStateProtection);
       
  4295 
       
  4296             // insert this pixmap into the cache.
       
  4297             itemCache->key = QPixmapCache::insert(pix);
       
  4298 
       
  4299             // Reset expose data.
       
  4300             itemCache->allExposed = false;
       
  4301             itemCache->exposed.clear();
       
  4302         }
       
  4303 
       
  4304         // Redraw the exposed area using the transformed painter. Depending on
       
  4305         // the hardware, this may be a server-side operation, or an expensive
       
  4306         // qpixmap-image-transform-pixmap roundtrip.
       
  4307         if (newPainterOpacity != oldPainterOpacity) {
       
  4308             painter->setOpacity(newPainterOpacity);
       
  4309             painter->drawPixmap(br, pix, QRectF(QPointF(), pix.size()));
       
  4310             painter->setOpacity(oldPainterOpacity);
       
  4311         } else {
       
  4312             painter->drawPixmap(br, pix, QRectF(QPointF(), pix.size()));
       
  4313         }
       
  4314         return;
       
  4315     }
       
  4316 
       
  4317     // Render using device coordinate cache mode.
       
  4318     if (cacheMode == QGraphicsItem::DeviceCoordinateCache) {
       
  4319         // Find the item's bounds in device coordinates.
       
  4320         QRectF deviceBounds = painter->worldTransform().mapRect(brect);
       
  4321         QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
       
  4322         if (deviceRect.isEmpty())
       
  4323             return;
       
  4324         QRect viewRect = widget ? widget->rect() : QRect();
       
  4325         if (widget && !viewRect.intersects(deviceRect))
       
  4326             return;
       
  4327 
       
  4328         // Resort to direct rendering if the device rect exceeds the
       
  4329         // (optional) maximum bounds. (QGraphicsSvgItem uses this).
       
  4330         QSize maximumCacheSize =
       
  4331             itemd->extra(QGraphicsItemPrivate::ExtraMaxDeviceCoordCacheSize).toSize();
       
  4332         if (!maximumCacheSize.isEmpty()
       
  4333             && (deviceRect.width() > maximumCacheSize.width()
       
  4334                 || deviceRect.height() > maximumCacheSize.height())) {
       
  4335             _q_paintItem(static_cast<QGraphicsWidget *>(item), painter, option, widget,
       
  4336                          oldPainterOpacity != newPainterOpacity, painterStateProtection);
       
  4337             return;
       
  4338         }
       
  4339 
       
  4340         // Create or reuse offscreen pixmap, possibly scroll/blit from the old one.
       
  4341         bool pixModified = false;
       
  4342         QGraphicsItemCache::DeviceData *deviceData = &itemCache->deviceData[widget];
       
  4343         bool invertable = true;
       
  4344         QTransform diff = deviceData->lastTransform.inverted(&invertable);
       
  4345         if (invertable)
       
  4346             diff *= painter->worldTransform();
       
  4347         deviceData->lastTransform = painter->worldTransform();
       
  4348         if (!invertable || diff.type() > QTransform::TxTranslate) {
       
  4349             pixModified = true;
       
  4350             itemCache->allExposed = true;
       
  4351             itemCache->exposed.clear();
       
  4352             pix = QPixmap();
       
  4353         }
       
  4354 
       
  4355         // ### This is a pretty bad way to determine when to start partial
       
  4356         // exposure for DeviceCoordinateCache but it's the least intrusive
       
  4357         // approach for now.
       
  4358 #if 0
       
  4359         // Only if the device rect isn't fully contained.
       
  4360         bool allowPartialCacheExposure = !viewRect.contains(deviceRect);
       
  4361 #else
       
  4362         // Only if deviceRect is 20% taller or wider than the desktop.
       
  4363         QRect desktopRect = QApplication::desktop()->availableGeometry(widget);
       
  4364         bool allowPartialCacheExposure = (desktopRect.width() * 1.2 < deviceRect.width()
       
  4365                                           || desktopRect.height() * 1.2 < deviceRect.height());
       
  4366 #endif
       
  4367         QRegion scrollExposure;
       
  4368         if (deviceData->cacheIndent != QPoint() || allowPartialCacheExposure) {
       
  4369             // Part of pixmap is drawn. Either device contains viewrect (big
       
  4370             // item covers whole screen) or parts of device are outside the
       
  4371             // viewport. In either case the device rect must be the intersect
       
  4372             // between the two.
       
  4373             int dx = deviceRect.left() < viewRect.left() ? viewRect.left() - deviceRect.left() : 0;
       
  4374             int dy = deviceRect.top() < viewRect.top() ? viewRect.top() - deviceRect.top() : 0;
       
  4375             QPoint newCacheIndent(dx, dy);
       
  4376             deviceRect &= viewRect;
       
  4377 
       
  4378             if (pix.isNull()) {
       
  4379                 deviceData->cacheIndent = QPoint();
       
  4380                 itemCache->allExposed = true;
       
  4381                 itemCache->exposed.clear();
       
  4382                 pixModified = true;
       
  4383             }
       
  4384 
       
  4385             // Copy / "scroll" the old pixmap onto the new ole and calculate
       
  4386             // scrolled exposure.
       
  4387             if (newCacheIndent != deviceData->cacheIndent || deviceRect.size() != pix.size()) {
       
  4388                 QPoint diff = newCacheIndent - deviceData->cacheIndent;
       
  4389                 QPixmap newPix(deviceRect.size());
       
  4390                 // ### Investigate removing this fill (test with Plasma and
       
  4391                 // graphicssystem raster).
       
  4392                 newPix.fill(Qt::transparent);
       
  4393                 if (!pix.isNull()) {
       
  4394                     QPainter newPixPainter(&newPix);
       
  4395                     newPixPainter.drawPixmap(-diff, pix);
       
  4396                     newPixPainter.end();
       
  4397                 }
       
  4398                 QRegion exposed;
       
  4399                 exposed += newPix.rect();
       
  4400                 if (!pix.isNull())
       
  4401                     exposed -= QRect(-diff, pix.size());
       
  4402                 scrollExposure = exposed;
       
  4403 
       
  4404                 pix = newPix;
       
  4405                 pixModified = true;
       
  4406             }
       
  4407             deviceData->cacheIndent = newCacheIndent;
       
  4408         } else {
       
  4409             // Full pixmap is drawn.
       
  4410             deviceData->cacheIndent = QPoint();
       
  4411 
       
  4412             // Auto-adjust the pixmap size.
       
  4413             if (deviceRect.size() != pix.size()) {
       
  4414                 // exposed needs to cover the whole pixmap
       
  4415                 pix = QPixmap(deviceRect.size());
       
  4416                 pixModified = true;
       
  4417                 itemCache->allExposed = true;
       
  4418                 itemCache->exposed.clear();
       
  4419             }
       
  4420         }
       
  4421 
       
  4422         // Check for newly invalidated areas.
       
  4423         if (itemCache->allExposed || !itemCache->exposed.isEmpty() || !scrollExposure.isEmpty()) {
       
  4424             //We know that we will modify the pixmap, removing it from the cache
       
  4425             //will detach the one we have and avoid a deep copy
       
  4426             if (pixmapFound)
       
  4427                 QPixmapCache::remove(pixmapKey);
       
  4428 
       
  4429             // Construct an item-to-pixmap transform.
       
  4430             QPointF p = deviceRect.topLeft();
       
  4431             QTransform itemToPixmap = painter->worldTransform();
       
  4432             if (!p.isNull())
       
  4433                 itemToPixmap *= QTransform::fromTranslate(-p.x(), -p.y());
       
  4434 
       
  4435             // Map the item's logical expose to pixmap coordinates.
       
  4436             QRegion pixmapExposed = scrollExposure;
       
  4437             if (!itemCache->allExposed) {
       
  4438                 const QVector<QRectF> &exposed = itemCache->exposed;
       
  4439                 for (int i = 0; i < exposed.size(); ++i)
       
  4440                     pixmapExposed += itemToPixmap.mapRect(exposed.at(i)).toRect().adjusted(-1, -1, 1, 1);
       
  4441             }
       
  4442 
       
  4443             // Calculate the style option's exposedRect.
       
  4444             QRectF br;
       
  4445             if (itemCache->allExposed) {
       
  4446                 br = item->boundingRect();
       
  4447             } else {
       
  4448                 const QVector<QRectF> &exposed = itemCache->exposed;
       
  4449                 for (int i = 0; i < exposed.size(); ++i)
       
  4450                     br |= exposed.at(i);
       
  4451                 QTransform pixmapToItem = itemToPixmap.inverted();
       
  4452                 foreach (QRect r, scrollExposure.rects())
       
  4453                     br |= pixmapToItem.mapRect(r);
       
  4454             }
       
  4455             styleOptionTmp = *option;
       
  4456             styleOptionTmp.exposedRect = br.adjusted(-1, -1, 1, 1);
       
  4457 
       
  4458             // Render the exposed areas.
       
  4459             _q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(),
       
  4460                               &styleOptionTmp, painterStateProtection);
       
  4461 
       
  4462             // Reset expose data.
       
  4463             pixModified = true;
       
  4464             itemCache->allExposed = false;
       
  4465             itemCache->exposed.clear();
       
  4466         }
       
  4467 
       
  4468         if (pixModified) {
       
  4469             // Insert this pixmap into the cache.
       
  4470             deviceData->key = QPixmapCache::insert(pix);
       
  4471         }
       
  4472 
       
  4473         // Redraw the exposed area using an untransformed painter. This
       
  4474         // effectively becomes a bitblit that does not transform the cache.
       
  4475         QTransform restoreTransform = painter->worldTransform();
       
  4476         painter->setWorldTransform(QTransform());
       
  4477         if (newPainterOpacity != oldPainterOpacity) {
       
  4478             painter->setOpacity(newPainterOpacity);
       
  4479             painter->drawPixmap(deviceRect.topLeft(), pix);
       
  4480             painter->setOpacity(oldPainterOpacity);
       
  4481         } else {
       
  4482             painter->drawPixmap(deviceRect.topLeft(), pix);
       
  4483         }
       
  4484         painter->setWorldTransform(restoreTransform);
       
  4485         return;
       
  4486     }
       
  4487 }
       
  4488 
       
  4489 void QGraphicsScenePrivate::drawItems(QPainter *painter, const QTransform *const viewTransform,
       
  4490                                       QRegion *exposedRegion, QWidget *widget)
       
  4491 {
       
  4492     // Make sure we don't have unpolished items before we draw.
       
  4493     if (!unpolishedItems.isEmpty())
       
  4494         _q_polishItems();
       
  4495 
       
  4496     QRectF exposedSceneRect;
       
  4497     if (exposedRegion && indexMethod != QGraphicsScene::NoIndex) {
       
  4498         exposedSceneRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1);
       
  4499         if (viewTransform)
       
  4500             exposedSceneRect = viewTransform->inverted().mapRect(exposedSceneRect);
       
  4501     }
       
  4502     const QList<QGraphicsItem *> tli = index->estimateTopLevelItems(exposedSceneRect, Qt::AscendingOrder);
       
  4503     for (int i = 0; i < tli.size(); ++i)
       
  4504         drawSubtreeRecursive(tli.at(i), painter, viewTransform, exposedRegion, widget);
       
  4505 }
       
  4506 
       
  4507 void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter,
       
  4508                                                  const QTransform *const viewTransform,
       
  4509                                                  QRegion *exposedRegion, QWidget *widget,
       
  4510                                                  qreal parentOpacity, const QTransform *const effectTransform)
       
  4511 {
       
  4512     Q_ASSERT(item);
       
  4513 
       
  4514     if (!item->d_ptr->visible)
       
  4515         return;
       
  4516 
       
  4517     const bool itemHasContents = !(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents);
       
  4518     const bool itemHasChildren = !item->d_ptr->children.isEmpty();
       
  4519     if (!itemHasContents && !itemHasChildren)
       
  4520         return; // Item has neither contents nor children!(?)
       
  4521 
       
  4522     const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
       
  4523     const bool itemIsFullyTransparent = (opacity < 0.0001);
       
  4524     if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity()))
       
  4525         return;
       
  4526 
       
  4527     QTransform transform(Qt::Uninitialized);
       
  4528     QTransform *transformPtr = 0;
       
  4529     bool translateOnlyTransform = false;
       
  4530 #define ENSURE_TRANSFORM_PTR \
       
  4531     if (!transformPtr) { \
       
  4532         Q_ASSERT(!itemIsUntransformable); \
       
  4533         if (viewTransform) { \
       
  4534             transform = item->d_ptr->sceneTransform; \
       
  4535             transform *= *viewTransform; \
       
  4536             transformPtr = &transform; \
       
  4537         } else { \
       
  4538             transformPtr = &item->d_ptr->sceneTransform; \
       
  4539             translateOnlyTransform = item->d_ptr->sceneTransformTranslateOnly; \
       
  4540         } \
       
  4541     }
       
  4542 
       
  4543     // Update the item's scene transform if the item is transformable;
       
  4544     // otherwise calculate the full transform,
       
  4545     bool wasDirtyParentSceneTransform = false;
       
  4546     const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable();
       
  4547     if (itemIsUntransformable) {
       
  4548         transform = item->deviceTransform(viewTransform ? *viewTransform : QTransform());
       
  4549         transformPtr = &transform;
       
  4550     } else if (item->d_ptr->dirtySceneTransform) {
       
  4551         item->d_ptr->updateSceneTransformFromParent();
       
  4552         Q_ASSERT(!item->d_ptr->dirtySceneTransform);
       
  4553         wasDirtyParentSceneTransform = true;
       
  4554     }
       
  4555 
       
  4556     const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
       
  4557     bool drawItem = itemHasContents && !itemIsFullyTransparent;
       
  4558     if (drawItem) {
       
  4559         const QRectF brect = adjustedItemEffectiveBoundingRect(item);
       
  4560         ENSURE_TRANSFORM_PTR
       
  4561         QRect viewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy()).toRect()
       
  4562                                                         : transformPtr->mapRect(brect).toRect();
       
  4563         if (widget)
       
  4564             item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
       
  4565         viewBoundingRect.adjust(-1, -1, 1, 1);
       
  4566         drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect) : !viewBoundingRect.isEmpty();
       
  4567         if (!drawItem) {
       
  4568             if (!itemHasChildren)
       
  4569                 return;
       
  4570             if (itemClipsChildrenToShape) {
       
  4571                 if (wasDirtyParentSceneTransform)
       
  4572                     item->d_ptr->invalidateChildrenSceneTransform();
       
  4573                 return;
       
  4574             }
       
  4575         }
       
  4576     } // else we know for sure this item has children we must process.
       
  4577 
       
  4578     if (itemHasChildren && itemClipsChildrenToShape)
       
  4579         ENSURE_TRANSFORM_PTR;
       
  4580 
       
  4581     if (item->d_ptr->graphicsEffect && item->d_ptr->graphicsEffect->isEnabled()) {
       
  4582         ENSURE_TRANSFORM_PTR;
       
  4583         QGraphicsItemPaintInfo info(viewTransform, transformPtr, effectTransform, exposedRegion, widget, &styleOptionTmp,
       
  4584                                     painter, opacity, wasDirtyParentSceneTransform, drawItem);
       
  4585         QGraphicsEffectSource *source = item->d_ptr->graphicsEffect->d_func()->source;
       
  4586         QGraphicsItemEffectSourcePrivate *sourced = static_cast<QGraphicsItemEffectSourcePrivate *>
       
  4587                                                     (source->d_func());
       
  4588         sourced->info = &info;
       
  4589         const QTransform restoreTransform = painter->worldTransform();
       
  4590         if (effectTransform)
       
  4591             painter->setWorldTransform(*transformPtr * *effectTransform);
       
  4592         else
       
  4593             painter->setWorldTransform(*transformPtr);
       
  4594         painter->setOpacity(opacity);
       
  4595 
       
  4596         if (sourced->lastEffectTransform != painter->worldTransform()) {
       
  4597             sourced->lastEffectTransform = painter->worldTransform();
       
  4598             sourced->invalidateCache();
       
  4599         }
       
  4600         item->d_ptr->graphicsEffect->draw(painter, source);
       
  4601         painter->setWorldTransform(restoreTransform);
       
  4602         sourced->info = 0;
       
  4603     } else {
       
  4604         draw(item, painter, viewTransform, transformPtr, exposedRegion, widget, opacity,
       
  4605              effectTransform, wasDirtyParentSceneTransform, drawItem);
       
  4606     }
       
  4607 }
       
  4608 
       
  4609 void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const QTransform *const viewTransform,
       
  4610                                  const QTransform *const transformPtr, QRegion *exposedRegion, QWidget *widget,
       
  4611                                  qreal opacity, const QTransform *effectTransform,
       
  4612                                  bool wasDirtyParentSceneTransform, bool drawItem)
       
  4613 {
       
  4614     const bool itemIsFullyTransparent = (opacity < 0.0001);
       
  4615     const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
       
  4616     const bool itemHasChildren = !item->d_ptr->children.isEmpty();
       
  4617 
       
  4618     int i = 0;
       
  4619     if (itemHasChildren) {
       
  4620         item->d_ptr->ensureSortedChildren();
       
  4621 
       
  4622         if (itemClipsChildrenToShape) {
       
  4623             painter->save();
       
  4624             Q_ASSERT(transformPtr);
       
  4625             if (effectTransform)
       
  4626                 painter->setWorldTransform(*transformPtr * *effectTransform);
       
  4627             else
       
  4628                 painter->setWorldTransform(*transformPtr);
       
  4629             painter->setClipPath(item->shape(), Qt::IntersectClip);
       
  4630         }
       
  4631 
       
  4632         // Draw children behind
       
  4633         for (i = 0; i < item->d_ptr->children.size(); ++i) {
       
  4634             QGraphicsItem *child = item->d_ptr->children.at(i);
       
  4635             if (wasDirtyParentSceneTransform)
       
  4636                 child->d_ptr->dirtySceneTransform = 1;
       
  4637             if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent))
       
  4638                 break;
       
  4639             if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
       
  4640                 continue;
       
  4641             drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform);
       
  4642         }
       
  4643     }
       
  4644 
       
  4645     // Draw item
       
  4646     if (drawItem) {
       
  4647         Q_ASSERT(!itemIsFullyTransparent);
       
  4648         Q_ASSERT(!(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents));
       
  4649         Q_ASSERT(transformPtr);
       
  4650         item->d_ptr->initStyleOption(&styleOptionTmp, *transformPtr, exposedRegion
       
  4651                                      ? *exposedRegion : QRegion(), exposedRegion == 0);
       
  4652 
       
  4653         const bool itemClipsToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsToShape;
       
  4654         const bool savePainter = itemClipsToShape || painterStateProtection;
       
  4655         if (savePainter)
       
  4656             painter->save();
       
  4657 
       
  4658         if (!itemHasChildren || !itemClipsChildrenToShape) {
       
  4659             if (effectTransform)
       
  4660                 painter->setWorldTransform(*transformPtr * *effectTransform);
       
  4661             else
       
  4662                 painter->setWorldTransform(*transformPtr);
       
  4663         }
       
  4664 
       
  4665         if (itemClipsToShape)
       
  4666             painter->setClipPath(item->shape(), Qt::IntersectClip);
       
  4667         painter->setOpacity(opacity);
       
  4668 
       
  4669         if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget)
       
  4670             item->paint(painter, &styleOptionTmp, widget);
       
  4671         else
       
  4672             drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection);
       
  4673 
       
  4674         if (savePainter)
       
  4675             painter->restore();
       
  4676     }
       
  4677 
       
  4678     // Draw children in front
       
  4679     if (itemHasChildren) {
       
  4680         for (; i < item->d_ptr->children.size(); ++i) {
       
  4681             QGraphicsItem *child = item->d_ptr->children.at(i);
       
  4682             if (wasDirtyParentSceneTransform)
       
  4683                 child->d_ptr->dirtySceneTransform = 1;
       
  4684             if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
       
  4685                 continue;
       
  4686             drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform);
       
  4687         }
       
  4688     }
       
  4689 
       
  4690     // Restore child clip
       
  4691     if (itemHasChildren && itemClipsChildrenToShape)
       
  4692         painter->restore();
       
  4693 }
       
  4694 
       
  4695 void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, bool invalidateChildren,
       
  4696                                       bool maybeDirtyClipPath, bool force, bool ignoreOpacity,
       
  4697                                       bool removingItemFromScene)
       
  4698 {
       
  4699     Q_ASSERT(item);
       
  4700     if (updateAll)
       
  4701         return;
       
  4702 
       
  4703     if (item->d_ptr->discardUpdateRequest(/*ignoreClipping=*/maybeDirtyClipPath,
       
  4704                                           /*ignoreVisibleBit=*/force,
       
  4705                                           /*ignoreDirtyBit=*/removingItemFromScene || invalidateChildren,
       
  4706                                           /*ignoreOpacity=*/ignoreOpacity)) {
       
  4707         if (item->d_ptr->dirty) {
       
  4708             // The item is already marked as dirty and will be processed later. However,
       
  4709             // we have to make sure ignoreVisible and ignoreOpacity are set properly;
       
  4710             // otherwise things like: item->update(); item->hide() (force is now true)
       
  4711             // won't work as expected.
       
  4712             if (force)
       
  4713                 item->d_ptr->ignoreVisible = 1;
       
  4714             if (ignoreOpacity)
       
  4715                 item->d_ptr->ignoreOpacity = 1;
       
  4716         }
       
  4717         return;
       
  4718     }
       
  4719 
       
  4720     const bool fullItemUpdate = rect.isNull();
       
  4721     if (!fullItemUpdate && rect.isEmpty())
       
  4722         return;
       
  4723 
       
  4724     if (!processDirtyItemsEmitted) {
       
  4725         QMetaObject::invokeMethod(q_ptr, "_q_processDirtyItems", Qt::QueuedConnection);
       
  4726         processDirtyItemsEmitted = true;
       
  4727     }
       
  4728 
       
  4729     if (removingItemFromScene) {
       
  4730         // Note that this function can be called from the item's destructor, so
       
  4731         // do NOT call any virtual functions on it within this block.
       
  4732         if (isSignalConnected(changedSignalIndex) || views.isEmpty()) {
       
  4733             // This block of code is kept for compatibility. Since 4.5, by default
       
  4734             // QGraphicsView does not connect the signal and we use the below
       
  4735             // method of delivering updates.
       
  4736             q_func()->update();
       
  4737             return;
       
  4738         }
       
  4739 
       
  4740         for (int i = 0; i < views.size(); ++i) {
       
  4741             QGraphicsViewPrivate *viewPrivate = views.at(i)->d_func();
       
  4742             QRect rect = item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport);
       
  4743             rect.translate(viewPrivate->dirtyScrollOffset);
       
  4744             viewPrivate->updateRect(rect);
       
  4745         }
       
  4746         return;
       
  4747     }
       
  4748 
       
  4749     bool hasNoContents = item->d_ptr->flags & QGraphicsItem::ItemHasNoContents
       
  4750                          && !item->d_ptr->graphicsEffect;
       
  4751     if (!hasNoContents) {
       
  4752         item->d_ptr->dirty = 1;
       
  4753         if (fullItemUpdate)
       
  4754             item->d_ptr->fullUpdatePending = 1;
       
  4755         else if (!item->d_ptr->fullUpdatePending)
       
  4756             item->d_ptr->needsRepaint |= rect;
       
  4757     }
       
  4758 
       
  4759     if (invalidateChildren) {
       
  4760         item->d_ptr->allChildrenDirty = 1;
       
  4761         item->d_ptr->dirtyChildren = 1;
       
  4762     }
       
  4763 
       
  4764     if (force)
       
  4765         item->d_ptr->ignoreVisible = 1;
       
  4766     if (ignoreOpacity)
       
  4767         item->d_ptr->ignoreOpacity = 1;
       
  4768 
       
  4769     QGraphicsItem *p = item->d_ptr->parent;
       
  4770     while (p) {
       
  4771         p->d_ptr->dirtyChildren = 1;
       
  4772         if (p->d_ptr->graphicsEffect && p->d_ptr->graphicsEffect->isEnabled()) {
       
  4773             p->d_ptr->dirty = 1;
       
  4774             p->d_ptr->fullUpdatePending = 1;
       
  4775         }
       
  4776         p = p->d_ptr->parent;
       
  4777     }
       
  4778 }
       
  4779 
       
  4780 static inline bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item,
       
  4781                                 const QRectF &rect, bool itemIsUntransformable)
       
  4782 {
       
  4783     Q_ASSERT(view);
       
  4784     Q_ASSERT(item);
       
  4785 
       
  4786     QGraphicsItem *itemq = static_cast<QGraphicsItem *>(item->q_ptr);
       
  4787     QGraphicsView *viewq = static_cast<QGraphicsView *>(view->q_ptr);
       
  4788 
       
  4789     if (itemIsUntransformable) {
       
  4790         const QTransform xform = itemq->deviceTransform(viewq->viewportTransform());
       
  4791         if (!item->hasBoundingRegionGranularity)
       
  4792             return view->updateRect(xform.mapRect(rect).toRect());
       
  4793         return view->updateRegion(xform.map(QRegion(rect.toRect())));
       
  4794     }
       
  4795 
       
  4796     if (item->sceneTransformTranslateOnly && view->identityMatrix) {
       
  4797         const qreal dx = item->sceneTransform.dx();
       
  4798         const qreal dy = item->sceneTransform.dy();
       
  4799         if (!item->hasBoundingRegionGranularity) {
       
  4800             QRectF r(rect);
       
  4801             r.translate(dx - view->horizontalScroll(), dy - view->verticalScroll());
       
  4802             return view->updateRect(r.toRect());
       
  4803         }
       
  4804         QRegion r(rect.toRect());
       
  4805         r.translate(qRound(dx) - view->horizontalScroll(), qRound(dy) - view->verticalScroll());
       
  4806         return view->updateRegion(r);
       
  4807     }
       
  4808 
       
  4809     if (!viewq->isTransformed()) {
       
  4810         if (!item->hasBoundingRegionGranularity)
       
  4811             return view->updateRect(item->sceneTransform.mapRect(rect).toRect());
       
  4812         return view->updateRegion(item->sceneTransform.map(QRegion(rect.toRect())));
       
  4813     }
       
  4814 
       
  4815     QTransform xform = item->sceneTransform;
       
  4816     xform *= viewq->viewportTransform();
       
  4817     if (!item->hasBoundingRegionGranularity)
       
  4818         return view->updateRect(xform.mapRect(rect).toRect());
       
  4819     return view->updateRegion(xform.map(QRegion(rect.toRect())));
       
  4820 }
       
  4821 
       
  4822 void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren,
       
  4823                                                        qreal parentOpacity)
       
  4824 {
       
  4825     Q_Q(QGraphicsScene);
       
  4826     Q_ASSERT(item);
       
  4827     Q_ASSERT(!updateAll);
       
  4828 
       
  4829     if (!item->d_ptr->dirty && !item->d_ptr->dirtyChildren) {
       
  4830         resetDirtyItem(item);
       
  4831         return;
       
  4832     }
       
  4833 
       
  4834     const bool itemIsHidden = !item->d_ptr->ignoreVisible && !item->d_ptr->visible;
       
  4835     if (itemIsHidden) {
       
  4836         resetDirtyItem(item, /*recursive=*/true);
       
  4837         return;
       
  4838     }
       
  4839 
       
  4840     bool itemHasContents = !(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents);
       
  4841     const bool itemHasChildren = !item->d_ptr->children.isEmpty();
       
  4842     if (!itemHasContents) {
       
  4843         if (!itemHasChildren) {
       
  4844             resetDirtyItem(item);
       
  4845             return; // Item has neither contents nor children!(?)
       
  4846         }
       
  4847         if (item->d_ptr->graphicsEffect)
       
  4848             itemHasContents = true;
       
  4849     }
       
  4850 
       
  4851     const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
       
  4852     const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity && opacity < 0.0001;
       
  4853     if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) {
       
  4854         resetDirtyItem(item, /*recursive=*/itemHasChildren);
       
  4855         return;
       
  4856     }
       
  4857 
       
  4858     bool wasDirtyParentSceneTransform = item->d_ptr->dirtySceneTransform;
       
  4859     const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable();
       
  4860     if (wasDirtyParentSceneTransform && !itemIsUntransformable) {
       
  4861         item->d_ptr->updateSceneTransformFromParent();
       
  4862         Q_ASSERT(!item->d_ptr->dirtySceneTransform);
       
  4863     }
       
  4864 
       
  4865     const bool wasDirtyParentViewBoundingRects = item->d_ptr->paintedViewBoundingRectsNeedRepaint;
       
  4866     if (itemIsFullyTransparent || !itemHasContents || dirtyAncestorContainsChildren) {
       
  4867         // Make sure we don't process invisible items or items with no content.
       
  4868         item->d_ptr->dirty = 0;
       
  4869         item->d_ptr->fullUpdatePending = 0;
       
  4870         // Might have a dirty view bounding rect otherwise.
       
  4871         if (itemIsFullyTransparent || !itemHasContents)
       
  4872             item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0;
       
  4873     }
       
  4874 
       
  4875     if (!hasSceneRect && item->d_ptr->geometryChanged && item->d_ptr->visible) {
       
  4876         // Update growingItemsBoundingRect.
       
  4877         if (item->d_ptr->sceneTransformTranslateOnly) {
       
  4878             growingItemsBoundingRect |= item->boundingRect().translated(item->d_ptr->sceneTransform.dx(),
       
  4879                                                                         item->d_ptr->sceneTransform.dy());
       
  4880         } else {
       
  4881             growingItemsBoundingRect |= item->d_ptr->sceneTransform.mapRect(item->boundingRect());
       
  4882         }
       
  4883     }
       
  4884 
       
  4885     // Process item.
       
  4886     if (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint) {
       
  4887         const bool useCompatUpdate = views.isEmpty() || isSignalConnected(changedSignalIndex);
       
  4888         const QRectF itemBoundingRect = adjustedItemEffectiveBoundingRect(item);
       
  4889 
       
  4890         if (useCompatUpdate && !itemIsUntransformable && qFuzzyIsNull(item->boundingRegionGranularity())) {
       
  4891             // This block of code is kept for compatibility. Since 4.5, by default
       
  4892             // QGraphicsView does not connect the signal and we use the below
       
  4893             // method of delivering updates.
       
  4894             if (item->d_ptr->sceneTransformTranslateOnly) {
       
  4895                 q->update(itemBoundingRect.translated(item->d_ptr->sceneTransform.dx(),
       
  4896                                                       item->d_ptr->sceneTransform.dy()));
       
  4897             } else {
       
  4898                 q->update(item->d_ptr->sceneTransform.mapRect(itemBoundingRect));
       
  4899             }
       
  4900         } else {
       
  4901             QRectF dirtyRect;
       
  4902             bool uninitializedDirtyRect = true;
       
  4903 
       
  4904             for (int j = 0; j < views.size(); ++j) {
       
  4905                 QGraphicsView *view = views.at(j);
       
  4906                 QGraphicsViewPrivate *viewPrivate = view->d_func();
       
  4907                 QRect &paintedViewBoundingRect = item->d_ptr->paintedViewBoundingRects[viewPrivate->viewport];
       
  4908                 if (viewPrivate->fullUpdatePending
       
  4909                     || viewPrivate->viewportUpdateMode == QGraphicsView::NoViewportUpdate) {
       
  4910                     // Okay, if we have a full update pending or no viewport update, this item's
       
  4911                     // paintedViewBoundingRect  will be updated correctly in the next paintEvent if
       
  4912                     // it is inside the viewport, but for now we can pretend that it is outside.
       
  4913                     paintedViewBoundingRect = QRect(-1, -1, -1, -1);
       
  4914                     continue;
       
  4915                 }
       
  4916 
       
  4917                 if (item->d_ptr->paintedViewBoundingRectsNeedRepaint && !paintedViewBoundingRect.isEmpty()) {
       
  4918                     paintedViewBoundingRect.translate(viewPrivate->dirtyScrollOffset);
       
  4919                     if (!viewPrivate->updateRect(paintedViewBoundingRect))
       
  4920                         paintedViewBoundingRect = QRect(-1, -1, -1, -1); // Outside viewport.
       
  4921                 }
       
  4922 
       
  4923                 if (!item->d_ptr->dirty)
       
  4924                     continue;
       
  4925 
       
  4926                 if (!item->d_ptr->paintedViewBoundingRectsNeedRepaint
       
  4927                     && paintedViewBoundingRect.x() == -1 && paintedViewBoundingRect.y() == -1
       
  4928                     && paintedViewBoundingRect.width() == -1 && paintedViewBoundingRect.height() == -1) {
       
  4929                     continue; // Outside viewport.
       
  4930                 }
       
  4931 
       
  4932                 if (uninitializedDirtyRect) {
       
  4933                     dirtyRect = itemBoundingRect;
       
  4934                     if (!item->d_ptr->fullUpdatePending) {
       
  4935                         _q_adjustRect(&item->d_ptr->needsRepaint);
       
  4936                         dirtyRect &= item->d_ptr->needsRepaint;
       
  4937                     }
       
  4938                     uninitializedDirtyRect = false;
       
  4939                 }
       
  4940 
       
  4941                 if (dirtyRect.isEmpty())
       
  4942                     continue; // Discard updates outside the bounding rect.
       
  4943 
       
  4944                 if (!updateHelper(viewPrivate, item->d_ptr.data(), dirtyRect, itemIsUntransformable)
       
  4945                     && item->d_ptr->paintedViewBoundingRectsNeedRepaint) {
       
  4946                     paintedViewBoundingRect = QRect(-1, -1, -1, -1); // Outside viewport.
       
  4947                 }
       
  4948             }
       
  4949         }
       
  4950     }
       
  4951 
       
  4952     // Process children.
       
  4953     if (itemHasChildren && item->d_ptr->dirtyChildren) {
       
  4954         if (!dirtyAncestorContainsChildren) {
       
  4955             dirtyAncestorContainsChildren = item->d_ptr->fullUpdatePending
       
  4956                                             && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
       
  4957         }
       
  4958         const bool allChildrenDirty = item->d_ptr->allChildrenDirty;
       
  4959         const bool parentIgnoresVisible = item->d_ptr->ignoreVisible;
       
  4960         const bool parentIgnoresOpacity = item->d_ptr->ignoreOpacity;
       
  4961         for (int i = 0; i < item->d_ptr->children.size(); ++i) {
       
  4962             QGraphicsItem *child = item->d_ptr->children.at(i);
       
  4963             if (wasDirtyParentSceneTransform)
       
  4964                 child->d_ptr->dirtySceneTransform = 1;
       
  4965             if (wasDirtyParentViewBoundingRects)
       
  4966                 child->d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
       
  4967             if (parentIgnoresVisible)
       
  4968                 child->d_ptr->ignoreVisible = 1;
       
  4969             if (parentIgnoresOpacity)
       
  4970                 child->d_ptr->ignoreOpacity = 1;
       
  4971             if (allChildrenDirty) {
       
  4972                 child->d_ptr->dirty = 1;
       
  4973                 child->d_ptr->fullUpdatePending = 1;
       
  4974                 child->d_ptr->dirtyChildren = 1;
       
  4975                 child->d_ptr->allChildrenDirty = 1;
       
  4976             }
       
  4977             processDirtyItemsRecursive(child, dirtyAncestorContainsChildren, opacity);
       
  4978         }
       
  4979     } else if (wasDirtyParentSceneTransform) {
       
  4980         item->d_ptr->invalidateChildrenSceneTransform();
       
  4981     }
       
  4982 
       
  4983     resetDirtyItem(item);
       
  4984 }
       
  4985 
       
  4986 /*!
       
  4987     Paints the given \a items using the provided \a painter, after the
       
  4988     background has been drawn, and before the foreground has been
       
  4989     drawn.  All painting is done in \e scene coordinates. Before
       
  4990     drawing each item, the painter must be transformed using
       
  4991     QGraphicsItem::sceneTransform().
       
  4992 
       
  4993     The \a options parameter is the list of style option objects for
       
  4994     each item in \a items. The \a numItems parameter is the number of
       
  4995     items in \a items and options in \a options. The \a widget
       
  4996     parameter is optional; if specified, it should point to the widget
       
  4997     that is being painted on.
       
  4998 
       
  4999     The default implementation prepares the painter matrix, and calls
       
  5000     QGraphicsItem::paint() on all items. Reimplement this function to
       
  5001     provide custom painting of all items for the scene; gaining
       
  5002     complete control over how each item is drawn. In some cases this
       
  5003     can increase drawing performance significantly.
       
  5004 
       
  5005     Example:
       
  5006 
       
  5007     \snippet doc/src/snippets/graphicssceneadditemsnippet.cpp 0
       
  5008 
       
  5009     \sa drawBackground(), drawForeground()
       
  5010 */
       
  5011 void QGraphicsScene::drawItems(QPainter *painter,
       
  5012                                int numItems,
       
  5013                                QGraphicsItem *items[],
       
  5014                                const QStyleOptionGraphicsItem options[], QWidget *widget)
       
  5015 {
       
  5016     Q_D(QGraphicsScene);
       
  5017     // Make sure we don't have unpolished items before we draw.
       
  5018     if (!d->unpolishedItems.isEmpty())
       
  5019         d->_q_polishItems();
       
  5020 
       
  5021     QTransform viewTransform = painter->worldTransform();
       
  5022     Q_UNUSED(options);
       
  5023 
       
  5024     // Determine view, expose and flags.
       
  5025     QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0;
       
  5026     QRegion *expose = 0;
       
  5027     if (view)
       
  5028         expose = &view->d_func()->exposedRegion;
       
  5029 
       
  5030     // Find all toplevels, they are already sorted.
       
  5031     QList<QGraphicsItem *> topLevelItems;
       
  5032     for (int i = 0; i < numItems; ++i) {
       
  5033         QGraphicsItem *item = items[i]->topLevelItem();
       
  5034         if (!item->d_ptr->itemDiscovered) {
       
  5035             topLevelItems << item;
       
  5036             item->d_ptr->itemDiscovered = 1;
       
  5037             d->drawSubtreeRecursive(item, painter, &viewTransform, expose, widget);
       
  5038         }
       
  5039     }
       
  5040 
       
  5041     // Reset discovery bits.
       
  5042     for (int i = 0; i < topLevelItems.size(); ++i)
       
  5043         topLevelItems.at(i)->d_ptr->itemDiscovered = 0;
       
  5044 
       
  5045     painter->setWorldTransform(viewTransform);
       
  5046 }
       
  5047 
       
  5048 /*!
       
  5049     \since 4.4
       
  5050 
       
  5051     Finds a new widget to give the keyboard focus to, as appropriate for Tab
       
  5052     and Shift+Tab, and returns true if it can find a new widget, or false if
       
  5053     it cannot. If \a next is true, this function searches forward; if \a next
       
  5054     is false, it searches backward.
       
  5055 
       
  5056     You can reimplement this function in a subclass of QGraphicsScene to
       
  5057     provide fine-grained control over how tab focus passes inside your
       
  5058     scene. The default implementation is based on the tab focus chain defined
       
  5059     by QGraphicsWidget::setTabOrder().
       
  5060 */
       
  5061 bool QGraphicsScene::focusNextPrevChild(bool next)
       
  5062 {
       
  5063     Q_D(QGraphicsScene);
       
  5064 
       
  5065     QGraphicsItem *item = focusItem();
       
  5066     if (item && !item->isWidget()) {
       
  5067         // Tab out of the scene.
       
  5068         return false;
       
  5069     }
       
  5070     if (!item) {
       
  5071         if (d->lastFocusItem && !d->lastFocusItem->isWidget()) {
       
  5072             // Restore focus to the last focusable non-widget item that had
       
  5073             // focus.
       
  5074             setFocusItem(d->lastFocusItem, next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
       
  5075             return true;
       
  5076         }
       
  5077     }
       
  5078     if (!d->tabFocusFirst) {
       
  5079         // No widgets...
       
  5080         return false;
       
  5081     }
       
  5082 
       
  5083     // The item must be a widget.
       
  5084     QGraphicsWidget *widget = 0;
       
  5085     if (!item) {
       
  5086         widget = next ? d->tabFocusFirst : d->tabFocusFirst->d_func()->focusPrev;
       
  5087     } else {
       
  5088         QGraphicsWidget *test = static_cast<QGraphicsWidget *>(item);
       
  5089         widget = next ? test->d_func()->focusNext : test->d_func()->focusPrev;
       
  5090         if ((next && widget == d->tabFocusFirst) || (!next && widget == d->tabFocusFirst->d_func()->focusPrev))
       
  5091             return false;
       
  5092     }
       
  5093     QGraphicsWidget *widgetThatHadFocus = widget;
       
  5094 
       
  5095     // Run around the focus chain until we find a widget that can take tab focus.
       
  5096     do {
       
  5097         if (widget->flags() & QGraphicsItem::ItemIsFocusable
       
  5098             && widget->isEnabled() && widget->isVisibleTo(0)
       
  5099             && (widget->focusPolicy() & Qt::TabFocus)
       
  5100             && (!item || !item->isPanel() || item->isAncestorOf(widget))
       
  5101             ) {
       
  5102             setFocusItem(widget, next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
       
  5103             return true;
       
  5104         }
       
  5105         widget = next ? widget->d_func()->focusNext : widget->d_func()->focusPrev;
       
  5106         if ((next && widget == d->tabFocusFirst) || (!next && widget == d->tabFocusFirst->d_func()->focusPrev))
       
  5107             return false;
       
  5108     } while (widget != widgetThatHadFocus);
       
  5109 
       
  5110     return false;
       
  5111 }
       
  5112 
       
  5113 /*!
       
  5114     \fn QGraphicsScene::changed(const QList<QRectF> &region)
       
  5115 
       
  5116     This signal is emitted by QGraphicsScene when control reaches the
       
  5117     event loop, if the scene content changes. The \a region parameter
       
  5118     contains a list of scene rectangles that indicate the area that
       
  5119     has been changed.
       
  5120 
       
  5121     \sa QGraphicsView::updateScene()
       
  5122 */
       
  5123 
       
  5124 /*!
       
  5125     \fn QGraphicsScene::sceneRectChanged(const QRectF &rect)
       
  5126 
       
  5127     This signal is emitted by QGraphicsScene whenever the scene rect changes.
       
  5128     The \a rect parameter is the new scene rectangle.
       
  5129 
       
  5130     \sa QGraphicsView::updateSceneRect()
       
  5131 */
       
  5132 
       
  5133 /*!
       
  5134     \fn QGraphicsScene::selectionChanged()
       
  5135     \since 4.3
       
  5136 
       
  5137     This signal is emitted by QGraphicsScene whenever the selection
       
  5138     changes. You can call selectedItems() to get the new list of selected
       
  5139     items.
       
  5140 
       
  5141     The selection changes whenever an item is selected or unselected, a
       
  5142     selection area is set, cleared or otherwise changed, if a preselected item
       
  5143     is added to the scene, or if a selected item is removed from the scene.
       
  5144 
       
  5145     QGraphicsScene emits this signal only once for group selection operations.
       
  5146     For example, if you set a selection area, select or unselect a
       
  5147     QGraphicsItemGroup, or if you add or remove from the scene a parent item
       
  5148     that contains several selected items, selectionChanged() is emitted only
       
  5149     once after the operation has completed (instead of once for each item).
       
  5150 
       
  5151     \sa setSelectionArea(), selectedItems(), QGraphicsItem::setSelected()
       
  5152 */
       
  5153 
       
  5154 /*!
       
  5155     \since 4.4
       
  5156 
       
  5157     Returns the scene's style, or the same as QApplication::style() if the
       
  5158     scene has not been explicitly assigned a style.
       
  5159 
       
  5160     \sa setStyle()
       
  5161 */
       
  5162 QStyle *QGraphicsScene::style() const
       
  5163 {
       
  5164     Q_D(const QGraphicsScene);
       
  5165     // ### This function, and the use of styles in general, is non-reentrant.
       
  5166     return d->style ? d->style : QApplication::style();
       
  5167 }
       
  5168 
       
  5169 /*!
       
  5170     \since 4.4
       
  5171 
       
  5172     Sets or replaces the style of the scene to \a style, and reparents the
       
  5173     style to this scene. Any previously assigned style is deleted. The scene's
       
  5174     style defaults to QApplication::style(), and serves as the default for all
       
  5175     QGraphicsWidget items in the scene.
       
  5176 
       
  5177     Changing the style, either directly by calling this function, or
       
  5178     indirectly by calling QApplication::setStyle(), will automatically update
       
  5179     the style for all widgets in the scene that do not have a style explicitly
       
  5180     assigned to them.
       
  5181 
       
  5182     If \a style is 0, QGraphicsScene will revert to QApplication::style().
       
  5183 
       
  5184     \sa style()
       
  5185 */
       
  5186 void QGraphicsScene::setStyle(QStyle *style)
       
  5187 {
       
  5188     Q_D(QGraphicsScene);
       
  5189     // ### This function, and the use of styles in general, is non-reentrant.
       
  5190     if (style == d->style)
       
  5191         return;
       
  5192 
       
  5193     // Delete the old style,
       
  5194     delete d->style;
       
  5195     if ((d->style = style))
       
  5196         d->style->setParent(this);
       
  5197 
       
  5198     // Notify the scene.
       
  5199     QEvent event(QEvent::StyleChange);
       
  5200     QApplication::sendEvent(this, &event);
       
  5201 
       
  5202     // Notify all widgets that don't have a style explicitly set.
       
  5203     foreach (QGraphicsItem *item, items()) {
       
  5204         if (item->isWidget()) {
       
  5205             QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
       
  5206             if (!widget->testAttribute(Qt::WA_SetStyle))
       
  5207                 QApplication::sendEvent(widget, &event);
       
  5208         }
       
  5209     }
       
  5210 }
       
  5211 
       
  5212 /*!
       
  5213     \property QGraphicsScene::font
       
  5214     \since 4.4
       
  5215     \brief the scene's default font
       
  5216 
       
  5217     This property provides the scene's font. The scene font defaults to,
       
  5218     and resolves all its entries from, QApplication::font.
       
  5219 
       
  5220     If the scene's font changes, either directly through setFont() or
       
  5221     indirectly when the application font changes, QGraphicsScene first
       
  5222     sends itself a \l{QEvent::FontChange}{FontChange} event, and it then
       
  5223     sends \l{QEvent::FontChange}{FontChange} events to all top-level
       
  5224     widget items in the scene. These items respond by resolving their own
       
  5225     fonts to the scene, and they then notify their children, who again
       
  5226     notify their children, and so on, until all widget items have updated
       
  5227     their fonts.
       
  5228 
       
  5229     Changing the scene font, (directly or indirectly through
       
  5230     QApplication::setFont(),) automatically schedules a redraw the entire
       
  5231     scene.
       
  5232 
       
  5233     \sa QWidget::font, QApplication::setFont(), palette, style()
       
  5234 */
       
  5235 QFont QGraphicsScene::font() const
       
  5236 {
       
  5237     Q_D(const QGraphicsScene);
       
  5238     return d->font;
       
  5239 }
       
  5240 void QGraphicsScene::setFont(const QFont &font)
       
  5241 {
       
  5242     Q_D(QGraphicsScene);
       
  5243     QFont naturalFont = QApplication::font();
       
  5244     naturalFont.resolve(0);
       
  5245     QFont resolvedFont = font.resolve(naturalFont);
       
  5246     d->setFont_helper(resolvedFont);
       
  5247 }
       
  5248 
       
  5249 /*!
       
  5250     \property QGraphicsScene::palette
       
  5251     \since 4.4
       
  5252     \brief the scene's default palette
       
  5253 
       
  5254     This property provides the scene's palette. The scene palette defaults to,
       
  5255     and resolves all its entries from, QApplication::palette.
       
  5256 
       
  5257     If the scene's palette changes, either directly through setPalette() or
       
  5258     indirectly when the application palette changes, QGraphicsScene first
       
  5259     sends itself a \l{QEvent::PaletteChange}{PaletteChange} event, and it then
       
  5260     sends \l{QEvent::PaletteChange}{PaletteChange} events to all top-level
       
  5261     widget items in the scene. These items respond by resolving their own
       
  5262     palettes to the scene, and they then notify their children, who again
       
  5263     notify their children, and so on, until all widget items have updated
       
  5264     their palettes.
       
  5265 
       
  5266     Changing the scene palette, (directly or indirectly through
       
  5267     QApplication::setPalette(),) automatically schedules a redraw the entire
       
  5268     scene.
       
  5269 
       
  5270     \sa QWidget::palette, QApplication::setPalette(), font, style()
       
  5271 */
       
  5272 QPalette QGraphicsScene::palette() const
       
  5273 {
       
  5274     Q_D(const QGraphicsScene);
       
  5275     return d->palette;
       
  5276 }
       
  5277 void QGraphicsScene::setPalette(const QPalette &palette)
       
  5278 {
       
  5279     Q_D(QGraphicsScene);
       
  5280     QPalette naturalPalette = QApplication::palette();
       
  5281     naturalPalette.resolve(0);
       
  5282     QPalette resolvedPalette = palette.resolve(naturalPalette);
       
  5283     d->setPalette_helper(resolvedPalette);
       
  5284 }
       
  5285 
       
  5286 /*!
       
  5287     \since 4.6
       
  5288 
       
  5289     Returns true if the scene is active (e.g., it's viewed by
       
  5290     at least one QGraphicsView that is active); otherwise returns false.
       
  5291 
       
  5292     \sa QGraphicsItem::isActive(), QWidget::isActiveWindow()
       
  5293 */
       
  5294 bool QGraphicsScene::isActive() const
       
  5295 {
       
  5296     Q_D(const QGraphicsScene);
       
  5297     return d->activationRefCount > 0;
       
  5298 }
       
  5299 
       
  5300 /*!
       
  5301     \since 4.6
       
  5302     Returns the current active panel, or 0 if no panel is currently active.
       
  5303 
       
  5304     \sa QGraphicsScene::setActivePanel()
       
  5305 */
       
  5306 QGraphicsItem *QGraphicsScene::activePanel() const
       
  5307 {
       
  5308     Q_D(const QGraphicsScene);
       
  5309     return d->activePanel;
       
  5310 }
       
  5311 
       
  5312 /*!
       
  5313     \since 4.6
       
  5314     Activates \a item, which must be an item in this scene. You
       
  5315     can also pass 0 for \a item, in which case QGraphicsScene will
       
  5316     deactivate any currently active panel.
       
  5317 
       
  5318     If the scene is currently inactive, \a item remains inactive until the
       
  5319     scene becomes active (or, ir \a item is 0, no item will be activated).
       
  5320 
       
  5321     \sa activePanel(), isActive(), QGraphicsItem::isActive()
       
  5322 */
       
  5323 void QGraphicsScene::setActivePanel(QGraphicsItem *item)
       
  5324 {
       
  5325     Q_D(QGraphicsScene);
       
  5326     d->setActivePanelHelper(item, false);
       
  5327 }
       
  5328 
       
  5329 /*!
       
  5330     \since 4.4
       
  5331 
       
  5332     Returns the current active window, or 0 if no window is currently
       
  5333     active.
       
  5334 
       
  5335     \sa QGraphicsScene::setActiveWindow()
       
  5336 */
       
  5337 QGraphicsWidget *QGraphicsScene::activeWindow() const
       
  5338 {
       
  5339     Q_D(const QGraphicsScene);
       
  5340     if (d->activePanel && d->activePanel->isWindow())
       
  5341         return static_cast<QGraphicsWidget *>(d->activePanel);
       
  5342     return 0;
       
  5343 }
       
  5344 
       
  5345 /*!
       
  5346     \since 4.4
       
  5347     Activates \a widget, which must be a widget in this scene. You can also
       
  5348     pass 0 for \a widget, in which case QGraphicsScene will deactivate any
       
  5349     currently active window.
       
  5350 
       
  5351     \sa activeWindow(), QGraphicsWidget::isActiveWindow()
       
  5352 */
       
  5353 void QGraphicsScene::setActiveWindow(QGraphicsWidget *widget)
       
  5354 {
       
  5355     if (widget && widget->scene() != this) {
       
  5356         qWarning("QGraphicsScene::setActiveWindow: widget %p must be part of this scene",
       
  5357                  widget);
       
  5358         return;
       
  5359     }
       
  5360 
       
  5361     // Activate the widget's panel (all windows are panels).
       
  5362     QGraphicsItem *panel = widget ? widget->panel() : 0;
       
  5363     setActivePanel(panel);
       
  5364 
       
  5365     // Raise
       
  5366     if (panel) {
       
  5367         QList<QGraphicsItem *> siblingWindows;
       
  5368         QGraphicsItem *parent = panel->parentItem();
       
  5369         // Raise ### inefficient for toplevels
       
  5370         foreach (QGraphicsItem *sibling, parent ? parent->children() : items()) {
       
  5371             if (sibling != panel && sibling->isWindow())
       
  5372                 siblingWindows << sibling;
       
  5373         }
       
  5374 
       
  5375         // Find the highest z value.
       
  5376         qreal z = panel->zValue();
       
  5377         for (int i = 0; i < siblingWindows.size(); ++i)
       
  5378             z = qMax(z, siblingWindows.at(i)->zValue());
       
  5379 
       
  5380         // This will probably never overflow.
       
  5381         const qreal litt = qreal(0.001);
       
  5382         panel->setZValue(z + litt);
       
  5383     }
       
  5384 }
       
  5385 
       
  5386 /*!
       
  5387     \since 4.6
       
  5388 
       
  5389     Sends event \a event to item \a item through possible event filters.
       
  5390 
       
  5391     The event is sent only if the item is enabled.
       
  5392 
       
  5393     Returns \c false if the event was filtered or if the item is disabled.
       
  5394     Otherwise returns the value that was returned from the event handler.
       
  5395 
       
  5396     \sa QGraphicsItem::sceneEvent(), QGraphicsItem::sceneEventFilter()
       
  5397 */
       
  5398 bool QGraphicsScene::sendEvent(QGraphicsItem *item, QEvent *event)
       
  5399 {
       
  5400     Q_D(QGraphicsScene);
       
  5401     if (!item) {
       
  5402         qWarning("QGraphicsScene::sendEvent: cannot send event to a null item");
       
  5403         return false;
       
  5404     }
       
  5405     if (item->scene() != this) {
       
  5406         qWarning("QGraphicsScene::sendEvent: item %p's scene (%p)"
       
  5407                  " is different from this scene (%p)",
       
  5408                  item, item->scene(), this);
       
  5409         return false;
       
  5410     }
       
  5411     return d->sendEvent(item, event);
       
  5412 }
       
  5413 
       
  5414 void QGraphicsScenePrivate::addView(QGraphicsView *view)
       
  5415 {
       
  5416     views << view;
       
  5417 }
       
  5418 
       
  5419 void QGraphicsScenePrivate::removeView(QGraphicsView *view)
       
  5420 {
       
  5421     views.removeAll(view);
       
  5422 }
       
  5423 
       
  5424 void QGraphicsScenePrivate::updateTouchPointsForItem(QGraphicsItem *item, QTouchEvent *touchEvent)
       
  5425 {
       
  5426     QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints();
       
  5427     for (int i = 0; i < touchPoints.count(); ++i) {
       
  5428         QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
       
  5429         touchPoint.setRect(item->mapFromScene(touchPoint.sceneRect()).boundingRect());
       
  5430         touchPoint.setStartPos(item->d_ptr->genericMapFromScene(touchPoint.startScenePos(), touchEvent->widget()));
       
  5431         touchPoint.setLastPos(item->d_ptr->genericMapFromScene(touchPoint.lastScenePos(), touchEvent->widget()));
       
  5432     }
       
  5433     touchEvent->setTouchPoints(touchPoints);
       
  5434 }
       
  5435 
       
  5436 int QGraphicsScenePrivate::findClosestTouchPointId(const QPointF &scenePos)
       
  5437 {
       
  5438     int closestTouchPointId = -1;
       
  5439     qreal closestDistance = qreal(0.);
       
  5440     foreach (const QTouchEvent::TouchPoint &touchPoint, sceneCurrentTouchPoints) {
       
  5441         qreal distance = QLineF(scenePos, touchPoint.scenePos()).length();
       
  5442         if (closestTouchPointId == -1|| distance < closestDistance) {
       
  5443             closestTouchPointId = touchPoint.id();
       
  5444             closestDistance = distance;
       
  5445         }
       
  5446     }
       
  5447     return closestTouchPointId;
       
  5448 }
       
  5449 
       
  5450 void QGraphicsScenePrivate::touchEventHandler(QTouchEvent *sceneTouchEvent)
       
  5451 {
       
  5452     typedef QPair<Qt::TouchPointStates, QList<QTouchEvent::TouchPoint> > StatesAndTouchPoints;
       
  5453     QHash<QGraphicsItem *, StatesAndTouchPoints> itemsNeedingEvents;
       
  5454 
       
  5455     for (int i = 0; i < sceneTouchEvent->touchPoints().count(); ++i) {
       
  5456         const QTouchEvent::TouchPoint &touchPoint = sceneTouchEvent->touchPoints().at(i);
       
  5457 
       
  5458         // update state
       
  5459         QGraphicsItem *item = 0;
       
  5460         if (touchPoint.state() == Qt::TouchPointPressed) {
       
  5461             if (sceneTouchEvent->deviceType() == QTouchEvent::TouchPad) {
       
  5462                 // on touch-pad devices, send all touch points to the same item
       
  5463                 item = itemForTouchPointId.isEmpty()
       
  5464                        ? 0
       
  5465                        : itemForTouchPointId.constBegin().value();
       
  5466             }
       
  5467 
       
  5468             if (!item) {
       
  5469                 // determine which item this touch point will go to
       
  5470                 cachedItemsUnderMouse = itemsAtPosition(touchPoint.screenPos().toPoint(),
       
  5471                                                         touchPoint.scenePos(),
       
  5472                                                         sceneTouchEvent->widget());
       
  5473                 item = cachedItemsUnderMouse.isEmpty() ? 0 : cachedItemsUnderMouse.first();
       
  5474             }
       
  5475 
       
  5476             if (sceneTouchEvent->deviceType() == QTouchEvent::TouchScreen) {
       
  5477                 // on touch-screens, combine this touch point with the closest one we find if it
       
  5478                 // is a a direct descendent or ancestor (
       
  5479                 int closestTouchPointId = findClosestTouchPointId(touchPoint.scenePos());
       
  5480                 QGraphicsItem *closestItem = itemForTouchPointId.value(closestTouchPointId);
       
  5481                 if (!item
       
  5482                     || (closestItem
       
  5483                         && (item->isAncestorOf(closestItem)
       
  5484                             || closestItem->isAncestorOf(item)))) {
       
  5485                     item = closestItem;
       
  5486                 }
       
  5487             }
       
  5488             if (!item)
       
  5489                 continue;
       
  5490 
       
  5491             itemForTouchPointId.insert(touchPoint.id(), item);
       
  5492             sceneCurrentTouchPoints.insert(touchPoint.id(), touchPoint);
       
  5493         } else if (touchPoint.state() == Qt::TouchPointReleased) {
       
  5494             item = itemForTouchPointId.take(touchPoint.id());
       
  5495             if (!item)
       
  5496                 continue;
       
  5497 
       
  5498             sceneCurrentTouchPoints.remove(touchPoint.id());
       
  5499         } else {
       
  5500             item = itemForTouchPointId.value(touchPoint.id());
       
  5501             if (!item)
       
  5502                 continue;
       
  5503             Q_ASSERT(sceneCurrentTouchPoints.contains(touchPoint.id()));
       
  5504             sceneCurrentTouchPoints[touchPoint.id()] = touchPoint;
       
  5505         }
       
  5506 
       
  5507         StatesAndTouchPoints &statesAndTouchPoints = itemsNeedingEvents[item];
       
  5508         statesAndTouchPoints.first |= touchPoint.state();
       
  5509         statesAndTouchPoints.second.append(touchPoint);
       
  5510     }
       
  5511 
       
  5512     if (itemsNeedingEvents.isEmpty()) {
       
  5513         sceneTouchEvent->accept();
       
  5514         return;
       
  5515     }
       
  5516 
       
  5517     bool ignoreSceneTouchEvent = true;
       
  5518     QHash<QGraphicsItem *, StatesAndTouchPoints>::ConstIterator it = itemsNeedingEvents.constBegin();
       
  5519     const QHash<QGraphicsItem *, StatesAndTouchPoints>::ConstIterator end = itemsNeedingEvents.constEnd();
       
  5520     for (; it != end; ++it) {
       
  5521         QGraphicsItem *item = it.key();
       
  5522 
       
  5523         (void) item->isBlockedByModalPanel(&item);
       
  5524 
       
  5525         // determine event type from the state mask
       
  5526         QEvent::Type eventType;
       
  5527         switch (it.value().first) {
       
  5528         case Qt::TouchPointPressed:
       
  5529             // all touch points have pressed state
       
  5530             eventType = QEvent::TouchBegin;
       
  5531             break;
       
  5532         case Qt::TouchPointReleased:
       
  5533             // all touch points have released state
       
  5534             eventType = QEvent::TouchEnd;
       
  5535             break;
       
  5536         case Qt::TouchPointStationary:
       
  5537             // don't send the event if nothing changed
       
  5538             continue;
       
  5539         default:
       
  5540             // all other combinations
       
  5541             eventType = QEvent::TouchUpdate;
       
  5542             break;
       
  5543         }
       
  5544 
       
  5545         QTouchEvent touchEvent(eventType);
       
  5546         touchEvent.setWidget(sceneTouchEvent->widget());
       
  5547         touchEvent.setDeviceType(sceneTouchEvent->deviceType());
       
  5548         touchEvent.setModifiers(sceneTouchEvent->modifiers());
       
  5549         touchEvent.setTouchPointStates(it.value().first);
       
  5550         touchEvent.setTouchPoints(it.value().second);
       
  5551 
       
  5552         switch (touchEvent.type()) {
       
  5553         case QEvent::TouchBegin:
       
  5554         {
       
  5555             // if the TouchBegin handler recurses, we assume that means the event
       
  5556             // has been implicitly accepted and continue to send touch events
       
  5557             item->d_ptr->acceptedTouchBeginEvent = true;
       
  5558             bool res = sendTouchBeginEvent(item, &touchEvent)
       
  5559                        && touchEvent.isAccepted();
       
  5560             if (!res)
       
  5561                 ignoreSceneTouchEvent = false;
       
  5562             break;
       
  5563         }
       
  5564         default:
       
  5565             if (item->d_ptr->acceptedTouchBeginEvent) {
       
  5566                 updateTouchPointsForItem(item, &touchEvent);
       
  5567                 (void) sendEvent(item, &touchEvent);
       
  5568                 ignoreSceneTouchEvent = false;
       
  5569             }
       
  5570             break;
       
  5571         }
       
  5572     }
       
  5573     sceneTouchEvent->setAccepted(ignoreSceneTouchEvent);
       
  5574 }
       
  5575 
       
  5576 bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEvent *touchEvent)
       
  5577 {
       
  5578     Q_Q(QGraphicsScene);
       
  5579 
       
  5580     if (cachedItemsUnderMouse.isEmpty() || cachedItemsUnderMouse.first() != origin) {
       
  5581         const QTouchEvent::TouchPoint &firstTouchPoint = touchEvent->touchPoints().first();
       
  5582         cachedItemsUnderMouse = itemsAtPosition(firstTouchPoint.screenPos().toPoint(),
       
  5583                                                 firstTouchPoint.scenePos(),
       
  5584                                                 touchEvent->widget());
       
  5585     }
       
  5586     Q_ASSERT(cachedItemsUnderMouse.first() == origin);
       
  5587 
       
  5588     // Set focus on the topmost enabled item that can take focus.
       
  5589     bool setFocus = false;
       
  5590     foreach (QGraphicsItem *item, cachedItemsUnderMouse) {
       
  5591         if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) {
       
  5592             if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) {
       
  5593                 setFocus = true;
       
  5594                 if (item != q->focusItem())
       
  5595                     q->setFocusItem(item, Qt::MouseFocusReason);
       
  5596                 break;
       
  5597             }
       
  5598         }
       
  5599         if (item->isPanel())
       
  5600             break;
       
  5601     }
       
  5602 
       
  5603     // If nobody could take focus, clear it.
       
  5604     if (!stickyFocus && !setFocus)
       
  5605         q->setFocusItem(0, Qt::MouseFocusReason);
       
  5606 
       
  5607     bool res = false;
       
  5608     bool eventAccepted = touchEvent->isAccepted();
       
  5609     foreach (QGraphicsItem *item, cachedItemsUnderMouse) {
       
  5610         // first, try to deliver the touch event
       
  5611         updateTouchPointsForItem(item, touchEvent);
       
  5612         bool acceptTouchEvents = item->acceptTouchEvents();
       
  5613         touchEvent->setAccepted(acceptTouchEvents);
       
  5614         res = acceptTouchEvents && sendEvent(item, touchEvent);
       
  5615         eventAccepted = touchEvent->isAccepted();
       
  5616         item->d_ptr->acceptedTouchBeginEvent = (res && eventAccepted);
       
  5617         touchEvent->spont = false;
       
  5618         if (res && eventAccepted) {
       
  5619             // the first item to accept the TouchBegin gets an implicit grab.
       
  5620             for (int i = 0; i < touchEvent->touchPoints().count(); ++i) {
       
  5621                 const QTouchEvent::TouchPoint &touchPoint = touchEvent->touchPoints().at(i);
       
  5622                 itemForTouchPointId[touchPoint.id()] = item;
       
  5623             }
       
  5624             break;
       
  5625         }
       
  5626         if (item->isPanel())
       
  5627             break;
       
  5628     }
       
  5629 
       
  5630     touchEvent->setAccepted(eventAccepted);
       
  5631     return res;
       
  5632 }
       
  5633 
       
  5634 void QGraphicsScenePrivate::enableTouchEventsOnViews()
       
  5635 {
       
  5636     foreach (QGraphicsView *view, views)
       
  5637         view->viewport()->setAttribute(Qt::WA_AcceptTouchEvents, true);
       
  5638 }
       
  5639 
       
  5640 void QGraphicsScenePrivate::updateInputMethodSensitivityInViews()
       
  5641 {
       
  5642     for (int i = 0; i < views.size(); ++i)
       
  5643         views.at(i)->d_func()->updateInputMethodSensitivity();
       
  5644 }
       
  5645 
       
  5646 void QGraphicsScenePrivate::enterModal(QGraphicsItem *panel, QGraphicsItem::PanelModality previousModality)
       
  5647 {
       
  5648     Q_Q(QGraphicsScene);
       
  5649     Q_ASSERT(panel && panel->isPanel());
       
  5650 
       
  5651     QGraphicsItem::PanelModality panelModality = panel->d_ptr->panelModality;
       
  5652     if (previousModality != QGraphicsItem::NonModal) {
       
  5653         // the panel is changing from one modality type to another... temporarily set it back so
       
  5654         // that blockedPanels is populated correctly
       
  5655         panel->d_ptr->panelModality = previousModality;
       
  5656     }
       
  5657 
       
  5658     QSet<QGraphicsItem *> blockedPanels;
       
  5659     QList<QGraphicsItem *> items = q->items(); // ### store panels separately
       
  5660     for (int i = 0; i < items.count(); ++i) {
       
  5661         QGraphicsItem *item = items.at(i);
       
  5662         if (item->isPanel() && item->isBlockedByModalPanel())
       
  5663             blockedPanels.insert(item);
       
  5664     }
       
  5665     // blockedPanels contains all currently blocked panels
       
  5666 
       
  5667     if (previousModality != QGraphicsItem::NonModal) {
       
  5668         // reset the modality to the proper value, since we changed it above
       
  5669         panel->d_ptr->panelModality = panelModality;
       
  5670         // remove this panel so that it will be reinserted at the front of the stack
       
  5671         modalPanels.removeAll(panel);
       
  5672     }
       
  5673 
       
  5674     modalPanels.prepend(panel);
       
  5675 
       
  5676     if (!hoverItems.isEmpty()) {
       
  5677         // send GraphicsSceneHoverLeave events to newly blocked hoverItems
       
  5678         QGraphicsSceneHoverEvent hoverEvent;
       
  5679         hoverEvent.setScenePos(lastSceneMousePos);
       
  5680         dispatchHoverEvent(&hoverEvent);
       
  5681     }
       
  5682 
       
  5683     if (!mouseGrabberItems.isEmpty() && lastMouseGrabberItemHasImplicitMouseGrab) {
       
  5684         QGraphicsItem *item = mouseGrabberItems.last();
       
  5685         if (item->isBlockedByModalPanel())
       
  5686             ungrabMouse(item, /*itemIsDying =*/ false);
       
  5687     }
       
  5688 
       
  5689     QEvent windowBlockedEvent(QEvent::WindowBlocked);
       
  5690     QEvent windowUnblockedEvent(QEvent::WindowUnblocked);
       
  5691     for (int i = 0; i < items.count(); ++i) {
       
  5692         QGraphicsItem *item = items.at(i);
       
  5693         if (item->isPanel()) {
       
  5694             if (!blockedPanels.contains(item) && item->isBlockedByModalPanel()) {
       
  5695                 // send QEvent::WindowBlocked to newly blocked panels
       
  5696                 sendEvent(item, &windowBlockedEvent);
       
  5697             } else if (blockedPanels.contains(item) && !item->isBlockedByModalPanel()) {
       
  5698                 // send QEvent::WindowUnblocked to unblocked panels when downgrading
       
  5699                 // a panel from SceneModal to PanelModal
       
  5700                 sendEvent(item, &windowUnblockedEvent);
       
  5701             }
       
  5702         }
       
  5703     }
       
  5704 }
       
  5705 
       
  5706 void QGraphicsScenePrivate::leaveModal(QGraphicsItem *panel)
       
  5707 {
       
  5708     Q_Q(QGraphicsScene);
       
  5709     Q_ASSERT(panel && panel->isPanel());
       
  5710 
       
  5711     QSet<QGraphicsItem *> blockedPanels;
       
  5712     QList<QGraphicsItem *> items = q->items(); // ### same as above
       
  5713     for (int i = 0; i < items.count(); ++i) {
       
  5714         QGraphicsItem *item = items.at(i);
       
  5715         if (item->isPanel() && item->isBlockedByModalPanel())
       
  5716             blockedPanels.insert(item);
       
  5717     }
       
  5718 
       
  5719     modalPanels.removeAll(panel);
       
  5720 
       
  5721     QEvent e(QEvent::WindowUnblocked);
       
  5722     for (int i = 0; i < items.count(); ++i) {
       
  5723         QGraphicsItem *item = items.at(i);
       
  5724         if (item->isPanel() && blockedPanels.contains(item) && !item->isBlockedByModalPanel())
       
  5725             sendEvent(item, &e);
       
  5726     }
       
  5727 
       
  5728     // send GraphicsSceneHoverEnter events to newly unblocked items
       
  5729     QGraphicsSceneHoverEvent hoverEvent;
       
  5730     hoverEvent.setScenePos(lastSceneMousePos);
       
  5731     dispatchHoverEvent(&hoverEvent);
       
  5732 }
       
  5733 
       
  5734 void QGraphicsScenePrivate::getGestureTargets(const QSet<QGesture *> &gestures,
       
  5735                                               QWidget *viewport,
       
  5736                                               QMap<Qt::GestureType, QGesture *> *conflictedGestures,
       
  5737                                               QList<QList<QGraphicsObject *> > *conflictedItems,
       
  5738                                               QHash<QGesture *, QGraphicsObject *> *normalGestures)
       
  5739 {
       
  5740     foreach (QGesture *gesture, gestures) {
       
  5741         Qt::GestureType gestureType = gesture->gestureType();
       
  5742         if (gesture->hasHotSpot()) {
       
  5743             QPoint screenPos = gesture->hotSpot().toPoint();
       
  5744             QList<QGraphicsItem *> items = itemsAtPosition(screenPos, QPointF(), viewport);
       
  5745             QList<QGraphicsObject *> result;
       
  5746             for (int j = 0; j < items.size(); ++j) {
       
  5747                 QGraphicsObject *item = items.at(j)->toGraphicsObject();
       
  5748                 if (!item)
       
  5749                     continue;
       
  5750                 QGraphicsItemPrivate *d = item->QGraphicsItem::d_func();
       
  5751                 if (d->gestureContext.contains(gestureType)) {
       
  5752                     result.append(item);
       
  5753                 }
       
  5754             }
       
  5755             DEBUG() << "QGraphicsScenePrivate::getGestureTargets:"
       
  5756                     << gesture << result;
       
  5757             if (result.size() == 1) {
       
  5758                 normalGestures->insert(gesture, result.first());
       
  5759             } else if (!result.isEmpty()) {
       
  5760                 conflictedGestures->insert(gestureType, gesture);
       
  5761                 conflictedItems->append(result);
       
  5762             }
       
  5763         }
       
  5764     }
       
  5765 }
       
  5766 
       
  5767 void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event)
       
  5768 {
       
  5769     QWidget *viewport = event->widget();
       
  5770     if (!viewport)
       
  5771         return;
       
  5772     QList<QGesture *> allGestures = event->allGestures();
       
  5773     DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
       
  5774             << "Delivering gestures:" <<  allGestures;
       
  5775 
       
  5776     typedef QHash<QGraphicsObject *, QList<QGesture *> > GesturesPerItem;
       
  5777     GesturesPerItem gesturesPerItem;
       
  5778 
       
  5779     QSet<QGesture *> startedGestures;
       
  5780     foreach (QGesture *gesture, allGestures) {
       
  5781         QGraphicsObject *target = gestureTargets.value(gesture, 0);
       
  5782         if (!target) {
       
  5783             // when we are not in started mode but don't have a target
       
  5784             // then the only one interested in gesture is the view/scene
       
  5785             if (gesture->state() == Qt::GestureStarted)
       
  5786                 startedGestures.insert(gesture);
       
  5787         } else {
       
  5788             gesturesPerItem[target].append(gesture);
       
  5789         }
       
  5790     }
       
  5791 
       
  5792     QMap<Qt::GestureType, QGesture *> conflictedGestures;
       
  5793     QList<QList<QGraphicsObject *> > conflictedItems;
       
  5794     QHash<QGesture *, QGraphicsObject *> normalGestures;
       
  5795     getGestureTargets(startedGestures, viewport, &conflictedGestures, &conflictedItems,
       
  5796                       &normalGestures);
       
  5797     DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
       
  5798             << "Conflicting gestures:" <<  conflictedGestures.values() << conflictedItems;
       
  5799     Q_ASSERT((conflictedGestures.isEmpty() && conflictedItems.isEmpty()) ||
       
  5800               (!conflictedGestures.isEmpty() && !conflictedItems.isEmpty()));
       
  5801 
       
  5802     // gestures that were sent as override events, but no one accepted them
       
  5803     QHash<QGesture *, QGraphicsObject *> ignoredConflictedGestures;
       
  5804 
       
  5805     // deliver conflicted gestures as override events first
       
  5806     while (!conflictedGestures.isEmpty() && !conflictedItems.isEmpty()) {
       
  5807         // get the topmost item to deliver the override event
       
  5808         Q_ASSERT(!conflictedItems.isEmpty());
       
  5809         Q_ASSERT(!conflictedItems.first().isEmpty());
       
  5810         QGraphicsObject *topmost = conflictedItems.first().first();
       
  5811         for (int i = 1; i < conflictedItems.size(); ++i) {
       
  5812             QGraphicsObject *item = conflictedItems.at(i).first();
       
  5813             if (qt_closestItemFirst(item, topmost)) {
       
  5814                 topmost = item;
       
  5815             }
       
  5816         }
       
  5817         // get a list of gestures to send to the item
       
  5818         QList<Qt::GestureType> grabbedGestures =
       
  5819                 topmost->QGraphicsItem::d_func()->gestureContext.keys();
       
  5820         QList<QGesture *> gestures;
       
  5821         for (int i = 0; i < grabbedGestures.size(); ++i) {
       
  5822             if (QGesture *g = conflictedGestures.value(grabbedGestures.at(i), 0)) {
       
  5823                 gestures.append(g);
       
  5824                 if (!ignoredConflictedGestures.contains(g))
       
  5825                     ignoredConflictedGestures.insert(g, topmost);
       
  5826             }
       
  5827         }
       
  5828 
       
  5829         // send gesture override to the topmost item
       
  5830         QGestureEvent ev(gestures);
       
  5831         ev.t = QEvent::GestureOverride;
       
  5832         ev.setWidget(event->widget());
       
  5833         // mark event and individual gestures as ignored
       
  5834         ev.ignore();
       
  5835         foreach(QGesture *g, gestures)
       
  5836             ev.setAccepted(g, false);
       
  5837         DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
       
  5838                 << "delivering override to"
       
  5839                 << topmost << gestures;
       
  5840         sendEvent(topmost, &ev);
       
  5841         // mark all accepted gestures to deliver them as normal gesture events
       
  5842         foreach (QGesture *g, gestures) {
       
  5843             if (ev.isAccepted() || ev.isAccepted(g)) {
       
  5844                 conflictedGestures.remove(g->gestureType());
       
  5845                 gestureTargets.remove(g);
       
  5846                 // add the gesture to the list of normal delivered gestures
       
  5847                 normalGestures.insert(g, topmost);
       
  5848                 DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
       
  5849                         << "override was accepted:"
       
  5850                         << g << topmost;
       
  5851                 ignoredConflictedGestures.remove(g);
       
  5852             }
       
  5853         }
       
  5854         // remove the item that we've already delivered from the list
       
  5855         for (int i = 0; i < conflictedItems.size(); ) {
       
  5856             QList<QGraphicsObject *> &items = conflictedItems[i];
       
  5857             if (items.first() == topmost) {
       
  5858                 items.removeFirst();
       
  5859                 if (items.isEmpty()) {
       
  5860                     conflictedItems.removeAt(i);
       
  5861                     continue;
       
  5862                 }
       
  5863             }
       
  5864             ++i;
       
  5865         }
       
  5866     }
       
  5867 
       
  5868     // put back those started gestures that are not in the conflicted state
       
  5869     // and remember their targets
       
  5870     QHash<QGesture *, QGraphicsObject *>::const_iterator it = normalGestures.begin(),
       
  5871                                                           e = normalGestures.end();
       
  5872     for (; it != e; ++it) {
       
  5873         QGesture *g = it.key();
       
  5874         QGraphicsObject *receiver = it.value();
       
  5875         Q_ASSERT(!gestureTargets.contains(g));
       
  5876         gestureTargets.insert(g, receiver);
       
  5877         gesturesPerItem[receiver].append(g);
       
  5878     }
       
  5879     it = ignoredConflictedGestures.begin();
       
  5880     e = ignoredConflictedGestures.end();
       
  5881     for (; it != e; ++it) {
       
  5882         QGesture *g = it.key();
       
  5883         QGraphicsObject *receiver = it.value();
       
  5884         Q_ASSERT(!gestureTargets.contains(g));
       
  5885         gestureTargets.insert(g, receiver);
       
  5886         gesturesPerItem[receiver].append(g);
       
  5887     }
       
  5888 
       
  5889     DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
       
  5890             << "Started gestures:" << normalGestures.keys()
       
  5891             << "All gestures:" << gesturesPerItem.values();
       
  5892 
       
  5893     // deliver all events
       
  5894     QList<QGesture *> alreadyIgnoredGestures;
       
  5895     QHash<QGraphicsObject *, QSet<QGesture *> > itemIgnoredGestures;
       
  5896     QList<QGraphicsObject *> targetItems = gesturesPerItem.keys();
       
  5897     qSort(targetItems.begin(), targetItems.end(), qt_closestItemFirst);
       
  5898     for (int i = 0; i < targetItems.size(); ++i) {
       
  5899         QGraphicsObject *item = targetItems.at(i);
       
  5900         QList<QGesture *> gestures = gesturesPerItem.value(item);
       
  5901         // remove gestures that were already delivered once and were ignored
       
  5902         DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
       
  5903                 << "already ignored gestures for item"
       
  5904                 << item << ":" << itemIgnoredGestures.value(item);
       
  5905 
       
  5906         if (itemIgnoredGestures.contains(item)) // don't deliver twice to the same item
       
  5907             continue;
       
  5908 
       
  5909         QGraphicsItemPrivate *gid = item->QGraphicsItem::d_func();
       
  5910         foreach(QGesture *g, alreadyIgnoredGestures) {
       
  5911             if (gid->gestureContext.contains(g->gestureType()))
       
  5912                 gestures += g;
       
  5913         }
       
  5914         if (gestures.isEmpty())
       
  5915             continue;
       
  5916         DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
       
  5917                 << "delivering to"
       
  5918                 << item << gestures;
       
  5919         QGestureEvent ev(gestures);
       
  5920         ev.setWidget(event->widget());
       
  5921         sendEvent(item, &ev);
       
  5922         QSet<QGesture *> ignoredGestures;
       
  5923         foreach (QGesture *g, gestures) {
       
  5924             if (!ev.isAccepted() && !ev.isAccepted(g))
       
  5925                 ignoredGestures.insert(g);
       
  5926         }
       
  5927         if (!ignoredGestures.isEmpty()) {
       
  5928             // get a list of items under the (current) hotspot of each ignored
       
  5929             // gesture and start delivery again from the beginning
       
  5930             DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
       
  5931                     << "item has ignored the event, will propagate."
       
  5932                     << item << ignoredGestures;
       
  5933             itemIgnoredGestures[item] += ignoredGestures;
       
  5934             QMap<Qt::GestureType, QGesture *> conflictedGestures;
       
  5935             QList<QList<QGraphicsObject *> > itemsForConflictedGestures;
       
  5936             QHash<QGesture *, QGraphicsObject *> normalGestures;
       
  5937             getGestureTargets(ignoredGestures, viewport,
       
  5938                               &conflictedGestures, &itemsForConflictedGestures,
       
  5939                               &normalGestures);
       
  5940             QSet<QGraphicsObject *> itemsSet = targetItems.toSet();
       
  5941             for (int k = 0; k < itemsForConflictedGestures.size(); ++k)
       
  5942                 itemsSet += itemsForConflictedGestures.at(k).toSet();
       
  5943             targetItems = itemsSet.toList();
       
  5944             qSort(targetItems.begin(), targetItems.end(), qt_closestItemFirst);
       
  5945             alreadyIgnoredGestures = conflictedGestures.values();
       
  5946             DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
       
  5947                     << "new targets:" << targetItems;
       
  5948             i = -1; // start delivery again
       
  5949             continue;
       
  5950         }
       
  5951     }
       
  5952 
       
  5953     // forget about targets for gestures that have ended
       
  5954     foreach (QGesture *g, allGestures) {
       
  5955         switch (g->state()) {
       
  5956         case Qt::GestureFinished:
       
  5957         case Qt::GestureCanceled:
       
  5958             gestureTargets.remove(g);
       
  5959             break;
       
  5960         default:
       
  5961             break;
       
  5962         }
       
  5963     }
       
  5964 }
       
  5965 
       
  5966 QT_END_NAMESPACE
       
  5967 
       
  5968 #include "moc_qgraphicsscene.cpp"
       
  5969 
       
  5970 #endif // QT_NO_GRAPHICSVIEW