Ignore:
Timestamp:
Feb 11, 2010, 11:19:06 PM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.6.1 sources.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/gui/graphicsview/qgraphicsitem.cpp

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information (qt-info@nokia.com)
     4** All rights reserved.
     5** Contact: Nokia Corporation (qt-info@nokia.com)
    56**
    67** This file is part of the QtGui module of the Qt Toolkit.
     
    2122** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
    2223**
    23 ** In addition, as a special exception, Nokia gives you certain
    24 ** additional rights. These rights are described in the Nokia Qt LGPL
    25 ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
    26 ** package.
     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.
    2727**
    2828** GNU General Public License Usage
     
    3434** met: http://www.gnu.org/copyleft/gpl.html.
    3535**
    36 ** If you are unsure which license is appropriate for your use, please
    37 ** contact the sales department at qt-sales@nokia.com.
     36** If you have questions regarding the use of this file, please contact
     37** Nokia at qt-info@nokia.com.
    3838** $QT_END_LICENSE$
    3939**
     
    4545    items in a QGraphicsScene.
    4646    \since 4.2
    47     \ingroup multimedia
     47
    4848    \ingroup graphicsview-api
    4949
     
    5353    QGraphicsItem is part of \l{The Graphics View Framework}
    5454
    55     \img graphicsview-items.png
     55    \image graphicsview-items.png
    5656
    5757    For convenience, Qt provides a set of standard graphics items for the most
     
    9292    \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 0
    9393
    94     The boundingRect() function has many different purposes. QGraphicsScene
    95     bases its item index on boundingRect(), and QGraphicsView uses it both for
    96     culling invisible items, and for determining the area that needs to be
    97     recomposed when drawing overlapping items. In addition, QGraphicsItem's
    98     collision detection mechanisms use boundingRect() to provide an efficient
    99     cut-off. The fine grained collision algorithm in collidesWithItem() is based
    100     on calling shape(), which returns an accurate outline of the item's shape
    101     as a QPainterPath.
    102 
    103     QGraphicsScene expects all items boundingRect() and shape() to remain
    104     unchanged unless it is notified. If you want to change an item's geometry
    105     in any way, you must first call prepareGeometryChange() to allow
    106     QGraphicsScene to update its bookkeeping.
     94    The boundingRect() function has many different purposes.
     95    QGraphicsScene bases its item index on boundingRect(), and
     96    QGraphicsView uses it both for culling invisible items, and for
     97    determining the area that needs to be recomposed when drawing
     98    overlapping items. In addition, QGraphicsItem's collision
     99    detection mechanisms use boundingRect() to provide an efficient
     100    cut-off. The fine grained collision algorithm in
     101    collidesWithItem() is based on calling shape(), which returns an
     102    accurate outline of the item's shape as a QPainterPath.
     103
     104    QGraphicsScene expects all items boundingRect() and shape() to
     105    remain unchanged unless it is notified. If you want to change an
     106    item's geometry in any way, you must first call
     107    prepareGeometryChange() to allow QGraphicsScene to update its
     108    bookkeeping.
    107109
    108110    Collision detection can be done in two ways:
     
    110112    \list 1
    111113
    112     \o Reimplement shape() to return an accurate shape for your item, and rely
    113     on the default implementation of collidesWithItem() to do shape-shape
    114     intersection. This can be rather expensive if the shapes are complex.
    115 
    116     \o Reimplement collidesWithItem() to provide your own custom item and shape
    117     collision algorithm.
     114    \o Reimplement shape() to return an accurate shape for your item,
     115    and rely on the default implementation of collidesWithItem() to do
     116    shape-shape intersection. This can be rather expensive if the
     117    shapes are complex.
     118
     119    \o Reimplement collidesWithItem() to provide your own custom item
     120    and shape collision algorithm.
    118121
    119122    \endlist
     
    131134    \img graphicsview-parentchild.png
    132135
    133     QGraphicsItem supports affine transformations in addition to its base
    134     position, pos(). To change the item's transformation, you can either pass
    135     a transformation matrix to setTransform(), or call one of the convenience
    136     functions rotate(), scale(), translate(), or shear(). Item transformations
    137     accumulate from parent to child, so if both a parent and child item are
    138     rotated 90 degrees, the child's total transformation will be 180 degrees.
    139     Similarly, if the item's parent is scaled to 2x its original size, its
    140     children will also be twice as large. An item's transformation does not
    141     affect its own local geometry; all geometry functions (e.g., contains(),
    142     update(), and all the mapping functions) still operate in local
    143     coordinates. For convenience, QGraphicsItem provides the functions
    144     sceneTransform(), which returns the item's total transformation matrix
    145     (including its position and all parents' positions and transformations),
    146     and scenePos(), which returns its position in scene coordinates. To reset
    147     an item's matrix, call resetTransform().
     136    \section1 Transformation
     137
     138    QGraphicsItem supports projective transformations in addition to its base
     139    position, pos(). There are several ways to change an item's transformation.
     140    For simple transformations, you can call either of the convenience
     141    functions setRotation() or setScale(), or you can pass any transformation
     142    matrix to setTransform(). For advanced transformation control you also have
     143    the option of setting several combined transformations by calling
     144    setTransformations().
     145
     146    Item transformations accumulate from parent to child, so if both a parent
     147    and child item are rotated 90 degrees, the child's total transformation
     148    will be 180 degrees. Similarly, if the item's parent is scaled to 2x its
     149    original size, its children will also be twice as large. An item's
     150    transformation does not affect its own local geometry; all geometry
     151    functions (e.g., contains(), update(), and all the mapping functions) still
     152    operate in local coordinates. For convenience, QGraphicsItem provides the
     153    functions sceneTransform(), which returns the item's total transformation
     154    matrix (including its position and all parents' positions and
     155    transformations), and scenePos(), which returns its position in scene
     156    coordinates. To reset an item's matrix, call resetTransform().
     157
     158    Certain transformation operations produce a different outcome depending on
     159    the order in which they are applied. For example, if you scale an
     160    transform, and then rotate it, you may get a different result than if the
     161    transform was rotated first. However, the order you set the transformation
     162    properties on QGraphicsItem does not affect the resulting transformation;
     163    QGraphicsItem always applies the properties in a fixed, defined order:
     164
     165    \list
     166    \o The item's base transform is applied (transform())
     167    \o The item's transformations list is applied in order (transformations())
     168    \o The item is rotated relative to its transform origin point (rotation(), transformOriginPoint())
     169    \o The item is scaled relative to its transform origin point (scale(), transformOriginPoint())
     170    \endlist
     171
     172    \section1 Painting
    148173
    149174    The paint() function is called by QGraphicsView to paint the item's
     
    162187    drawn before their children.
    163188
     189    \section1 Sorting
     190
     191    All items are drawn in a defined, stable order, and this same order decides
     192    which items will receive mouse input first when you click on the scene.
     193    Normally you don't have to worry about sorting, as the items follow a
     194    "natural order", following the logical structure of the scene.
     195
     196    An item's children are stacked on top of the parent, and sibling items are
     197    stacked by insertion order (i.e., in the same order that they were either
     198    added to the scene, or added to the same parent). If you add item A, and
     199    then B, then B will be on top of A. If you then add C, the items' stacking
     200    order will be A, then B, then C.
     201
     202    \image graphicsview-zorder.png
     203
     204    This example shows the stacking order of all limbs of the robot from the
     205    \l{graphicsview/dragdroprobot}{Drag and Drop Robot} example. The torso is
     206    the root item (all other items are children or descendants of the torso),
     207    so it is drawn first. Next, the head is drawn, as it is the first item in
     208    the torso's list of children. Then the upper left arm is drawn. As the
     209    lower arm is a child of the upper arm, the lower arm is then drawn,
     210    followed by the upper arm's next sibling, which is the upper right arm, and
     211    so on.
     212
     213    For advanced users, there are ways to alter how your items are sorted:
     214
     215    \list
     216    \o You can call setZValue() on an item to explicitly stack it on top of, or
     217    under, other sibling items. The default Z value for an item is 0. Items
     218    with the same Z value are stacked by insertion order.
     219
     220    \o You can call stackBefore() to reorder the list of children. This will
     221    directly modify the insertion order.
     222
     223    \o You can set the ItemStacksBehindParent flag to stack a child item behind
     224    its parent.
     225    \endlist
     226
     227    The stacking order of two sibling items also counts for each item's
     228    children and descendant items. So if one item is on top of another, then
     229    all its children will also be on top of all the other item's children as
     230    well.
     231
     232    \section1 Events
     233
    164234    QGraphicsItem receives events from QGraphicsScene through the virtual
    165235    function sceneEvent(). This function distributes the most common events
     
    172242    hover enter, move and leave events
    173243    \o inputMethodEvent() handles input events, for accessibility support
    174     \o keyPressEvent() and keyReleaseEvent handle key press and release events
     244    \o keyPressEvent() and keyReleaseEvent() handle key press and release events
    175245    \o mousePressEvent(), mouseMoveEvent(), mouseReleaseEvent(), and
    176246    mouseDoubleClickEvent() handles mouse press, move, release, click and
     
    178248    \endlist
    179249
    180     You can filter events for any other item by installing event
    181     filters. This functionaly is separate from from Qt's regular
    182     event filters (see QObject::installEventFilter()), which only
    183     work on subclasses of QObject. After installing your item as an
    184     event filter for another item by calling
    185     installSceneEventFilter(), the filtered events will be received
    186     by the virtual function sceneEventFilter(). You can remove item
    187     event filters by calling removeSceneEventFilter().
     250    You can filter events for any other item by installing event filters. This
     251    functionality is separate from Qt's regular event filters (see
     252    QObject::installEventFilter()), which only work on subclasses of QObject. After
     253    installing your item as an event filter for another item by calling
     254    installSceneEventFilter(), the filtered events will be received by the virtual
     255    function sceneEventFilter(). You can remove item event filters by calling
     256    removeSceneEventFilter().
     257
     258    \section1 Custom Data
    188259
    189260    Sometimes it's useful to register custom data with an item, be it a custom
     
    275346    drop shadow effects and for decoration objects that follow the parent
    276347    item's geometry without drawing on top of it.
     348
     349    \value ItemUsesExtendedStyleOption The item makes use of either
     350    \l{QStyleOptionGraphicsItem::}{exposedRect} or
     351    \l{QStyleOptionGraphicsItem::}{matrix} in QStyleOptionGraphicsItem. By default,
     352    the \l{QStyleOptionGraphicsItem::}{exposedRect} is initialized to the item's
     353    boundingRect() and the \l{QStyleOptionGraphicsItem::}{matrix} is untransformed.
     354    You can enable this flag for the style options to be set up with more
     355    fine-grained values.
     356    Note that QStyleOptionGraphicsItem::levelOfDetail is unaffected by this flag
     357    and always initialized to 1. Use
     358    QStyleOptionGraphicsItem::levelOfDetailFromTransform() if you need a higher
     359    value.
     360
     361    \value ItemHasNoContents The item does not paint anything (i.e., calling
     362    paint() on the item has no effect). You should set this flag on items that
     363    do not need to be painted to ensure that Graphics View avoids unnecessary
     364    painting preparations. This flag was introduced in Qt 4.6.
     365
     366    \value ItemSendsGeometryChanges The item enables itemChange()
     367    notifications for ItemPositionChange, ItemPositionHasChanged,
     368    ItemMatrixChange, ItemTransformChange, and ItemTransformHasChanged. For
     369    performance reasons, these notifications are disabled by default. You must
     370    enable this flag to receive notifications for position and transform
     371    changes. This flag was introduced in Qt 4.6.
     372
     373    \value ItemAcceptsInputMethod The item supports input methods typically
     374    used for Asian languages.
     375    This flag was introduced in Qt 4.6.
     376
     377    \value ItemNegativeZStacksBehindParent The item automatically stacks behind
     378    it's parent if it's z-value is negative. This flag enables setZValue() to
     379    toggle ItemStacksBehindParent.
     380
     381    \value ItemIsPanel The item is a panel. A panel provides activation and
     382    contained focus handling. Only one panel can be active at a time (see
     383    QGraphicsItem::isActive()). When no panel is active, QGraphicsScene
     384    activates all non-panel items. Window items (i.e.,
     385    QGraphicsItem::isWindow() returns true) are panels. This flag was
     386    introduced in Qt 4.6.
     387
     388    \omitvalue ItemIsFocusScope \omit Internal only (for now). \endomit
     389
     390    \value ItemSendsScenePositionChanges The item enables itemChange()
     391    notifications for ItemScenePositionHasChanged. For performance reasons,
     392    these notifications are disabled by default. You must enable this flag
     393    to receive notifications for scene position changes. This flag was
     394    introduced in Qt 4.6.
    277395*/
    278396
     
    313431
    314432    \value ItemPositionChange The item's position changes. This notification
    315     is only sent when the item's local position changes, relative to its
    316     parent, has changed (i.e., as a result of calling setPos() or
    317     moveBy()). The value argument is the new position (i.e., a QPointF).  You
    318     can call pos() to get the original position. Do not call setPos() or
    319     moveBy() in itemChange() as this notification is delivered; instead, you
    320     can return the new, adjusted position from itemChange(). After this
    321     notification, QGraphicsItem immediately sends the ItemPositionHasChanged
    322     notification if the position changed.
     433    is sent if the ItemSendsGeometryChanges flag is enabled, and when the
     434    item's local position changes, relative to its parent (i.e., as a result
     435    of calling setPos() or moveBy()). The value argument is the new position
     436    (i.e., a QPointF).  You can call pos() to get the original position. Do
     437    not call setPos() or moveBy() in itemChange() as this notification is
     438    delivered; instead, you can return the new, adjusted position from
     439    itemChange(). After this notification, QGraphicsItem immediately sends the
     440    ItemPositionHasChanged notification if the position changed.
    323441
    324442    \value ItemPositionHasChanged The item's position has changed. This
    325     notification is only sent after the item's local position, relative to its
    326     parent, has changed. The value argument is the new position (the same as
    327     pos()), and QGraphicsItem ignores the return value for this notification
    328     (i.e., a read-only notification).
     443    notification is sent if the ItemSendsGeometryChanges flag is enabled, and
     444    after the item's local position, relative to its parent, has changed. The
     445    value argument is the new position (the same as pos()), and QGraphicsItem
     446    ignores the return value for this notification (i.e., a read-only
     447    notification).
    329448
    330449    \value ItemTransformChange The item's transformation matrix changes. This
    331     notification is only sent when the item's local transformation matrix
    332     changes (i.e., as a result of calling setTransform(), or one of the
    333     convenience transformation functions, such as rotate()). The value
    334     argument is the new matrix (i.e., a QTransform); to get the old matrix,
    335     call transform(). Do not call setTransform() or any of the transformation
    336     convenience functions in itemChange() as this notification is delivered;
    337     instead, you can return the new matrix from itemChange().
     450    notification is send if the ItemSendsGeometryChanges flag is enabled, and
     451    when the item's local transformation matrix changes (i.e., as a result of
     452    calling setTransform(). The value argument is the new matrix (i.e., a
     453    QTransform); to get the old matrix, call transform(). Do not call
     454    setTransform() or set any of the transformation properties in itemChange()
     455    as this notification is delivered; instead, you can return the new matrix
     456    from itemChange().  This notification is not sent if you change the
     457    transformation properties.
    338458
    339459    \value ItemTransformHasChanged The item's transformation matrix has
    340     changed.  This notification is only sent after the item's local
    341     trasformation matrix has changed. The value argument is the new matrix
     460    changed either because setTransform is called, or one of the
     461    transformation properties is changed. This notification is sent if the
     462    ItemSendsGeometryChanges flag is enabled, and after the item's local
     463    transformation matrix has changed. The value argument is the new matrix
    342464    (same as transform()), and QGraphicsItem ignores the return value for this
    343465    notification (i.e., a read-only notification).
    344466
    345     \value ItemSelectedChange The item's selected state changes. If the item
    346     is presently selected, it will become unselected, and vice verca. The
    347     value argument is the new selected state (i.e., true or false). Do not
    348     call setSelected() in itemChange() as this notification is delivered();
    349     instead, you can return the new selected state from itemChange().
     467    \value ItemSelectedChange The item's selected state changes. If the item is
     468    presently selected, it will become unselected, and vice verca. The value
     469    argument is the new selected state (i.e., true or false). Do not call
     470    setSelected() in itemChange() as this notification is delivered; instead, you
     471    can return the new selected state from itemChange().
    350472
    351473    \value ItemSelectedHasChanged The item's selected state has changed. The
     
    447569    argument is the new opacity (i.e., a double). Do not call setOpacity() as
    448570    this notification is delivered. The return value is ignored.
     571
     572    \value ItemScenePositionHasChanged The item's scene position has changed.
     573    This notification is sent if the ItemSendsScenePositionChanges flag is
     574    enabled, and after the item's scene position has changed (i.e., the
     575    position or transformation of the item itself or the position or
     576    transformation of any ancestor has changed). The value argument is the
     577    new scene position (the same as scenePos()), and QGraphicsItem ignores
     578    the return value for this notification (i.e., a read-only notification).
    449579*/
    450580
     
    492622*/
    493623
     624/*!
     625    \enum QGraphicsItem::PanelModality
     626    \since 4.6
     627
     628    This enum specifies the behavior of a modal panel. A modal panel
     629    is one that blocks input to other panels. Note that items that
     630    are children of a modal panel are not blocked.
     631
     632    The values are:
     633    \value NonModal   The panel is not modal and does not block input to other panels.
     634    \value PanelModal The panel is modal to a single item hierarchy and blocks input to its parent pane, all grandparent panels, and all siblings of its parent and grandparent panels.
     635    \value SceneModal The window is modal to the entire scene and blocks input to all panels.
     636
     637    \sa QGraphicsItem::setPanelModality(), QGraphicsItem::panelModality(), QGraphicsItem::ItemIsPanel
     638*/
     639
    494640#include "qgraphicsitem.h"
    495641
     
    502648#include "qgraphicswidget.h"
    503649#include "qgraphicsproxywidget.h"
     650#include "qgraphicsscenebsptreeindex_p.h"
    504651#include <QtCore/qbitarray.h>
    505652#include <QtCore/qdebug.h>
     
    516663#include <QtGui/qstyleoption.h>
    517664#include <QtGui/qevent.h>
     665#include <QtGui/qinputcontext.h>
     666#include <QtGui/qgraphicseffect.h>
    518667
    519668#include <private/qgraphicsitem_p.h>
     
    522671#include <private/qtextdocumentlayout_p.h>
    523672#include <private/qtextengine_p.h>
     673#include <private/qwidget_p.h>
     674
     675#ifdef Q_WS_X11
     676#include <private/qt_x11_p.h>
     677#include <private/qpixmap_x11_p.h>
     678#endif
     679
     680#include <private/qgesturemanager_p.h>
    524681
    525682#include <math.h>
    526683
    527684QT_BEGIN_NAMESPACE
    528 
    529 // QRectF::intersects() returns false always if either the source or target
    530 // rectangle's width or height are 0. This works around that problem.
    531 static inline void _q_adjustRect(QRectF *rect)
    532 {
    533     Q_ASSERT(rect);
    534     if (!rect->width())
    535         rect->adjust(-0.00001, 0, 0.00001, 0);
    536     if (!rect->height())
    537         rect->adjust(0, -0.00001, 0, 0.00001);
    538 }
    539685
    540686static inline void _q_adjustRect(QRect *rect)
     
    556702};
    557703Q_GLOBAL_STATIC(QGraphicsItemCustomDataStore, qt_dataStore)
    558 
    559 /*!
    560     \internal
    561 
    562     Removes the first instance of \a child from \a children. This is a
    563     heuristic approach that assumes that it's common to remove items from the
    564     start or end of the list.
    565 */
    566 static void qt_graphicsitem_removeChild(QGraphicsItem *child, QList<QGraphicsItem *> *children)
    567 {
    568     const int n = children->size();
    569     for (int i = 0; i < (n + 1) / 2; ++i) {
    570         if (children->at(i) == child) {
    571             children->removeAt(i);
    572             return;
    573         }
    574         int j = n - i - 1;
    575         if (children->at(j) == child) {
    576             children->removeAt(j);
    577             return;
    578         }
    579     }
    580 }
    581704
    582705/*!
     
    622745        // disabled \a childFlag, or has been reparented.
    623746        switch (int(childFlag)) {
     747        case -2:
     748            flag = AncestorFiltersChildEvents;
     749            enabled = q->filtersChildEvents();
     750            break;
    624751        case -1:
    625752            flag = AncestorHandlesChildEvents;
     
    629756            flag = AncestorClipsChildren;
    630757            enabled = flags & QGraphicsItem::ItemClipsChildrenToShape;
    631             invalidateCachedClipPathRecursively(/*childrenOnly=*/true);
    632758            break;
    633759        case QGraphicsItem::ItemIgnoresTransformations:
     
    639765        }
    640766
    641         // Inherit the enabled-state from our parents.
    642         if ((parent && ((parent->d_ptr->ancestorFlags & flag)
    643                         || (int(parent->d_ptr->flags & childFlag) == childFlag)
    644                         || (childFlag == -1 && parent->d_ptr->handlesChildEvents)))) {
    645             enabled = true;
    646             ancestorFlags |= flag;
     767        if (parent) {
     768            // Inherit the enabled-state from our parents.
     769            if ((parent->d_ptr->ancestorFlags & flag)
     770                    || (int(parent->d_ptr->flags & childFlag) == childFlag)
     771                        || (childFlag == -1 && parent->d_ptr->handlesChildEvents)
     772                        || (childFlag == -2 && parent->d_ptr->filtersDescendantEvents)) {
     773                enabled = true;
     774                ancestorFlags |= flag;
     775            } else {
     776                ancestorFlags &= ~flag;
     777            }
     778        } else {
     779            // Top-level root items don't have any ancestors, so there are no
     780            // ancestor flags either.
     781            ancestorFlags = 0;
    647782        }
    648 
    649         // Top-level root items don't have any ancestors, so there are no
    650         // ancestor flags either.
    651         if (!parent)
    652             ancestorFlags = 0;
    653783    } else {
    654784        // Don't set or propagate the ancestor flag if it's already correct.
     
    663793
    664794        // Don't process children if the item has the main flag set on itself.
    665         if ((childFlag != -1 &&  int(flags & childFlag) == childFlag) || (int(childFlag) == -1 && handlesChildEvents))
     795        if ((childFlag != -1 &&  int(flags & childFlag) == childFlag)
     796            || (int(childFlag) == -1 && handlesChildEvents)
     797            || (int(childFlag) == -2 && filtersDescendantEvents))
    666798            return;
    667799    }
     
    755887    \internal
    756888
    757     Returns true if this item or any of its ancestors are untransformable.
    758 */
    759 bool QGraphicsItemPrivate::itemIsUntransformable() const
    760 {
    761     return (flags & QGraphicsItem::ItemIgnoresTransformations)
    762         || (ancestorFlags & AncestorIgnoresTransformations);
     889    Combines this item's position and transform onto \a transform.
     890
     891    If you need to change this function (e.g., adding more transformation
     892    modes / options), make sure to change all places marked with COMBINE.
     893*/
     894void QGraphicsItemPrivate::combineTransformToParent(QTransform *x, const QTransform *viewTransform) const
     895{
     896    // COMBINE
     897    if (viewTransform && itemIsUntransformable()) {
     898        *x = q_ptr->deviceTransform(*viewTransform);
     899    } else {
     900        if (transformData)
     901            *x *= transformData->computedFullTransform();
     902        if (!pos.isNull())
     903            *x *= QTransform::fromTranslate(pos.x(), pos.y());
     904    }
     905}
     906
     907/*!
     908    \internal
     909
     910    Combines this item's position and transform onto \a transform.
     911
     912    If you need to change this function (e.g., adding more transformation
     913    modes / options), make sure to change QGraphicsItem::deviceTransform() as
     914    well.
     915*/
     916void QGraphicsItemPrivate::combineTransformFromParent(QTransform *x, const QTransform *viewTransform) const
     917{
     918    // COMBINE
     919    if (viewTransform && itemIsUntransformable()) {
     920        *x = q_ptr->deviceTransform(*viewTransform);
     921    } else {
     922        x->translate(pos.x(), pos.y());
     923        if (transformData)
     924            *x = transformData->computedFullTransform(x);
     925    }
     926}
     927
     928void QGraphicsItemPrivate::updateSceneTransformFromParent()
     929{
     930    if (parent) {
     931        Q_ASSERT(!parent->d_ptr->dirtySceneTransform);
     932        if (parent->d_ptr->sceneTransformTranslateOnly) {
     933            sceneTransform = QTransform::fromTranslate(parent->d_ptr->sceneTransform.dx() + pos.x(),
     934                                                       parent->d_ptr->sceneTransform.dy() + pos.y());
     935        } else {
     936            sceneTransform = parent->d_ptr->sceneTransform;
     937            sceneTransform.translate(pos.x(), pos.y());
     938        }
     939        if (transformData) {
     940            sceneTransform = transformData->computedFullTransform(&sceneTransform);
     941            sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate);
     942        } else {
     943            sceneTransformTranslateOnly = parent->d_ptr->sceneTransformTranslateOnly;
     944        }
     945    } else if (!transformData) {
     946        sceneTransform = QTransform::fromTranslate(pos.x(), pos.y());
     947        sceneTransformTranslateOnly = 1;
     948    } else if (transformData->onlyTransform) {
     949        sceneTransform = transformData->transform;
     950        if (!pos.isNull())
     951            sceneTransform *= QTransform::fromTranslate(pos.x(), pos.y());
     952        sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate);
     953    } else if (pos.isNull()) {
     954        sceneTransform = transformData->computedFullTransform();
     955        sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate);
     956    } else {
     957        sceneTransform = QTransform::fromTranslate(pos.x(), pos.y());
     958        sceneTransform = transformData->computedFullTransform(&sceneTransform);
     959        sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate);
     960    }
     961    dirtySceneTransform = 0;
    763962}
    764963
     
    782981    \internal
    783982
     983    Make sure not to trigger any pure virtual function calls (e.g.,
     984    prepareGeometryChange) if the item is in its destructor, i.e.
     985    inDestructor is 1.
     986*/
     987void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent)
     988{
     989    Q_Q(QGraphicsItem);
     990    if (newParent == q) {
     991        qWarning("QGraphicsItem::setParentItem: cannot assign %p as a parent of itself", this);
     992        return;
     993    }
     994    if (newParent == parent)
     995        return;
     996
     997    const QVariant newParentVariant(q->itemChange(QGraphicsItem::ItemParentChange,
     998                                                  qVariantFromValue<QGraphicsItem *>(newParent)));
     999    newParent = qVariantValue<QGraphicsItem *>(newParentVariant);
     1000    if (newParent == parent)
     1001        return;
     1002
     1003    if (scene) {
     1004        // Deliver the change to the index
     1005        scene->d_func()->index->itemChange(q, QGraphicsItem::ItemParentChange, newParentVariant);
     1006
     1007        // Disable scene pos notifications for old ancestors
     1008        if (scenePosDescendants || (flags & QGraphicsItem::ItemSendsScenePositionChanges))
     1009            scene->d_func()->setScenePosItemEnabled(q, false);
     1010    }
     1011
     1012    if (subFocusItem && parent) {
     1013        // Make sure none of the old parents point to this guy.
     1014        subFocusItem->d_ptr->clearSubFocus(parent);
     1015    }
     1016
     1017    // We anticipate geometry changes. If the item is deleted, it will be
     1018    // removed from the index at a later stage, and the whole scene will be
     1019    // updated.
     1020    if (!inDestructor)
     1021        q_ptr->prepareGeometryChange();
     1022
     1023    const QVariant thisPointerVariant(qVariantFromValue<QGraphicsItem *>(q));
     1024    if (parent) {
     1025        // Remove from current parent
     1026        parent->d_ptr->removeChild(q);
     1027        parent->itemChange(QGraphicsItem::ItemChildRemovedChange, thisPointerVariant);
     1028    }
     1029
     1030    // Update toplevelitem list. If this item is being deleted, its parent
     1031    // will be 0 but we don't want to register/unregister it in the TLI list.
     1032    if (scene && !inDestructor) {
     1033        if (parent && !newParent) {
     1034            scene->d_func()->registerTopLevelItem(q);
     1035        } else if (!parent && newParent) {
     1036            scene->d_func()->unregisterTopLevelItem(q);
     1037        }
     1038    }
     1039
     1040    // Ensure any last parent focus scope does not point to this item or any of
     1041    // its descendents.
     1042    QGraphicsItem *p = parent;
     1043    QGraphicsItem *parentFocusScopeItem = 0;
     1044    while (p) {
     1045        if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
     1046            // If this item's focus scope's focus scope item points
     1047            // to this item or a descendent, then clear it.
     1048            QGraphicsItem *fsi = p->d_ptr->focusScopeItem;
     1049            if (q_ptr == fsi || q_ptr->isAncestorOf(fsi)) {
     1050                parentFocusScopeItem = fsi;
     1051                p->d_ptr->focusScopeItem = 0;
     1052            }
     1053            break;
     1054        }
     1055        p = p->d_ptr->parent;
     1056    }
     1057
     1058    // Update focus scope item ptr in new scope.
     1059    QGraphicsItem *newFocusScopeItem = subFocusItem ? subFocusItem : parentFocusScopeItem;
     1060    if (newFocusScopeItem && newParent) {
     1061        if (subFocusItem) {
     1062            // Find the subFocusItem's topmost focus scope.
     1063            QGraphicsItem *ancestorScope = 0;
     1064            QGraphicsItem *p = subFocusItem->d_ptr->parent;
     1065            while (p) {
     1066                if (p->flags() & QGraphicsItem::ItemIsFocusScope)
     1067                    ancestorScope = p;
     1068                if (p->isPanel())
     1069                    break;
     1070                p = p->parentItem();
     1071            }
     1072            if (ancestorScope)
     1073                newFocusScopeItem = ancestorScope;
     1074        }
     1075
     1076        QGraphicsItem *p = newParent;
     1077        while (p) {
     1078            if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
     1079                p->d_ptr->focusScopeItem = newFocusScopeItem;
     1080                // Ensure the new item is no longer the subFocusItem. The
     1081                // only way to set focus on a child of a focus scope is
     1082                // by setting focus on the scope itself.
     1083                if (subFocusItem && !p->focusItem())
     1084                    subFocusItem->d_ptr->clearSubFocus();
     1085                break;
     1086            }
     1087            p = p->d_ptr->parent;
     1088        }
     1089    }
     1090
     1091    if ((parent = newParent)) {
     1092        bool implicitUpdate = false;
     1093        if (parent->d_func()->scene && parent->d_func()->scene != scene) {
     1094            // Move this item to its new parent's scene
     1095            parent->d_func()->scene->addItem(q);
     1096            implicitUpdate = true;
     1097        } else if (!parent->d_func()->scene && scene) {
     1098            // Remove this item from its former scene
     1099            scene->removeItem(q);
     1100        }
     1101
     1102        parent->d_ptr->addChild(q);
     1103        parent->itemChange(QGraphicsItem::ItemChildAddedChange, thisPointerVariant);
     1104        if (scene) {
     1105            if (!implicitUpdate)
     1106                scene->d_func()->markDirty(q_ptr);
     1107
     1108            // Re-enable scene pos notifications for new ancestors
     1109            if (scenePosDescendants || (flags & QGraphicsItem::ItemSendsScenePositionChanges))
     1110                scene->d_func()->setScenePosItemEnabled(q, true);
     1111        }
     1112
     1113        // Inherit ancestor flags from the new parent.
     1114        updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2));
     1115        updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
     1116        updateAncestorFlag(QGraphicsItem::ItemClipsChildrenToShape);
     1117        updateAncestorFlag(QGraphicsItem::ItemIgnoresTransformations);
     1118
     1119        // Update item visible / enabled.
     1120        if (parent->isVisible() != visible) {
     1121            if (!parent->isVisible() || !explicitlyHidden)
     1122                setVisibleHelper(parent->isVisible(), /* explicit = */ false, /* update = */ !implicitUpdate);
     1123        }
     1124        if (parent->isEnabled() != enabled) {
     1125            if (!parent->isEnabled() || !explicitlyDisabled)
     1126                setEnabledHelper(parent->isEnabled(), /* explicit = */ false, /* update = */ !implicitUpdate);
     1127        }
     1128
     1129        // Auto-activate if visible and the parent is active.
     1130        if (q->isVisible() && parent->isActive())
     1131            q->setActive(true);
     1132    } else {
     1133        // Inherit ancestor flags from the new parent.
     1134        updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2));
     1135        updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
     1136        updateAncestorFlag(QGraphicsItem::ItemClipsChildrenToShape);
     1137        updateAncestorFlag(QGraphicsItem::ItemIgnoresTransformations);
     1138
     1139        if (!inDestructor) {
     1140            // Update item visible / enabled.
     1141            if (!visible && !explicitlyHidden)
     1142                setVisibleHelper(true, /* explicit = */ false);
     1143            if (!enabled && !explicitlyDisabled)
     1144                setEnabledHelper(true, /* explicit = */ false);
     1145
     1146            // If the item is being deleted, the whole scene will be updated.
     1147            if (scene)
     1148                scene->d_func()->markDirty(q_ptr);
     1149        }
     1150    }
     1151
     1152    // Resolve depth.
     1153    invalidateDepthRecursively();
     1154    dirtySceneTransform = 1;
     1155
     1156    // Restore the sub focus chain.
     1157    if (subFocusItem) {
     1158        subFocusItem->d_ptr->setSubFocus(newParent);
     1159        if (parent && parent->isActive())
     1160            subFocusItem->setFocus();
     1161    }
     1162
     1163    // Deliver post-change notification
     1164    q->itemChange(QGraphicsItem::ItemParentHasChanged, newParentVariant);
     1165
     1166    if (isObject)
     1167        emit static_cast<QGraphicsObject *>(q)->parentChanged();
     1168}
     1169
     1170/*!
     1171    \internal
     1172
     1173    Returns the bounding rect of this item's children (excluding itself).
     1174*/
     1175void QGraphicsItemPrivate::childrenBoundingRectHelper(QTransform *x, QRectF *rect)
     1176{
     1177    for (int i = 0; i < children.size(); ++i) {
     1178        QGraphicsItem *child = children.at(i);
     1179        QGraphicsItemPrivate *childd = child->d_ptr.data();
     1180        bool hasPos = !childd->pos.isNull();
     1181        if (hasPos || childd->transformData) {
     1182            // COMBINE
     1183            QTransform matrix = childd->transformToParent();
     1184            if (x)
     1185                matrix *= *x;
     1186            *rect |= matrix.mapRect(child->boundingRect());
     1187            if (!childd->children.isEmpty())
     1188                childd->childrenBoundingRectHelper(&matrix, rect);
     1189        } else {
     1190            if (x)
     1191                *rect |= x->mapRect(child->boundingRect());
     1192            else
     1193                *rect |= child->boundingRect();
     1194            if (!childd->children.isEmpty())
     1195                childd->childrenBoundingRectHelper(x, rect);
     1196        }
     1197    }
     1198}
     1199
     1200void QGraphicsItemPrivate::initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform,
     1201                                           const QRegion &exposedRegion, bool allItems) const
     1202{
     1203    Q_ASSERT(option);
     1204    Q_Q(const QGraphicsItem);
     1205
     1206    // Initialize standard QStyleOption values.
     1207    const QRectF brect = q->boundingRect();
     1208    option->state = QStyle::State_None;
     1209    option->rect = brect.toRect();
     1210    option->levelOfDetail = 1;
     1211    option->exposedRect = brect;
     1212    if (selected)
     1213        option->state |= QStyle::State_Selected;
     1214    if (enabled)
     1215        option->state |= QStyle::State_Enabled;
     1216    if (q->hasFocus())
     1217        option->state |= QStyle::State_HasFocus;
     1218    if (scene) {
     1219        if (scene->d_func()->hoverItems.contains(q_ptr))
     1220            option->state |= QStyle::State_MouseOver;
     1221        if (q == scene->mouseGrabberItem())
     1222            option->state |= QStyle::State_Sunken;
     1223    }
     1224
     1225    if (!(flags & QGraphicsItem::ItemUsesExtendedStyleOption))
     1226        return;
     1227
     1228    // Initialize QStyleOptionGraphicsItem specific values (matrix, exposedRect).
     1229    option->matrix = worldTransform.toAffine(); //### discards perspective
     1230
     1231    if (!allItems) {
     1232        // Determine the item's exposed area
     1233        option->exposedRect = QRectF();
     1234        const QTransform reverseMap = worldTransform.inverted();
     1235        const QVector<QRect> exposedRects(exposedRegion.rects());
     1236        for (int i = 0; i < exposedRects.size(); ++i) {
     1237            option->exposedRect |= reverseMap.mapRect(QRectF(exposedRects.at(i)));
     1238            if (option->exposedRect.contains(brect))
     1239                break;
     1240        }
     1241        option->exposedRect &= brect;
     1242    }
     1243}
     1244
     1245/*!
     1246    \internal
     1247
    7841248    Empty all cached pixmaps from the pixmap cache.
    7851249*/
     
    7871251{
    7881252    QPixmapCache::remove(key);
     1253    key = QPixmapCache::Key();
    7891254    QMutableMapIterator<QPaintDevice *, DeviceData> it(deviceData);
    7901255    while (it.hasNext()) {
     
    7991264
    8001265/*!
    801     Constructs a QGraphicsItem with the given \a parent.
     1266    Constructs a QGraphicsItem with the given \a parent item.
     1267    It does not modify the parent object returned by QObject::parent().
    8021268
    8031269    If \a parent is 0, you can add the item to a scene by calling
     
    8511317    associated with a scene, the item will be removed from the scene before it
    8521318    is deleted.
     1319
     1320    \note It is more efficient to remove the item from the QGraphicsScene before
     1321    destroying the item.
    8531322*/
    8541323QGraphicsItem::~QGraphicsItem()
    8551324{
     1325    if (d_ptr->isObject)
     1326        QObjectPrivate::get(static_cast<QGraphicsObject *>(this))->wasDeleted = true;
     1327    d_ptr->inDestructor = 1;
     1328    d_ptr->removeExtraItemCache();
     1329
    8561330    clearFocus();
    857     d_ptr->removeExtraItemCache();
    858 
    859     QVariant variant;
    860     foreach (QGraphicsItem *child, d_ptr->children) {
    861         if (QGraphicsItem *parent = child->parentItem()) {
    862             qVariantSetValue<QGraphicsItem *>(variant, child);
    863             parent->itemChange(ItemChildRemovedChange, variant);
     1331
     1332    // Update focus scope item ptr.
     1333    QGraphicsItem *p = d_ptr->parent;
     1334    while (p) {
     1335        if (p->flags() & ItemIsFocusScope) {
     1336            if (p->d_ptr->focusScopeItem == this)
     1337                p->d_ptr->focusScopeItem = 0;
     1338            break;
    8641339        }
    865         delete child;
    866     }
    867     d_ptr->children.clear();
    868 
    869     if (QGraphicsItem *parent = parentItem()) {
    870         qVariantSetValue<QGraphicsItem *>(variant, this);
    871         parent->itemChange(ItemChildRemovedChange, variant);
    872         qt_graphicsitem_removeChild(this, &parent->d_func()->children);
    873     }
    874     if (d_ptr->scene)
    875         d_ptr->scene->d_func()->_q_removeItemLater(this);
    876 
    877     delete d_ptr;
     1340        p = p->d_ptr->parent;
     1341    }
     1342
     1343    if (!d_ptr->children.isEmpty()) {
     1344        while (!d_ptr->children.isEmpty())
     1345            delete d_ptr->children.first();
     1346        Q_ASSERT(d_ptr->children.isEmpty());
     1347    }
     1348
     1349    if (d_ptr->scene) {
     1350        d_ptr->scene->d_func()->removeItemHelper(this);
     1351    } else {
     1352        d_ptr->resetFocusProxy();
     1353        d_ptr->setParentItemHelper(0);
     1354    }
     1355
     1356#ifndef QT_NO_GRAPHICSEFFECT
     1357    delete d_ptr->graphicsEffect;
     1358#endif //QT_NO_GRAPHICSEFFECT
     1359    if (d_ptr->transformData) {
     1360        for(int i = 0; i < d_ptr->transformData->graphicsTransforms.size(); ++i) {
     1361            QGraphicsTransform *t = d_ptr->transformData->graphicsTransforms.at(i);
     1362            static_cast<QGraphicsTransformPrivate *>(t->d_ptr.data())->item = 0;
     1363            delete t;
     1364        }
     1365    }
     1366    delete d_ptr->transformData;
    8781367
    8791368    qt_dataStore()->data.remove(this);
     
    9321421    parent, 0 is returned.
    9331422
    934     \sa setParentItem(), children()
     1423    \sa setParentItem(), childItems()
    9351424*/
    9361425QGraphicsItem *QGraphicsItem::parentItem() const
     
    9551444
    9561445/*!
     1446    \since 4.6
     1447
     1448    Returns a pointer to the item's parent, cast to a QGraphicsObject. returns 0 if the parent item
     1449    is not a QGraphicsObject.
     1450
     1451    \sa parentItem(), childItems()
     1452*/
     1453QGraphicsObject *QGraphicsItem::parentObject() const
     1454{
     1455    QGraphicsItem *p = d_ptr->parent;
     1456    return (p && p->d_ptr->isObject) ? static_cast<QGraphicsObject *>(p) : 0;
     1457}
     1458
     1459/*!
    9571460    \since 4.4
    9581461
     
    9961499QGraphicsWidget *QGraphicsItem::window() const
    9971500{
    998     if (isWidget() && static_cast<const QGraphicsWidget *>(this)->isWindow())
    999         return static_cast<QGraphicsWidget *>(const_cast<QGraphicsItem *>(this));
    1000     if (QGraphicsWidget *parent = parentWidget())
    1001         return parent->window();
     1501    QGraphicsItem *p = panel();
     1502    if (p && p->isWindow())
     1503        return static_cast<QGraphicsWidget *>(p);
    10021504    return 0;
     1505}
     1506
     1507/*!
     1508    \since 4.6
     1509
     1510    Returns the item's panel, or 0 if this item does not have a panel. If the
     1511    item is a panel, it will return itself. Otherwise it will return the
     1512    closest ancestor that is a panel.
     1513
     1514    \sa isPanel(), ItemIsPanel
     1515*/
     1516QGraphicsItem *QGraphicsItem::panel() const
     1517{
     1518    if (d_ptr->flags & ItemIsPanel)
     1519        return const_cast<QGraphicsItem *>(this);
     1520    return d_ptr->parent ? d_ptr->parent->panel() : 0;
     1521}
     1522
     1523/*!
     1524  \since 4.6
     1525
     1526  Return the graphics item cast to a QGraphicsObject, if the class is actually a
     1527  graphics object, 0 otherwise.
     1528*/
     1529QGraphicsObject *QGraphicsItem::toGraphicsObject()
     1530{
     1531    return d_ptr->isObject ? static_cast<QGraphicsObject *>(this) : 0;
     1532}
     1533
     1534/*!
     1535  \since 4.6
     1536
     1537  Return the graphics item cast to a QGraphicsObject, if the class is actually a
     1538  graphics object, 0 otherwise.
     1539*/
     1540const QGraphicsObject *QGraphicsItem::toGraphicsObject() const
     1541{
     1542    return d_ptr->isObject ? static_cast<const QGraphicsObject *>(this) : 0;
    10031543}
    10041544
     
    10121552    item to the scene yourself.
    10131553
    1014     \sa parentItem(), children()
     1554    Calling this function on an item that is an ancestor of \a parent have undefined behaviour.
     1555
     1556    \sa parentItem(), childItems()
    10151557*/
    10161558void QGraphicsItem::setParentItem(QGraphicsItem *parent)
    10171559{
    1018     if (parent == this) {
    1019         qWarning("QGraphicsItem::setParentItem: cannot assign %p as a parent of itself", this);
    1020         return;
    1021     }
    1022     if (parent == d_ptr->parent)
    1023         return;
    1024     const QVariant newParentVariant(itemChange(ItemParentChange, qVariantFromValue<QGraphicsItem *>(parent)));
    1025     parent = qVariantValue<QGraphicsItem *>(newParentVariant);
    1026     if (parent == d_ptr->parent)
    1027         return;
    1028 
    1029     if (QGraphicsWidget *w = d_ptr->isWidget ? static_cast<QGraphicsWidget *>(this) : parentWidget()) {
    1030         // Update the child focus chain; when reparenting a widget that has a
    1031         // focus child, ensure that that focus child clears its focus child
    1032         // chain from our parents before it's reparented.
    1033         if (QGraphicsWidget *focusChild = w->focusWidget())
    1034             focusChild->clearFocus();
    1035     }
    1036 
    1037     // We anticipate geometry changes
    1038     prepareGeometryChange();
    1039 
    1040     const QVariant thisPointerVariant(qVariantFromValue<QGraphicsItem *>(this));
    1041     if (d_ptr->parent) {
    1042         // Remove from current parent
    1043         qt_graphicsitem_removeChild(this, &d_ptr->parent->d_func()->children);
    1044         d_ptr->parent->itemChange(ItemChildRemovedChange, thisPointerVariant);
    1045     }
    1046 
    1047     if ((d_ptr->parent = parent)) {
    1048         bool implicitUpdate = false;
    1049         if (parent->d_func()->scene && parent->d_func()->scene != d_ptr->scene) {
    1050             // Move this item to its new parent's scene
    1051             parent->d_func()->scene->addItem(this);
    1052             implicitUpdate = true;
    1053         } else if (!parent->d_func()->scene && d_ptr->scene) {
    1054             // Remove this item from its former scene
    1055             d_ptr->scene->removeItem(this);
    1056         }
    1057 
    1058         d_ptr->parent->d_func()->children << this;
    1059         d_ptr->parent->itemChange(ItemChildAddedChange, thisPointerVariant);
    1060         if (!implicitUpdate)
    1061             d_ptr->updateHelper(QRectF(), false, true);
    1062 
    1063         // Inherit ancestor flags from the new parent.
    1064         d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
    1065         d_ptr->updateAncestorFlag(ItemClipsChildrenToShape);
    1066         d_ptr->updateAncestorFlag(ItemIgnoresTransformations);
    1067 
    1068         // Update item visible / enabled.
    1069         if (d_ptr->parent->isVisible() != d_ptr->visible) {
    1070             if (!d_ptr->parent->isVisible() || !d_ptr->explicitlyHidden)
    1071                 d_ptr->setVisibleHelper(d_ptr->parent->isVisible(), /* explicit = */ false, /* update = */ !implicitUpdate);
    1072         }
    1073         if (d_ptr->parent->isEnabled() != d_ptr->enabled) {
    1074             if (!d_ptr->parent->isEnabled() || !d_ptr->explicitlyDisabled)
    1075                 d_ptr->setEnabledHelper(d_ptr->parent->isEnabled(), /* explicit = */ false, /* update = */ !implicitUpdate);
    1076         }
    1077 
    1078     } else {
    1079         // Inherit ancestor flags from the new parent.
    1080         d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
    1081         d_ptr->updateAncestorFlag(ItemClipsChildrenToShape);
    1082         d_ptr->updateAncestorFlag(ItemIgnoresTransformations);
    1083 
    1084         // Update item visible / enabled.
    1085         if (!d_ptr->visible && !d_ptr->explicitlyHidden)
    1086             d_ptr->setVisibleHelper(true, /* explicit = */ false);
    1087         if (!d_ptr->enabled && !d_ptr->explicitlyDisabled)
    1088             d_ptr->setEnabledHelper(true, /* explicit = */ false);
    1089 
    1090         d_ptr->updateHelper(QRectF(), false, true);
    1091     }
    1092 
    1093     if (d_ptr->scene) {
    1094         // Invalidate any sort caching; arrival of a new item means we need to
    1095         // resort.
    1096         d_ptr->scene->d_func()->invalidateSortCache();
    1097     }
    1098 
    1099     // Resolve opacity.
    1100     d_ptr->updateEffectiveOpacity();
    1101 
    1102     // Resolve depth.
    1103     d_ptr->resolveDepth(parent ? parent->d_ptr->depth : -1);
    1104 
    1105     // Invalidate transform cache.
    1106     d_ptr->invalidateSceneTransformCache();
    1107 
    1108     // Deliver post-change notification
    1109     itemChange(QGraphicsItem::ItemParentHasChanged, newParentVariant);
     1560    d_ptr->setParentItemHelper(parent);
    11101561}
    11111562
     
    11251576    \since 4.4
    11261577
    1127     Returns a list of this item's children. The items are returned in no
    1128     particular order.
    1129 
    1130     \sa setParentItem()
     1578    Returns a list of this item's children.
     1579
     1580    The items are sorted by stacking order. This takes into account both the
     1581    items' insertion order and their Z-values.
     1582
     1583    \sa setParentItem(), zValue(), {QGraphicsItem#Sorting}{Sorting}
    11311584*/
    11321585QList<QGraphicsItem *> QGraphicsItem::childItems() const
    11331586{
     1587    const_cast<QGraphicsItem *>(this)->d_ptr->ensureSortedChildren();
    11341588    return d_ptr->children;
    11351589}
     
    11551609{
    11561610    return isWidget() && (static_cast<const QGraphicsWidget *>(this)->windowType() & Qt::Window);
     1611}
     1612
     1613/*!
     1614    \since 4.6
     1615    Returns true if the item is a panel; otherwise returns false.
     1616
     1617    \sa QGraphicsItem::panel(), ItemIsPanel
     1618*/
     1619bool QGraphicsItem::isPanel() const
     1620{
     1621    return d_ptr->flags & ItemIsPanel;
    11571622}
    11581623
     
    12121677    item is automatically unselected.
    12131678
    1214     By default, no flags are enabled.
     1679    By default, no flags are enabled. (QGraphicsWidget enables the
     1680    ItemSendsGeometryChanges flag by default in order to track position
     1681    changes.)
    12151682
    12161683    \sa flags(), setFlag()
     
    12181685void QGraphicsItem::setFlags(GraphicsItemFlags flags)
    12191686{
     1687    if (isWindow())
     1688        flags |= ItemIsPanel;
     1689
    12201690    // Notify change and check for adjustment.
    12211691    if (quint32(d_ptr->flags) == quint32(flags))
     
    12241694    if (quint32(d_ptr->flags) == quint32(flags))
    12251695        return;
     1696    if (d_ptr->scene)
     1697        d_ptr->scene->d_func()->index->itemChange(this, ItemFlagsChange, quint32(flags));
    12261698
    12271699    // Flags that alter the geometry of the item (or its children).
    1228     int geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations);
    1229     bool fullUpdate = (flags & geomChangeFlagsMask) != (d_ptr->flags & geomChangeFlagsMask);
     1700    const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations | ItemIsSelectable);
     1701    bool fullUpdate = (quint32(flags) & geomChangeFlagsMask) != (d_ptr->flags & geomChangeFlagsMask);
    12301702    if (fullUpdate)
    1231         d_ptr->fullUpdateHelper(false, true);
     1703        d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
    12321704
    12331705    // Keep the old flags to compare the diff.
     
    12361708    // Update flags.
    12371709    d_ptr->flags = flags;
    1238 
    1239     // Reresolve effective opacity if the opacity flags change.
    1240     static const quint32 opacityFlagsMask = ItemIgnoresParentOpacity | ItemDoesntPropagateOpacityToChildren;
    1241     if ((flags & opacityFlagsMask) != (oldFlags & opacityFlagsMask))
    1242         d_ptr->updateEffectiveOpacity();
    12431710
    12441711    if (!(d_ptr->flags & ItemIsFocusable) && hasFocus()) {
     
    12601727    }
    12611728
    1262     if ((flags & ItemClipsToShape) != (oldFlags & ItemClipsToShape))
    1263         d_ptr->invalidateCachedClipPath();
    1264 
    12651729    if ((flags & ItemIgnoresTransformations) != (oldFlags & ItemIgnoresTransformations)) {
    12661730        // Item children clipping changes. Propagate the ancestor flag to
     
    12691733    }
    12701734
    1271     // ### Why updateHelper?
    1272     d_ptr->updateHelper(QRectF(), false, true);
     1735    if ((flags & ItemStacksBehindParent) != (oldFlags & ItemStacksBehindParent)) {
     1736        // Ensure child item sorting is up to date when toggling this flag.
     1737        if (d_ptr->parent)
     1738            d_ptr->parent->d_ptr->needSortChildren = 1;
     1739        else if (d_ptr->scene)
     1740            d_ptr->scene->d_func()->needSortTopLevelItems = 1;
     1741    }
     1742
     1743    if ((flags & ItemAcceptsInputMethod) != (oldFlags & ItemAcceptsInputMethod)) {
     1744        // Update input method sensitivity in any views.
     1745        if (d_ptr->scene)
     1746            d_ptr->scene->d_func()->updateInputMethodSensitivityInViews();
     1747    }
     1748
     1749    if ((flags & ItemNegativeZStacksBehindParent) != (oldFlags & ItemNegativeZStacksBehindParent)) {
     1750        // Update stack-behind.
     1751        setFlag(ItemStacksBehindParent, d_ptr->z < qreal(0.0));
     1752    }
     1753
     1754    if ((d_ptr->panelModality != NonModal)
     1755        && d_ptr->scene
     1756        && (flags & ItemIsPanel) != (oldFlags & ItemIsPanel)) {
     1757        // update the panel's modal state
     1758        if (flags & ItemIsPanel)
     1759            d_ptr->scene->d_func()->enterModal(this);
     1760        else
     1761            d_ptr->scene->d_func()->leaveModal(this);
     1762    }
     1763
     1764    if (d_ptr->scene) {
     1765        if ((flags & ItemSendsScenePositionChanges) != (oldFlags & ItemSendsScenePositionChanges)) {
     1766            if (flags & ItemSendsScenePositionChanges)
     1767                d_ptr->scene->d_func()->registerScenePosItem(this);
     1768            else
     1769                d_ptr->scene->d_func()->unregisterScenePosItem(this);
     1770        }
     1771        d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true);
     1772    }
    12731773
    12741774    // Notify change.
     
    13331833
    13341834        if (mode == ItemCoordinateCache) {
    1335             if (cache->key.isEmpty()) {
    1336                 // Generate new simple pixmap cache key.
    1337                 QString tmp;
    1338                 tmp.sprintf("qgv-%p", this);
    1339                 cache->key = tmp;
    1340             }
    13411835            if (lastMode == mode && cache->fixedSize == logicalCacheSize)
    13421836                noVisualChange = true;
     
    13481842}
    13491843
     1844/*!
     1845    \since 4.6
     1846
     1847    Returns the modality for this item.
     1848*/
     1849QGraphicsItem::PanelModality QGraphicsItem::panelModality() const
     1850{
     1851    return d_ptr->panelModality;
     1852}
     1853
     1854/*!
     1855    \since 4.6
     1856
     1857    Sets the modality for this item to \a panelModality.
     1858
     1859    Changing the modality of a visible item takes effect immediately.
     1860*/
     1861void QGraphicsItem::setPanelModality(PanelModality panelModality)
     1862{
     1863    if (d_ptr->panelModality == panelModality)
     1864        return;
     1865
     1866    PanelModality previousModality = d_ptr->panelModality;
     1867    bool enterLeaveModal = (isPanel() && d_ptr->scene && isVisible());
     1868    if (enterLeaveModal && panelModality == NonModal)
     1869        d_ptr->scene->d_func()->leaveModal(this);
     1870    d_ptr->panelModality = panelModality;
     1871    if (enterLeaveModal && d_ptr->panelModality != NonModal)
     1872        d_ptr->scene->d_func()->enterModal(this, previousModality);
     1873}
     1874
     1875/*!
     1876    \since 4.6
     1877
     1878    Returns true if this item is blocked by a modal panel, false otherwise. If \a blockingPanel is
     1879    non-zero, \a blockingPanel will be set to the modal panel that is blocking this item. If this
     1880    item is not blocked, \a blockingPanel will not be set by this function.
     1881
     1882    This function always returns false for items not in a scene.
     1883
     1884    \sa panelModality() setPanelModality() PanelModality
     1885*/
     1886bool QGraphicsItem::isBlockedByModalPanel(QGraphicsItem **blockingPanel) const
     1887{
     1888    if (!d_ptr->scene)
     1889        return false;
     1890
     1891
     1892    QGraphicsItem *dummy = 0;
     1893    if (!blockingPanel)
     1894        blockingPanel = &dummy;
     1895
     1896    QGraphicsScenePrivate *scene_d = d_ptr->scene->d_func();
     1897    if (scene_d->modalPanels.isEmpty())
     1898        return false;
     1899
     1900    // ###
     1901    if (!scene_d->popupWidgets.isEmpty() && scene_d->popupWidgets.first() == this)
     1902        return false;
     1903
     1904    for (int i = 0; i < scene_d->modalPanels.count(); ++i) {
     1905        QGraphicsItem *modalPanel = scene_d->modalPanels.at(i);
     1906        if (modalPanel->panelModality() == QGraphicsItem::SceneModal) {
     1907            // Scene modal panels block all non-descendents.
     1908            if (modalPanel != this && !modalPanel->isAncestorOf(this)) {
     1909                *blockingPanel = modalPanel;
     1910                return true;
     1911            }
     1912        } else {
     1913            // Window modal panels block ancestors and siblings/cousins.
     1914            if (modalPanel != this
     1915                && !modalPanel->isAncestorOf(this)
     1916                && commonAncestorItem(modalPanel)) {
     1917                *blockingPanel = modalPanel;
     1918                return true;
     1919            }
     1920        }
     1921    }
     1922    return false;
     1923}
     1924
    13501925#ifndef QT_NO_TOOLTIP
    13511926/*!
     
    14161991    d_ptr->hasCursor = 1;
    14171992    if (d_ptr->scene) {
     1993        d_ptr->scene->d_func()->allItemsUseDefaultCursor = false;
    14181994        foreach (QGraphicsView *view, d_ptr->scene->views()) {
     1995            view->viewport()->setMouseTracking(true);
    14191996            // Note: Some of this logic is duplicated in QGraphicsView's mouse events.
    14201997            if (view->underMouse()) {
     
    15232100        return;
    15242101
     2102    // Don't show child if parent is not visible
     2103    if (parent && newVisible && !parent->d_ptr->visible)
     2104        return;
     2105
    15252106    // Modify the property.
    15262107    const QVariant newVisibleVariant(q_ptr->itemChange(QGraphicsItem::ItemVisibleChange,
     
    15362117        if (c)
    15372118            c->purge();
    1538         updateHelper(QRectF(), /* force = */ true);
     2119        if (scene)
     2120            scene->d_func()->markDirty(q_ptr, QRectF(), /*invalidateChildren=*/false, /*force=*/true);
    15392121    }
    15402122
     
    15462128            if (scene->d_func()->keyboardGrabberItems.contains(q))
    15472129                q->ungrabKeyboard();
     2130            if (q->isPanel() && panelModality != QGraphicsItem::NonModal)
     2131                scene->d_func()->leaveModal(q_ptr);
    15482132        }
    15492133        if (q_ptr->hasFocus() && scene) {
    1550             // Hiding the closest non-window ancestor of the focus item
     2134            // Hiding the closest non-panel ancestor of the focus item
    15512135            QGraphicsItem *focusItem = scene->focusItem();
    15522136            bool clear = true;
    1553             if (isWidget && !focusItem->isWindow()) {
     2137            if (isWidget && !focusItem->isPanel()) {
    15542138                do {
    15552139                    if (focusItem == q_ptr) {
     
    15572141                        break;
    15582142                    }
    1559                 } while ((focusItem = focusItem->parentWidget()) && !focusItem->isWindow());
     2143                } while ((focusItem = focusItem->parentWidget()) && !focusItem->isPanel());
    15602144            }
    15612145            if (clear)
     
    15652149            q_ptr->setSelected(false);
    15662150    } else {
    1567         if (isWidget && scene) {
    1568             QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(q_ptr);
    1569             if (widget->windowType() == Qt::Popup)
    1570                 scene->d_func()->addPopup(widget);
     2151        geometryChanged = 1;
     2152        paintedViewBoundingRectsNeedRepaint = 1;
     2153        if (scene) {
     2154            if (isWidget) {
     2155                QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(q_ptr);
     2156                if (widget->windowType() == Qt::Popup)
     2157                    scene->d_func()->addPopup(widget);
     2158            }
     2159            if (q->isPanel() && panelModality != QGraphicsItem::NonModal) {
     2160                scene->d_func()->enterModal(q_ptr);
     2161            }
    15712162        }
    15722163    }
     
    15792170    }
    15802171
     2172    // Update activation
     2173    if (scene && q->isPanel()) {
     2174        if (newVisible) {
     2175            if (parent && parent->isActive())
     2176                q->setActive(true);
     2177        } else {
     2178            if (q->isActive())
     2179                scene->setActivePanel(parent);
     2180        }
     2181    }
     2182
    15812183    // Enable subfocus
    1582     if (newVisible && isWidget) {
    1583         QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(q_ptr);
    1584         QGraphicsWidget *fw = widget->focusWidget();
    1585         if (fw && fw != scene->focusItem())
    1586             scene->setFocusItem(fw);
     2184    if (scene && newVisible) {
     2185        QGraphicsItem *p = parent;
     2186        bool done = false;
     2187        while (p) {
     2188            if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
     2189                QGraphicsItem *fsi = p->d_ptr->focusScopeItem;
     2190                if (q_ptr == fsi || q_ptr->isAncestorOf(fsi)) {
     2191                    done = true;
     2192                    while (fsi->d_ptr->focusScopeItem && fsi->d_ptr->focusScopeItem->isVisible())
     2193                        fsi = fsi->d_ptr->focusScopeItem;
     2194                    scene->setFocusItem(fsi);
     2195                }
     2196                break;
     2197            }
     2198            p = p->d_ptr->parent;
     2199        }
     2200        if (!done) {
     2201            QGraphicsItem *fi = subFocusItem;
     2202            if (fi && fi != scene->focusItem()) {
     2203                scene->setFocusItem(fi);
     2204            }
     2205        }
    15872206    }
    15882207
    15892208    // Deliver post-change notification.
    15902209    q_ptr->itemChange(QGraphicsItem::ItemVisibleHasChanged, newVisibleVariant);
     2210
     2211    if (isObject)
     2212        emit static_cast<QGraphicsObject *>(q_ptr)->visibleChanged();
    15912213}
    15922214
     
    16742296            q_ptr->ungrabMouse();
    16752297        if (q_ptr->hasFocus()) {
    1676             // Disabling the closest non-window ancestor of the focus item
     2298            // Disabling the closest non-panel ancestor of the focus item
    16772299            // causes focus to pop to the next item, otherwise it's cleared.
    16782300            QGraphicsItem *focusItem = scene->focusItem();
    16792301            bool clear = true;
    1680             if (isWidget && !focusItem->isWindow() && q_ptr->isAncestorOf(focusItem)) {
     2302            if (isWidget && !focusItem->isPanel() && q_ptr->isAncestorOf(focusItem)) {
    16812303                do {
    16822304                    if (focusItem == q_ptr) {
     
    16842306                        break;
    16852307                    }
    1686                 } while ((focusItem = focusItem->parentWidget()) && !focusItem->isWindow());
     2308                } while ((focusItem = focusItem->parentWidget()) && !focusItem->isPanel());
    16872309            }
    16882310            if (clear)
     
    17002322    // Schedule redraw.
    17012323    if (update)
    1702         updateHelper();
     2324        q_ptr->update();
    17032325
    17042326    foreach (QGraphicsItem *child, children) {
     
    17092331    // Deliver post-change notification.
    17102332    q_ptr->itemChange(QGraphicsItem::ItemEnabledHasChanged, newEnabledVariant);
     2333
     2334    if (isObject)
     2335        emit static_cast<QGraphicsObject *>(q_ptr)->enabledChanged();
    17112336}
    17122337
     
    18012426    d_ptr->selected = newSelected;
    18022427
    1803     d_ptr->updateHelper();
    1804 
     2428    update();
    18052429    if (d_ptr->scene) {
    18062430        QGraphicsScenePrivate *sceneD = d_ptr->scene->d_func();
     
    18392463qreal QGraphicsItem::opacity() const
    18402464{
    1841     if (d_ptr->hasOpacity) {
    1842         QVariant o = d_ptr->extra(QGraphicsItemPrivate::ExtraOpacity);
    1843         if (!o.isNull())
    1844             return o.toDouble();
    1845     }
    1846     return qreal(1.0);
     2465    return d_ptr->opacity;
    18472466}
    18482467
     
    18602479qreal QGraphicsItem::effectiveOpacity() const
    18612480{
    1862     if (!d_ptr->hasEffectiveOpacity)
    1863         return qreal(1.0);
    1864 
    1865     QVariant effectiveOpacity = d_ptr->extra(QGraphicsItemPrivate::ExtraEffectiveOpacity);
    1866     return effectiveOpacity.isNull() ? qreal(1.0) : qreal(effectiveOpacity.toDouble());
     2481    return d_ptr->effectiveOpacity();
    18672482}
    18682483
     
    18922507{
    18932508    // Notify change.
    1894     const QVariant newOpacityVariant(itemChange(ItemOpacityChange, double(opacity)));
    1895     qreal newOpacity = newOpacityVariant.toDouble();
    1896 
    1897     // Normalize.
    1898     newOpacity = qBound<qreal>(0.0, newOpacity, 1.0);
     2509    const QVariant newOpacityVariant(itemChange(ItemOpacityChange, opacity));
     2510
     2511    // Normalized opacity
     2512    qreal newOpacity = qBound(qreal(0), newOpacityVariant.toReal(), qreal(1));
    18992513
    19002514    // No change? Done.
    1901     if (qFuzzyCompare(newOpacity, this->opacity()))
     2515    if (newOpacity == d_ptr->opacity)
    19022516        return;
    19032517
    1904     // Assign local opacity.
    1905     if (qFuzzyCompare(newOpacity, qreal(1.0))) {
    1906         // Opaque, unset opacity.
    1907         d_ptr->hasOpacity = 0;
    1908         d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraOpacity);
    1909     } else {
    1910         d_ptr->hasOpacity = 1;
    1911         d_ptr->setExtra(QGraphicsItemPrivate::ExtraOpacity, double(newOpacity));
    1912     }
    1913 
    1914     // Resolve effective opacity.
    1915     if (QGraphicsItem *p = d_ptr->parent)
    1916         d_ptr->resolveEffectiveOpacity(p->effectiveOpacity());
    1917     else
    1918         d_ptr->resolveEffectiveOpacity(1.0);
     2518    d_ptr->opacity = newOpacity;
    19192519
    19202520    // Notify change.
    1921     itemChange(ItemOpacityHasChanged, newOpacity);
     2521    itemChange(ItemOpacityHasChanged, newOpacityVariant);
    19222522
    19232523    // Update.
    1924     d_ptr->fullUpdateHelper();
     2524    if (d_ptr->scene) {
     2525#ifndef QT_NO_GRAPHICSEFFECT
     2526        d_ptr->invalidateGraphicsEffectsRecursively();
     2527#endif //QT_NO_GRAPHICSEFFECT
     2528        d_ptr->scene->d_func()->markDirty(this, QRectF(),
     2529                                          /*invalidateChildren=*/true,
     2530                                          /*force=*/false,
     2531                                          /*ignoreOpacity=*/true);
     2532    }
     2533
     2534    if (d_ptr->isObject)
     2535        emit static_cast<QGraphicsObject *>(this)->opacityChanged();
     2536}
     2537
     2538/*!
     2539    Returns a pointer to this item's effect if it has one; otherwise 0.
     2540
     2541    \since 4.6
     2542*/
     2543#ifndef QT_NO_GRAPHICSEFFECT
     2544QGraphicsEffect *QGraphicsItem::graphicsEffect() const
     2545{
     2546    return d_ptr->graphicsEffect;
     2547}
     2548
     2549/*!
     2550    Sets \a effect as the item's effect. If there already is an effect installed
     2551    on this item, QGraphicsItem will delete the existing effect before installing
     2552    the new \a effect.
     2553
     2554    If \a effect is the installed on a different item, setGraphicsEffect() will remove
     2555    the effect from the item and install it on this item.
     2556
     2557    QGraphicsItem takes ownership of \a effect.
     2558
     2559    \note This function will apply the effect on itself and all its children.
     2560
     2561    \since 4.6
     2562*/
     2563void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect)
     2564{
     2565    if (d_ptr->graphicsEffect == effect)
     2566        return;
     2567
     2568    if (d_ptr->graphicsEffect) {
     2569        delete d_ptr->graphicsEffect;
     2570        d_ptr->graphicsEffect = 0;
     2571    }
     2572
     2573    if (effect) {
     2574        // Set new effect.
     2575        QGraphicsEffectSourcePrivate *sourced = new QGraphicsItemEffectSourcePrivate(this);
     2576        QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced);
     2577        d_ptr->graphicsEffect = effect;
     2578        effect->d_func()->setGraphicsEffectSource(source);
     2579        prepareGeometryChange();
     2580    }
     2581}
     2582#endif //QT_NO_GRAPHICSEFFECT
     2583
     2584/*!
     2585    \internal
     2586    \since 4.6
     2587    Returns the effective bounding rect of the given item space rect.
     2588    If the item has no effect, the rect is returned unmodified.
     2589    If the item has an effect, the effective rect can be extend beyond the
     2590    item's bounding rect, depending on the effect.
     2591
     2592    \sa boundingRect()
     2593*/
     2594QRectF QGraphicsItemPrivate::effectiveBoundingRect(const QRectF &rect) const
     2595{
     2596#ifndef QT_NO_GRAPHICSEFFECT
     2597    Q_Q(const QGraphicsItem);
     2598    QGraphicsEffect *effect = graphicsEffect;
     2599    if (scene && effect && effect->isEnabled()) {
     2600        QRectF sceneRect = q->mapRectToScene(rect);
     2601        QRectF sceneEffectRect;
     2602        foreach (QGraphicsView *view, scene->views()) {
     2603            QRectF deviceRect = view->d_func()->mapRectFromScene(sceneRect);
     2604            QRect deviceEffectRect = effect->boundingRectFor(deviceRect).toAlignedRect();
     2605            sceneEffectRect |= view->d_func()->mapRectToScene(deviceEffectRect);
     2606        }
     2607        return q->mapRectFromScene(sceneEffectRect);
     2608    }
     2609#endif //QT_NO_GRAPHICSEFFECT
     2610    return rect;
     2611}
     2612
     2613/*!
     2614    \internal
     2615    \since 4.6
     2616    Returns the effective bounding rect of the item.
     2617    If the item has no effect, this is the same as the item's bounding rect.
     2618    If the item has an effect, the effective rect can be larger than the item's
     2619    bouding rect, depending on the effect.
     2620
     2621    \sa boundingRect()
     2622*/
     2623QRectF QGraphicsItemPrivate::effectiveBoundingRect() const
     2624{
     2625#ifndef QT_NO_GRAPHICSEFFECT
     2626    Q_Q(const QGraphicsItem);
     2627    QRectF brect = effectiveBoundingRect(q_ptr->boundingRect());
     2628    if (ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
     2629        return brect;
     2630
     2631    const QGraphicsItem *effectParent = parent;
     2632    while (effectParent) {
     2633        QGraphicsEffect *effect = effectParent->d_ptr->graphicsEffect;
     2634        if (scene && effect && effect->isEnabled()) {
     2635            const QRectF brectInParentSpace = q->mapRectToItem(effectParent, brect);
     2636            const QRectF effectRectInParentSpace = effectParent->d_ptr->effectiveBoundingRect(brectInParentSpace);
     2637            brect = effectParent->mapRectToItem(q, effectRectInParentSpace);
     2638        }
     2639        if (effectParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
     2640            return brect;
     2641        effectParent = effectParent->d_ptr->parent;
     2642    }
     2643
     2644    return brect;
     2645#else //QT_NO_GRAPHICSEFFECT
     2646    return q_ptr->boundingRect();
     2647#endif //QT_NO_GRAPHICSEFFECT
     2648
     2649}
     2650
     2651/*!
     2652    \internal
     2653    \since 4.6
     2654    Returns the effective bounding rect of this item in scene coordinates,
     2655    by combining sceneTransform() with boundingRect(), taking into account
     2656    the effect that the item might have.
     2657
     2658    If the item has no effect, this is the same as sceneBoundingRect().
     2659
     2660    \sa effectiveBoundingRect(), sceneBoundingRect()
     2661*/
     2662QRectF QGraphicsItemPrivate::sceneEffectiveBoundingRect() const
     2663{
     2664    // Find translate-only offset
     2665    // COMBINE
     2666    QPointF offset;
     2667    const QGraphicsItem *parentItem = q_ptr;
     2668    const QGraphicsItemPrivate *itemd;
     2669    do {
     2670        itemd = parentItem->d_ptr.data();
     2671        if (itemd->transformData)
     2672            break;
     2673        offset += itemd->pos;
     2674    } while ((parentItem = itemd->parent));
     2675
     2676    QRectF br = effectiveBoundingRect();
     2677    br.translate(offset);
     2678    return !parentItem ? br : parentItem->sceneTransform().mapRect(br);
    19252679}
    19262680
     
    20352789    children's areas.
    20362790
    2037     If a parent item handles child events (setHandlesChildEvents()), it will
    2038     receive hover move, drag move, and drop events as the cursor passes
    2039     through its children, but it does not receive hover enter and hover leave,
    2040     nor drag enter and drag leave events on behalf of its children.
     2791    If a parent item handles child events, it will receive hover move,
     2792    drag move, and drop events as the cursor passes through its
     2793    children, but it does not receive hover enter and hover leave, nor
     2794    drag enter and drag leave events on behalf of its children.
    20412795
    20422796    A QGraphicsWidget with window decorations will accept hover events
     
    20482802void QGraphicsItem::setAcceptHoverEvents(bool enabled)
    20492803{
     2804    if (d_ptr->acceptsHover == quint32(enabled))
     2805        return;
    20502806    d_ptr->acceptsHover = quint32(enabled);
     2807    if (d_ptr->acceptsHover && d_ptr->scene && d_ptr->scene->d_func()->allItemsIgnoreHoverEvents) {
     2808        d_ptr->scene->d_func()->allItemsIgnoreHoverEvents = false;
     2809        d_ptr->scene->d_func()->enableMouseTrackingOnViews();
     2810    }
    20512811}
    20522812
     
    20582818void QGraphicsItem::setAcceptsHoverEvents(bool enabled)
    20592819{
    2060     d_ptr->acceptsHover = quint32(enabled);
    2061 }
    2062 
    2063 /*!
     2820    setAcceptHoverEvents(enabled);
     2821}
     2822
     2823/*! \since 4.6
     2824
     2825    Returns true if an item accepts \l{QTouchEvent}{touch events};
     2826    otherwise, returns false. By default, items do not accept touch events.
     2827
     2828    \sa setAcceptTouchEvents()
     2829*/
     2830bool QGraphicsItem::acceptTouchEvents() const
     2831{
     2832    return d_ptr->acceptTouchEvents;
     2833}
     2834
     2835/*!
     2836    \since 4.6
     2837
     2838    If \a enabled is true, this item will accept \l{QTouchEvent}{touch events};
     2839    otherwise, it will ignore them. By default, items do not accept
     2840    touch events.
     2841*/
     2842void QGraphicsItem::setAcceptTouchEvents(bool enabled)
     2843{
     2844    if (d_ptr->acceptTouchEvents == quint32(enabled))
     2845        return;
     2846    d_ptr->acceptTouchEvents = quint32(enabled);
     2847    if (d_ptr->acceptTouchEvents && d_ptr->scene && d_ptr->scene->d_func()->allItemsIgnoreTouchEvents) {
     2848        d_ptr->scene->d_func()->allItemsIgnoreTouchEvents = false;
     2849        d_ptr->scene->d_func()->enableTouchEventsOnViews();
     2850    }
     2851}
     2852
     2853/*!
     2854    \since 4.6
     2855
     2856    Returns true if this item filters child events (i.e., all events
     2857    intended for any of its children are instead sent to this item);
     2858    otherwise, false is returned.
     2859
     2860    The default value is false; child events are not filtered.
     2861
     2862    \sa setFiltersChildEvents()
     2863*/
     2864bool QGraphicsItem::filtersChildEvents() const
     2865{
     2866    return d_ptr->filtersDescendantEvents;
     2867}
     2868
     2869/*!
     2870    \since 4.6
     2871
     2872    If \a enabled is true, this item is set to filter all events for
     2873    all its children (i.e., all events intented for any of its
     2874    children are instead sent to this item); otherwise, if \a enabled
     2875    is false, this item will only handle its own events. The default
     2876    value is false.
     2877
     2878    \sa filtersChildEvents()
     2879*/
     2880void QGraphicsItem::setFiltersChildEvents(bool enabled)
     2881{
     2882    if (d_ptr->filtersDescendantEvents == enabled)
     2883        return;
     2884
     2885    d_ptr->filtersDescendantEvents = enabled;
     2886    d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2));
     2887}
     2888
     2889/*!
     2890    \obsolete
     2891
    20642892    Returns true if this item handles child events (i.e., all events
    20652893    intended for any of its children are instead sent to this item);
     
    20822910
    20832911/*!
     2912    \obsolete
     2913
    20842914    If \a enabled is true, this item is set to handle all events for
    20852915    all its children (i.e., all events intented for any of its
     
    21072937    d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
    21082938}
    2109 
    2110 /*!
    2111     Returns true if this item has keyboard input focus; otherwise, returns
    2112     false.
    2113 
    2114     \sa QGraphicsScene::focusItem(), setFocus(), QGraphicsScene::setFocusItem()
     2939/*!
     2940    \since 4.6
     2941    Returns true if this item is active; otherwise returns false.
     2942
     2943    An item can only be active if the scene is active. An item is active
     2944    if it is, or is a descendent of, an active panel. Items in non-active
     2945    panels are not active.
     2946
     2947    Items that are not part of a panel follow scene activation when the
     2948    scene has no active panel.
     2949
     2950    Only active items can gain input focus.
     2951
     2952    \sa QGraphicsScene::isActive(), QGraphicsScene::activePanel(), panel(), isPanel()
     2953*/
     2954bool QGraphicsItem::isActive() const
     2955{
     2956    if (!d_ptr->scene || !d_ptr->scene->isActive())
     2957        return false;
     2958    return panel() == d_ptr->scene->activePanel();
     2959}
     2960
     2961/*!
     2962    \since 4.6
     2963
     2964    If \a active is true, and the scene is active, this item's panel will be
     2965    activated. Otherwise, the panel is deactivated.
     2966
     2967    If the item is not part of an active scene, \a active will decide what
     2968    happens to the panel when the scene becomes active or the item is added to
     2969    the scene. If true, the item's panel will be activated when the item is
     2970    either added to the scene or the scene is activated. Otherwise, the item
     2971    will stay inactive independent of the scene's activated state.
     2972
     2973    \sa isPanel(), QGraphicsScene::setActivePanel(), QGraphicsScene::isActive()
     2974*/
     2975void QGraphicsItem::setActive(bool active)
     2976{
     2977    d_ptr->explicitActivate = 1;
     2978    d_ptr->wantsActive = active;
     2979    if (d_ptr->scene) {
     2980        if (active) {
     2981            // Activate this item.
     2982            d_ptr->scene->setActivePanel(this);
     2983        } else {
     2984            // Deactivate this item, and reactivate the last active item
     2985            // (if any).
     2986            QGraphicsItem *lastActive = d_ptr->scene->d_func()->lastActivePanel;
     2987            d_ptr->scene->setActivePanel(lastActive != this ? lastActive : 0);
     2988        }
     2989    }
     2990}
     2991
     2992/*!
     2993    Returns true if this item is active, and it or its \l{focusProxy()}{focus
     2994    proxy} has keyboard input focus; otherwise, returns false.
     2995
     2996    \sa focusItem(), setFocus(), QGraphicsScene::setFocusItem(), isActive()
    21152997*/
    21162998bool QGraphicsItem::hasFocus() const
    21172999{
    2118     return (d_ptr->scene && d_ptr->scene->focusItem() == this);
     3000    if (d_ptr->focusProxy)
     3001        return d_ptr->focusProxy->hasFocus();
     3002    return isActive() && (d_ptr->scene && d_ptr->scene->focusItem() == this);
    21193003}
    21203004
    21213005/*!
    21223006    Gives keyboard input focus to this item. The \a focusReason argument will
    2123     be passed into any focus event generated by this function; it is used to
    2124     give an explanation of what caused the item to get focus.
    2125 
    2126     Only items that set the ItemIsFocusable flag can accept keyboard focus.
    2127 
    2128     If this item is not visible (i.e., isVisible() returns false), not
    2129     enabled, not associated with a scene, or if it already has input focus,
    2130     this function will do nothing.
    2131 
    2132     As a result of calling this function, this item will receive a focus in
    2133     event with \a focusReason. If another item already has focus, that item
    2134     will first receive a focus out event indicating that it has lost input
     3007    be passed into any \l{QFocusEvent}{focus event} generated by this function;
     3008    it is used to give an explanation of what caused the item to get focus.
     3009
     3010    Only enabled items that set the ItemIsFocusable flag can accept keyboard
    21353011    focus.
    21363012
    2137     \sa clearFocus(), hasFocus()
     3013    If this item is not visible, not active, or not associated with a scene,
     3014    it will not gain immediate input focus. However, it will be registered as
     3015    the preferred focus item for its subtree of items, should it later become
     3016    visible.
     3017
     3018    As a result of calling this function, this item will receive a
     3019    \l{focusInEvent()}{focus in event} with \a focusReason. If another item
     3020    already has focus, that item will first receive a \l{focusOutEvent()}
     3021    {focus out event} indicating that it has lost input focus.
     3022
     3023    \sa clearFocus(), hasFocus(), focusItem(), focusProxy()
    21383024*/
    21393025void QGraphicsItem::setFocus(Qt::FocusReason focusReason)
    21403026{
    2141     if (!d_ptr->scene || !isEnabled() || hasFocus() || !(d_ptr->flags & ItemIsFocusable))
     3027    d_ptr->setFocusHelper(focusReason, /* climb = */ true);
     3028}
     3029
     3030/*!
     3031    \internal
     3032*/
     3033void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool climb)
     3034{
     3035    // Disabled / unfocusable items cannot accept focus.
     3036    if (!q_ptr->isEnabled() || !(flags & QGraphicsItem::ItemIsFocusable))
    21423037        return;
    2143     if (isVisible()) {
    2144         // Visible items immediately gain focus from scene.
    2145         d_ptr->scene->setFocusItem(this, focusReason);
    2146     } else if (d_ptr->isWidget) {
    2147         // Just set up subfocus.
    2148         static_cast<QGraphicsWidget *>(this)->d_func()->setFocusWidget();
     3038
     3039    // Find focus proxy.
     3040    QGraphicsItem *f = q_ptr;
     3041    while (f->d_ptr->focusProxy)
     3042        f = f->d_ptr->focusProxy;
     3043
     3044    // Return if it already has focus.
     3045    if (scene && scene->focusItem() == f)
     3046        return;
     3047
     3048    // Update focus scope item ptr.
     3049    QGraphicsItem *p = parent;
     3050    while (p) {
     3051        if (p->flags() & QGraphicsItem::ItemIsFocusScope) {
     3052            p->d_ptr->focusScopeItem = q_ptr;
     3053            if (!p->focusItem()) {
     3054                // If you call setFocus on a child of a focus scope that
     3055                // doesn't currently have a focus item, then stop.
     3056                return;
     3057            }
     3058            break;
     3059        }
     3060        p = p->d_ptr->parent;
     3061    }
     3062
     3063    if (climb) {
     3064        while (f->d_ptr->focusScopeItem && f->d_ptr->focusScopeItem->isVisible())
     3065            f = f->d_ptr->focusScopeItem;
     3066    }
     3067
     3068    // Update the child focus chain.
     3069    f->d_ptr->setSubFocus();
     3070
     3071    // Update the scene's focus item.
     3072    if (scene) {
     3073        QGraphicsItem *p = q_ptr->panel();
     3074        if ((!p && scene->isActive()) || (p && p->isActive())) {
     3075            // Visible items immediately gain focus from scene.
     3076            scene->d_func()->setFocusItemHelper(f, focusReason);
     3077        }
    21493078    }
    21503079}
     
    21533082    Takes keyboard input focus from the item.
    21543083
    2155     If it has focus, a focus out event is sent to this item to tell it that it
    2156     is about to lose the focus.
     3084    If it has focus, a \l{focusOutEvent()}{focus out event} is sent to this
     3085    item to tell it that it is about to lose the focus.
    21573086
    21583087    Only items that set the ItemIsFocusable flag, or widgets that set an
    21593088    appropriate focus policy, can accept keyboard focus.
    21603089
    2161     \sa setFocus(), QGraphicsWidget::focusPolicy
     3090    \sa setFocus(), hasFocus(), QGraphicsWidget::focusPolicy
    21623091*/
    21633092void QGraphicsItem::clearFocus()
    21643093{
    2165     if (!d_ptr->scene)
    2166         return;
    2167     if (d_ptr->isWidget) {
    2168         // Invisible widget items with focus must explicitly clear subfocus.
    2169         static_cast<QGraphicsWidget *>(this)->d_func()->clearFocusWidget();
    2170     }
    2171     if (d_ptr->scene->focusItem() == this) {
     3094    // Pass focus to the closest parent focus scope.
     3095    if (!d_ptr->inDestructor) {
     3096        QGraphicsItem *p = d_ptr->parent;
     3097        while (p) {
     3098            if (p->flags() & ItemIsFocusScope) {
     3099                p->d_ptr->setFocusHelper(Qt::OtherFocusReason, /* climb = */ false);
     3100                return;
     3101            }
     3102            p = p->d_ptr->parent;
     3103        }
     3104    }
     3105
     3106    // Invisible items with focus must explicitly clear subfocus.
     3107    d_ptr->clearSubFocus(this);
     3108
     3109    if (hasFocus()) {
    21723110        // If this item has the scene's input focus, clear it.
    21733111        d_ptr->scene->setFocusItem(0);
    21743112    }
     3113}
     3114
     3115/*!
     3116    \since 4.6
     3117
     3118    Returns this item's focus proxy, or 0 if this item has no
     3119    focus proxy.
     3120
     3121    \sa setFocusProxy(), setFocus(), hasFocus()
     3122*/
     3123QGraphicsItem *QGraphicsItem::focusProxy() const
     3124{
     3125    return d_ptr->focusProxy;
     3126}
     3127
     3128/*!
     3129    \since 4.6
     3130
     3131    Sets the item's focus proxy to \a item.
     3132
     3133    If an item has a focus proxy, the focus proxy will receive
     3134    input focus when the item gains input focus. The item itself
     3135    will still have focus (i.e., hasFocus() will return true),
     3136    but only the focus proxy will receive the keyboard input.
     3137
     3138    A focus proxy can itself have a focus proxy, and so on. In
     3139    such case, keyboard input will be handled by the outermost
     3140    focus proxy.
     3141
     3142    The focus proxy \a item must belong to the same scene as
     3143    this item.
     3144
     3145    \sa focusProxy(), setFocus(), hasFocus()
     3146*/
     3147void QGraphicsItem::setFocusProxy(QGraphicsItem *item)
     3148{
     3149    if (item == d_ptr->focusProxy)
     3150        return;
     3151    if (item == this) {
     3152        qWarning("QGraphicsItem::setFocusProxy: cannot assign self as focus proxy");
     3153        return;
     3154    }
     3155    if (item) {
     3156        if (item->d_ptr->scene != d_ptr->scene) {
     3157            qWarning("QGraphicsItem::setFocusProxy: focus proxy must be in same scene");
     3158            return;
     3159        }
     3160        for (QGraphicsItem *f = item->focusProxy(); f != 0; f = f->focusProxy()) {
     3161            if (f == this) {
     3162                qWarning("QGraphicsItem::setFocusProxy: %p is already in the focus proxy chain", item);
     3163                return;
     3164            }
     3165        }
     3166    }
     3167
     3168    QGraphicsItem *lastFocusProxy = d_ptr->focusProxy;
     3169    if (lastFocusProxy)
     3170        lastFocusProxy->d_ptr->focusProxyRefs.removeOne(&d_ptr->focusProxy);
     3171    d_ptr->focusProxy = item;
     3172    if (item)
     3173        item->d_ptr->focusProxyRefs << &d_ptr->focusProxy;
     3174}
     3175
     3176/*!
     3177    \since 4.6
     3178
     3179    If this item, a child or descendant of this item currently has input
     3180    focus, this function will return a pointer to that item. If
     3181    no descendant has input focus, 0 is returned.
     3182
     3183    \sa hasFocus(), setFocus(), QWidget::focusWidget()
     3184*/
     3185QGraphicsItem *QGraphicsItem::focusItem() const
     3186{
     3187    return d_ptr->subFocusItem;
     3188}
     3189
     3190/*!
     3191    \internal
     3192
     3193    Returns this item's focus scope item.
     3194*/
     3195QGraphicsItem *QGraphicsItem::focusScopeItem() const
     3196{
     3197    return d_ptr->focusScopeItem;
    21753198}
    21763199
     
    23103333    item's position in scene coordinates, regardless of its parent.
    23113334
    2312     \sa x(), y(), setPos(), matrix(), {The Graphics View Coordinate System}
     3335    \sa x(), y(), setPos(), transform(), {The Graphics View Coordinate System}
    23133336*/
    23143337QPointF QGraphicsItem::pos() const
     
    23263349
    23273350/*!
     3351    \since 4.6
     3352
     3353    Set's the \a x coordinate of the item's position. Equivalent to
     3354    calling setPos(x, y()).
     3355
     3356    \sa x(), setPos()
     3357*/
     3358void QGraphicsItem::setX(qreal x)
     3359{
     3360    if (d_ptr->inDestructor)
     3361        return;
     3362
     3363    d_ptr->setPosHelper(QPointF(x, d_ptr->pos.y()));
     3364}
     3365
     3366/*!
    23283367    \fn QGraphicsItem::y() const
    23293368
     
    23323371    \sa x()
    23333372*/
     3373
     3374/*!
     3375    \since 4.6
     3376
     3377    Set's the \a y coordinate of the item's position. Equivalent to
     3378    calling setPos(x(), y).
     3379
     3380    \sa x(), setPos()
     3381*/
     3382void QGraphicsItem::setY(qreal y)
     3383{
     3384    if (d_ptr->inDestructor)
     3385        return;
     3386
     3387    d_ptr->setPosHelper(QPointF(d_ptr->pos.x(), y));
     3388}
    23343389
    23353390/*!
     
    23473402    \internal
    23483403
    2349     Sets the position \a pos and notifies the change. If \a update is true,
    2350     the item is also updated; otherwise it is not updated before and after the
    2351     change.
     3404    Sets the position \a pos.
    23523405*/
    23533406void QGraphicsItemPrivate::setPosHelper(const QPointF &pos)
    23543407{
    23553408    Q_Q(QGraphicsItem);
    2356     if (this->pos == pos)
    2357         return;
    2358 
    2359     // Notify the item that the position is changing.
    2360     const QVariant newPosVariant(q->itemChange(QGraphicsItem::ItemPositionChange, pos));
    2361     QPointF newPos = newPosVariant.toPointF();
    2362     if (newPos == this->pos)
    2363         return;
    2364 
    2365     // Update and repositition.
    23663409    inSetPosHelper = 1;
    2367     updateCachedClipPathFromSetPosHelper(newPos);
    2368     if (scene) {
    2369         fullUpdateHelper(true);
     3410    if (scene)
    23703411        q->prepareGeometryChange();
    2371     }
    2372     this->pos = newPos;
    2373     invalidateSceneTransformCache();
    2374 
    2375     // Send post-notification.
    2376     q->itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant);
     3412    QPointF oldPos = this->pos;
     3413    this->pos = pos;
     3414    dirtySceneTransform = 1;
    23773415    inSetPosHelper = 0;
     3416    if (isObject) {
     3417        if (pos.x() != oldPos.x())
     3418            emit static_cast<QGraphicsObject *>(q_ptr)->xChanged();
     3419        if (pos.y() != oldPos.y())
     3420            emit static_cast<QGraphicsObject *>(q_ptr)->yChanged();
     3421    }
     3422}
     3423
     3424/*!
     3425    \internal
     3426
     3427    Sets the transform \a transform.
     3428*/
     3429void QGraphicsItemPrivate::setTransformHelper(const QTransform &transform)
     3430{
     3431    q_ptr->prepareGeometryChange();
     3432    transformData->transform = transform;
     3433    dirtySceneTransform = 1;
    23783434}
    23793435
     
    23903446void QGraphicsItem::setPos(const QPointF &pos)
    23913447{
    2392     d_ptr->setPosHelper(pos);
     3448    if (d_ptr->pos == pos)
     3449        return;
     3450
     3451    if (d_ptr->inDestructor)
     3452        return;
     3453
     3454    // Update and repositition.
     3455    if (!(d_ptr->flags & ItemSendsGeometryChanges)) {
     3456        d_ptr->setPosHelper(pos);
     3457        return;
     3458    }
     3459
     3460    // Notify the item that the position is changing.
     3461    const QVariant newPosVariant(itemChange(ItemPositionChange, qVariantFromValue<QPointF>(pos)));
     3462    QPointF newPos = newPosVariant.toPointF();
     3463    if (newPos == d_ptr->pos)
     3464        return;
     3465
     3466    // Update and repositition.
     3467    d_ptr->setPosHelper(newPos);
     3468
     3469    // Send post-notification.
     3470    itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant);
     3471    d_ptr->sendScenePosChange();
    23933472}
    23943473
     
    24633542    \since 4.3
    24643543
    2465     Returns this item's transformation matrix. If no matrix has been set, the
    2466     identity matrix is returned.
     3544    Returns this item's transformation matrix.
     3545
     3546    The transformation matrix is combined with the item's rotation(), scale()
     3547    and transformations() into a combined transformations for the item.
     3548
     3549    The default transformation matrix is an identity matrix.
    24673550
    24683551    \sa setTransform(), sceneTransform()
     
    24703553QTransform QGraphicsItem::transform() const
    24713554{
    2472     if (!d_ptr->hasTransform)
     3555    if (!d_ptr->transformData)
    24733556        return QTransform();
    2474     return qVariantValue<QTransform>(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform));
    2475 }
     3557    return d_ptr->transformData->transform;
     3558}
     3559
     3560/*!
     3561    \since 4.6
     3562
     3563    Returns the clockwise rotation, in degrees, around the Z axis. The default
     3564    value is 0 (i.e., the item is not rotated).
     3565
     3566    The rotation is combined with the item's scale(), transform() and
     3567    transformations() to map the item's coordinate system to the parent item.
     3568
     3569    \sa setRotation(), transformOriginPoint(), {Transformations}
     3570*/
     3571qreal QGraphicsItem::rotation() const
     3572{
     3573    if (!d_ptr->transformData)
     3574        return 0;
     3575    return d_ptr->transformData->rotation;
     3576}
     3577
     3578/*!
     3579    \since 4.6
     3580
     3581    Sets the clockwise rotation \a angle, in degrees, around the Z axis. The
     3582    default value is 0 (i.e., the item is not rotated). Assigning a negative
     3583    value will rotate the item counter-clockwise. Normally the rotation angle
     3584    is in the range (-360, 360), but it's also possible to assign values
     3585    outside of this range (e.g., a rotation of 370 degrees is the same as a
     3586    rotation of 10 degrees).
     3587
     3588    The item is rotated around its transform origin point, which by default
     3589    is (0, 0). You can select a different transformation origin by calling
     3590    setTransformOriginPoint().
     3591
     3592    The rotation is combined with the item's scale(), transform() and
     3593    transformations() to map the item's coordinate system to the parent item.
     3594
     3595    \sa rotation(), setTransformOriginPoint(), {Transformations}
     3596*/
     3597void QGraphicsItem::setRotation(qreal angle)
     3598{
     3599    prepareGeometryChange();
     3600    if (!d_ptr->transformData)
     3601        d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
     3602    d_ptr->transformData->rotation = angle;
     3603    d_ptr->transformData->onlyTransform = false;
     3604    d_ptr->dirtySceneTransform = 1;
     3605
     3606    if (d_ptr->isObject)
     3607        emit static_cast<QGraphicsObject *>(this)->rotationChanged();
     3608}
     3609
     3610/*!
     3611    \since 4.6
     3612
     3613    Returns the scale factor of the item. The default scale factor is 1.0
     3614    (i.e., the item is not scaled).
     3615
     3616    The scale is combined with the item's rotation(), transform() and
     3617    transformations() to map the item's coordinate system to the parent item.
     3618
     3619    \sa setScale(), rotation(), {Transformations}
     3620*/
     3621qreal QGraphicsItem::scale() const
     3622{
     3623    if (!d_ptr->transformData)
     3624        return 1.;
     3625    return d_ptr->transformData->scale;
     3626}
     3627
     3628/*!
     3629    \since 4.6
     3630
     3631    Sets the scale \a factor of the item. The default scale factor is 1.0
     3632    (i.e., the item is not scaled). A scale factor of 0.0 will collapse the
     3633    item to a single point. If you provide a negative scale factor, the
     3634    item will be flipped and mirrored (i.e., rotated 180 degrees).
     3635
     3636    The item is scaled around its transform origin point, which by default
     3637    is (0, 0). You can select a different transformation origin by calling
     3638    setTransformOriginPoint().
     3639
     3640    The scale is combined with the item's rotation(), transform() and
     3641    transformations() to map the item's coordinate system to the parent item.
     3642
     3643    \sa scale(), setTransformOriginPoint(), {Transformations}
     3644*/
     3645void QGraphicsItem::setScale(qreal factor)
     3646{
     3647    prepareGeometryChange();
     3648    if (!d_ptr->transformData)
     3649        d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
     3650    d_ptr->transformData->scale = factor;
     3651    d_ptr->transformData->onlyTransform = false;
     3652    d_ptr->dirtySceneTransform = 1;
     3653
     3654    if (d_ptr->isObject)
     3655        emit static_cast<QGraphicsObject *>(this)->scaleChanged();
     3656}
     3657
     3658
     3659/*!
     3660    \since 4.6
     3661
     3662    Returns a list of graphics transforms that currently apply to this item.
     3663
     3664    QGraphicsTransform is for applying and controlling a chain of individual
     3665    transformation operations on an item. It's particularily useful in
     3666    animations, where each transform operation needs to be interpolated
     3667    independently, or differently.
     3668
     3669    The transformations are combined with the item's rotation(), scale() and
     3670    transform() to map the item's coordinate system to the parent item.
     3671
     3672    \sa scale(), rotation(), transformOriginPoint(), {Transformations}
     3673*/
     3674QList<QGraphicsTransform *> QGraphicsItem::transformations() const
     3675{
     3676    if (!d_ptr->transformData)
     3677        return QList<QGraphicsTransform *>();
     3678    return d_ptr->transformData->graphicsTransforms;
     3679}
     3680
     3681/*!
     3682    \since 4.6
     3683
     3684    Sets a list of graphics \a transformations (QGraphicsTransform) that
     3685    currently apply to this item.
     3686
     3687    If all you want is to rotate or scale an item, you should call setRotation()
     3688    or setScale() instead. If you want to set an arbitrary transformation on
     3689    an item, you can call setTransform().
     3690
     3691    QGraphicsTransform is for applying and controlling a chain of individual
     3692    transformation operations on an item. It's particularily useful in
     3693    animations, where each transform operation needs to be interpolated
     3694    independently, or differently.
     3695
     3696    The transformations are combined with the item's rotation(), scale() and
     3697    transform() to map the item's coordinate system to the parent item.
     3698
     3699    \sa scale(), setTransformOriginPoint(), {Transformations}
     3700*/
     3701void QGraphicsItem::setTransformations(const QList<QGraphicsTransform *> &transformations)
     3702{
     3703    prepareGeometryChange();
     3704    if (!d_ptr->transformData)
     3705        d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
     3706    d_ptr->transformData->graphicsTransforms = transformations;
     3707    for (int i = 0; i < transformations.size(); ++i)
     3708        transformations.at(i)->d_func()->setItem(this);
     3709    d_ptr->transformData->onlyTransform = false;
     3710    d_ptr->dirtySceneTransform = 1;
     3711}
     3712
     3713/*!
     3714    \internal
     3715*/
     3716void QGraphicsItemPrivate::appendGraphicsTransform(QGraphicsTransform *t)
     3717{
     3718    if (!transformData)
     3719        transformData = new QGraphicsItemPrivate::TransformData;
     3720    if (!transformData->graphicsTransforms.contains(t))
     3721        transformData->graphicsTransforms.append(t);
     3722
     3723    Q_Q(QGraphicsItem);
     3724    t->d_func()->setItem(q);
     3725    transformData->onlyTransform = false;
     3726    dirtySceneTransform = 1;
     3727}
     3728
     3729/*!
     3730    \since 4.6
     3731
     3732    Returns the origin point for the transformation in item coordinates.
     3733
     3734    The default is QPointF(0,0).
     3735
     3736    \sa setTransformOriginPoint(), {Transformations}
     3737*/
     3738QPointF QGraphicsItem::transformOriginPoint() const
     3739{
     3740    if (!d_ptr->transformData)
     3741        return QPointF(0,0);
     3742    return QPointF(d_ptr->transformData->xOrigin, d_ptr->transformData->yOrigin);
     3743}
     3744
     3745/*!
     3746    \since 4.6
     3747
     3748    Sets the \a origin point for the transformation in item coordinates.
     3749
     3750    \sa transformOriginPoint(), {Transformations}
     3751*/
     3752void QGraphicsItem::setTransformOriginPoint(const QPointF &origin)
     3753{
     3754    prepareGeometryChange();
     3755    if (!d_ptr->transformData)
     3756        d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
     3757    d_ptr->transformData->xOrigin = origin.x();
     3758    d_ptr->transformData->yOrigin = origin.y();
     3759    d_ptr->transformData->onlyTransform = false;
     3760    d_ptr->dirtySceneTransform = 1;
     3761}
     3762
     3763/*!
     3764    \fn void QGraphicsItem::setTransformOriginPoint(qreal x, qreal y)
     3765
     3766    \since 4.6
     3767    \overload
     3768
     3769    Sets the origin point for the transformation in item coordinates.
     3770    This is equivalent to calling setTransformOriginPoint(QPointF(\a x, \a y)).
     3771
     3772    \sa setTransformOriginPoint(), {Transformations}
     3773*/
     3774
    24763775
    24773776/*!
     
    24843783QMatrix QGraphicsItem::sceneMatrix() const
    24853784{
    2486     return sceneTransform().toAffine();
     3785    d_ptr->ensureSceneTransform();
     3786    return d_ptr->sceneTransform.toAffine();
    24873787}
    24883788
     
    25013801
    25023802    Unlike transform(), which returns only an item's local transformation, this
    2503     function includes the item's (and any parents') position.
    2504 
    2505     \sa transform(), setTransform(), scenePos(), {The Graphics View Coordinate System}
     3803    function includes the item's (and any parents') position, and all the transfomation properties.
     3804
     3805    \sa transform(), setTransform(), scenePos(), {The Graphics View Coordinate System}, {Transformations}
    25063806*/
    25073807QTransform QGraphicsItem::sceneTransform() const
    25083808{
    2509     // Check if there's any entry in the transform cache.
    2510     QGraphicsScenePrivate *sd = d_ptr->scene ? d_ptr->scene->d_func() : 0;
    2511     int index = d_ptr->sceneTransformIndex;
    2512     if (sd && index != -1 && sd->validTransforms.testBit(index))
    2513         return sd->sceneTransformCache[index];
    2514 
    2515     // Calculate local transform.
    2516     QTransform m;
    2517     if (d_ptr->hasTransform) {
    2518         m = transform();
    2519         if (!d_ptr->pos.isNull())
    2520             m *= QTransform::fromTranslate(d_ptr->pos.x(), d_ptr->pos.y());
    2521     } else if (!d_ptr->pos.isNull()) {
    2522         m = QTransform::fromTranslate(d_ptr->pos.x(), d_ptr->pos.y());
    2523     }
    2524 
    2525     // Combine with parent and add to cache.
    2526     if (d_ptr->parent) {
    2527         m *= d_ptr->parent->sceneTransform();
    2528         // Don't cache toplevels
    2529         if (sd) {
    2530             if (index == -1) {
    2531                 if (!sd->freeSceneTransformSlots.isEmpty()) {
    2532                     index = sd->freeSceneTransformSlots.last();
    2533                     sd->freeSceneTransformSlots.pop_back();
    2534                 } else {
    2535                     index = sd->sceneTransformCache.size();
    2536                 }
    2537                 d_ptr->sceneTransformIndex = index;
    2538                 if (index >= sd->validTransforms.size()) {
    2539                     sd->validTransforms.resize(index + 1);
    2540                     sd->sceneTransformCache.resize(index + 1);
    2541                 }
    2542             }
    2543             sd->validTransforms.setBit(index, 1);
    2544             sd->sceneTransformCache[index] = m;
    2545         }
    2546     }
    2547     return m;
     3809    d_ptr->ensureSceneTransform();
     3810    return d_ptr->sceneTransform;
    25483811}
    25493812
     
    25733836QTransform QGraphicsItem::deviceTransform(const QTransform &viewportTransform) const
    25743837{
     3838    // Ensure we return the standard transform if we're not untransformable.
     3839    if (!d_ptr->itemIsUntransformable()) {
     3840        d_ptr->ensureSceneTransform();
     3841        return d_ptr->sceneTransform * viewportTransform;
     3842    }
     3843
    25753844    // Find the topmost item that ignores view transformations.
    25763845    const QGraphicsItem *untransformedAncestor = this;
     
    25903859
    25913860    // First translate the base untransformable item.
    2592     QPointF mappedPoint = (untransformedAncestor->sceneTransform() * viewportTransform).map(QPointF(0, 0));
    2593     QTransform matrix;
    2594     matrix.translate(mappedPoint.x(), mappedPoint.y());
    2595     matrix = untransformedAncestor->transform() * matrix;
     3861    untransformedAncestor->d_ptr->ensureSceneTransform();
     3862    QPointF mappedPoint = (untransformedAncestor->d_ptr->sceneTransform * viewportTransform).map(QPointF(0, 0));
     3863
     3864    // COMBINE
     3865    QTransform matrix = QTransform::fromTranslate(mappedPoint.x(), mappedPoint.y());
     3866    if (untransformedAncestor->d_ptr->transformData)
     3867        matrix = untransformedAncestor->d_ptr->transformData->computedFullTransform(&matrix);
    25963868
    25973869    // Then transform and translate all children.
    25983870    for (int i = 0; i < parents.size(); ++i) {
    25993871        const QGraphicsItem *parent = parents.at(i);
    2600         QPointF pos = parent->pos();
    2601         QTransform moveMatrix;
    2602         moveMatrix.translate(pos.x(), pos.y());
    2603         matrix = (parent->transform() * moveMatrix) * matrix;
     3872        parent->d_ptr->combineTransformFromParent(&matrix);
    26043873    }
    26053874
     
    26443913        if (ok)
    26453914            *ok = true;
    2646         const QPointF &itemPos = d_ptr->pos;
    2647         if (itemPos.isNull())
    2648             return d_ptr->hasTransform ? transform() : QTransform();
    2649         if (d_ptr->hasTransform)
    2650             return transform() * QTransform::fromTranslate(itemPos.x(), itemPos.y());
    2651         return QTransform::fromTranslate(itemPos.x(), itemPos.y());
     3915        QTransform x;
     3916        d_ptr->combineTransformFromParent(&x);
     3917        return x;
    26523918    }
    26533919
     
    26553921    if (otherParent == this) {
    26563922        const QPointF &otherPos = other->d_ptr->pos;
    2657         if (other->d_ptr->hasTransform) {
    2658             QTransform otherToParent = other->transform();
    2659             if (!otherPos.isNull())
    2660                 otherToParent *= QTransform::fromTranslate(otherPos.x(), otherPos.y());
     3923        if (other->d_ptr->transformData) {
     3924            QTransform otherToParent;
     3925            other->d_ptr->combineTransformFromParent(&otherToParent);
    26613926            return otherToParent.inverted(ok);
    2662         } else {
    2663             if (ok)
    2664                 *ok = true;
    2665             return QTransform::fromTranslate(-otherPos.x(), -otherPos.y());
    26663927        }
     3928        if (ok)
     3929            *ok = true;
     3930        return QTransform::fromTranslate(-otherPos.x(), -otherPos.y());
    26673931    }
    26683932
    26693933    // Siblings
    26703934    if (parent == otherParent) {
    2671         bool hasTr = d_ptr->hasTransform;
    2672         bool otherHasTr = other->d_ptr->hasTransform;
     3935        // COMBINE
    26733936        const QPointF &itemPos = d_ptr->pos;
    26743937        const QPointF &otherPos = other->d_ptr->pos;
    2675 
    2676         if (!hasTr && !otherHasTr) {
     3938        if (!d_ptr->transformData && !other->d_ptr->transformData) {
    26773939            QPointF delta = itemPos - otherPos;
    26783940            if (ok)
     
    26813943        }
    26823944
    2683         QTransform itemToParent = QTransform::fromTranslate(itemPos.x(), itemPos.y());
    2684         if (hasTr)
    2685             itemToParent = itemPos.isNull() ? transform() : transform() * itemToParent;
    2686 
    2687         QTransform otherToParent = QTransform::fromTranslate(otherPos.x(), otherPos.y());
    2688         if (otherHasTr)
    2689             otherToParent = otherPos.isNull() ? other->transform() : other->transform() * otherToParent;
    2690 
     3945        QTransform itemToParent;
     3946        d_ptr->combineTransformFromParent(&itemToParent);
     3947        QTransform otherToParent;
     3948        other->d_ptr->combineTransformFromParent(&otherToParent);
    26913949        return itemToParent * otherToParent.inverted(ok);
    26923950    }
     
    26953953    // ancestor, then the only way is to combine their scene transforms.
    26963954    const QGraphicsItem *commonAncestor = commonAncestorItem(other);
    2697     if (!commonAncestor)
    2698         return sceneTransform() * other->sceneTransform().inverted(ok);
     3955    if (!commonAncestor) {
     3956        d_ptr->ensureSceneTransform();
     3957        other->d_ptr->ensureSceneTransform();
     3958        return d_ptr->sceneTransform * other->d_ptr->sceneTransform.inverted(ok);
     3959    }
    26993960
    27003961    // If the two items are cousins (in sibling branches), map both to the
     
    27033964    if (cousins) {
    27043965        bool good = false;
    2705         QTransform thisToScene;
    2706         QTransform otherToScene;
    2707         thisToScene = itemTransform(commonAncestor, &good);
     3966        QTransform thisToScene = itemTransform(commonAncestor, &good);
     3967        QTransform otherToScene(Qt::Uninitialized);
    27083968        if (good)
    27093969            otherToScene = other->itemTransform(commonAncestor, &good);
     
    27243984    const QGraphicsItem *p = child;
    27253985    do {
    2726         const QGraphicsItemPrivate *pd = p->d_ptr;
    2727         if (pd->hasTransform)
    2728             x *= p->transform();
    2729         if (!pd->pos.isNull())
    2730             x *= QTransform::fromTranslate(pd->pos.x(), pd->pos.y());
     3986        p->d_ptr.data()->combineTransformToParent(&x);
    27313987    } while ((p = p->d_ptr->parent) && p != root);
    27323988    if (parentOfOther)
     
    27464002    Use setTransform() instead.
    27474003
    2748     \sa transform(), rotate(), scale(), shear(), translate(), {The Graphics View Coordinate System}
     4004    \sa transform(), {The Graphics View Coordinate System}
    27494005*/
    27504006void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine)
    27514007{
    2752     QTransform oldTransform = this->transform();
    2753     QTransform newTransform;
    2754     if (!combine)
    2755         newTransform = QTransform(matrix);
    2756     else
    2757         newTransform = QTransform(matrix) * oldTransform;
    2758     if (oldTransform == newTransform)
     4008    if (!d_ptr->transformData)
     4009        d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
     4010
     4011    QTransform newTransform(combine ? QTransform(matrix) * d_ptr->transformData->transform : QTransform(matrix));
     4012    if (d_ptr->transformData->transform == newTransform)
    27594013        return;
    27604014
    2761     // Notify the item that the matrix is changing.
    2762     QVariant newTransformVariant(itemChange(ItemMatrixChange,
    2763                                             qVariantFromValue<QMatrix>(newTransform.toAffine())));
    2764     newTransform = QTransform(qVariantValue<QMatrix>(newTransformVariant));
    2765     if (oldTransform == newTransform)
     4015    // Update and set the new transformation.
     4016    if (!(d_ptr->flags & ItemSendsGeometryChanges)) {
     4017        d_ptr->setTransformHelper(newTransform);
    27664018        return;
     4019    }
     4020
     4021    // Notify the item that the transformation matrix is changing.
     4022    const QVariant newMatrixVariant = qVariantFromValue<QMatrix>(newTransform.toAffine());
     4023    newTransform = QTransform(qVariantValue<QMatrix>(itemChange(ItemMatrixChange, newMatrixVariant)));
     4024    if (d_ptr->transformData->transform == newTransform)
     4025        return;
    27674026
    27684027    // Update and set the new transformation.
    2769     d_ptr->fullUpdateHelper(true, true);
    2770     prepareGeometryChange();
    2771     d_ptr->hasTransform = !newTransform.isIdentity();
    2772     d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, newTransform);
    2773     d_ptr->invalidateSceneTransformCache();
     4028    d_ptr->setTransformHelper(newTransform);
    27744029
    27754030    // Send post-notification.
    2776     // NB! We have to change the value from QMatrix to QTransform.
    2777     qVariantSetValue<QTransform>(newTransformVariant, newTransform);
    2778     itemChange(ItemTransformHasChanged, newTransformVariant);
     4031    itemChange(ItemTransformHasChanged, qVariantFromValue<QTransform>(newTransform));
    27794032}
    27804033
     
    27944047    from scene coordinates to item coordinates.
    27954048
    2796     \sa transform(), rotate(), scale(), shear(), translate(), {The Graphics View Coordinate System}
     4049    The transformation matrix is combined with the item's rotation(), scale()
     4050    and transformations() into a combined transformation that maps the item's
     4051    coordinate system to its parent.
     4052
     4053    \sa transform(), setRotation(), setScale(), setTransformOriginPoint(), {The Graphics View Coordinate System}, {Transformations}
    27974054*/
    27984055void QGraphicsItem::setTransform(const QTransform &matrix, bool combine)
    27994056{
    2800     QTransform oldTransform = this->transform();
    2801     QTransform newTransform;
    2802     if (!combine)
    2803         newTransform = matrix;
    2804     else
    2805         newTransform = matrix * oldTransform;
    2806     if (oldTransform == newTransform)
     4057    if (!d_ptr->transformData)
     4058        d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
     4059
     4060    QTransform newTransform(combine ? matrix * d_ptr->transformData->transform : matrix);
     4061    if (d_ptr->transformData->transform == newTransform)
    28074062        return;
     4063
     4064    // Update and set the new transformation.
     4065    if (!(d_ptr->flags & ItemSendsGeometryChanges)) {
     4066        d_ptr->setTransformHelper(newTransform);
     4067        return;
     4068    }
    28084069
    28094070    // Notify the item that the transformation matrix is changing.
     
    28114072                                                  qVariantFromValue<QTransform>(newTransform)));
    28124073    newTransform = qVariantValue<QTransform>(newTransformVariant);
    2813     if (oldTransform == newTransform)
     4074    if (d_ptr->transformData->transform == newTransform)
    28144075        return;
    28154076
    28164077    // Update and set the new transformation.
    2817     d_ptr->fullUpdateHelper(true, true);
    2818     prepareGeometryChange();
    2819     d_ptr->hasTransform = !newTransform.isIdentity();
    2820     d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, newTransform);
    2821     d_ptr->invalidateSceneTransformCache();
     4078    d_ptr->setTransformHelper(newTransform);
    28224079
    28234080    // Send post-notification.
    28244081    itemChange(ItemTransformHasChanged, newTransformVariant);
     4082    d_ptr->sendScenePosChange();
    28254083}
    28264084
     
    28384096    \since 4.3
    28394097
    2840     Resets this item's transformation matrix to the identity matrix. This is
    2841     equivalent to calling \c setTransform(QTransform()).
     4098    Resets this item's transformation matrix to the identity matrix or
     4099    all the transformation properties to their default values.
     4100    This is equivalent to calling \c setTransform(QTransform()).
    28424101
    28434102    \sa setTransform(), transform()
     
    28494108
    28504109/*!
     4110    \obsolete
     4111
     4112    Use
     4113
     4114    \code
     4115    setRotation(rotation() + angle);
     4116    \endcode
     4117
     4118    instead.
     4119
    28514120    Rotates the current item transformation \a angle degrees clockwise around
    28524121    its origin. To translate around an arbitrary point (x, y), you need to
     
    28654134
    28664135/*!
     4136    \obsolete
     4137
     4138    Use
     4139
     4140    \code
     4141    setTransform(QTransform::fromScale(sx, sy), true);
     4142    \endcode
     4143
     4144    instead.
     4145
    28674146    Scales the current item transformation by (\a sx, \a sy) around its
    28684147    origin. To scale from an arbitrary point (x, y), you need to combine
     
    28734152    \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 7
    28744153
    2875     \sa setTransform(), transform(), rotate(), shear(), translate()
     4154    \sa setTransform(), transform()
    28764155*/
    28774156void QGraphicsItem::scale(qreal sx, qreal sy)
     
    28814160
    28824161/*!
     4162    \obsolete
     4163
     4164    Use
     4165
     4166    \code
     4167    setTransform(QTransform().shear(sh, sv), true);
     4168    \endcode
     4169
     4170    instead.
     4171
    28834172    Shears the current item transformation by (\a sh, \a sv).
    28844173
    2885     \sa setTransform(), transform(), rotate(), scale(), translate()
     4174    \sa setTransform(), transform()
    28864175*/
    28874176void QGraphicsItem::shear(qreal sh, qreal sv)
     
    28914180
    28924181/*!
     4182    \obsolete
     4183
     4184    Use setPos() or setTransformOriginPoint() instead. For identical
     4185    behavior, use
     4186
     4187    \code
     4188    setTransform(QTransform::fromTranslate(dx, dy), true);
     4189    \endcode
     4190
    28934191    Translates the current item transformation by (\a dx, \a dy).
    28944192
     
    28974195    which is conceptually separate from its position.
    28984196
    2899     \sa setTransform(), transform(), rotate(), scale(), shear()
     4197    \sa setTransform(), transform()
    29004198*/
    29014199void QGraphicsItem::translate(qreal dx, qreal dy)
     
    29274225
    29284226/*!
    2929     Returns the Z-value, or the elevation, of the item. The Z-value decides
    2930     the stacking order of sibling (neighboring) items.
     4227    Returns the Z-value of the item. The Z-value affects the stacking order of
     4228    sibling (neighboring) items.
    29314229
    29324230    The default Z-value is 0.
    29334231
    2934     \sa setZValue()
     4232    \sa setZValue(), {QGraphicsItem#Sorting}{Sorting}, stackBefore(), ItemStacksBehindParent
    29354233*/
    29364234qreal QGraphicsItem::zValue() const
     
    29404238
    29414239/*!
    2942     Sets the Z-value, or the elevation, of the item, to \a z. The elevation
    2943     decides the stacking order of sibling (neighboring) items. An item of high
    2944     Z-value will be drawn on top of an item with a lower Z-value if they
    2945     share the same parent item. In addition, children of an item will always be drawn
    2946     on top of the parent, regardless of the child's Z-value. Sibling items
    2947     that share the same Z-value will be drawn in an undefined order, although
    2948     the order will stay the same for as long as the items live.
    2949 
    2950     \img graphicsview-zorder.png
    2951 
    2952     Children of different parents are stacked according to the Z-value of
    2953     each item's ancestor item which is an immediate child of the two
    2954     items' closest common ancestor. For example, a robot item might
    2955     define a torso item as the parent of a head item, two arm items,
    2956     and two upper-leg items. The upper-leg items would each be parents
    2957     of one lower-leg item, and each lower-leg item would be parents of
    2958     one foot item.  The stacking order of the feet is the same as the
    2959     stacking order of each foot's ancestor that is an immediate child
    2960     of the two feet's common ancestor (i.e., the torso item); so the
    2961     feet are stacked in the same order as the upper-leg items,
    2962     regardless of each foot's Z-value.
     4240    Sets the Z-value of the item to \a z. The Z value decides the stacking
     4241    order of sibling (neighboring) items. A sibling item of high Z value will
     4242    always be drawn on top of another sibling item with a lower Z value.
     4243
     4244    If you restore the Z value, the item's insertion order will decide its
     4245    stacking order.
    29634246
    29644247    The Z-value does not affect the item's size in any way.
     
    29664249    The default Z-value is 0.
    29674250
    2968     \sa zValue()
     4251    \sa zValue(), {QGraphicsItem#Sorting}{Sorting}, stackBefore(), ItemStacksBehindParent
    29694252*/
    29704253void QGraphicsItem::setZValue(qreal z)
    29714254{
    2972     const QVariant newZVariant(itemChange(ItemZValueChange, double(z)));
    2973     qreal newZ = qreal(newZVariant.toDouble());
     4255    const QVariant newZVariant(itemChange(ItemZValueChange, z));
     4256    qreal newZ = newZVariant.toReal();
    29744257    if (newZ == d_ptr->z)
    29754258        return;
    2976     d_ptr->z = z;
    2977     d_ptr->fullUpdateHelper();
    29784259
    29794260    if (d_ptr->scene) {
    2980         // Invalidate any sort caching; arrival of a new item means we need to
    2981         // resort.
    2982         d_ptr->scene->d_func()->invalidateSortCache();
    2983     }
     4261        // Z Value has changed, we have to notify the index.
     4262        d_ptr->scene->d_func()->index->itemChange(this, ItemZValueChange, newZVariant);
     4263    }
     4264
     4265    d_ptr->z = newZ;
     4266    if (d_ptr->parent)
     4267        d_ptr->parent->d_ptr->needSortChildren = 1;
     4268    else if (d_ptr->scene)
     4269        d_ptr->scene->d_func()->needSortTopLevelItems = 1;
     4270
     4271    if (d_ptr->scene)
     4272        d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true);
    29844273
    29854274    itemChange(ItemZValueHasChanged, newZVariant);
     4275
     4276    if (d_ptr->flags & ItemNegativeZStacksBehindParent)
     4277        setFlag(QGraphicsItem::ItemStacksBehindParent, z < qreal(0.0));
     4278
     4279    if (d_ptr->isObject)
     4280        emit static_cast<QGraphicsObject *>(this)->zChanged();
     4281}
     4282
     4283/*!
     4284    \internal
     4285
     4286    Ensures that the list of children is sorted by insertion order, and that
     4287    the siblingIndexes are packed (no gaps), and start at 0.
     4288
     4289    ### This function is almost identical to
     4290    QGraphicsScenePrivate::ensureSequentialTopLevelSiblingIndexes().
     4291*/
     4292void QGraphicsItemPrivate::ensureSequentialSiblingIndex()
     4293{
     4294    if (!sequentialOrdering) {
     4295        qSort(children.begin(), children.end(), insertionOrder);
     4296        sequentialOrdering = 1;
     4297        needSortChildren = 1;
     4298    }
     4299    if (holesInSiblingIndex) {
     4300        holesInSiblingIndex = 0;
     4301        for (int i = 0; i < children.size(); ++i)
     4302            children[i]->d_ptr->siblingIndex = i;
     4303    }
     4304}
     4305
     4306/*!
     4307    \internal
     4308*/
     4309inline void QGraphicsItemPrivate::sendScenePosChange()
     4310{
     4311    Q_Q(QGraphicsItem);
     4312    if (scene) {
     4313        if (flags & QGraphicsItem::ItemSendsScenePositionChanges)
     4314            q->itemChange(QGraphicsItem::ItemScenePositionHasChanged, q->scenePos());
     4315        if (scenePosDescendants) {
     4316            foreach (QGraphicsItem *item, scene->d_func()->scenePosItems) {
     4317                if (q->isAncestorOf(item))
     4318                    item->itemChange(QGraphicsItem::ItemScenePositionHasChanged, item->scenePos());
     4319            }
     4320        }
     4321    }
     4322}
     4323
     4324/*!
     4325    \since 4.6
     4326
     4327    Stacks this item before \a sibling, which must be a sibling item (i.e., the
     4328    two items must share the same parent item, or must both be toplevel items).
     4329    The \a sibling must have the same Z value as this item, otherwise calling
     4330    this function will have no effect.
     4331
     4332    By default, all sibling items are stacked by insertion order (i.e., the
     4333    first item you add is drawn before the next item you add). If two items' Z
     4334    values are different, then the item with the highest Z value is drawn on
     4335    top. When the Z values are the same, the insertion order will decide the
     4336    stacking order.
     4337
     4338    \sa setZValue(), ItemStacksBehindParent, {QGraphicsItem#Sorting}{Sorting}
     4339*/
     4340void QGraphicsItem::stackBefore(const QGraphicsItem *sibling)
     4341{
     4342    if (sibling == this)
     4343        return;
     4344    if (!sibling || d_ptr->parent != sibling->parentItem()) {
     4345        qWarning("QGraphicsItem::stackUnder: cannot stack under %p, which must be a sibling", sibling);
     4346        return;
     4347    }
     4348    QList<QGraphicsItem *> *siblings = d_ptr->parent
     4349                                       ? &d_ptr->parent->d_ptr->children
     4350                                       : (d_ptr->scene ? &d_ptr->scene->d_func()->topLevelItems : 0);
     4351    if (!siblings) {
     4352        qWarning("QGraphicsItem::stackUnder: cannot stack under %p, which must be a sibling", sibling);
     4353        return;
     4354    }
     4355
     4356    // First, make sure that the sibling indexes have no holes. This also
     4357    // marks the children list for sorting.
     4358    if (d_ptr->parent)
     4359        d_ptr->parent->d_ptr->ensureSequentialSiblingIndex();
     4360    else
     4361        d_ptr->scene->d_func()->ensureSequentialTopLevelSiblingIndexes();
     4362
     4363    // Only move items with the same Z value, and that need moving.
     4364    int siblingIndex = sibling->d_ptr->siblingIndex;
     4365    int myIndex = d_ptr->siblingIndex;
     4366    if (myIndex >= siblingIndex) {
     4367        siblings->move(myIndex, siblingIndex);
     4368        // Fixup the insertion ordering.
     4369        for (int i = 0; i < siblings->size(); ++i) {
     4370            int &index = siblings->at(i)->d_ptr->siblingIndex;
     4371            if (i != siblingIndex && index >= siblingIndex && index <= myIndex)
     4372                ++index;
     4373        }
     4374        d_ptr->siblingIndex = siblingIndex;
     4375        for (int i = 0; i < siblings->size(); ++i) {
     4376            int &index = siblings->at(i)->d_ptr->siblingIndex;
     4377            if (i != siblingIndex && index >= siblingIndex && index <= myIndex)
     4378                siblings->at(i)->d_ptr->siblingOrderChange();
     4379        }
     4380        d_ptr->siblingOrderChange();
     4381    }
    29864382}
    29874383
     
    30054401QRectF QGraphicsItem::childrenBoundingRect() const
    30064402{
    3007     QRectF childRect;
    3008     foreach (QGraphicsItem *child, children()) {
    3009         QPointF childPos = child->pos();
    3010         QTransform matrix = child->transform();
    3011         if (!childPos.isNull())
    3012             matrix *= QTransform::fromTranslate(childPos.x(), childPos.y());
    3013         childRect |= matrix.mapRect(child->boundingRect() | child->childrenBoundingRect());
    3014     }
    3015     return childRect;
     4403    if (!d_ptr->dirtyChildrenBoundingRect)
     4404        return d_ptr->childrenBoundingRect;
     4405
     4406    d_ptr->childrenBoundingRect = QRectF();
     4407    d_ptr->childrenBoundingRectHelper(0, &d_ptr->childrenBoundingRect);
     4408    d_ptr->dirtyChildrenBoundingRect = 0;
     4409    return d_ptr->childrenBoundingRect;
    30164410}
    30174411
     
    30264420    Although the item's shape can be arbitrary, the bounding rect is
    30274421    always rectangular, and it is unaffected by the items'
    3028     transformation (scale(), rotate(), etc.).
     4422    transformation.
    30294423
    30304424    If you want to change the item's bounding rectangle, you must first call
     
    30584452{
    30594453    // Find translate-only offset
     4454    // COMBINE
    30604455    QPointF offset;
    30614456    const QGraphicsItem *parentItem = this;
    30624457    const QGraphicsItemPrivate *itemd;
    30634458    do {
    3064         itemd = parentItem->d_ptr;
    3065         if (itemd->hasTransform)
     4459        itemd = parentItem->d_ptr.data();
     4460        if (itemd->transformData)
    30664461            break;
    30674462        offset += itemd->pos;
     
    30704465    QRectF br = boundingRect();
    30714466    br.translate(offset);
    3072     return !parentItem ? br : parentItem->sceneTransform().mapRect(br);
     4467    if (!parentItem)
     4468        return br;
     4469    if (parentItem->d_ptr->hasTranslateOnlySceneTransform()) {
     4470        br.translate(parentItem->d_ptr->sceneTransform.dx(), parentItem->d_ptr->sceneTransform.dy());
     4471        return br;
     4472    }
     4473    return parentItem->d_ptr->sceneTransform.mapRect(br);
    30734474}
    30744475
     
    31424543{
    31434544    Q_D(const QGraphicsItem);
    3144     if (!d->dirtyClipPath)
    3145         return d->emptyClipPath ? QPainterPath() : d->cachedClipPath;
    3146 
    3147     if (!isClipped()) {
    3148         d_ptr->setCachedClipPath(QPainterPath());
    3149         return d->cachedClipPath;
    3150     }
     4545    if (!isClipped())
     4546        return QPainterPath();
    31514547
    31524548    const QRectF thisBoundingRect(boundingRect());
    3153     if (thisBoundingRect.isEmpty()) {
    3154         if (d_ptr->flags & ItemClipsChildrenToShape)
    3155             d_ptr->setEmptyCachedClipPathRecursively();
    3156         else
    3157             d_ptr->setEmptyCachedClipPath();
     4549    if (thisBoundingRect.isEmpty())
    31584550        return QPainterPath();
    3159     }
    31604551
    31614552    QPainterPath clip;
     
    31684559
    31694560        // Intersect any in-between clips starting at the top and moving downwards.
    3170         bool foundValidClipPath = false;
    31714561        while ((parent = parent->d_ptr->parent)) {
    31724562            if (parent->d_ptr->flags & ItemClipsChildrenToShape) {
    31734563                // Map clip to the current parent and intersect with its shape/clipPath
    31744564                clip = lastParent->itemTransform(parent).map(clip);
    3175                 if ((foundValidClipPath = !parent->d_ptr->dirtyClipPath && parent->isClipped())) {
    3176                     if (parent->d_ptr->emptyClipPath) {
    3177                         if (d_ptr->flags & ItemClipsChildrenToShape)
    3178                             d_ptr->setEmptyCachedClipPathRecursively();
    3179                         else
    3180                             d_ptr->setEmptyCachedClipPath();
    3181                         return QPainterPath();
    3182                     }
    3183                     clip = clip.intersected(parent->d_ptr->cachedClipPath);
    3184                     if (!(parent->d_ptr->flags & ItemClipsToShape))
    3185                         clip = clip.intersected(parent->shape());
    3186                 } else {
    3187                     clip = clip.intersected(parent->shape());
    3188                 }
    3189 
    3190                 if (clip.isEmpty()) {
    3191                     if (d_ptr->flags & ItemClipsChildrenToShape)
    3192                         d_ptr->setEmptyCachedClipPathRecursively();
    3193                     else
    3194                         d_ptr->setEmptyCachedClipPath();
     4565                clip = clip.intersected(parent->shape());
     4566                if (clip.isEmpty())
    31954567                    return clip;
    3196                 }
    31974568                lastParent = parent;
    31984569            }
    31994570
    3200             if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
    3201                 || foundValidClipPath) {
     4571            if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren))
    32024572                break;
    3203             }
    32044573        }
    32054574
     
    32144583        clip = clip.intersected(shape());
    32154584
    3216     d_ptr->setCachedClipPath(clip);
    32174585    return clip;
    32184586}
     
    32364604
    32374605/*!
    3238     Returns true if this item collides with \a other; otherwise returns false.
    3239     The ways items collide is determined by \a mode. The default value for \a
    3240     mode is Qt::IntersectsItemShape; \a other collides with this item if it
    3241     either intersects, contains, or is contained by this item's shape.
     4606
     4607    Returns true if this item collides with \a other; otherwise
     4608    returns false.
     4609
     4610    The \a mode is applied to \a other, and the resulting shape or
     4611    bounding rectangle is then compared to this item's shape. The
     4612    default value for \a mode is Qt::IntersectsItemShape; \a other
     4613    collides with this item if it either intersects, contains, or is
     4614    contained by this item's shape (see Qt::ItemSelectionMode for
     4615    details).
    32424616
    32434617    The default implementation is based on shape intersection, and it calls
     
    32944668    intersects, contains, or is contained by this item's shape.
    32954669
     4670    Note that this function checks whether the item's shape or
     4671    bounding rectangle (depending on \a mode) is contained within \a
     4672    path, and not whether \a path is contained within the items shape
     4673    or bounding rectangle.
     4674
    32964675    \sa collidesWithItem(), contains(), shape()
    32974676*/
     
    33344713    Returns a list of all items that collide with this item.
    33354714
    3336     The way collisions are detected is determined by \a mode. The default
    3337     value for \a mode is Qt::IntersectsItemShape; All items whose shape
    3338     intersects or is contained by this item's shape are returned.
    3339 
    3340     \sa QGraphicsScene::collidingItems(), collidesWithItem()
     4715    The way collisions are detected is determined by applying \a mode
     4716    to items that are compared to this item, i.e., each item's shape
     4717    or bounding rectangle is checked against this item's shape. The
     4718    default value for \a mode is Qt::IntersectsItemShape.
     4719
     4720    \sa collidesWithItem()
    33414721*/
    33424722QList<QGraphicsItem *> QGraphicsItem::collidingItems(Qt::ItemSelectionMode mode) const
     
    34334813    if (!item)
    34344814        return false;
    3435     return QGraphicsScenePrivate::closestItemFirst_withoutCache(item, this)
     4815    return qt_closestItemFirst(item, this)
    34364816        && qt_QGraphicsItem_isObscured(this, item, boundingRect());
    34374817}
     
    35184898
    35194899    // Transform QRegion back to device space
    3520     QTransform unscale;
    3521     unscale.scale(1 / granularity, 1 / granularity);
     4900    QTransform unscale = QTransform::fromScale(1 / granularity, 1 / granularity);
    35224901    QRegion r;
    35234902    QBitmap colorMask = QBitmap::fromImage(mask.createMaskFromColor(0));
     
    36154994    All painting is done in local coordinates.
    36164995
    3617     \sa setCacheMode(), QPen::width(), {Item Coordinates}
     4996    \sa setCacheMode(), QPen::width(), {Item Coordinates}, ItemUsesExtendedStyleOption
    36184997*/
    36194998
     
    36225001    Returns true if we can discard an update request; otherwise false.
    36235002*/
    3624 bool QGraphicsItemPrivate::discardUpdateRequest(bool ignoreClipping,
    3625                                                 bool ignoreVisibleBit,
    3626                                                 bool ignoreDirtyBit) const
     5003bool QGraphicsItemPrivate::discardUpdateRequest(bool ignoreVisibleBit, bool ignoreDirtyBit,
     5004                                                bool ignoreOpacity) const
    36275005{
    36285006    // No scene, or if the scene is updating everything, means we have nothing
    36295007    // to do. The only exception is if the scene tracks the growing scene rect.
    3630     return (!visible && !ignoreVisibleBit)
    3631            || (dirty && !ignoreDirtyBit)
    3632            || !scene
    3633            || (scene->d_func()->updateAll && scene->d_func()->hasSceneRect)
    3634            || (!ignoreClipping && (childrenClippedToShape() && isClippedAway()))
    3635            || (childrenCombineOpacity() && isFullyTransparent());
     5008    return !scene
     5009           || (!visible && !ignoreVisibleBit && !this->ignoreVisible)
     5010           || (!ignoreDirtyBit && fullUpdatePending)
     5011           || (!ignoreOpacity && !this->ignoreOpacity && childrenCombineOpacity() && isFullyTransparent());
    36365012}
    36375013
    36385014/*!
    36395015    \internal
    3640 
    3641     Asks the scene to mark this item's scene rect as dirty, requesting a
    3642     redraw.  This does not invalidate any cache.
    3643 
    3644     The \a force argument is for the update call in setVisible(), which is the
    3645     only case where the item's background should be marked as dirty even when
    3646     the item isn't visible.
    3647 */
    3648 void QGraphicsItemPrivate::updateHelper(const QRectF &rect, bool force, bool maybeDirtyClipPath)
    3649 {
    3650     // No scene, or if the scene is updating everything, means we have nothing
    3651     // to do. The only exception is if the scene tracks the growing scene rect.
    3652     if (discardUpdateRequest(/*ignoreClipping=*/maybeDirtyClipPath, /*ignoreVisibleBit=*/force))
     5016*/
     5017int QGraphicsItemPrivate::depth() const
     5018{
     5019    if (itemDepth == -1)
     5020        const_cast<QGraphicsItemPrivate *>(this)->resolveDepth();
     5021
     5022    return itemDepth;
     5023}
     5024
     5025/*!
     5026    \internal
     5027*/
     5028#ifndef QT_NO_GRAPHICSEFFECT
     5029void QGraphicsItemPrivate::invalidateGraphicsEffectsRecursively()
     5030{
     5031    QGraphicsItemPrivate *itemPrivate = this;
     5032    do {
     5033        if (itemPrivate->graphicsEffect) {
     5034            itemPrivate->notifyInvalidated = 1;
     5035
     5036            if (!itemPrivate->updateDueToGraphicsEffect)
     5037                static_cast<QGraphicsItemEffectSourcePrivate *>(itemPrivate->graphicsEffect->d_func()->source->d_func())->invalidateCache();
     5038        }
     5039    } while ((itemPrivate = itemPrivate->parent ? itemPrivate->parent->d_ptr.data() : 0));
     5040}
     5041#endif //QT_NO_GRAPHICSEFFECT
     5042
     5043/*!
     5044    \internal
     5045*/
     5046void QGraphicsItemPrivate::invalidateDepthRecursively()
     5047{
     5048    if (itemDepth == -1)
    36535049        return;
    36545050
    3655     if (rect.isNull())
    3656         dirty = 1;
    3657     scene->itemUpdated(q_ptr, rect);
     5051    itemDepth = -1;
     5052    for (int i = 0; i < children.size(); ++i)
     5053        children.at(i)->d_ptr->invalidateDepthRecursively();
    36585054}
    36595055
     
    36615057    \internal
    36625058
    3663     Propagates updates to \a item and all its children.
    3664 */
    3665 void QGraphicsItemPrivate::fullUpdateHelper(bool childrenOnly, bool maybeDirtyClipPath)
    3666 {
    3667     if (discardUpdateRequest(/*ignoreClipping=*/maybeDirtyClipPath,
    3668                              /*ignoreVisibleBit=*/false,
    3669                              /*ignoreDirtyBit=*/true)) {
    3670         return;
    3671     }
    3672 
    3673     if (!childrenOnly && !dirty) {
    3674         // Effectively the same as updateHelper(QRectF(), false, maybeDirtyClipPath).
    3675         dirty = 1;
    3676         scene->itemUpdated(q_ptr, QRectF());
    3677     }
    3678 
    3679     if (dirtyChildren || childrenClippedToShape()) {
    3680         // Unnecessary to update children as well.
    3681         return;
    3682     }
    3683 
    3684     if (ancestorFlags & AncestorClipsChildren) {
    3685         Q_Q(QGraphicsItem);
    3686         // Check if we can avoid updating all children.
    3687         QGraphicsItem *p = parent;
    3688         QRectF br = q->boundingRect();
    3689         while (p) {
    3690             if (p->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) {
    3691                 bool ok;
    3692                 QTransform x = q->itemTransform(p, &ok);
    3693                 if (!ok)
    3694                     break;
    3695                 if (x.mapRect(br).contains(p->boundingRect()))
    3696                     return;
    3697             }
    3698             p = p->d_ptr->parent;
    3699             if (!p || !(p->d_ptr->ancestorFlags & AncestorClipsChildren))
    3700                 break;
    3701             // ### check one level only
    3702             break;
    3703         }
    3704     }
    3705     foreach (QGraphicsItem *child, children)
    3706         child->d_ptr->fullUpdateHelper(false, maybeDirtyClipPath);
    3707     dirtyChildren = 1;
    3708 }
    3709 
    3710 static inline bool qt_allChildrenCombineOpacity(QGraphicsItem *parent)
    3711 {
    3712     Q_ASSERT(parent);
    3713     if (parent->flags() & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)
    3714         return false;
    3715 
    3716     const QList<QGraphicsItem *> children(parent->childItems());
    3717     for (int i = 0; i < children.size(); ++i) {
    3718         if (children.at(i)->flags() & QGraphicsItem::ItemIgnoresParentOpacity)
    3719             return false;
    3720     }
    3721     return true;
    3722 }
    3723 
    3724 void QGraphicsItemPrivate::updateEffectiveOpacity()
    3725 {
    3726     Q_Q(QGraphicsItem);
    3727     if (parent) {
    3728         resolveEffectiveOpacity(parent->effectiveOpacity());
    3729         parent->d_ptr->allChildrenCombineOpacity = qt_allChildrenCombineOpacity(parent);
    3730     } else {
    3731         resolveEffectiveOpacity(1.0);
    3732     }
    3733     allChildrenCombineOpacity = qt_allChildrenCombineOpacity(q);
     5059    Resolves the stacking depth of this object and all its ancestors.
     5060*/
     5061void QGraphicsItemPrivate::resolveDepth()
     5062{
     5063    if (!parent)
     5064        itemDepth = 0;
     5065    else {
     5066        if (parent->d_ptr->itemDepth == -1)
     5067            parent->d_ptr->resolveDepth();
     5068        itemDepth = parent->d_ptr->itemDepth + 1;
     5069    }
    37345070}
    37355071
     
    37375073    \internal
    37385074
    3739     Resolves and propagates this item's effective opacity to its children.
    3740 */
    3741 void QGraphicsItemPrivate::resolveEffectiveOpacity(qreal parentEffectiveOpacity)
    3742 {
    3743     Q_Q(QGraphicsItem);
    3744     QGraphicsItem::GraphicsItemFlags myFlags = q->flags();
    3745     QGraphicsItem::GraphicsItemFlags parentFlags = parent ? parent->flags() : QGraphicsItem::GraphicsItemFlags(0);
    3746 
    3747     // My local opacity is always part of my effective opacity.
    3748     qreal myEffectiveOpacity = q->opacity();
    3749 
    3750     // If I have a parent, and I don't ignore my parent's opacity, and my
    3751     // parent propagates to me, then combine my local opacity with my parent's
    3752     // effective opacity into my effective opacity.
    3753     if (parent
    3754         && !(myFlags & QGraphicsItem::ItemIgnoresParentOpacity)
    3755         && !(parentFlags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) {
    3756         myEffectiveOpacity *= parentEffectiveOpacity;
    3757     }
    3758 
    3759     // Set this item's resolved opacity.
    3760     if (qFuzzyCompare(myEffectiveOpacity, qreal(1.0))) {
    3761         // Opaque, unset effective opacity.
    3762         hasEffectiveOpacity = 0;
    3763         unsetExtra(ExtraEffectiveOpacity);
    3764     } else {
    3765         hasEffectiveOpacity = 1;
    3766         setExtra(ExtraEffectiveOpacity, myEffectiveOpacity);
    3767     }
    3768 
    3769     // Resolve children always.
    3770     for (int i = 0; i < children.size(); ++i)
    3771         children.at(i)->d_ptr->resolveEffectiveOpacity(myEffectiveOpacity);
     5075    ### This function is almost identical to
     5076    QGraphicsScenePrivate::registerTopLevelItem().
     5077*/
     5078void QGraphicsItemPrivate::addChild(QGraphicsItem *child)
     5079{
     5080    // Remove all holes from the sibling index list. Now the max index
     5081    // number is equal to the size of the children list.
     5082    ensureSequentialSiblingIndex();
     5083    needSortChildren = 1; // ### maybe 0
     5084    child->d_ptr->siblingIndex = children.size();
     5085    children.append(child);
    37725086}
    37735087
     
    37755089    \internal
    37765090
    3777     Resolves the stacking depth of this object and all its children.
    3778 */
    3779 void QGraphicsItemPrivate::resolveDepth(int parentDepth)
    3780 {
    3781     depth = parentDepth + 1;
    3782     for (int i = 0; i < children.size(); ++i)
    3783         children.at(i)->d_ptr->resolveDepth(depth);
     5091    ### This function is almost identical to
     5092    QGraphicsScenePrivate::unregisterTopLevelItem().
     5093*/
     5094void QGraphicsItemPrivate::removeChild(QGraphicsItem *child)
     5095{
     5096    // When removing elements in the middle of the children list,
     5097    // there will be a "gap" in the list of sibling indexes (0,1,3,4).
     5098    if (!holesInSiblingIndex)
     5099        holesInSiblingIndex = child->d_ptr->siblingIndex != children.size() - 1;
     5100    if (sequentialOrdering && !holesInSiblingIndex)
     5101        children.removeAt(child->d_ptr->siblingIndex);
     5102    else
     5103        children.removeOne(child);
     5104    // NB! Do not use children.removeAt(child->d_ptr->siblingIndex) because
     5105    // the child is not guaranteed to be at the index after the list is sorted.
     5106    // (see ensureSortedChildren()).
     5107    child->d_ptr->siblingIndex = -1;
    37845108}
    37855109
     
    37875111    \internal
    37885112*/
    3789 void QGraphicsItemPrivate::invalidateSceneTransformCache()
    3790 {
    3791     if (!scene || (parent && sceneTransformIndex == -1))
    3792         return;
    3793     if (sceneTransformIndex != -1)
    3794         scene->d_func()->validTransforms.setBit(sceneTransformIndex, 0);
    3795     for (int i = 0; i < children.size(); ++i)
    3796         children.at(i)->d_ptr->invalidateSceneTransformCache();
    3797 }
    3798 
     5113QGraphicsItemCache *QGraphicsItemPrivate::maybeExtraItemCache() const
     5114{
     5115    return (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData));
     5116}
     5117
     5118/*!
     5119    \internal
     5120*/
    37995121QGraphicsItemCache *QGraphicsItemPrivate::extraItemCache() const
    38005122{
     
    38085130}
    38095131
     5132/*!
     5133    \internal
     5134*/
    38105135void QGraphicsItemPrivate::removeExtraItemCache()
    38115136{
     
    38185143}
    38195144
    3820 void QGraphicsItemPrivate::setEmptyCachedClipPathRecursively(const QRectF &emptyIfOutsideThisRect)
    3821 {
    3822     setEmptyCachedClipPath();
    3823 
    3824     const bool checkRect = !emptyIfOutsideThisRect.isNull()
    3825                            && !(flags & QGraphicsItem::ItemClipsChildrenToShape);
    3826     for (int i = 0; i < children.size(); ++i) {
    3827         if (!checkRect) {
    3828             children.at(i)->d_ptr->setEmptyCachedClipPathRecursively();
    3829             continue;
     5145// Traverses all the ancestors up to the top-level and updates the pointer to
     5146// always point to the top-most item that has a dirty scene transform.
     5147// It then backtracks to the top-most dirty item and start calculating the
     5148// scene transform by combining the item's transform (+pos) with the parent's
     5149// cached scene transform (which we at this point know for sure is valid).
     5150void QGraphicsItemPrivate::ensureSceneTransformRecursive(QGraphicsItem **topMostDirtyItem)
     5151{
     5152    Q_ASSERT(topMostDirtyItem);
     5153
     5154    if (dirtySceneTransform)
     5155        *topMostDirtyItem = q_ptr;
     5156
     5157    if (parent)
     5158        parent->d_ptr->ensureSceneTransformRecursive(topMostDirtyItem);
     5159
     5160    if (*topMostDirtyItem == q_ptr) {
     5161        if (!dirtySceneTransform)
     5162            return; // OK, neither my ancestors nor I have dirty scene transforms.
     5163        *topMostDirtyItem = 0;
     5164    } else if (*topMostDirtyItem) {
     5165        return; // Continue backtrack.
     5166    }
     5167
     5168    // This item and all its descendants have dirty scene transforms.
     5169    // We're about to validate this item's scene transform, so we have to
     5170    // invalidate all the children; otherwise there's no way for the descendants
     5171    // to detect that the ancestor has changed.
     5172    invalidateChildrenSceneTransform();
     5173
     5174    // COMBINE my transform with the parent's scene transform.
     5175    updateSceneTransformFromParent();
     5176    Q_ASSERT(!dirtySceneTransform);
     5177}
     5178
     5179/*!
     5180    \internal
     5181*/
     5182void QGraphicsItemPrivate::setSubFocus(QGraphicsItem *rootItem)
     5183{
     5184    // Update focus child chain. Stop at panels, or if this item
     5185    // is hidden, stop at the first item with a visible parent.
     5186    QGraphicsItem *parent = rootItem ? rootItem : q_ptr;
     5187    do {
     5188        // Clear any existing ancestor's subFocusItem.
     5189        if (parent != q_ptr && parent->d_ptr->subFocusItem) {
     5190            if (parent->d_ptr->subFocusItem == q_ptr)
     5191                break;
     5192            parent->d_ptr->subFocusItem->d_ptr->clearSubFocus();
    38305193        }
    3831 
    3832         QGraphicsItem *child = children.at(i);
    3833         const QRectF rect = child->mapRectFromParent(emptyIfOutsideThisRect);
    3834         if (rect.intersects(child->boundingRect()))
    3835             child->d_ptr->invalidateCachedClipPathRecursively(false, rect);
    3836         else
    3837             child->d_ptr->setEmptyCachedClipPathRecursively(rect);
    3838     }
    3839 }
    3840 
    3841 void QGraphicsItemPrivate::invalidateCachedClipPathRecursively(bool childrenOnly, const QRectF &emptyIfOutsideThisRect)
    3842 {
    3843     if (!childrenOnly)
    3844         invalidateCachedClipPath();
    3845 
    3846     const bool checkRect = !emptyIfOutsideThisRect.isNull();
    3847     for (int i = 0; i < children.size(); ++i) {
    3848         if (!checkRect) {
    3849             children.at(i)->d_ptr->invalidateCachedClipPathRecursively(false);
    3850             continue;
    3851         }
    3852 
    3853         QGraphicsItem *child = children.at(i);
    3854         const QRectF rect = child->mapRectFromParent(emptyIfOutsideThisRect);
    3855         if (rect.intersects(child->boundingRect()))
    3856             child->d_ptr->invalidateCachedClipPathRecursively(false, rect);
    3857         else
    3858             child->d_ptr->setEmptyCachedClipPathRecursively(rect);
    3859     }
    3860 }
    3861 
    3862 void QGraphicsItemPrivate::updateCachedClipPathFromSetPosHelper(const QPointF &newPos)
    3863 {
    3864     Q_ASSERT(inSetPosHelper);
    3865 
    3866     if (!(ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren))
    3867         return; // Not clipped by any ancestor.
    3868 
    3869     // Find closest clip ancestor and transform.
    3870     Q_Q(QGraphicsItem);
    3871     QTransform thisToParentTransform = hasTransform
    3872                                        ? q->transform() * QTransform::fromTranslate(newPos.x(), newPos.y())
    3873                                        : QTransform::fromTranslate(newPos.x(), newPos.y());
    3874     QGraphicsItem *clipParent = parent;
    3875     while (clipParent && !(clipParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)) {
    3876         if (clipParent->d_ptr->hasTransform)
    3877             thisToParentTransform *= clipParent->transform();
    3878         if (!clipParent->d_ptr->pos.isNull()) {
    3879             thisToParentTransform *= QTransform::fromTranslate(clipParent->d_ptr->pos.x(),
    3880                                                                clipParent->d_ptr->pos.y());
    3881         }
    3882         clipParent = clipParent->d_ptr->parent;
    3883     }
    3884 
    3885     // thisToParentTransform is now the same as q->itemTransform(clipParent), except
    3886     // that the new position (which is not yet set on the item) is taken into account.
    3887     Q_ASSERT(clipParent);
    3888     Q_ASSERT(clipParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
    3889 
    3890     // From here everything is calculated in clip parent's coordinates.
    3891     const QRectF parentBoundingRect(clipParent->boundingRect());
    3892     const QRectF thisBoundingRect(thisToParentTransform.mapRect(q->boundingRect()));
    3893 
    3894     if (!parentBoundingRect.intersects(thisBoundingRect)) {
    3895         // Item is moved outside the clip parent's bounding rect,
    3896         // i.e. it is fully clipped and the clip path is empty.
    3897         if (flags & QGraphicsItem::ItemClipsChildrenToShape)
    3898             setEmptyCachedClipPathRecursively();
    3899         else
    3900             setEmptyCachedClipPathRecursively(thisToParentTransform.inverted().mapRect(parentBoundingRect));
    3901         return;
    3902     }
    3903 
    3904     const QPainterPath parentClip(clipParent->isClipped() ? clipParent->clipPath() : clipParent->shape());
    3905     if (parentClip.contains(thisBoundingRect))
    3906         return; // Item is inside the clip parent's shape. No update required.
    3907 
    3908     const QRectF parentClipRect(parentClip.controlPointRect());
    3909     if (!parentClipRect.intersects(thisBoundingRect)) {
    3910         // Item is moved outside the clip parent's shape,
    3911         // i.e. it is fully clipped and the clip path is empty.
    3912         if (flags & QGraphicsItem::ItemClipsChildrenToShape)
    3913             setEmptyCachedClipPathRecursively();
    3914         else
    3915             setEmptyCachedClipPathRecursively(thisToParentTransform.inverted().mapRect(parentClipRect));
    3916     } else {
    3917         // Item is partially inside the clip parent's shape,
    3918         // i.e. the cached clip path must be invalidated.
    3919         invalidateCachedClipPathRecursively(false, thisToParentTransform.inverted().mapRect(parentClipRect));
    3920     }
     5194        parent->d_ptr->subFocusItem = q_ptr;
     5195        parent->d_ptr->subFocusItemChange();
     5196    } while (!parent->isPanel() && (parent = parent->d_ptr->parent) && (visible || !parent->d_ptr->visible));
     5197
     5198    if (scene && !scene->isActive())
     5199        scene->d_func()->lastFocusItem = subFocusItem;
     5200}
     5201
     5202/*!
     5203    \internal
     5204*/
     5205void QGraphicsItemPrivate::clearSubFocus(QGraphicsItem *rootItem)
     5206{
     5207    // Reset sub focus chain.
     5208    QGraphicsItem *parent = rootItem ? rootItem : q_ptr;
     5209    do {
     5210        if (parent->d_ptr->subFocusItem != q_ptr)
     5211            break;
     5212        parent->d_ptr->subFocusItem = 0;
     5213        parent->d_ptr->subFocusItemChange();
     5214    } while (!parent->isPanel() && (parent = parent->d_ptr->parent));
     5215}
     5216
     5217/*!
     5218    \internal
     5219
     5220    Sets the focusProxy pointer to 0 for all items that have this item as their
     5221    focusProxy. ### Qt 5: Use QPointer instead.
     5222*/
     5223void QGraphicsItemPrivate::resetFocusProxy()
     5224{
     5225    for (int i = 0; i < focusProxyRefs.size(); ++i)
     5226        *focusProxyRefs.at(i) = 0;
     5227    focusProxyRefs.clear();
     5228}
     5229
     5230/*!
     5231    \internal
     5232
     5233    Subclasses can reimplement this function to be notified when subFocusItem
     5234    changes.
     5235*/
     5236void QGraphicsItemPrivate::subFocusItemChange()
     5237{
     5238}
     5239
     5240/*!
     5241    \internal
     5242
     5243    Subclasses can reimplement this function to be notified when its
     5244    siblingIndex order is changed.
     5245*/
     5246void QGraphicsItemPrivate::siblingOrderChange()
     5247{
    39215248}
    39225249
     
    39545281        return;
    39555282
     5283    // Make sure we notify effects about invalidated source.
     5284#ifndef QT_NO_GRAPHICSEFFECT
     5285    d_ptr->invalidateGraphicsEffectsRecursively();
     5286#endif //QT_NO_GRAPHICSEFFECT
     5287
    39565288    if (CacheMode(d_ptr->cacheMode) != NoCache) {
     5289        // Invalidate cache.
    39575290        QGraphicsItemCache *cache = d_ptr->extraItemCache();
    3958         if (d_ptr->discardUpdateRequest(/* ignoreVisibleBit = */ false,
    3959                                         /* ignoreClipping = */ false,
    3960                                         /* ignoreDirtyBit = */ true)) {
    3961             return;
    3962         }
    3963 
    3964         // Invalidate cache.
    3965         if (rect.isNull()) {
    3966             cache->allExposed = true;
    3967             cache->exposed.clear();
    3968         } else {
    3969             cache->exposed.append(rect);
     5291        if (!cache->allExposed) {
     5292            if (rect.isNull()) {
     5293                cache->allExposed = true;
     5294                cache->exposed.clear();
     5295            } else {
     5296                cache->exposed.append(rect);
     5297            }
    39705298        }
    39715299        // Only invalidate cache; item is already dirty.
    3972         if (d_ptr->dirty)
     5300        if (d_ptr->fullUpdatePending)
    39735301            return;
    3974     } else if (d_ptr->discardUpdateRequest()) {
     5302    }
     5303
     5304    if (d_ptr->discardUpdateRequest())
    39755305        return;
    3976     }
    3977 
    3978     // Effectively the same as updateHelper(rect);
    3979     if (rect.isNull())
    3980         d_ptr->dirty = 1;
    3981     d_ptr->scene->itemUpdated(this, rect);
    3982 }
    3983 
     5306
     5307    if (d_ptr->scene)
     5308        d_ptr->scene->d_func()->markDirty(this, rect);
     5309}
    39845310
    39855311/*!
     
    40105336        return;
    40115337    if (d->cacheMode != NoCache) {
    4012         // ### This is very slow, and can be done much better. If the cache is
    4013         // local and matches the below criteria for rotation and scaling, we
    4014         // can easily scroll. And if the cache is in device coordinates, we
    4015         // can scroll both the viewport and the cache.
    4016         update(rect);
     5338        QGraphicsItemCache *c;
     5339        bool scrollCache = qFuzzyIsNull(dx - int(dx)) && qFuzzyIsNull(dy - int(dy))
     5340                           && (c = (QGraphicsItemCache *)qVariantValue<void *>(d_ptr->extra(QGraphicsItemPrivate::ExtraCacheData)))
     5341                           && (d->cacheMode == ItemCoordinateCache && !c->fixedSize.isValid());
     5342        if (scrollCache) {
     5343            QPixmap pix;
     5344            if (QPixmapCache::find(c->key, &pix)) {
     5345                // Adjust with 2 pixel margin. Notice the loss of precision
     5346                // when converting to QRect.
     5347                int adjust = 2;
     5348                QRectF br = boundingRect().adjusted(-adjust, -adjust, adjust, adjust);
     5349                QRect irect = rect.toRect().translated(-br.x(), -br.y());
     5350
     5351                pix.scroll(dx, dy, irect);
     5352
     5353                QPixmapCache::replace(c->key, pix);
     5354
     5355                // Translate the existing expose.
     5356                foreach (QRectF exposedRect, c->exposed)
     5357                    c->exposed += exposedRect.translated(dx, dy) & rect;
     5358
     5359                // Calculate exposure.
     5360                QRegion exposed;
     5361                QRect r = rect.toRect();
     5362                exposed += r;
     5363                exposed -= r.translated(dx, dy);
     5364                foreach (QRect rect, exposed.rects())
     5365                    update(rect);
     5366                d->scene->d_func()->markDirty(this);
     5367            } else {
     5368                update(rect);
     5369            }
     5370        } else {
     5371            // ### This is very slow, and can be done much better. If the cache is
     5372            // local and matches the below criteria for rotation and scaling, we
     5373            // can easily scroll. And if the cache is in device coordinates, we
     5374            // can scroll both the viewport and the cache.
     5375            update(rect);
     5376        }
    40175377        return;
    40185378    }
     
    40335393        static const QLineF right(0, 0, 1, 0);
    40345394
    4035         QTransform deviceTr;
    4036         if (d->itemIsUntransformable()) {
    4037             deviceTr = deviceTransform(view->viewportTransform());
    4038         } else {
    4039             deviceTr = sceneTransform() * view->viewportTransform();
    4040         }
    4041 
     5395        QTransform deviceTr = deviceTransform(view->viewportTransform());
    40425396        QRect deviceScrollRect = deviceTr.mapRect(scrollRect).toRect();
    40435397        QLineF v1 = deviceTr.map(right);
     
    41715525QPointF QGraphicsItem::mapToParent(const QPointF &point) const
    41725526{
    4173     return d_ptr->pos + (d_ptr->hasTransform ? transform().map(point) : point);
     5527    // COMBINE
     5528    if (!d_ptr->transformData)
     5529        return point + d_ptr->pos;
     5530    return d_ptr->transformToParent().map(point);
    41745531}
    41755532
     
    41915548QPointF QGraphicsItem::mapToScene(const QPointF &point) const
    41925549{
    4193     return sceneTransform().map(point);
     5550    if (d_ptr->hasTranslateOnlySceneTransform())
     5551        return QPointF(point.x() + d_ptr->sceneTransform.dx(), point.y() + d_ptr->sceneTransform.dy());
     5552    return d_ptr->sceneTransform.map(point);
    41945553}
    41955554
     
    42365595QPolygonF QGraphicsItem::mapToParent(const QRectF &rect) const
    42375596{
    4238     QPolygonF p = !d_ptr->hasTransform ? rect : transform().map(rect);
    4239     p.translate(d_ptr->pos);
    4240     return p;
     5597    // COMBINE
     5598    if (!d_ptr->transformData)
     5599        return rect.translated(d_ptr->pos);
     5600    return d_ptr->transformToParent().map(rect);
    42415601}
    42425602
     
    42575617QPolygonF QGraphicsItem::mapToScene(const QRectF &rect) const
    42585618{
    4259     return sceneTransform().map(rect);
     5619    if (d_ptr->hasTranslateOnlySceneTransform())
     5620        return rect.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy());
     5621    return d_ptr->sceneTransform.map(rect);
    42605622}
    42615623
     
    43055667QRectF QGraphicsItem::mapRectToParent(const QRectF &rect) const
    43065668{
    4307     QRectF r = !d_ptr->hasTransform ? rect : transform().mapRect(rect);
    4308     return r.translated(d_ptr->pos);
     5669    // COMBINE
     5670    if (!d_ptr->transformData)
     5671        return rect.translated(d_ptr->pos);
     5672    return d_ptr->transformToParent().mapRect(rect);
    43095673}
    43105674
     
    43285692QRectF QGraphicsItem::mapRectToScene(const QRectF &rect) const
    43295693{
    4330     return sceneTransform().mapRect(rect);
     5694    if (d_ptr->hasTranslateOnlySceneTransform())
     5695        return rect.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy());
     5696    return d_ptr->sceneTransform.mapRect(rect);
    43315697}
    43325698
     
    43775743QRectF QGraphicsItem::mapRectFromParent(const QRectF &rect) const
    43785744{
    4379     QRectF r = rect.translated(-d_ptr->pos);
    4380     return d_ptr->hasTransform ? transform().inverted().mapRect(r) : r;
     5745    // COMBINE
     5746    if (!d_ptr->transformData)
     5747        return rect.translated(-d_ptr->pos);
     5748    return d_ptr->transformToParent().inverted().mapRect(rect);
    43815749}
    43825750
     
    44005768QRectF QGraphicsItem::mapRectFromScene(const QRectF &rect) const
    44015769{
    4402     return sceneTransform().inverted().mapRect(rect);
     5770    if (d_ptr->hasTranslateOnlySceneTransform())
     5771        return rect.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy());
     5772    return d_ptr->sceneTransform.inverted().mapRect(rect);
    44035773}
    44045774
     
    44375807QPolygonF QGraphicsItem::mapToParent(const QPolygonF &polygon) const
    44385808{
    4439     QPolygonF p = !d_ptr->hasTransform ? polygon : transform().map(polygon);
    4440     p.translate(d_ptr->pos);
    4441     return p;
     5809    // COMBINE
     5810    if (!d_ptr->transformData)
     5811        return polygon.translated(d_ptr->pos);
     5812    return d_ptr->transformToParent().map(polygon);
    44425813}
    44435814
     
    44515822QPolygonF QGraphicsItem::mapToScene(const QPolygonF &polygon) const
    44525823{
    4453     return sceneTransform().map(polygon);
     5824    if (d_ptr->hasTranslateOnlySceneTransform())
     5825        return polygon.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy());
     5826    return d_ptr->sceneTransform.map(polygon);
    44545827}
    44555828
     
    44815854QPainterPath QGraphicsItem::mapToParent(const QPainterPath &path) const
    44825855{
    4483     QTransform x = QTransform::fromTranslate(d_ptr->pos.x(), d_ptr->pos.y());
    4484     if (d_ptr->hasTransform)
    4485         x = transform() * x;
    4486     return x.map(path);
     5856    // COMBINE
     5857    if (!d_ptr->transformData)
     5858        return path.translated(d_ptr->pos);
     5859    return d_ptr->transformToParent().map(path);
    44875860}
    44885861
     
    44965869QPainterPath QGraphicsItem::mapToScene(const QPainterPath &path) const
    44975870{
    4498     return sceneTransform().map(path);
     5871    if (d_ptr->hasTranslateOnlySceneTransform())
     5872        return path.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy());
     5873    return d_ptr->sceneTransform.map(path);
    44995874}
    45005875
     
    45335908QPointF QGraphicsItem::mapFromParent(const QPointF &point) const
    45345909{
    4535     if (d_ptr->hasTransform)
    4536         return transform().inverted().map(point - d_ptr->pos);
     5910    // COMBINE
     5911    if (d_ptr->transformData)
     5912        return d_ptr->transformToParent().inverted().map(point);
    45375913    return point - d_ptr->pos;
    45385914}
     
    45565932QPointF QGraphicsItem::mapFromScene(const QPointF &point) const
    45575933{
    4558     return sceneTransform().inverted().map(point);
     5934    if (d_ptr->hasTranslateOnlySceneTransform())
     5935        return QPointF(point.x() - d_ptr->sceneTransform.dx(), point.y() - d_ptr->sceneTransform.dy());
     5936    return d_ptr->sceneTransform.inverted().map(point);
    45595937}
    45605938
     
    46015979QPolygonF QGraphicsItem::mapFromParent(const QRectF &rect) const
    46025980{
    4603     QRectF r = rect.translated(-d_ptr->pos);
    4604     return d_ptr->hasTransform ? transform().inverted().map(r) : r;
     5981    // COMBINE
     5982    if (!d_ptr->transformData)
     5983        return rect.translated(-d_ptr->pos);
     5984    return d_ptr->transformToParent().inverted().map(rect);
    46055985}
    46065986
     
    46226002QPolygonF QGraphicsItem::mapFromScene(const QRectF &rect) const
    46236003{
    4624     return sceneTransform().inverted().map(rect);
     6004    if (d_ptr->hasTranslateOnlySceneTransform())
     6005        return rect.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy());
     6006    return d_ptr->sceneTransform.inverted().map(rect);
    46256007}
    46266008
     
    46576039QPolygonF QGraphicsItem::mapFromParent(const QPolygonF &polygon) const
    46586040{
    4659     QPolygonF p = polygon;
    4660     p.translate(-d_ptr->pos);
    4661     return d_ptr->hasTransform ? transform().inverted().map(p) : p;
     6041    // COMBINE
     6042    if (!d_ptr->transformData)
     6043        return polygon.translated(-d_ptr->pos);
     6044    return d_ptr->transformToParent().inverted().map(polygon);
    46626045}
    46636046
     
    46716054QPolygonF QGraphicsItem::mapFromScene(const QPolygonF &polygon) const
    46726055{
    4673     return sceneTransform().inverted().map(polygon);
     6056    if (d_ptr->hasTranslateOnlySceneTransform())
     6057        return polygon.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy());
     6058    return d_ptr->sceneTransform.inverted().map(polygon);
    46746059}
    46756060
     
    46996084QPainterPath QGraphicsItem::mapFromParent(const QPainterPath &path) const
    47006085{
    4701     if (d_ptr->parent)
    4702         return d_ptr->parent->itemTransform(this).map(path);
    4703     return mapFromScene(path);
     6086    // COMBINE
     6087    if (!d_ptr->transformData)
     6088            return path.translated(-d_ptr->pos);
     6089    return d_ptr->transformToParent().inverted().map(path);
    47046090}
    47056091
     
    47136099QPainterPath QGraphicsItem::mapFromScene(const QPainterPath &path) const
    47146100{
    4715     return sceneTransform().inverted().map(path);
     6101    if (d_ptr->hasTranslateOnlySceneTransform())
     6102        return path.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy());
     6103    return d_ptr->sceneTransform.inverted().map(path);
    47166104}
    47176105
     
    47256113{
    47266114    if (!child || child == this)
     6115        return false;
     6116    if (child->d_ptr->depth() < d_ptr->depth())
    47276117        return false;
    47286118    const QGraphicsItem *ancestor = child;
     
    47506140    const QGraphicsItem *thisw = this;
    47516141    const QGraphicsItem *otherw = other;
    4752     int thisDepth = d_ptr->depth;
    4753     int otherDepth = other->d_ptr->depth;
     6142    int thisDepth = d_ptr->depth();
     6143    int otherDepth = other->d_ptr->depth();
    47546144    while (thisDepth > otherDepth) {
    47556145        thisw = thisw->d_ptr->parent;
     
    50506440        inputMethodEvent(static_cast<QInputMethodEvent *>(event));
    50516441        break;
     6442    case QEvent::WindowActivate:
     6443    case QEvent::WindowDeactivate:
     6444        // Propagate panel activation.
     6445        if (d_ptr->scene) {
     6446            for (int i = 0; i < d_ptr->children.size(); ++i) {
     6447                QGraphicsItem *child = d_ptr->children.at(i);
     6448                if (child->isVisible() && !child->isPanel()) {
     6449                    if (!(child->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorHandlesChildEvents))
     6450                        d_ptr->scene->sendEvent(child, event);
     6451                }
     6452            }
     6453        }
     6454        break;
    50526455    default:
    50536456        return false;
     
    51896592    ensureVisible().
    51906593
    5191     \sa focusOutEvent(), sceneEvent()
     6594    \sa focusOutEvent(), sceneEvent(), setFocus()
    51926595*/
    51936596void QGraphicsItem::focusInEvent(QFocusEvent *event)
    51946597{
    51956598    Q_UNUSED(event);
     6599    update();
    51966600}
    51976601
     
    52006604    focus out events for this item. The default implementation does nothing.
    52016605
    5202     \sa focusInEvent(), sceneEvent()
     6606    \sa focusInEvent(), sceneEvent(), setFocus()
    52036607*/
    52046608void QGraphicsItem::focusOutEvent(QFocusEvent *event)
    52056609{
    52066610    Q_UNUSED(event);
     6611    update();
    52076612}
    52086613
     
    52196624{
    52206625    Q_UNUSED(event);
    5221     d_ptr->updateHelper();
     6626    update();
    52226627}
    52236628
     
    52476652{
    52486653    Q_UNUSED(event);
    5249     d_ptr->updateHelper();
     6654    update();
    52506655}
    52516656
     
    53376742        // Qt::Popup closes when you click outside.
    53386743        QGraphicsWidget *w = static_cast<QGraphicsWidget *>(this);
    5339         if (w->windowFlags() & Qt::Popup) {
     6744        if ((w->windowFlags() & Qt::Popup) == Qt::Popup) {
    53406745            event->accept();
    53416746            if (!w->rect().contains(event->pos()))
     
    55846989    property is queried.
    55856990
    5586     \sa inputMethodEvent()
     6991    \sa inputMethodEvent(), QInputMethodEvent, QInputContext
    55876992*/
    55886993QVariant QGraphicsItem::inputMethodQuery(Qt::InputMethodQuery query) const
     
    56007005
    56017006/*!
     7007    Returns the current input method hints of this item.
     7008
     7009    Input method hints are only relevant for input items.
     7010    The hints are used by the input method to indicate how it should operate.
     7011    For example, if the Qt::ImhNumbersOnly flag is set, the input method may change
     7012    its visual components to reflect that only numbers can be entered.
     7013
     7014    The effect may vary between input method implementations.
     7015
     7016    \since 4.6
     7017
     7018    \sa setInputMethodHints(), inputMethodQuery(), QInputContext
     7019*/
     7020Qt::InputMethodHints QGraphicsItem::inputMethodHints() const
     7021{
     7022    Q_D(const QGraphicsItem);
     7023    return d->imHints;
     7024}
     7025
     7026/*!
     7027    Sets the current input method hints of this item to \a hints.
     7028
     7029    \since 4.6
     7030
     7031    \sa inputMethodHints(), inputMethodQuery(), QInputContext
     7032*/
     7033void QGraphicsItem::setInputMethodHints(Qt::InputMethodHints hints)
     7034{
     7035    Q_D(QGraphicsItem);
     7036    d->imHints = hints;
     7037}
     7038
     7039/*!
    56027040    This virtual function is called by QGraphicsItem to notify custom items
    56037041    that some part of the item's state changes. By reimplementing this
     
    56767114    }
    56777115    if (d_ptr->scene)
    5678         d_ptr->scene->d_func()->addToIndex(this);
    5679     d_ptr->updateHelper();
     7116        d_ptr->scene->d_func()->index->addItem(this);
    56807117}
    56817118
     
    56937130        return;
    56947131    }
    5695     d_ptr->updateHelper();
    56967132    if (d_ptr->scene)
    5697         d_ptr->scene->d_func()->removeFromIndex(this);
     7133        d_ptr->scene->d_func()->index->removeItem(this);
    56987134}
    56997135
     
    57137149void QGraphicsItem::prepareGeometryChange()
    57147150{
     7151    if (d_ptr->inDestructor)
     7152        return;
    57157153    if (d_ptr->scene) {
    5716         d_ptr->updateHelper(QRectF(), false, /*maybeDirtyClipPath=*/!d_ptr->inSetPosHelper);
     7154        d_ptr->scene->d_func()->dirtyGrowingItemsBoundingRect = true;
     7155        d_ptr->geometryChanged = 1;
     7156        d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
     7157        d_ptr->notifyBoundingRectChanged = !d_ptr->inSetPosHelper;
     7158
    57177159        QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func();
    5718         scenePrivate->removeFromIndex(this);
    5719     }
    5720 
    5721     if (d_ptr->inSetPosHelper)
    5722         return;
    5723 
    5724     if (d_ptr->flags & ItemClipsChildrenToShape)
    5725         d_ptr->invalidateCachedClipPathRecursively();
    5726     else
    5727         d_ptr->invalidateCachedClipPath();
     7160        scenePrivate->index->prepareBoundingRectChange(this);
     7161        scenePrivate->markDirty(this, QRectF(), /*invalidateChildren=*/true);
     7162
     7163        // For compatibility reasons, we have to update the item's old geometry
     7164        // if someone is connected to the changed signal or the scene has no views.
     7165        // Note that this has to be done *after* markDirty to ensure that
     7166        // _q_processDirtyItems is called before _q_emitUpdated.
     7167        if (scenePrivate->isSignalConnected(scenePrivate->changedSignalIndex)
     7168            || scenePrivate->views.isEmpty()) {
     7169            if (d_ptr->hasTranslateOnlySceneTransform()) {
     7170                d_ptr->scene->update(boundingRect().translated(d_ptr->sceneTransform.dx(),
     7171                                                               d_ptr->sceneTransform.dy()));
     7172            } else {
     7173                d_ptr->scene->update(d_ptr->sceneTransform.mapRect(boundingRect()));
     7174            }
     7175        }
     7176    }
     7177
     7178    QGraphicsItem *parent = this;
     7179    while ((parent = parent->d_ptr->parent)) {
     7180        QGraphicsItemPrivate *parentp = parent->d_ptr.data();
     7181        parentp->dirtyChildrenBoundingRect = 1;
     7182        // ### Only do this if the parent's effect applies to the entire subtree.
     7183        parentp->notifyBoundingRectChanged = 1;
     7184#ifndef QT_NO_GRAPHICSEFFECT
     7185        if (parentp->scene && parentp->graphicsEffect) {
     7186            parentp->notifyInvalidated = 1;
     7187            static_cast<QGraphicsItemEffectSourcePrivate *>(parentp->graphicsEffect->d_func()->source->d_func())->invalidateCache();
     7188        }
     7189#endif
     7190    }
    57287191}
    57297192
     
    57407203{
    57417204    const QRectF murect = painter->transform().mapRect(QRectF(0, 0, 1, 1));
    5742     if (qFuzzyCompare(qMax(murect.width(), murect.height()) + 1, 1))
     7205    if (qFuzzyIsNull(qMax(murect.width(), murect.height())))
    57437206        return;
    57447207
     
    57907253
    57917254/*!
     7255    \class QGraphicsObject
     7256    \brief The QGraphicsObject class provides a base class for all graphics items that
     7257    require signals, slots and properties.
     7258    \since 4.6
     7259    \ingroup graphicsview-api
     7260
     7261    The class extends a QGraphicsItem with QObject's signal/slot and property mechanisms.
     7262    It maps many of QGraphicsItem's basic setters and getters to properties and adds notification
     7263    signals for many of them.
     7264
     7265    \section1 Parents and Children
     7266
     7267    Each graphics object can be constructed with a parent item. This ensures that the
     7268    item will be destroyed when its parent item is destroyed. Although QGraphicsObject
     7269    inherits from both QObject and QGraphicsItem, you should use the functions provided
     7270    by QGraphicsItem, \e not QObject, to manage the relationships between parent and
     7271    child items.
     7272
     7273    The relationships between items can be explored using the parentItem() and childItems()
     7274    functions. In the hierarchy of items in a scene, the parentObject() and parentWidget()
     7275    functions are the equivalent of the QWidget::parent() and QWidget::parentWidget()
     7276    functions for QWidget subclasses.
     7277
     7278    \sa QGraphicsWidget
     7279*/
     7280
     7281/*!
     7282    Constructs a QGraphicsObject with \a parent.
     7283*/
     7284QGraphicsObject::QGraphicsObject(QGraphicsItem *parent)
     7285        : QGraphicsItem(parent)
     7286{
     7287    QGraphicsItem::d_ptr->isObject = true;
     7288}
     7289
     7290/*!
     7291  \internal
     7292*/
     7293QGraphicsObject::QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene)
     7294    : QGraphicsItem(dd, parent, scene)
     7295{
     7296    QGraphicsItem::d_ptr->isObject = true;
     7297}
     7298
     7299/*!
     7300    Subscribes the graphics object to the given \a gesture with specific \a flags.
     7301
     7302    \sa ungrabGesture(), QGestureEvent
     7303*/
     7304void QGraphicsObject::grabGesture(Qt::GestureType gesture, Qt::GestureFlags flags)
     7305{
     7306    QGraphicsItemPrivate * const d = QGraphicsItem::d_func();
     7307    d->gestureContext.insert(gesture, flags);
     7308    (void)QGestureManager::instance(); // create a gesture manager
     7309}
     7310
     7311/*!
     7312    Unsubscribes the graphics object from the given \a gesture.
     7313
     7314    \sa grabGesture(), QGestureEvent
     7315*/
     7316void QGraphicsObject::ungrabGesture(Qt::GestureType gesture)
     7317{
     7318    QGraphicsItemPrivate * const d = QGraphicsItem::d_func();
     7319    if (d->gestureContext.remove(gesture)) {
     7320        QGestureManager *manager = QGestureManager::instance();
     7321        manager->cleanupCachedGestures(this, gesture);
     7322    }
     7323}
     7324
     7325/*!
     7326  \property QGraphicsObject::parent
     7327  \brief the parent of the item
     7328
     7329  \note The item's parent is set independently of the parent object returned
     7330  by QObject::parent().
     7331
     7332  \sa QGraphicsItem::setParentItem(), QGraphicsItem::parentObject()
     7333*/
     7334
     7335/*!
     7336  \property QGraphicsObject::opacity
     7337  \brief the opacity of the item
     7338
     7339  \sa QGraphicsItem::setOpacity(), QGraphicsItem::opacity()
     7340*/
     7341
     7342/*!
     7343  \fn QGraphicsObject::opacityChanged()
     7344
     7345  This signal gets emitted whenever the opacity of the item changes
     7346
     7347  \sa QGraphicsItem::opacity()
     7348*/
     7349
     7350/*!
     7351  \fn QGraphicsObject::parentChanged()
     7352
     7353  This signal gets emitted whenever the parent of the item changes
     7354*/
     7355
     7356/*!
     7357  \property QGraphicsObject::pos
     7358  \brief the position of the item
     7359
     7360  Describes the items position.
     7361
     7362  \sa QGraphicsItem::setPos(), QGraphicsItem::pos()
     7363*/
     7364
     7365/*!
     7366  \property QGraphicsObject::x
     7367  \brief the x position of the item
     7368
     7369  Describes the items x position.
     7370
     7371  \sa QGraphicsItem::setX(), setPos(), xChanged()
     7372*/
     7373
     7374/*!
     7375  \fn QGraphicsObject::xChanged()
     7376
     7377  This signal gets emitted whenever the x position of the item changes
     7378
     7379  \sa pos()
     7380*/
     7381
     7382/*!
     7383  \property QGraphicsObject::y
     7384  \brief the y position of the item
     7385
     7386  Describes the items y position.
     7387
     7388  \sa QGraphicsItem::setY(), setPos(), yChanged()
     7389*/
     7390
     7391/*!
     7392  \fn QGraphicsObject::yChanged()
     7393
     7394  This signal gets emitted whenever the y position of the item changes.
     7395
     7396  \sa pos()
     7397*/
     7398
     7399/*!
     7400  \property QGraphicsObject::z
     7401  \brief the z value of the item
     7402
     7403  Describes the items z value.
     7404
     7405  \sa QGraphicsItem::setZValue(), zValue(), zChanged()
     7406*/
     7407
     7408/*!
     7409  \fn QGraphicsObject::zChanged()
     7410
     7411  This signal gets emitted whenever the z value of the item changes.
     7412
     7413  \sa pos()
     7414*/
     7415
     7416/*!
     7417  \property QGraphicsObject::rotation
     7418  This property holds the rotation of the item in degrees.
     7419
     7420  This specifies how many degrees to rotate the item around its transformOrigin.
     7421  The default rotation is 0 degrees (i.e. not rotated at all).
     7422*/
     7423
     7424/*!
     7425  \fn QGraphicsObject::rotationChanged()
     7426
     7427  This signal gets emitted whenever the roation of the item changes.
     7428*/
     7429
     7430/*!
     7431  \property QGraphicsObject::scale
     7432  This property holds the scale of the item.
     7433
     7434  A scale of less than 1 means the item will be displayed smaller than
     7435  normal, and a scale of greater than 1 means the item will be
     7436  displayed larger than normal.  A negative scale means the item will
     7437  be mirrored.
     7438
     7439  By default, items are displayed at a scale of 1 (i.e. at their
     7440  normal size).
     7441
     7442  Scaling is from the item's transformOrigin.
     7443*/
     7444
     7445/*!
     7446  \fn void QGraphicsObject::scaleChanged()
     7447
     7448  This signal is emitted when the scale of the item changes.
     7449*/
     7450
     7451
     7452/*!
     7453  \property QGraphicsObject::enabled
     7454  \brief whether the item is enabled or not
     7455
     7456  This property is declared in QGraphicsItem.
     7457
     7458  By default, this property is true.
     7459
     7460  \sa QGraphicsItem::isEnabled(), QGraphicsItem::setEnabled()
     7461  \sa QGraphicsObject::enabledChanged()
     7462*/
     7463
     7464/*!
     7465  \fn void QGraphicsObject::enabledChanged()
     7466
     7467  This signal gets emitted whenever the item get's enabled or disabled.
     7468
     7469  \sa isEnabled()
     7470*/
     7471
     7472/*!
     7473  \property QGraphicsObject::visible
     7474  \brief whether the item is visible or not
     7475
     7476  This property is declared in QGraphicsItem.
     7477
     7478  By default, this property is true.
     7479
     7480  \sa QGraphicsItem::isVisible(), QGraphicsItem::setVisible(), visibleChanged()
     7481*/
     7482
     7483/*!
     7484  \fn QGraphicsObject::visibleChanged()
     7485
     7486  This signal gets emitted whenever the visibility of the item changes
     7487
     7488  \sa visible
     7489*/
     7490
     7491/*!
     7492  \fn const QObjectList &QGraphicsObject::children() const
     7493  \internal
     7494
     7495  This function returns the same value as QObject::children(). It's
     7496  provided to differentiate between the obsolete member
     7497  QGraphicsItem::children() and QObject::children(). QGraphicsItem now
     7498  provides childItems() instead.
     7499*/
     7500
     7501/*!
     7502  \property QGraphicsObject::transformOriginPoint
     7503  \brief the transformation origin
     7504
     7505  This property sets a specific point in the items coordiante system as the
     7506  origin for scale and rotation.
     7507
     7508  \sa scale, rotation, QGraphicsItem::transformOriginPoint()
     7509*/
     7510
     7511
     7512/*!
    57927513    \class QAbstractGraphicsShapeItem
    57937514    \brief The QAbstractGraphicsShapeItem class provides a common base for
    57947515    all path items.
    57957516    \since 4.2
    5796     \ingroup multimedia
     7517    \ingroup graphicsview-api
    57977518
    57987519    This class does not fully implement an item by itself; in particular, it
     
    59297650    can add to a QGraphicsScene.
    59307651    \since 4.2
    5931     \ingroup multimedia
    59327652    \ingroup graphicsview-api
    59337653
     
    61327852    can add to a QGraphicsScene.
    61337853    \since 4.2
    6134     \ingroup multimedia
    61357854    \ingroup graphicsview-api
    61367855
     
    63778096    can add to a QGraphicsScene.
    63788097    \since 4.2
    6379     \ingroup multimedia
    63808098    \ingroup graphicsview-api
    63818099
     
    66948412    can add to a QGraphicsScene.
    66958413    \since 4.2
    6696     \ingroup multimedia
    66978414    \ingroup graphicsview-api
    66988415
     
    69288645    QGraphicsScene.
    69298646    \since 4.2
    6930     \ingroup multimedia
    69318647    \ingroup graphicsview-api
    69328648
     
    71908906    a QGraphicsScene.
    71918907    \since 4.2
    7192     \ingroup multimedia
    71938908    \ingroup graphicsview-api
    71948909
     
    73799094    Q_D(QGraphicsPixmapItem);
    73809095    if (mode != d->transformationMode) {
    7381         d_ptr->updateHelper();
    73829096        d->transformationMode = mode;
    73839097        update();
     
    74279141{
    74289142    Q_D(const QGraphicsPixmapItem);
    7429     qreal pw = 1.0;
    74309143    if (d->pixmap.isNull())
    74319144        return QRectF();
    7432     return QRectF(d->offset, d->pixmap.size()).adjusted(-pw/2, -pw/2, pw/2, pw/2);
     9145    if (d->flags & ItemIsSelectable) {
     9146        qreal pw = 1.0;
     9147        return QRectF(d->offset, d->pixmap.size()).adjusted(-pw/2, -pw/2, pw/2, pw/2);
     9148    } else {
     9149        return QRectF(d->offset, d->pixmap.size());
     9150    }
    74339151}
    74349152
     
    74679185                           (d->transformationMode == Qt::SmoothTransformation));
    74689186
    7469     QRectF exposed = option->exposedRect.adjusted(-1, -1, 1, 1);
    7470     exposed &= QRectF(d->offset.x(), d->offset.y(), d->pixmap.width(), d->pixmap.height());
    7471     painter->drawPixmap(exposed, d->pixmap, exposed.translated(-d->offset));
     9187    painter->drawPixmap(d->offset, d->pixmap);
    74729188
    74739189    if (option->state & QStyle::State_Selected)
     
    75579273    a QGraphicsScene to display formatted text.
    75589274    \since 4.2
    7559     \ingroup multimedia
    75609275    \ingroup graphicsview-api
    75619276
     
    75929307public:
    75939308    QGraphicsTextItemPrivate()
    7594         : control(0), pageNumber(0), useDefaultImpl(false), tabChangesFocus(false)
     9309        : control(0), pageNumber(0), useDefaultImpl(false), tabChangesFocus(false), clickCausedFocus(0)
    75959310    { }
    75969311
     
    76139328    bool tabChangesFocus;
    76149329
     9330    uint clickCausedFocus : 1;
     9331
    76159332    QGraphicsTextItem *qq;
    76169333};
     9334
    76179335
    76189336/*!
     
    76289346#endif
    76299347    )
    7630     : QGraphicsItem(parent, scene), dd(new QGraphicsTextItemPrivate)
     9348    : QGraphicsObject(*new QGraphicsItemPrivate, parent, scene), dd(new QGraphicsTextItemPrivate)
    76319349{
    76329350    dd->qq = this;
     
    76359353    setAcceptDrops(true);
    76369354    setAcceptHoverEvents(true);
     9355    setFlags(ItemUsesExtendedStyleOption);
    76379356}
    76389357
     
    76499368#endif
    76509369    )
    7651     : QGraphicsItem(parent, scene), dd(new QGraphicsTextItemPrivate)
     9370    : QGraphicsObject(*new QGraphicsItemPrivate, parent, scene), dd(new QGraphicsTextItemPrivate)
    76529371{
    76539372    dd->qq = this;
    76549373    setAcceptDrops(true);
    76559374    setAcceptHoverEvents(true);
     9375    setFlag(ItemUsesExtendedStyleOption);
    76569376}
    76579377
     
    77439463    QTextControl *c = dd->textControl();
    77449464    QPalette pal = c->palette();
     9465    QColor old = pal.color(QPalette::Text);
    77459466    pal.setColor(QPalette::Text, col);
    77469467    c->setPalette(pal);
     9468    if (old != col)
     9469        update();
    77479470}
    77489471
     
    79159638        }
    79169639    }
    7917     return QGraphicsItem::sceneEvent(event);
     9640    bool result = QGraphicsItem::sceneEvent(event);
     9641
     9642    // Ensure input context is updated.
     9643    switch (event->type()) {
     9644    case QEvent::ContextMenu:
     9645    case QEvent::FocusIn:
     9646    case QEvent::FocusOut:
     9647    case QEvent::GraphicsSceneDragEnter:
     9648    case QEvent::GraphicsSceneDragLeave:
     9649    case QEvent::GraphicsSceneDragMove:
     9650    case QEvent::GraphicsSceneDrop:
     9651    case QEvent::GraphicsSceneHoverEnter:
     9652    case QEvent::GraphicsSceneHoverLeave:
     9653    case QEvent::GraphicsSceneHoverMove:
     9654    case QEvent::GraphicsSceneMouseDoubleClick:
     9655    case QEvent::GraphicsSceneMousePress:
     9656    case QEvent::GraphicsSceneMouseMove:
     9657    case QEvent::GraphicsSceneMouseRelease:
     9658    case QEvent::KeyPress:
     9659    case QEvent::KeyRelease:
     9660        // Reset the focus widget's input context, regardless
     9661        // of how this item gained or lost focus.
     9662        if (QWidget *fw = qApp->focusWidget()) {
     9663#ifndef QT_NO_IM
     9664            if (QInputContext *qic = fw->inputContext()) {
     9665                if (event->type() == QEvent::FocusIn || event->type() == QEvent::FocusOut)
     9666                    qic->reset();
     9667                else
     9668                    qic->update();
     9669            }
     9670#endif //QT_NO_IM
     9671        }
     9672        break;
     9673    default:
     9674        break;
     9675    }
     9676
     9677    return result;
    79189678}
    79199679
     
    79249684{
    79259685    if ((QGraphicsItem::d_ptr->flags & (ItemIsSelectable | ItemIsMovable))
    7926         && (event->buttons() & Qt::LeftButton) && dd->_q_mouseOnEdge(event)) {
    7927         // User left-pressed on edge of selectable/movable item, use
    7928         // base impl.
    7929         dd->useDefaultImpl = true;
     9686        && (event->buttons() & Qt::LeftButton) && dd->_q_mouseOnEdge(event)) {
     9687        // User left-pressed on edge of selectable/movable item, use
     9688        // base impl.
     9689        dd->useDefaultImpl = true;
    79309690    } else if (event->buttons() == event->button()
    7931                && dd->control->textInteractionFlags() == Qt::NoTextInteraction) {
    7932         // User pressed first button on non-interactive item.
    7933         dd->useDefaultImpl = true;
     9691               && dd->control->textInteractionFlags() == Qt::NoTextInteraction) {
     9692        // User pressed first button on non-interactive item.
     9693        dd->useDefaultImpl = true;
    79349694    }
    79359695    if (dd->useDefaultImpl) {
    79369696        QGraphicsItem::mousePressEvent(event);
    7937         if (!event->isAccepted())
    7938             dd->useDefaultImpl = false;
     9697        if (!event->isAccepted())
     9698            dd->useDefaultImpl = false;
    79399699        return;
    79409700    }
     9701
    79419702    dd->sendControlEvent(event);
    79429703}
     
    79519712        return;
    79529713    }
     9714
    79539715    dd->sendControlEvent(event);
    79549716}
     
    79619723    if (dd->useDefaultImpl) {
    79629724        QGraphicsItem::mouseReleaseEvent(event);
    7963         if (dd->control->textInteractionFlags() == Qt::NoTextInteraction
    7964             && !event->buttons()) {
    7965             // User released last button on non-interactive item.
     9725        if (dd->control->textInteractionFlags() == Qt::NoTextInteraction
     9726            && !event->buttons()) {
     9727            // User released last button on non-interactive item.
    79669728            dd->useDefaultImpl = false;
    7967         } else  if ((event->buttons() & Qt::LeftButton) == 0) {
    7968             // User released the left button on an interactive item.
     9729        } else  if ((event->buttons() & Qt::LeftButton) == 0) {
     9730            // User released the left button on an interactive item.
    79699731            dd->useDefaultImpl = false;
    7970         }
     9732        }
    79719733        return;
    79729734    }
     9735
     9736    QWidget *widget = event->widget();
     9737    if (widget && (dd->control->textInteractionFlags() & Qt::TextEditable) && boundingRect().contains(event->pos())) {
     9738        qt_widget_private(widget)->handleSoftwareInputPanel(event->button(), dd->clickCausedFocus);
     9739    }
     9740    dd->clickCausedFocus = 0;
    79739741    dd->sendControlEvent(event);
    79749742}
     
    80229790{
    80239791    dd->sendControlEvent(event);
     9792    if (event->reason() == Qt::MouseFocusReason) {
     9793        dd->clickCausedFocus = 1;
     9794    }
    80249795    update();
    80259796}
     
    825810029    input.
    825910030
    8260     The default for a QGraphicsTextItem is Qt::NoTextInteraction. Setting a
    8261     value different to Qt::NoTextInteraction will also set the ItemIsFocusable
    8262     QGraphicsItem flag.
     10031    The default for a QGraphicsTextItem is Qt::NoTextInteraction. This function
     10032    also affects the ItemIsFocusable QGraphicsItem flag by setting it if \a flags
     10033    is different from Qt::NoTextInteraction and clearing it otherwise.
    826310034
    826410035    By default, the text is read-only. To transform the item into an editor,
     
    826810039{
    826910040    if (flags == Qt::NoTextInteraction)
    8270         setFlags(this->flags() & ~QGraphicsItem::ItemIsFocusable);
     10041        setFlags(this->flags() & ~(QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemAcceptsInputMethod));
    827110042    else
    8272         setFlags(this->flags() | QGraphicsItem::ItemIsFocusable);
     10043        setFlags(this->flags() | QGraphicsItem::ItemIsFocusable | QGraphicsItem::ItemAcceptsInputMethod);
     10044
    827310045    dd->textControl()->setTextInteractionFlags(flags);
    827410046}
     
    841910191    that you can add to a QGraphicsScene.
    842010192    \since 4.2
    8421     \ingroup multimedia
    842210193    \ingroup graphicsview-api
    842310194
     
    865510426    one.
    865610427    \since 4.2
    8657     \ingroup multimedia
    865810428    \ingroup graphicsview-api
    865910429
     
    867010440
    867110441    The boundingRect() function of QGraphicsItemGroup returns the
    8672     bounding rectangle of all items in the item group. In addition,
    8673     item groups have handlesChildEvents() enabled by default, so all
    8674     events sent to a member of the group go to the item group (i.e.,
    8675     selecting one item in a group will select them all).
    8676     QGraphicsItemGroup ignores the ItemIgnoresTransformations flag on its
    8677     children (i.e., with respect to the geometry of the group item, the
    8678     children are treated as if they were transformable).
     10442    bounding rectangle of all items in the item group.
     10443    QGraphicsItemGroup ignores the ItemIgnoresTransformations flag on
     10444    its children (i.e., with respect to the geometry of the group
     10445    item, the children are treated as if they were transformable).
    867910446
    868010447    There are two ways to construct an item group. The easiest and
     
    876110528    }
    876210529
    8763     QTransform oldSceneMatrix = item->sceneTransform();
     10530    // COMBINE
     10531    bool ok;
     10532    QTransform itemTransform = item->itemTransform(this, &ok);
     10533
     10534    if (!ok) {
     10535        qWarning("QGraphicsItemGroup::addToGroup: could not find a valid transformation from item to group coordinates");
     10536        return;
     10537    }
     10538
     10539    QTransform newItemTransform(itemTransform);
    876410540    item->setPos(mapFromItem(item, 0, 0));
    876510541    item->setParentItem(this);
    8766     QTransform newItemTransform(oldSceneMatrix);
    8767     newItemTransform *= sceneTransform().inverted();
     10542
     10543    // removing position from translation component of the new transform
    876810544    if (!item->pos().isNull())
    876910545        newItemTransform *= QTransform::fromTranslate(-item->x(), -item->y());
     10546
     10547    // removing additional transformations properties applied with itemTransform()
     10548    QPointF origin = item->transformOriginPoint();
     10549    QMatrix4x4 m;
     10550    QList<QGraphicsTransform*> transformList = item->transformations();
     10551    for (int i = 0; i < transformList.size(); ++i)
     10552        transformList.at(i)->applyTo(&m);
     10553    newItemTransform *= m.toTransform().inverted();
     10554    newItemTransform.translate(origin.x(), origin.y());
     10555    newItemTransform.rotate(-item->rotation());
     10556    newItemTransform.scale(1/item->scale(), 1/item->scale());
     10557    newItemTransform.translate(-origin.x(), -origin.y());
     10558
     10559    // ### Expensive, we could maybe use dirtySceneTransform bit for optimization
     10560
    877010561    item->setTransform(newItemTransform);
    877110562    item->d_func()->setIsMemberOfGroup(true);
    877210563    prepareGeometryChange();
    8773     QTransform itemTransform(item->transform());
    8774     if (!item->pos().isNull())
    8775         itemTransform *= QTransform::fromTranslate(item->x(), item->y());
    877610564    d->itemsBoundingRect |= itemTransform.mapRect(item->boundingRect() | item->childrenBoundingRect());
    877710565    update();
     
    879510583
    879610584    QGraphicsItem *newParent = d_ptr->parent;
     10585
     10586    // COMBINE
     10587    bool ok;
     10588    QTransform itemTransform;
     10589    if (newParent)
     10590        itemTransform = item->itemTransform(newParent, &ok);
     10591    else
     10592        itemTransform = item->sceneTransform();
     10593
    879710594    QPointF oldPos = item->mapToItem(newParent, 0, 0);
    879810595    item->setParentItem(newParent);
    8799     // ### This function should remap the item's matrix to keep the item's
    8800     // transformation unchanged relative to the scene.
    880110596    item->setPos(oldPos);
     10597
     10598    // removing position from translation component of the new transform
     10599    if (!item->pos().isNull())
     10600        itemTransform *= QTransform::fromTranslate(-item->x(), -item->y());
     10601
     10602    // removing additional transformations properties applied
     10603    // with itemTransform() or sceneTransform()
     10604    QPointF origin = item->transformOriginPoint();
     10605    QMatrix4x4 m;
     10606    QList<QGraphicsTransform*> transformList = item->transformations();
     10607    for (int i = 0; i < transformList.size(); ++i)
     10608        transformList.at(i)->applyTo(&m);
     10609    itemTransform *= m.toTransform().inverted();
     10610    itemTransform.translate(origin.x(), origin.y());
     10611    itemTransform.rotate(-item->rotation());
     10612    itemTransform.scale(1 / item->scale(), 1 / item->scale());
     10613    itemTransform.translate(-origin.x(), -origin.y());
     10614
     10615    // ### Expensive, we could maybe use dirtySceneTransform bit for optimization
     10616
     10617    item->setTransform(itemTransform);
    880210618    item->d_func()->setIsMemberOfGroup(item->group() != 0);
    880310619
     
    885610672}
    885710673
     10674#ifndef QT_NO_GRAPHICSEFFECT
     10675QRectF QGraphicsItemEffectSourcePrivate::boundingRect(Qt::CoordinateSystem system) const
     10676{
     10677    const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
     10678    if (!info && deviceCoordinates) {
     10679        // Device coordinates without info not yet supported.
     10680        qWarning("QGraphicsEffectSource::boundingRect: Not yet implemented, lacking device context");
     10681        return QRectF();
     10682    }
     10683
     10684    QRectF rect = item->boundingRect();
     10685    if (!item->d_ptr->children.isEmpty())
     10686        rect |= item->childrenBoundingRect();
     10687
     10688    if (deviceCoordinates) {
     10689        Q_ASSERT(info->painter);
     10690        rect = info->painter->worldTransform().mapRect(rect);
     10691    }
     10692
     10693    return rect;
     10694}
     10695
     10696void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter)
     10697{
     10698    if (!info) {
     10699        qWarning("QGraphicsEffectSource::draw: Can only begin as a result of QGraphicsEffect::draw");
     10700        return;
     10701    }
     10702
     10703    Q_ASSERT(item->d_ptr->scene);
     10704    QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func();
     10705    if (painter == info->painter) {
     10706        scened->draw(item, painter, info->viewTransform, info->transformPtr, info->exposedRegion,
     10707                     info->widget, info->opacity, info->effectTransform, info->wasDirtySceneTransform,
     10708                     info->drawItem);
     10709    } else {
     10710        QTransform effectTransform = info->painter->worldTransform().inverted();
     10711        effectTransform *= painter->worldTransform();
     10712        scened->draw(item, painter, info->viewTransform, info->transformPtr, info->exposedRegion,
     10713                     info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform,
     10714                     info->drawItem);
     10715    }
     10716}
     10717
     10718QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset,
     10719                                                 QGraphicsEffect::PixmapPadMode mode) const
     10720{
     10721    const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
     10722    if (!info && deviceCoordinates) {
     10723        // Device coordinates without info not yet supported.
     10724        qWarning("QGraphicsEffectSource::pixmap: Not yet implemented, lacking device context");
     10725        return QPixmap();
     10726    }
     10727    if (!item->d_ptr->scene)
     10728        return QPixmap();
     10729    QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func();
     10730
     10731    const QRectF sourceRect = boundingRect(system);
     10732    QRectF effectRectF;
     10733
     10734    bool unpadded = false;
     10735    if (mode == QGraphicsEffect::PadToEffectiveBoundingRect) {
     10736        if (info) {
     10737            effectRectF = item->graphicsEffect()->boundingRectFor(boundingRect(Qt::DeviceCoordinates));
     10738            unpadded = (effectRectF.size() == sourceRect.size());
     10739            if (info && system == Qt::LogicalCoordinates)
     10740                effectRectF = info->painter->worldTransform().inverted().mapRect(effectRectF);
     10741        } else {
     10742            // no choice but to send a logical coordinate bounding rect to boundingRectFor
     10743            effectRectF = item->graphicsEffect()->boundingRectFor(sourceRect);
     10744        }
     10745    } else if (mode == QGraphicsEffect::PadToTransparentBorder) {
     10746        // adjust by 1.5 to account for cosmetic pens
     10747        effectRectF = sourceRect.adjusted(-1.5, -1.5, 1.5, 1.5);
     10748    } else {
     10749        effectRectF = sourceRect;
     10750        unpadded = true;
     10751    }
     10752
     10753    QRect effectRect = effectRectF.toAlignedRect();
     10754
     10755    if (offset)
     10756        *offset = effectRect.topLeft();
     10757
     10758    bool untransformed = !deviceCoordinates
     10759            || info->painter->worldTransform().type() <= QTransform::TxTranslate;
     10760    if (untransformed && unpadded && isPixmap()) {
     10761        if (offset)
     10762            *offset = boundingRect(system).topLeft().toPoint();
     10763        return static_cast<QGraphicsPixmapItem *>(item)->pixmap();
     10764    }
     10765
     10766    if (deviceCoordinates) {
     10767        // Clip to viewport rect.
     10768        int left, top, right, bottom;
     10769        effectRect.getCoords(&left, &top, &right, &bottom);
     10770        if (left < 0) {
     10771            if (offset)
     10772                offset->rx() += -left;
     10773            effectRect.setX(0);
     10774        }
     10775        if (top < 0) {
     10776            if (offset)
     10777                offset->ry() += -top;
     10778            effectRect.setY(0);
     10779        }
     10780        // NB! We use +-1 for historical reasons (see QRect documentation).
     10781        QPaintDevice *device = info->painter->device();
     10782        const int deviceWidth = device->width();
     10783        const int deviceHeight = device->height();
     10784        if (right + 1 > deviceWidth)
     10785            effectRect.setRight(deviceWidth - 1);
     10786        if (bottom + 1 > deviceHeight)
     10787            effectRect.setBottom(deviceHeight -1);
     10788
     10789    }
     10790    if (effectRect.isEmpty())
     10791        return QPixmap();
     10792
     10793    QPixmap pixmap(effectRect.size());
     10794    pixmap.fill(Qt::transparent);
     10795    QPainter pixmapPainter(&pixmap);
     10796    pixmapPainter.setRenderHints(info ? info->painter->renderHints() : QPainter::TextAntialiasing);
     10797
     10798    QTransform effectTransform = QTransform::fromTranslate(-effectRect.x(), -effectRect.y());
     10799    if (deviceCoordinates && info->effectTransform)
     10800        effectTransform *= *info->effectTransform;
     10801
     10802    if (!info) {
     10803        // Logical coordinates without info.
     10804        QTransform sceneTransform = item->sceneTransform();
     10805        QTransform newEffectTransform = sceneTransform.inverted();
     10806        newEffectTransform *= effectTransform;
     10807        scened->draw(item, &pixmapPainter, 0, &sceneTransform, 0, 0, qreal(1.0),
     10808                     &newEffectTransform, false, true);
     10809    } else if (deviceCoordinates) {
     10810        // Device coordinates with info.
     10811        scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, info->exposedRegion,
     10812                     info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform,
     10813                     info->drawItem);
     10814    } else {
     10815        // Item coordinates with info.
     10816        QTransform newEffectTransform = info->transformPtr->inverted();
     10817        newEffectTransform *= effectTransform;
     10818        scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, info->exposedRegion,
     10819                     info->widget, info->opacity, &newEffectTransform, info->wasDirtySceneTransform,
     10820                     info->drawItem);
     10821    }
     10822
     10823    pixmapPainter.end();
     10824
     10825    return pixmap;
     10826}
     10827#endif //QT_NO_GRAPHICSEFFECT
     10828
    885810829#ifndef QT_NO_DEBUG_STREAM
    885910830QDebug operator<<(QDebug debug, QGraphicsItem *item)
     
    886410835    }
    886510836
    8866     QStringList flags;
    8867     if (item->isVisible()) flags << QLatin1String("isVisible");
    8868     if (item->isEnabled()) flags << QLatin1String("isEnabled");
    8869     if (item->isSelected()) flags << QLatin1String("isSelected");
    8870     if (item->hasFocus()) flags << QLatin1String("HasFocus");
    8871 
    8872     debug << "QGraphicsItem(this =" << ((void*)item)
    8873           << ", parent =" << ((void*)item->parentItem())
     10837    if (QGraphicsObject *o = item->toGraphicsObject())
     10838        debug << o->metaObject()->className();
     10839    else
     10840        debug << "QGraphicsItem";
     10841    debug << "(this =" << (void*)item
     10842          << ", parent =" << (void*)item->parentItem()
    887410843          << ", pos =" << item->pos()
    8875           << ", z =" << item->zValue() << ", flags = {"
    8876           << flags.join(QLatin1String("|")) << " })";
     10844          << ", z =" << item->zValue() << ", flags = "
     10845          << item->flags() << ")";
    887710846    return debug;
     10847}
     10848
     10849QDebug operator<<(QDebug debug, QGraphicsObject *item)
     10850{
     10851    if (!item) {
     10852        debug << "QGraphicsObject(0)";
     10853        return debug;
     10854    }
     10855
     10856    debug.nospace() << item->metaObject()->className() << '(' << (void*)item;
     10857    if (!item->objectName().isEmpty())
     10858        debug << ", name = " << item->objectName();
     10859    debug.nospace() << ", parent = " << ((void*)item->parentItem())
     10860          << ", pos = " << item->pos()
     10861          << ", z = " << item->zValue() << ", flags = "
     10862          << item->flags() << ')';
     10863    return debug.space();
    887810864}
    887910865
     
    896310949        str = "ItemOpacityHasChanged";
    896410950        break;
     10951    case QGraphicsItem::ItemScenePositionHasChanged:
     10952        str = "ItemScenePositionHasChanged";
     10953        break;
    896510954    }
    896610955    debug << str;
     
    899910988        str = "ItemStacksBehindParent";
    900010989        break;
     10990    case QGraphicsItem::ItemUsesExtendedStyleOption:
     10991        str = "ItemUsesExtendedStyleOption";
     10992        break;
     10993    case QGraphicsItem::ItemHasNoContents:
     10994        str = "ItemHasNoContents";
     10995        break;
     10996    case QGraphicsItem::ItemSendsGeometryChanges:
     10997        str = "ItemSendsGeometryChanges";
     10998        break;
     10999    case QGraphicsItem::ItemAcceptsInputMethod:
     11000        str = "ItemAcceptsInputMethod";
     11001        break;
     11002    case QGraphicsItem::ItemNegativeZStacksBehindParent:
     11003        str = "ItemNegativeZStacksBehindParent";
     11004        break;
     11005    case QGraphicsItem::ItemIsPanel:
     11006        str = "ItemIsPanel";
     11007        break;
     11008    case QGraphicsItem::ItemIsFocusScope:
     11009        str = "ItemIsFocusScope";
     11010        break;
     11011    case QGraphicsItem::ItemSendsScenePositionChanges:
     11012        str = "ItemSendsScenePositionChanges";
     11013        break;
    900111014    }
    900211015    debug << str;
     
    900611019QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlags flags)
    900711020{
    9008     debug << "(";
     11021    debug << '(';
    900911022    bool f = false;
    9010     for (int i = 0; i < 9; ++i) {
     11023    for (int i = 0; i < 16; ++i) {
    901111024        if (flags & (1 << i)) {
    901211025            if (f)
    9013                 debug << "|";
     11026                debug << '|';
    901411027            f = true;
    901511028            debug << QGraphicsItem::GraphicsItemFlag(int(flags & (1 << i)));
    901611029        }
    901711030    }
    9018     debug << ")";
     11031    debug << ')';
    901911032    return debug;
    902011033}
Note: See TracChangeset for help on using the changeset viewer.