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:
37 edited
16 copied

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/gui/graphicsview/graphicsview.pri

    r2 r561  
    11# Qt graphicsview module
     2HEADERS += graphicsview/qgraphicsgridlayout.h \
     3    graphicsview/qgraphicsitem.h \
     4    graphicsview/qgraphicsitem_p.h \
     5    graphicsview/qgraphicsitemanimation.h \
     6    graphicsview/qgraphicslayout.h \
     7    graphicsview/qgraphicslayout_p.h \
     8    graphicsview/qgraphicslayoutitem.h \
     9    graphicsview/qgraphicslayoutitem_p.h \
     10    graphicsview/qgraphicslinearlayout.h \
     11    graphicsview/qgraphicsproxywidget.h \
     12    graphicsview/qgraphicsscene.h \
     13    graphicsview/qgraphicsscene_bsp_p.h \
     14    graphicsview/qgraphicsscene_p.h \
     15    graphicsview/qgraphicsscenebsptreeindex_p.h \
     16    graphicsview/qgraphicssceneevent.h \
     17    graphicsview/qgraphicssceneindex_p.h \
     18    graphicsview/qgraphicsscenelinearindex_p.h \
     19    graphicsview/qgraphicstransform.h \
     20    graphicsview/qgraphicstransform_p.h \
     21    graphicsview/qgraphicsview.h \
     22    graphicsview/qgraphicsview_p.h \
     23    graphicsview/qgraphicswidget.h \
     24    graphicsview/qgraphicswidget_p.h \
     25    graphicsview/qgridlayoutengine_p.h \
     26    graphicsview/qgraph_p.h \
     27    graphicsview/qsimplex_p.h \
     28    graphicsview/qgraphicsanchorlayout_p.h \
     29    graphicsview/qgraphicsanchorlayout.h
    230
    3 HEADERS += \
    4         graphicsview/qgraphicsitem.h \
    5         graphicsview/qgraphicsitem_p.h \
    6         graphicsview/qgraphicsitemanimation.h \
    7         graphicsview/qgraphicsscene.h \
    8         graphicsview/qgraphicsscene_p.h \
    9         graphicsview/qgraphicsscene_bsp_p.h \
    10         graphicsview/qgraphicssceneevent.h \
    11         graphicsview/qgraphicsview_p.h \
    12         graphicsview/qgraphicsview.h
    13 
    14 SOURCES += \
    15         graphicsview/qgraphicsitem.cpp \
    16         graphicsview/qgraphicsitemanimation.cpp \
    17         graphicsview/qgraphicsscene.cpp \
    18         graphicsview/qgraphicsscene_bsp.cpp \
    19         graphicsview/qgraphicssceneevent.cpp \
    20         graphicsview/qgraphicsview.cpp
    21 
    22 # Widgets on the canvas
    23 
    24 HEADERS += \
    25         graphicsview/qgraphicslayout.h \
    26         graphicsview/qgraphicslayout_p.h \
    27         graphicsview/qgraphicslayoutitem.h \
    28         graphicsview/qgraphicslayoutitem_p.h \
    29         graphicsview/qgraphicslinearlayout.h \
    30         graphicsview/qgraphicswidget.h \
    31         graphicsview/qgraphicswidget_p.h \
    32         graphicsview/qgridlayoutengine_p.h \
    33         graphicsview/qgraphicsproxywidget.h \
    34         graphicsview/qgraphicsgridlayout.h
    35                                        
    36 SOURCES += \
    37         graphicsview/qgraphicslayout.cpp \
    38         graphicsview/qgraphicslayout_p.cpp \
    39         graphicsview/qgraphicslayoutitem.cpp \
    40         graphicsview/qgraphicslinearlayout.cpp \
    41         graphicsview/qgraphicswidget.cpp \
    42         graphicsview/qgraphicswidget_p.cpp \
    43         graphicsview/qgridlayoutengine.cpp \
    44         graphicsview/qgraphicsproxywidget.cpp \
    45         graphicsview/qgraphicsgridlayout.cpp
    46 
     31SOURCES += graphicsview/qgraphicsgridlayout.cpp \
     32    graphicsview/qgraphicsitem.cpp \
     33    graphicsview/qgraphicsitemanimation.cpp \
     34    graphicsview/qgraphicslayout.cpp \
     35    graphicsview/qgraphicslayout_p.cpp \
     36    graphicsview/qgraphicslayoutitem.cpp \
     37    graphicsview/qgraphicslinearlayout.cpp \
     38    graphicsview/qgraphicsproxywidget.cpp \
     39    graphicsview/qgraphicsscene.cpp \
     40    graphicsview/qgraphicsscene_bsp.cpp \
     41    graphicsview/qgraphicsscenebsptreeindex.cpp \
     42    graphicsview/qgraphicssceneevent.cpp \
     43    graphicsview/qgraphicssceneindex.cpp \
     44    graphicsview/qgraphicsscenelinearindex.cpp \
     45    graphicsview/qgraphicstransform.cpp \
     46    graphicsview/qgraphicsview.cpp \
     47    graphicsview/qgraphicswidget.cpp \
     48    graphicsview/qgraphicswidget_p.cpp \
     49    graphicsview/qgridlayoutengine.cpp \
     50    graphicsview/qsimplex_p.cpp \
     51    graphicsview/qgraphicsanchorlayout_p.cpp \
     52    graphicsview/qgraphicsanchorlayout.cpp
  • trunk/src/gui/graphicsview/qgraphicsgridlayout.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    widgets in Graphics View.
    4646    \since 4.4
    47     \ingroup multimedia
     47
    4848    \ingroup graphicsview-api
    4949
     
    6464    removeAt() will remove an item from the layout, without
    6565    destroying it.
    66    
     66
    6767    \sa QGraphicsLinearLayout, QGraphicsWidget
    6868*/
     
    9090
    9191    QGridLayoutEngine engine;
    92 #ifdef QT_DEBUG   
     92#ifdef QT_DEBUG
    9393    void dump(int indent) const;
    9494#endif
     
    101101        wid = new QWidget;
    102102    QGraphicsItem *item = parentItem();
    103     QStyle *style = (item && item->isWidget()) ? static_cast<QGraphicsWidget*>(item)->style() : qApp->style();
     103    QStyle *style = (item && item->isWidget()) ? static_cast<QGraphicsWidget*>(item)->style() : QApplication::style();
    104104    return QLayoutStyleInfo(style, wid);
    105105}
     
    122122        QGraphicsLayoutItem *item = itemAt(i);
    123123        // The following lines can be removed, but this removes the item
    124         // from the layout more efficiently than the implementation of 
     124        // from the layout more efficiently than the implementation of
    125125        // ~QGraphicsLayoutItem.
    126126        removeAt(i);
     
    142142    Q_D(QGraphicsGridLayout);
    143143    if (row < 0 || column < 0) {
    144         qWarning("QGraphicsGridLayout::addItem: invalid row/column: %d",
    145                 row < 0 ? row : column);
    146         return;
     144        qWarning("QGraphicsGridLayout::addItem: invalid row/column: %d",
     145                row < 0 ? row : column);
     146        return;
    147147    }
    148148    if (columnSpan < 1 || rowSpan < 1) {
    149         qWarning("QGraphicsGridLayout::addItem: invalid row span/column span: %d",
    150                 rowSpan < 1 ? rowSpan : columnSpan);
    151         return;
     149        qWarning("QGraphicsGridLayout::addItem: invalid row span/column span: %d",
     150                rowSpan < 1 ? rowSpan : columnSpan);
     151        return;
    152152    }
    153153    if (!item) {
    154         qWarning("QGraphicsGridLayout::addItem: cannot add null item");
    155         return;
     154        qWarning("QGraphicsGridLayout::addItem: cannot add null item");
     155        return;
     156    }
     157    if (item == this) {
     158        qWarning("QGraphicsGridLayout::addItem: cannot insert itself");
     159        return;
    156160    }
    157161
     
    648652
    649653QT_END_NAMESPACE
    650        
    651 #endif //QT_NO_GRAPHICSVIEW       
     654
     655#endif //QT_NO_GRAPHICSVIEW
  • trunk/src/gui/graphicsview/qgraphicsgridlayout.h

    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**
  • 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}
  • trunk/src/gui/graphicsview/qgraphicsitem.h

    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**
     
    4747#include <QtCore/qvariant.h>
    4848#include <QtCore/qrect.h>
     49#include <QtCore/qscopedpointer.h>
    4950#include <QtGui/qpainterpath.h>
    5051#include <QtGui/qpixmap.h>
     
    6364class QCursor;
    6465class QFocusEvent;
     66class QGraphicsEffect;
    6567class QGraphicsItemGroup;
     68class QGraphicsObject;
    6669class QGraphicsSceneContextMenuEvent;
    6770class QGraphicsSceneDragDropEvent;
     
    7174class QGraphicsSceneWheelEvent;
    7275class QGraphicsScene;
     76class QGraphicsTransform;
    7377class QGraphicsWidget;
    7478class QInputMethodEvent;
     
    9599        ItemIgnoresParentOpacity = 0x40,
    96100        ItemDoesntPropagateOpacityToChildren = 0x80,
    97         ItemStacksBehindParent = 0x100
     101        ItemStacksBehindParent = 0x100,
     102        ItemUsesExtendedStyleOption = 0x200,
     103        ItemHasNoContents = 0x400,
     104        ItemSendsGeometryChanges = 0x800,
     105        ItemAcceptsInputMethod = 0x1000,
     106        ItemNegativeZStacksBehindParent = 0x2000,
     107        ItemIsPanel = 0x4000,
     108        ItemIsFocusScope = 0x8000, // internal
     109        ItemSendsScenePositionChanges = 0x10000
     110        // NB! Don't forget to increase the d_ptr->flags bit field by 1 when adding a new flag.
    98111    };
    99112    Q_DECLARE_FLAGS(GraphicsItemFlags, GraphicsItemFlag)
     
    126139        ItemZValueHasChanged,
    127140        ItemOpacityChange,
    128         ItemOpacityHasChanged
     141        ItemOpacityHasChanged,
     142        ItemScenePositionHasChanged
    129143    };
    130144
     
    135149    };
    136150
     151    enum PanelModality
     152    {
     153        NonModal,
     154        PanelModal,
     155        SceneModal
     156    };
     157
    137158    QGraphicsItem(QGraphicsItem *parent = 0
    138159#ifndef Q_QDOC
    139                   // obsolete argument
     160                  // ### obsolete argument
    140161                  , QGraphicsScene *scene = 0
    141162#endif
     
    147168    QGraphicsItem *parentItem() const;
    148169    QGraphicsItem *topLevelItem() const;
     170    QGraphicsObject *parentObject() const;
    149171    QGraphicsWidget *parentWidget() const;
    150172    QGraphicsWidget *topLevelWidget() const;
    151173    QGraphicsWidget *window() const;
     174    QGraphicsItem *panel() const;
    152175    void setParentItem(QGraphicsItem *parent);
    153176    QList<QGraphicsItem *> children() const; // ### obsolete
     
    155178    bool isWidget() const;
    156179    bool isWindow() const;
     180    bool isPanel() const;
     181
     182    QGraphicsObject *toGraphicsObject();
     183    const QGraphicsObject *toGraphicsObject() const;
    157184
    158185    QGraphicsItemGroup *group() const;
     
    165192    CacheMode cacheMode() const;
    166193    void setCacheMode(CacheMode mode, const QSize &cacheSize = QSize());
     194
     195    PanelModality panelModality() const;
     196    void setPanelModality(PanelModality panelModality);
     197    bool isBlockedByModalPanel(QGraphicsItem **blockingPanel = 0) const;
    167198
    168199#ifndef QT_NO_TOOLTIP
     
    197228    void setOpacity(qreal opacity);
    198229
     230#ifndef QT_NO_GRAPHICSEFFECT
     231    // Effect
     232    QGraphicsEffect *graphicsEffect() const;
     233    void setGraphicsEffect(QGraphicsEffect *effect);
     234#endif //QT_NO_GRAPHICSEFFECT
     235
    199236    Qt::MouseButtons acceptedMouseButtons() const;
    200237    void setAcceptedMouseButtons(Qt::MouseButtons buttons);
    201238
    202     bool acceptsHoverEvents() const; // obsolete
    203     void setAcceptsHoverEvents(bool enabled); // obsolete
     239    bool acceptsHoverEvents() const; // ### obsolete
     240    void setAcceptsHoverEvents(bool enabled); // ### obsolete
    204241    bool acceptHoverEvents() const;
    205242    void setAcceptHoverEvents(bool enabled);
     243    bool acceptTouchEvents() const;
     244    void setAcceptTouchEvents(bool enabled);
     245
     246    bool filtersChildEvents() const;
     247    void setFiltersChildEvents(bool enabled);
    206248
    207249    bool handlesChildEvents() const;
    208250    void setHandlesChildEvents(bool enabled);
     251
     252    bool isActive() const;
     253    void setActive(bool active);
    209254
    210255    bool hasFocus() const;
    211256    void setFocus(Qt::FocusReason focusReason = Qt::OtherFocusReason);
    212257    void clearFocus();
     258
     259    QGraphicsItem *focusProxy() const;
     260    void setFocusProxy(QGraphicsItem *item);
     261
     262    QGraphicsItem *focusItem() const;
     263    QGraphicsItem *focusScopeItem() const;
    213264
    214265    void grabMouse();
     
    220271    QPointF pos() const;
    221272    inline qreal x() const { return pos().x(); }
     273    void setX(qreal x);
    222274    inline qreal y() const { return pos().y(); }
     275    void setY(qreal y);
    223276    QPointF scenePos() const;
    224277    void setPos(const QPointF &pos);
     
    240293    void setTransform(const QTransform &matrix, bool combine = false);
    241294    void resetTransform();
    242    
    243     void rotate(qreal angle);
    244     void scale(qreal sx, qreal sy);
    245     void shear(qreal sh, qreal sv);
    246     void translate(qreal dx, qreal dy);
     295
     296    void rotate(qreal angle);           // ### obsolete
     297    void scale(qreal sx, qreal sy);     // ### obsolete
     298    void shear(qreal sh, qreal sv);     // ### obsolete
     299    void translate(qreal dx, qreal dy); // ### obsolete
     300
     301    void setRotation(qreal angle);
     302    qreal rotation() const;
     303
     304    void setScale(qreal scale);
     305    qreal scale() const;
     306
     307    QList<QGraphicsTransform *> transformations() const;
     308    void setTransformations(const QList<QGraphicsTransform *> &transformations);
     309
     310    QPointF transformOriginPoint() const;
     311    void setTransformOriginPoint(const QPointF &origin);
     312    inline void setTransformOriginPoint(qreal ax, qreal ay)
     313    { setTransformOriginPoint(QPointF(ax,ay)); }
     314
    247315    virtual void advance(int phase);
    248316
     
    250318    qreal zValue() const;
    251319    void setZValue(qreal z);
     320    void stackBefore(const QGraphicsItem *sibling);
    252321
    253322    // Hit test
     
    337406    void setData(int key, const QVariant &value);
    338407
     408    Qt::InputMethodHints inputMethodHints() const;
     409    void setInputMethodHints(Qt::InputMethodHints hints);
     410
    339411    enum {
    340412        Type = 1,
     
    381453    QGraphicsItem(QGraphicsItemPrivate &dd,
    382454                  QGraphicsItem *parent, QGraphicsScene *scene);
    383     QGraphicsItemPrivate *d_ptr;
     455    QScopedPointer<QGraphicsItemPrivate> d_ptr;
    384456
    385457    void addToIndex();
     
    394466    friend class QGraphicsScenePrivate;
    395467    friend class QGraphicsSceneFindItemBspTreeVisitor;
     468    friend class QGraphicsSceneBspTree;
    396469    friend class QGraphicsView;
    397470    friend class QGraphicsViewPrivate;
     471    friend class QGraphicsObject;
    398472    friend class QGraphicsWidget;
    399473    friend class QGraphicsWidgetPrivate;
    400474    friend class QGraphicsProxyWidgetPrivate;
     475    friend class QGraphicsSceneIndex;
     476    friend class QGraphicsSceneIndexPrivate;
     477    friend class QGraphicsSceneBspTreeIndex;
     478    friend class QGraphicsSceneBspTreeIndexPrivate;
     479    friend class QGraphicsItemEffectSourcePrivate;
     480    friend class QGraphicsTransformPrivate;
     481    friend class QGestureManager;
    401482    friend class ::tst_QGraphicsItem;
    402483    friend bool qt_closestLeaf(const QGraphicsItem *, const QGraphicsItem *);
     
    405486
    406487Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsItem::GraphicsItemFlags)
     488Q_DECLARE_INTERFACE(QGraphicsItem, "com.trolltech.Qt.QGraphicsItem")
    407489
    408490inline void QGraphicsItem::setPos(qreal ax, qreal ay)
     
    451533{ return mapRectFromScene(QRectF(ax, ay, w, h)); }
    452534
     535
     536class Q_GUI_EXPORT QGraphicsObject : public QObject, public QGraphicsItem
     537{
     538    Q_OBJECT
     539    Q_PROPERTY(QGraphicsObject * parent READ parentObject WRITE setParentItem NOTIFY parentChanged DESIGNABLE false)
     540    Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged FINAL)
     541    Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
     542    Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged FINAL)
     543    Q_PROPERTY(QPointF pos READ pos WRITE setPos)
     544    Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
     545    Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
     546    Q_PROPERTY(qreal z READ zValue WRITE setZValue NOTIFY zChanged)
     547    Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged)
     548    Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged)
     549    Q_PROPERTY(QPointF transformOriginPoint READ transformOriginPoint WRITE setTransformOriginPoint)
     550    Q_INTERFACES(QGraphicsItem)
     551public:
     552    QGraphicsObject(QGraphicsItem *parent = 0);
     553
     554    // ### Qt 5: Disambiguate
     555#ifdef Q_NO_USING_KEYWORD
     556    const QObjectList &children() const { return QObject::children(); }
     557#else
     558    using QObject::children;
     559#endif
     560
     561    void grabGesture(Qt::GestureType type, Qt::GestureFlags flags = Qt::GestureFlags());
     562    void ungrabGesture(Qt::GestureType type);
     563
     564Q_SIGNALS:
     565    void parentChanged();
     566    void opacityChanged();
     567    void visibleChanged();
     568    void enabledChanged();
     569    void xChanged();
     570    void yChanged();
     571    void zChanged();
     572    void rotationChanged();
     573    void scaleChanged();
     574
     575protected:
     576    QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene);
     577private:
     578    friend class QGraphicsItem;
     579    friend class QGraphicsItemPrivate;
     580};
     581
     582
    453583class QAbstractGraphicsShapeItemPrivate;
    454584class Q_GUI_EXPORT QAbstractGraphicsShapeItem : public QGraphicsItem
     
    457587    QAbstractGraphicsShapeItem(QGraphicsItem *parent = 0
    458588#ifndef Q_QDOC
    459                                // obsolete argument
     589                               // ### obsolete argument
    460590                               , QGraphicsScene *scene = 0
    461591#endif
     
    487617    QGraphicsPathItem(QGraphicsItem *parent = 0
    488618#ifndef Q_QDOC
    489                       // obsolete argument
     619                      // ### obsolete argument
    490620                      , QGraphicsScene *scene = 0
    491621#endif
     
    493623    QGraphicsPathItem(const QPainterPath &path, QGraphicsItem *parent = 0
    494624#ifndef Q_QDOC
    495                       // obsolete argument
     625                      // ### obsolete argument
    496626                      , QGraphicsScene *scene = 0
    497627#endif
     
    530660    QGraphicsRectItem(QGraphicsItem *parent = 0
    531661#ifndef Q_QDOC
    532                       // obsolete argument
     662                      // ### obsolete argument
    533663                      , QGraphicsScene *scene = 0
    534664#endif
     
    536666    QGraphicsRectItem(const QRectF &rect, QGraphicsItem *parent = 0
    537667#ifndef Q_QDOC
    538                       // obsolete argument
     668                      // ### obsolete argument
    539669                      , QGraphicsScene *scene = 0
    540670#endif
     
    542672    QGraphicsRectItem(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent = 0
    543673#ifndef Q_QDOC
    544                       // obsolete argument
     674                      // ### obsolete argument
    545675                      , QGraphicsScene *scene = 0
    546676#endif
     
    583713    QGraphicsEllipseItem(QGraphicsItem *parent = 0
    584714#ifndef Q_QDOC
    585                          // obsolete argument
     715                         // ### obsolete argument
    586716                         , QGraphicsScene *scene = 0
    587717#endif
     
    589719    QGraphicsEllipseItem(const QRectF &rect, QGraphicsItem *parent = 0
    590720#ifndef Q_QDOC
    591                          // obsolete argument
     721                         // ### obsolete argument
    592722                         , QGraphicsScene *scene = 0
    593723#endif
     
    595725    QGraphicsEllipseItem(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent = 0
    596726#ifndef Q_QDOC
    597                          // obsolete argument
     727                         // ### obsolete argument
    598728                         , QGraphicsScene *scene = 0
    599729#endif
     
    642772    QGraphicsPolygonItem(QGraphicsItem *parent = 0
    643773#ifndef Q_QDOC
    644                          // obsolete argument
     774                         // ### obsolete argument
    645775                         , QGraphicsScene *scene = 0
    646776#endif
     
    649779                         QGraphicsItem *parent = 0
    650780#ifndef Q_QDOC
    651                          // obsolete argument
     781                         // ### obsolete argument
    652782                         , QGraphicsScene *scene = 0
    653783#endif
     
    689819    QGraphicsLineItem(QGraphicsItem *parent = 0
    690820#ifndef Q_QDOC
    691                       // obsolete argument
     821                      // ### obsolete argument
    692822                      , QGraphicsScene *scene = 0
    693823#endif
     
    695825    QGraphicsLineItem(const QLineF &line, QGraphicsItem *parent = 0
    696826#ifndef Q_QDOC
    697                       // obsolete argument
     827                      // ### obsolete argument
    698828                      , QGraphicsScene *scene = 0
    699829#endif
     
    701831    QGraphicsLineItem(qreal x1, qreal y1, qreal x2, qreal y2, QGraphicsItem *parent = 0
    702832#ifndef Q_QDOC
    703                       // obsolete argument
     833                      // ### obsolete argument
    704834                      , QGraphicsScene *scene = 0
    705835#endif
     
    749879    QGraphicsPixmapItem(QGraphicsItem *parent = 0
    750880#ifndef Q_QDOC
    751                         // obsolete argument
     881                        // ### obsolete argument
    752882                        , QGraphicsScene *scene = 0
    753883#endif
     
    755885    QGraphicsPixmapItem(const QPixmap &pixmap, QGraphicsItem *parent = 0
    756886#ifndef Q_QDOC
    757                         // obsolete argument
     887                        // ### obsolete argument
    758888                        , QGraphicsScene *scene = 0
    759889#endif
     
    802932class QTextDocument;
    803933class QTextCursor;
    804 class Q_GUI_EXPORT QGraphicsTextItem : public QObject, public QGraphicsItem
     934class Q_GUI_EXPORT QGraphicsTextItem : public QGraphicsObject
    805935{
    806936    Q_OBJECT
     
    811941    QGraphicsTextItem(QGraphicsItem *parent = 0
    812942#ifndef Q_QDOC
    813                       // obsolete argument
     943                      // ### obsolete argument
    814944                      , QGraphicsScene *scene = 0
    815945#endif
     
    817947    QGraphicsTextItem(const QString &text, QGraphicsItem *parent = 0
    818948#ifndef Q_QDOC
    819                       // obsolete argument
     949                      // ### obsolete argument
    820950                      , QGraphicsScene *scene = 0
    821951#endif
     
    9121042    QGraphicsSimpleTextItem(QGraphicsItem *parent = 0
    9131043#ifndef Q_QDOC
    914                             // obsolete argument
     1044                            // ### obsolete argument
    9151045                            , QGraphicsScene *scene = 0
    9161046#endif
     
    9181048    QGraphicsSimpleTextItem(const QString &text, QGraphicsItem *parent = 0
    9191049#ifndef Q_QDOC
    920                             // obsolete argument
     1050                            // ### obsolete argument
    9211051                            , QGraphicsScene *scene = 0
    9221052#endif
     
    9581088    QGraphicsItemGroup(QGraphicsItem *parent = 0
    9591089#ifndef Q_QDOC
    960                        // obsolete argument
     1090                       // ### obsolete argument
    9611091                       , QGraphicsScene *scene = 0
    9621092#endif
     
    9951125#ifndef QT_NO_DEBUG_STREAM
    9961126Q_GUI_EXPORT QDebug operator<<(QDebug debug, QGraphicsItem *item);
     1127Q_GUI_EXPORT QDebug operator<<(QDebug debug, QGraphicsObject *item);
    9971128Q_GUI_EXPORT QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemChange change);
    9981129Q_GUI_EXPORT QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag);
     
    10141145
    10151146#endif // QGRAPHICSITEM_H
    1016 
  • trunk/src/gui/graphicsview/qgraphicsitem_p.h

    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**
     
    4848//
    4949// This file is not part of the Qt API.  It exists for the convenience
    50 // of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp.  This header
    51 // file may change from version to version without notice, or even be removed.
     50// of other Qt classes.  This header file may change from version to
     51// version without notice, or even be removed.
    5252//
    5353// We mean it.
     
    5555
    5656#include "qgraphicsitem.h"
     57#include "qset.h"
     58#include "qpixmapcache.h"
     59#include <private/qgraphicsview_p.h>
     60#include "qgraphicstransform.h"
     61#include <private/qgraphicstransform_p.h>
     62
     63#include <private/qgraphicseffect_p.h>
     64#include <qgraphicseffect.h>
     65
     66#include <QtCore/qpoint.h>
    5767
    5868#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW
     
    7080    QRect boundingRect;
    7181    QSize fixedSize;
    72     QString key;
     82    QPixmapCache::Key key;
    7383
    7484    // DeviceCoordinateCache only
    7585    struct DeviceData {
     86        DeviceData() {}
    7687        QTransform lastTransform;
    7788        QPoint cacheIndent;
    78         QString key;
     89        QPixmapCache::Key key;
    7990    };
    8091    QMap<QPaintDevice *, DeviceData> deviceData;
     
    8899};
    89100
    90 class Q_AUTOTEST_EXPORT QGraphicsItemPrivate
     101class Q_GUI_EXPORT QGraphicsItemPrivate
    91102{
    92103    Q_DECLARE_PUBLIC(QGraphicsItem)
    93104public:
    94105    enum Extra {
    95         ExtraTransform,
    96106        ExtraToolTip,
    97107        ExtraCursor,
    98108        ExtraCacheData,
    99109        ExtraMaxDeviceCoordCacheSize,
    100         ExtraBoundingRegionGranularity,
    101         ExtraOpacity,
    102         ExtraEffectiveOpacity
     110        ExtraBoundingRegionGranularity
    103111    };
    104112
     
    107115        AncestorHandlesChildEvents = 0x1,
    108116        AncestorClipsChildren = 0x2,
    109         AncestorIgnoresTransformations = 0x4
     117        AncestorIgnoresTransformations = 0x4,
     118        AncestorFiltersChildEvents = 0x8
    110119    };
    111120
    112121    inline QGraphicsItemPrivate()
    113122        : z(0),
     123        opacity(1.),
    114124        scene(0),
    115125        parent(0),
     126        transformData(0),
     127        graphicsEffect(0),
    116128        index(-1),
    117         depth(0),
     129        siblingIndex(-1),
     130        itemDepth(-1),
     131        focusProxy(0),
     132        subFocusItem(0),
     133        focusScopeItem(0),
     134        imHints(Qt::ImhNone),
     135        panelModality(QGraphicsItem::NonModal),
    118136        acceptedMouseButtons(0x1f),
    119137        visible(1),
     
    127145        handlesChildEvents(0),
    128146        itemDiscovered(0),
    129         hasTransform(0),
    130147        hasCursor(0),
    131148        ancestorFlags(0),
    132149        cacheMode(0),
    133150        hasBoundingRegionGranularity(0),
    134         flags(0),
    135         hasOpacity(0),
    136         hasEffectiveOpacity(0),
    137151        isWidget(0),
    138152        dirty(0),
    139153        dirtyChildren(0),
    140154        localCollisionHack(0),
    141         dirtyClipPath(1),
    142         emptyClipPath(0),
    143155        inSetPosHelper(0),
    144         allChildrenCombineOpacity(1),
     156        needSortChildren(1), // ### can be 0 by default?
     157        allChildrenDirty(0),
     158        fullUpdatePending(0),
     159        flags(0),
     160        dirtyChildrenBoundingRect(1),
     161        paintedViewBoundingRectsNeedRepaint(0),
     162        dirtySceneTransform(1),
     163        geometryChanged(1),
     164        inDestructor(0),
     165        isObject(0),
     166        ignoreVisible(0),
     167        ignoreOpacity(0),
     168        acceptTouchEvents(0),
     169        acceptedTouchBeginEvent(0),
     170        filtersDescendantEvents(0),
     171        sceneTransformTranslateOnly(0),
     172        notifyBoundingRectChanged(0),
     173        notifyInvalidated(0),
     174        mouseSetsFocus(1),
     175        explicitActivate(0),
     176        wantsActive(0),
     177        holesInSiblingIndex(0),
     178        sequentialOrdering(1),
     179        updateDueToGraphicsEffect(0),
     180        scenePosDescendants(0),
    145181        globalStackingOrder(-1),
    146         sceneTransformIndex(-1),
    147182        q_ptr(0)
    148183    {
     
    151186    inline virtual ~QGraphicsItemPrivate()
    152187    { }
     188
     189    static const QGraphicsItemPrivate *get(const QGraphicsItem *item)
     190    {
     191        return item->d_ptr.data();
     192    }
     193    static QGraphicsItemPrivate *get(QGraphicsItem *item)
     194    {
     195        return item->d_ptr.data();
     196    }
    153197
    154198    void updateAncestorFlag(QGraphicsItem::GraphicsItemFlag childFlag,
     
    157201    void remapItemPos(QEvent *event, QGraphicsItem *item);
    158202    QPointF genericMapFromScene(const QPointF &pos, const QWidget *viewport) const;
    159     bool itemIsUntransformable() const;
     203    inline bool itemIsUntransformable() const
     204    {
     205        return (flags & QGraphicsItem::ItemIgnoresTransformations)
     206            || (ancestorFlags & AncestorIgnoresTransformations);
     207    }
     208
     209    void combineTransformToParent(QTransform *x, const QTransform *viewTransform = 0) const;
     210    void combineTransformFromParent(QTransform *x, const QTransform *viewTransform = 0) const;
     211    virtual void updateSceneTransformFromParent();
    160212
    161213    // ### Qt 5: Remove. Workaround for reimplementation added after Qt 4.4.
     
    163215    static bool movableAncestorIsSelected(const QGraphicsItem *item);
    164216
    165     void setPosHelper(const QPointF &pos);
     217    virtual void setPosHelper(const QPointF &pos);
     218    void setTransformHelper(const QTransform &transform);
     219    void appendGraphicsTransform(QGraphicsTransform *t);
    166220    void setVisibleHelper(bool newVisible, bool explicitly, bool update = true);
    167221    void setEnabledHelper(bool newEnabled, bool explicitly, bool update = true);
    168     bool discardUpdateRequest(bool ignoreClipping = false,
    169                               bool ignoreVisibleBit = false,
    170                               bool ignoreDirtyBit = false) const;
    171     void updateHelper(const QRectF &rect = QRectF(), bool force = false, bool maybeDirtyClipPath = false);
    172     void fullUpdateHelper(bool childrenOnly = false, bool maybeDirtyClipPath = false);
    173     void updateEffectiveOpacity();
    174     void resolveEffectiveOpacity(qreal effectiveParentOpacity);
    175     void resolveDepth(int parentDepth);
    176     void invalidateSceneTransformCache();
     222    bool discardUpdateRequest(bool ignoreVisibleBit = false,
     223                              bool ignoreDirtyBit = false, bool ignoreOpacity = false) const;
     224    int depth() const;
     225#ifndef QT_NO_GRAPHICSEFFECT
     226    void invalidateGraphicsEffectsRecursively();
     227#endif //QT_NO_GRAPHICSEFFECT
     228    void invalidateDepthRecursively();
     229    void resolveDepth();
     230    void addChild(QGraphicsItem *child);
     231    void removeChild(QGraphicsItem *child);
     232    void setParentItemHelper(QGraphicsItem *parent);
     233    void childrenBoundingRectHelper(QTransform *x, QRectF *rect);
     234    void initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform,
     235                         const QRegion &exposedRegion, bool allItems = false) const;
     236    QRectF effectiveBoundingRect() const;
     237    QRectF sceneEffectiveBoundingRect() const;
     238
     239    QRectF effectiveBoundingRect(const QRectF &rect) const;
    177240
    178241    virtual void resolveFont(uint inheritedMask)
     
    238301        { return type < extra; }
    239302    };
     303
    240304    QList<ExtraStruct> extras;
    241305
     306    QGraphicsItemCache *maybeExtraItemCache() const;
    242307    QGraphicsItemCache *extraItemCache() const;
    243308    void removeExtraItemCache();
    244309
    245     inline void setCachedClipPath(const QPainterPath &path)
    246     {
    247         cachedClipPath = path;
    248         dirtyClipPath = 0;
    249         emptyClipPath = 0;
    250     }
    251 
    252     inline void setEmptyCachedClipPath()
    253     {
    254         emptyClipPath = 1;
    255         dirtyClipPath = 0;
    256     }
    257 
    258     void setEmptyCachedClipPathRecursively(const QRectF &emptyIfOutsideThisRect = QRectF());
    259 
    260     inline void invalidateCachedClipPath()
    261     { /*static int count = 0 ;qWarning("%i", ++count);*/ dirtyClipPath = 1; emptyClipPath = 0; }
    262 
    263     void invalidateCachedClipPathRecursively(bool childrenOnly = false, const QRectF &emptyIfOutsideThisRect = QRectF());
    264     void updateCachedClipPathFromSetPosHelper(const QPointF &newPos);
     310    void ensureSceneTransformRecursive(QGraphicsItem **topMostDirtyItem);
     311    inline void ensureSceneTransform()
     312    {
     313        QGraphicsItem *that = q_func();
     314        ensureSceneTransformRecursive(&that);
     315    }
     316
     317    inline bool hasTranslateOnlySceneTransform()
     318    {
     319        ensureSceneTransform();
     320        return sceneTransformTranslateOnly;
     321    }
     322
     323    inline void invalidateChildrenSceneTransform()
     324    {
     325        for (int i = 0; i < children.size(); ++i)
     326            children.at(i)->d_ptr->dirtySceneTransform = 1;
     327    }
     328
     329    inline qreal calcEffectiveOpacity() const
     330    {
     331        qreal o = opacity;
     332        QGraphicsItem *p = parent;
     333        int myFlags = flags;
     334        while (p) {
     335            int parentFlags = p->d_ptr->flags;
     336
     337            // If I have a parent, and I don't ignore my parent's opacity, and my
     338            // parent propagates to me, then combine my local opacity with my parent's
     339            // effective opacity into my effective opacity.
     340            if ((myFlags & QGraphicsItem::ItemIgnoresParentOpacity)
     341                || (parentFlags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) {
     342                break;
     343            }
     344
     345            o *= p->d_ptr->opacity;
     346            p = p->d_ptr->parent;
     347            myFlags = parentFlags;
     348        }
     349        return o;
     350    }
    265351
    266352    inline bool isFullyTransparent() const
    267     { return hasEffectiveOpacity && qFuzzyCompare(q_func()->effectiveOpacity() + 1, qreal(1.0)); }
     353    {
     354        if (opacity < 0.001)
     355            return true;
     356        if (!parent)
     357            return false;
     358
     359        return calcEffectiveOpacity() < 0.001;
     360    }
     361
     362    inline qreal effectiveOpacity() const {
     363        if (!parent || !opacity)
     364            return opacity;
     365
     366        return calcEffectiveOpacity();
     367    }
     368
     369    inline qreal combineOpacityFromParent(qreal parentOpacity) const
     370    {
     371        if (parent && !(flags & QGraphicsItem::ItemIgnoresParentOpacity)
     372            && !(parent->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) {
     373            return parentOpacity * opacity;
     374        }
     375        return opacity;
     376    }
    268377
    269378    inline bool childrenCombineOpacity() const
    270     { return allChildrenCombineOpacity || children.isEmpty(); }
    271 
    272     inline bool isClippedAway() const
    273     { return !dirtyClipPath && q_func()->isClipped() && (emptyClipPath || cachedClipPath.isEmpty()); }
     379    {
     380        if (!children.size())
     381            return true;
     382        if (flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)
     383            return false;
     384
     385        for (int i = 0; i < children.size(); ++i) {
     386            if (children.at(i)->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)
     387                return false;
     388        }
     389        return true;
     390    }
    274391
    275392    inline bool childrenClippedToShape() const
     
    278395    inline bool isInvisible() const
    279396    {
    280         return !visible
    281                || (childrenClippedToShape() && isClippedAway())
    282                || (childrenCombineOpacity() && isFullyTransparent());
    283     }
    284 
    285     QPainterPath cachedClipPath;
     397        return !visible || (childrenCombineOpacity() && isFullyTransparent());
     398    }
     399
     400    void setFocusHelper(Qt::FocusReason focusReason, bool climb);
     401    void setSubFocus(QGraphicsItem *rootItem = 0);
     402    void clearSubFocus(QGraphicsItem *rootItem = 0);
     403    void resetFocusProxy();
     404    virtual void subFocusItemChange();
     405
     406    inline QTransform transformToParent() const;
     407    inline void ensureSortedChildren();
     408    static inline bool insertionOrder(QGraphicsItem *a, QGraphicsItem *b);
     409    void ensureSequentialSiblingIndex();
     410    inline void sendScenePosChange();
     411    virtual void siblingOrderChange();
     412
     413    QRectF childrenBoundingRect;
     414    QRectF needsRepaint;
     415    QMap<QWidget *, QRect> paintedViewBoundingRects;
    286416    QPointF pos;
    287417    qreal z;
     418    qreal opacity;
    288419    QGraphicsScene *scene;
    289420    QGraphicsItem *parent;
    290421    QList<QGraphicsItem *> children;
     422    struct TransformData;
     423    TransformData *transformData;
     424    QGraphicsEffect *graphicsEffect;
     425    QTransform sceneTransform;
    291426    int index;
    292     int depth;
    293 
    294     // Packed 32 bytes
     427    int siblingIndex;
     428    int itemDepth;  // Lazily calculated when calling depth().
     429    QGraphicsItem *focusProxy;
     430    QList<QGraphicsItem **> focusProxyRefs;
     431    QGraphicsItem *subFocusItem;
     432    QGraphicsItem *focusScopeItem;
     433    Qt::InputMethodHints imHints;
     434    QGraphicsItem::PanelModality panelModality;
     435    QMap<Qt::GestureType, Qt::GestureFlags> gestureContext;
     436
     437    // Packed 32 bits
    295438    quint32 acceptedMouseButtons : 5;
    296439    quint32 visible : 1;
     
    304447    quint32 handlesChildEvents : 1;
    305448    quint32 itemDiscovered : 1;
    306     quint32 hasTransform : 1;
    307449    quint32 hasCursor : 1;
    308     quint32 ancestorFlags : 3;
     450    quint32 ancestorFlags : 4;
    309451    quint32 cacheMode : 2;
    310452    quint32 hasBoundingRegionGranularity : 1;
    311     quint32 flags : 9;
    312 
    313     // New 32 bytes
    314     quint32 hasOpacity : 1;
    315     quint32 hasEffectiveOpacity : 1;
    316453    quint32 isWidget : 1;
    317     quint32 dirty : 1;   
    318     quint32 dirtyChildren : 1;   
     454    quint32 dirty : 1;
     455    quint32 dirtyChildren : 1;
    319456    quint32 localCollisionHack : 1;
    320     quint32 dirtyClipPath : 1;
    321     quint32 emptyClipPath : 1;
    322457    quint32 inSetPosHelper : 1;
    323     quint32 allChildrenCombineOpacity : 1;
     458    quint32 needSortChildren : 1;
     459    quint32 allChildrenDirty : 1;
     460
     461    // Packed 32 bits
     462    quint32 fullUpdatePending : 1;
     463    quint32 flags : 17;
     464    quint32 dirtyChildrenBoundingRect : 1;
     465    quint32 paintedViewBoundingRectsNeedRepaint : 1;
     466    quint32 dirtySceneTransform : 1;
     467    quint32 geometryChanged : 1;
     468    quint32 inDestructor : 1;
     469    quint32 isObject : 1;
     470    quint32 ignoreVisible : 1;
     471    quint32 ignoreOpacity : 1;
     472    quint32 acceptTouchEvents : 1;
     473    quint32 acceptedTouchBeginEvent : 1;
     474    quint32 filtersDescendantEvents : 1;
     475    quint32 sceneTransformTranslateOnly : 1;
     476    quint32 notifyBoundingRectChanged : 1;
     477    quint32 notifyInvalidated : 1;
     478
     479    // New 32 bits
     480    quint32 mouseSetsFocus : 1;
     481    quint32 explicitActivate : 1;
     482    quint32 wantsActive : 1;
     483    quint32 holesInSiblingIndex : 1;
     484    quint32 sequentialOrdering : 1;
     485    quint32 updateDueToGraphicsEffect : 1;
     486    quint32 scenePosDescendants : 1;
    324487
    325488    // Optional stacking order
    326489    int globalStackingOrder;
    327     int sceneTransformIndex;
    328 
    329490    QGraphicsItem *q_ptr;
    330491};
    331492
     493struct QGraphicsItemPrivate::TransformData
     494{
     495    QTransform transform;
     496    qreal scale;
     497    qreal rotation;
     498    qreal xOrigin;
     499    qreal yOrigin;
     500    QList<QGraphicsTransform *> graphicsTransforms;
     501    bool onlyTransform;
     502
     503    TransformData() :
     504        scale(1.0), rotation(0.0),
     505        xOrigin(0.0), yOrigin(0.0),
     506        onlyTransform(true)
     507    { }
     508
     509    QTransform computedFullTransform(QTransform *postmultiplyTransform = 0) const
     510    {
     511        if (onlyTransform) {
     512            if (!postmultiplyTransform || postmultiplyTransform->isIdentity())
     513                return transform;
     514            if (transform.isIdentity())
     515                return *postmultiplyTransform;
     516            return transform * *postmultiplyTransform;
     517        }
     518
     519        QTransform x(transform);
     520        if (!graphicsTransforms.isEmpty()) {
     521            QMatrix4x4 m;
     522            for (int i = 0; i < graphicsTransforms.size(); ++i)
     523                graphicsTransforms.at(i)->applyTo(&m);
     524            x *= m.toTransform();
     525        }
     526        x.translate(xOrigin, yOrigin);
     527        x.rotate(rotation);
     528        x.scale(scale, scale);
     529        x.translate(-xOrigin, -yOrigin);
     530        if (postmultiplyTransform)
     531            x *= *postmultiplyTransform;
     532        return x;
     533    }
     534};
     535
     536struct QGraphicsItemPaintInfo
     537{
     538    inline QGraphicsItemPaintInfo(const QTransform *const xform1, const QTransform *const xform2,
     539                                  const QTransform *const xform3,
     540                                  QRegion *r, QWidget *w, QStyleOptionGraphicsItem *opt,
     541                                  QPainter *p, qreal o, bool b1, bool b2)
     542        : viewTransform(xform1), transformPtr(xform2), effectTransform(xform3), exposedRegion(r), widget(w),
     543          option(opt), painter(p), opacity(o), wasDirtySceneTransform(b1), drawItem(b2)
     544    {}
     545
     546    const QTransform *viewTransform;
     547    const QTransform *transformPtr;
     548    const QTransform *effectTransform;
     549    QRegion *exposedRegion;
     550    QWidget *widget;
     551    QStyleOptionGraphicsItem *option;
     552    QPainter *painter;
     553    qreal opacity;
     554    quint32 wasDirtySceneTransform : 1;
     555    quint32 drawItem : 1;
     556};
     557
     558#ifndef QT_NO_GRAPHICSEFFECT
     559class QGraphicsItemEffectSourcePrivate : public QGraphicsEffectSourcePrivate
     560{
     561public:
     562    QGraphicsItemEffectSourcePrivate(QGraphicsItem *i)
     563        : QGraphicsEffectSourcePrivate(), item(i), info(0)
     564    {}
     565
     566    inline void detach()
     567    {
     568        item->d_ptr->graphicsEffect = 0;
     569        item->prepareGeometryChange();
     570    }
     571
     572    inline const QGraphicsItem *graphicsItem() const
     573    { return item; }
     574
     575    inline const QWidget *widget() const
     576    { return 0; }
     577
     578    inline void update() {
     579        item->d_ptr->updateDueToGraphicsEffect = true;
     580        item->update();
     581        item->d_ptr->updateDueToGraphicsEffect = false;
     582    }
     583
     584    inline void effectBoundingRectChanged()
     585    { item->prepareGeometryChange(); }
     586
     587    inline bool isPixmap() const
     588    {
     589        return item->type() == QGraphicsPixmapItem::Type
     590               && !(item->flags() & QGraphicsItem::ItemIsSelectable)
     591               && item->d_ptr->children.size() == 0;
     592            //|| (item->d_ptr->isObject && qobject_cast<QmlGraphicsImage *>(q_func()));
     593    }
     594
     595    inline const QStyleOption *styleOption() const
     596    { return info ? info->option : 0; }
     597
     598    inline QRect deviceRect() const
     599    {
     600        if (!info || !info->widget) {
     601            qWarning("QGraphicsEffectSource::deviceRect: Not yet implemented, lacking device context");
     602            return QRect();
     603        }
     604        return info->widget->rect();
     605    }
     606
     607    QRectF boundingRect(Qt::CoordinateSystem system) const;
     608    void draw(QPainter *);
     609    QPixmap pixmap(Qt::CoordinateSystem system,
     610                   QPoint *offset,
     611                   QGraphicsEffect::PixmapPadMode mode) const;
     612
     613    QGraphicsItem *item;
     614    QGraphicsItemPaintInfo *info;
     615    QTransform lastEffectTransform;
     616};
     617#endif //QT_NO_GRAPHICSEFFECT
     618
     619/*!
     620    Returns true if \a item1 is on top of \a item2.
     621    The items dont need to be siblings.
     622
     623    \internal
     624*/
     625inline bool qt_closestItemFirst(const QGraphicsItem *item1, const QGraphicsItem *item2)
     626{
     627    // Siblings? Just check their z-values.
     628    const QGraphicsItemPrivate *d1 = item1->d_ptr.data();
     629    const QGraphicsItemPrivate *d2 = item2->d_ptr.data();
     630    if (d1->parent == d2->parent)
     631        return qt_closestLeaf(item1, item2);
     632
     633    // Find common ancestor, and each item's ancestor closest to the common
     634    // ancestor.
     635    int item1Depth = d1->depth();
     636    int item2Depth = d2->depth();
     637    const QGraphicsItem *p = item1;
     638    const QGraphicsItem *t1 = item1;
     639    while (item1Depth > item2Depth && (p = p->d_ptr->parent)) {
     640        if (p == item2) {
     641            // item2 is one of item1's ancestors; item1 is on top
     642            return !(t1->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent);
     643        }
     644        t1 = p;
     645        --item1Depth;
     646    }
     647    p = item2;
     648    const QGraphicsItem *t2 = item2;
     649    while (item2Depth > item1Depth && (p = p->d_ptr->parent)) {
     650        if (p == item1) {
     651            // item1 is one of item2's ancestors; item1 is not on top
     652            return (t2->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent);
     653        }
     654        t2 = p;
     655        --item2Depth;
     656    }
     657
     658    // item1Ancestor is now at the same level as item2Ancestor, but not the same.
     659    const QGraphicsItem *p1 = t1;
     660    const QGraphicsItem *p2 = t2;
     661    while (t1 && t1 != t2) {
     662        p1 = t1;
     663        p2 = t2;
     664        t1 = t1->d_ptr->parent;
     665        t2 = t2->d_ptr->parent;
     666    }
     667
     668    // in case we have a common ancestor, we compare the immediate children in the ancestor's path.
     669    // otherwise we compare the respective items' topLevelItems directly.
     670    return qt_closestLeaf(p1, p2);
     671}
     672
     673/*!
     674    Returns true if \a item2 is on top of \a item1.
     675    The items dont need to be siblings.
     676
     677    \internal
     678*/
     679inline bool qt_closestItemLast(const QGraphicsItem *item1, const QGraphicsItem *item2)
     680{
     681    return qt_closestItemFirst(item2, item1);
     682}
     683
     684/*!
     685    \internal
     686*/
     687inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2)
     688{
     689    // Return true if sibling item1 is on top of item2.
     690    const QGraphicsItemPrivate *d1 = item1->d_ptr.data();
     691    const QGraphicsItemPrivate *d2 = item2->d_ptr.data();
     692    bool f1 = d1->flags & QGraphicsItem::ItemStacksBehindParent;
     693    bool f2 = d2->flags & QGraphicsItem::ItemStacksBehindParent;
     694    if (f1 != f2)
     695        return f2;
     696    if (d1->z != d2->z)
     697        return d1->z > d2->z;
     698    return d1->siblingIndex > d2->siblingIndex;
     699}
     700
     701/*!
     702    \internal
     703*/
     704inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2)
     705{ return qt_closestLeaf(item2, item1); }
     706
     707/*
     708   return the full transform of the item to the parent.  This include the position and all the transform data
     709*/
     710inline QTransform QGraphicsItemPrivate::transformToParent() const
     711{
     712    QTransform matrix;
     713    combineTransformToParent(&matrix);
     714    return matrix;
     715}
     716
     717/*!
     718    \internal
     719*/
     720inline void QGraphicsItemPrivate::ensureSortedChildren()
     721{
     722    if (needSortChildren) {
     723        qSort(children.begin(), children.end(), qt_notclosestLeaf);
     724        needSortChildren = 0;
     725        sequentialOrdering = 1;
     726        for (int i = 0; i < children.size(); ++i) {
     727            if (children[i]->d_ptr->siblingIndex != i) {
     728                sequentialOrdering = 0;
     729                break;
     730            }
     731        }
     732    }
     733}
     734
     735/*!
     736    \internal
     737*/
     738inline bool QGraphicsItemPrivate::insertionOrder(QGraphicsItem *a, QGraphicsItem *b)
     739{
     740    return a->d_ptr->siblingIndex < b->d_ptr->siblingIndex;
     741}
     742
    332743QT_END_NAMESPACE
    333744
  • trunk/src/gui/graphicsview/qgraphicsitemanimation.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    support for QGraphicsItem.
    4646    \since 4.2
    47     \ingroup multimedia
    4847    \ingroup graphicsview-api
     48    \deprecated
    4949
    5050    The QGraphicsItemAnimation class animates a QGraphicsItem. You can
  • trunk/src/gui/graphicsview/qgraphicsitemanimation.h

    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**
  • trunk/src/gui/graphicsview/qgraphicslayout.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**
     
    5858    in Graphics View.
    5959    \since 4.4
    60     \ingroup multimedia
    6160    \ingroup graphicsview-api
    6261
     
    150149    \a parent is passed to QGraphicsLayoutItem's constructor and the
    151150    QGraphicsLayoutItem's isLayout argument is set to \e true.
     151
     152    If \a parent is a QGraphicsWidget the layout will be installed
     153    on that widget. (Note that installing a layout will delete the old one
     154    installed.)
    152155*/
    153156QGraphicsLayout::QGraphicsLayout(QGraphicsLayoutItem *parent)
     
    392395    reimplementation can assume that \a i is valid (i.e., it respects the
    393396    value of count()).
    394 
    395     The subclass is free to decide how to store the items.
     397    Together with count(), it is provided as a means of iterating over all items in a layout.
     398
     399    The subclass is free to decide how to store the items, and the visual arrangement
     400    does not have to be reflected through this function.
    396401
    397402    \sa count(), removeAt()
     
    419424*/
    420425
     426/*!
     427    \since 4.6
     428
     429    This function is a convenience function provided for custom layouts, and will go through
     430    all items in the layout and reparent their graphics items to the closest QGraphicsWidget
     431    ancestor of the layout.
     432
     433    If \a layoutItem is already in a different layout, it will be removed  from that layout.
     434
     435    If custom layouts want special behaviour they can ignore to use this function, and implement
     436    their own behaviour.
     437
     438    \sa graphicsItem()
     439 */
     440void QGraphicsLayout::addChildLayoutItem(QGraphicsLayoutItem *layoutItem)
     441{
     442    Q_D(QGraphicsLayout);
     443    d->addChildLayoutItem(layoutItem);
     444}
     445
    421446QT_END_NAMESPACE
    422447
  • trunk/src/gui/graphicsview/qgraphicslayout.h

    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**
     
    7979protected:
    8080    QGraphicsLayout(QGraphicsLayoutPrivate &, QGraphicsLayoutItem *);
     81    void addChildLayoutItem(QGraphicsLayoutItem *layoutItem);
    8182
    8283private:
     
    8586    friend class QGraphicsWidget;
    8687};
     88
     89Q_DECLARE_INTERFACE(QGraphicsLayout, "com.trolltech.Qt.QGraphicsLayout")
    8790
    8891#endif
  • trunk/src/gui/graphicsview/qgraphicslayout_p.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**
     
    121121        return false;
    122122
    123     QGraphicsLayoutItem *child;
    124     for (int i = 0; (child = lay->itemAt(i)); ++i) {
     123    for (int i = lay->count() - 1; i >= 0; --i) {
     124        QGraphicsLayoutItem *child = lay->itemAt(i);
    125125        if (child && child->isLayout()) {
    126126            if (removeLayoutItemFromLayout(static_cast<QGraphicsLayout*>(child), layoutItem))
  • trunk/src/gui/graphicsview/qgraphicslayout_p.h

    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**
     
    4848//
    4949// This file is not part of the Qt API.  It exists for the convenience
    50 // of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp.  This header
    51 // file may change from version to version without notice, or even be removed.
     50// of other Qt classes.  This header file may change from version to
     51// version without notice, or even be removed.
    5252//
    5353// We mean it.
     
    6161#include "qgraphicslayoutitem_p.h"
    6262#include <QtGui/qstyle.h>
     63#include <QtGui/qwidget.h>
     64#include <QtGui/qstyleoption.h>
    6365
    6466QT_BEGIN_NAMESPACE
     
    7678}
    7779#endif
     80
     81
     82class QLayoutStyleInfo
     83{
     84public:
     85    inline QLayoutStyleInfo() { invalidate(); }
     86    inline QLayoutStyleInfo(QStyle *style, QWidget *widget)
     87        : m_valid(true), m_style(style), m_widget(widget)
     88    {
     89        Q_ASSERT(style);
     90        if (widget) //###
     91            m_styleOption.initFrom(widget);
     92        m_defaultSpacing[0] = style->pixelMetric(QStyle::PM_LayoutHorizontalSpacing);
     93        m_defaultSpacing[1] = style->pixelMetric(QStyle::PM_LayoutVerticalSpacing);
     94    }
     95
     96    inline void invalidate() { m_valid = false; m_style = 0; m_widget = 0; }
     97
     98    inline QStyle *style() const { return m_style; }
     99    inline QWidget *widget() const { return m_widget; }
     100
     101    inline bool operator==(const QLayoutStyleInfo &other)
     102        { return m_style == other.m_style && m_widget == other.m_widget; }
     103    inline bool operator!=(const QLayoutStyleInfo &other)
     104        { return !(*this == other); }
     105
     106    inline void setDefaultSpacing(Qt::Orientation o, qreal spacing){
     107        if (spacing >= 0)
     108            m_defaultSpacing[o - 1] = spacing;
     109    }
     110
     111    inline qreal defaultSpacing(Qt::Orientation o) const {
     112        return m_defaultSpacing[o - 1];
     113    }
     114
     115    inline qreal perItemSpacing(QSizePolicy::ControlType control1,
     116                                  QSizePolicy::ControlType control2,
     117                                  Qt::Orientation orientation) const
     118    {
     119        Q_ASSERT(style());
     120        return style()->layoutSpacing(control1, control2, orientation, &m_styleOption, widget());
     121    }
     122private:
     123    bool m_valid;
     124    QStyle *m_style;
     125    QWidget *m_widget;
     126    QStyleOption m_styleOption;
     127    qreal m_defaultSpacing[2];
     128};
    78129
    79130class Q_AUTOTEST_EXPORT QGraphicsLayoutPrivate : public QGraphicsLayoutItemPrivate
  • trunk/src/gui/graphicsview/qgraphicslayoutitem.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**
     
    109109*/
    110110QGraphicsLayoutItemPrivate::QGraphicsLayoutItemPrivate(QGraphicsLayoutItem *par, bool layout)
    111     : parent(par), isLayout(layout), ownedByLayout(false), graphicsItem(0)
    112 {
     111    : parent(par), userSizeHints(0), isLayout(layout), ownedByLayout(false), graphicsItem(0)
     112{
     113}
     114
     115/*!
     116    \internal
     117*/
     118QGraphicsLayoutItemPrivate::~QGraphicsLayoutItemPrivate()
     119{
     120    // Remove any lazily allocated data
     121    delete[] userSizeHints;
    113122}
    114123
     
    133142    for (int i = 0; i < Qt::NSizeHints; ++i) {
    134143        cachedSizeHints[i] = constraint;
    135         combineSize(cachedSizeHints[i], userSizeHints[i]);
     144        if (userSizeHints)
     145            combineSize(cachedSizeHints[i], userSizeHints[i]);
    136146    }
    137147
     
    199209
    200210/*!
     211    \internal
     212
     213     Ensures that userSizeHints is allocated.
     214     This function must be called before any dereferencing.
     215*/
     216void QGraphicsLayoutItemPrivate::ensureUserSizeHints()
     217{
     218    if (!userSizeHints)
     219        userSizeHints = new QSizeF[Qt::NSizeHints];
     220}
     221
     222/*!
     223    \internal
     224
     225    Sets the user size hint \a which to \a size. Use an invalid size to unset the size hint.
     226 */
     227void QGraphicsLayoutItemPrivate::setSize(Qt::SizeHint which, const QSizeF &size)
     228{
     229    Q_Q(QGraphicsLayoutItem);
     230
     231    if (userSizeHints) {
     232        if (size == userSizeHints[which])
     233            return;
     234    } else if (!size.isValid()) {
     235        return;
     236    }
     237
     238    ensureUserSizeHints();
     239    userSizeHints[which] = size;
     240    q->updateGeometry();
     241}
     242
     243/*!
     244    \internal
     245
     246    Sets the width of the user size hint \a which to \a width.
     247 */
     248void QGraphicsLayoutItemPrivate::setSizeComponent(
     249    Qt::SizeHint which, SizeComponent component, qreal value)
     250{
     251    Q_Q(QGraphicsLayoutItem);
     252    ensureUserSizeHints();
     253    qreal &userValue = (component == Width)
     254        ? userSizeHints[which].rwidth()
     255        : userSizeHints[which].rheight();
     256    if (value == userValue)
     257        return;
     258    userValue = value;
     259    q->updateGeometry();
     260}
     261
     262/*!
    201263    \class QGraphicsLayoutItem
    202264    \brief The QGraphicsLayoutItem class can be inherited to allow your custom
    203265    items to be managed by layouts.
    204266    \since 4.4
    205     \ingroup multimedia
    206267    \ingroup graphicsview-api
    207268
     
    256317    protected constructor, or by calling setParentLayoutItem(). The
    257318    parentLayoutItem() function returns a pointer to the item's layoutItem
    258     parent. If the item's parent is 0 or if the the parent does not inherit
     319    parent. If the item's parent is 0 or if the parent does not inherit
    259320    from QGraphicsItem, the parentLayoutItem() function then returns 0.
    260321    isLayout() returns true if the QGraphicsLayoutItem subclass is itself a
     
    308369        }
    309370    }
    310     delete d_ptr;
    311371}
    312372
     
    382442void QGraphicsLayoutItem::setMinimumSize(const QSizeF &size)
    383443{
    384     Q_D(QGraphicsLayoutItem);
    385     if (size == d->userSizeHints[Qt::MinimumSize])
    386         return;
    387 
    388     d->userSizeHints[Qt::MinimumSize] = size;
    389     updateGeometry();
     444    d_ptr->setSize(Qt::MinimumSize, size);
    390445}
    391446
     
    417472void QGraphicsLayoutItem::setMinimumWidth(qreal width)
    418473{
    419     Q_D(QGraphicsLayoutItem);
    420     qreal &userSizeHint = d->userSizeHints[Qt::MinimumSize].rwidth();
    421     if (width == userSizeHint)
    422         return;
    423     userSizeHint = width;
    424     updateGeometry();
     474    d_ptr->setSizeComponent(Qt::MinimumSize, d_ptr->Width, width);
    425475}
    426476
     
    432482void QGraphicsLayoutItem::setMinimumHeight(qreal height)
    433483{
    434     Q_D(QGraphicsLayoutItem);
    435     qreal &userSizeHint = d->userSizeHints[Qt::MinimumSize].rheight();
    436     if (height == userSizeHint)
    437         return;
    438     userSizeHint = height;
    439     updateGeometry();
     484    d_ptr->setSizeComponent(Qt::MinimumSize, d_ptr->Height, height);
    440485}
    441486
     
    451496void QGraphicsLayoutItem::setPreferredSize(const QSizeF &size)
    452497{
    453     Q_D(QGraphicsLayoutItem);
    454     if (size == d->userSizeHints[Qt::PreferredSize])
    455         return;
    456 
    457     d->userSizeHints[Qt::PreferredSize] = size;
    458     updateGeometry();
     498    d_ptr->setSize(Qt::PreferredSize, size);
    459499}
    460500
     
    486526void QGraphicsLayoutItem::setPreferredHeight(qreal height)
    487527{
    488     Q_D(QGraphicsLayoutItem);
    489     qreal &userSizeHint = d->userSizeHints[Qt::PreferredSize].rheight();
    490     if (height == userSizeHint)
    491         return;
    492     userSizeHint = height;
    493     updateGeometry();
     528    d_ptr->setSizeComponent(Qt::PreferredSize, d_ptr->Height, height);
    494529}
    495530
     
    501536void QGraphicsLayoutItem::setPreferredWidth(qreal width)
    502537{
    503     Q_D(QGraphicsLayoutItem);
    504     qreal &userSizeHint = d->userSizeHints[Qt::PreferredSize].rwidth();
    505     if (width == userSizeHint)
    506         return;
    507     userSizeHint = width;
    508     updateGeometry();
     538    d_ptr->setSizeComponent(Qt::PreferredSize, d_ptr->Width, width);
    509539}
    510540
     
    520550void QGraphicsLayoutItem::setMaximumSize(const QSizeF &size)
    521551{
    522     Q_D(QGraphicsLayoutItem);
    523     if (size == d->userSizeHints[Qt::MaximumSize])
    524         return;
    525 
    526     d->userSizeHints[Qt::MaximumSize] = size;
    527     updateGeometry();
     552    d_ptr->setSize(Qt::MaximumSize, size);
    528553}
    529554
     
    555580void QGraphicsLayoutItem::setMaximumWidth(qreal width)
    556581{
    557     Q_D(QGraphicsLayoutItem);
    558     qreal &userSizeHint = d->userSizeHints[Qt::MaximumSize].rwidth();
    559     if (width == userSizeHint)
    560         return;
    561     userSizeHint = width;
    562     updateGeometry();
     582    d_ptr->setSizeComponent(Qt::MaximumSize, d_ptr->Width, width);
    563583}
    564584
     
    570590void QGraphicsLayoutItem::setMaximumHeight(qreal height)
    571591{
    572     Q_D(QGraphicsLayoutItem);
    573     qreal &userSizeHint = d->userSizeHints[Qt::MaximumSize].rheight();
    574     if (height == userSizeHint)
    575         return;
    576     userSizeHint = height;
    577     updateGeometry();
     592    d_ptr->setSizeComponent(Qt::MaximumSize, d_ptr->Height, height);
    578593}
    579594
     
    733748QSizeF QGraphicsLayoutItem::effectiveSizeHint(Qt::SizeHint which, const QSizeF &constraint) const
    734749{
     750    Q_D(const QGraphicsLayoutItem);
     751
     752    if (!d->userSizeHints && constraint.isValid())
     753        return constraint;
     754
    735755    // ### should respect size policy???
    736756    return d_ptr->effectiveSizeHints(constraint)[which];
     
    787807
    788808/*!
     809    \since 4.6
     810
    789811    Returns whether a layout should delete this item in its destructor.
    790812    If its true, then the layout will delete it. If its false, then it is
     
    813835}
    814836/*!
     837    \since 4.6
     838
    815839    Sets whether a layout should delete this item in its destructor or not.
    816840    \a ownership must be true to in order for the layout to delete it.
  • trunk/src/gui/graphicsview/qgraphicslayoutitem.h

    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**
     
    4343#define QGRAPHICSLAYOUTITEM_H
    4444
     45#include <QtCore/qscopedpointer.h>
    4546#include <QtGui/qsizepolicy.h>
    4647#include <QtGui/qevent.h>
     
    113114
    114115    virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const = 0;
    115     QGraphicsLayoutItemPrivate *d_ptr;
     116    QScopedPointer<QGraphicsLayoutItemPrivate> d_ptr;
    116117
    117118private:
     
    121122    friend class QGraphicsLayout;
    122123};
     124
     125Q_DECLARE_INTERFACE(QGraphicsLayoutItem, "com.trolltech.Qt.QGraphicsLayoutItem")
    123126
    124127inline void QGraphicsLayoutItem::setMinimumSize(qreal aw, qreal ah)
  • trunk/src/gui/graphicsview/qgraphicslayoutitem_p.h

    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**
     
    4848//
    4949// This file is not part of the Qt API.  It exists for the convenience
    50 // of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp.  This header
    51 // file may change from version to version without notice, or even be removed.
     50// of other Qt classes.  This header file may change from version to
     51// version without notice, or even be removed.
    5252//
    5353// We mean it.
     
    6464    Q_DECLARE_PUBLIC(QGraphicsLayoutItem)
    6565public:
    66     virtual ~QGraphicsLayoutItemPrivate() {}
     66    virtual ~QGraphicsLayoutItemPrivate();
    6767    QGraphicsLayoutItemPrivate(QGraphicsLayoutItem *parent, bool isLayout);
    6868    void init();
    6969    QSizeF *effectiveSizeHints(const QSizeF &constraint) const;
    7070    QGraphicsItem *parentItem() const;
     71    void ensureUserSizeHints();
     72    void setSize(Qt::SizeHint which, const QSizeF &size);
     73    enum SizeComponent { Width, Height };
     74    void setSizeComponent(Qt::SizeHint which, SizeComponent component, qreal value);
    7175
    7276    QSizePolicy sizePolicy;
    7377    QGraphicsLayoutItem *parent;
    7478
    75     QSizeF userSizeHints[Qt::NSizeHints];
     79    QSizeF *userSizeHints;
    7680    mutable QSizeF cachedSizeHints[Qt::NSizeHints];
    7781    mutable QSizeF cachedConstraint;
  • trunk/src/gui/graphicsview/qgraphicslinearlayout.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    layout for managing widgets in Graphics View.
    4646    \since 4.4
    47     \ingroup multimedia
    4847    \ingroup graphicsview-api
    4948
     
    6160    You can add widgets, layouts, stretches (addStretch(), insertStretch() or
    6261    setStretchFactor()), and spacings (setItemSpacing()) to a linear
    63     layout. The layout takes ownership of the items. In some cases when the layout 
     62    layout. The layout takes ownership of the items. In some cases when the layout
    6463    item also inherits from QGraphicsItem (such as QGraphicsWidget) there will be a
    6564    ambiguity in ownership because the layout item belongs to two ownership hierarchies.
     
    179178        wid = new QWidget;
    180179    QGraphicsItem *item = parentItem();
    181     QStyle *style = (item && item->isWidget()) ? static_cast<QGraphicsWidget*>(item)->style() : qApp->style();
     180    QStyle *style = (item && item->isWidget()) ? static_cast<QGraphicsWidget*>(item)->style() : QApplication::style();
    182181    return QLayoutStyleInfo(style, wid);
    183182}
     
    210209        QGraphicsLayoutItem *item = itemAt(i);
    211210        // The following lines can be removed, but this removes the item
    212         // from the layout more efficiently than the implementation of 
     211        // from the layout more efficiently than the implementation of
    213212        // ~QGraphicsLayoutItem.
    214213        removeAt(i);
     
    274273        return;
    275274    }
     275    if (item == this) {
     276        qWarning("QGraphicsLinearLayout::insertItem: cannot insert itself");
     277        return;
     278    }
    276279    d->addChildLayoutItem(item);
    277280
     
    279282    d->fixIndex(&index);
    280283    d->engine.insertRow(index, d->orientation);
    281     new QGridLayoutItem(&d->engine, item, d->gridRow(index), d->gridColumn(index));
     284    new QGridLayoutItem(&d->engine, item, d->gridRow(index), d->gridColumn(index), 1, 1, 0, index);
    282285    invalidate();
    283286}
     
    324327{
    325328    Q_D(QGraphicsLinearLayout);
    326     if (QGridLayoutItem *gridItem = d->engine.itemAt(d->gridRow(index), d->gridColumn(index))) {
     329    if (index < 0 || index >= d->engine.itemCount()) {
     330        qWarning("QGraphicsLinearLayout::removeAt: invalid index %d", index);
     331        return;
     332    }
     333    if (QGridLayoutItem *gridItem = d->engine.itemAt(index)) {
    327334        if (QGraphicsLayoutItem *layoutItem = gridItem->layoutItem())
    328335            layoutItem->setParentLayoutItem(0);
     
    464471{
    465472    Q_D(const QGraphicsLinearLayout);
    466     return d->engine.rowCount(d->orientation);
     473    return d->engine.itemCount();
    467474}
    468475
    469476/*!
    470477    \reimp
     478    When iterating from 0 and up, it will return the items in the visual arranged order.
    471479*/
    472480QGraphicsLayoutItem *QGraphicsLinearLayout::itemAt(int index) const
    473481{
    474482    Q_D(const QGraphicsLinearLayout);
     483    if (index < 0 || index >= d->engine.itemCount()) {
     484        qWarning("QGraphicsLinearLayout::itemAt: invalid index %d", index);
     485        return 0;
     486    }
    475487    QGraphicsLayoutItem *item = 0;
    476     if (QGridLayoutItem *gridItem = d->engine.itemAt(d->gridRow(index), d->gridColumn(index)))
     488    if (QGridLayoutItem *gridItem = d->engine.itemAt(index))
    477489        item = gridItem->layoutItem();
    478490    return item;
     
    531543}
    532544
     545/*!
     546    \internal
     547*/
     548void QGraphicsLinearLayout::dump(int indent) const
     549{
    533550#ifdef QT_DEBUG
    534 void QGraphicsLinearLayout::dump(int indent) const
    535 {
    536551    if (qt_graphicsLayoutDebug()) {
    537552        Q_D(const QGraphicsLinearLayout);
     
    540555        d->engine.dump(indent + 1);
    541556    }
    542 }
    543557#endif
     558}
    544559
    545560QT_END_NAMESPACE
    546        
     561
    547562#endif //QT_NO_GRAPHICSVIEW
  • trunk/src/gui/graphicsview/qgraphicslinearlayout.h

    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**
     
    9898#endif
    9999
    100 #ifdef QT_DEBUG
    101100    void dump(int indent = 0) const;
    102 #endif
    103101
    104102protected:
  • trunk/src/gui/graphicsview/qgraphicsproxywidget.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**
     
    5858#include <QtGui/qstyleoption.h>
    5959#include <QtGui/qgraphicsview.h>
     60#include <QtGui/qlistview.h>
     61#include <QtGui/qlineedit.h>
     62#include <QtGui/qtextedit.h>
    6063
    6164QT_BEGIN_NAMESPACE
     
    6871    a QWidget in a QGraphicsScene.
    6972    \since 4.4
    70     \ingroup multimedia
    7173    \ingroup graphicsview-api
    7274
     
    8890    means that when an embedded QComboBox shows its popup list, a new
    8991    QGraphicsProxyWidget is created automatically, embedding the popup, and
    90     positioning it correctly.
     92    positioning it correctly. This only works if the popup is child of the
     93    embedded widget (for example QToolButton::setMenu() requires the QMenu instance
     94    to be child of the QToolButton).
    9195
    9296    \section1 Embedding a Widget with QGraphicsProxyWidget
     
    178182    in behavior from when it is not embedded.
    179183
     184    \warning This class is provided for convenience when bridging
     185    QWidgets and QGraphicsItems, it should not be used for
     186    high-performance scenarios.
     187
    180188    \sa QGraphicsScene::addWidget(), QGraphicsWidget
    181189*/
    182190
    183191extern bool qt_sendSpontaneousEvent(QObject *, QEvent *);
     192extern bool qt_tab_all_widgets;
    184193
    185194/*!
     
    272281    QWidget *embeddedMouseGrabberPtr = (QWidget *)embeddedMouseGrabber;
    273282    QApplicationPrivate::sendMouseEvent(receiver, mouseEvent, alienWidget, widget,
    274                                         &embeddedMouseGrabberPtr, lastWidgetUnderMouse);
     283                                        &embeddedMouseGrabberPtr, lastWidgetUnderMouse, event->spontaneous());
    275284    embeddedMouseGrabber = embeddedMouseGrabberPtr;
    276285
     
    367376/*!
    368377    \internal
     378    Some of the logic is shared with QApplicationPrivate::focusNextPrevChild_helper
    369379*/
    370380QWidget *QGraphicsProxyWidgetPrivate::findFocusChild(QWidget *child, bool next) const
     
    380390        if ((next && child == widget) || (!next && child == widget->d_func()->focus_prev)) {
    381391             return 0;
    382         }
     392        }
    383393    }
    384394
    385395    QWidget *oldChild = child;
     396    uint focus_flag = qt_tab_all_widgets ? Qt::TabFocus : Qt::StrongFocus;
    386397    do {
    387398        if (child->isEnabled()
    388399            && child->isVisibleTo(widget)
    389             && (child->focusPolicy() & Qt::TabFocus)) {
    390             return child;
     400            && ((child->focusPolicy() & focus_flag) == focus_flag)
     401            && !(child->d_func()->extra && child->d_func()->extra->focus_proxy)) {
     402            return child;
    391403        }
    392404        child = next ? child->d_func()->focus_next : child->d_func()->focus_prev;
     
    448460/*!
    449461    \internal
     462*/
     463void QGraphicsProxyWidgetPrivate::updateProxyInputMethodAcceptanceFromWidget()
     464{
     465    Q_Q(QGraphicsProxyWidget);
     466    if (!widget)
     467        return;
     468
     469    QWidget *focusWidget = widget->focusWidget();
     470    if (!focusWidget)
     471        focusWidget = widget;
     472    q->setFlag(QGraphicsItem::ItemAcceptsInputMethod,
     473               focusWidget->testAttribute(Qt::WA_InputMethodEnabled));
     474}
     475
     476/*!
     477    \internal
    450478
    451479    Embeds \a subWin as a subwindow of this proxy widget. \a subWin must be a top-level
     
    457485    QWExtra *extra;
    458486    if (!((extra = subWin->d_func()->extra) && extra->proxyWidget)) {
    459         QGraphicsProxyWidget *subProxy = new QGraphicsProxyWidget(q_func());
     487        QGraphicsProxyWidget *subProxy = new QGraphicsProxyWidget(q_func(), subWin->windowFlags());
    460488        subProxy->d_func()->setWidget_helper(subWin, false);
    461489    }
     
    540568    hidden or disabled after embedding is complete. The class documentation
    541569    has a full overview over the shared state.
     570
     571    QGraphicsProxyWidget's window flags determine whether the widget, after
     572    embedding, will be given window decorations or not.
    542573
    543574    After this function returns, QGraphicsProxyWidget will keep its state
     
    658689        q->setCursor(widget->cursor());
    659690#endif
    660     Qt::WFlags flags = newWidget->windowFlags();
    661     if (newWidget->windowType() == Qt::Window)
    662         flags &= ~Qt::Window;
    663     q->setWindowFlags(flags);
    664691    q->setEnabled(newWidget->isEnabled());
    665692    q->setVisible(newWidget->isVisible());
     
    687714
    688715    updateProxyGeometryFromWidget();
     716
     717    updateProxyInputMethodAcceptanceFromWidget();
    689718
    690719    // Hook up the event filter to keep the state up to date.
     
    837866        // of inputMethodEvent().
    838867        QWidget *focusWidget = d->widget->focusWidget();
    839         if (focusWidget->testAttribute(Qt::WA_InputMethodEnabled))
     868        if (focusWidget && focusWidget->testAttribute(Qt::WA_InputMethodEnabled))
    840869            QApplication::sendEvent(focusWidget, event);
    841870        break;
     
    954983{
    955984    Q_D(QGraphicsProxyWidget);
    956     if (!event || !d->widget || !d->widget->isVisible())
     985    if (!event || !d->widget || !d->widget->isVisible() || !hasFocus())
    957986        return;
    958987
     
    9741003#endif // QT_NO_CONTEXTMENU
    9751004
     1005#ifndef QT_NO_DRAGANDDROP
    9761006/*!
    9771007    \reimp
     
    10341064            // Try to enter before we leave
    10351065            QDragEnterEvent dragEnter(receiverPos, event->possibleActions(), event->mimeData(), event->buttons(), event->modifiers());
    1036             dragEnter.setDropAction(event->proposedAction());           
     1066            dragEnter.setDropAction(event->proposedAction());
    10371067            QApplication::sendEvent(receiver, &dragEnter);
    10381068            event->setAccepted(dragEnter.isAccepted());
     
    10941124#endif
    10951125}
     1126#endif
    10961127
    10971128/*!
     
    12991330            d->widget->focusWidget()->setFocus(event->reason());
    13001331            return;
    1301         }
    1302         break;
     1332        }
     1333        break;
    13031334    }
    13041335}
     
    14321463  Creates a proxy widget for the given \a child of the widget
    14331464  contained in this proxy.
    1434  
     1465
    14351466  This function makes it possible to aquire proxies for
    14361467  non top-level widgets. For instance, you can embed a dialog,
  • trunk/src/gui/graphicsview/qgraphicsproxywidget.h

    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**
     
    9191#endif
    9292
     93#ifndef QT_NO_DRAGANDDROP
    9394    void dragEnterEvent(QGraphicsSceneDragDropEvent *event);
    9495    void dragLeaveEvent(QGraphicsSceneDragDropEvent *event);
    9596    void dragMoveEvent(QGraphicsSceneDragDropEvent *event);
    9697    void dropEvent(QGraphicsSceneDragDropEvent *event);
     98#endif
    9799
    98100    void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
     
    128130private:
    129131    Q_DISABLE_COPY(QGraphicsProxyWidget)
    130     Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr, QGraphicsProxyWidget)
     132    Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QGraphicsProxyWidget)
    131133    Q_PRIVATE_SLOT(d_func(), void _q_removeWidgetSlot())
    132134
  • trunk/src/gui/graphicsview/qgraphicsproxywidget_p.h

    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**
     
    4848//
    4949// This file is not part of the Qt API.  It exists for the convenience
    50 // of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp.  This header
    51 // file may change from version to version without notice, or even be removed.
     50// of other Qt classes.  This header file may change from version to
     51// version without notice, or even be removed.
    5252//
    5353// We mean it.
     
    103103    void updateProxyGeometryFromWidget();
    104104
     105    void updateProxyInputMethodAcceptanceFromWidget();
     106
    105107    QPointF mapToReceiver(const QPointF &pos, const QWidget *receiver) const;
    106108
  • trunk/src/gui/graphicsview/qgraphicsscene.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**
    4040****************************************************************************/
    41 
    42 static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000;
    4341
    4442/*!
     
    4745    number of 2D graphical items.
    4846    \since 4.2
    49     \ingroup multimedia
    5047    \ingroup graphicsview-api
    51     \mainclass
     48
    5249
    5350    The class serves as a container for QGraphicsItems. It is used together
     
    220217#include "qgraphicswidget.h"
    221218#include "qgraphicswidget_p.h"
     219#include "qgraphicssceneindex_p.h"
     220#include "qgraphicsscenebsptreeindex_p.h"
     221#include "qgraphicsscenelinearindex_p.h"
    222222
    223223#include <QtCore/qdebug.h>
     
    243243#include <QtGui/qtooltip.h>
    244244#include <QtGui/qtransform.h>
     245#include <QtGui/qinputcontext.h>
     246#include <QtGui/qgraphicseffect.h>
    245247#include <private/qapplication_p.h>
    246248#include <private/qobject_p.h>
     
    248250#include <private/qt_x11_p.h>
    249251#endif
     252#include <private/qgraphicseffect_p.h>
     253#include <private/qgesturemanager_p.h>
     254
     255// #define GESTURE_DEBUG
     256#ifndef GESTURE_DEBUG
     257# define DEBUG if (0) qDebug
     258#else
     259# define DEBUG qDebug
     260#endif
    250261
    251262QT_BEGIN_NAMESPACE
    252263
    253 static inline bool QRectF_intersects(const QRectF &s, const QRectF &r)
    254 {
    255     qreal xp = s.left();
    256     qreal yp = s.top();
    257     qreal w = s.width();
    258     qreal h = s.height();
    259     qreal l1 = xp;
    260     qreal r1 = xp;
    261     if (w < 0)
    262         l1 += w;
    263     else
    264         r1 += w;
    265 
    266     qreal l2 = r.left();
    267     qreal r2 = r.left();
    268     if (w < 0)
    269         l2 += r.width();
    270     else
    271         r2 += r.width();
    272 
    273     if (l1 >= r2 || l2 >= r1)
    274         return false;
    275 
    276     qreal t1 = yp;
    277     qreal b1 = yp;
    278     if (h < 0)
    279         t1 += h;
    280     else
    281         b1 += h;
    282 
    283     qreal t2 = r.top();
    284     qreal b2 = r.top();
    285     if (r.height() < 0)
    286         t2 += r.height();
    287     else
    288         b2 += r.height();
    289 
    290     return !(t1 >= b2 || t2 >= b1);
    291 }
    292 
    293 // QRectF::intersects() returns false always if either the source or target
    294 // rectangle's width or height are 0. This works around that problem.
    295 static inline void _q_adjustRect(QRectF *rect)
    296 {
    297     Q_ASSERT(rect);
    298     if (!rect->width())
    299         rect->adjust(-0.00001, 0, 0.00001, 0);
    300     if (!rect->height())
    301         rect->adjust(0, -0.00001, 0, 0.00001);
    302 }
    303 
    304 static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item)
    305 {
    306     Q_ASSERT(item);
    307     QRectF boundingRect(item->boundingRect());
    308     _q_adjustRect(&boundingRect);
    309     return boundingRect;
    310 }
     264bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event);
    311265
    312266static void _q_hoverFromMouseEvent(QGraphicsSceneHoverEvent *hover, const QGraphicsSceneMouseEvent *mouseEvent)
     
    323277}
    324278
     279int QGraphicsScenePrivate::changedSignalIndex;
     280
    325281/*!
    326282    \internal
    327283*/
    328284QGraphicsScenePrivate::QGraphicsScenePrivate()
    329     : changedSignalMask(0),
    330       indexMethod(QGraphicsScene::BspTreeIndex),
    331       bspTreeDepth(0),
     285    : indexMethod(QGraphicsScene::BspTreeIndex),
     286      index(0),
    332287      lastItemCount(0),
    333288      hasSceneRect(false),
     289      dirtyGrowingItemsBoundingRect(true),
    334290      updateAll(false),
    335291      calledEmitUpdated(false),
     292      processDirtyItemsEmitted(false),
    336293      selectionChanging(0),
    337       dirtyItemResetPending(false),
    338       regenerateIndex(true),
    339       purgePending(false),
    340       indexTimerId(0),
    341       restartIndexTimer(false),
     294      needSortTopLevelItems(true),
     295      unpolishedItemsModified(true),
     296      holesInTopLevelSiblingIndex(false),
     297      topLevelSequentialOrdering(true),
     298      scenePosDescendantsUpdatePending(false),
    342299      stickyFocus(false),
    343300      hasFocus(false),
     
    345302      lastFocusItem(0),
    346303      tabFocusFirst(0),
    347       activeWindow(0),
     304      activePanel(0),
     305      lastActivePanel(0),
    348306      activationRefCount(0),
     307      childExplicitActivation(0),
    349308      lastMouseGrabberItem(0),
    350309      lastMouseGrabberItemHasImplicitMouseGrab(false),
     
    352311      enterWidget(0),
    353312      lastDropAction(Qt::IgnoreAction),
     313      allItemsIgnoreHoverEvents(true),
     314      allItemsUseDefaultCursor(true),
    354315      painterStateProtection(true),
    355316      sortCacheEnabled(false),
    356       updatingSortCache(false),
    357       style(0)
     317      style(0),
     318      allItemsIgnoreTouchEvents(true)
    358319{
    359320}
     
    366327    Q_Q(QGraphicsScene);
    367328
     329    index = new QGraphicsSceneBspTreeIndex(q);
     330
    368331    // Keep this index so we can check for connected slots later on.
    369     changedSignalMask = (1 << q->metaObject()->indexOfSignal("changed(QList<QRectF>)"));
     332    if (!changedSignalIndex) {
     333        changedSignalIndex = signalIndex("changed(QList<QRectF>)");
     334    }
    370335    qApp->d_func()->scene_list.append(q);
    371336    q->update();
     
    375340    \internal
    376341*/
    377 QList<QGraphicsItem *> QGraphicsScenePrivate::estimateItemsInRect(const QRectF &rect) const
    378 {
    379     const_cast<QGraphicsScenePrivate *>(this)->purgeRemovedItems();
    380     const_cast<QGraphicsScenePrivate *>(this)->_q_updateSortCache();
    381 
    382     if (indexMethod == QGraphicsScene::BspTreeIndex) {
    383         // ### Only do this once in a while.
    384         QGraphicsScenePrivate *that = const_cast<QGraphicsScenePrivate *>(this);
    385 
    386         // Get items from BSP tree
    387         QList<QGraphicsItem *> items = that->bspTree.items(rect);
    388 
    389         // Fill in with any unindexed items
    390         for (int i = 0; i < unindexedItems.size(); ++i) {
    391             if (QGraphicsItem *item = unindexedItems.at(i)) {
    392                 if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) {
    393                     QRectF boundingRect = item->sceneBoundingRect();
    394                     if (QRectF_intersects(boundingRect, rect)) {
    395                         item->d_ptr->itemDiscovered = 1;
    396                         items << item;
    397                     }
    398                 }
    399             }
    400         }
    401 
    402         // Reset the discovered state of all discovered items
    403         for (int i = 0; i < items.size(); ++i)
    404             items.at(i)->d_func()->itemDiscovered = 0;
    405         return items;
    406     }
    407 
    408     QList<QGraphicsItem *> itemsInRect;
    409     for (int i = 0; i < unindexedItems.size(); ++i) {
    410         if (QGraphicsItem *item = unindexedItems.at(i)) {
    411             if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
    412                 continue;
    413             if (item->d_ptr->visible && item->effectiveOpacity() > qreal(0.0))
    414                 itemsInRect << item;
    415         }
    416     }
    417     for (int i = 0; i < indexedItems.size(); ++i) {
    418         if (QGraphicsItem *item = indexedItems.at(i)) {
    419             if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
    420                 continue;
    421             if (item->d_ptr->visible && item->effectiveOpacity() > qreal(0.0))
    422                 itemsInRect << item;
    423         }
    424     }
    425 
    426     return itemsInRect;
    427 }
    428 
    429 /*!
    430     \internal
    431 */
    432 void QGraphicsScenePrivate::addToIndex(QGraphicsItem *item)
    433 {
    434     if (indexMethod == QGraphicsScene::BspTreeIndex) {
    435         if (item->d_func()->index != -1) {
    436             bspTree.insertItem(item, item->sceneBoundingRect());
    437             foreach (QGraphicsItem *child, item->children())
    438                 child->addToIndex();
    439         } else {
    440             // The BSP tree is regenerated if the number of items grows to a
    441             // certain threshold, or if the bounding rect of the graph doubles in
    442             // size.
    443             startIndexTimer();
    444         }
    445     }
    446 }
    447 
    448 /*!
    449     \internal
    450 */
    451 void QGraphicsScenePrivate::removeFromIndex(QGraphicsItem *item)
    452 {
    453     if (indexMethod == QGraphicsScene::BspTreeIndex) {
    454         int index = item->d_func()->index;
    455         if (index != -1) {
    456             bspTree.removeItem(item, item->sceneBoundingRect());
    457             freeItemIndexes << index;
    458             indexedItems[index] = 0;
    459             item->d_func()->index = -1;
    460             unindexedItems << item;
    461 
    462             foreach (QGraphicsItem *child, item->children())
    463                 child->removeFromIndex();
    464         }
    465 
    466         startIndexTimer();
    467     }
    468 }
    469 
    470 /*!
    471     \internal
    472 */
    473 void QGraphicsScenePrivate::resetIndex()
    474 {
    475     purgeRemovedItems();
    476     if (indexMethod == QGraphicsScene::BspTreeIndex) {
    477         for (int i = 0; i < indexedItems.size(); ++i) {
    478             if (QGraphicsItem *item = indexedItems.at(i)) {
    479                 item->d_ptr->index = -1;
    480                 unindexedItems << item;
    481             }
    482         }
    483         indexedItems.clear();
    484         freeItemIndexes.clear();
    485         regenerateIndex = true;
    486         startIndexTimer();
    487     }
    488 }
    489 
    490 static inline int intmaxlog(int n)
    491 {
    492     return  (n > 0 ? qMax(qCeil(qLn(qreal(n)) / qLn(qreal(2))), 5) : 0);
    493 }
    494 
    495 /*!
    496     \internal
    497 */
    498 void QGraphicsScenePrivate::_q_updateIndex()
    499 {
    500     if (!indexTimerId)
    501         return;
    502 
    503     Q_Q(QGraphicsScene);
    504     q->killTimer(indexTimerId);
    505     indexTimerId = 0;
    506 
    507     purgeRemovedItems();
    508 
    509     // Add unindexedItems to indexedItems
    510     QRectF unindexedItemsBoundingRect;
    511     for (int i = 0; i < unindexedItems.size(); ++i) {
    512         if (QGraphicsItem *item = unindexedItems.at(i)) {
    513             unindexedItemsBoundingRect |= item->sceneBoundingRect();
    514             if (!freeItemIndexes.isEmpty()) {
    515                 int freeIndex = freeItemIndexes.takeFirst();
    516                 item->d_func()->index = freeIndex;
    517                 indexedItems[freeIndex] = item;
    518             } else {
    519                 item->d_func()->index = indexedItems.size();
    520                 indexedItems << item;
    521             }
    522         }
    523     }
    524 
    525     // Update growing scene rect.
    526     QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect;
    527     growingItemsBoundingRect |= unindexedItemsBoundingRect;
    528 
    529     // Determine whether we should regenerate the BSP tree.
    530     if (indexMethod == QGraphicsScene::BspTreeIndex) {
    531         int depth = bspTreeDepth;
    532         if (depth == 0) {
    533             int oldDepth = intmaxlog(lastItemCount);
    534             depth = intmaxlog(indexedItems.size());
    535             static const int slack = 100;
    536             if (bspTree.leafCount() == 0 || (oldDepth != depth && qAbs(lastItemCount - indexedItems.size()) > slack)) {
    537                 // ### Crude algorithm.
    538                 regenerateIndex = true;
    539             }
    540         }
    541 
    542         // Regenerate the tree.
    543         if (regenerateIndex) {
    544             regenerateIndex = false;
    545             bspTree.initialize(q->sceneRect(), depth);
    546             unindexedItems = indexedItems;
    547             lastItemCount = indexedItems.size();
    548             q->update();
    549 
    550             // Take this opportunity to reset our largest-item counter for
    551             // untransformable items. When the items are inserted into the BSP
    552             // tree, we'll get an accurate calculation.
    553             largestUntransformableItem = QRectF();
    554         }
    555     }
    556 
    557     // Insert all unindexed items into the tree.
    558     for (int i = 0; i < unindexedItems.size(); ++i) {
    559         if (QGraphicsItem *item = unindexedItems.at(i)) {
    560             QRectF rect = item->sceneBoundingRect();
    561             if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
    562                 continue;
    563             if (indexMethod == QGraphicsScene::BspTreeIndex)
    564                 bspTree.insertItem(item, rect);
    565 
    566             // If the item ignores view transformations, update our
    567             // largest-item-counter to ensure that the view can accurately
    568             // discover untransformable items when drawing.
    569             if (item->d_ptr->itemIsUntransformable()) {
    570                 QGraphicsItem *topmostUntransformable = item;
    571                 while (topmostUntransformable && (topmostUntransformable->d_ptr->ancestorFlags
    572                                                   & QGraphicsItemPrivate::AncestorIgnoresTransformations)) {
    573                     topmostUntransformable = topmostUntransformable->parentItem();
    574                 }
    575                 // ### Verify that this is the correct largest untransformable rectangle.
    576                 largestUntransformableItem |= item->mapToItem(topmostUntransformable, item->boundingRect()).boundingRect();
    577             }
    578         }
    579     }
    580     unindexedItems.clear();
    581 
    582     // Notify scene rect changes.
    583     if (!hasSceneRect && growingItemsBoundingRect != oldGrowingItemsBoundingRect)
    584         emit q->sceneRectChanged(growingItemsBoundingRect);
    585 }
    586 
    587 /*!
    588     \internal
    589 */
     342QGraphicsScenePrivate *QGraphicsScenePrivate::get(QGraphicsScene *q)
     343{
     344    return q->d_func();
     345}
     346
    590347void QGraphicsScenePrivate::_q_emitUpdated()
    591348{
    592349    Q_Q(QGraphicsScene);
    593350    calledEmitUpdated = false;
     351
     352    if (dirtyGrowingItemsBoundingRect) {
     353        if (!hasSceneRect) {
     354            const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect;
     355            growingItemsBoundingRect |= q->itemsBoundingRect();
     356            if (oldGrowingItemsBoundingRect != growingItemsBoundingRect)
     357                emit q->sceneRectChanged(growingItemsBoundingRect);
     358        }
     359        dirtyGrowingItemsBoundingRect = false;
     360    }
    594361
    595362    // Ensure all views are connected if anything is connected. This disables
     
    597364    // needs to happen in order to keep compatibility with the behavior from
    598365    // Qt 4.4 and backward.
    599     if (!views.isEmpty() && (connectedSignals & changedSignalMask)) {
     366    if (isSignalConnected(changedSignalIndex)) {
    600367        for (int i = 0; i < views.size(); ++i) {
    601368            QGraphicsView *view = views.at(i);
     
    606373            }
    607374        }
    608     }
    609 
    610     // Ensure all dirty items's current positions are recorded in the list of
    611     // updated rects.
    612     for (int i = 0; i < dirtyItems.size(); ++i)
    613         updatedRects += dirtyItems.at(i)->sceneBoundingRect();
     375    } else {
     376        updateAll = false;
     377        for (int i = 0; i < views.size(); ++i)
     378            views.at(i)->d_func()->processPendingUpdates();
     379        // It's important that we update all views before we dispatch, hence two for-loops.
     380        for (int i = 0; i < views.size(); ++i)
     381            views.at(i)->d_func()->dispatchPendingUpdateRequests();
     382        return;
     383    }
    614384
    615385    // Notify the changes to anybody interested.
     
    624394    \internal
    625395
    626     Updates all items in the pending update list. At this point, the list is
    627     unlikely to contain partially constructed items.
    628 */
    629 void QGraphicsScenePrivate::_q_updateLater()
    630 {
    631     foreach (QGraphicsItem *item, pendingUpdateItems)
    632         item->update();
    633     pendingUpdateItems.clear();
     396    ### This function is almost identical to QGraphicsItemPrivate::addChild().
     397*/
     398void QGraphicsScenePrivate::registerTopLevelItem(QGraphicsItem *item)
     399{
     400    item->d_ptr->ensureSequentialSiblingIndex();
     401    needSortTopLevelItems = true; // ### maybe false
     402    item->d_ptr->siblingIndex = topLevelItems.size();
     403    topLevelItems.append(item);
    634404}
    635405
    636406/*!
    637407    \internal
     408
     409    ### This function is almost identical to QGraphicsItemPrivate::removeChild().
     410*/
     411void QGraphicsScenePrivate::unregisterTopLevelItem(QGraphicsItem *item)
     412{
     413    if (!holesInTopLevelSiblingIndex)
     414        holesInTopLevelSiblingIndex = item->d_ptr->siblingIndex != topLevelItems.size() - 1;
     415    if (topLevelSequentialOrdering && !holesInTopLevelSiblingIndex)
     416        topLevelItems.removeAt(item->d_ptr->siblingIndex);
     417    else
     418        topLevelItems.removeOne(item);
     419    // NB! Do not use topLevelItems.removeAt(item->d_ptr->siblingIndex) because
     420    // the item is not guaranteed to be at the index after the list is sorted
     421    // (see ensureSortedTopLevelItems()).
     422    item->d_ptr->siblingIndex = -1;
     423    if (topLevelSequentialOrdering)
     424        topLevelSequentialOrdering = !holesInTopLevelSiblingIndex;
     425}
     426
     427/*!
     428    \internal
    638429*/
    639430void QGraphicsScenePrivate::_q_polishItems()
    640431{
     432    QSet<QGraphicsItem *>::Iterator it = unpolishedItems.begin();
    641433    const QVariant booleanTrueVariant(true);
    642     foreach (QGraphicsItem *item, unpolishedItems) {
     434    while (!unpolishedItems.isEmpty()) {
     435        QGraphicsItem *item = *it;
     436        it = unpolishedItems.erase(it);
     437        unpolishedItemsModified = false;
    643438        if (!item->d_ptr->explicitlyHidden) {
    644439            item->itemChange(QGraphicsItem::ItemVisibleChange, booleanTrueVariant);
     
    649444            QApplication::sendEvent((QGraphicsWidget *)item, &event);
    650445        }
    651     }
    652     unpolishedItems.clear();
     446        if (unpolishedItemsModified)
     447            it = unpolishedItems.begin();
     448    }
     449}
     450
     451void QGraphicsScenePrivate::_q_processDirtyItems()
     452{
     453    processDirtyItemsEmitted = false;
     454
     455    if (updateAll) {
     456        Q_ASSERT(calledEmitUpdated);
     457        // No need for further processing (except resetting the dirty states).
     458        // The growingItemsBoundingRect is updated in _q_emitUpdated.
     459        for (int i = 0; i < topLevelItems.size(); ++i)
     460            resetDirtyItem(topLevelItems.at(i), /*recursive=*/true);
     461        return;
     462    }
     463
     464    const bool wasPendingSceneUpdate = calledEmitUpdated;
     465    const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect;
     466
     467    // Process items recursively.
     468    for (int i = 0; i < topLevelItems.size(); ++i)
     469        processDirtyItemsRecursive(topLevelItems.at(i));
     470
     471    dirtyGrowingItemsBoundingRect = false;
     472    if (!hasSceneRect && oldGrowingItemsBoundingRect != growingItemsBoundingRect)
     473        emit q_func()->sceneRectChanged(growingItemsBoundingRect);
     474
     475    if (wasPendingSceneUpdate)
     476        return;
     477
     478    for (int i = 0; i < views.size(); ++i)
     479        views.at(i)->d_func()->processPendingUpdates();
     480
     481    if (calledEmitUpdated) {
     482        // We did a compatibility QGraphicsScene::update in processDirtyItemsRecursive
     483        // and we cannot wait for the control to reach the eventloop before the
     484        // changed signal is emitted, so we emit it now.
     485        _q_emitUpdated();
     486    }
     487
     488    // Immediately dispatch all pending update requests on the views.
     489    for (int i = 0; i < views.size(); ++i)
     490        views.at(i)->d_func()->dispatchPendingUpdateRequests();
    653491}
    654492
     
    656494    \internal
    657495*/
    658 void QGraphicsScenePrivate::_q_resetDirtyItems()
    659 {
    660     for (int i = 0; i < dirtyItems.size(); ++i) {
    661         QGraphicsItem *item = dirtyItems.at(i);
    662         item->d_ptr->dirty = 0;
    663         item->d_ptr->dirtyChildren = 0;
    664     }
    665     dirtyItems.clear();
    666     dirtyItemResetPending = false;
     496void QGraphicsScenePrivate::setScenePosItemEnabled(QGraphicsItem *item, bool enabled)
     497{
     498    QGraphicsItem *p = item->d_ptr->parent;
     499    while (p) {
     500        p->d_ptr->scenePosDescendants = enabled;
     501        p = p->d_ptr->parent;
     502    }
     503    if (!enabled && !scenePosDescendantsUpdatePending) {
     504        scenePosDescendantsUpdatePending = true;
     505        QMetaObject::invokeMethod(q_func(), "_q_updateScenePosDescendants", Qt::QueuedConnection);
     506    }
    667507}
    668508
     
    670510    \internal
    671511*/
    672 void QGraphicsScenePrivate::resetDirtyItemsLater()
    673 {
    674     Q_Q(QGraphicsScene);
    675     if (dirtyItemResetPending)
    676         return;
    677     // dirtyItems.reserve(indexedItems.size() + unindexedItems.size());
    678     dirtyItemResetPending = true;
    679     QMetaObject::invokeMethod(q, "_q_resetDirtyItems", Qt::QueuedConnection);
     512void QGraphicsScenePrivate::registerScenePosItem(QGraphicsItem *item)
     513{
     514    scenePosItems.insert(item);
     515    setScenePosItemEnabled(item, true);
    680516}
    681517
    682518/*!
    683519    \internal
     520*/
     521void QGraphicsScenePrivate::unregisterScenePosItem(QGraphicsItem *item)
     522{
     523    scenePosItems.remove(item);
     524    setScenePosItemEnabled(item, false);
     525}
     526
     527/*!
     528    \internal
     529*/
     530void QGraphicsScenePrivate::_q_updateScenePosDescendants()
     531{
     532    foreach (QGraphicsItem *item, scenePosItems) {
     533        QGraphicsItem *p = item->d_ptr->parent;
     534        while (p) {
     535            p->d_ptr->scenePosDescendants = 1;
     536            p = p->d_ptr->parent;
     537        }
     538    }
     539    scenePosDescendantsUpdatePending = false;
     540}
     541
     542/*!
     543    \internal
    684544
    685545    Schedules an item for removal. This function leaves some stale indexes
    686     around in the BSP tree; these will be cleaned up the next time someone
    687     triggers purgeRemovedItems().
    688 
    689     Note: This function is called from QGraphicsItem's destructor. \a item is
     546    around in the BSP tree if called from the item's destructor; these will
     547    be cleaned up the next time someone triggers purgeRemovedItems().
     548
     549    Note: This function might get called from QGraphicsItem's destructor. \a item is
    690550    being destroyed, so we cannot call any pure virtual functions on it (such
    691551    as boundingRect()). Also, it is unnecessary to update the item's own state
    692552    in any way.
    693 
    694     ### Refactoring: This function shares much functionality with removeItem()
    695 */
    696 void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item)
     553*/
     554void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item)
    697555{
    698556    Q_Q(QGraphicsScene);
    699557
    700     // Clear focus on the item to remove any reference in the focusWidget
    701     // chain.
     558    // Clear focus on the item to remove any reference in the focusWidget chain.
    702559    item->clearFocus();
    703560
    704     int index = item->d_func()->index;
    705     if (index != -1) {
    706         // Important: The index is useless until purgeRemovedItems() is
    707         // called.
    708         indexedItems[index] = (QGraphicsItem *)0;
    709         if (!purgePending) {
    710             purgePending = true;
    711             q->update();
    712         }
    713         removedItems << item;
     561    markDirty(item, QRectF(), /*invalidateChildren=*/false, /*force=*/false,
     562              /*ignoreOpacity=*/false, /*removingItemFromScene=*/true);
     563
     564    if (item->d_ptr->inDestructor) {
     565        // The item is actually in its destructor, we call the special method in the index.
     566        index->deleteItem(item);
    714567    } else {
    715         // Recently added items are purged immediately. unindexedItems() never
    716         // contains stale items.
    717         unindexedItems.removeAll(item);
    718         q->update();
     568        // Can potentially call item->boundingRect() (virtual function), that's why
     569        // we only can call this function if the item is not in its destructor.
     570        index->removeItem(item);
     571    }
     572
     573    item->d_ptr->clearSubFocus();
     574
     575    if (item->flags() & QGraphicsItem::ItemSendsScenePositionChanges)
     576        unregisterScenePosItem(item);
     577
     578    QGraphicsScene *oldScene = item->d_func()->scene;
     579    item->d_func()->scene = 0;
     580
     581    //We need to remove all children first because they might use their parent
     582    //attributes (e.g. sceneTransform).
     583    if (!item->d_ptr->inDestructor) {
     584        // Remove all children recursively
     585        for (int i = 0; i < item->d_ptr->children.size(); ++i)
     586            q->removeItem(item->d_ptr->children.at(i));
     587    }
     588
     589    if (!item->d_ptr->inDestructor && item == tabFocusFirst) {
     590        QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
     591        widget->d_func()->fixFocusChainBeforeReparenting(0, oldScene, 0);
     592    }
     593
     594    // Unregister focus proxy.
     595    item->d_ptr->resetFocusProxy();
     596
     597    // Remove from parent, or unregister from toplevels.
     598    if (QGraphicsItem *parentItem = item->parentItem()) {
     599        if (parentItem->scene()) {
     600            Q_ASSERT_X(parentItem->scene() == q, "QGraphicsScene::removeItem",
     601                       "Parent item's scene is different from this item's scene");
     602            item->d_ptr->setParentItemHelper(0);
     603        }
     604    } else {
     605        unregisterTopLevelItem(item);
    719606    }
    720607
     
    724611    if (item == lastFocusItem)
    725612        lastFocusItem = 0;
    726     if (item == activeWindow) {
     613    if (item == activePanel) {
    727614        // ### deactivate...
    728         activeWindow = 0;
     615        activePanel = 0;
     616    }
     617    if (item == lastActivePanel)
     618        lastActivePanel = 0;
     619
     620    // Cancel active touches
     621    {
     622        QMap<int, QGraphicsItem *>::iterator it = itemForTouchPointId.begin();
     623        while (it != itemForTouchPointId.end()) {
     624            if (it.value() == item) {
     625                sceneCurrentTouchPoints.remove(it.key());
     626                it = itemForTouchPointId.erase(it);
     627            } else {
     628                ++it;
     629            }
     630        }
    729631    }
    730632
     
    736638    selectedItems.remove(item);
    737639    hoverItems.removeAll(item);
    738     pendingUpdateItems.removeAll(item);
    739640    cachedItemsUnderMouse.removeAll(item);
    740     unpolishedItems.removeAll(item);
    741     dirtyItems.removeAll(item);
     641    unpolishedItems.remove(item);
     642    unpolishedItemsModified = true;
     643    resetDirtyItem(item);
    742644
    743645    //We remove all references of item from the sceneEventFilter arrays
     
    750652    }
    751653
    752     // Remove from scene transform cache
    753     int transformIndex = item->d_func()->sceneTransformIndex;
    754     if (transformIndex != -1) {
    755         validTransforms.setBit(transformIndex, 0);
    756         freeSceneTransformSlots.append(transformIndex);
    757     }
    758 
    759     // Remove all children recursively.
    760     foreach (QGraphicsItem *child, item->children())
    761         _q_removeItemLater(child);
    762 
    763     // Reset the mouse grabber
     654    if (item->isPanel() && item->isVisible() && item->panelModality() != QGraphicsItem::NonModal)
     655        leaveModal(item);
     656
     657    // Reset the mouse grabber and focus item data.
    764658    if (mouseGrabberItems.contains(item))
    765         ungrabMouse(item, /* item is dying */ true);
     659        ungrabMouse(item, /* item is dying */ item->d_ptr->inDestructor);
    766660
    767661    // Reset the keyboard grabber
    768662    if (keyboardGrabberItems.contains(item))
    769         ungrabKeyboard(item, /* item is dying */ true);
     663        ungrabKeyboard(item, /* item is dying */ item->d_ptr->inDestructor);
    770664
    771665    // Reset the last mouse grabber item
     
    781675/*!
    782676    \internal
    783 
    784     Removes stale pointers from all data structures.
    785 */
    786 void QGraphicsScenePrivate::purgeRemovedItems()
     677*/
     678void QGraphicsScenePrivate::setActivePanelHelper(QGraphicsItem *item, bool duringActivationEvent)
    787679{
    788680    Q_Q(QGraphicsScene);
    789 
    790     if (!purgePending && removedItems.isEmpty())
     681    if (item && item->scene() != q) {
     682        qWarning("QGraphicsScene::setActivePanel: item %p must be part of this scene",
     683                 item);
    791684        return;
    792 
    793     // Remove stale items from the BSP tree.
    794     if (indexMethod != QGraphicsScene::NoIndex)
    795         bspTree.removeItems(removedItems);
    796 
    797     // Purge this list.
    798     removedItems.clear();
    799     freeItemIndexes.clear();
    800     for (int i = 0; i < indexedItems.size(); ++i) {
    801         if (!indexedItems.at(i))
    802             freeItemIndexes << i;
    803     }
    804     purgePending = false;
    805 
    806     // No locality info for the items; update the whole scene.
    807     q->update();
     685    }
     686
     687    // Ensure the scene has focus when we change panel activation.
     688    q->setFocus(Qt::ActiveWindowFocusReason);
     689
     690    // Find the item's panel.
     691    QGraphicsItem *panel = item ? item->panel() : 0;
     692    lastActivePanel = panel ? activePanel : 0;
     693    if (panel == activePanel || (!q->isActive() && !duringActivationEvent))
     694        return;
     695
     696    // Deactivate the last active panel.
     697    if (activePanel) {
     698        if (QGraphicsItem *fi = activePanel->focusItem()) {
     699            // Remove focus from the current focus item.
     700            if (fi == q->focusItem())
     701                q->setFocusItem(0, Qt::ActiveWindowFocusReason);
     702        }
     703
     704        QEvent event(QEvent::WindowDeactivate);
     705        q->sendEvent(activePanel, &event);
     706    } else if (panel && !duringActivationEvent) {
     707        // Deactivate the scene if changing activation to a panel.
     708        QEvent event(QEvent::WindowDeactivate);
     709        foreach (QGraphicsItem *item, q->items()) {
     710            if (item->isVisible() && !item->isPanel() && !item->parentItem())
     711                q->sendEvent(item, &event);
     712        }
     713    }
     714
     715    // Update activate state.
     716    activePanel = panel;
     717    QEvent event(QEvent::ActivationChange);
     718    QApplication::sendEvent(q, &event);
     719
     720    // Activate
     721    if (panel) {
     722        QEvent event(QEvent::WindowActivate);
     723        q->sendEvent(panel, &event);
     724
     725        // Set focus on the panel's focus item.
     726        if (QGraphicsItem *focusItem = panel->focusItem())
     727            focusItem->setFocus(Qt::ActiveWindowFocusReason);
     728    } else if (q->isActive()) {
     729        // Activate the scene
     730        QEvent event(QEvent::WindowActivate);
     731        foreach (QGraphicsItem *item, q->items()) {
     732            if (item->isVisible() && !item->isPanel() && !item->parentItem())
     733                q->sendEvent(item, &event);
     734        }
     735    }
    808736}
    809737
    810738/*!
    811739    \internal
    812 
    813     Starts or restarts the timer used for reindexing unindexed items.
    814 */
    815 void QGraphicsScenePrivate::startIndexTimer()
     740*/
     741void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item,
     742                                               Qt::FocusReason focusReason)
    816743{
    817744    Q_Q(QGraphicsScene);
    818     if (indexTimerId) {
    819         restartIndexTimer = true;
    820     } else {
    821         indexTimerId = q->startTimer(QGRAPHICSSCENE_INDEXTIMER_TIMEOUT);
    822     }
     745    if (item == focusItem)
     746        return;
     747
     748    // Clear focus if asked to set focus on something that can't
     749    // accept input focus.
     750    if (item && (!(item->flags() & QGraphicsItem::ItemIsFocusable)
     751                 || !item->isVisible() || !item->isEnabled())) {
     752        item = 0;
     753    }
     754
     755    // Set focus on the scene if an item requests focus.
     756    if (item) {
     757        q->setFocus(focusReason);
     758        if (item == focusItem)
     759            return;
     760    }
     761
     762    if (focusItem) {
     763        QFocusEvent event(QEvent::FocusOut, focusReason);
     764        lastFocusItem = focusItem;
     765        focusItem = 0;
     766        sendEvent(lastFocusItem, &event);
     767
     768#ifndef QT_NO_IM
     769        if (lastFocusItem
     770            && (lastFocusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) {
     771            // Reset any visible preedit text
     772            QInputMethodEvent imEvent;
     773            sendEvent(lastFocusItem, &imEvent);
     774
     775            // Close any external input method panel. This happens
     776            // automatically by removing WA_InputMethodEnabled on
     777            // the views, but if we are changing focus, we have to
     778            // do it ourselves.
     779            if (item) {
     780                for (int i = 0; i < views.size(); ++i)
     781                    views.at(i)->inputContext()->reset();
     782            }
     783        }
     784#endif //QT_NO_IM
     785    }
     786
     787    if (item) {
     788        focusItem = item;
     789        QFocusEvent event(QEvent::FocusIn, focusReason);
     790        sendEvent(item, &event);
     791    }
     792
     793    updateInputMethodSensitivityInViews();
    823794}
    824795
     
    864835            QFocusEvent event(QEvent::FocusIn, Qt::PopupFocusReason);
    865836            sendEvent(focusItem, &event);
    866         } else {
    867             ungrabKeyboard((QGraphicsItem *)widget, itemIsDying);
     837        } else if (keyboardGrabberItems.contains(static_cast<QGraphicsItem *>(widget))) {
     838            ungrabKeyboard(static_cast<QGraphicsItem *>(widget), itemIsDying);
    868839        }
    869840        if (!itemIsDying && widget->isVisible()) {
     
    881852    // Append to list of mouse grabber items, and send a mouse grab event.
    882853    if (mouseGrabberItems.contains(item)) {
    883         if (mouseGrabberItems.last() == item)
    884             qWarning("QGraphicsItem::grabMouse: already a mouse grabber");
    885         else
     854        if (mouseGrabberItems.last() == item) {
     855            Q_ASSERT(!implicit);
     856            if (!lastMouseGrabberItemHasImplicitMouseGrab) {
     857                qWarning("QGraphicsItem::grabMouse: already a mouse grabber");
     858            } else {
     859                // Upgrade to an explicit mouse grab
     860                lastMouseGrabberItemHasImplicitMouseGrab = false;
     861            }
     862        } else {
    886863            qWarning("QGraphicsItem::grabMouse: already blocked by mouse grabber: %p",
    887864                     mouseGrabberItems.last());
     865        }
    888866        return;
    889867    }
     
    10371015}
    10381016
     1017void QGraphicsScenePrivate::enableMouseTrackingOnViews()
     1018{
     1019    foreach (QGraphicsView *view, views)
     1020        view->viewport()->setMouseTracking(true);
     1021}
     1022
    10391023/*!
    10401024    Returns all items for the screen position in \a event.
     
    10461030    Q_Q(const QGraphicsScene);
    10471031    QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0;
    1048     QList<QGraphicsItem *> items;
    1049     if (view)
    1050         items = view->items(view->viewport()->mapFromGlobal(screenPos));
    1051     else
    1052         items = q->items(scenePos);
    1053     return items;
    1054 }
    1055 
    1056 /*!
    1057     \internal
    1058 
    1059     Checks if item collides with the path and mode, but also checks that if it
    1060     doesn't collide, maybe its frame rect will.
    1061 */
    1062 bool QGraphicsScenePrivate::itemCollidesWithPath(QGraphicsItem *item,
    1063                                                  const QPainterPath &path,
    1064                                                  Qt::ItemSelectionMode mode)
    1065 {
    1066     if (item->collidesWithPath(path, mode))
    1067         return true;
    1068     if (item->isWidget()) {
    1069         // Check if this is a window, and if its frame rect collides.
    1070         QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
    1071         if (widget->isWindow()) {
    1072             QRectF frameRect = widget->windowFrameRect();
    1073             QPainterPath framePath;
    1074             framePath.addRect(frameRect);
    1075             bool intersects = path.intersects(frameRect);
    1076             if (mode == Qt::IntersectsItemShape || mode == Qt::IntersectsItemBoundingRect)
    1077                 return intersects || path.contains(frameRect.topLeft())
    1078                     || framePath.contains(path.elementAt(0));
    1079             return !intersects && path.contains(frameRect.topLeft());
    1080         }
    1081     }
    1082     return false;
     1032    if (!view)
     1033        return q->items(scenePos, Qt::IntersectsItemShape, Qt::DescendingOrder, QTransform());
     1034
     1035    const QRectF pointRect(QPointF(widget->mapFromGlobal(screenPos)), QSizeF(1, 1));
     1036    if (!view->isTransformed())
     1037        return q->items(pointRect, Qt::IntersectsItemShape, Qt::DescendingOrder);
     1038
     1039    const QTransform viewTransform = view->viewportTransform();
     1040    if (viewTransform.type() <= QTransform::TxScale) {
     1041        return q->items(viewTransform.inverted().mapRect(pointRect), Qt::IntersectsItemShape,
     1042                        Qt::DescendingOrder, viewTransform);
     1043    }
     1044    return q->items(viewTransform.inverted().map(pointRect), Qt::IntersectsItemShape,
     1045                    Qt::DescendingOrder, viewTransform);
    10831046}
    10841047
     
    10921055            mouseGrabberButtonDownPos.insert(Qt::MouseButton(i),
    10931056                                             mouseGrabberItems.last()->d_ptr->genericMapFromScene(event->scenePos(),
    1094                                                                                           event->widget()));
     1057                                                                                                  event->widget()));
    10951058            mouseGrabberButtonDownScenePos.insert(Qt::MouseButton(i), event->scenePos());
    10961059            mouseGrabberButtonDownScreenPos.insert(Qt::MouseButton(i), event->screenPos());
     
    11261089
    11271090/*!
     1091  \internal
     1092*/
     1093bool QGraphicsScenePrivate::filterDescendantEvent(QGraphicsItem *item, QEvent *event)
     1094{
     1095    if (item && (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorFiltersChildEvents)) {
     1096        QGraphicsItem *parent = item->parentItem();
     1097        while (parent) {
     1098            if (parent->d_ptr->filtersDescendantEvents && parent->sceneEventFilter(item, event))
     1099                return true;
     1100            if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorFiltersChildEvents))
     1101                return false;
     1102            parent = parent->parentItem();
     1103        }
     1104    }
     1105    return false;
     1106}
     1107
     1108/*!
    11281109    \internal
    11291110*/
     
    11551136bool QGraphicsScenePrivate::sendEvent(QGraphicsItem *item, QEvent *event)
    11561137{
     1138    if (QGraphicsObject *object = item->toGraphicsObject()) {
     1139        QGestureManager *gestureManager = QApplicationPrivate::instance()->gestureManager;
     1140        if (gestureManager) {
     1141            if (gestureManager->filterEvent(object, event))
     1142                return true;
     1143        }
     1144    }
     1145
    11571146    if (filterEvent(item, event))
    11581147        return false;
    1159     return (item && item->isEnabled()) ? item->sceneEvent(event) : false;
     1148    if (filterDescendantEvent(item, event))
     1149        return false;
     1150    if (!item || !item->isEnabled())
     1151        return false;
     1152    if (QGraphicsObject *o = item->toGraphicsObject()) {
     1153        bool spont = event->spontaneous();
     1154        if (spont ? qt_sendSpontaneousEvent(o, event) : QApplication::sendEvent(o, event))
     1155            return true;
     1156        event->spont = spont;
     1157    }
     1158    return item->sceneEvent(event);
    11601159}
    11611160
     
    12201219
    12211220    QGraphicsItem *item = mouseGrabberItems.last();
     1221    if (item->isBlockedByModalPanel())
     1222        return;
     1223
    12221224    for (int i = 0x1; i <= 0x10; i <<= 1) {
    12231225        Qt::MouseButton button = Qt::MouseButton(i);
     
    12431245    // Deliver to any existing mouse grabber.
    12441246    if (!mouseGrabberItems.isEmpty()) {
     1247        if (mouseGrabberItems.last()->isBlockedByModalPanel())
     1248            return;
    12451249        // The event is ignored by default, but we disregard the event's
    12461250        // accepted state after delivery; the mouse is grabbed, after all.
     
    12581262
    12591263    // Update window activation.
    1260     QGraphicsWidget *newActiveWindow = windowForItem(cachedItemsUnderMouse.value(0));
    1261     if (newActiveWindow != activeWindow)
     1264    QGraphicsItem *topItem = cachedItemsUnderMouse.value(0);
     1265    QGraphicsWidget *newActiveWindow = topItem ? topItem->window() : 0;
     1266    if (newActiveWindow && newActiveWindow->isBlockedByModalPanel(&topItem)) {
     1267        // pass activation to the blocking modal window
     1268        newActiveWindow = topItem ? topItem->window() : 0;
     1269    }
     1270
     1271    if (newActiveWindow != q->activeWindow())
    12621272        q->setActiveWindow(newActiveWindow);
    12631273
     
    12651275    bool setFocus = false;
    12661276    foreach (QGraphicsItem *item, cachedItemsUnderMouse) {
    1267         if (item->isEnabled() && (item->flags() & QGraphicsItem::ItemIsFocusable)) {
     1277        if (item->isBlockedByModalPanel()) {
     1278            // Make sure we don't clear focus.
     1279            setFocus = true;
     1280            break;
     1281        }
     1282        if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) {
    12681283            if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) {
    12691284                setFocus = true;
     
    12731288            }
    12741289        }
     1290        if (item->isPanel())
     1291            break;
     1292    }
     1293
     1294    // Check for scene modality.
     1295    bool sceneModality = false;
     1296    for (int i = 0; i < modalPanels.size(); ++i) {
     1297        if (modalPanels.at(i)->panelModality() == QGraphicsItem::SceneModal) {
     1298            sceneModality = true;
     1299            break;
     1300        }
    12751301    }
    12761302
    12771303    // If nobody could take focus, clear it.
    1278     if (!stickyFocus && !setFocus)
     1304    if (!stickyFocus && !setFocus && !sceneModality)
    12791305        q->setFocusItem(0, Qt::MouseFocusReason);
     1306
     1307    // Any item will do.
     1308    if (sceneModality && cachedItemsUnderMouse.isEmpty())
     1309        cachedItemsUnderMouse << modalPanels.first();
    12801310
    12811311    // Find a mouse grabber by sending mouse press events to all mouse grabber
     
    12891319        }
    12901320
     1321        // Check if this item is blocked by a modal panel and deliver the mouse event to the
     1322        // blocking panel instead of this item if blocked.
     1323        (void) item->isBlockedByModalPanel(&item);
     1324
    12911325        grabMouse(item, /* implicit = */ true);
    12921326        mouseEvent->accept();
     
    12941328        // check if the item we are sending to are disabled (before we send the event)
    12951329        bool disabled = !item->isEnabled();
    1296         bool isWindow = item->isWindow();
    1297         if (mouseEvent->type() == QEvent::GraphicsSceneMouseDoubleClick && item != lastMouseGrabberItem) {
     1330        bool isPanel = item->isPanel();
     1331        if (mouseEvent->type() == QEvent::GraphicsSceneMouseDoubleClick
     1332            && item != lastMouseGrabberItem && lastMouseGrabberItem) {
    12981333            // If this item is different from the item that received the last
    12991334            // mouse event, and mouseEvent is a doubleclick event, then the
     
    13011336            // Triple-clicking will not generate a doubleclick, though.
    13021337            QGraphicsSceneMouseEvent mousePress(QEvent::GraphicsSceneMousePress);
     1338            mousePress.spont = mouseEvent->spont;
    13031339            mousePress.accept();
    13041340            mousePress.setButton(mouseEvent->button());
     
    13331369        ungrabMouse(item, /* itemIsDying = */ dontSendUngrabEvents);
    13341370
    1335         // Don't propagate through windows.
    1336         if (isWindow)
     1371        // Don't propagate through panels.
     1372        if (isPanel)
    13371373            break;
    13381374    }
     
    13561392}
    13571393
    1358 QGraphicsWidget *QGraphicsScenePrivate::windowForItem(const QGraphicsItem *item) const
    1359 {
    1360     if (!item)
    1361         return 0;
    1362     do {
    1363         if (item->isWidget())
    1364             return static_cast<const QGraphicsWidget *>(item)->window();
    1365         item = item->parentItem();
    1366     } while (item);
    1367     return 0;
    1368 }
    1369 
    1370 
    1371 QList<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QPointF &pos) const
    1372 {
    1373     QList<QGraphicsItem *> items;
    1374 
    1375     // The index returns a rough estimate of what items are inside the rect.
    1376     // Refine it by iterating through all returned items.
    1377     QRectF adjustedRect = QRectF(pos, QSize(1,1));
    1378     foreach (QGraphicsItem *item, estimateItemsInRect(adjustedRect)) {
    1379         // Find the item's scene transform in a clever way.
    1380         QTransform x = item->sceneTransform();
    1381         bool keep = false;
    1382 
    1383         // ### _q_adjustedRect is only needed because QRectF::intersects,
    1384         // QRectF::contains and QTransform::map() and friends don't work with
    1385         // flat rectangles.
    1386         const QRectF br(adjustedItemBoundingRect(item));
    1387             // Rect intersects/contains item's shape
    1388         if (QRectF_intersects(adjustedRect, x.mapRect(br))) {
    1389             bool ok;
    1390             QTransform xinv = x.inverted(&ok);
    1391             if (ok) {
    1392                 if (item->contains(xinv.map(pos))) {
    1393                     items << item;
    1394                     keep = true;
    1395                 }
    1396             }
    1397         }
    1398 
    1399         if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) {
    1400             // Recurse into children that clip children.
    1401             bool ok;
    1402             QTransform xinv = x.inverted(&ok);
    1403             if (ok)
    1404                 childItems_helper(&items, item, xinv.map(pos));
    1405         }
    1406     }
    1407 
    1408     sortItems(&items, Qt::AscendingOrder, sortCacheEnabled);
    1409     return items;
    1410 }
    1411 
    1412 QList<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QRectF &rect,
    1413                                                            Qt::ItemSelectionMode mode,
    1414                                                            Qt::SortOrder order) const
    1415 {
    1416     QList<QGraphicsItem *> items;
    1417 
    1418     QPainterPath path;
    1419 
    1420     // The index returns a rough estimate of what items are inside the rect.
    1421     // Refine it by iterating through all returned items.
    1422     QRectF adjustedRect(rect);
    1423     _q_adjustRect(&adjustedRect);
    1424     foreach (QGraphicsItem *item, estimateItemsInRect(adjustedRect)) {
    1425         // Find the item's scene transform in a clever way.
    1426         QTransform x = item->sceneTransform();
    1427         bool keep = false;
    1428 
    1429         // ### _q_adjustedRect is only needed because QRectF::intersects,
    1430         // QRectF::contains and QTransform::map() and friends don't work with
    1431         // flat rectangles.
    1432         const QRectF br(adjustedItemBoundingRect(item));
    1433         if (mode >= Qt::ContainsItemBoundingRect) {
    1434             // Rect intersects/contains item's bounding rect
    1435             QRectF mbr = x.mapRect(br);
    1436             if ((mode == Qt::IntersectsItemBoundingRect && QRectF_intersects(rect, mbr))
    1437                 || (mode == Qt::ContainsItemBoundingRect && rect != mbr && rect.contains(mbr))) {
    1438                 items << item;
    1439                 keep = true;
    1440             }
    1441         } else {
    1442             // Rect intersects/contains item's shape
    1443             if (QRectF_intersects(adjustedRect, x.mapRect(br))) {
    1444                 bool ok;
    1445                 QTransform xinv = x.inverted(&ok);
    1446                 if (ok) {
    1447                     if (path.isEmpty())
    1448                         path.addRect(rect);
    1449                     if (itemCollidesWithPath(item, xinv.map(path), mode)) {
    1450                         items << item;
    1451                         keep = true;
    1452                     }
    1453                 }
    1454             }
    1455         }
    1456 
    1457         if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) {
    1458             // Recurse into children that clip children.
    1459             bool ok;
    1460             QTransform xinv = x.inverted(&ok);
    1461             if (ok) {
    1462                 if (x.type() <= QTransform::TxScale) {
    1463                     // Rect
    1464                     childItems_helper(&items, item, xinv.mapRect(rect), mode);
    1465                 } else {
    1466                     // Polygon
    1467                     childItems_helper(&items, item, xinv.map(rect), mode);
    1468                 }
    1469             }
    1470         }
    1471     }
    1472 
    1473     if (order != Qt::SortOrder(-1))
    1474         sortItems(&items, order, sortCacheEnabled);
    1475     return items;
    1476 }
    1477 
    1478 QList<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QPolygonF &polygon,
    1479                                                            Qt::ItemSelectionMode mode,
    1480                                                            Qt::SortOrder order) const
    1481 {
    1482     QList<QGraphicsItem *> items;
    1483 
    1484     QRectF polyRect(polygon.boundingRect());
    1485      _q_adjustRect(&polyRect);
    1486     QPainterPath path;
    1487 
    1488     // The index returns a rough estimate of what items are inside the rect.
    1489     // Refine it by iterating through all returned items.
    1490     foreach (QGraphicsItem *item, estimateItemsInRect(polyRect)) {
    1491         // Find the item's scene transform in a clever way.
    1492         QTransform x = item->sceneTransform();
    1493         bool keep = false;
    1494 
    1495         // ### _q_adjustedRect is only needed because QRectF::intersects,
    1496         // QRectF::contains and QTransform::map() and friends don't work with
    1497         // flat rectangles.
    1498         const QRectF br(adjustedItemBoundingRect(item));
    1499         if (mode >= Qt::ContainsItemBoundingRect) {
    1500             // Polygon contains/intersects item's bounding rect
    1501             if (path == QPainterPath())
    1502                 path.addPolygon(polygon);
    1503             if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(x.mapRect(br)))
    1504                 || (mode == Qt::ContainsItemBoundingRect && path.contains(x.mapRect(br)))) {
    1505                 items << item;
    1506                 keep = true;
    1507             }
    1508         } else {
    1509             // Polygon contains/intersects item's shape
    1510             if (QRectF_intersects(polyRect, x.mapRect(br))) {
    1511                 bool ok;
    1512                 QTransform xinv = x.inverted(&ok);
    1513                 if (ok) {
    1514                     if (path == QPainterPath())
    1515                         path.addPolygon(polygon);
    1516                     if (itemCollidesWithPath(item, xinv.map(path), mode)) {
    1517                         items << item;
    1518                         keep = true;
    1519                     }
    1520                 }
    1521             }
    1522         }
    1523 
    1524         if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) {
    1525             // Recurse into children that clip children.
    1526             bool ok;
    1527             QTransform xinv = x.inverted(&ok);
    1528             if (ok)
    1529                 childItems_helper(&items, item, xinv.map(polygon), mode);
    1530         }
    1531     }
    1532 
    1533     if (order != Qt::SortOrder(-1))
    1534         sortItems(&items, order, sortCacheEnabled);
    1535     return items;
    1536 }
    1537 
    1538 QList<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QPainterPath &path,
    1539                                                            Qt::ItemSelectionMode mode,
    1540                                                            Qt::SortOrder order) const
    1541 {
    1542     QList<QGraphicsItem *> items;
    1543     QRectF pathRect(path.controlPointRect());
    1544     _q_adjustRect(&pathRect);
    1545 
    1546     // The index returns a rough estimate of what items are inside the rect.
    1547     // Refine it by iterating through all returned items.
    1548     foreach (QGraphicsItem *item, estimateItemsInRect(pathRect)) {
    1549         // Find the item's scene transform in a clever way.
    1550         QTransform x = item->sceneTransform();
    1551         bool keep = false;
    1552 
    1553         // ### _q_adjustedRect is only needed because QRectF::intersects,
    1554         // QRectF::contains and QTransform::map() and friends don't work with
    1555         // flat rectangles.
    1556         const QRectF br(adjustedItemBoundingRect(item));
    1557         if (mode >= Qt::ContainsItemBoundingRect) {
    1558             // Path contains/intersects item's bounding rect
    1559             if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(x.mapRect(br)))
    1560                 || (mode == Qt::ContainsItemBoundingRect && path.contains(x.mapRect(br)))) {
    1561                 items << item;
    1562                 keep = true;
    1563             }
    1564         } else {
    1565             // Path contains/intersects item's shape
    1566             if (QRectF_intersects(pathRect, x.mapRect(br))) {
    1567                 bool ok;
    1568                 QTransform xinv = x.inverted(&ok);
    1569                 if (ok) {
    1570                     if (itemCollidesWithPath(item, xinv.map(path), mode)) {
    1571                         items << item;
    1572                         keep = true;
    1573                     }
    1574                 }
    1575             }
    1576         }
    1577 
    1578         if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) {
    1579             bool ok;
    1580             QTransform xinv = x.inverted(&ok);
    1581             if (ok)
    1582                 childItems_helper(&items, item, xinv.map(path), mode);
    1583         }
    1584     }
    1585 
    1586     if (order != Qt::SortOrder(-1))
    1587         sortItems(&items, order, sortCacheEnabled);
    1588     return items;
    1589 }
    1590 
    1591 void QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *items,
    1592                                               const QGraphicsItem *parent,
    1593                                               const QPointF &pos) const
    1594 {
    1595     bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape);
    1596     if (parentClip && parent->d_ptr->isClippedAway())
    1597         return;
    1598     // ### is this needed?
    1599     if (parentClip && !parent->boundingRect().contains(pos))
    1600         return;
    1601 
    1602     QList<QGraphicsItem *> &children = parent->d_ptr->children;
    1603     for (int i = 0; i < children.size(); ++i) {
    1604         QGraphicsItem *item = children.at(i);
    1605         if (item->d_ptr->hasTransform && !item->transform().isInvertible())
    1606             continue;
    1607 
    1608         // Skip invisible items and all their children.
    1609         if (item->d_ptr->isInvisible())
    1610             continue;
    1611 
    1612         bool keep = false;
    1613         if (!item->d_ptr->isClippedAway()) {
    1614             if (item->contains(item->mapFromParent(pos))) {
    1615                 items->append(item);
    1616                 keep = true;
    1617             }
    1618         }
    1619 
    1620         if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty())
    1621             // Recurse into children.
    1622             childItems_helper(items, item, item->mapFromParent(pos));
    1623     }
    1624 }
    1625 
    1626 
    1627 void QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *items,
    1628                                               const QGraphicsItem *parent,
    1629                                               const QRectF &rect,
    1630                                               Qt::ItemSelectionMode mode) const
    1631 {
    1632     bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape);
    1633     if (parentClip && parent->d_ptr->isClippedAway())
    1634         return;
    1635     QRectF adjustedRect(rect);
    1636     _q_adjustRect(&adjustedRect);
    1637     QRectF r = !parentClip ? adjustedRect : adjustedRect.intersected(adjustedItemBoundingRect(parent));
    1638     if (r.isEmpty())
    1639         return;
    1640 
    1641     QPainterPath path;
    1642     QList<QGraphicsItem *> &children = parent->d_ptr->children;
    1643     for (int i = 0; i < children.size(); ++i) {
    1644         QGraphicsItem *item = children.at(i);
    1645         if (item->d_ptr->hasTransform && !item->transform().isInvertible())
    1646             continue;
    1647 
    1648         // Skip invisible items and all their children.
    1649         if (item->d_ptr->isInvisible())
    1650             continue;
    1651 
    1652         bool keep = false;
    1653         if (!item->d_ptr->isClippedAway()) {
    1654             // ### _q_adjustedRect is only needed because QRectF::intersects,
    1655             // QRectF::contains and QTransform::map() and friends don't work with
    1656             // flat rectangles.
    1657             const QRectF br(adjustedItemBoundingRect(item));
    1658             QRectF mbr = item->mapRectToParent(br);
    1659             if (mode >= Qt::ContainsItemBoundingRect) {
    1660                 // Rect intersects/contains item's bounding rect
    1661                 if ((mode == Qt::IntersectsItemBoundingRect && QRectF_intersects(rect, mbr))
    1662                     || (mode == Qt::ContainsItemBoundingRect && rect != mbr && rect.contains(br))) {
    1663                     items->append(item);
    1664                     keep = true;
    1665                 }
    1666             } else {
    1667                 // Rect intersects/contains item's shape
    1668                 if (QRectF_intersects(rect, mbr)) {
    1669                     if (path == QPainterPath())
    1670                         path.addRect(rect);
    1671                     if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) {
    1672                         items->append(item);
    1673                         keep = true;
    1674                     }
    1675                 }
    1676             }
    1677         }
    1678 
    1679         if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) {
    1680             // Recurse into children.
    1681             if (!item->d_ptr->hasTransform || item->transform().type() <= QTransform::TxScale) {
    1682                 // Rect
    1683                 childItems_helper(items, item, item->mapRectFromParent(rect), mode);
    1684             } else {
    1685                 // Polygon
    1686                 childItems_helper(items, item, item->mapFromParent(rect), mode);
    1687             }
    1688         }
    1689     }
    1690 }
    1691 
    1692 
    1693 void QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *items,
    1694                                               const QGraphicsItem *parent,
    1695                                               const QPolygonF &polygon,
    1696                                               Qt::ItemSelectionMode mode) const
    1697 {
    1698     bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape);
    1699     if (parentClip && parent->d_ptr->isClippedAway())
    1700         return;
    1701     QRectF polyRect(polygon.boundingRect());
    1702     _q_adjustRect(&polyRect);
    1703     QRectF r = !parentClip ? polyRect : polyRect.intersected(adjustedItemBoundingRect(parent));
    1704     if (r.isEmpty())
    1705         return;
    1706 
    1707     QPainterPath path;
    1708     QList<QGraphicsItem *> &children = parent->d_ptr->children;
    1709     for (int i = 0; i < children.size(); ++i) {
    1710         QGraphicsItem *item = children.at(i);
    1711         if (item->d_ptr->hasTransform && !item->transform().isInvertible())
    1712             continue;
    1713 
    1714         // Skip invisible items.
    1715         if (item->d_ptr->isInvisible())
    1716             continue;
    1717 
    1718         bool keep = false;
    1719         if (!item->d_ptr->isClippedAway()) {
    1720             // ### _q_adjustedRect is only needed because QRectF::intersects,
    1721             // QRectF::contains and QTransform::map() and friends don't work with
    1722             // flat rectangles.
    1723             const QRectF br(adjustedItemBoundingRect(item));
    1724             if (mode >= Qt::ContainsItemBoundingRect) {
    1725                 // Polygon contains/intersects item's bounding rect
    1726                 if (path == QPainterPath())
    1727                     path.addPolygon(polygon);
    1728                 if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br)))
    1729                     || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) {
    1730                     items->append(item);
    1731                     keep = true;
    1732                 }
    1733             } else {
    1734                 // Polygon contains/intersects item's shape
    1735                 if (QRectF_intersects(polyRect, item->mapRectToParent(br))) {
    1736                     if (path == QPainterPath())
    1737                         path.addPolygon(polygon);
    1738                     if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) {
    1739                         items->append(item);
    1740                         keep = true;
    1741                     }
    1742                 }
    1743             }
    1744         }
    1745 
    1746         if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) {
    1747             // Recurse into children that clip children.
    1748             childItems_helper(items, item, item->mapFromParent(polygon), mode);
    1749         }
    1750     }
    1751 }
    1752 
    1753 void QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *items,
    1754                                               const QGraphicsItem *parent,
    1755                                               const QPainterPath &path,
    1756                                               Qt::ItemSelectionMode mode) const
    1757 {
    1758     bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape);
    1759     if (parentClip && parent->d_ptr->isClippedAway())
    1760         return;
    1761     QRectF pathRect(path.boundingRect());
    1762     _q_adjustRect(&pathRect);
    1763     QRectF r = !parentClip ? pathRect : pathRect.intersected(adjustedItemBoundingRect(parent));
    1764     if (r.isEmpty())
    1765         return;
    1766 
    1767     QList<QGraphicsItem *> &children = parent->d_ptr->children;
    1768     for (int i = 0; i < children.size(); ++i) {
    1769         QGraphicsItem *item = children.at(i);
    1770         if (item->d_ptr->hasTransform && !item->transform().isInvertible())
    1771             continue;
    1772 
    1773         // Skip invisible items.
    1774         if (item->d_ptr->isInvisible())
    1775             continue;
    1776 
    1777         bool keep = false;
    1778         if (!item->d_ptr->isClippedAway()) {
    1779             // ### _q_adjustedRect is only needed because QRectF::intersects,
    1780             // QRectF::contains and QTransform::map() and friends don't work with
    1781             // flat rectangles.
    1782             const QRectF br(adjustedItemBoundingRect(item));
    1783             if (mode >= Qt::ContainsItemBoundingRect) {
    1784                 // Polygon contains/intersects item's bounding rect
    1785                 if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br)))
    1786                     || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) {
    1787                     items->append(item);
    1788                     keep = true;
    1789                 }
    1790             } else {
    1791                 // Path contains/intersects item's shape
    1792                 if (QRectF_intersects(pathRect, item->mapRectToParent(br))) {
    1793                     if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) {
    1794                         items->append(item);
    1795                         keep = true;
    1796                     }
    1797                 }
    1798             }
    1799         }
    1800 
    1801         if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) {
    1802             // Recurse into children that clip children.
    1803             childItems_helper(items, item, item->mapFromParent(path), mode);
    1804         }
    1805     }
    1806 }
    1807 
    1808 void QGraphicsScenePrivate::invalidateSortCache()
    1809 {
    1810     Q_Q(QGraphicsScene);
    1811     if (!sortCacheEnabled || updatingSortCache)
    1812         return;
    1813 
    1814     updatingSortCache = true;
    1815     QMetaObject::invokeMethod(q, "_q_updateSortCache", Qt::QueuedConnection);
    1816 }
    1817 
    18181394/*!
    18191395    \internal
    18201396
    1821     Should not be exported, but we can't change that now.
    1822     ### Qt 5: Remove symbol / make static
    1823 */
    1824 inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2)
    1825 {
    1826     // Return true if sibling item1 is on top of item2.
    1827     const QGraphicsItemPrivate *d1 = item1->d_ptr;
    1828     const QGraphicsItemPrivate *d2 = item2->d_ptr;
    1829     bool f1 = d1->flags & QGraphicsItem::ItemStacksBehindParent;
    1830     bool f2 = d2->flags & QGraphicsItem::ItemStacksBehindParent;
    1831     if (f1 != f2) return f2;
    1832     qreal z1 = d1->z;
    1833     qreal z2 = d2->z;
    1834     return z1 != z2 ? z1 > z2 : item1 > item2;
    1835 }
    1836 
    1837 /*!
    1838     \internal
    1839 
    1840     Should not be exported, but we can't change that now.
    1841 */
    1842 inline bool qt_closestItemFirst(const QGraphicsItem *item1, const QGraphicsItem *item2)
    1843 {
    1844     return QGraphicsScenePrivate::closestItemFirst_withoutCache(item1, item2);
    1845 }
    1846 
    1847 /*!
    1848     Returns true if \a item1 is on top of \a item2.
    1849 
    1850     \internal
    1851 */
    1852 bool QGraphicsScenePrivate::closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2)
    1853 {
    1854     // Siblings? Just check their z-values.
    1855     const QGraphicsItemPrivate *d1 = item1->d_ptr;
    1856     const QGraphicsItemPrivate *d2 = item2->d_ptr;
    1857     if (d1->parent == d2->parent)
    1858         return qt_closestLeaf(item1, item2);
    1859 
    1860     // Find common ancestor, and each item's ancestor closest to the common
    1861     // ancestor.
    1862     int item1Depth = d1->depth;
    1863     int item2Depth = d2->depth;
    1864     const QGraphicsItem *p = item1;
    1865     const QGraphicsItem *t1 = item1;
    1866     while (item1Depth > item2Depth && (p = p->d_ptr->parent)) {
    1867         if (p == item2) {
    1868             // item2 is one of item1's ancestors; item1 is on top
    1869             return !(t1->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent);
    1870         }
    1871         t1 = p;
    1872         --item1Depth;
    1873     }
    1874     p = item2;
    1875     const QGraphicsItem *t2 = item2;
    1876     while (item2Depth > item1Depth && (p = p->d_ptr->parent)) {
    1877         if (p == item1) {
    1878             // item1 is one of item2's ancestors; item1 is not on top
    1879             return (t2->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent);
    1880         }
    1881         t2 = p;
    1882         --item2Depth;
    1883     }
    1884 
    1885     // item1Ancestor is now at the same level as item2Ancestor, but not the same.
    1886     const QGraphicsItem *a1 = t1;
    1887     const QGraphicsItem *a2 = t2;
    1888     while (a1) {
    1889         const QGraphicsItem *p1 = a1;
    1890         const QGraphicsItem *p2 = a2;
    1891         a1 = a1->parentItem();
    1892         a2 = a2->parentItem();
    1893         if (a1 && a1 == a2)
    1894             return qt_closestLeaf(p1, p2);
    1895     }
    1896 
    1897     // No common ancestor? Then just compare the items' toplevels directly.
    1898     return qt_closestLeaf(t1->topLevelItem(), t2->topLevelItem());
    1899 }
    1900 
    1901 /*!
    1902     Returns true if \a item2 is on top of \a item1.
    1903 
    1904     \internal
    1905 */
    1906 bool QGraphicsScenePrivate::closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2)
    1907 {
    1908     return closestItemFirst_withoutCache(item2, item1);
    1909 }
    1910 
    1911 void QGraphicsScenePrivate::climbTree(QGraphicsItem *item, int *stackingOrder)
    1912 {
    1913     if (!item->d_ptr->children.isEmpty()) {
    1914         QList<QGraphicsItem *> childList = item->d_ptr->children;
    1915         qSort(childList.begin(), childList.end(), qt_closestLeaf);
    1916         for (int i = 0; i < childList.size(); ++i) {
    1917             QGraphicsItem *item = childList.at(i);
    1918             if (!(item->flags() & QGraphicsItem::ItemStacksBehindParent))
    1919                 climbTree(childList.at(i), stackingOrder);
    1920         }
    1921         item->d_ptr->globalStackingOrder = (*stackingOrder)++;
    1922         for (int i = 0; i < childList.size(); ++i) {
    1923             QGraphicsItem *item = childList.at(i);
    1924             if (item->flags() & QGraphicsItem::ItemStacksBehindParent)
    1925                 climbTree(childList.at(i), stackingOrder);
    1926         }
    1927     } else {
    1928         item->d_ptr->globalStackingOrder = (*stackingOrder)++;
    1929     }
    1930 }
    1931 
    1932 void QGraphicsScenePrivate::_q_updateSortCache()
    1933 {
    1934     _q_updateIndex();
    1935 
    1936     if (!sortCacheEnabled || !updatingSortCache)
    1937         return;
    1938 
    1939     updatingSortCache = false;
    1940     int stackingOrder = 0;
    1941 
    1942     QList<QGraphicsItem *> topLevels;
    1943 
    1944     for (int i = 0; i < indexedItems.size(); ++i) {
    1945         QGraphicsItem *item = indexedItems.at(i);
    1946         if (item && item->parentItem() == 0)
    1947             topLevels << item;
    1948     }
    1949     for (int i = 0; i < unindexedItems.size(); ++i) {
    1950         QGraphicsItem *item = unindexedItems.at(i);
    1951         if (item->parentItem() == 0)
    1952             topLevels << item;
    1953     }
    1954 
    1955     qSort(topLevels.begin(), topLevels.end(), qt_closestLeaf);
    1956     for (int i = 0; i < topLevels.size(); ++i)
    1957         climbTree(topLevels.at(i), &stackingOrder);
    1958 }
    1959 
    1960 void QGraphicsScenePrivate::sortItems(QList<QGraphicsItem *> *itemList, Qt::SortOrder order,
    1961                                       bool sortCacheEnabled)
    1962 {
    1963     if (sortCacheEnabled) {
    1964         if (order == Qt::AscendingOrder) {
    1965             qSort(itemList->begin(), itemList->end(), closestItemFirst_withCache);
    1966         } else if (order == Qt::DescendingOrder) {
    1967             qSort(itemList->begin(), itemList->end(), closestItemLast_withCache);
    1968         }
    1969     } else {
    1970         if (order == Qt::AscendingOrder) {
    1971             qSort(itemList->begin(), itemList->end(), closestItemFirst_withoutCache);
    1972         } else if (order == Qt::DescendingOrder) {
    1973             qSort(itemList->begin(), itemList->end(), closestItemLast_withoutCache);
    1974         }
     1397    Ensures that the list of toplevels is sorted by insertion order, and that
     1398    the siblingIndexes are packed (no gaps), and start at 0.
     1399
     1400    ### This function is almost identical to
     1401    QGraphicsItemPrivate::ensureSequentialSiblingIndex().
     1402*/
     1403void QGraphicsScenePrivate::ensureSequentialTopLevelSiblingIndexes()
     1404{
     1405    if (!topLevelSequentialOrdering) {
     1406        qSort(topLevelItems.begin(), topLevelItems.end(), QGraphicsItemPrivate::insertionOrder);
     1407        topLevelSequentialOrdering = true;
     1408        needSortTopLevelItems = 1;
     1409    }
     1410    if (holesInTopLevelSiblingIndex) {
     1411        holesInTopLevelSiblingIndex = 0;
     1412        for (int i = 0; i < topLevelItems.size(); ++i)
     1413            topLevelItems[i]->d_ptr->siblingIndex = i;
    19751414    }
    19761415}
     
    19971436void QGraphicsScenePrivate::resolveFont()
    19981437{
    1999     QFont naturalFont = qApp->font();
     1438    QFont naturalFont = QApplication::font();
    20001439    naturalFont.resolve(0);
    20011440    QFont resolvedFont = font.resolve(naturalFont);
     
    20531492void QGraphicsScenePrivate::resolvePalette()
    20541493{
    2055     QPalette naturalPalette = qApp->palette();
     1494    QPalette naturalPalette = QApplication::palette();
    20561495    naturalPalette.resolve(0);
    20571496    QPalette resolvedPalette = palette.resolve(naturalPalette);
     
    21081547    : QObject(*new QGraphicsScenePrivate, parent)
    21091548{
     1549    d_func()->init();
    21101550    setSceneRect(sceneRect);
    2111     d_func()->init();
    21121551}
    21131552
     
    21231562    : QObject(*new QGraphicsScenePrivate, parent)
    21241563{
     1564    d_func()->init();
    21251565    setSceneRect(x, y, width, height);
    2126     d_func()->init();
    2127 }
    2128 
    2129 /*!
    2130     Destroys the QGraphicsScene object.
     1566}
     1567
     1568/*!
     1569  Removes and deletes all items from the scene object
     1570  before destroying the scene object. The scene object
     1571  is removed from the application's global scene list,
     1572  and it is removed from all associated views.
    21311573*/
    21321574QGraphicsScene::~QGraphicsScene()
    21331575{
    21341576    Q_D(QGraphicsScene);
     1577
    21351578    // Remove this scene from qApp's global scene list.
    21361579    qApp->d_func()->scene_list.removeAll(this);
     
    21611604{
    21621605    Q_D(const QGraphicsScene);
    2163     const_cast<QGraphicsScenePrivate *>(d)->_q_updateIndex();
    2164     return d->hasSceneRect ? d->sceneRect : d->growingItemsBoundingRect;
     1606    if (d->hasSceneRect)
     1607        return d->sceneRect;
     1608
     1609    if (d->dirtyGrowingItemsBoundingRect) {
     1610        // Lazily update the growing items bounding rect
     1611        QGraphicsScenePrivate *thatd = const_cast<QGraphicsScenePrivate *>(d);
     1612        QRectF oldGrowingBoundingRect = thatd->growingItemsBoundingRect;
     1613        thatd->growingItemsBoundingRect |= itemsBoundingRect();
     1614        thatd->dirtyGrowingItemsBoundingRect = false;
     1615        if (oldGrowingBoundingRect != thatd->growingItemsBoundingRect)
     1616            emit const_cast<QGraphicsScene *>(this)->sceneRectChanged(thatd->growingItemsBoundingRect);
     1617    }
     1618    return d->growingItemsBoundingRect;
    21651619}
    21661620void QGraphicsScene::setSceneRect(const QRectF &rect)
     
    21701624        d->hasSceneRect = !rect.isNull();
    21711625        d->sceneRect = rect;
    2172         d->resetIndex();
    2173         emit sceneRectChanged(rect);
     1626        emit sceneRectChanged(d->hasSceneRect ? rect : d->growingItemsBoundingRect);
    21741627    }
    21751628}
     
    22121665                            Qt::AspectRatioMode aspectRatioMode)
    22131666{
    2214     Q_D(QGraphicsScene);
     1667    // ### Switch to using the recursive rendering algorithm instead.
    22151668
    22161669    // Default source rect = scene rect
     
    22701723    // Generate the style options
    22711724    QStyleOptionGraphicsItem *styleOptionArray = new QStyleOptionGraphicsItem[numItems];
    2272     for (int i = 0; i < numItems; ++i) {
    2273         QGraphicsItem *item = itemArray[i];
    2274 
    2275         QStyleOptionGraphicsItem option;
    2276         option.state = QStyle::State_None;
    2277         option.rect = item->boundingRect().toRect();
    2278         if (item->isSelected())
    2279             option.state |= QStyle::State_Selected;
    2280         if (item->isEnabled())
    2281             option.state |= QStyle::State_Enabled;
    2282         if (item->hasFocus())
    2283             option.state |= QStyle::State_HasFocus;
    2284         if (d->hoverItems.contains(item))
    2285             option.state |= QStyle::State_MouseOver;
    2286         if (item == mouseGrabberItem())
    2287             option.state |= QStyle::State_Sunken;
    2288 
    2289         // Calculate a simple level-of-detail metric.
    2290         // ### almost identical code in QGraphicsView::paintEvent()
    2291         //     and QGraphicsView::render() - consider refactoring
    2292         QTransform itemToDeviceTransform;
    2293         if (item->d_ptr->itemIsUntransformable()) {
    2294             itemToDeviceTransform = item->deviceTransform(painterTransform);
    2295         } else {
    2296             itemToDeviceTransform = item->sceneTransform() * painterTransform;
    2297         }
    2298 
    2299         option.levelOfDetail = qSqrt(itemToDeviceTransform.map(v1).length() * itemToDeviceTransform.map(v2).length());
    2300         option.matrix = itemToDeviceTransform.toAffine(); //### discards perspective
    2301 
    2302         option.exposedRect = item->boundingRect();
    2303         option.exposedRect &= itemToDeviceTransform.inverted().mapRect(targetRect);
    2304 
    2305         styleOptionArray[i] = option;
    2306     }
     1725    for (int i = 0; i < numItems; ++i)
     1726        itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], painterTransform, targetRect.toRect());
    23071727
    23081728    // Render the scene.
     
    23411761{
    23421762    Q_D(QGraphicsScene);
    2343     d->resetIndex();
     1763    if (d->indexMethod == method)
     1764        return;
     1765
    23441766    d->indexMethod = method;
     1767
     1768    QList<QGraphicsItem *> oldItems = d->index->items(Qt::DescendingOrder);
     1769    delete d->index;
     1770    if (method == BspTreeIndex)
     1771        d->index = new QGraphicsSceneBspTreeIndex(this);
     1772    else
     1773        d->index = new QGraphicsSceneLinearIndex(this);
     1774    for (int i = oldItems.size() - 1; i >= 0; --i)
     1775        d->index->addItem(oldItems.at(i));
    23451776}
    23461777
     
    23801811{
    23811812    Q_D(const QGraphicsScene);
    2382     return d->bspTreeDepth;
     1813    QGraphicsSceneBspTreeIndex *bspTree = qobject_cast<QGraphicsSceneBspTreeIndex *>(d->index);
     1814    return bspTree ? bspTree->bspTreeDepth() : 0;
    23831815}
    23841816void QGraphicsScene::setBspTreeDepth(int depth)
    23851817{
    23861818    Q_D(QGraphicsScene);
    2387     if (d->bspTreeDepth == depth)
    2388         return;
    2389 
    23901819    if (depth < 0) {
    23911820        qWarning("QGraphicsScene::setBspTreeDepth: invalid depth %d ignored; must be >= 0", depth);
     
    23931822    }
    23941823
    2395     d->bspTreeDepth = depth;
    2396     d->resetIndex();
     1824    QGraphicsSceneBspTreeIndex *bspTree = qobject_cast<QGraphicsSceneBspTreeIndex *>(d->index);
     1825    if (!bspTree) {
     1826        qWarning("QGraphicsScene::setBspTreeDepth: can not apply if indexing method is not BSP");
     1827        return;
     1828    }
     1829    bspTree->setBspTreeDepth(depth);
    23971830}
    23981831
     
    24011834    \brief whether sort caching is enabled
    24021835    \since 4.5
    2403 
    2404     When enabled, this property adds a cache that speeds up sorting and
    2405     transformations for scenes with deep hierarchies (i.e., items with many
    2406     levels of descendents), at the cost of using more memory (approx. 100 more
    2407     bytes of memory per item).
    2408 
    2409     Items that are not part of a deep hierarchy suffer no penalty from this
    2410     cache.
     1836    \obsolete
     1837
     1838    Since Qt 4.6, this property has no effect.
    24111839*/
    24121840bool QGraphicsScene::isSortCacheEnabled() const
     
    24181846{
    24191847    Q_D(QGraphicsScene);
    2420     if (enabled == d->sortCacheEnabled)
     1848    if (d->sortCacheEnabled == enabled)
    24211849        return;
    2422     if ((d->sortCacheEnabled = enabled))
    2423         d->invalidateSortCache();
     1850    d->sortCacheEnabled = enabled;
    24241851}
    24251852
     
    24331860QRectF QGraphicsScene::itemsBoundingRect() const
    24341861{
     1862    // Does not take untransformable items into account.
    24351863    QRectF boundingRect;
    24361864    foreach (QGraphicsItem *item, items())
     
    24401868
    24411869/*!
    2442     Returns a list of all items on the scene, in no particular order.
    2443 
    2444     \sa addItem(), removeItem()
     1870    Returns a list of all items in the scene in descending stacking order.
     1871
     1872    \sa addItem(), removeItem(), {QGraphicsItem#Sorting}{Sorting}
    24451873*/
    24461874QList<QGraphicsItem *> QGraphicsScene::items() const
    24471875{
    24481876    Q_D(const QGraphicsScene);
    2449     const_cast<QGraphicsScenePrivate *>(d)->purgeRemovedItems();
    2450 
    2451     // If freeItemIndexes is empty, we know there are no holes in indexedItems and
    2452     // unindexedItems.
    2453     if (d->freeItemIndexes.isEmpty()) {
    2454         if (d->unindexedItems.isEmpty())
    2455             return d->indexedItems;
    2456         return d->indexedItems + d->unindexedItems;
    2457     }
    2458 
    2459     // Rebuild the list of items to avoid holes. ### We could also just
    2460     // compress the item lists at this point.
    2461     QList<QGraphicsItem *> itemList;
    2462     foreach (QGraphicsItem *item, d->indexedItems + d->unindexedItems) {
    2463         if (item)
    2464             itemList << item;
    2465     }
    2466     return itemList;
    2467 }
    2468 
    2469 /*!
     1877    return d->index->items(Qt::DescendingOrder);
     1878}
     1879
     1880/*!
     1881    Returns an ordered list of all items on the scene. \a order decides the
     1882    stacking order.
     1883
     1884    \sa addItem(), removeItem(), {QGraphicsItem#Sorting}{Sorting}
     1885*/
     1886QList<QGraphicsItem *> QGraphicsScene::items(Qt::SortOrder order) const
     1887{
     1888    Q_D(const QGraphicsScene);
     1889    return d->index->items(order);
     1890}
     1891
     1892/*!
     1893    \obsolete
     1894
    24701895    Returns all visible items at position \a pos in the scene. The items are
    2471     listed in descending Z order (i.e., the first item in the list is the
     1896    listed in descending stacking order (i.e., the first item in the list is the
    24721897    top-most item, and the last item is the bottom-most item).
    24731898
    2474     \sa itemAt()
     1899    This function is deprecated and returns incorrect results if the scene
     1900    contains items that ignore transformations. Use the overload that takes
     1901    a QTransform instead.
     1902
     1903    \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
    24751904*/
    24761905QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const
    24771906{
    24781907    Q_D(const QGraphicsScene);
    2479     return d->items_helper(pos);
    2480 }
    2481 
    2482 
    2483 /*!
    2484     \fn QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSelectionMode mode) const
    2485 
     1908    return d->index->items(pos, Qt::IntersectsItemShape, Qt::DescendingOrder);
     1909}
     1910
     1911/*!
    24861912    \overload
     1913    \obsolete
    24871914
    24881915    Returns all visible items that, depending on \a mode, are either inside or
     
    24921919    exact shape intersects with or is contained by \a rectangle are returned.
    24931920
    2494     \sa itemAt()
    2495 */
    2496 QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode) const
     1921    This function is deprecated and returns incorrect results if the scene
     1922    contains items that ignore transformations. Use the overload that takes
     1923    a QTransform instead.
     1924
     1925    \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
     1926*/
     1927QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSelectionMode mode) const
    24971928{
    24981929    Q_D(const QGraphicsScene);
    2499     return d->items_helper(rect, mode, Qt::AscendingOrder);
     1930    return d->index->items(rectangle, mode, Qt::DescendingOrder);
    25001931}
    25011932
    25021933/*!
    25031934    \fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode) const
     1935    \obsolete
    25041936    \since 4.3
    25051937
    25061938    This convenience function is equivalent to calling items(QRectF(\a x, \a y, \a w, \a h), \a mode).
    2507 */
    2508 
    2509 /*!
     1939   
     1940    This function is deprecated and returns incorrect results if the scene
     1941    contains items that ignore transformations. Use the overload that takes
     1942    a QTransform instead.
     1943*/
     1944
     1945/*!
     1946    \fn QList<QGraphicsItem *> QGraphicsScene::items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const
    25101947    \overload
     1948    \since 4.6
     1949
     1950    \brief Returns all visible items that, depending on \a mode, are
     1951    either inside or intersect with the rectangle defined by \a x, \a y,
     1952    \a w and \a h, in a list sorted using \a order.
     1953
     1954    \a deviceTransform is the transformation that applies to the view, and needs to
     1955    be provided if the scene contains items that ignore transformations.
     1956*/
     1957
     1958/*!
     1959    \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode) const
     1960    \overload
     1961    \obsolete
    25111962
    25121963    Returns all visible items that, depending on \a mode, are either inside or
     
    25161967    exact shape intersects with or is contained by \a polygon are returned.
    25171968
    2518     \sa itemAt()
     1969    This function is deprecated and returns incorrect results if the scene
     1970    contains items that ignore transformations. Use the overload that takes
     1971    a QTransform instead.
     1972
     1973    \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
    25191974*/
    25201975QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode) const
    25211976{
    25221977    Q_D(const QGraphicsScene);
    2523     return d->items_helper(polygon, mode, Qt::AscendingOrder);
    2524 }
    2525 
    2526 /*!
     1978    return d->index->items(polygon, mode, Qt::DescendingOrder);
     1979}
     1980
     1981/*!
     1982    \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const
    25271983    \overload
     1984    \obsolete
    25281985
    25291986    Returns all visible items that, depending on \a path, are either inside or
     
    25331990    exact shape intersects with or is contained by \a path are returned.
    25341991
    2535     \sa itemAt()
     1992    This function is deprecated and returns incorrect results if the scene
     1993    contains items that ignore transformations. Use the overload that takes
     1994    a QTransform instead.
     1995
     1996    \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
    25361997*/
    25371998QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const
    25381999{
    25392000    Q_D(const QGraphicsScene);
    2540     return d->items_helper(path, mode, Qt::AscendingOrder);
     2001    return d->index->items(path, mode, Qt::DescendingOrder);
     2002}
     2003
     2004/*!
     2005    \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const
     2006    \since 4.6
     2007
     2008    \brief Returns all visible items that, depending on \a mode, are at
     2009    the specified \a pos in a list sorted using \a order.
     2010
     2011    The default value for \a mode is Qt::IntersectsItemShape; all items whose
     2012    exact shape intersects with \a pos are returned.
     2013
     2014    \a deviceTransform is the transformation that applies to the view, and needs to
     2015    be provided if the scene contains items that ignore transformations.
     2016
     2017    \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
     2018*/
     2019QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos, Qt::ItemSelectionMode mode,
     2020                                             Qt::SortOrder order, const QTransform &deviceTransform) const
     2021{
     2022    Q_D(const QGraphicsScene);
     2023    return d->index->items(pos, mode, order, deviceTransform);
     2024}
     2025
     2026/*!
     2027    \fn QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const
     2028    \overload
     2029    \since 4.6
     2030
     2031    \brief Returns all visible items that, depending on \a mode, are
     2032    either inside or intersect with the specified \a rect and return a
     2033    list sorted using \a order.
     2034
     2035    The default value for \a mode is Qt::IntersectsItemShape; all items whose
     2036    exact shape intersects with or is contained by \a rect are returned.
     2037
     2038    \a deviceTransform is the transformation that applies to the view, and needs to
     2039    be provided if the scene contains items that ignore transformations.
     2040
     2041    \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
     2042*/
     2043QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode,
     2044                                             Qt::SortOrder order, const QTransform &deviceTransform) const
     2045{
     2046    Q_D(const QGraphicsScene);
     2047    return d->index->items(rect, mode, order, deviceTransform);
     2048}
     2049
     2050/*!
     2051    \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const
     2052    \overload
     2053    \since 4.6
     2054
     2055    \brief Returns all visible items that, depending on \a mode, are
     2056    either inside or intersect with the specified \a polygon and return
     2057    a list sorted using \a order.
     2058
     2059    The default value for \a mode is Qt::IntersectsItemShape; all items whose
     2060    exact shape intersects with or is contained by \a polygon are returned.
     2061
     2062    \a deviceTransform is the transformation that applies to the view, and needs to
     2063    be provided if the scene contains items that ignore transformations.
     2064
     2065    \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
     2066*/
     2067QList<QGraphicsItem *> QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode,
     2068                                             Qt::SortOrder order, const QTransform &deviceTransform) const
     2069{
     2070    Q_D(const QGraphicsScene);
     2071    return d->index->items(polygon, mode, order, deviceTransform);
     2072}
     2073
     2074/*!
     2075    \fn QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const
     2076    \overload
     2077    \since 4.6
     2078
     2079    \brief Returns all visible items that, depending on \a mode, are
     2080    either inside or intersect with the specified \a path and return a
     2081    list sorted using \a order.
     2082
     2083    The default value for \a mode is Qt::IntersectsItemShape; all items whose
     2084    exact shape intersects with or is contained by \a path are returned.
     2085
     2086    \a deviceTransform is the transformation that applies to the view, and needs to
     2087    be provided if the scene contains items that ignore transformations.
     2088
     2089    \sa itemAt(), {QGraphicsItem#Sorting}{Sorting}
     2090*/
     2091QList<QGraphicsItem *> QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode,
     2092                                             Qt::SortOrder order, const QTransform &deviceTransform) const
     2093{
     2094    Q_D(const QGraphicsScene);
     2095    return d->index->items(path, mode, order, deviceTransform);
    25412096}
    25422097
     
    25472102    intersects \a item or is contained inside \a item's shape are returned.
    25482103
    2549     The items are returned in descending Z order (i.e., the first item in the
    2550     list is the top-most item, and the last item is the bottom-most item).
    2551 
    2552     \sa items(), itemAt(), QGraphicsItem::collidesWithItem()
     2104    The items are returned in descending stacking order (i.e., the first item
     2105    in the list is the uppermost item, and the last item is the lowermost
     2106    item).
     2107
     2108    \sa items(), itemAt(), QGraphicsItem::collidesWithItem(), {QGraphicsItem#Sorting}{Sorting}
    25532109*/
    25542110QList<QGraphicsItem *> QGraphicsScene::collidingItems(const QGraphicsItem *item,
     
    25612117    }
    25622118
     2119    // Does not support ItemIgnoresTransformations.
    25632120    QList<QGraphicsItem *> tmp;
    2564     foreach (QGraphicsItem *itemInVicinity, d->estimateItemsInRect(item->sceneBoundingRect())) {
     2121    foreach (QGraphicsItem *itemInVicinity, d->index->estimateItems(item->sceneBoundingRect(), Qt::DescendingOrder)) {
    25652122        if (item != itemInVicinity && item->collidesWithItem(itemInVicinity, mode))
    25662123            tmp << itemInVicinity;
    25672124    }
    2568     d->sortItems(&tmp, Qt::AscendingOrder, d->sortCacheEnabled);
    25692125    return tmp;
    25702126}
    25712127
    25722128/*!
    2573     \fn QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position) const
     2129    \overload
     2130    \obsolete
    25742131
    25752132    Returns the topmost visible item at the specified \a position, or 0 if
    25762133    there are no items at this position.
    25772134
    2578     \note The topmost item is the one with the highest Z-value.
    2579 
    2580     \sa items(), collidingItems(), QGraphicsItem::setZValue()
    2581 */
    2582 QGraphicsItem *QGraphicsScene::itemAt(const QPointF &pos) const
    2583 {
    2584     QList<QGraphicsItem *> itemsAtPoint = items(pos);
     2135    This function is deprecated and returns incorrect results if the scene
     2136    contains items that ignore transformations. Use the overload that takes
     2137    a QTransform instead.
     2138
     2139    \sa items(), collidingItems(), {QGraphicsItem#Sorting}{Sorting}
     2140*/
     2141QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position) const
     2142{
     2143    QList<QGraphicsItem *> itemsAtPoint = items(position);
    25852144    return itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first();
    25862145}
     2146
     2147/*!
     2148    \since 4.6
     2149
     2150    Returns the topmost visible item at the specified \a position, or 0
     2151    if there are no items at this position.
     2152
     2153    \a deviceTransform is the transformation that applies to the view, and needs to
     2154    be provided if the scene contains items that ignore transformations.
     2155
     2156    \sa items(), collidingItems(), {QGraphicsItem#Sorting}{Sorting}
     2157*/
     2158QGraphicsItem *QGraphicsScene::itemAt(const QPointF &position, const QTransform &deviceTransform) const
     2159{
     2160    QList<QGraphicsItem *> itemsAtPoint = items(position, Qt::IntersectsItemShape,
     2161                                                Qt::DescendingOrder, deviceTransform);
     2162    return itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first();
     2163}
     2164
     2165/*!
     2166    \fn QGraphicsScene::itemAt(qreal x, qreal y, const QTransform &deviceTransform) const
     2167    \overload
     2168    \since 4.6
     2169
     2170    Returns the topmost item at the position specified by (\a x, \a
     2171    y), or 0 if there are no items at this position.
     2172
     2173    \a deviceTransform is the transformation that applies to the view, and needs to
     2174    be provided if the scene contains items that ignore transformations.
     2175
     2176    This convenience function is equivalent to calling \c
     2177    {itemAt(QPointF(x, y), deviceTransform)}.
     2178*/
    25872179
    25882180/*!
    25892181    \fn QGraphicsScene::itemAt(qreal x, qreal y) const
    25902182    \overload
     2183    \obsolete
    25912184
    25922185    Returns the topmost item at the position specified by (\a x, \a
     
    25962189    {itemAt(QPointF(x, y))}.
    25972190
    2598     \note The topmost item is the one with the highest Z-value.
     2191    This function is deprecated and returns incorrect results if the scene
     2192    contains items that ignore transformations. Use the overload that takes
     2193    a QTransform instead.
    25992194*/
    26002195
     
    26362231
    26372232/*!
     2233    \since 4.6
     2234
    26382235    Sets the selection area to \a path. All items within this area are
    26392236    immediately selected, and all items outside are unselected. You can get
    26402237    the list of all selected items by calling selectedItems().
    26412238
     2239    \a deviceTransform is the transformation that applies to the view, and needs to
     2240    be provided if the scene contains items that ignore transformations.
     2241
    26422242    For an item to be selected, it must be marked as \e selectable
    26432243    (QGraphicsItem::ItemIsSelectable).
     
    26452245    \sa clearSelection(), selectionArea()
    26462246*/
     2247void QGraphicsScene::setSelectionArea(const QPainterPath &path, const QTransform &deviceTransform)
     2248{
     2249    setSelectionArea(path, Qt::IntersectsItemShape, deviceTransform);
     2250}
     2251
     2252/*!
     2253    \obsolete
     2254    \overload
     2255
     2256    Sets the selection area to \a path.
     2257
     2258    This function is deprecated and leads to incorrect results if the scene
     2259    contains items that ignore transformations. Use the overload that takes
     2260    a QTransform instead.
     2261*/
    26472262void QGraphicsScene::setSelectionArea(const QPainterPath &path)
    26482263{
    2649     setSelectionArea(path, Qt::IntersectsItemShape);
    2650 }
    2651 
    2652 /*!
     2264    setSelectionArea(path, Qt::IntersectsItemShape, QTransform());
     2265}
     2266
     2267/*!
     2268    \obsolete
    26532269    \overload
    26542270    \since 4.3
     
    26602276*/
    26612277void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode)
     2278{
     2279    setSelectionArea(path, mode, QTransform());
     2280}
     2281
     2282/*!
     2283    \overload
     2284    \since 4.6
     2285
     2286    Sets the selection area to \a path using \a mode to determine if items are
     2287    included in the selection area.
     2288
     2289    \a deviceTransform is the transformation that applies to the view, and needs to
     2290    be provided if the scene contains items that ignore transformations.
     2291
     2292    \sa clearSelection(), selectionArea()
     2293*/
     2294void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode,
     2295                                      const QTransform &deviceTransform)
    26622296{
    26632297    Q_D(QGraphicsScene);
     
    26762310
    26772311    // Set all items in path to selected.
    2678     foreach (QGraphicsItem *item, items(path, mode)) {
     2312    foreach (QGraphicsItem *item, items(path, mode, Qt::DescendingOrder, deviceTransform)) {
    26792313        if (item->flags() & QGraphicsItem::ItemIsSelectable) {
    26802314            if (!item->isSelected())
     
    27332367{
    27342368    Q_D(QGraphicsScene);
    2735     // Recursive descent delete
    2736     for (int i = 0; i < d->indexedItems.size(); ++i) {
    2737         if (QGraphicsItem *item = d->indexedItems.at(i)) {
    2738             if (!item->parentItem())
    2739                 delete item;
    2740         }
    2741     }
    2742     QList<QGraphicsItem *> unindexedParents;
    2743     for (int i = 0; i < d->unindexedItems.size(); ++i) {
    2744         QGraphicsItem *item = d->unindexedItems.at(i);
    2745         if (!item->parentItem())
    2746             unindexedParents << item;
    2747     }
    2748     d->unindexedItems.clear();
    2749     qDeleteAll(unindexedParents);
    2750 
    2751     d->indexedItems.clear();
    2752     d->freeItemIndexes.clear();
     2369    // NB! We have to clear the index before deleting items; otherwise the
     2370    // index might try to access dangling item pointers.
     2371    d->index->clear();
     2372    // NB! QGraphicsScenePrivate::unregisterTopLevelItem() removes items
     2373    while (!d->topLevelItems.isEmpty())
     2374        delete d->topLevelItems.first();
     2375    Q_ASSERT(d->topLevelItems.isEmpty());
    27532376    d->lastItemCount = 0;
    2754     d->bspTree.clear();
    2755     d->largestUntransformableItem = QRectF();
     2377    d->allItemsIgnoreHoverEvents = true;
     2378    d->allItemsUseDefaultCursor = true;
     2379    d->allItemsIgnoreTouchEvents = true;
    27562380}
    27572381
     
    28282452
    28292453/*!
    2830     Adds or moves the item \a item and all its childen to the scene.
     2454    Adds or moves the \a item and all its childen to this scene.
     2455    This scene takes ownership of the \a item.
    28312456
    28322457    If the item is visible (i.e., QGraphicsItem::isVisible() returns
     
    28342459    to the event loop.
    28352460
    2836     If the item is already in a different scene, it will first be removed from
    2837     its old scene, and then added to this scene as a top-level.
    2838 
    2839     QGraphicsScene will send ItemSceneChange notifications to \a item while
    2840     it is added to the scene. If item does not currently belong to a scene, only one
    2841     notification is sent. If it does belong to scene already (i.e., it is
    2842     moved to this scene), QGraphicsScene will send an addition notification as
    2843     the item is removed from its previous scene.
     2461    If the item is already in a different scene, it will first be
     2462    removed from its old scene, and then added to this scene as a
     2463    top-level.
     2464
     2465    QGraphicsScene will send ItemSceneChange notifications to \a item
     2466    while it is added to the scene. If item does not currently belong
     2467    to a scene, only one notification is sent. If it does belong to
     2468    scene already (i.e., it is moved to this scene), QGraphicsScene
     2469    will send an addition notification as the item is removed from its
     2470    previous scene.
     2471
     2472    If the item is a panel, the scene is active, and there is no
     2473    active panel in the scene, then the item will be activated.
    28442474
    28452475    \sa removeItem(), addEllipse(), addLine(), addPath(), addPixmap(),
    2846     addRect(), addText(), addWidget()
     2476    addRect(), addText(), addWidget(), {QGraphicsItem#Sorting}{Sorting}
    28472477*/
    28482478void QGraphicsScene::addItem(QGraphicsItem *item)
     
    28572487        return;
    28582488    }
    2859 
    28602489    // Remove this item from its existing scene
    28612490    if (QGraphicsScene *oldScene = item->scene())
     
    28732502    }
    28742503
    2875     // Prevent reusing a recently deleted pointer: purge all removed items
    2876     // from our lists.
    2877     d->purgeRemovedItems();
    2878 
    2879     // Invalidate any sort caching; arrival of a new item means we need to
    2880     // resort.
    2881     d->invalidateSortCache();
    2882 
    28832504    // Detach this item from its parent if the parent's scene is different
    28842505    // from this scene.
     
    28912512    item->d_func()->scene = targetScene;
    28922513
    2893     // Indexing requires sceneBoundingRect(), but because \a item might
    2894     // not be completely constructed at this point, we need to store it in
    2895     // a temporary list and schedule an indexing for later.
    2896     d->unindexedItems << item;
    2897     item->d_func()->index = -1;
    2898     d->startIndexTimer();
    2899 
    2900     // Update the scene's sort cache settings.
    2901     item->d_ptr->globalStackingOrder = -1;
    2902     d->invalidateSortCache();
     2514    // Add the item in the index
     2515    d->index->addItem(item);
     2516
     2517    // Add to list of toplevels if this item is a toplevel.
     2518    if (!item->d_ptr->parent)
     2519        d->registerTopLevelItem(item);
    29032520
    29042521    // Add to list of items that require an update. We cannot assume that the
    29052522    // item is fully constructed, so calling item->update() can lead to a pure
    29062523    // virtual function call to boundingRect().
    2907     if (!d->updateAll) {
    2908         if (d->pendingUpdateItems.isEmpty())
    2909             QMetaObject::invokeMethod(this, "_q_updateLater", Qt::QueuedConnection);
    2910         d->pendingUpdateItems << item;
    2911     }
     2524    d->markDirty(item);
     2525    d->dirtyGrowingItemsBoundingRect = true;
    29122526
    29132527    // Disable selectionChanged() for individual items
    29142528    ++d->selectionChanging;
    29152529    int oldSelectedItemSize = d->selectedItems.size();
     2530
     2531    // Enable mouse tracking if the item accepts hover events or has a cursor set.
     2532    if (d->allItemsIgnoreHoverEvents && d->itemAcceptsHoverEvents_helper(item)) {
     2533        d->allItemsIgnoreHoverEvents = false;
     2534        d->enableMouseTrackingOnViews();
     2535    }
     2536#ifndef QT_NO_CURSOR
     2537    if (d->allItemsUseDefaultCursor && item->hasCursor()) {
     2538        d->allItemsUseDefaultCursor = false;
     2539        if (d->allItemsIgnoreHoverEvents) // already enabled otherwise
     2540            d->enableMouseTrackingOnViews();
     2541    }
     2542#endif //QT_NO_CURSOR
     2543
     2544    // Enable touch events if the item accepts touch events.
     2545    if (d->allItemsIgnoreTouchEvents && item->acceptTouchEvents()) {
     2546        d->allItemsIgnoreTouchEvents = false;
     2547        d->enableTouchEventsOnViews();
     2548    }
    29162549
    29172550    // Update selection lists
     
    29202553    if (item->isWidget() && item->isVisible() && static_cast<QGraphicsWidget *>(item)->windowType() == Qt::Popup)
    29212554        d->addPopup(static_cast<QGraphicsWidget *>(item));
     2555    if (item->isPanel() && item->isVisible() && item->panelModality() != QGraphicsItem::NonModal)
     2556        d->enterModal(item);
    29222557
    29232558    // Update creation order focus chain. Make sure to leave the widget's
     
    29482583    item->d_ptr->resolvePalette(d->palette.resolve());
    29492584
    2950     if (!item->d_ptr->explicitlyHidden) {
    2951        if (d->unpolishedItems.isEmpty())
    2952            QMetaObject::invokeMethod(this, "_q_polishItems", Qt::QueuedConnection);
    2953        d->unpolishedItems << item;
    2954     }
     2585    if (d->unpolishedItems.isEmpty())
     2586        QMetaObject::invokeMethod(this, "_q_polishItems", Qt::QueuedConnection);
     2587    d->unpolishedItems.insert(item);
     2588    d->unpolishedItemsModified = true;
    29552589
    29562590    // Reenable selectionChanged() for individual items
     
    29612595    // Deliver post-change notification
    29622596    item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant);
     2597
     2598    // Update explicit activation
     2599    bool autoActivate = true;
     2600    if (!d->childExplicitActivation && item->d_ptr->explicitActivate)
     2601        d->childExplicitActivation = item->d_ptr->wantsActive ? 1 : 2;
     2602    if (d->childExplicitActivation && item->isPanel()) {
     2603        if (d->childExplicitActivation == 1)
     2604            setActivePanel(item);
     2605        else
     2606            autoActivate = false;
     2607        d->childExplicitActivation = 0;
     2608    } else if (!item->d_ptr->parent) {
     2609        d->childExplicitActivation = 0;
     2610    }
     2611
     2612    // Auto-activate this item's panel if nothing else has been activated
     2613    if (autoActivate) {
     2614        if (!d->lastActivePanel && !d->activePanel && item->isPanel()) {
     2615            if (isActive())
     2616                setActivePanel(item);
     2617            else
     2618                d->lastActivePanel = item;
     2619        }
     2620    }
     2621
     2622    if (item->flags() & QGraphicsItem::ItemSendsScenePositionChanges)
     2623        d->registerScenePosItem(item);
     2624
     2625    // Ensure that newly added items that have subfocus set, gain
     2626    // focus automatically if there isn't a focus item already.
     2627    if (!d->focusItem && item != d->lastFocusItem && item->focusItem() == item)
     2628        item->focusItem()->setFocus();
     2629
     2630    d->updateInputMethodSensitivityInViews();
    29632631}
    29642632
     
    32322900    }
    32332901
    3234     // If the item has focus, remove it (and any focusWidget reference).
    3235     item->clearFocus();
    3236 
    3237     // Clear its background
    3238     item->update();
    3239 
    3240     // Note: This will access item's sceneBoundingRect(), which (as this is
    3241     // C++) is why we cannot call removeItem() from QGraphicsItem's
    3242     // destructor.
    3243     d->removeFromIndex(item);
    3244 
    3245     if (item == d->tabFocusFirst) {
    3246         QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
    3247         widget->d_func()->fixFocusChainBeforeReparenting(0, 0);
    3248     }
    3249     // Set the item's scene ptr to 0.
    3250     item->d_func()->scene = 0;
    3251 
    3252     // Detach the item from its parent.
    3253     if (QGraphicsItem *parentItem = item->parentItem()) {
    3254         if (parentItem->scene()) {
    3255             Q_ASSERT_X(parentItem->scene() == this, "QGraphicsScene::removeItem",
    3256                        "Parent item's scene is different from this item's scene");
    3257             item->setParentItem(0);
    3258         }
    3259     }
    3260 
    3261     // Remove from our item lists.
    3262     int index = item->d_func()->index;
    3263     if (index != -1) {
    3264         d->freeItemIndexes << index;
    3265         d->indexedItems[index] = 0;
    3266     } else {
    3267         d->unindexedItems.removeAll(item);
    3268     }
    3269 
    3270     // Remove from scene transform cache
    3271     int transformIndex = item->d_func()->sceneTransformIndex;
    3272     if (transformIndex != -1) {
    3273         d->validTransforms.setBit(transformIndex, 0);
    3274         d->freeSceneTransformSlots.append(transformIndex);
    3275         item->d_func()->sceneTransformIndex = -1;
    3276     }
    3277 
    3278     if (item == d->focusItem)
    3279         d->focusItem = 0;
    3280     if (item == d->lastFocusItem)
    3281         d->lastFocusItem = 0;
    3282     if (item == d->activeWindow) {
    3283         // ### deactivate...
    3284         d->activeWindow = 0;
    3285     }
    3286 
    3287     // Disable selectionChanged() for individual items
    3288     ++d->selectionChanging;
    3289     int oldSelectedItemsSize = d->selectedItems.size();
    3290 
    3291     // Update selected & hovered item bookkeeping
    3292     d->selectedItems.remove(item);
    3293     d->hoverItems.removeAll(item);
    3294     d->pendingUpdateItems.removeAll(item);
    3295     d->cachedItemsUnderMouse.removeAll(item);
    3296     d->unpolishedItems.removeAll(item);
    3297     d->dirtyItems.removeAll(item);
    3298 
    3299     //We remove all references of item from the sceneEventFilter arrays
    3300     QMultiMap<QGraphicsItem*, QGraphicsItem*>::iterator iterator = d->sceneEventFilters.begin();
    3301     while (iterator != d->sceneEventFilters.end()) {
    3302         if (iterator.value() == item || iterator.key() == item)
    3303             iterator = d->sceneEventFilters.erase(iterator);
    3304         else
    3305             ++iterator;
    3306     }
    3307 
    3308 
    3309     //Ensure dirty flag have the correct default value so the next time it will be added it will receive updates
    3310     item->d_func()->dirty = 0;
    3311     item->d_func()->dirtyChildren = 0;
    3312 
    3313     // Remove all children recursively
    3314     foreach (QGraphicsItem *child, item->children())
    3315         removeItem(child);
    3316 
    3317     // Reset the mouse grabber and focus item data.
    3318     if (d->mouseGrabberItems.contains(item))
    3319         d->ungrabMouse(item);
    3320 
    3321     // Reset the keyboard grabber
    3322     if (d->keyboardGrabberItems.contains(item))
    3323         item->ungrabKeyboard();
    3324 
    3325     // Reset the last mouse grabber item
    3326     if (item == d->lastMouseGrabberItem)
    3327         d->lastMouseGrabberItem = 0;
    3328 
    3329     // Reenable selectionChanged() for individual items
    3330     --d->selectionChanging;
    3331 
    3332     if (!d->selectionChanging && d->selectedItems.size() != oldSelectedItemsSize)
    3333         emit selectionChanged();
     2902    d->removeItemHelper(item);
    33342903
    33352904    // Deliver post-change notification
    33362905    item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant);
    3337 }
    3338 
    3339 /*!
    3340     Returns the scene's current focus item, or 0 if no item currently has
    3341     focus.
     2906
     2907    d->updateInputMethodSensitivityInViews();
     2908}
     2909
     2910/*!
     2911    When the scene is active, this functions returns the scene's current focus
     2912    item, or 0 if no item currently has focus. When the scene is inactive, this
     2913    functions returns the item that will gain input focus when the scene becomes
     2914    active.
    33422915
    33432916    The focus item receives keyboard input when the scene receives a
    33442917    key event.
    33452918
    3346     \sa setFocusItem(), QGraphicsItem::hasFocus()
     2919    \sa setFocusItem(), QGraphicsItem::hasFocus(), isActive()
    33472920*/
    33482921QGraphicsItem *QGraphicsScene::focusItem() const
    33492922{
    33502923    Q_D(const QGraphicsScene);
    3351     return d->focusItem;
     2924    return isActive() ? d->focusItem : d->lastFocusItem;
    33522925}
    33532926
     
    33712944{
    33722945    Q_D(QGraphicsScene);
    3373     if (item == d->focusItem)
    3374         return;
    3375     if (item && (!(item->flags() & QGraphicsItem::ItemIsFocusable)
    3376                  || !item->isVisible() || !item->isEnabled())) {
    3377         item = 0;
    3378     }
    3379 
    3380     if (item) {
    3381         setFocus(focusReason);
    3382         if (item == d->focusItem)
    3383             return;
    3384     }
    3385 
    3386     if (d->focusItem) {
    3387         QFocusEvent event(QEvent::FocusOut, focusReason);
    3388         d->lastFocusItem = d->focusItem;
    3389         d->focusItem = 0;
    3390         d->sendEvent(d->lastFocusItem, &event);
    3391     }
    3392 
    3393     if (item) {
    3394         if (item->isWidget()) {
    3395             // Update focus child chain.
    3396             static_cast<QGraphicsWidget *>(item)->d_func()->setFocusWidget();
    3397         }
    3398 
    3399         d->focusItem = item;
    3400         QFocusEvent event(QEvent::FocusIn, focusReason);
    3401         d->sendEvent(item, &event);
    3402     }
     2946    if (item)
     2947        item->setFocus(focusReason);
     2948    else
     2949        d->setFocusItemHelper(item, focusReason);
    34032950}
    34042951
     
    34292976{
    34302977    Q_D(QGraphicsScene);
    3431     if (d->hasFocus)
     2978    if (d->hasFocus || !isActive())
    34322979        return;
    34332980    QFocusEvent event(QEvent::FocusIn, focusReason);
     
    34553002/*!
    34563003    \property QGraphicsScene::stickyFocus
    3457     \brief whether or not clicking the scene will clear focus
    3458 
    3459     If this property is false (the default), then clicking on the scene
    3460     background or on an item that does not accept focus, will clear
    3461     focus. Otherwise, focus will remain unchanged.
    3462 
    3463     The focus change happens in response to a mouse press. You can reimplement
     3004    \brief whether clicking into the scene background will clear focus
     3005
     3006    \since 4.6
     3007
     3008    In a QGraphicsScene with stickyFocus set to true, focus will remain
     3009    unchanged when the user clicks into the scene background or on an item
     3010    that does not accept focus. Otherwise, focus will be cleared.
     3011
     3012    By default, this property is false.
     3013
     3014    Focus changes in response to a mouse press. You can reimplement
    34643015    mousePressEvent() in a subclass of QGraphicsScene to toggle this property
    34653016    based on where the user has clicked.
     
    35843135{
    35853136    Q_D(const QGraphicsScene);
    3586     if (!d->focusItem)
     3137    if (!d->focusItem || !(d->focusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod))
    35873138        return QVariant();
    35883139    const QTransform matrix = d->focusItem->sceneTransform();
     
    36133164    // Check if anyone's connected; if not, we can send updates directly to
    36143165    // the views. Otherwise or if there are no views, use old behavior.
    3615     bool directUpdates = !(d->connectedSignals & d->changedSignalMask) && !d->views.isEmpty();
     3166    bool directUpdates = !(d->isSignalConnected(d->changedSignalIndex)) && !d->views.isEmpty();
    36163167    if (rect.isNull()) {
    36173168        d->updateAll = true;
     
    36203171            // Update all views.
    36213172            for (int i = 0; i < d->views.size(); ++i)
    3622                 d->views.at(i)->d_func()->updateAll();
     3173                d->views.at(i)->d_func()->fullUpdatePending = true;
    36233174        }
    36243175    } else {
     
    36343185    }
    36353186
    3636     if (!directUpdates && !d->calledEmitUpdated) {
     3187    if (!d->calledEmitUpdated) {
    36373188        d->calledEmitUpdated = true;
    36383189        QMetaObject::invokeMethod(this, "_q_emitUpdated", Qt::QueuedConnection);
     
    37453296    case QEvent::GraphicsSceneHoverLeave:
    37463297    case QEvent::GraphicsSceneHoverMove:
     3298    case QEvent::TouchBegin:
     3299    case QEvent::TouchUpdate:
     3300    case QEvent::TouchEnd:
    37473301        // Reset the under-mouse list to ensure that this event gets fresh
    37483302        // item-under-mouse data. Be careful about this list; if people delete
     
    37503304        // having stale pointers in it. We need to clear it before dispatching
    37513305        // events that use it.
     3306        // ### this should only be cleared if we received a new mouse move event,
     3307        // which relies on us fixing the replay mechanism in QGraphicsView.
    37523308        d->cachedItemsUnderMouse.clear();
    37533309    default:
     
    38053361        return false;
    38063362    case QEvent::GraphicsSceneMouseMove:
    3807         mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
     3363    {
     3364        QGraphicsSceneMouseEvent *mouseEvent = static_cast<QGraphicsSceneMouseEvent *>(event);
     3365        d->lastSceneMousePos = mouseEvent->scenePos();
     3366        mouseMoveEvent(mouseEvent);
    38083367        break;
     3368    }
    38093369    case QEvent::GraphicsSceneMousePress:
    38103370        mousePressEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
     
    38283388    case QEvent::GraphicsSceneHoverLeave:
    38293389    case QEvent::GraphicsSceneHoverMove:
    3830         d->dispatchHoverEvent(static_cast<QGraphicsSceneHoverEvent *>(event));
     3390    {
     3391        QGraphicsSceneHoverEvent *hoverEvent = static_cast<QGraphicsSceneHoverEvent *>(event);
     3392        d->lastSceneMousePos = hoverEvent->scenePos();
     3393        d->dispatchHoverEvent(hoverEvent);
    38313394        break;
     3395    }
    38323396    case QEvent::Leave:
    38333397        d->leaveScene();
     
    38393403        inputMethodEvent(static_cast<QInputMethodEvent *>(event));
    38403404        break;
    3841     case QEvent::WindowActivate: {
     3405    case QEvent::WindowActivate:
    38423406        if (!d->activationRefCount++) {
    3843             // Notify all non-window widgets.
    3844             foreach (QGraphicsItem *item, items()) {
    3845                 if (item->isWidget() && item->isVisible() && !item->isWindow() && !item->parentWidget()) {
    3846                     QEvent event(QEvent::WindowActivate);
    3847                     QApplication::sendEvent(static_cast<QGraphicsWidget *>(item), &event);
     3407            if (d->lastActivePanel) {
     3408                // Activate the last panel.
     3409                d->setActivePanelHelper(d->lastActivePanel, true);
     3410            } else if (d->tabFocusFirst && d->tabFocusFirst->isPanel()) {
     3411                // Activate the panel of the first item in the tab focus
     3412                // chain.
     3413                d->setActivePanelHelper(d->tabFocusFirst, true);
     3414            } else {
     3415                // Activate all toplevel items.
     3416                QEvent event(QEvent::WindowActivate);
     3417                foreach (QGraphicsItem *item, items()) {
     3418                    if (item->isVisible() && !item->isPanel() && !item->parentItem())
     3419                        sendEvent(item, &event);
    38483420                }
    38493421            }
    3850 
    3851             // Restore window activation.
    3852             QGraphicsItem *nextFocusItem = d->focusItem ? d->focusItem : d->lastFocusItem;
    3853             if (nextFocusItem && nextFocusItem->window())
    3854                 setActiveWindow(static_cast<QGraphicsWidget *>(nextFocusItem));
    3855             else if (d->tabFocusFirst && d->tabFocusFirst->isWindow())
    3856                 setActiveWindow(d->tabFocusFirst);
    38573422        }
    38583423        break;
    3859     }
    3860     case QEvent::WindowDeactivate: {
     3424    case QEvent::WindowDeactivate:
    38613425        if (!--d->activationRefCount) {
    3862             // Remove window activation.
    3863             setActiveWindow(0);
    3864 
    3865             // Notify all non-window widgets.
    3866             foreach (QGraphicsItem *item, items()) {
    3867                 if (item->isWidget() && item->isVisible() && !item->isWindow() && !item->parentWidget()) {
    3868                     QEvent event(QEvent::WindowDeactivate);
    3869                     QApplication::sendEvent(static_cast<QGraphicsWidget *>(item), &event);
     3426            if (d->activePanel) {
     3427                // Deactivate the active panel (but keep it so we can
     3428                // reactivate it later).
     3429                QGraphicsItem *lastActivePanel = d->activePanel;
     3430                d->setActivePanelHelper(0, true);
     3431                d->lastActivePanel = lastActivePanel;
     3432            } else {
     3433                // Activate all toplevel items.
     3434                QEvent event(QEvent::WindowDeactivate);
     3435                foreach (QGraphicsItem *item, items()) {
     3436                    if (item->isVisible() && !item->isPanel() && !item->parentItem())
     3437                        sendEvent(item, &event);
    38703438                }
    38713439            }
    38723440        }
    38733441        break;
    3874     }
    38753442    case QEvent::ApplicationFontChange: {
    38763443        // Resolve the existing scene font.
     
    38963463        update();
    38973464        break;
    3898     case QEvent::Timer:
    3899         if (d->indexTimerId && static_cast<QTimerEvent *>(event)->timerId() == d->indexTimerId) {
    3900             if (d->restartIndexTimer) {
    3901                 d->restartIndexTimer = false;
    3902             } else {
    3903                 // this call will kill the timer
    3904                 d->_q_updateIndex();
    3905             }
    3906         }
    3907         // Fallthrough intended - support timers in subclasses.
     3465    case QEvent::TouchBegin:
     3466    case QEvent::TouchUpdate:
     3467    case QEvent::TouchEnd:
     3468        d->touchEventHandler(static_cast<QTouchEvent *>(event));
     3469        break;
     3470    case QEvent::Gesture:
     3471    case QEvent::GestureOverride:
     3472        d->gestureEventHandler(static_cast<QGestureEvent *>(event));
     3473        break;
    39083474    default:
    39093475        return QObject::event(event);
     
    39253491    switch (event->type()) {
    39263492    case QEvent::ApplicationPaletteChange:
    3927         qApp->postEvent(this, new QEvent(QEvent::ApplicationPaletteChange));
     3493        QApplication::postEvent(this, new QEvent(QEvent::ApplicationPaletteChange));
    39283494        break;
    39293495    case QEvent::ApplicationFontChange:
    3930         qApp->postEvent(this, new QEvent(QEvent::ApplicationFontChange));
     3496        QApplication::postEvent(this, new QEvent(QEvent::ApplicationFontChange));
    39313497        break;
    39323498    default:
     
    41943760        point = helpEvent->screenPos();
    41953761    }
    4196     QToolTip::showText(point, text);
     3762    QToolTip::showText(point, text, helpEvent->widget());
    41973763    helpEvent->setAccepted(!text.isEmpty());
    41983764#endif
     
    42013767bool QGraphicsScenePrivate::itemAcceptsHoverEvents_helper(const QGraphicsItem *item) const
    42023768{
    4203     return item->acceptHoverEvents()
    4204         || (item->isWidget() && static_cast<const QGraphicsWidget *>(item)->d_func()->hasDecoration());
     3769    return (!item->isBlockedByModalPanel() &&
     3770            (item->acceptHoverEvents()
     3771             || (item->isWidget()
     3772                 && static_cast<const QGraphicsWidget *>(item)->d_func()->hasDecoration())));
    42053773}
    42063774
     
    42153783bool QGraphicsScenePrivate::dispatchHoverEvent(QGraphicsSceneHoverEvent *hoverEvent)
    42163784{
     3785    if (allItemsIgnoreHoverEvents)
     3786        return false;
     3787
    42173788    // Find the first item that accepts hover events, reusing earlier
    42183789    // calculated data is possible.
     
    42373808    while (commonAncestorItem && !itemAcceptsHoverEvents_helper(commonAncestorItem))
    42383809        commonAncestorItem = commonAncestorItem->parentItem();
    4239     if (commonAncestorItem && commonAncestorItem->window() != item->window()) {
    4240         // The common ancestor isn't in the same window as the two hovered
     3810    if (commonAncestorItem && commonAncestorItem->panel() != item->panel()) {
     3811        // The common ancestor isn't in the same panel as the two hovered
    42413812        // items.
    42423813        commonAncestorItem = 0;
     
    42593830    while (parent && parent != commonAncestorItem) {
    42603831        parents.prepend(parent);
    4261         if (parent->isWindow()) {
    4262             // Stop at the window - we don't deliver beyond this point.
     3832        if (parent->isPanel()) {
     3833            // Stop at the panel - we don't deliver beyond this point.
    42633834            break;
    42643835        }
     
    42733844
    42743845    // Generate a move event for the item itself
    4275     if (item && !hoverItems.isEmpty() && item == hoverItems.last()) {
     3846    if (item
     3847        && !hoverItems.isEmpty()
     3848        && item == hoverItems.last()) {
    42763849        sendHoverEvent(QEvent::GraphicsSceneHoverMove, item, hoverEvent);
    42773850        return true;
     
    42903863    Q_Q(QGraphicsScene);
    42913864#ifndef QT_NO_TOOLTIP
    4292     // Remove any tooltips
    4293     QToolTip::showText(QPoint(), QString());
     3865    QToolTip::hideText();
    42943866#endif
    42953867    // Send HoverLeave events to all existing hover items, topmost first.
     
    43083880    while (!hoverItems.isEmpty()) {
    43093881        QGraphicsItem *lastItem = hoverItems.takeLast();
    4310         if (lastItem->acceptHoverEvents()
    4311             || (lastItem->isWidget() && static_cast<QGraphicsWidget*>(lastItem)->d_func()->hasDecoration()))
     3882        if (itemAcceptsHoverEvents_helper(lastItem))
    43123883            sendHoverEvent(QEvent::GraphicsSceneHoverLeave, lastItem, &hoverEvent);
    43133884    }
     
    43363907            // Send it; QGraphicsItem::keyPressEvent ignores it.  If the event
    43373908            // is filtered out, stop propagating it.
     3909            if (p->isBlockedByModalPanel())
     3910                break;
    43383911            if (!d->sendEvent(p, keyEvent))
    43393912                break;
    4340         } while (!keyEvent->isAccepted() && !p->isWindow() && (p = p->parentItem()));
     3913        } while (!keyEvent->isAccepted() && !p->isPanel() && (p = p->parentItem()));
    43413914    } else {
    43423915        keyEvent->ignore();
     
    43663939            // Send it; QGraphicsItem::keyPressEvent ignores it.  If the event
    43673940            // is filtered out, stop propagating it.
     3941            if (p->isBlockedByModalPanel())
     3942                break;
    43683943            if (!d->sendEvent(p, keyEvent))
    43693944                break;
    4370         } while (!keyEvent->isAccepted() && !p->isWindow() && (p = p->parentItem()));
     3945        } while (!keyEvent->isAccepted() && !p->isPanel() && (p = p->parentItem()));
    43713946    } else {
    43723947        keyEvent->ignore();
     
    43943969{
    43953970    Q_D(QGraphicsScene);
     3971    if (d->mouseGrabberItems.isEmpty()) {
     3972        // Dispatch hover events
     3973        QGraphicsSceneHoverEvent hover;
     3974        _q_hoverFromMouseEvent(&hover, mouseEvent);
     3975        d->dispatchHoverEvent(&hover);
     3976    }
     3977
    43963978    d->mousePressEventHandler(mouseEvent);
    43973979}
     
    45114093    bool hasSetFocus = false;
    45124094    foreach (QGraphicsItem *item, wheelCandidates) {
    4513         if (!hasSetFocus && item->isEnabled() && (item->flags() & QGraphicsItem::ItemIsFocusable)) {
     4095        if (!hasSetFocus && item->isEnabled()
     4096            && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) {
    45144097            if (item->isWidget() && static_cast<QGraphicsWidget *>(item)->focusPolicy() == Qt::WheelFocus) {
    45154098                hasSetFocus = true;
     
    45224105                                                            wheelEvent->widget()));
    45234106        wheelEvent->accept();
    4524         bool isWindow = item->isWindow();
     4107        bool isPanel = item->isPanel();
    45254108        d->sendEvent(item, wheelEvent);
    4526         if (isWindow || wheelEvent->isAccepted())
     4109        if (isPanel || wheelEvent->isAccepted())
    45274110            break;
    45284111    }
     
    45344117
    45354118    The default implementation forwards the event to the focusItem().
    4536     If no item currently has focus, this function does nothing.
     4119    If no item currently has focus or the current focus item does not
     4120    accept input methods, this function does nothing.
    45374121
    45384122    \sa QGraphicsItem::inputMethodEvent()
     
    45414125{
    45424126    Q_D(QGraphicsScene);
    4543     if (!d->focusItem)
    4544         return;
    4545     d->sendEvent(d->focusItem, event);
     4127    if (d->focusItem && (d->focusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod))
     4128        d->sendEvent(d->focusItem, event);
    45464129}
    45474130
     
    46144197    const qreal oldPainterOpacity = painter->opacity();
    46154198
    4616     if (qFuzzyCompare(windowOpacity + 1, qreal(1.0)))
     4199    if (qFuzzyIsNull(windowOpacity))
    46174200        return;
    46184201    // Set new painter opacity.
     
    46514234
    46524235    // Don't use subpixmap if we get a full update.
    4653     if (pixmapExposed.isEmpty() || (pixmapExposed.numRects() == 1 && br.contains(pix->rect()))) {
     4236    if (pixmapExposed.isEmpty() || (pixmapExposed.rectCount() == 1 && br.contains(pix->rect()))) {
    46544237        pix->fill(Qt::transparent);
    46554238        pixmapPainter.begin(pix);
     
    46774260        // Blit the subpixmap into the main pixmap.
    46784261        pixmapPainter.begin(pix);
    4679         pixmapPainter.setCompositionMode(QPainter::CompositionMode_Source);
    46804262        pixmapPainter.setClipRegion(pixmapExposed);
    46814263        pixmapPainter.drawPixmap(br.topLeft(), subPix);
     
    46934275                                           bool painterStateProtection)
    46944276{
    4695     QGraphicsItemPrivate *itemd = item->d_ptr;
     4277    QGraphicsItemPrivate *itemd = item->d_ptr.data();
    46964278    QGraphicsItem::CacheMode cacheMode = QGraphicsItem::CacheMode(itemd->cacheMode);
    46974279
     
    47234305
    47244306    // Fetch the off-screen transparent buffer and exposed area info.
    4725     QString pixmapKey;
     4307    QPixmapCache::Key pixmapKey;
    47264308    QPixmap pix;
     4309    bool pixmapFound;
    47274310    QGraphicsItemCache *itemCache = itemd->extraItemCache();
    47284311    if (cacheMode == QGraphicsItem::ItemCoordinateCache) {
     
    47344317        pixmapKey = itemCache->key;
    47354318    } else {
    4736         if ((pixmapKey = itemCache->deviceData.value(widget).key).isEmpty()) {
    4737             pixmapKey.sprintf("qgv-%p-%p", item, widget);
    4738             QGraphicsItemCache::DeviceData data;
    4739             data.key = pixmapKey;
    4740             itemCache->deviceData.insert(widget, data);
    4741         }
     4319        pixmapKey = itemCache->deviceData.value(widget).key;
    47424320    }
    47434321
    47444322    // Find pixmap in cache.
    4745     if (!itemCache->allExposed)
    4746         QPixmapCache::find(pixmapKey, pix);
     4323    pixmapFound = QPixmapCache::find(pixmapKey, &pix);
    47474324
    47484325    // Render using item coordinate cache mode.
     
    47694346        // Redraw any newly exposed areas.
    47704347        if (itemCache->allExposed || !itemCache->exposed.isEmpty()) {
     4348
     4349            //We know that we will modify the pixmap, removing it from the cache
     4350            //will detach the one we have and avoid a deep copy
     4351            if (pixmapFound)
     4352                QPixmapCache::remove(pixmapKey);
     4353
    47714354            // Fit the item's bounding rect into the pixmap's coordinates.
    47724355            QTransform itemToPixmap;
     
    47794362            // Generate the item's exposedRect and map its list of expose
    47804363            // rects to device coordinates.
    4781             QStyleOptionGraphicsItem cacheOption = *option;
     4364            styleOptionTmp = *option;
    47824365            QRegion pixmapExposed;
    47834366            QRectF exposedRect;
     
    47914374                exposedRect = brect;
    47924375            }
    4793             cacheOption.exposedRect = exposedRect;
     4376            styleOptionTmp.exposedRect = exposedRect;
    47944377
    47954378            // Render.
    47964379            _q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(),
    4797                               &cacheOption, painterStateProtection);
    4798 
    4799             // Reinsert this pixmap into the cache.
    4800             QPixmapCache::insert(pixmapKey, pix);
     4380                              &styleOptionTmp, painterStateProtection);
     4381
     4382            // insert this pixmap into the cache.
     4383            itemCache->key = QPixmapCache::insert(pix);
    48014384
    48024385            // Reset expose data.
     
    48644447#else
    48654448        // Only if deviceRect is 20% taller or wider than the desktop.
    4866         QRect desktopRect = qApp->desktop()->availableGeometry(widget);
    4867         bool allowPartialCacheExposure = (desktopRect.width() * 1.2 < deviceRect.width()
    4868                                           || desktopRect.height() * 1.2 < deviceRect.height());
     4449        bool allowPartialCacheExposure = false;
     4450        if (widget) {
     4451            QRect desktopRect = QApplication::desktop()->availableGeometry(widget);
     4452            allowPartialCacheExposure = (desktopRect.width() * 1.2 < deviceRect.width()
     4453                                         || desktopRect.height() * 1.2 < deviceRect.height());
     4454        }
    48694455#endif
    48704456        QRegion scrollExposure;
     
    49254511        // Check for newly invalidated areas.
    49264512        if (itemCache->allExposed || !itemCache->exposed.isEmpty() || !scrollExposure.isEmpty()) {
     4513            //We know that we will modify the pixmap, removing it from the cache
     4514            //will detach the one we have and avoid a deep copy
     4515            if (pixmapFound)
     4516                QPixmapCache::remove(pixmapKey);
     4517
    49274518            // Construct an item-to-pixmap transform.
    49284519            QPointF p = deviceRect.topLeft();
     
    49514542                    br |= pixmapToItem.mapRect(r);
    49524543            }
    4953             QStyleOptionGraphicsItem cacheOption = *option;
    4954             cacheOption.exposedRect = br.adjusted(-1, -1, 1, 1);
     4544            styleOptionTmp = *option;
     4545            styleOptionTmp.exposedRect = br.adjusted(-1, -1, 1, 1);
    49554546
    49564547            // Render the exposed areas.
    49574548            _q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(),
    4958                               &cacheOption, painterStateProtection);
     4549                              &styleOptionTmp, painterStateProtection);
    49594550
    49604551            // Reset expose data.
     
    49654556
    49664557        if (pixModified) {
    4967             // Reinsert this pixmap into the cache
    4968             QPixmapCache::insert(pixmapKey, pix);
     4558            // Insert this pixmap into the cache.
     4559            deviceData->key = QPixmapCache::insert(pix);
    49694560        }
    49704561
     
    49854576}
    49864577
     4578void QGraphicsScenePrivate::drawItems(QPainter *painter, const QTransform *const viewTransform,
     4579                                      QRegion *exposedRegion, QWidget *widget)
     4580{
     4581    // Make sure we don't have unpolished items before we draw.
     4582    if (!unpolishedItems.isEmpty())
     4583        _q_polishItems();
     4584
     4585    QRectF exposedSceneRect;
     4586    if (exposedRegion && indexMethod != QGraphicsScene::NoIndex) {
     4587        exposedSceneRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1);
     4588        if (viewTransform)
     4589            exposedSceneRect = viewTransform->inverted().mapRect(exposedSceneRect);
     4590    }
     4591    const QList<QGraphicsItem *> tli = index->estimateTopLevelItems(exposedSceneRect, Qt::AscendingOrder);
     4592    for (int i = 0; i < tli.size(); ++i)
     4593        drawSubtreeRecursive(tli.at(i), painter, viewTransform, exposedRegion, widget);
     4594}
     4595
     4596void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter,
     4597                                                 const QTransform *const viewTransform,
     4598                                                 QRegion *exposedRegion, QWidget *widget,
     4599                                                 qreal parentOpacity, const QTransform *const effectTransform)
     4600{
     4601    Q_ASSERT(item);
     4602
     4603    if (!item->d_ptr->visible)
     4604        return;
     4605
     4606    const bool itemHasContents = !(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents);
     4607    const bool itemHasChildren = !item->d_ptr->children.isEmpty();
     4608    if (!itemHasContents && !itemHasChildren)
     4609        return; // Item has neither contents nor children!(?)
     4610
     4611    const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
     4612    const bool itemIsFullyTransparent = (opacity < 0.0001);
     4613    if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity()))
     4614        return;
     4615
     4616    QTransform transform(Qt::Uninitialized);
     4617    QTransform *transformPtr = 0;
     4618    bool translateOnlyTransform = false;
     4619#define ENSURE_TRANSFORM_PTR \
     4620    if (!transformPtr) { \
     4621        Q_ASSERT(!itemIsUntransformable); \
     4622        if (viewTransform) { \
     4623            transform = item->d_ptr->sceneTransform; \
     4624            transform *= *viewTransform; \
     4625            transformPtr = &transform; \
     4626        } else { \
     4627            transformPtr = &item->d_ptr->sceneTransform; \
     4628            translateOnlyTransform = item->d_ptr->sceneTransformTranslateOnly; \
     4629        } \
     4630    }
     4631
     4632    // Update the item's scene transform if the item is transformable;
     4633    // otherwise calculate the full transform,
     4634    bool wasDirtyParentSceneTransform = false;
     4635    const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable();
     4636    if (itemIsUntransformable) {
     4637        transform = item->deviceTransform(viewTransform ? *viewTransform : QTransform());
     4638        transformPtr = &transform;
     4639    } else if (item->d_ptr->dirtySceneTransform) {
     4640        item->d_ptr->updateSceneTransformFromParent();
     4641        Q_ASSERT(!item->d_ptr->dirtySceneTransform);
     4642        wasDirtyParentSceneTransform = true;
     4643    }
     4644
     4645    const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
     4646    bool drawItem = itemHasContents && !itemIsFullyTransparent;
     4647    if (drawItem) {
     4648        const QRectF brect = adjustedItemEffectiveBoundingRect(item);
     4649        ENSURE_TRANSFORM_PTR
     4650        QRect viewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy()).toRect()
     4651                                                        : transformPtr->mapRect(brect).toRect();
     4652        if (widget)
     4653            item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
     4654        viewBoundingRect.adjust(-1, -1, 1, 1);
     4655        drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect) : !viewBoundingRect.isEmpty();
     4656        if (!drawItem) {
     4657            if (!itemHasChildren)
     4658                return;
     4659            if (itemClipsChildrenToShape) {
     4660                if (wasDirtyParentSceneTransform)
     4661                    item->d_ptr->invalidateChildrenSceneTransform();
     4662                return;
     4663            }
     4664        }
     4665    } // else we know for sure this item has children we must process.
     4666
     4667    if (itemHasChildren && itemClipsChildrenToShape)
     4668        ENSURE_TRANSFORM_PTR;
     4669
     4670#ifndef QT_NO_GRAPHICSEFFECT
     4671    if (item->d_ptr->graphicsEffect && item->d_ptr->graphicsEffect->isEnabled()) {
     4672        ENSURE_TRANSFORM_PTR;
     4673        QGraphicsItemPaintInfo info(viewTransform, transformPtr, effectTransform, exposedRegion, widget, &styleOptionTmp,
     4674                                    painter, opacity, wasDirtyParentSceneTransform, drawItem);
     4675        QGraphicsEffectSource *source = item->d_ptr->graphicsEffect->d_func()->source;
     4676        QGraphicsItemEffectSourcePrivate *sourced = static_cast<QGraphicsItemEffectSourcePrivate *>
     4677                                                    (source->d_func());
     4678        sourced->info = &info;
     4679        const QTransform restoreTransform = painter->worldTransform();
     4680        if (effectTransform)
     4681            painter->setWorldTransform(*transformPtr * *effectTransform);
     4682        else
     4683            painter->setWorldTransform(*transformPtr);
     4684        painter->setOpacity(opacity);
     4685
     4686        if (sourced->currentCachedSystem() != Qt::LogicalCoordinates
     4687            && sourced->lastEffectTransform != painter->worldTransform())
     4688        {
     4689            sourced->lastEffectTransform = painter->worldTransform();
     4690            sourced->invalidateCache(QGraphicsEffectSourcePrivate::TransformChanged);
     4691        }
     4692
     4693        item->d_ptr->graphicsEffect->draw(painter);
     4694        painter->setWorldTransform(restoreTransform);
     4695        sourced->info = 0;
     4696    } else
     4697#endif //QT_NO_GRAPHICSEFFECT
     4698    {
     4699        draw(item, painter, viewTransform, transformPtr, exposedRegion, widget, opacity,
     4700             effectTransform, wasDirtyParentSceneTransform, drawItem);
     4701    }
     4702}
     4703
     4704void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const QTransform *const viewTransform,
     4705                                 const QTransform *const transformPtr, QRegion *exposedRegion, QWidget *widget,
     4706                                 qreal opacity, const QTransform *effectTransform,
     4707                                 bool wasDirtyParentSceneTransform, bool drawItem)
     4708{
     4709    const bool itemIsFullyTransparent = (opacity < 0.0001);
     4710    const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
     4711    const bool itemHasChildren = !item->d_ptr->children.isEmpty();
     4712
     4713    int i = 0;
     4714    if (itemHasChildren) {
     4715        item->d_ptr->ensureSortedChildren();
     4716
     4717        if (itemClipsChildrenToShape) {
     4718            painter->save();
     4719            Q_ASSERT(transformPtr);
     4720            if (effectTransform)
     4721                painter->setWorldTransform(*transformPtr * *effectTransform);
     4722            else
     4723                painter->setWorldTransform(*transformPtr);
     4724            painter->setClipPath(item->shape(), Qt::IntersectClip);
     4725        }
     4726
     4727        // Draw children behind
     4728        for (i = 0; i < item->d_ptr->children.size(); ++i) {
     4729            QGraphicsItem *child = item->d_ptr->children.at(i);
     4730            if (wasDirtyParentSceneTransform)
     4731                child->d_ptr->dirtySceneTransform = 1;
     4732            if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent))
     4733                break;
     4734            if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
     4735                continue;
     4736            drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform);
     4737        }
     4738    }
     4739
     4740    // Draw item
     4741    if (drawItem) {
     4742        Q_ASSERT(!itemIsFullyTransparent);
     4743        Q_ASSERT(!(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents));
     4744        Q_ASSERT(transformPtr);
     4745        item->d_ptr->initStyleOption(&styleOptionTmp, *transformPtr, exposedRegion
     4746                                     ? *exposedRegion : QRegion(), exposedRegion == 0);
     4747
     4748        const bool itemClipsToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsToShape;
     4749        const bool savePainter = itemClipsToShape || painterStateProtection;
     4750        if (savePainter)
     4751            painter->save();
     4752
     4753        if (!itemHasChildren || !itemClipsChildrenToShape) {
     4754            if (effectTransform)
     4755                painter->setWorldTransform(*transformPtr * *effectTransform);
     4756            else
     4757                painter->setWorldTransform(*transformPtr);
     4758        }
     4759
     4760        if (itemClipsToShape)
     4761            painter->setClipPath(item->shape(), Qt::IntersectClip);
     4762        painter->setOpacity(opacity);
     4763
     4764        if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget)
     4765            item->paint(painter, &styleOptionTmp, widget);
     4766        else
     4767            drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection);
     4768
     4769        if (savePainter)
     4770            painter->restore();
     4771    }
     4772
     4773    // Draw children in front
     4774    if (itemHasChildren) {
     4775        for (; i < item->d_ptr->children.size(); ++i) {
     4776            QGraphicsItem *child = item->d_ptr->children.at(i);
     4777            if (wasDirtyParentSceneTransform)
     4778                child->d_ptr->dirtySceneTransform = 1;
     4779            if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
     4780                continue;
     4781            drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform);
     4782        }
     4783    }
     4784
     4785    // Restore child clip
     4786    if (itemHasChildren && itemClipsChildrenToShape)
     4787        painter->restore();
     4788}
     4789
     4790void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, bool invalidateChildren,
     4791                                      bool force, bool ignoreOpacity, bool removingItemFromScene)
     4792{
     4793    Q_ASSERT(item);
     4794    if (updateAll)
     4795        return;
     4796
     4797    if (item->d_ptr->discardUpdateRequest(/*ignoreVisibleBit=*/force,
     4798                                          /*ignoreDirtyBit=*/removingItemFromScene || invalidateChildren,
     4799                                          /*ignoreOpacity=*/ignoreOpacity)) {
     4800        if (item->d_ptr->dirty) {
     4801            // The item is already marked as dirty and will be processed later. However,
     4802            // we have to make sure ignoreVisible and ignoreOpacity are set properly;
     4803            // otherwise things like: item->update(); item->hide() (force is now true)
     4804            // won't work as expected.
     4805            if (force)
     4806                item->d_ptr->ignoreVisible = 1;
     4807            if (ignoreOpacity)
     4808                item->d_ptr->ignoreOpacity = 1;
     4809        }
     4810        return;
     4811    }
     4812
     4813    const bool fullItemUpdate = rect.isNull();
     4814    if (!fullItemUpdate && rect.isEmpty())
     4815        return;
     4816
     4817    if (!processDirtyItemsEmitted) {
     4818        QMetaObject::invokeMethod(q_ptr, "_q_processDirtyItems", Qt::QueuedConnection);
     4819        processDirtyItemsEmitted = true;
     4820    }
     4821
     4822    if (removingItemFromScene) {
     4823        // Note that this function can be called from the item's destructor, so
     4824        // do NOT call any virtual functions on it within this block.
     4825        if (isSignalConnected(changedSignalIndex) || views.isEmpty()) {
     4826            // This block of code is kept for compatibility. Since 4.5, by default
     4827            // QGraphicsView does not connect the signal and we use the below
     4828            // method of delivering updates.
     4829            q_func()->update();
     4830            return;
     4831        }
     4832
     4833        for (int i = 0; i < views.size(); ++i) {
     4834            QGraphicsViewPrivate *viewPrivate = views.at(i)->d_func();
     4835            QRect rect = item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport);
     4836            rect.translate(viewPrivate->dirtyScrollOffset);
     4837            viewPrivate->updateRect(rect);
     4838        }
     4839        return;
     4840    }
     4841
     4842    bool hasNoContents = item->d_ptr->flags & QGraphicsItem::ItemHasNoContents
     4843                         && !item->d_ptr->graphicsEffect;
     4844    if (!hasNoContents) {
     4845        item->d_ptr->dirty = 1;
     4846        if (fullItemUpdate)
     4847            item->d_ptr->fullUpdatePending = 1;
     4848        else if (!item->d_ptr->fullUpdatePending)
     4849            item->d_ptr->needsRepaint |= rect;
     4850    }
     4851
     4852    if (invalidateChildren) {
     4853        item->d_ptr->allChildrenDirty = 1;
     4854        item->d_ptr->dirtyChildren = 1;
     4855    }
     4856
     4857    if (force)
     4858        item->d_ptr->ignoreVisible = 1;
     4859    if (ignoreOpacity)
     4860        item->d_ptr->ignoreOpacity = 1;
     4861
     4862    QGraphicsItem *p = item->d_ptr->parent;
     4863    while (p) {
     4864        p->d_ptr->dirtyChildren = 1;
     4865#ifndef QT_NO_GRAPHICSEFFECT
     4866        if (p->d_ptr->graphicsEffect && p->d_ptr->graphicsEffect->isEnabled()) {
     4867            p->d_ptr->dirty = 1;
     4868            p->d_ptr->fullUpdatePending = 1;
     4869        }
     4870#endif //QT_NO_GRAPHICSEFFECT
     4871        p = p->d_ptr->parent;
     4872    }
     4873}
     4874
     4875static inline bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item,
     4876                                const QRectF &rect, bool itemIsUntransformable)
     4877{
     4878    Q_ASSERT(view);
     4879    Q_ASSERT(item);
     4880
     4881    QGraphicsItem *itemq = static_cast<QGraphicsItem *>(item->q_ptr);
     4882    QGraphicsView *viewq = static_cast<QGraphicsView *>(view->q_ptr);
     4883
     4884    if (itemIsUntransformable) {
     4885        const QTransform xform = itemq->deviceTransform(viewq->viewportTransform());
     4886        if (!item->hasBoundingRegionGranularity)
     4887            return view->updateRect(xform.mapRect(rect).toRect());
     4888        return view->updateRegion(xform.map(QRegion(rect.toRect())));
     4889    }
     4890
     4891    if (item->sceneTransformTranslateOnly && view->identityMatrix) {
     4892        const qreal dx = item->sceneTransform.dx();
     4893        const qreal dy = item->sceneTransform.dy();
     4894        if (!item->hasBoundingRegionGranularity) {
     4895            QRectF r(rect);
     4896            r.translate(dx - view->horizontalScroll(), dy - view->verticalScroll());
     4897            return view->updateRect(r.toRect());
     4898        }
     4899        QRegion r(rect.toRect());
     4900        r.translate(qRound(dx) - view->horizontalScroll(), qRound(dy) - view->verticalScroll());
     4901        return view->updateRegion(r);
     4902    }
     4903
     4904    if (!viewq->isTransformed()) {
     4905        if (!item->hasBoundingRegionGranularity)
     4906            return view->updateRect(item->sceneTransform.mapRect(rect).toRect());
     4907        return view->updateRegion(item->sceneTransform.map(QRegion(rect.toRect())));
     4908    }
     4909
     4910    QTransform xform = item->sceneTransform;
     4911    xform *= viewq->viewportTransform();
     4912    if (!item->hasBoundingRegionGranularity)
     4913        return view->updateRect(xform.mapRect(rect).toRect());
     4914    return view->updateRegion(xform.map(QRegion(rect.toRect())));
     4915}
     4916
     4917void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren,
     4918                                                       qreal parentOpacity)
     4919{
     4920    Q_Q(QGraphicsScene);
     4921    Q_ASSERT(item);
     4922    Q_ASSERT(!updateAll);
     4923
     4924    if (!item->d_ptr->dirty && !item->d_ptr->dirtyChildren) {
     4925        resetDirtyItem(item);
     4926        return;
     4927    }
     4928
     4929    const bool itemIsHidden = !item->d_ptr->ignoreVisible && !item->d_ptr->visible;
     4930    if (itemIsHidden) {
     4931        resetDirtyItem(item, /*recursive=*/true);
     4932        return;
     4933    }
     4934
     4935    bool itemHasContents = !(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents);
     4936    const bool itemHasChildren = !item->d_ptr->children.isEmpty();
     4937    if (!itemHasContents) {
     4938        if (!itemHasChildren) {
     4939            resetDirtyItem(item);
     4940            return; // Item has neither contents nor children!(?)
     4941        }
     4942        if (item->d_ptr->graphicsEffect)
     4943            itemHasContents = true;
     4944    }
     4945
     4946    const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
     4947    const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity && opacity < 0.0001;
     4948    if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) {
     4949        resetDirtyItem(item, /*recursive=*/itemHasChildren);
     4950        return;
     4951    }
     4952
     4953    bool wasDirtyParentSceneTransform = item->d_ptr->dirtySceneTransform;
     4954    const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable();
     4955    if (wasDirtyParentSceneTransform && !itemIsUntransformable) {
     4956        item->d_ptr->updateSceneTransformFromParent();
     4957        Q_ASSERT(!item->d_ptr->dirtySceneTransform);
     4958    }
     4959
     4960    const bool wasDirtyParentViewBoundingRects = item->d_ptr->paintedViewBoundingRectsNeedRepaint;
     4961    if (itemIsFullyTransparent || !itemHasContents || dirtyAncestorContainsChildren) {
     4962        // Make sure we don't process invisible items or items with no content.
     4963        item->d_ptr->dirty = 0;
     4964        item->d_ptr->fullUpdatePending = 0;
     4965        // Might have a dirty view bounding rect otherwise.
     4966        if (itemIsFullyTransparent || !itemHasContents)
     4967            item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0;
     4968    }
     4969
     4970    if (!hasSceneRect && item->d_ptr->geometryChanged && item->d_ptr->visible) {
     4971        // Update growingItemsBoundingRect.
     4972        if (item->d_ptr->sceneTransformTranslateOnly) {
     4973            growingItemsBoundingRect |= item->boundingRect().translated(item->d_ptr->sceneTransform.dx(),
     4974                                                                        item->d_ptr->sceneTransform.dy());
     4975        } else {
     4976            growingItemsBoundingRect |= item->d_ptr->sceneTransform.mapRect(item->boundingRect());
     4977        }
     4978    }
     4979
     4980    // Process item.
     4981    if (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint) {
     4982        const bool useCompatUpdate = views.isEmpty() || isSignalConnected(changedSignalIndex);
     4983        const QRectF itemBoundingRect = adjustedItemEffectiveBoundingRect(item);
     4984
     4985        if (useCompatUpdate && !itemIsUntransformable && qFuzzyIsNull(item->boundingRegionGranularity())) {
     4986            // This block of code is kept for compatibility. Since 4.5, by default
     4987            // QGraphicsView does not connect the signal and we use the below
     4988            // method of delivering updates.
     4989            if (item->d_ptr->sceneTransformTranslateOnly) {
     4990                q->update(itemBoundingRect.translated(item->d_ptr->sceneTransform.dx(),
     4991                                                      item->d_ptr->sceneTransform.dy()));
     4992            } else {
     4993                q->update(item->d_ptr->sceneTransform.mapRect(itemBoundingRect));
     4994            }
     4995        } else {
     4996            QRectF dirtyRect;
     4997            bool uninitializedDirtyRect = true;
     4998
     4999            for (int j = 0; j < views.size(); ++j) {
     5000                QGraphicsView *view = views.at(j);
     5001                QGraphicsViewPrivate *viewPrivate = view->d_func();
     5002                QRect &paintedViewBoundingRect = item->d_ptr->paintedViewBoundingRects[viewPrivate->viewport];
     5003                if (viewPrivate->fullUpdatePending
     5004                    || viewPrivate->viewportUpdateMode == QGraphicsView::NoViewportUpdate) {
     5005                    // Okay, if we have a full update pending or no viewport update, this item's
     5006                    // paintedViewBoundingRect  will be updated correctly in the next paintEvent if
     5007                    // it is inside the viewport, but for now we can pretend that it is outside.
     5008                    paintedViewBoundingRect = QRect(-1, -1, -1, -1);
     5009                    continue;
     5010                }
     5011
     5012                if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) {
     5013                    paintedViewBoundingRect.translate(viewPrivate->dirtyScrollOffset);
     5014                    if (!viewPrivate->updateRect(paintedViewBoundingRect))
     5015                        paintedViewBoundingRect = QRect(-1, -1, -1, -1); // Outside viewport.
     5016                }
     5017
     5018                if (!item->d_ptr->dirty)
     5019                    continue;
     5020
     5021                if (!item->d_ptr->paintedViewBoundingRectsNeedRepaint
     5022                    && paintedViewBoundingRect.x() == -1 && paintedViewBoundingRect.y() == -1
     5023                    && paintedViewBoundingRect.width() == -1 && paintedViewBoundingRect.height() == -1) {
     5024                    continue; // Outside viewport.
     5025                }
     5026
     5027                if (uninitializedDirtyRect) {
     5028                    dirtyRect = itemBoundingRect;
     5029                    if (!item->d_ptr->fullUpdatePending) {
     5030                        _q_adjustRect(&item->d_ptr->needsRepaint);
     5031                        dirtyRect &= item->d_ptr->needsRepaint;
     5032                    }
     5033                    uninitializedDirtyRect = false;
     5034                }
     5035
     5036                if (dirtyRect.isEmpty())
     5037                    continue; // Discard updates outside the bounding rect.
     5038
     5039                if (!updateHelper(viewPrivate, item->d_ptr.data(), dirtyRect, itemIsUntransformable)
     5040                    && item->d_ptr->paintedViewBoundingRectsNeedRepaint) {
     5041                    paintedViewBoundingRect = QRect(-1, -1, -1, -1); // Outside viewport.
     5042                }
     5043            }
     5044        }
     5045    }
     5046
     5047    // Process children.
     5048    if (itemHasChildren && item->d_ptr->dirtyChildren) {
     5049        if (!dirtyAncestorContainsChildren) {
     5050            dirtyAncestorContainsChildren = item->d_ptr->fullUpdatePending
     5051                                            && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
     5052        }
     5053        const bool allChildrenDirty = item->d_ptr->allChildrenDirty;
     5054        const bool parentIgnoresVisible = item->d_ptr->ignoreVisible;
     5055        const bool parentIgnoresOpacity = item->d_ptr->ignoreOpacity;
     5056        for (int i = 0; i < item->d_ptr->children.size(); ++i) {
     5057            QGraphicsItem *child = item->d_ptr->children.at(i);
     5058            if (wasDirtyParentSceneTransform)
     5059                child->d_ptr->dirtySceneTransform = 1;
     5060            if (wasDirtyParentViewBoundingRects)
     5061                child->d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
     5062            if (parentIgnoresVisible)
     5063                child->d_ptr->ignoreVisible = 1;
     5064            if (parentIgnoresOpacity)
     5065                child->d_ptr->ignoreOpacity = 1;
     5066            if (allChildrenDirty) {
     5067                child->d_ptr->dirty = 1;
     5068                child->d_ptr->fullUpdatePending = 1;
     5069                child->d_ptr->dirtyChildren = 1;
     5070                child->d_ptr->allChildrenDirty = 1;
     5071            }
     5072            processDirtyItemsRecursive(child, dirtyAncestorContainsChildren, opacity);
     5073        }
     5074    } else if (wasDirtyParentSceneTransform) {
     5075        item->d_ptr->invalidateChildrenSceneTransform();
     5076    }
     5077
     5078    resetDirtyItem(item);
     5079}
     5080
    49875081/*!
    49885082    Paints the given \a items using the provided \a painter, after the
     
    49905084    drawn.  All painting is done in \e scene coordinates. Before
    49915085    drawing each item, the painter must be transformed using
    4992     QGraphicsItem::sceneMatrix().
     5086    QGraphicsItem::sceneTransform().
    49935087
    49945088    The \a options parameter is the list of style option objects for
     
    50085102    \snippet doc/src/snippets/graphicssceneadditemsnippet.cpp 0
    50095103
     5104    \obsolete Since Qt 4.6, this function is not called anymore unless
     5105    the QGraphicsView::IndirectPainting flag is given as an Optimization
     5106    flag.
     5107
    50105108    \sa drawBackground(), drawForeground()
    50115109*/
     
    50165114{
    50175115    Q_D(QGraphicsScene);
    5018 
    5019     // Detect if painter state protection is disabled.
     5116    // Make sure we don't have unpolished items before we draw.
     5117    if (!d->unpolishedItems.isEmpty())
     5118        d->_q_polishItems();
     5119
    50205120    QTransform viewTransform = painter->worldTransform();
    5021     QVarLengthArray<QGraphicsItem *, 16> childClippers;
    5022 
     5121    Q_UNUSED(options);
     5122
     5123    // Determine view, expose and flags.
     5124    QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0;
     5125    QRegion *expose = 0;
     5126    if (view)
     5127        expose = &view->d_func()->exposedRegion;
     5128
     5129    // Find all toplevels, they are already sorted.
     5130    QList<QGraphicsItem *> topLevelItems;
    50235131    for (int i = 0; i < numItems; ++i) {
    5024         QGraphicsItem *item = items[i];
    5025         if (!(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) {
    5026             if (!childClippers.isEmpty()) {
    5027                 // Item is not clipped to any ancestor: pop all current clippers.
    5028                 for (int i = 0; i < childClippers.size(); ++i)
    5029                     painter->restore();
    5030                 childClippers.clear();
    5031             }
    5032         } else {
    5033             // Item is clipped to an ancestor, which may or may not be in our
    5034             // child clipper list. Let's start by finding the item's closest
    5035             // clipping ancestor.
    5036             QGraphicsItem *clipParent = item->parentItem();
    5037             while (clipParent && !(clipParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape))
    5038                 clipParent = clipParent->parentItem();
    5039 
    5040             // Pop any in-between clippers. If the clipper is unknown, pop
    5041             // them all.  ### QVarLengthArray::lastIndexOf().
    5042             int index = -1;
    5043             for (int n = childClippers.size() - 1; n >= 0; --n) {
    5044                 if (childClippers[n] == clipParent) {
    5045                     index = n;
    5046                     break;
    5047                 }
    5048             }
    5049             if (index != -1) {
    5050                 int toPop = childClippers.size() - index - 1;
    5051                 if (toPop > 0) {
    5052                     for (int i = 0; i < toPop; ++i)
    5053                         painter->restore();
    5054                     childClippers.resize(index + 1);
    5055                 }
    5056             }
    5057 
    5058             // Sanity check
    5059             if (!childClippers.isEmpty())
    5060                 Q_ASSERT(childClippers[childClippers.size() - 1] == clipParent);
    5061 
    5062             // If the clipper list is empty at this point, but we're still
    5063             // clipped to an ancestor, then we need to build the clip chain
    5064             // ourselves. There is only one case that can produce this issue:
    5065             // This item is stacked behind an ancestor:
    5066             // ItemStacksBehindParent.
    5067             if (childClippers.isEmpty()) {
    5068                 Q_ASSERT(clipParent != 0);
    5069                 // Build a stack of clippers.
    5070                 QVarLengthArray<QGraphicsItem *, 16> clippers;
    5071                 QGraphicsItem *p = clipParent;
    5072                 do {
    5073                     if (p->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)
    5074                         clippers.append(p);
    5075                 } while ((p = p->parentItem()) && (p->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren));
    5076 
    5077                 // ### This code path can also use the itemTransform
    5078                 // optimization, but it's hit very rarely.
    5079                 for (int i = clippers.size() - 1; i >= 0; --i) {
    5080                     QGraphicsItem *clipper = clippers[i];
    5081                     if (clipper->d_ptr->itemIsUntransformable()) {
    5082                         painter->setWorldTransform(clipper->deviceTransform(viewTransform), false);
    5083                     } else {
    5084                         painter->setWorldTransform(clipper->sceneTransform() * viewTransform, false);
    5085                     }
    5086 
    5087                     childClippers.append(clipper);
    5088                     painter->save();
    5089                     painter->setClipPath(clipper->shape(), Qt::IntersectClip);
    5090                 }
    5091                 Q_ASSERT(childClippers[childClippers.size() - 1] == clipParent);
    5092             }
    5093         }
    5094 
    5095         // Set up the painter transform
    5096         if (item->d_ptr->itemIsUntransformable()) {
    5097             painter->setWorldTransform(item->deviceTransform(viewTransform), false);
    5098         } else {
    5099             painter->setWorldTransform(item->sceneTransform() * viewTransform, false);
    5100         }
    5101        
    5102         // Save painter
    5103         bool saveState = (d->painterStateProtection || (item->flags() & QGraphicsItem::ItemClipsToShape));
    5104         if (saveState)
    5105             painter->save();
    5106 
    5107         // Set local clip
    5108         if (item->flags() & QGraphicsItem::ItemClipsToShape)
    5109             painter->setClipPath(item->shape(), Qt::IntersectClip);
    5110 
    5111         // Setup opacity
    5112         painter->setOpacity(item->effectiveOpacity());
    5113 
    5114         // Draw the item
    5115         d->drawItemHelper(item, painter, &options[i], widget, d->painterStateProtection);
    5116 
    5117         if (saveState)
    5118             painter->restore();
    5119 
    5120         if (item->flags() & QGraphicsItem::ItemClipsChildrenToShape) {
    5121             // Clip descendents to this item's shape, and keep the painter
    5122             // saved.
    5123             childClippers.append(item);
    5124             painter->save();
    5125             painter->setClipPath(item->shape(), Qt::IntersectClip);
    5126         }
    5127     }
    5128 
    5129     for (int i = 0; i < childClippers.size(); ++i)
    5130         painter->restore();
     5132        QGraphicsItem *item = items[i]->topLevelItem();
     5133        if (!item->d_ptr->itemDiscovered) {
     5134            topLevelItems << item;
     5135            item->d_ptr->itemDiscovered = 1;
     5136            d->drawSubtreeRecursive(item, painter, &viewTransform, expose, widget);
     5137        }
     5138    }
     5139
     5140    // Reset discovery bits.
     5141    for (int i = 0; i < topLevelItems.size(); ++i)
     5142        topLevelItems.at(i)->d_ptr->itemDiscovered = 0;
    51315143
    51325144    painter->setWorldTransform(viewTransform);
     
    51855197            && widget->isEnabled() && widget->isVisibleTo(0)
    51865198            && (widget->focusPolicy() & Qt::TabFocus)
    5187             && (!item || !item->isWindow() || item->isAncestorOf(widget))
     5199            && (!item || !item->isPanel() || item->isAncestorOf(widget))
    51885200            ) {
    51895201            setFocusItem(widget, next ? Qt::TabFocusReason : Qt::BacktabFocusReason);
     
    52405252
    52415253/*!
    5242     \internal
    5243 
    5244     This private function is called by QGraphicsItem, which is a friend of
    5245     QGraphicsScene. It is used by QGraphicsScene to record the rectangles that
    5246     need updating. It also launches a single-shot timer to ensure that
    5247     updated() will be emitted later.
    5248 
    5249     The \a item parameter is the item that changed, and \a rect is the
    5250     area of the item that changed given in item coordinates.
    5251 */
    5252 void QGraphicsScene::itemUpdated(QGraphicsItem *item, const QRectF &rect)
    5253 {
    5254     Q_D(QGraphicsScene);
    5255     // Deliver the actual update.
    5256     if (!d->updateAll) {
    5257         if (d->views.isEmpty() || ((d->connectedSignals & d->changedSignalMask) && !item->d_ptr->itemIsUntransformable()
    5258                                    && qFuzzyCompare(item->boundingRegionGranularity(), qreal(0.0)))) {
    5259             // This block of code is kept for compatibility. Since 4.5, by default
    5260             // QGraphicsView does not connect the signal and we use the below
    5261             // method of delivering updates.
    5262             update(item->sceneBoundingRect());
    5263         } else {
    5264             // ### Remove _q_adjustedRects().
    5265             QRectF boundingRect(adjustedItemBoundingRect(item));
    5266             if (!rect.isNull()) {
    5267                 QRectF adjustedRect(rect);
    5268                 _q_adjustRect(&adjustedRect);
    5269                 boundingRect &= adjustedRect;
    5270             }
    5271 
    5272             // Update each view directly.
    5273             for (int i = 0; i < d->views.size(); ++i)
    5274                 d->views.at(i)->d_func()->itemUpdated(item, boundingRect);
    5275         }
    5276     }
    5277     if (item->d_ptr->dirty) {
    5278         d->dirtyItems << item;
    5279         d->resetDirtyItemsLater();
    5280     }
    5281 
    5282     if (!item->isVisible())
    5283         return; // Hiding an item won't effect the largestUntransformableItem/sceneRect.
    5284 
    5285     // Update d->largestUntransformableItem by mapping this item's bounding
    5286     // rect back to the topmost untransformable item's untransformed
    5287     // coordinate system (which sort of equals the 1:1 coordinate system of an
    5288     // untransformed view).
    5289     if (item->d_ptr->itemIsUntransformable()) {
    5290         QGraphicsItem *parent = item;
    5291         while (parent && (parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorIgnoresTransformations))
    5292             parent = parent->parentItem();
    5293         d->largestUntransformableItem |= item->mapToItem(parent, item->boundingRect()).boundingRect();
    5294     }
    5295 
    5296     // Only track the automatically growing scene rect if the scene has no
    5297     // defined scene rect.
    5298     if (!d->hasSceneRect) {
    5299         QRectF oldGrowingItemsBoundingRect = d->growingItemsBoundingRect;
    5300         QRectF adjustedItemSceneBoundingRect(item->sceneBoundingRect());
    5301         _q_adjustRect(&adjustedItemSceneBoundingRect);
    5302         d->growingItemsBoundingRect |= adjustedItemSceneBoundingRect;
    5303         if (d->growingItemsBoundingRect != oldGrowingItemsBoundingRect)
    5304             emit sceneRectChanged(d->growingItemsBoundingRect);
    5305     }
    5306 }
    5307 
    5308 /*!
    53095254    \since 4.4
    53105255
     
    53185263    Q_D(const QGraphicsScene);
    53195264    // ### This function, and the use of styles in general, is non-reentrant.
    5320     return d->style ? d->style : qApp->style();
     5265    return d->style ? d->style : QApplication::style();
    53215266}
    53225267
     
    53955340{
    53965341    Q_D(QGraphicsScene);
    5397     QFont naturalFont = qApp->font();
     5342    QFont naturalFont = QApplication::font();
    53985343    naturalFont.resolve(0);
    53995344    QFont resolvedFont = font.resolve(naturalFont);
     
    54325377{
    54335378    Q_D(QGraphicsScene);
    5434     QPalette naturalPalette = qApp->palette();
     5379    QPalette naturalPalette = QApplication::palette();
    54355380    naturalPalette.resolve(0);
    54365381    QPalette resolvedPalette = palette.resolve(naturalPalette);
     
    54395384
    54405385/*!
     5386    \since 4.6
     5387
     5388    Returns true if the scene is active (e.g., it's viewed by
     5389    at least one QGraphicsView that is active); otherwise returns false.
     5390
     5391    \sa QGraphicsItem::isActive(), QWidget::isActiveWindow()
     5392*/
     5393bool QGraphicsScene::isActive() const
     5394{
     5395    Q_D(const QGraphicsScene);
     5396    return d->activationRefCount > 0;
     5397}
     5398
     5399/*!
     5400    \since 4.6
     5401    Returns the current active panel, or 0 if no panel is currently active.
     5402
     5403    \sa QGraphicsScene::setActivePanel()
     5404*/
     5405QGraphicsItem *QGraphicsScene::activePanel() const
     5406{
     5407    Q_D(const QGraphicsScene);
     5408    return d->activePanel;
     5409}
     5410
     5411/*!
     5412    \since 4.6
     5413    Activates \a item, which must be an item in this scene. You
     5414    can also pass 0 for \a item, in which case QGraphicsScene will
     5415    deactivate any currently active panel.
     5416
     5417    If the scene is currently inactive, \a item remains inactive until the
     5418    scene becomes active (or, ir \a item is 0, no item will be activated).
     5419
     5420    \sa activePanel(), isActive(), QGraphicsItem::isActive()
     5421*/
     5422void QGraphicsScene::setActivePanel(QGraphicsItem *item)
     5423{
     5424    Q_D(QGraphicsScene);
     5425    d->setActivePanelHelper(item, false);
     5426}
     5427
     5428/*!
    54415429    \since 4.4
    54425430
    5443     Returns the current active window, or 0 if there is no window is currently
     5431    Returns the current active window, or 0 if no window is currently
    54445432    active.
    54455433
     
    54495437{
    54505438    Q_D(const QGraphicsScene);
    5451     return d->activeWindow;
     5439    if (d->activePanel && d->activePanel->isWindow())
     5440        return static_cast<QGraphicsWidget *>(d->activePanel);
     5441    return 0;
    54525442}
    54535443
     
    54625452void QGraphicsScene::setActiveWindow(QGraphicsWidget *widget)
    54635453{
    5464     Q_D(QGraphicsScene);
    54655454    if (widget && widget->scene() != this) {
    54665455        qWarning("QGraphicsScene::setActiveWindow: widget %p must be part of this scene",
     
    54695458    }
    54705459
    5471     // Activate the widget's window.
    5472     QGraphicsWidget *window = widget ? widget->window() : 0;
    5473     if (window == d->activeWindow)
    5474         return;
    5475 
    5476     // Deactivate the last active window.
    5477     if (d->activeWindow) {
    5478         if (QGraphicsWidget *fw = d->activeWindow->focusWidget()) {
    5479             // Remove focus from the current focus item.
    5480             if (fw == focusItem())
    5481                 setFocusItem(0, Qt::ActiveWindowFocusReason);
    5482         }
    5483 
    5484         QEvent event(QEvent::WindowDeactivate);
    5485         QApplication::sendEvent(d->activeWindow, &event);
    5486     }
    5487 
    5488     // Update activate state.
    5489     d->activeWindow = window;
    5490     QEvent event(QEvent::ActivationChange);
    5491     QApplication::sendEvent(this, &event);
    5492 
    5493     // Activate
    5494     if (window) {
    5495         QEvent event(QEvent::WindowActivate);
    5496         QApplication::sendEvent(window, &event);
    5497 
     5460    // Activate the widget's panel (all windows are panels).
     5461    QGraphicsItem *panel = widget ? widget->panel() : 0;
     5462    setActivePanel(panel);
     5463
     5464    // Raise
     5465    if (panel) {
    54985466        QList<QGraphicsItem *> siblingWindows;
    5499         QGraphicsItem *parent = window->parentItem();
     5467        QGraphicsItem *parent = panel->parentItem();
    55005468        // Raise ### inefficient for toplevels
    55015469        foreach (QGraphicsItem *sibling, parent ? parent->children() : items()) {
    5502             if (sibling != window && sibling->isWidget()
    5503                 && static_cast<QGraphicsWidget *>(sibling)->isWindow()) {
     5470            if (sibling != panel && sibling->isWindow())
    55045471                siblingWindows << sibling;
    5505             }
    55065472        }
    55075473
    55085474        // Find the highest z value.
    5509         qreal z = window->zValue();
     5475        qreal z = panel->zValue();
    55105476        for (int i = 0; i < siblingWindows.size(); ++i)
    55115477            z = qMax(z, siblingWindows.at(i)->zValue());
     
    55135479        // This will probably never overflow.
    55145480        const qreal litt = qreal(0.001);
    5515         window->setZValue(z + litt);
    5516 
    5517         if (QGraphicsWidget *focusChild = window->focusWidget())
    5518             focusChild->setFocus(Qt::ActiveWindowFocusReason);
     5481        panel->setZValue(z + litt);
     5482    }
     5483}
     5484
     5485/*!
     5486    \since 4.6
     5487
     5488    Sends event \a event to item \a item through possible event filters.
     5489
     5490    The event is sent only if the item is enabled.
     5491
     5492    Returns \c false if the event was filtered or if the item is disabled.
     5493    Otherwise returns the value that was returned from the event handler.
     5494
     5495    \sa QGraphicsItem::sceneEvent(), QGraphicsItem::sceneEventFilter()
     5496*/
     5497bool QGraphicsScene::sendEvent(QGraphicsItem *item, QEvent *event)
     5498{
     5499    Q_D(QGraphicsScene);
     5500    if (!item) {
     5501        qWarning("QGraphicsScene::sendEvent: cannot send event to a null item");
     5502        return false;
     5503    }
     5504    if (item->scene() != this) {
     5505        qWarning("QGraphicsScene::sendEvent: item %p's scene (%p)"
     5506                 " is different from this scene (%p)",
     5507                 item, item->scene(), this);
     5508        return false;
     5509    }
     5510    return d->sendEvent(item, event);
     5511}
     5512
     5513void QGraphicsScenePrivate::addView(QGraphicsView *view)
     5514{
     5515    views << view;
     5516}
     5517
     5518void QGraphicsScenePrivate::removeView(QGraphicsView *view)
     5519{
     5520    views.removeAll(view);
     5521}
     5522
     5523void QGraphicsScenePrivate::updateTouchPointsForItem(QGraphicsItem *item, QTouchEvent *touchEvent)
     5524{
     5525    QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints();
     5526    for (int i = 0; i < touchPoints.count(); ++i) {
     5527        QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
     5528        touchPoint.setRect(item->mapFromScene(touchPoint.sceneRect()).boundingRect());
     5529        touchPoint.setStartPos(item->d_ptr->genericMapFromScene(touchPoint.startScenePos(), touchEvent->widget()));
     5530        touchPoint.setLastPos(item->d_ptr->genericMapFromScene(touchPoint.lastScenePos(), touchEvent->widget()));
     5531    }
     5532    touchEvent->setTouchPoints(touchPoints);
     5533}
     5534
     5535int QGraphicsScenePrivate::findClosestTouchPointId(const QPointF &scenePos)
     5536{
     5537    int closestTouchPointId = -1;
     5538    qreal closestDistance = qreal(0.);
     5539    foreach (const QTouchEvent::TouchPoint &touchPoint, sceneCurrentTouchPoints) {
     5540        qreal distance = QLineF(scenePos, touchPoint.scenePos()).length();
     5541        if (closestTouchPointId == -1|| distance < closestDistance) {
     5542            closestTouchPointId = touchPoint.id();
     5543            closestDistance = distance;
     5544        }
     5545    }
     5546    return closestTouchPointId;
     5547}
     5548
     5549void QGraphicsScenePrivate::touchEventHandler(QTouchEvent *sceneTouchEvent)
     5550{
     5551    typedef QPair<Qt::TouchPointStates, QList<QTouchEvent::TouchPoint> > StatesAndTouchPoints;
     5552    QHash<QGraphicsItem *, StatesAndTouchPoints> itemsNeedingEvents;
     5553
     5554    for (int i = 0; i < sceneTouchEvent->touchPoints().count(); ++i) {
     5555        const QTouchEvent::TouchPoint &touchPoint = sceneTouchEvent->touchPoints().at(i);
     5556
     5557        // update state
     5558        QGraphicsItem *item = 0;
     5559        if (touchPoint.state() == Qt::TouchPointPressed) {
     5560            if (sceneTouchEvent->deviceType() == QTouchEvent::TouchPad) {
     5561                // on touch-pad devices, send all touch points to the same item
     5562                item = itemForTouchPointId.isEmpty()
     5563                       ? 0
     5564                       : itemForTouchPointId.constBegin().value();
     5565            }
     5566
     5567            if (!item) {
     5568                // determine which item this touch point will go to
     5569                cachedItemsUnderMouse = itemsAtPosition(touchPoint.screenPos().toPoint(),
     5570                                                        touchPoint.scenePos(),
     5571                                                        sceneTouchEvent->widget());
     5572                item = cachedItemsUnderMouse.isEmpty() ? 0 : cachedItemsUnderMouse.first();
     5573            }
     5574
     5575            if (sceneTouchEvent->deviceType() == QTouchEvent::TouchScreen) {
     5576                // on touch-screens, combine this touch point with the closest one we find if it
     5577                // is a a direct descendent or ancestor (
     5578                int closestTouchPointId = findClosestTouchPointId(touchPoint.scenePos());
     5579                QGraphicsItem *closestItem = itemForTouchPointId.value(closestTouchPointId);
     5580                if (!item
     5581                    || (closestItem
     5582                        && (item->isAncestorOf(closestItem)
     5583                            || closestItem->isAncestorOf(item)))) {
     5584                    item = closestItem;
     5585                }
     5586            }
     5587            if (!item)
     5588                continue;
     5589
     5590            itemForTouchPointId.insert(touchPoint.id(), item);
     5591            sceneCurrentTouchPoints.insert(touchPoint.id(), touchPoint);
     5592        } else if (touchPoint.state() == Qt::TouchPointReleased) {
     5593            item = itemForTouchPointId.take(touchPoint.id());
     5594            if (!item)
     5595                continue;
     5596
     5597            sceneCurrentTouchPoints.remove(touchPoint.id());
     5598        } else {
     5599            item = itemForTouchPointId.value(touchPoint.id());
     5600            if (!item)
     5601                continue;
     5602            Q_ASSERT(sceneCurrentTouchPoints.contains(touchPoint.id()));
     5603            sceneCurrentTouchPoints[touchPoint.id()] = touchPoint;
     5604        }
     5605
     5606        StatesAndTouchPoints &statesAndTouchPoints = itemsNeedingEvents[item];
     5607        statesAndTouchPoints.first |= touchPoint.state();
     5608        statesAndTouchPoints.second.append(touchPoint);
     5609    }
     5610
     5611    if (itemsNeedingEvents.isEmpty()) {
     5612        sceneTouchEvent->accept();
     5613        return;
     5614    }
     5615
     5616    bool ignoreSceneTouchEvent = true;
     5617    QHash<QGraphicsItem *, StatesAndTouchPoints>::ConstIterator it = itemsNeedingEvents.constBegin();
     5618    const QHash<QGraphicsItem *, StatesAndTouchPoints>::ConstIterator end = itemsNeedingEvents.constEnd();
     5619    for (; it != end; ++it) {
     5620        QGraphicsItem *item = it.key();
     5621
     5622        (void) item->isBlockedByModalPanel(&item);
     5623
     5624        // determine event type from the state mask
     5625        QEvent::Type eventType;
     5626        switch (it.value().first) {
     5627        case Qt::TouchPointPressed:
     5628            // all touch points have pressed state
     5629            eventType = QEvent::TouchBegin;
     5630            break;
     5631        case Qt::TouchPointReleased:
     5632            // all touch points have released state
     5633            eventType = QEvent::TouchEnd;
     5634            break;
     5635        case Qt::TouchPointStationary:
     5636            // don't send the event if nothing changed
     5637            continue;
     5638        default:
     5639            // all other combinations
     5640            eventType = QEvent::TouchUpdate;
     5641            break;
     5642        }
     5643
     5644        QTouchEvent touchEvent(eventType);
     5645        touchEvent.setWidget(sceneTouchEvent->widget());
     5646        touchEvent.setDeviceType(sceneTouchEvent->deviceType());
     5647        touchEvent.setModifiers(sceneTouchEvent->modifiers());
     5648        touchEvent.setTouchPointStates(it.value().first);
     5649        touchEvent.setTouchPoints(it.value().second);
     5650
     5651        switch (touchEvent.type()) {
     5652        case QEvent::TouchBegin:
     5653        {
     5654            // if the TouchBegin handler recurses, we assume that means the event
     5655            // has been implicitly accepted and continue to send touch events
     5656            item->d_ptr->acceptedTouchBeginEvent = true;
     5657            bool res = sendTouchBeginEvent(item, &touchEvent)
     5658                       && touchEvent.isAccepted();
     5659            if (!res)
     5660                ignoreSceneTouchEvent = false;
     5661            break;
     5662        }
     5663        default:
     5664            if (item->d_ptr->acceptedTouchBeginEvent) {
     5665                updateTouchPointsForItem(item, &touchEvent);
     5666                (void) sendEvent(item, &touchEvent);
     5667                ignoreSceneTouchEvent = false;
     5668            }
     5669            break;
     5670        }
     5671    }
     5672    sceneTouchEvent->setAccepted(ignoreSceneTouchEvent);
     5673}
     5674
     5675bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEvent *touchEvent)
     5676{
     5677    Q_Q(QGraphicsScene);
     5678
     5679    if (cachedItemsUnderMouse.isEmpty() || cachedItemsUnderMouse.first() != origin) {
     5680        const QTouchEvent::TouchPoint &firstTouchPoint = touchEvent->touchPoints().first();
     5681        cachedItemsUnderMouse = itemsAtPosition(firstTouchPoint.screenPos().toPoint(),
     5682                                                firstTouchPoint.scenePos(),
     5683                                                touchEvent->widget());
     5684    }
     5685    Q_ASSERT(cachedItemsUnderMouse.first() == origin);
     5686
     5687    // Set focus on the topmost enabled item that can take focus.
     5688    bool setFocus = false;
     5689    foreach (QGraphicsItem *item, cachedItemsUnderMouse) {
     5690        if (item->isEnabled() && ((item->flags() & QGraphicsItem::ItemIsFocusable) && item->d_ptr->mouseSetsFocus)) {
     5691            if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) {
     5692                setFocus = true;
     5693                if (item != q->focusItem())
     5694                    q->setFocusItem(item, Qt::MouseFocusReason);
     5695                break;
     5696            }
     5697        }
     5698        if (item->isPanel())
     5699            break;
     5700    }
     5701
     5702    // If nobody could take focus, clear it.
     5703    if (!stickyFocus && !setFocus)
     5704        q->setFocusItem(0, Qt::MouseFocusReason);
     5705
     5706    bool res = false;
     5707    bool eventAccepted = touchEvent->isAccepted();
     5708    foreach (QGraphicsItem *item, cachedItemsUnderMouse) {
     5709        // first, try to deliver the touch event
     5710        updateTouchPointsForItem(item, touchEvent);
     5711        bool acceptTouchEvents = item->acceptTouchEvents();
     5712        touchEvent->setAccepted(acceptTouchEvents);
     5713        res = acceptTouchEvents && sendEvent(item, touchEvent);
     5714        eventAccepted = touchEvent->isAccepted();
     5715        if (itemForTouchPointId.value(touchEvent->touchPoints().first().id()) == 0) {
     5716            // item was deleted
     5717            item = 0;
     5718        } else {
     5719            item->d_ptr->acceptedTouchBeginEvent = (res && eventAccepted);
     5720        }
     5721        touchEvent->spont = false;
     5722        if (res && eventAccepted) {
     5723            // the first item to accept the TouchBegin gets an implicit grab.
     5724            for (int i = 0; i < touchEvent->touchPoints().count(); ++i) {
     5725                const QTouchEvent::TouchPoint &touchPoint = touchEvent->touchPoints().at(i);
     5726                itemForTouchPointId[touchPoint.id()] = item; // can be zero
     5727            }
     5728            break;
     5729        }
     5730        if (item && item->isPanel())
     5731            break;
     5732    }
     5733
     5734    touchEvent->setAccepted(eventAccepted);
     5735    return res;
     5736}
     5737
     5738void QGraphicsScenePrivate::enableTouchEventsOnViews()
     5739{
     5740    foreach (QGraphicsView *view, views)
     5741        view->viewport()->setAttribute(Qt::WA_AcceptTouchEvents, true);
     5742}
     5743
     5744void QGraphicsScenePrivate::updateInputMethodSensitivityInViews()
     5745{
     5746    for (int i = 0; i < views.size(); ++i)
     5747        views.at(i)->d_func()->updateInputMethodSensitivity();
     5748}
     5749
     5750void QGraphicsScenePrivate::enterModal(QGraphicsItem *panel, QGraphicsItem::PanelModality previousModality)
     5751{
     5752    Q_Q(QGraphicsScene);
     5753    Q_ASSERT(panel && panel->isPanel());
     5754
     5755    QGraphicsItem::PanelModality panelModality = panel->d_ptr->panelModality;
     5756    if (previousModality != QGraphicsItem::NonModal) {
     5757        // the panel is changing from one modality type to another... temporarily set it back so
     5758        // that blockedPanels is populated correctly
     5759        panel->d_ptr->panelModality = previousModality;
     5760    }
     5761
     5762    QSet<QGraphicsItem *> blockedPanels;
     5763    QList<QGraphicsItem *> items = q->items(); // ### store panels separately
     5764    for (int i = 0; i < items.count(); ++i) {
     5765        QGraphicsItem *item = items.at(i);
     5766        if (item->isPanel() && item->isBlockedByModalPanel())
     5767            blockedPanels.insert(item);
     5768    }
     5769    // blockedPanels contains all currently blocked panels
     5770
     5771    if (previousModality != QGraphicsItem::NonModal) {
     5772        // reset the modality to the proper value, since we changed it above
     5773        panel->d_ptr->panelModality = panelModality;
     5774        // remove this panel so that it will be reinserted at the front of the stack
     5775        modalPanels.removeAll(panel);
     5776    }
     5777
     5778    modalPanels.prepend(panel);
     5779
     5780    if (!hoverItems.isEmpty()) {
     5781        // send GraphicsSceneHoverLeave events to newly blocked hoverItems
     5782        QGraphicsSceneHoverEvent hoverEvent;
     5783        hoverEvent.setScenePos(lastSceneMousePos);
     5784        dispatchHoverEvent(&hoverEvent);
     5785    }
     5786
     5787    if (!mouseGrabberItems.isEmpty() && lastMouseGrabberItemHasImplicitMouseGrab) {
     5788        QGraphicsItem *item = mouseGrabberItems.last();
     5789        if (item->isBlockedByModalPanel())
     5790            ungrabMouse(item, /*itemIsDying =*/ false);
     5791    }
     5792
     5793    QEvent windowBlockedEvent(QEvent::WindowBlocked);
     5794    QEvent windowUnblockedEvent(QEvent::WindowUnblocked);
     5795    for (int i = 0; i < items.count(); ++i) {
     5796        QGraphicsItem *item = items.at(i);
     5797        if (item->isPanel()) {
     5798            if (!blockedPanels.contains(item) && item->isBlockedByModalPanel()) {
     5799                // send QEvent::WindowBlocked to newly blocked panels
     5800                sendEvent(item, &windowBlockedEvent);
     5801            } else if (blockedPanels.contains(item) && !item->isBlockedByModalPanel()) {
     5802                // send QEvent::WindowUnblocked to unblocked panels when downgrading
     5803                // a panel from SceneModal to PanelModal
     5804                sendEvent(item, &windowUnblockedEvent);
     5805            }
     5806        }
     5807    }
     5808}
     5809
     5810void QGraphicsScenePrivate::leaveModal(QGraphicsItem *panel)
     5811{
     5812    Q_Q(QGraphicsScene);
     5813    Q_ASSERT(panel && panel->isPanel());
     5814
     5815    QSet<QGraphicsItem *> blockedPanels;
     5816    QList<QGraphicsItem *> items = q->items(); // ### same as above
     5817    for (int i = 0; i < items.count(); ++i) {
     5818        QGraphicsItem *item = items.at(i);
     5819        if (item->isPanel() && item->isBlockedByModalPanel())
     5820            blockedPanels.insert(item);
     5821    }
     5822
     5823    modalPanels.removeAll(panel);
     5824
     5825    QEvent e(QEvent::WindowUnblocked);
     5826    for (int i = 0; i < items.count(); ++i) {
     5827        QGraphicsItem *item = items.at(i);
     5828        if (item->isPanel() && blockedPanels.contains(item) && !item->isBlockedByModalPanel())
     5829            sendEvent(item, &e);
     5830    }
     5831
     5832    // send GraphicsSceneHoverEnter events to newly unblocked items
     5833    QGraphicsSceneHoverEvent hoverEvent;
     5834    hoverEvent.setScenePos(lastSceneMousePos);
     5835    dispatchHoverEvent(&hoverEvent);
     5836}
     5837
     5838void QGraphicsScenePrivate::getGestureTargets(const QSet<QGesture *> &gestures,
     5839                                              QWidget *viewport,
     5840                                              QMap<Qt::GestureType, QGesture *> *conflictedGestures,
     5841                                              QList<QList<QGraphicsObject *> > *conflictedItems,
     5842                                              QHash<QGesture *, QGraphicsObject *> *normalGestures)
     5843{
     5844    foreach (QGesture *gesture, gestures) {
     5845        Qt::GestureType gestureType = gesture->gestureType();
     5846        if (gesture->hasHotSpot()) {
     5847            QPoint screenPos = gesture->hotSpot().toPoint();
     5848            QList<QGraphicsItem *> items = itemsAtPosition(screenPos, QPointF(), viewport);
     5849            QList<QGraphicsObject *> result;
     5850            for (int j = 0; j < items.size(); ++j) {
     5851                QGraphicsObject *item = items.at(j)->toGraphicsObject();
     5852                if (!item)
     5853                    continue;
     5854                QGraphicsItemPrivate *d = item->QGraphicsItem::d_func();
     5855                if (d->gestureContext.contains(gestureType)) {
     5856                    result.append(item);
     5857                }
     5858            }
     5859            DEBUG() << "QGraphicsScenePrivate::getGestureTargets:"
     5860                    << gesture << result;
     5861            if (result.size() == 1) {
     5862                normalGestures->insert(gesture, result.first());
     5863            } else if (!result.isEmpty()) {
     5864                conflictedGestures->insert(gestureType, gesture);
     5865                conflictedItems->append(result);
     5866            }
     5867        }
     5868    }
     5869}
     5870
     5871void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event)
     5872{
     5873    QWidget *viewport = event->widget();
     5874    if (!viewport)
     5875        return;
     5876    QList<QGesture *> allGestures = event->gestures();
     5877    DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
     5878            << "Delivering gestures:" <<  allGestures;
     5879
     5880    typedef QHash<QGraphicsObject *, QList<QGesture *> > GesturesPerItem;
     5881    GesturesPerItem gesturesPerItem;
     5882
     5883    QSet<QGesture *> startedGestures;
     5884    foreach (QGesture *gesture, allGestures) {
     5885        QGraphicsObject *target = gestureTargets.value(gesture, 0);
     5886        if (!target) {
     5887            // when we are not in started mode but don't have a target
     5888            // then the only one interested in gesture is the view/scene
     5889            if (gesture->state() == Qt::GestureStarted)
     5890                startedGestures.insert(gesture);
     5891        } else {
     5892            gesturesPerItem[target].append(gesture);
     5893        }
     5894    }
     5895
     5896    QMap<Qt::GestureType, QGesture *> conflictedGestures;
     5897    QList<QList<QGraphicsObject *> > conflictedItems;
     5898    QHash<QGesture *, QGraphicsObject *> normalGestures;
     5899    getGestureTargets(startedGestures, viewport, &conflictedGestures, &conflictedItems,
     5900                      &normalGestures);
     5901    DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
     5902            << "Conflicting gestures:" <<  conflictedGestures.values() << conflictedItems;
     5903    Q_ASSERT((conflictedGestures.isEmpty() && conflictedItems.isEmpty()) ||
     5904              (!conflictedGestures.isEmpty() && !conflictedItems.isEmpty()));
     5905
     5906    // gestures that were sent as override events, but no one accepted them
     5907    QHash<QGesture *, QGraphicsObject *> ignoredConflictedGestures;
     5908
     5909    // deliver conflicted gestures as override events first
     5910    while (!conflictedGestures.isEmpty() && !conflictedItems.isEmpty()) {
     5911        // get the topmost item to deliver the override event
     5912        Q_ASSERT(!conflictedItems.isEmpty());
     5913        Q_ASSERT(!conflictedItems.first().isEmpty());
     5914        QGraphicsObject *topmost = conflictedItems.first().first();
     5915        for (int i = 1; i < conflictedItems.size(); ++i) {
     5916            QGraphicsObject *item = conflictedItems.at(i).first();
     5917            if (qt_closestItemFirst(item, topmost)) {
     5918                topmost = item;
     5919            }
     5920        }
     5921        // get a list of gestures to send to the item
     5922        QList<Qt::GestureType> grabbedGestures =
     5923                topmost->QGraphicsItem::d_func()->gestureContext.keys();
     5924        QList<QGesture *> gestures;
     5925        for (int i = 0; i < grabbedGestures.size(); ++i) {
     5926            if (QGesture *g = conflictedGestures.value(grabbedGestures.at(i), 0)) {
     5927                gestures.append(g);
     5928                if (!ignoredConflictedGestures.contains(g))
     5929                    ignoredConflictedGestures.insert(g, topmost);
     5930            }
     5931        }
     5932
     5933        // send gesture override to the topmost item
     5934        QGestureEvent ev(gestures);
     5935        ev.t = QEvent::GestureOverride;
     5936        ev.setWidget(event->widget());
     5937        // mark event and individual gestures as ignored
     5938        ev.ignore();
     5939        foreach(QGesture *g, gestures)
     5940            ev.setAccepted(g, false);
     5941        DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
     5942                << "delivering override to"
     5943                << topmost << gestures;
     5944        sendEvent(topmost, &ev);
     5945        // mark all accepted gestures to deliver them as normal gesture events
     5946        foreach (QGesture *g, gestures) {
     5947            if (ev.isAccepted() || ev.isAccepted(g)) {
     5948                conflictedGestures.remove(g->gestureType());
     5949                gestureTargets.remove(g);
     5950                // add the gesture to the list of normal delivered gestures
     5951                normalGestures.insert(g, topmost);
     5952                DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
     5953                        << "override was accepted:"
     5954                        << g << topmost;
     5955                ignoredConflictedGestures.remove(g);
     5956            }
     5957        }
     5958        // remove the item that we've already delivered from the list
     5959        for (int i = 0; i < conflictedItems.size(); ) {
     5960            QList<QGraphicsObject *> &items = conflictedItems[i];
     5961            if (items.first() == topmost) {
     5962                items.removeFirst();
     5963                if (items.isEmpty()) {
     5964                    conflictedItems.removeAt(i);
     5965                    continue;
     5966                }
     5967            }
     5968            ++i;
     5969        }
     5970    }
     5971
     5972    // put back those started gestures that are not in the conflicted state
     5973    // and remember their targets
     5974    QHash<QGesture *, QGraphicsObject *>::const_iterator it = normalGestures.begin(),
     5975                                                          e = normalGestures.end();
     5976    for (; it != e; ++it) {
     5977        QGesture *g = it.key();
     5978        QGraphicsObject *receiver = it.value();
     5979        Q_ASSERT(!gestureTargets.contains(g));
     5980        gestureTargets.insert(g, receiver);
     5981        gesturesPerItem[receiver].append(g);
     5982    }
     5983    it = ignoredConflictedGestures.begin();
     5984    e = ignoredConflictedGestures.end();
     5985    for (; it != e; ++it) {
     5986        QGesture *g = it.key();
     5987        QGraphicsObject *receiver = it.value();
     5988        Q_ASSERT(!gestureTargets.contains(g));
     5989        gestureTargets.insert(g, receiver);
     5990        gesturesPerItem[receiver].append(g);
     5991    }
     5992
     5993    DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
     5994            << "Started gestures:" << normalGestures.keys()
     5995            << "All gestures:" << gesturesPerItem.values();
     5996
     5997    // deliver all events
     5998    QList<QGesture *> alreadyIgnoredGestures;
     5999    QHash<QGraphicsObject *, QSet<QGesture *> > itemIgnoredGestures;
     6000    QList<QGraphicsObject *> targetItems = gesturesPerItem.keys();
     6001    qSort(targetItems.begin(), targetItems.end(), qt_closestItemFirst);
     6002    for (int i = 0; i < targetItems.size(); ++i) {
     6003        QGraphicsObject *item = targetItems.at(i);
     6004        QList<QGesture *> gestures = gesturesPerItem.value(item);
     6005        // remove gestures that were already delivered once and were ignored
     6006        DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
     6007                << "already ignored gestures for item"
     6008                << item << ":" << itemIgnoredGestures.value(item);
     6009
     6010        if (itemIgnoredGestures.contains(item)) // don't deliver twice to the same item
     6011            continue;
     6012
     6013        QGraphicsItemPrivate *gid = item->QGraphicsItem::d_func();
     6014        foreach(QGesture *g, alreadyIgnoredGestures) {
     6015            QMap<Qt::GestureType, Qt::GestureFlags>::iterator contextit =
     6016                    gid->gestureContext.find(g->gestureType());
     6017            bool deliver = contextit != gid->gestureContext.end() &&
     6018                (g->state() == Qt::GestureStarted ||
     6019                 (contextit.value() & Qt::ReceivePartialGestures));
     6020            if (deliver)
     6021                gestures += g;
     6022        }
     6023        if (gestures.isEmpty())
     6024            continue;
     6025        DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
     6026                << "delivering to"
     6027                << item << gestures;
     6028        QGestureEvent ev(gestures);
     6029        ev.setWidget(event->widget());
     6030        sendEvent(item, &ev);
     6031        QSet<QGesture *> ignoredGestures;
     6032        foreach (QGesture *g, gestures) {
     6033            if (!ev.isAccepted() && !ev.isAccepted(g)) {
     6034                ignoredGestures.insert(g);
     6035            } else {
     6036                if (g->state() == Qt::GestureStarted)
     6037                    gestureTargets[g] = item;
     6038            }
     6039        }
     6040        if (!ignoredGestures.isEmpty()) {
     6041            // get a list of items under the (current) hotspot of each ignored
     6042            // gesture and start delivery again from the beginning
     6043            DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
     6044                    << "item has ignored the event, will propagate."
     6045                    << item << ignoredGestures;
     6046            itemIgnoredGestures[item] += ignoredGestures;
     6047            QMap<Qt::GestureType, QGesture *> conflictedGestures;
     6048            QList<QList<QGraphicsObject *> > itemsForConflictedGestures;
     6049            QHash<QGesture *, QGraphicsObject *> normalGestures;
     6050            getGestureTargets(ignoredGestures, viewport,
     6051                              &conflictedGestures, &itemsForConflictedGestures,
     6052                              &normalGestures);
     6053            QSet<QGraphicsObject *> itemsSet = targetItems.toSet();
     6054            for (int k = 0; k < itemsForConflictedGestures.size(); ++k)
     6055                itemsSet += itemsForConflictedGestures.at(k).toSet();
     6056            targetItems = itemsSet.toList();
     6057            qSort(targetItems.begin(), targetItems.end(), qt_closestItemFirst);
     6058            alreadyIgnoredGestures = conflictedGestures.values();
     6059            DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
     6060                    << "new targets:" << targetItems;
     6061            i = -1; // start delivery again
     6062            continue;
     6063        }
     6064    }
     6065    foreach (QGesture *g, startedGestures) {
     6066        if (g->gestureCancelPolicy() == QGesture::CancelAllInContext) {
     6067            DEBUG() << "lets try to cancel some";
     6068            // find gestures in context in Qt::GestureStarted or Qt::GestureUpdated state and cancel them
     6069            cancelGesturesForChildren(g, event->widget());
     6070        }
     6071    }
     6072
     6073    // forget about targets for gestures that have ended
     6074    foreach (QGesture *g, allGestures) {
     6075        switch (g->state()) {
     6076        case Qt::GestureFinished:
     6077        case Qt::GestureCanceled:
     6078            gestureTargets.remove(g);
     6079            break;
     6080        default:
     6081            break;
     6082        }
     6083    }
     6084}
     6085
     6086void QGraphicsScenePrivate::cancelGesturesForChildren(QGesture *original, QWidget *viewport)
     6087{
     6088    Q_ASSERT(original);
     6089    QGraphicsItem *originalItem = gestureTargets.value(original);
     6090    Q_ASSERT(originalItem);
     6091
     6092    // iterate over all active gestures and for each find the owner
     6093    // if the owner is part of our sub-hierarchy, cancel it.
     6094
     6095    QSet<QGesture *> canceledGestures;
     6096    QHash<QGesture *, QGraphicsObject *>::Iterator iter = gestureTargets.begin();
     6097    while (iter != gestureTargets.end()) {
     6098        QGraphicsObject *item = iter.value();
     6099        // note that we don't touch the gestures for our originalItem
     6100        if (item != originalItem && originalItem->isAncestorOf(item)) {
     6101            DEBUG() << "  found a gesture to cancel" << iter.key();
     6102            iter.key()->d_func()->state = Qt::GestureCanceled;
     6103            canceledGestures << iter.key();
     6104        }
     6105        ++iter;
     6106    }
     6107
     6108    // sort them per target item by cherry picking from almostCanceledGestures and delivering
     6109    QSet<QGesture *> almostCanceledGestures = canceledGestures;
     6110    QSet<QGesture *>::Iterator setIter;
     6111    while (!almostCanceledGestures.isEmpty()) {
     6112        QGraphicsObject *target = 0;
     6113        QSet<QGesture*> gestures;
     6114        setIter = almostCanceledGestures.begin();
     6115        // sort per target item
     6116        while (setIter != almostCanceledGestures.end()) {
     6117            QGraphicsObject *item = gestureTargets.value(*setIter);
     6118            if (target == 0)
     6119                target = item;
     6120            if (target == item) {
     6121                gestures << *setIter;
     6122                setIter = almostCanceledGestures.erase(setIter);
     6123            } else {
     6124                ++setIter;
     6125            }
     6126        }
     6127        Q_ASSERT(target);
     6128
     6129        QList<QGesture *> list = gestures.toList();
     6130        QGestureEvent ev(list);
     6131        sendEvent(target, &ev);
     6132
     6133        foreach (QGesture *g, list) {
     6134            if (ev.isAccepted() || ev.isAccepted(g))
     6135                gestures.remove(g);
     6136        }
     6137
     6138        foreach (QGesture *g, gestures) {
     6139            if (!g->hasHotSpot())
     6140                continue;
     6141
     6142            QPoint screenPos = g->hotSpot().toPoint();
     6143            QList<QGraphicsItem *> items = itemsAtPosition(screenPos, QPointF(), viewport);
     6144            for (int j = 0; j < items.size(); ++j) {
     6145                QGraphicsObject *item = items.at(j)->toGraphicsObject();
     6146                if (!item)
     6147                    continue;
     6148                QGraphicsItemPrivate *d = item->QGraphicsItem::d_func();
     6149                if (d->gestureContext.contains(g->gestureType())) {
     6150                    QList<QGesture *> list;
     6151                    list << g;
     6152                    QGestureEvent ev(list);
     6153                    sendEvent(item, &ev);
     6154                    if (ev.isAccepted() || ev.isAccepted(g))
     6155                        break; // successfully delivered
     6156                }
     6157            }
     6158        }
     6159    }
     6160
     6161    QGestureManager *gestureManager = QApplicationPrivate::instance()->gestureManager;
     6162    Q_ASSERT(gestureManager); // it would be very odd if we got called without a manager.
     6163    for (setIter = canceledGestures.begin(); setIter != canceledGestures.end(); ++setIter) {
     6164        gestureManager->recycle(*setIter);
     6165        gestureTargets.remove(*setIter);
    55196166    }
    55206167}
  • trunk/src/gui/graphicsview/qgraphicsscene.h

    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**
     
    8484class QGraphicsView;
    8585class QGraphicsWidget;
     86class QGraphicsSceneIndex;
    8687class QHelpEvent;
    8788class QInputMethodEvent;
     
    153154
    154155    QList<QGraphicsItem *> items() const;
    155     QList<QGraphicsItem *> items(const QPointF &pos) const;
    156     QList<QGraphicsItem *> items(const QRectF &rect, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const;
    157     QList<QGraphicsItem *> items(const QPolygonF &polygon, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const;
    158     QList<QGraphicsItem *> items(const QPainterPath &path, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const;
     156    QList<QGraphicsItem *> items(Qt::SortOrder order) const; // ### Qt 5: unify
     157
     158    QList<QGraphicsItem *> items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const;
     159    QList<QGraphicsItem *> items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const;
     160    QList<QGraphicsItem *> items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const;
     161    QList<QGraphicsItem *> items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const;
     162
     163    QList<QGraphicsItem *> items(const QPointF &pos) const; // ### obsolete
     164    QList<QGraphicsItem *> items(const QRectF &rect, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; // ### obsolete
     165    QList<QGraphicsItem *> items(const QPolygonF &polygon, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; // ### obsolete
     166    QList<QGraphicsItem *> items(const QPainterPath &path, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; // ### obsolete
     167
    159168    QList<QGraphicsItem *> collidingItems(const QGraphicsItem *item, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const;
    160     QGraphicsItem *itemAt(const QPointF &pos) const;
     169
     170    QGraphicsItem *itemAt(const QPointF &pos) const; // ### obsolete
     171    QGraphicsItem *itemAt(const QPointF &pos, const QTransform &deviceTransform) const;
    161172
    162173    inline QList<QGraphicsItem *> items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const
    163     { return items(QRectF(x, y, w, h), mode); }
    164     inline QGraphicsItem *itemAt(qreal x, qreal y) const
     174    { return items(QRectF(x, y, w, h), mode); } // ### obsolete
     175    inline QList<QGraphicsItem *> items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode, Qt::SortOrder order,
     176                                        const QTransform &deviceTransform = QTransform()) const
     177    { return items(QRectF(x, y, w, h), mode, order, deviceTransform); }
     178    inline QGraphicsItem *itemAt(qreal x, qreal y) const // ### obsolete
    165179    { return itemAt(QPointF(x, y)); }
     180    inline QGraphicsItem *itemAt(qreal x, qreal y, const QTransform &deviceTransform) const
     181    { return itemAt(QPointF(x, y), deviceTransform); }
    166182
    167183    QList<QGraphicsItem *> selectedItems() const;
    168184    QPainterPath selectionArea() const;
    169     void setSelectionArea(const QPainterPath &path);
    170     void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode);
     185    void setSelectionArea(const QPainterPath &path); // ### obsolete
     186    void setSelectionArea(const QPainterPath &path, const QTransform &deviceTransform);
     187    void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode); // ### obsolete
     188    void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode, const QTransform &deviceTransform);
    171189
    172190    QGraphicsItemGroup *createItemGroup(const QList<QGraphicsItem *> &items);
     
    190208    { return addRect(QRectF(x, y, w, h), pen, brush); }
    191209    void removeItem(QGraphicsItem *item);
    192    
     210
    193211    QGraphicsItem *focusItem() const;
    194212    void setFocusItem(QGraphicsItem *item, Qt::FocusReason focusReason = Qt::OtherFocusReason);
     
    226244    void setPalette(const QPalette &palette);
    227245
     246    bool isActive() const;
     247    QGraphicsItem *activePanel() const;
     248    void setActivePanel(QGraphicsItem *item);
    228249    QGraphicsWidget *activeWindow() const;
    229250    void setActiveWindow(QGraphicsWidget *widget);
     251
     252    bool sendEvent(QGraphicsItem *item, QEvent *event);
    230253
    231254public Q_SLOTS:
     
    272295
    273296private:
    274     void itemUpdated(QGraphicsItem *item, const QRectF &rect);
    275 
    276297    Q_DECLARE_PRIVATE(QGraphicsScene)
    277298    Q_DISABLE_COPY(QGraphicsScene)
    278     Q_PRIVATE_SLOT(d_func(), void _q_updateIndex())
    279299    Q_PRIVATE_SLOT(d_func(), void _q_emitUpdated())
    280     Q_PRIVATE_SLOT(d_func(), void _q_removeItemLater(QGraphicsItem *item))
    281     Q_PRIVATE_SLOT(d_func(), void _q_updateLater())
    282300    Q_PRIVATE_SLOT(d_func(), void _q_polishItems())
    283     Q_PRIVATE_SLOT(d_func(), void _q_updateSortCache())
    284     Q_PRIVATE_SLOT(d_func(), void _q_resetDirtyItems())
     301    Q_PRIVATE_SLOT(d_func(), void _q_processDirtyItems())
     302    Q_PRIVATE_SLOT(d_func(), void _q_updateScenePosDescendants())
    285303    friend class QGraphicsItem;
    286304    friend class QGraphicsItemPrivate;
     
    289307    friend class QGraphicsWidget;
    290308    friend class QGraphicsWidgetPrivate;
     309    friend class QGraphicsEffect;
     310    friend class QGraphicsSceneIndex;
     311    friend class QGraphicsSceneIndexPrivate;
     312    friend class QGraphicsSceneBspTreeIndex;
     313    friend class QGraphicsSceneBspTreeIndexPrivate;
     314    friend class QGraphicsItemEffectSourcePrivate;
     315    friend class QGesture;
    291316};
    292317
  • trunk/src/gui/graphicsview/qgraphicsscene_bsp.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**
     
    7171public:
    7272    QList<QGraphicsItem *> *foundItems;
     73    bool onlyTopLevelItems;
    7374
    7475    void visit(QList<QGraphicsItem *> *items)
     
    7677        for (int i = 0; i < items->size(); ++i) {
    7778            QGraphicsItem *item = items->at(i);
    78             if (!item->d_func()->itemDiscovered && item->isVisible()) {
     79            if (onlyTopLevelItems && item->d_ptr->parent)
     80                item = item->topLevelItem();
     81            if (!item->d_func()->itemDiscovered && item->d_ptr->visible) {
    7982                item->d_func()->itemDiscovered = 1;
    8083                foundItems->prepend(item);
     
    144147}
    145148
    146 QList<QGraphicsItem *> QGraphicsSceneBspTree::items(const QRectF &rect)
     149QList<QGraphicsItem *> QGraphicsSceneBspTree::items(const QRectF &rect, bool onlyTopLevelItems) const
    147150{
    148151    QList<QGraphicsItem *> tmp;
    149152    findVisitor->foundItems = &tmp;
     153    findVisitor->onlyTopLevelItems = onlyTopLevelItems;
    150154    climbTree(findVisitor, rect);
    151     return tmp;
    152 }
    153 
    154 QList<QGraphicsItem *> QGraphicsSceneBspTree::items(const QPointF &pos)
    155 {
    156     QList<QGraphicsItem *> tmp;
    157     findVisitor->foundItems = &tmp;
    158     climbTree(findVisitor, pos);
     155    // Reset discovery bits.
     156    for (int i = 0; i < tmp.size(); ++i)
     157        tmp.at(i)->d_ptr->itemDiscovered = 0;
    159158    return tmp;
    160159}
     
    236235}
    237236
    238 void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index)
     237void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index) const
    239238{
    240239    if (nodes.isEmpty())
     
    242241
    243242    const Node &node = nodes.at(index);
    244     int childIndex = firstChildIndex(index);
     243    const int childIndex = firstChildIndex(index);
    245244
    246245    switch (node.type) {
    247246    case Node::Leaf: {
    248         visitor->visit(&leaves[node.leafIndex]);
    249         break;
    250     }
    251     case Node::Vertical:
    252         if (pos.x() < node.offset) {
    253             climbTree(visitor, pos, childIndex);
    254         } else {
    255             climbTree(visitor, pos, childIndex + 1);
    256         }
    257         break;
    258     case Node::Horizontal:
    259         if (pos.y() < node.offset) {
    260             climbTree(visitor, pos, childIndex);
    261         } else {
    262             climbTree(visitor, pos, childIndex + 1);
    263         }
    264         break;
    265     }
    266 }
    267 
    268 void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index)
    269 {
    270     if (nodes.isEmpty())
    271         return;
    272 
    273     const Node &node = nodes.at(index);
    274     int childIndex = firstChildIndex(index);
    275 
    276     switch (node.type) {
    277     case Node::Leaf: {
    278         visitor->visit(&leaves[node.leafIndex]);
     247        visitor->visit(const_cast<QList<QGraphicsItem*>*>(&leaves[node.leafIndex]));
    279248        break;
    280249    }
     
    289258        break;
    290259    case Node::Horizontal:
    291         int childIndex = firstChildIndex(index);
    292260        if (rect.top() < node.offset) {
    293261            climbTree(visitor, rect, childIndex);
  • trunk/src/gui/graphicsview/qgraphicsscene_bsp_p.h

    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**
     
    9393    void removeItems(const QSet<QGraphicsItem *> &items);
    9494
    95     QList<QGraphicsItem *> items(const QRectF &rect);
    96     QList<QGraphicsItem *> items(const QPointF &pos);
     95    QList<QGraphicsItem *> items(const QRectF &rect, bool onlyTopLevelItems = false) const;
    9796    int leafCount() const;
    9897
     
    107106private:
    108107    void initialize(const QRectF &rect, int depth, int index);
    109     void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index = 0);
    110     void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index = 0);
    111 
    112     void findItems(QList<QGraphicsItem *> *foundItems, const QRectF &rect, int index);
    113     void findItems(QList<QGraphicsItem *> *foundItems, const QPointF &pos, int index);
     108    void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index = 0) const;
    114109    QRectF rectForIndex(int index) const;
    115110
  • trunk/src/gui/graphicsview/qgraphicsscene_p.h

    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**
     
    4848//
    4949// This file is not part of the Qt API.  It exists for the convenience
    50 // of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp.  This header
    51 // file may change from version to version without notice, or even be removed.
     50// of other Qt classes.  This header file may change from version to
     51// version without notice, or even be removed.
    5252//
    5353// We mean it.
     
    5858#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW
    5959
    60 #include "qgraphicsscene_bsp_p.h"
     60#include "qgraphicssceneevent.h"
     61#include "qgraphicsview.h"
     62#include "qgraphicsview_p.h"
    6163#include "qgraphicsitem_p.h"
    6264
     
    6971#include <QtGui/qpalette.h>
    7072#include <QtGui/qstyle.h>
     73#include <QtGui/qstyleoption.h>
    7174
    7275QT_BEGIN_NAMESPACE
    7376
     77class QGraphicsSceneIndex;
    7478class QGraphicsView;
    7579class QGraphicsWidget;
    7680
    77 class QGraphicsScenePrivate : public QObjectPrivate
     81class Q_AUTOTEST_EXPORT QGraphicsScenePrivate : public QObjectPrivate
    7882{
    7983    Q_DECLARE_PUBLIC(QGraphicsScene)
     
    8286    void init();
    8387
    84     quint32 changedSignalMask;
     88    static QGraphicsScenePrivate *get(QGraphicsScene *q);
     89
     90    static int changedSignalIndex;
    8591
    8692    QGraphicsScene::ItemIndexMethod indexMethod;
    87     int bspTreeDepth;
    88 
    89     QList<QGraphicsItem *> estimateItemsInRect(const QRectF &rect) const;
    90     void addToIndex(QGraphicsItem *item);
    91     void removeFromIndex(QGraphicsItem *item);
    92     void resetIndex();
    93 
    94     QGraphicsSceneBspTree bspTree;
    95     void _q_updateIndex();
     93    QGraphicsSceneIndex *index;
     94
    9695    int lastItemCount;
    9796
    9897    QRectF sceneRect;
    9998    bool hasSceneRect;
     99    bool dirtyGrowingItemsBoundingRect;
    100100    QRectF growingItemsBoundingRect;
    101     QRectF largestUntransformableItem;
    102101
    103102    void _q_emitUpdated();
     
    105104    bool updateAll;
    106105    bool calledEmitUpdated;
     106    bool processDirtyItemsEmitted;
    107107
    108108    QPainterPath selectionArea;
    109109    int selectionChanging;
    110110    QSet<QGraphicsItem *> selectedItems;
    111     QList<QGraphicsItem *> unindexedItems;
    112     QList<QGraphicsItem *> indexedItems;
    113     QList<QGraphicsItem *> dirtyItems;
    114     QList<QGraphicsItem *> pendingUpdateItems;
    115     QList<QGraphicsItem *> unpolishedItems;
     111    QSet<QGraphicsItem *> unpolishedItems;
     112    QList<QGraphicsItem *> topLevelItems;
     113    bool needSortTopLevelItems;
     114    bool unpolishedItemsModified;
     115    bool holesInTopLevelSiblingIndex;
     116    bool topLevelSequentialOrdering;
     117
    116118    QMap<QGraphicsItem *, QPointF> movingItemsInitialPositions;
     119    void registerTopLevelItem(QGraphicsItem *item);
     120    void unregisterTopLevelItem(QGraphicsItem *item);
    117121    void _q_updateLater();
    118122    void _q_polishItems();
    119123
    120     void _q_resetDirtyItems();
    121     void resetDirtyItemsLater();
    122     bool dirtyItemResetPending;
    123 
    124     QList<int> freeItemIndexes;
    125     bool regenerateIndex;
    126 
    127     bool purgePending;
    128     void _q_removeItemLater(QGraphicsItem *item);
    129     QSet<QGraphicsItem *> removedItems;
    130     void purgeRemovedItems();
     124    void _q_processDirtyItems();
     125
     126    QSet<QGraphicsItem *> scenePosItems;
     127    bool scenePosDescendantsUpdatePending;
     128    void setScenePosItemEnabled(QGraphicsItem *item, bool enabled);
     129    void registerScenePosItem(QGraphicsItem *item);
     130    void unregisterScenePosItem(QGraphicsItem *item);
     131    void _q_updateScenePosDescendants();
     132
     133    void removeItemHelper(QGraphicsItem *item);
    131134
    132135    QBrush backgroundBrush;
    133136    QBrush foregroundBrush;
    134 
    135     int indexTimerId;
    136     bool restartIndexTimer;
    137     void startIndexTimer();
    138137
    139138    bool stickyFocus;
     
    142141    QGraphicsItem *lastFocusItem;
    143142    QGraphicsWidget *tabFocusFirst;
    144     QGraphicsWidget *activeWindow;
     143    QGraphicsItem *activePanel;
     144    QGraphicsItem *lastActivePanel;
    145145    int activationRefCount;
     146    int childExplicitActivation;
     147    void setActivePanelHelper(QGraphicsItem *item, bool duringActivationEvent);
     148    void setFocusItemHelper(QGraphicsItem *item, Qt::FocusReason focusReason);
    146149
    147150    QList<QGraphicsWidget *> popupWidgets;
     
    160163    void ungrabKeyboard(QGraphicsItem *item, bool itemIsDying = false);
    161164    void clearKeyboardGrabber();
    162    
     165
    163166    QGraphicsItem *dragDropItem;
    164167    QGraphicsWidget *enterWidget;
     
    166169    QList<QGraphicsItem *> cachedItemsUnderMouse;
    167170    QList<QGraphicsItem *> hoverItems;
     171    QPointF lastSceneMousePos;
     172    bool allItemsIgnoreHoverEvents;
     173    bool allItemsUseDefaultCursor;
     174    void enableMouseTrackingOnViews();
    168175    QMap<Qt::MouseButton, QPointF> mouseGrabberButtonDownPos;
    169176    QMap<Qt::MouseButton, QPointF> mouseGrabberButtonDownScenePos;
     
    172179                                           const QPointF &scenePos,
    173180                                           QWidget *widget) const;
    174     static bool itemCollidesWithPath(QGraphicsItem *item, const QPainterPath &path, Qt::ItemSelectionMode mode);
    175181    void storeMouseButtonsForMouseGrabber(QGraphicsSceneMouseEvent *event);
    176182
    177183    QList<QGraphicsView *> views;
     184    void addView(QGraphicsView *view);
     185    void removeView(QGraphicsView *view);
     186
    178187    bool painterStateProtection;
    179188
     
    181190    void installSceneEventFilter(QGraphicsItem *watched, QGraphicsItem *filter);
    182191    void removeSceneEventFilter(QGraphicsItem *watched, QGraphicsItem *filter);
     192    bool filterDescendantEvent(QGraphicsItem *item, QEvent *event);
    183193    bool filterEvent(QGraphicsItem *item, QEvent *event);
    184194    bool sendEvent(QGraphicsItem *item, QEvent *event);
     
    198208    QGraphicsWidget *windowForItem(const QGraphicsItem *item) const;
    199209
    200     QList<QGraphicsItem *> items_helper(const QPointF &pos) const;
    201     QList<QGraphicsItem *> items_helper(const QRectF &rect,
    202                                         Qt::ItemSelectionMode mode,
    203                                         Qt::SortOrder order) const;
    204     QList<QGraphicsItem *> items_helper(const QPolygonF &rect,
    205                                         Qt::ItemSelectionMode mode,
    206                                         Qt::SortOrder order) const;
    207     QList<QGraphicsItem *> items_helper(const QPainterPath &rect,
    208                                         Qt::ItemSelectionMode mode,
    209                                         Qt::SortOrder order) const;
    210     void childItems_helper(QList<QGraphicsItem *> *items,
    211                            const QGraphicsItem *parent,
    212                            const QPointF &pos) const;
    213     void childItems_helper(QList<QGraphicsItem *> *items,
    214                            const QGraphicsItem *parent,
    215                            const QRectF &rect,
    216                            Qt::ItemSelectionMode mode) const;
    217     void childItems_helper(QList<QGraphicsItem *> *items,
    218                            const QGraphicsItem *parent,
    219                            const QPolygonF &polygon,
    220                            Qt::ItemSelectionMode mode) const;
    221     void childItems_helper(QList<QGraphicsItem *> *items,
    222                            const QGraphicsItem *parent,
    223                            const QPainterPath &path,
    224                            Qt::ItemSelectionMode mode) const;
    225 
    226     bool sortCacheEnabled;
    227     bool updatingSortCache;
    228     void invalidateSortCache();
    229     static void climbTree(QGraphicsItem *item, int *stackingOrder);
    230     void _q_updateSortCache();
    231 
    232     static bool closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2);
    233     static bool closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2);
    234 
    235     static inline bool closestItemFirst_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2)
    236     {
    237         return item1->d_ptr->globalStackingOrder < item2->d_ptr->globalStackingOrder;
    238     }
    239     static inline bool closestItemLast_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2)
    240     {
    241         return item1->d_ptr->globalStackingOrder >= item2->d_ptr->globalStackingOrder;
    242     }
    243 
    244     static void sortItems(QList<QGraphicsItem *> *itemList, Qt::SortOrder order, bool cached);
     210    bool sortCacheEnabled; // for compatibility
    245211
    246212    void drawItemHelper(QGraphicsItem *item, QPainter *painter,
    247213                        const QStyleOptionGraphicsItem *option, QWidget *widget,
    248214                        bool painterStateProtection);
    249    
     215
     216    void drawItems(QPainter *painter, const QTransform *const viewTransform,
     217                   QRegion *exposedRegion, QWidget *widget);
     218
     219    void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform *const,
     220                              QRegion *exposedRegion, QWidget *widget, qreal parentOpacity = qreal(1.0),
     221                              const QTransform *const effectTransform = 0);
     222    void draw(QGraphicsItem *, QPainter *, const QTransform *const, const QTransform *const,
     223              QRegion *, QWidget *, qreal, const QTransform *const, bool, bool);
     224
     225    void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false,
     226                   bool force = false, bool ignoreOpacity = false, bool removingItemFromScene = false);
     227    void processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren = false,
     228                                    qreal parentOpacity = qreal(1.0));
     229
     230    inline void resetDirtyItem(QGraphicsItem *item, bool recursive = false)
     231    {
     232        Q_ASSERT(item);
     233        item->d_ptr->dirty = 0;
     234        item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0;
     235        item->d_ptr->geometryChanged = 0;
     236        if (!item->d_ptr->dirtyChildren)
     237            recursive = false;
     238        item->d_ptr->dirtyChildren = 0;
     239        item->d_ptr->needsRepaint = QRectF();
     240        item->d_ptr->allChildrenDirty = 0;
     241        item->d_ptr->fullUpdatePending = 0;
     242        item->d_ptr->ignoreVisible = 0;
     243        item->d_ptr->ignoreOpacity = 0;
     244#ifndef QT_NO_GRAPHICSEFFECT
     245        QGraphicsEffect::ChangeFlags flags;
     246        if (item->d_ptr->notifyBoundingRectChanged) {
     247            flags |= QGraphicsEffect::SourceBoundingRectChanged;
     248            item->d_ptr->notifyBoundingRectChanged = 0;
     249        }
     250        if (item->d_ptr->notifyInvalidated) {
     251            flags |= QGraphicsEffect::SourceInvalidated;
     252            item->d_ptr->notifyInvalidated = 0;
     253        }
     254#endif //QT_NO_GRAPHICSEFFECT
     255        if (recursive) {
     256            for (int i = 0; i < item->d_ptr->children.size(); ++i)
     257                resetDirtyItem(item->d_ptr->children.at(i), recursive);
     258        }
     259#ifndef QT_NO_GRAPHICSEFFECT
     260        if (flags && item->d_ptr->graphicsEffect)
     261            item->d_ptr->graphicsEffect->sourceChanged(flags);
     262#endif //QT_NO_GRAPHICSEFFECT
     263    }
     264
     265    inline void ensureSortedTopLevelItems()
     266    {
     267        if (needSortTopLevelItems) {
     268            qSort(topLevelItems.begin(), topLevelItems.end(), qt_notclosestLeaf);
     269            topLevelSequentialOrdering = false;
     270            needSortTopLevelItems = false;
     271        }
     272    }
     273
     274    void ensureSequentialTopLevelSiblingIndexes();
     275
    250276    QStyle *style;
    251277    QFont font;
     
    258284    void updatePalette(const QPalette &palette);
    259285
    260     mutable QVector<QTransform> sceneTransformCache;
    261     mutable QBitArray validTransforms;
    262     mutable QVector<int> freeSceneTransformSlots;
     286    QStyleOptionGraphicsItem styleOptionTmp;
     287
     288    QMap<int, QTouchEvent::TouchPoint> sceneCurrentTouchPoints;
     289    QMap<int, QGraphicsItem *> itemForTouchPointId;
     290    static void updateTouchPointsForItem(QGraphicsItem *item, QTouchEvent *touchEvent);
     291    int findClosestTouchPointId(const QPointF &scenePos);
     292    void touchEventHandler(QTouchEvent *touchEvent);
     293    bool sendTouchBeginEvent(QGraphicsItem *item, QTouchEvent *touchEvent);
     294    bool allItemsIgnoreTouchEvents;
     295    void enableTouchEventsOnViews();
     296
     297    QHash<QGesture *, QGraphicsObject *> gestureTargets;
     298    void gestureEventHandler(QGestureEvent *event);
     299    void getGestureTargets(const QSet<QGesture *> &gestures, QWidget *viewport,
     300                           QMap<Qt::GestureType, QGesture *> *conflictedGestures,
     301                           QList<QList<QGraphicsObject *> > *conflictedItems,
     302                           QHash<QGesture *, QGraphicsObject *> *normalGestures);
     303    void cancelGesturesForChildren(QGesture *original, QWidget *viewport);
     304
     305    void updateInputMethodSensitivityInViews();
     306
     307    QList<QGraphicsItem *> modalPanels;
     308    void enterModal(QGraphicsItem *item,
     309                    QGraphicsItem::PanelModality panelModality = QGraphicsItem::NonModal);
     310    void leaveModal(QGraphicsItem *item);
    263311};
    264312
     313// QRectF::intersects() returns false always if either the source or target
     314// rectangle's width or height are 0. This works around that problem.
     315static inline void _q_adjustRect(QRectF *rect)
     316{
     317    Q_ASSERT(rect);
     318    if (!rect->width())
     319        rect->adjust(qreal(-0.00001), 0, qreal(0.00001), 0);
     320    if (!rect->height())
     321        rect->adjust(0, qreal(-0.00001), 0, qreal(0.00001));
     322}
     323
     324static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item)
     325{
     326    Q_ASSERT(item);
     327    QRectF boundingRect(item->boundingRect());
     328    _q_adjustRect(&boundingRect);
     329    return boundingRect;
     330}
     331
     332static inline QRectF adjustedItemEffectiveBoundingRect(const QGraphicsItem *item)
     333{
     334    Q_ASSERT(item);
     335    QRectF boundingRect(QGraphicsItemPrivate::get(item)->effectiveBoundingRect());
     336    _q_adjustRect(&boundingRect);
     337    return boundingRect;
     338}
     339
    265340QT_END_NAMESPACE
    266341
  • trunk/src/gui/graphicsview/qgraphicssceneevent.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    graphics view related events.
    4646    \since 4.2
    47     \ingroup multimedia
    4847    \ingroup graphicsview-api
    4948
     
    7776    \l{QGraphicsSceneMouseEvent::}{lastScreenPos()},
    7877    \l{QGraphicsSceneMouseEvent::}{lastScenePos()}, and
    79     \l{QGraphicsSceneMouseEvent::}{lastPos()}). 
     78    \l{QGraphicsSceneMouseEvent::}{lastPos()}).
    8079
    8180    \sa QEvent
     
    8483/*!
    8584    \class QGraphicsSceneMouseEvent
    86     \brief The QGraphicsSceneMouseEvent class provides mouse events 
     85    \brief The QGraphicsSceneMouseEvent class provides mouse events
    8786           in the graphics view framework.
    8887    \since 4.2
    89     \ingroup multimedia
    9088    \ingroup graphicsview-api
    9189
    92     When a QGraphicsView receives a QMouseEvent, it translates it to
    93     a QGraphicsSceneMouseEvent. The event is then forwarded to the
    94     QGraphicsScene associated with the view.
     90    When a QGraphicsView receives a QMouseEvent, it translates it to a
     91    QGraphicsSceneMouseEvent. The event is then forwarded to the
     92    QGraphicsScene associated with the view. If the event is not
     93    handled by the scene, the view may use it, e.g., for the
     94    \l{QGraphicsView::}{DragMode}.
    9595
    9696    In addition to containing the item, scene, and screen coordinates
     
    107107/*!
    108108    \class QGraphicsSceneWheelEvent
    109     \brief The QGraphicsSceneWheelEvent class provides wheel events 
     109    \brief The QGraphicsSceneWheelEvent class provides wheel events
    110110           in the graphics view framework.
    111111    \brief The QGraphicsSceneWheelEvent class provides wheel events in the
    112112    graphics view framework.
    113113    \since 4.2
    114     \ingroup multimedia
    115114    \ingroup graphicsview-api
    116115
     
    129128           menu events in the graphics view framework.
    130129    \since 4.2
    131     \ingroup multimedia
    132130    \ingroup graphicsview-api
    133131
     
    158156/*!
    159157    \class QGraphicsSceneHoverEvent
    160     \brief The QGraphicsSceneHoverEvent class provides hover events 
     158    \brief The QGraphicsSceneHoverEvent class provides hover events
    161159           in the graphics view framework.
    162160    \since 4.2
    163     \ingroup multimedia
    164161    \ingroup graphicsview-api
    165162
     
    174171/*!
    175172    \class QGraphicsSceneHelpEvent
    176     \brief The QGraphicsSceneHelpEvent class provides events when a 
     173    \brief The QGraphicsSceneHelpEvent class provides events when a
    177174           tooltip is requested.
    178175    \since 4.2
    179     \ingroup multimedia
    180176    \ingroup graphicsview-api
    181177
     
    200196    \class QGraphicsSceneDragDropEvent
    201197    \brief The QGraphicsSceneDragDropEvent class provides events for
    202            drag and drop in the graphics view framework. 
     198           drag and drop in the graphics view framework.
    203199    \since 4.2
    204     \ingroup multimedia
    205200    \ingroup graphicsview-api
    206201
     
    227222    resizing in the graphics view framework.
    228223    \since 4.4
    229     \ingroup multimedia
    230224    \ingroup graphicsview-api
    231225
     
    244238    moving in the graphics view framework.
    245239    \since 4.4
    246     \ingroup multimedia
    247240    \ingroup graphicsview-api
    248241
     
    269262#include <QtCore/qsize.h>
    270263#include <QtCore/qstring.h>
     264#include "qgraphicsview.h"
     265#include "qgraphicsitem.h"
     266#include <QtGui/qgesture.h>
     267#include <private/qevent_p.h>
    271268
    272269QT_BEGIN_NAMESPACE
     
    314311QGraphicsSceneEvent::~QGraphicsSceneEvent()
    315312{
    316     delete d_ptr;
    317313}
    318314
     
    523519
    524520/*!
    525     Returns the last recorded mouse cursor position in scene 
     521    Returns the last recorded mouse cursor position in scene
    526522    coordinates. The last recorded position is the position of
    527523    the previous mouse event received by the view that created
     
    546542
    547543/*!
    548     Returns the last recorded mouse cursor position in screen 
     544    Returns the last recorded mouse cursor position in screen
    549545    coordinates. The last recorded position is the position of
    550546    the previous mouse event received by the view that created
     
    845841/*!
    846842    Returns the position of the mouse cursor in item coordinates at the moment
    847     the the context menu was requested.
     843    the context menu was requested.
    848844
    849845    \sa scenePos(), screenPos()
     
    993989/*!
    994990    Returns the position of the mouse cursor in item coordinates at the moment
    995     the the hover event was sent.
     991    the hover event was sent.
    996992
    997993    \sa scenePos(), screenPos()
     
    10181014/*!
    10191015    Returns the position of the mouse cursor in scene coordinates at the
    1020     moment the the hover event was sent.
     1016    moment the hover event was sent.
    10211017
    10221018    \sa pos(), screenPos()
     
    10431039/*!
    10441040    Returns the position of the mouse cursor in screen coordinates at the
    1045     moment the the hover event was sent.
     1041    moment the hover event was sent.
    10461042
    10471043    \sa pos(), scenePos()
     
    11391135    \since 4.4
    11401136
    1141     Returns the keyboard modifiers at the moment the the hover event was sent.
     1137    Returns the keyboard modifiers at the moment the hover event was sent.
    11421138*/
    11431139Qt::KeyboardModifiers QGraphicsSceneHoverEvent::modifiers() const
     
    11851181/*!
    11861182    Returns the position of the mouse cursor in scene coordinates at the
    1187     moment the the help event was sent.
     1183    moment the help event was sent.
    11881184
    11891185    \sa screenPos()
     
    12101206/*!
    12111207    Returns the position of the mouse cursor in screen coordinates at the
    1212     moment the the help event was sent.
     1208    moment the help event was sent.
    12131209
    12141210  \sa scenePos()
     
    12761272    Returns the mouse position of the event relative to the
    12771273    view that sent the event.
    1278    
     1274
    12791275    \sa QGraphicsView, screenPos(), scenePos()
    12801276*/
     
    13741370/*!
    13751371    Returns the keyboard modifiers that were pressed when the drag
    1376     and drop event was created. 
     1372    and drop event was created.
    13771373
    13781374    \sa Qt::KeyboardModifiers
     
    14291425    \c possibleActions().
    14301426
    1431     \sa Qt::DropAction, possibleActions()   
     1427    \sa Qt::DropAction, possibleActions()
    14321428*/
    14331429
     
    14731469    Returns the action that was performed in this drag and drop.
    14741470    This should be set by the receiver of the drop and is
    1475     returned by QDrag::start().
     1471    returned by QDrag::exec().
    14761472
    14771473    \sa setDropAction(), acceptProposedAction()
  • trunk/src/gui/graphicsview/qgraphicssceneevent.h

    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#include <QtCore/qcoreevent.h>
    4646#include <QtCore/qpoint.h>
     47#include <QtCore/qscopedpointer.h>
     48#include <QtCore/qrect.h>
     49#include <QtGui/qpolygon.h>
     50#include <QtCore/qset.h>
     51#include <QtCore/qhash.h>
    4752
    4853QT_BEGIN_HEADER
     
    7176protected:
    7277    QGraphicsSceneEvent(QGraphicsSceneEventPrivate &dd, Type type = None);
    73     QGraphicsSceneEventPrivate *d_ptr;
     78    QScopedPointer<QGraphicsSceneEventPrivate> d_ptr;
    7479    Q_DECLARE_PRIVATE(QGraphicsSceneEvent)
    7580};
  • trunk/src/gui/graphicsview/qgraphicsview.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**
    4040****************************************************************************/
    41 
    42 //#define QGRAPHICSVIEW_DEBUG
    4341
    4442static const int QGRAPHICSVIEW_REGION_RECT_THRESHOLD = 50;
     
    5149    contents of a QGraphicsScene.
    5250    \since 4.2
    53     \ingroup multimedia
    5451    \ingroup graphicsview-api
    55     \mainclass
     52
    5653
    5754    QGraphicsView visualizes the contents of a QGraphicsScene in a scrollable
     
    10097    widget.
    10198
    102     QGraphicsView supports affine transformations, using QMatrix. You can
    103     either pass a matrix to setMatrix(), or you can call one of the
     99    QGraphicsView supports affine transformations, using QTransform. You can
     100    either pass a matrix to setTransform(), or you can call one of the
    104101    convenience functions rotate(), scale(), translate() or shear(). The most
    105102    two common transformations are scaling, which is used to implement
     
    201198    can vary between paint devices and platforms.
    202199
    203     \value DontClipPainter QGraphicsView sometimes clips the painter when
    204     rendering the scene contents. This can generally improve performance
    205     (e.g., rendering only small parts of a large pixmap), and protects against
    206     rendering mistakes (e.g., drawing outside bounding rectangles, or outside
    207     the exposed area). In some situations, however, the painter clip can slow
    208     down rendering; especially when all painting is restricted to inside
    209     exposed areas. By enabling this flag, QGraphicsView will completely
    210     disable its implicit clipping. Note that rendering artifacts from using a
    211     semi-transparent foreground or background brush can occur if clipping is
    212     disabled.
     200    \value DontClipPainter This value is obsolete and has no effect.
    213201
    214202    \value DontSavePainterState When rendering, QGraphicsView protects the
     
    229217    common side effect is that items that do draw with antialiasing can leave
    230218    painting traces behind on the scene as they are moved.
     219
     220    \value IndirectPainting Since Qt 4.6, restore the old painting algorithm
     221    that calls QGraphicsView::drawItems() and QGraphicsScene::drawItems().
     222    To be used only for compatibility with old code.
    231223*/
    232224
     
    290282#include <QtGui/qscrollbar.h>
    291283#include <QtGui/qstyleoption.h>
     284#include <QtGui/qinputcontext.h>
    292285#ifdef Q_WS_X11
     286#include <QtGui/qpaintengine.h>
    293287#include <private/qt_x11_p.h>
    294288#endif
    295289
     290#include <private/qevent_p.h>
     291
    296292QT_BEGIN_NAMESPACE
     293
     294bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event);
    297295
    298296inline int q_round_bound(qreal d) //### (int)(qreal) INT_MAX != INT_MAX for single precision
     
    303301        return INT_MAX;
    304302    return d >= 0.0 ? int(d + 0.5) : int(d - int(d-1) + 0.5) + int(d-1);
     303}
     304
     305void QGraphicsViewPrivate::translateTouchEvent(QGraphicsViewPrivate *d, QTouchEvent *touchEvent)
     306{
     307    QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints();
     308    for (int i = 0; i < touchPoints.count(); ++i) {
     309        QTouchEvent::TouchPoint &touchPoint = touchPoints[i];
     310        // the scene will set the item local pos, startPos, lastPos, and rect before delivering to
     311        // an item, but for now those functions are returning the view's local coordinates
     312        touchPoint.setSceneRect(d->mapToScene(touchPoint.rect()));
     313        touchPoint.setStartScenePos(d->mapToScene(touchPoint.startPos()));
     314        touchPoint.setLastScenePos(d->mapToScene(touchPoint.lastPos()));
     315
     316        // screenPos, startScreenPos, lastScreenPos, and screenRect are already set
     317    }
     318
     319    touchEvent->setTouchPoints(touchPoints);
    305320}
    306321
     
    339354      lastDragDropEvent(0),
    340355      fullUpdatePending(true),
    341       dirtyRectCount(0),
    342       updatingLater(false),
    343356      updateSceneSlotReimplementedChecked(false)
    344357{
     
    401414    int right = q_round_bound(viewRect.right() - width);
    402415    if (left >= right) {
    403         q->horizontalScrollBar()->setRange(0, 0);
     416        hbar->setRange(0, 0);
    404417
    405418        switch (alignment & Qt::AlignHorizontal_Mask) {
     
    416429        }
    417430    } else {
    418         q->horizontalScrollBar()->setRange(left, right);
    419         q->horizontalScrollBar()->setPageStep(width);
    420         q->horizontalScrollBar()->setSingleStep(width / 20);
     431        hbar->setRange(left, right);
     432        hbar->setPageStep(width);
     433        hbar->setSingleStep(width / 20);
    421434        leftIndent = 0;
    422435    }
     
    427440    int bottom = q_round_bound(viewRect.bottom()  - height);
    428441    if (top >= bottom) {
    429         q->verticalScrollBar()->setRange(0, 0);
     442        vbar->setRange(0, 0);
    430443
    431444        switch (alignment & Qt::AlignVertical_Mask) {
     
    442455        }
    443456    } else {
    444         q->verticalScrollBar()->setRange(top, bottom);
    445         q->verticalScrollBar()->setPageStep(height);
    446         q->verticalScrollBar()->setSingleStep(height / 20);
     457        vbar->setRange(top, bottom);
     458        vbar->setPageStep(height);
     459        vbar->setSingleStep(height / 20);
    447460        topIndent = 0;
    448461    }
     
    456469    if (oldLeftIndent != leftIndent || oldTopIndent != topIndent) {
    457470        dirtyScroll = true;
    458         q->viewport()->update();
     471        updateAll();
    459472    } else if (q->isRightToLeft() && !leftIndent) {
    460473        // In reverse mode, the horizontal scroll always changes after the content
     
    482495            // Last scene pos: lastMouseMoveScenePoint
    483496            // Current mouse pos:
    484             QPointF transformationDiff = q->mapToScene(q->viewport()->rect().center())
    485                                          - q->mapToScene(q->mapFromGlobal(QCursor::pos()));
    486             q->centerOn(lastMouseMoveScenePoint + transformationDiff);;
     497            QPointF transformationDiff = q->mapToScene(viewport->rect().center())
     498                                         - q->mapToScene(viewport->mapFromGlobal(QCursor::pos()));
     499            q->centerOn(lastMouseMoveScenePoint + transformationDiff);
    487500        } else {
    488501            q->centerOn(lastCenterPoint);
     
    504517{
    505518    Q_Q(QGraphicsView);
    506     lastCenterPoint = q->mapToScene(q->viewport()->rect().center());
     519    lastCenterPoint = q->mapToScene(viewport->rect().center());
    507520}
    508521
     
    531544        const_cast<QGraphicsViewPrivate *>(this)->updateScroll();
    532545    return scrollY;
     546}
     547
     548/*!
     549    \internal
     550
     551    Maps the given rectangle to the scene using QTransform::mapRect()
     552*/
     553QRectF QGraphicsViewPrivate::mapRectToScene(const QRect &rect) const
     554{
     555    if (dirtyScroll)
     556        const_cast<QGraphicsViewPrivate *>(this)->updateScroll();
     557    QRectF scrolled = QRectF(rect.translated(scrollX, scrollY));
     558    return identityMatrix ? scrolled : matrix.inverted().mapRect(scrolled);
     559}
     560
     561
     562/*!
     563    \internal
     564
     565    Maps the given rectangle from the scene using QTransform::mapRect()
     566*/
     567QRectF QGraphicsViewPrivate::mapRectFromScene(const QRectF &rect) const
     568{
     569    if (dirtyScroll)
     570        const_cast<QGraphicsViewPrivate *>(this)->updateScroll();
     571    return (identityMatrix ? rect : matrix.mapRect(rect)).translated(-scrollX, -scrollY);
    533572}
    534573
     
    542581    if (q->isRightToLeft()) {
    543582        if (!leftIndent) {
    544             scrollX += q->horizontalScrollBar()->minimum();
    545             scrollX += q->horizontalScrollBar()->maximum();
    546             scrollX -= q->horizontalScrollBar()->value();
     583            scrollX += hbar->minimum();
     584            scrollX += hbar->maximum();
     585            scrollX -= hbar->value();
    547586        }
    548587    } else {
    549         scrollX += q->horizontalScrollBar()->value();
    550     }
    551 
    552     scrollY = qint64(q->verticalScrollBar()->value() - topIndent);
     588        scrollX += hbar->value();
     589    }
     590
     591    scrollY = qint64(vbar->value() - topIndent);
    553592
    554593    dirtyScroll = false;
     
    590629
    591630    QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
    592     mouseEvent.setWidget(q->viewport());
     631    mouseEvent.setWidget(viewport);
    593632    mouseEvent.setButtonDownScenePos(mousePressButton, mousePressScenePoint);
    594633    mouseEvent.setButtonDownScreenPos(mousePressButton, mousePressScreenPoint);
     
    603642    lastMouseMoveScreenPoint = mouseEvent.screenPos();
    604643    mouseEvent.setAccepted(false);
    605     QApplication::sendEvent(scene, &mouseEvent);
     644    if (event->spontaneous())
     645        qt_sendSpontaneousEvent(scene, &mouseEvent);
     646    else
     647        QApplication::sendEvent(scene, &mouseEvent);
    606648
    607649    // Remember whether the last event was accepted or not.
     
    615657
    616658#ifndef QT_NO_CURSOR
     659    // If all the items ignore hover events, we don't look-up any items
     660    // in QGraphicsScenePrivate::dispatchHoverEvent, hence the
     661    // cachedItemsUnderMouse list will be empty. We therefore do the look-up
     662    // for cursor items here if not all items use the default cursor.
     663    if (scene->d_func()->allItemsIgnoreHoverEvents && !scene->d_func()->allItemsUseDefaultCursor
     664        && scene->d_func()->cachedItemsUnderMouse.isEmpty()) {
     665        scene->d_func()->cachedItemsUnderMouse = scene->d_func()->itemsAtPosition(mouseEvent.screenPos(),
     666                                                                                  mouseEvent.scenePos(),
     667                                                                                  mouseEvent.widget());
     668    }
    617669    // Find the topmost item under the mouse with a cursor.
    618670    foreach (QGraphicsItem *item, scene->d_func()->cachedItemsUnderMouse) {
     
    627679        // Restore the original viewport cursor.
    628680        hasStoredOriginalCursor = false;
    629         q->viewport()->setCursor(originalCursor);
     681        viewport->setCursor(originalCursor);
    630682    }
    631683#endif
     
    659711void QGraphicsViewPrivate::_q_setViewportCursor(const QCursor &cursor)
    660712{
    661     Q_Q(QGraphicsView);
    662     QWidget *viewport = q->viewport();
    663713    if (!hasStoredOriginalCursor) {
    664714        hasStoredOriginalCursor = true;
     
    686736    hasStoredOriginalCursor = false;
    687737    if (dragMode == QGraphicsView::ScrollHandDrag)
    688         q->viewport()->setCursor(Qt::OpenHandCursor);
     738        viewport->setCursor(Qt::OpenHandCursor);
    689739    else
    690         q->viewport()->setCursor(originalCursor);
     740        viewport->setCursor(originalCursor);
    691741}
    692742#endif
     
    727777    dest->setDropAction(source->dropAction());
    728778    dest->setMimeData(source->mimeData());
    729     dest->setWidget(q->viewport());
     779    dest->setWidget(viewport);
    730780    dest->setSource(source->source());
    731781#else
     
    750800
    751801    // Translate-only
     802    // COMBINE
    752803    QPointF offset;
    753804    const QGraphicsItem *parentItem = item;
    754805    const QGraphicsItemPrivate *itemd;
    755806    do {
    756         itemd = parentItem->d_ptr;
    757         if (itemd->hasTransform)
     807        itemd = parentItem->d_ptr.data();
     808        if (itemd->transformData)
    758809            break;
    759810        offset += itemd->pos;
     
    787838
    788839    // Accurate bounding region
    789     QTransform itv = item->sceneTransform() * q->viewportTransform();
     840    QTransform itv = item->deviceTransform(q->viewportTransform());
    790841    return item->boundingRegion(itv) & itv.mapRect(rect).toAlignedRect();
    791842}
    792843
    793 // QRectF::intersects() returns false always if either the source or target
    794 // rectangle's width or height are 0. This works around that problem.
    795 static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item)
    796 {
    797     Q_ASSERT(item);
    798     QRectF boundingRect(item->boundingRect());
    799     if (!boundingRect.width())
    800         boundingRect.adjust(-0.00001, 0, 0.00001, 0);
    801     if (!boundingRect.height())
    802         boundingRect.adjust(0, -0.00001, 0, 0.00001);
    803     return boundingRect;
    804 }
    805 
    806844/*!
    807845    \internal
    808846*/
    809 void QGraphicsViewPrivate::itemUpdated(QGraphicsItem *item, const QRectF &rect)
    810 {
    811     if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate)
    812         return;
    813     if (item->d_ptr->dirty)
    814         updateLater();
    815 
    816     QRectF updateRect = rect;
    817     if ((item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) || item->d_ptr->children.isEmpty()) {
    818         updateRect &= adjustedItemBoundingRect(item);
    819         if (updateRect.isEmpty())
    820             return;
    821     }
    822 
    823     QGraphicsItem *clipItem = item;
    824     if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) {
    825         // Minimize unnecessary redraw.
    826         QGraphicsItem *parent = item;
    827         while ((parent = parent->d_ptr->parent)) {
    828             if (parent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) {
    829                 // Map update rect to the current parent and itersect with its bounding rect.
    830                 updateRect = clipItem->itemTransform(parent).mapRect(updateRect)
    831                              & adjustedItemBoundingRect(parent);
    832                 if (updateRect.isEmpty())
    833                     return;
    834                 clipItem = parent;
    835             }
    836 
    837             if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren))
    838                 break;
    839         }
    840     }
    841 
    842     // Map update rect from clipItem coordinates to view coordinates.
    843     Q_ASSERT(clipItem);
    844     if (!item->d_ptr->hasBoundingRegionGranularity)
    845         this->updateRect(mapToViewRect(clipItem, updateRect) & viewport->rect());
    846     else
    847         updateRegion(mapToViewRegion(clipItem, updateRect) & viewport->rect());
    848 }
    849 
    850 void QGraphicsViewPrivate::updateLater()
    851 {
    852     Q_Q(QGraphicsView);
    853     if (updatingLater)
    854         return;
    855     updatingLater = true;
    856     QMetaObject::invokeMethod(q, "_q_updateLaterSlot", Qt::QueuedConnection);
    857 }
    858 
    859 void QGraphicsViewPrivate::_q_updateLaterSlot()
    860 {
    861     Q_Q(QGraphicsView);
     847void QGraphicsViewPrivate::processPendingUpdates()
     848{
    862849    if (!scene)
    863850        return;
    864851
    865     QRect vr = viewport->rect();
    866     QTransform viewTransform = q->viewportTransform();
    867     const QList<QGraphicsItem *> &dirtyItems = scene->d_func()->dirtyItems;
    868     for (int i = 0; i < dirtyItems.size(); ++i) {
    869         const QGraphicsItem *item = dirtyItems.at(i);
    870         if (item->d_ptr->discardUpdateRequest(/*ignoreClipping=*/false,
    871                                               /*ignoreVisibleBit=*/false,
    872                                               /*ignoreDirtyBit=*/true)) {
    873             continue;
    874         }
    875         QTransform x = item->sceneTransform() * viewTransform;
    876         updateRect(x.mapRect(item->boundingRect()).toAlignedRect() & vr);
    877     }
    878 
    879     dirtyRectCount += dirtyRects.size();
    880 
    881     bool noUpdate = !fullUpdatePending && viewportUpdateMode == QGraphicsView::FullViewportUpdate;
    882     if ((dirtyRectCount > 0 || !dirtyBoundingRect.isEmpty()) && !fullUpdatePending && !noUpdate) {
    883         if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate
    884             || (viewportUpdateMode == QGraphicsView::SmartViewportUpdate
    885                 && dirtyRectCount >= QGRAPHICSVIEW_REGION_RECT_THRESHOLD)) {
    886             if (!(optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)) {
    887                 viewport->update(dirtyBoundingRect.adjusted(-2, -2, 2, 2));
    888             } else {
    889                 viewport->update(dirtyBoundingRect);
    890             }
    891         } else {
    892             // ### Improve this block, which is very slow for complex regions. We
    893             // need to strike the balance between having an accurate update
    894             // region, and running fast. The below approach is the simplest way to
    895             // create a region from a bunch of rects, but we might want to use
    896             // other approaches; e.g., a grid of a fixed size representing
    897             // quadrants of the viewport, which we mark as dirty depending on the
    898             // rectangles in the list. Perhaps this should go into a
    899             // QRegion::fromRects(rects, how) function.
    900             QRegion region;
    901             if (!(optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)) {
    902                 for (int i = 0; i < dirtyRegions.size(); ++i) {
    903                     QVector<QRect> rects = dirtyRegions.at(i).rects();
    904                     for (int j = 0; j < rects.size(); ++j)
    905                         region += rects.at(j).adjusted(-2, -2, 2, 2);
    906                 }
    907                 for (int i = 0; i < dirtyRects.size(); ++i)
    908                     region += dirtyRects.at(i).adjusted(-2, -2, 2, 2);
    909             } else {
    910                 for (int i = 0; i < dirtyRegions.size(); ++i)
    911                     region += dirtyRegions.at(i);
    912                 for (int i = 0; i < dirtyRects.size(); ++i)
    913                     region += dirtyRects.at(i);
    914             }
    915 
    916             viewport->update(region);
    917         }
    918     }
    919 
    920     dirtyRegions.clear();
    921     dirtyRects.clear();
    922     dirtyRectCount = 0;
     852    if (fullUpdatePending) {
     853        viewport->update();
     854    } else if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) {
     855        if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
     856            viewport->update(dirtyBoundingRect.adjusted(-1, -1, 1, 1));
     857        else
     858            viewport->update(dirtyBoundingRect.adjusted(-2, -2, 2, 2));
     859    } else {
     860        viewport->update(dirtyRegion); // Already adjusted in updateRect/Region.
     861    }
     862
    923863    dirtyBoundingRect = QRect();
    924     updatingLater = false;
    925 }
    926 
    927 void QGraphicsViewPrivate::updateAll()
    928 {
    929     Q_Q(QGraphicsView);
    930     q->viewport()->update();
    931     fullUpdatePending = true;
    932     dirtyRectCount = 0;
    933     dirtyBoundingRect = QRect();
    934     updatingLater = false;
    935 }
    936 
    937 void QGraphicsViewPrivate::updateRegion(const QRegion &r)
    938 {
    939     if (r.isEmpty())
    940         return;
    941 
    942     Q_Q(QGraphicsView);
    943 
    944     // Rect intersects viewport - update everything?
     864    dirtyRegion = QRegion();
     865}
     866
     867static inline bool intersectsViewport(const QRect &r, int width, int height)
     868{ return !(r.left() > width) && !(r.right() < 0) && !(r.top() >= height) && !(r.bottom() < 0); }
     869
     870static inline bool containsViewport(const QRect &r, int width, int height)
     871{ return r.left() <= 0 && r.top() <= 0 && r.right() >= width - 1 && r.bottom() >= height - 1; }
     872
     873static inline void QRect_unite(QRect *rect, const QRect &other)
     874{
     875    if (rect->isEmpty()) {
     876        *rect = other;
     877    } else {
     878        rect->setCoords(qMin(rect->left(), other.left()), qMin(rect->top(), other.top()),
     879                        qMax(rect->right(), other.right()), qMax(rect->bottom(), other.bottom()));
     880    }
     881}
     882
     883bool QGraphicsViewPrivate::updateRegion(const QRegion &r)
     884{
     885    if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate || r.isEmpty())
     886        return false;
     887
     888    const QRect boundingRect = r.boundingRect();
     889    if (!intersectsViewport(boundingRect, viewport->width(), viewport->height()))
     890        return false; // Update region outside viewport.
     891
    945892    switch (viewportUpdateMode) {
    946893    case QGraphicsView::FullViewportUpdate:
    947894        fullUpdatePending = true;
    948         q->viewport()->update();
     895        viewport->update();
    949896        break;
    950897    case QGraphicsView::BoundingRectViewportUpdate:
    951         dirtyBoundingRect |= r.boundingRect();
    952         if (dirtyBoundingRect == q->viewport()->rect()) {
     898        QRect_unite(&dirtyBoundingRect, boundingRect);
     899        if (containsViewport(dirtyBoundingRect, viewport->width(), viewport->height())) {
    953900            fullUpdatePending = true;
    954             q->viewport()->update();
    955         } else {
    956             updateLater();
     901            viewport->update();
    957902        }
    958903        break;
    959     case QGraphicsView::SmartViewportUpdate:
    960         dirtyBoundingRect |= r.boundingRect();
    961         if ((dirtyRectCount + r.numRects()) < QGRAPHICSVIEW_REGION_RECT_THRESHOLD)
    962             dirtyRegions << r;
    963         dirtyRectCount += r.numRects();
    964         updateLater();
     904    case QGraphicsView::SmartViewportUpdate: // ### DEPRECATE
     905    case QGraphicsView::MinimalViewportUpdate:
     906    {
     907        const QVector<QRect> &rects = r.rects();
     908        for (int i = 0; i < rects.size(); ++i) {
     909            if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
     910                dirtyRegion += rects.at(i).adjusted(-1, -1, 1, 1);
     911            else
     912                dirtyRegion += rects.at(i).adjusted(-2, -2, 2, 2);
     913        }
    965914        break;
    966     case QGraphicsView::MinimalViewportUpdate:
    967         dirtyRegions << r;
    968         dirtyRectCount += r.numRects();
    969         updateLater();
     915    }
     916    default:
    970917        break;
    971     case QGraphicsView::NoViewportUpdate:
    972         // Unreachable
    973         break;
    974     }
    975 
    976     // Compress the regions...
    977     if (dirtyRectCount > QGRAPHICSVIEW_REGION_RECT_THRESHOLD && dirtyRegions.size() > 1) {
    978         QRegion masterRegion;
    979         for (int i=0; i<dirtyRegions.size(); ++i) {
    980             masterRegion |= dirtyRegions.at(i);
    981         }
    982         dirtyRectCount = masterRegion.numRects();
    983         dirtyRegions.clear();
    984         dirtyRegions << masterRegion;
    985     }
    986 }
    987 
    988 void QGraphicsViewPrivate::updateRect(const QRect &r)
    989 {
    990     if (r.isEmpty())
    991         return;
    992 
    993     Q_Q(QGraphicsView);
    994 
    995     // Rect intersects viewport - update everything?
     918    }
     919
     920    return true;
     921}
     922
     923bool QGraphicsViewPrivate::updateRect(const QRect &r)
     924{
     925    if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate
     926        || !intersectsViewport(r, viewport->width(), viewport->height())) {
     927        return false;
     928    }
     929
    996930    switch (viewportUpdateMode) {
    997931    case QGraphicsView::FullViewportUpdate:
    998932        fullUpdatePending = true;
    999         q->viewport()->update();
     933        viewport->update();
    1000934        break;
    1001935    case QGraphicsView::BoundingRectViewportUpdate:
    1002         dirtyBoundingRect |= r;
    1003         if (dirtyBoundingRect == q->viewport()->rect()) {
     936        QRect_unite(&dirtyBoundingRect, r);
     937        if (containsViewport(dirtyBoundingRect, viewport->width(), viewport->height())) {
    1004938            fullUpdatePending = true;
    1005             q->viewport()->update();
    1006         } else {
    1007             updateLater();
     939            viewport->update();
    1008940        }
    1009941        break;
    1010     case QGraphicsView::SmartViewportUpdate:
    1011         dirtyBoundingRect |= r;
    1012         if ((dirtyRectCount + dirtyRects.size()) < QGRAPHICSVIEW_REGION_RECT_THRESHOLD)
    1013             dirtyRects << r;
    1014         updateLater();
     942    case QGraphicsView::SmartViewportUpdate: // ### DEPRECATE
     943    case QGraphicsView::MinimalViewportUpdate:
     944        if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
     945            dirtyRegion += r.adjusted(-1, -1, 1, 1);
     946        else
     947            dirtyRegion += r.adjusted(-2, -2, 2, 2);
    1015948        break;
    1016     case QGraphicsView::MinimalViewportUpdate:
    1017         dirtyRects << r;
    1018         updateLater();
     949    default:
    1019950        break;
    1020     case QGraphicsView::NoViewportUpdate:
    1021         // Unreachable
    1022         break;
    1023     }
     951    }
     952
     953    return true;
    1024954}
    1025955
     
    1047977extern QPainterPath qt_regionToPath(const QRegion &region);
    1048978
    1049 QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(const QRegion &exposedRegion, bool *allItems) const
     979/*!
     980    ### Adjustments in findItems: mapToScene(QRect) forces us to adjust the
     981    input rectangle by (0, 0, 1, 1), because it uses QRect::bottomRight()
     982    (etc) when mapping the rectangle to a polygon (which is _wrong_). In
     983    addition, as QGraphicsItem::boundingRect() is defined in logical space,
     984    but the default pen for QPainter is cosmetic with a width of 0, QPainter
     985    is at risk of painting 1 pixel outside the bounding rect. Therefore we
     986    must search for items with an adjustment of (-1, -1, 1, 1).
     987*/
     988QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(const QRegion &exposedRegion, bool *allItems,
     989                                                       const QTransform &viewTransform) const
    1050990{
    1051991    Q_Q(const QGraphicsView);
    1052     const QPainterPath exposedPath(qt_regionToPath(exposedRegion));
    1053     const QPainterPath exposedScenePath(q->mapToScene(exposedPath));
    1054 
    1055     if (exposedScenePath.contains(scene->d_func()->growingItemsBoundingRect)) {
     992
     993    // Step 1) If all items are contained within the expose region, then
     994    // return a list of all visible items. ### the scene's growing bounding
     995    // rect does not take into account untransformable items.
     996    const QRectF exposedRegionSceneBounds = q->mapToScene(exposedRegion.boundingRect().adjusted(-1, -1, 1, 1))
     997                                            .boundingRect();
     998    if (exposedRegionSceneBounds.contains(scene->sceneRect())) {
    1056999        Q_ASSERT(allItems);
    10571000        *allItems = true;
    10581001
    1059         // All items are guaranteed within the exposed region, don't bother using the index.
    1060         QList<QGraphicsItem *> itemList(scene->items());
    1061         int i = 0;
    1062         while (i < itemList.size()) {
    1063             // But we only want to include items that are visible
    1064             if (!itemList.at(i)->isVisible())
    1065                 itemList.removeAt(i);
    1066             else
    1067                 ++i;
    1068         }
    1069 
    1070         // Sort the items.
    1071         QGraphicsScenePrivate::sortItems(&itemList, Qt::DescendingOrder, scene->d_func()->sortCacheEnabled);
    1072         return itemList;
    1073     }
    1074 
    1075     if (scene->d_func()->largestUntransformableItem.isNull()) {
    1076         if (exposedRegion.numRects() == 1 && matrix.type() <= QTransform::TxScale) {
    1077             return scene->d_func()->items_helper(exposedScenePath.controlPointRect(),
    1078                                                  Qt::IntersectsItemBoundingRect,
    1079                                                  Qt::DescendingOrder);
    1080         }
    1081         return scene->d_func()->items_helper(exposedScenePath,
    1082                                              Qt::IntersectsItemBoundingRect,
    1083                                              Qt::DescendingOrder);
    1084     }
    1085 
    1086     // NB! Path must be in viewport coordinates.
    1087     return itemsInArea(exposedPath, Qt::IntersectsItemBoundingRect, Qt::DescendingOrder);
    1088 }
    1089 
    1090 void QGraphicsViewPrivate::generateStyleOptions(const QList<QGraphicsItem *> &itemList,
    1091                                                 QGraphicsItem **itemArray,
    1092                                                 QStyleOptionGraphicsItem *styleOptionArray,
    1093                                                 const QTransform &worldTransform,
    1094                                                 bool allItems,
    1095                                                 const QRegion &exposedRegion) const
    1096 {
    1097     // Two unit vectors.
    1098     QLineF v1(0, 0, 1, 0);
    1099     QLineF v2(0, 0, 0, 1);
    1100     QTransform itemToViewportTransform;
    1101     QRectF brect;
    1102     QTransform reverseMap;
    1103 
    1104     for (int i = 0; i < itemList.size(); ++i) {
    1105         QGraphicsItem *item = itemArray[i] = itemList[i];
    1106 
    1107         QStyleOptionGraphicsItem &option = styleOptionArray[i];
    1108         brect = item->boundingRect();
    1109         option.state = QStyle::State_None;
    1110         option.rect = brect.toRect();
    1111         option.exposedRect = QRectF();
    1112         if (item->d_ptr->selected)
    1113             option.state |= QStyle::State_Selected;
    1114         if (item->d_ptr->enabled)
    1115             option.state |= QStyle::State_Enabled;
    1116         if (item->hasFocus())
    1117             option.state |= QStyle::State_HasFocus;
    1118         if (scene->d_func()->hoverItems.contains(item))
    1119             option.state |= QStyle::State_MouseOver;
    1120         if (item == scene->mouseGrabberItem())
    1121             option.state |= QStyle::State_Sunken;
    1122 
    1123         // Calculate a simple level-of-detail metric.
    1124         // ### almost identical code in QGraphicsScene::render()
    1125         //     and QGraphicsView::render() - consider refactoring
    1126         if (item->d_ptr->itemIsUntransformable()) {
    1127             itemToViewportTransform = item->deviceTransform(worldTransform);
    1128         } else {
    1129             itemToViewportTransform = item->sceneTransform() * worldTransform;
    1130         }
    1131 
    1132         if (itemToViewportTransform.type() <= QTransform::TxTranslate) {
    1133             // Translation and rotation only? The LOD is 1.
    1134             option.levelOfDetail = 1;
    1135         } else {
    1136             // LOD is the transformed area of a 1x1 rectangle.
    1137             option.levelOfDetail = qSqrt(itemToViewportTransform.map(v1).length() * itemToViewportTransform.map(v2).length());
    1138         }
    1139         option.matrix = itemToViewportTransform.toAffine(); //### discards perspective
    1140 
    1141         if (!allItems) {
    1142             // Determine the item's exposed area
    1143             reverseMap = itemToViewportTransform.inverted();
    1144             foreach (const QRect &rect, exposedRegion.rects()) {
    1145                 option.exposedRect |= reverseMap.mapRect(QRectF(rect.adjusted(-1, -1, 1, 1)));
    1146                 if (option.exposedRect.contains(brect))
    1147                     break;
    1148             }
    1149             option.exposedRect &= brect;
    1150         } else {
    1151             // The whole item is exposed
    1152             option.exposedRect = brect;
    1153         }
    1154     }
     1002        // All items are guaranteed within the exposed region.
     1003        return scene->items(Qt::AscendingOrder);
     1004    }
     1005
     1006    // Step 2) If the expose region is a simple rect and the view is only
     1007    // translated or scaled, search for items using
     1008    // QGraphicsScene::items(QRectF).
     1009    bool simpleRectLookup =  exposedRegion.rectCount() == 1 && matrix.type() <= QTransform::TxScale;
     1010    if (simpleRectLookup) {
     1011        return scene->items(exposedRegionSceneBounds,
     1012                            Qt::IntersectsItemBoundingRect,
     1013                            Qt::AscendingOrder, viewTransform);
     1014    }
     1015
     1016    // If the region is complex or the view has a complex transform, adjust
     1017    // the expose region, convert it to a path, and then search for items
     1018    // using QGraphicsScene::items(QPainterPath);
     1019    QRegion adjustedRegion;
     1020    foreach (const QRect &r, exposedRegion.rects())
     1021        adjustedRegion += r.adjusted(-1, -1, 1, 1);
     1022
     1023    const QPainterPath exposedScenePath(q->mapToScene(qt_regionToPath(adjustedRegion)));
     1024    return scene->items(exposedScenePath, Qt::IntersectsItemBoundingRect,
     1025                        Qt::AscendingOrder, viewTransform);
     1026}
     1027
     1028/*!
     1029    \internal
     1030
     1031    Enables input methods for the view if and only if the current focus item of
     1032    the scene accepts input methods. Call function whenever that condition has
     1033    potentially changed.
     1034*/
     1035void QGraphicsViewPrivate::updateInputMethodSensitivity()
     1036{
     1037    Q_Q(QGraphicsView);
     1038    bool enabled = scene && scene->focusItem()
     1039                   && (scene->focusItem()->flags() & QGraphicsItem::ItemAcceptsInputMethod);
     1040    q->setAttribute(Qt::WA_InputMethodEnabled, enabled);
     1041    q->viewport()->setAttribute(Qt::WA_InputMethodEnabled, enabled);
    11551042}
    11561043
     
    11641051    setAcceptDrops(true);
    11651052    setBackgroundRole(QPalette::Base);
    1166 
    1167     // ### Ideally this would be enabled/disabled depending on whether any
    1168     // widgets in the current scene enabled input methods. We could do that
    1169     // using a simple reference count. The same goes for acceptDrops and mouse
    1170     // tracking.
     1053    // Investigate leaving these disabled by default.
    11711054    setAttribute(Qt::WA_InputMethodEnabled);
     1055    viewport()->setAttribute(Qt::WA_InputMethodEnabled);
    11721056}
    11731057
     
    11831067    setAcceptDrops(true);
    11841068    setBackgroundRole(QPalette::Base);
     1069    // Investigate leaving these disabled by default.
    11851070    setAttribute(Qt::WA_InputMethodEnabled);
     1071    viewport()->setAttribute(Qt::WA_InputMethodEnabled);
    11861072}
    11871073
     
    11951081    setAcceptDrops(true);
    11961082    setBackgroundRole(QPalette::Base);
     1083    // Investigate leaving these disabled by default.
    11971084    setAttribute(Qt::WA_InputMethodEnabled);
     1085    viewport()->setAttribute(Qt::WA_InputMethodEnabled);
    11981086}
    11991087
     
    12491137        return;
    12501138    d->renderHints = hints;
    1251     viewport()->update();
     1139    d->updateAll();
    12521140}
    12531141
     
    12671155        d->renderHints &= ~hint;
    12681156    if (oldHints != d->renderHints)
    1269         viewport()->update();
     1157        d->updateAll();
    12701158}
    12711159
     
    13231211    Q_D(QGraphicsView);
    13241212    d->transformationAnchor = anchor;
     1213
     1214    // Ensure mouse tracking is enabled in the case we are using AnchorUnderMouse
     1215    // in order to have up-to-date information for centering the view.
     1216    if (d->transformationAnchor == AnchorUnderMouse)
     1217        d->viewport->setMouseTracking(true);
    13251218}
    13261219
     
    13501243    Q_D(QGraphicsView);
    13511244    d->resizeAnchor = anchor;
     1245
     1246    // Ensure mouse tracking is enabled in the case we are using AnchorUnderMouse
     1247    // in order to have up-to-date information for centering the view.
     1248    if (d->resizeAnchor == AnchorUnderMouse)
     1249        d->viewport->setMouseTracking(true);
    13521250}
    13531251
     
    15541452        // Background caching is enabled.
    15551453        d->mustResizeBackgroundPixmap = true;
    1556         viewport()->update();
     1454        d->updateAll();
    15571455    } else if (d->mustResizeBackgroundPixmap) {
    15581456        // Background caching is disabled.
     
    16431541
    16441542    // Always update the viewport when the scene changes.
    1645     viewport()->update();
     1543    d->updateAll();
    16461544
    16471545    // Remove the previously assigned scene.
     
    16511549        disconnect(d->scene, SIGNAL(sceneRectChanged(QRectF)),
    16521550                   this, SLOT(updateSceneRect(QRectF)));
    1653         d->scene->d_func()->views.removeAll(this);
     1551        d->scene->d_func()->removeView(this);
     1552        d->connectedToScene = false;
     1553
     1554        if (isActiveWindow() && isVisible()) {
     1555            QEvent windowDeactivate(QEvent::WindowDeactivate);
     1556            QApplication::sendEvent(d->scene, &windowDeactivate);
     1557        }
     1558        if(hasFocus())
     1559            d->scene->clearFocus();
    16541560    }
    16551561
     
    16591565                this, SLOT(updateSceneRect(QRectF)));
    16601566        d->updateSceneSlotReimplementedChecked = false;
    1661         d->scene->d_func()->views << this;
     1567        d->scene->d_func()->addView(this);
    16621568        d->recalculateContentSize();
    16631569        d->lastCenterPoint = sceneRect().center();
    16641570        d->keepLastCenterPoint = true;
     1571        // We are only interested in mouse tracking if items accept
     1572        // hover events or use non-default cursors.
     1573        if (!d->scene->d_func()->allItemsIgnoreHoverEvents
     1574            || !d->scene->d_func()->allItemsUseDefaultCursor) {
     1575            d->viewport->setMouseTracking(true);
     1576        }
     1577
     1578        // enable touch events if any items is interested in them
     1579        if (!d->scene->d_func()->allItemsIgnoreTouchEvents)
     1580            d->viewport->setAttribute(Qt::WA_AcceptTouchEvents);
     1581
     1582        if (isActiveWindow() && isVisible()) {
     1583            QEvent windowActivate(QEvent::WindowActivate);
     1584            QApplication::sendEvent(d->scene, &windowActivate);
     1585        }
    16651586    } else {
    16661587        d->recalculateContentSize();
    16671588    }
     1589
     1590    d->updateInputMethodSensitivity();
     1591
     1592    if (d->scene && hasFocus())
     1593        d->scene->setFocus();
    16681594}
    16691595
     
    17121638    transformation is set, the identity matrix is returned.
    17131639
    1714     \sa setMatrix(), rotate(), scale(), shear(), translate()
     1640    \sa setMatrix(), transform(), rotate(), scale(), shear(), translate()
    17151641*/
    17161642QMatrix QGraphicsView::matrix() const
     
    17441670    to map from floating point scene coordinates to view coordinates.
    17451671
    1746     \sa matrix(), rotate(), scale(), shear(), translate()
     1672    \sa matrix(), setTransform(), rotate(), scale(), shear(), translate()
    17471673*/
    17481674void QGraphicsView::setMatrix(const QMatrix &matrix, bool combine)
     
    17531679/*!
    17541680    Resets the view transformation matrix to the identity matrix.
     1681
     1682    \sa resetTransform()
    17551683*/
    17561684void QGraphicsView::resetMatrix()
     
    17621690    Rotates the current view transformation \a angle degrees clockwise.
    17631691
    1764     \sa setMatrix(), matrix(), scale(), shear(), translate()
     1692    \sa setTransform(), transform(), scale(), shear(), translate()
    17651693*/
    17661694void QGraphicsView::rotate(qreal angle)
     
    17751703    Scales the current view transformation by (\a sx, \a sy).
    17761704
    1777     \sa setMatrix(), matrix(), rotate(), shear(), translate()
     1705    \sa setTransform(), transform(), rotate(), shear(), translate()
    17781706*/
    17791707void QGraphicsView::scale(qreal sx, qreal sy)
     
    17881716    Shears the current view transformation by (\a sh, \a sv).
    17891717
    1790     \sa setMatrix(), matrix(), rotate(), scale(), translate()
     1718    \sa setTransform(), transform(), rotate(), scale(), translate()
    17911719*/
    17921720void QGraphicsView::shear(qreal sh, qreal sv)
     
    18011729    Translates the current view transformation by (\a dx, \a dy).
    18021730
    1803     \sa setMatrix(), matrix(), rotate(), shear()
     1731    \sa setTransform(), transform(), rotate(), shear()
    18041732*/
    18051733void QGraphicsView::translate(qreal dx, qreal dy)
     
    19591887    function will do nothing.
    19601888
    1961     \sa setMatrix(), ensureVisible(), centerOn()
     1889    \sa setTransform(), ensureVisible(), centerOn()
    19621890*/
    19631891void QGraphicsView::fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRatioMode)
     
    20241952{
    20251953    QPainterPath path = item->isClipped() ? item->clipPath() : item->shape();
    2026     fitInView(item->sceneTransform().map(path).boundingRect(), aspectRatioMode);
     1954    if (item->d_ptr->hasTranslateOnlySceneTransform()) {
     1955        path.translate(item->d_ptr->sceneTransform.dx(), item->d_ptr->sceneTransform.dy());
     1956        fitInView(path.boundingRect(), aspectRatioMode);
     1957    } else {
     1958        fitInView(item->d_ptr->sceneTransform.map(path).boundingRect(), aspectRatioMode);
     1959    }
    20271960}
    20281961
     
    20501983                           Qt::AspectRatioMode aspectRatioMode)
    20511984{
     1985    // ### Switch to using the recursive rendering algorithm instead.
     1986
    20521987    Q_D(QGraphicsView);
    20531988    if (!d->scene || !(painter && painter->isActive()))
     
    20962031
    20972032    // Setup painter matrix.
    2098     QTransform moveMatrix;
    2099     moveMatrix.translate(-d->horizontalScroll(), -d->verticalScroll());
     2033    QTransform moveMatrix = QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll());
    21002034    QTransform painterMatrix = d->matrix * moveMatrix;
    21012035    painterMatrix *= QTransform()
     
    21042038                     .translate(-sourceRect.left(), -sourceRect.top());
    21052039
    2106     // Two unit vectors.
    2107     QLineF v1(0, 0, 1, 0);
    2108     QLineF v2(0, 0, 0, 1);
    2109 
    21102040    // Generate the style options
    21112041    QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems);
    2112     QStyleOptionGraphicsItem* option = styleOptionArray;
    2113     for (int i = 0; i < numItems; ++i, ++option) {
    2114         QGraphicsItem *item = itemArray[i];
    2115 
    2116         option->state = QStyle::State_None;
    2117         option->rect = item->boundingRect().toRect();
    2118         if (item->isSelected())
    2119             option->state |= QStyle::State_Selected;
    2120         if (item->isEnabled())
    2121             option->state |= QStyle::State_Enabled;
    2122         if (item->hasFocus())
    2123             option->state |= QStyle::State_HasFocus;
    2124         if (d->scene->d_func()->hoverItems.contains(item))
    2125             option->state |= QStyle::State_MouseOver;
    2126         if (item == d->scene->mouseGrabberItem())
    2127             option->state |= QStyle::State_Sunken;
    2128 
    2129         // Calculate a simple level-of-detail metric.
    2130         // ### almost identical code in QGraphicsScene::render()
    2131         //     and QGraphicsView::paintEvent() - consider refactoring
    2132         QTransform itemToViewportTransform;
    2133         if (item->d_ptr->itemIsUntransformable()) {
    2134             itemToViewportTransform = item->deviceTransform(painterMatrix);
    2135         } else {
    2136             itemToViewportTransform = item->sceneTransform() * painterMatrix;
    2137         }
    2138 
    2139         option->levelOfDetail = qSqrt(itemToViewportTransform.map(v1).length() * itemToViewportTransform.map(v2).length());
    2140         option->matrix = itemToViewportTransform.toAffine();
    2141 
    2142         option->exposedRect = item->boundingRect();
    2143         option->exposedRect &= itemToViewportTransform.inverted().mapRect(targetRect);
    2144     }
     2042    for (int i = 0; i < numItems; ++i)
     2043        itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], painterMatrix, targetRect.toRect());
    21452044
    21462045    painter->save();
     
    21692068
    21702069/*!
    2171     Returns a list of all the items in the associated scene.
    2172 
    2173     \sa QGraphicsScene::items()
     2070    Returns a list of all the items in the associated scene, in descending
     2071    stacking order (i.e., the first item in the returned list is the uppermost
     2072    item).
     2073
     2074    \sa QGraphicsScene::items(), {QGraphicsItem#Sorting}{Sorting}
    21742075*/
    21752076QList<QGraphicsItem *> QGraphicsView::items() const
     
    21822083
    21832084/*!
    2184     Returns all items in the area \a path, which is in viewport coordinates,
    2185     also taking untransformable items into consideration. This function is
    2186     considerably slower than just checking the scene directly. There is
    2187     certainly room for improvement.
    2188 */
    2189 QList<QGraphicsItem *> QGraphicsViewPrivate::itemsInArea(const QPainterPath &path,
    2190                                                          Qt::ItemSelectionMode mode,
    2191                                                          Qt::SortOrder order) const
    2192 {
    2193     Q_Q(const QGraphicsView);
    2194 
    2195     // Determine the size of the largest untransformable subtree of children
    2196     // mapped to scene coordinates.
    2197     QRectF untr = scene->d_func()->largestUntransformableItem;
    2198     QRectF ltri = matrix.inverted().mapRect(untr);
    2199     ltri.adjust(-untr.width(), -untr.height(), untr.width(), untr.height());
    2200 
    2201     QRectF rect = path.controlPointRect();
    2202 
    2203     // Find all possible items in the relevant area.
    2204     // ### Improve this algorithm; it might be searching a too large area.
    2205     QRectF adjustedRect = q->mapToScene(rect.adjusted(-1, -1, 1, 1).toRect()).boundingRect();
    2206     adjustedRect.adjust(-ltri.width(), -ltri.height(), ltri.width(), ltri.height());
    2207 
    2208     // First build a (potentially large) list of all items in the vicinity
    2209     // that might be untransformable.
    2210     QList<QGraphicsItem *> allCandidates = scene->d_func()->estimateItemsInRect(adjustedRect);
    2211 
    2212     // Then find the minimal list of items that are inside \a path, and
    2213     // convert it to a set.
    2214     QList<QGraphicsItem *> regularCandidates = scene->items(q->mapToScene(path), mode);
    2215     QSet<QGraphicsItem *> candSet = QSet<QGraphicsItem *>::fromList(regularCandidates);
    2216 
    2217     QTransform viewMatrix = q->viewportTransform();
    2218 
    2219     QList<QGraphicsItem *> result;
    2220 
    2221     // Run through all candidates and keep all items that are in candSet, or
    2222     // are untransformable and collide with \a path. ### We can improve this
    2223     // algorithm.
    2224     QList<QGraphicsItem *>::Iterator it = allCandidates.begin();
    2225     while (it != allCandidates.end()) {
    2226         QGraphicsItem *item = *it;
    2227         if (item->d_ptr->itemIsUntransformable()) {
    2228             // Check if this untransformable item collides with the
    2229             // original selection rect.
    2230             QTransform itemTransform = item->deviceTransform(viewMatrix);
    2231             if (QGraphicsScenePrivate::itemCollidesWithPath(item, itemTransform.inverted().map(path), mode))
    2232                 result << item;
    2233         } else {
    2234             if (candSet.contains(item))
    2235                 result << item;
    2236         }
    2237         ++it;
    2238     }
    2239 
    2240     // ### Insertion sort would be faster.
    2241     if (order != Qt::SortOrder(-1))
    2242         QGraphicsScenePrivate::sortItems(&result, order, scene->d_func()->sortCacheEnabled);
    2243     return result;
    2244 }
    2245 
    2246 /*!
    22472085    Returns a list of all the items at the position \a pos in the view. The
    2248     items are listed in descending Z order (i.e., the first item in the list
    2249     is the top-most item, and the last item is the bottom-most item). \a pos
    2250     is in viewport coordinates.
     2086    items are listed in descending stacking order (i.e., the first item in the
     2087    list is the uppermost item, and the last item is the lowermost item). \a
     2088    pos is in viewport coordinates.
    22512089
    22522090    This function is most commonly called from within mouse event handlers in
     
    22562094    \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 5
    22572095
    2258     \sa QGraphicsScene::items(), QGraphicsItem::zValue()
     2096    \sa QGraphicsScene::items(), {QGraphicsItem#Sorting}{Sorting}
    22592097*/
    22602098QList<QGraphicsItem *> QGraphicsView::items(const QPoint &pos) const
     
    22632101    if (!d->scene)
    22642102        return QList<QGraphicsItem *>();
    2265     if (d->scene->d_func()->largestUntransformableItem.isNull()) {
    2266         if ((d->identityMatrix || d->matrix.type() <= QTransform::TxScale)) {
    2267             QTransform xinv = viewportTransform().inverted();
    2268             return d->scene->items(xinv.mapRect(QRectF(pos.x(), pos.y(), 1, 1)));
    2269         }
    2270         return d->scene->items(mapToScene(pos.x(), pos.y(), 2, 2));
    2271     }
    2272 
    2273     QPainterPath path;
    2274     path.addRect(QRectF(pos.x(), pos.y(), 1, 1));
    2275     return d->itemsInArea(path);
     2103    // ### Unify these two, and use the items(QPointF) version in
     2104    // QGraphicsScene instead. The scene items function could use the viewport
     2105    // transform to map the point to a rect/polygon.
     2106    if ((d->identityMatrix || d->matrix.type() <= QTransform::TxScale)) {
     2107        // Use the rect version
     2108        QTransform xinv = viewportTransform().inverted();
     2109        return d->scene->items(xinv.mapRect(QRectF(pos.x(), pos.y(), 1, 1)),
     2110                               Qt::IntersectsItemShape,
     2111                               Qt::DescendingOrder,
     2112                               viewportTransform());
     2113    }
     2114    // Use the polygon version
     2115    return d->scene->items(mapToScene(pos.x(), pos.y(), 1, 1),
     2116                           Qt::IntersectsItemShape,
     2117                           Qt::DescendingOrder,
     2118                           viewportTransform());
    22762119}
    22772120
     
    22932136    exact shape intersects with or is contained by \a rect are returned.
    22942137
    2295     \sa itemAt(), items(), mapToScene()
     2138    The items are sorted in descending stacking order (i.e., the first item in
     2139    the returned list is the uppermost item).
     2140
     2141    \sa itemAt(), items(), mapToScene(), {QGraphicsItem#Sorting}{Sorting}
    22962142*/
    22972143QList<QGraphicsItem *> QGraphicsView::items(const QRect &rect, Qt::ItemSelectionMode mode) const
     
    23002146    if (!d->scene)
    23012147        return QList<QGraphicsItem *>();
    2302     if (d->scene->d_func()->largestUntransformableItem.isNull())
    2303         return d->scene->items(mapToScene(rect), mode);
    2304 
    2305     QPainterPath path;
    2306     path.addRect(rect);
    2307     return d->itemsInArea(path);
     2148    return d->scene->items(mapToScene(rect), mode, Qt::DescendingOrder, viewportTransform());
    23082149}
    23092150
     
    23262167    exact shape intersects with or is contained by \a polygon are returned.
    23272168
    2328     \sa itemAt(), items(), mapToScene()
     2169    The items are sorted by descending stacking order (i.e., the first item in
     2170    the returned list is the uppermost item).
     2171
     2172    \sa itemAt(), items(), mapToScene(), {QGraphicsItem#Sorting}{Sorting}
    23292173*/
    23302174QList<QGraphicsItem *> QGraphicsView::items(const QPolygon &polygon, Qt::ItemSelectionMode mode) const
     
    23332177    if (!d->scene)
    23342178        return QList<QGraphicsItem *>();
    2335     if (d->scene->d_func()->largestUntransformableItem.isNull())
    2336         return d->scene->items(mapToScene(polygon), mode);
    2337 
    2338     QPainterPath path;
    2339     path.addPolygon(polygon);
    2340     path.closeSubpath();
    2341     return d->itemsInArea(path);
     2179    return d->scene->items(mapToScene(polygon), mode, Qt::DescendingOrder, viewportTransform());
    23422180}
    23432181
     
    23522190    exact shape intersects with or is contained by \a path are returned.
    23532191
    2354     \sa itemAt(), items(), mapToScene()
     2192    \sa itemAt(), items(), mapToScene(), {QGraphicsItem#Sorting}{Sorting}
    23552193*/
    23562194QList<QGraphicsItem *> QGraphicsView::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const
     
    23592197    if (!d->scene)
    23602198        return QList<QGraphicsItem *>();
    2361     if (d->scene->d_func()->largestUntransformableItem.isNull())
    2362         return d->scene->items(mapToScene(path), mode);
    2363     return d->itemsInArea(path);
     2199    return d->scene->items(mapToScene(path), mode, Qt::DescendingOrder, viewportTransform());
    23642200}
    23652201
     
    23732209    \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsview.cpp 6
    23742210
    2375     \sa items()
     2211    \sa items(), {QGraphicsItem#Sorting}{Sorting}
    23762212*/
    23772213QGraphicsItem *QGraphicsView::itemAt(const QPoint &pos) const
     
    24302266
    24312267    QPointF scrollOffset(d->horizontalScroll(), d->verticalScroll());
    2432     QPointF tl = scrollOffset + rect.topLeft();
    2433     QPointF tr = scrollOffset + rect.topRight();
    2434     QPointF br = scrollOffset + rect.bottomRight();
    2435     QPointF bl = scrollOffset + rect.bottomLeft();
    2436 
    2437     QPolygonF poly;
    2438     poly.resize(4);
     2268    QRect r = rect.adjusted(0, 0, 1, 1);
     2269    QPointF tl = scrollOffset + r.topLeft();
     2270    QPointF tr = scrollOffset + r.topRight();
     2271    QPointF br = scrollOffset + r.bottomRight();
     2272    QPointF bl = scrollOffset + r.bottomLeft();
     2273
     2274    QPolygonF poly(4);
    24392275    if (!d->identityMatrix) {
    24402276        QTransform x = d->matrix.inverted();
     
    24822318{
    24832319    Q_D(const QGraphicsView);
    2484     QTransform moveMatrix;
    2485     moveMatrix.translate(d->horizontalScroll(), d->verticalScroll());
    2486     return (moveMatrix * d->matrix.inverted()).map(path);
     2320    QTransform matrix = QTransform::fromTranslate(d->horizontalScroll(), d->verticalScroll());
     2321    matrix *= d->matrix.inverted();
     2322    return matrix.map(path);
    24872323}
    24882324
     
    25392375    bl -= scrollOffset;
    25402376
    2541     QPolygon poly;
    2542     poly.resize(4);
     2377    QPolygon poly(4);
    25432378    poly[0] = tl.toPoint();
    25442379    poly[1] = tr.toPoint();
     
    25782413{
    25792414    Q_D(const QGraphicsView);
    2580     QTransform moveMatrix;
    2581     moveMatrix.translate(-d->horizontalScroll(), -d->verticalScroll());
    2582     return (d->matrix * moveMatrix).map(path);
     2415    QTransform matrix = d->matrix;
     2416    matrix *= QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll());
     2417    return matrix.map(path);
    25832418}
    25842419
     
    26262461    Q_D(QGraphicsView);
    26272462    d->backgroundBrush = brush;
    2628     viewport()->update();
     2463    d->updateAll();
    26292464
    26302465    if (d->cacheMode & CacheBackground) {
     
    26562491    Q_D(QGraphicsView);
    26572492    d->foregroundBrush = brush;
    2658     viewport()->update();
     2493    d->updateAll();
    26592494}
    26602495
     
    26772512    // Extract and reset dirty scene rect info.
    26782513    QVector<QRect> dirtyViewportRects;
    2679     for (int i = 0; i < d->dirtyRegions.size(); ++i)
    2680         dirtyViewportRects += d->dirtyRegions.at(i).rects();
    2681     d->dirtyRegions.clear();
     2514    const QVector<QRect> &dirtyRects = d->dirtyRegion.rects();
     2515    for (int i = 0; i < dirtyRects.size(); ++i)
     2516        dirtyViewportRects += dirtyRects.at(i);
     2517    d->dirtyRegion = QRegion();
     2518    d->dirtyBoundingRect = QRect();
    26822519
    26832520    bool fullUpdate = !d->accelerateScrolling || d->viewportUpdateMode == QGraphicsView::FullViewportUpdate;
     
    27632600    const bool isGLWidget = widget->inherits("QGLWidget");
    27642601
    2765     d->accelerateScrolling = !(isGLWidget
    2766                                || widget->testAttribute(Qt::WA_MSWindowsUseDirect3D)
    2767                                || qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault));
     2602    d->accelerateScrolling = !(isGLWidget);
    27682603
    27692604    widget->setFocusPolicy(Qt::StrongFocus);
     
    27742609    }
    27752610
    2776     widget->setMouseTracking(true);
     2611    // We are only interested in mouse tracking if items
     2612    // accept hover events or use non-default cursors or if
     2613    // AnchorUnderMouse is used as transformation or resize anchor.
     2614    if ((d->scene && (!d->scene->d_func()->allItemsIgnoreHoverEvents
     2615                     || !d->scene->d_func()->allItemsUseDefaultCursor))
     2616        || d->transformationAnchor == AnchorUnderMouse
     2617        || d->resizeAnchor == AnchorUnderMouse) {
     2618        widget->setMouseTracking(true);
     2619    }
     2620
     2621    // enable touch events if any items is interested in them
     2622    if (d->scene && !d->scene->d_func()->allItemsIgnoreTouchEvents)
     2623        widget->setAttribute(Qt::WA_AcceptTouchEvents);
     2624
    27772625    widget->setAcceptDrops(acceptDrops());
    27782626}
     
    28252673{
    28262674    Q_D(QGraphicsView);
    2827 
    28282675    if (!d->scene)
    28292676        return QAbstractScrollArea::viewportEvent(event);
     
    28442691            d->scene->d_func()->removePopup(d->scene->d_func()->popupWidgets.first());
    28452692        QApplication::sendEvent(d->scene, event);
     2693        break;
     2694    case QEvent::Show:
     2695        if (d->scene && isActiveWindow()) {
     2696            QEvent windowActivate(QEvent::WindowActivate);
     2697            QApplication::sendEvent(d->scene, &windowActivate);
     2698        }
     2699        break;
     2700    case QEvent::Hide:
     2701        // spontaneous event will generate a WindowDeactivate.
     2702        if (!event->spontaneous() && d->scene && isActiveWindow()) {
     2703            QEvent windowDeactivate(QEvent::WindowDeactivate);
     2704            QApplication::sendEvent(d->scene, &windowDeactivate);
     2705        }
    28462706        break;
    28472707    case QEvent::Leave:
     
    28732733        // Reset full update
    28742734        d->fullUpdatePending = false;
     2735        d->dirtyScrollOffset = QPoint();
    28752736        if (d->scene) {
    28762737            // Check if this view reimplements the updateScene slot; if it
     
    28912752        }
    28922753        break;
     2754    case QEvent::TouchBegin:
     2755    case QEvent::TouchUpdate:
     2756    case QEvent::TouchEnd:
     2757    {
     2758        if (!isEnabled())
     2759            return false;
     2760
     2761        if (d->scene && d->sceneInteractionAllowed) {
     2762            // Convert and deliver the touch event to the scene.
     2763            QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event);
     2764            touchEvent->setWidget(viewport());
     2765            QGraphicsViewPrivate::translateTouchEvent(d, touchEvent);
     2766            (void) QApplication::sendEvent(d->scene, touchEvent);
     2767        }
     2768
     2769        return true;
     2770    }
     2771    case QEvent::Gesture:
     2772    case QEvent::GestureOverride:
     2773    {
     2774        if (!isEnabled())
     2775            return false;
     2776
     2777        if (d->scene && d->sceneInteractionAllowed) {
     2778            QGestureEvent *gestureEvent = static_cast<QGestureEvent *>(event);
     2779            gestureEvent->setWidget(viewport());
     2780            (void) QApplication::sendEvent(d->scene, gestureEvent);
     2781        }
     2782        return true;
     2783    }
    28932784    default:
    28942785        break;
     
    30642955{
    30652956    Q_D(QGraphicsView);
     2957    d->updateInputMethodSensitivity();
    30662958    QAbstractScrollArea::focusInEvent(event);
    30672959    if (d->scene)
     
    31493041    mouseEvent.setButton(event->button());
    31503042    mouseEvent.setModifiers(event->modifiers());
    3151     QApplication::sendEvent(d->scene, &mouseEvent);
     3043    if (event->spontaneous())
     3044        qt_sendSpontaneousEvent(d->scene, &mouseEvent);
     3045    else
     3046        QApplication::sendEvent(d->scene, &mouseEvent);
    31523047}
    31533048
     
    31883083            mouseEvent.setModifiers(event->modifiers());
    31893084            mouseEvent.setAccepted(false);
    3190             QApplication::sendEvent(d->scene, &mouseEvent);
     3085            if (event->spontaneous())
     3086                qt_sendSpontaneousEvent(d->scene, &mouseEvent);
     3087            else
     3088                QApplication::sendEvent(d->scene, &mouseEvent);
    31913089
    31923090            // Update the original mouse event accepted state.
     
    32493147                    viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect));
    32503148                else
    3251                     viewport()->update();
     3149                    d->updateAll();
    32523150            }
    32533151
     
    32713169                    viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect));
    32723170                else
    3273                     viewport()->update();
     3171                    d->updateAll();
    32743172            }
    32753173            // Set the new selection area
     
    32783176            selectionArea.closeSubpath();
    32793177            if (d->scene)
    3280                 d->scene->setSelectionArea(selectionArea, d->rubberBandSelectionMode);
     3178                d->scene->setSelectionArea(selectionArea, d->rubberBandSelectionMode,
     3179                                           viewportTransform());
    32813180            return;
    32823181        }
     
    33143213                    viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect));
    33153214                else
    3316                     viewport()->update();
     3215                    d->updateAll();
    33173216            }
    33183217            d->rubberBanding = false;
     
    33213220    } else
    33223221#endif
    3323     if (d->dragMode == QGraphicsView::ScrollHandDrag) {
     3222    if (d->dragMode == QGraphicsView::ScrollHandDrag && event->button() == Qt::LeftButton) {
    33243223#ifndef QT_NO_CURSOR
    33253224        // Restore the open hand cursor. ### There might be items
     
    33583257    mouseEvent.setModifiers(event->modifiers());
    33593258    mouseEvent.setAccepted(false);
    3360     QApplication::sendEvent(d->scene, &mouseEvent);
     3259    if (event->spontaneous())
     3260        qt_sendSpontaneousEvent(d->scene, &mouseEvent);
     3261    else
     3262        QApplication::sendEvent(d->scene, &mouseEvent);
    33613263
    33623264    // Update the last mouse event selected state.
     
    34163318
    34173319    // Determine the exposed region
    3418     QRegion exposedRegion = event->region();
    3419     if (!d->accelerateScrolling)
    3420         exposedRegion = viewport()->rect();
    3421     else if (d->viewportUpdateMode == BoundingRectViewportUpdate)
    3422         exposedRegion = event->rect();
    3423     QRectF exposedSceneRect = mapToScene(exposedRegion.boundingRect().adjusted(0, 0, 1, 1)).boundingRect();
     3320    d->exposedRegion = event->region();
     3321    QRectF exposedSceneRect = mapToScene(d->exposedRegion.boundingRect()).boundingRect();
    34243322
    34253323    // Set up the painter
    34263324    QPainter painter(viewport());
    3427     QTransform original = painter.worldTransform();
    34283325#ifndef QT_NO_RUBBERBAND
    34293326    if (d->rubberBanding && !d->rubberBandRect.isEmpty())
     
    34353332
    34363333    // Set up viewport transform
    3437     const QTransform viewTransform = viewportTransform();
    3438     painter.setTransform(viewTransform, true);
    3439 
    3440 #ifdef QGRAPHICSVIEW_DEBUG
    3441     QTime stopWatch;
    3442     stopWatch.start();
    3443     qDebug() << "QGraphicsView::paintEvent(" << exposedRegion << ")";
    3444 #endif
    3445 
    3446     // Find all exposed items
    3447     bool allItems = false;
    3448     QList<QGraphicsItem *> itemList = d->findItems(exposedRegion, &allItems);
    3449 
    3450 #ifdef QGRAPHICSVIEW_DEBUG
    3451     int exposedTime = stopWatch.elapsed();
    3452 #endif
    3453 
     3334    const bool viewTransformed = isTransformed();
     3335    if (viewTransformed)
     3336        painter.setWorldTransform(viewportTransform());
     3337    const QTransform viewTransform = painter.worldTransform();
     3338
     3339    // Draw background
    34543340    if ((d->cacheMode & CacheBackground)
    34553341#ifdef Q_WS_X11
     
    34743360            QPainter backgroundPainter(&d->backgroundPixmap);
    34753361            backgroundPainter.setClipRegion(d->backgroundPixmapExposed, Qt::ReplaceClip);
    3476             backgroundPainter.setTransform(viewportTransform());
    3477             drawBackground(&backgroundPainter, exposedSceneRect);
     3362            if (viewTransformed)
     3363                backgroundPainter.setTransform(viewTransform);
     3364#ifdef Q_WS_X11
     3365#undef X11
     3366            if (backgroundPainter.paintEngine()->type() != QPaintEngine::X11)
     3367#define X11 qt_x11Data
     3368#endif
     3369                backgroundPainter.setCompositionMode(QPainter::CompositionMode_Source);
     3370            QRectF backgroundExposedSceneRect = mapToScene(d->backgroundPixmapExposed.boundingRect()).boundingRect();
     3371            drawBackground(&backgroundPainter, backgroundExposedSceneRect);
    34783372            d->backgroundPixmapExposed = QRegion();
    34793373        }
    34803374
    34813375        // Blit the background from the background pixmap
    3482         QTransform oldMatrix = painter.worldTransform();
    3483         painter.setWorldTransform(original);
    3484         painter.drawPixmap(QPoint(), d->backgroundPixmap);
    3485         painter.setWorldTransform(oldMatrix);
     3376        if (viewTransformed) {
     3377            painter.setWorldTransform(QTransform());
     3378            painter.drawPixmap(QPoint(), d->backgroundPixmap);
     3379            painter.setWorldTransform(viewTransform);
     3380        } else {
     3381            painter.drawPixmap(QPoint(), d->backgroundPixmap);
     3382        }
    34863383    } else {
    34873384        if (!(d->optimizationFlags & DontSavePainterState))
     
    34923389    }
    34933390
    3494 #ifdef QGRAPHICSVIEW_DEBUG
    3495     int backgroundTime = stopWatch.elapsed() - exposedTime;
    3496 #endif
    3497 
    3498     // Generate the style options
    3499     QGraphicsItem **itemArray = new QGraphicsItem *[itemList.size()];
    3500     QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(itemList.size());
    3501 
    3502     d->generateStyleOptions(itemList, itemArray, styleOptionArray, viewTransform,
    3503                             allItems, exposedRegion);
    3504 
    35053391    // Items
    3506     drawItems(&painter, itemList.size(), itemArray, styleOptionArray);
    3507 
    3508 #ifdef QGRAPHICSVIEW_DEBUG
    3509     int itemsTime = stopWatch.elapsed() - exposedTime - backgroundTime;
    3510 #endif
     3392    if (!(d->optimizationFlags & IndirectPainting)) {
     3393        d->scene->d_func()->drawItems(&painter, viewTransformed ? &viewTransform : 0,
     3394                                      &d->exposedRegion, viewport());
     3395        // Make sure the painter's world transform is restored correctly when
     3396        // drawing without painter state protection (DontSavePainterState).
     3397        // We only change the worldTransform() so there's no need to do a full-blown
     3398        // save() and restore(). Also note that we don't have to do this in case of
     3399        // IndirectPainting (the else branch), because in that case we always save()
     3400        // and restore() in QGraphicsScene::drawItems().
     3401        if (!d->scene->d_func()->painterStateProtection)
     3402            painter.setWorldTransform(viewTransform);
     3403    } else {
     3404        // Find all exposed items
     3405        bool allItems = false;
     3406        QList<QGraphicsItem *> itemList = d->findItems(d->exposedRegion, &allItems, viewTransform);
     3407        if (!itemList.isEmpty()) {
     3408            // Generate the style options.
     3409            const int numItems = itemList.size();
     3410            QGraphicsItem **itemArray = &itemList[0]; // Relies on QList internals, but is perfectly valid.
     3411            QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems);
     3412            for (int i = 0; i < numItems; ++i) {
     3413                itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], viewTransform,
     3414                                                     d->exposedRegion, allItems);
     3415            }
     3416            // Draw the items.
     3417            drawItems(&painter, numItems, itemArray, styleOptionArray);
     3418            d->freeStyleOptionsArray(styleOptionArray);
     3419        }
     3420    }
    35113421
    35123422    // Foreground
    35133423    drawForeground(&painter, exposedSceneRect);
    3514 
    3515     delete [] itemArray;
    3516     d->freeStyleOptionsArray(styleOptionArray);
    3517 
    3518 #ifdef QGRAPHICSVIEW_DEBUG
    3519     int foregroundTime = stopWatch.elapsed() - exposedTime - backgroundTime - itemsTime;
    3520 #endif
    35213424
    35223425#ifndef QT_NO_RUBBERBAND
     
    35413444    painter.end();
    35423445
    3543 #ifdef QGRAPHICSVIEW_DEBUG
    3544     qDebug() << "\tItem discovery....... " << exposedTime << "msecs (" << itemList.size() << "items,"
    3545              << (exposedTime > 0 ? (itemList.size() * 1000.0 / exposedTime) : -1) << "/ sec )";
    3546     qDebug() << "\tDrawing background... " << backgroundTime << "msecs (" << exposedRegion.numRects() << "segments )";
    3547     qDebug() << "\tDrawing items........ " << itemsTime << "msecs ("
    3548              << (itemsTime > 0 ? (itemList.size() * 1000.0 / itemsTime) : -1) << "/ sec )";
    3549     qDebug() << "\tDrawing foreground... " << foregroundTime << "msecs (" << exposedRegion.numRects() << "segments )";
    3550     qDebug() << "\tTotal rendering time: " << stopWatch.elapsed() << "msecs ("
    3551              << (stopWatch.elapsed() > 0 ? (1000.0 / stopWatch.elapsed()) : -1.0) << "fps )";
    3552 #endif
    3553 
    35543446    // Restore painter state protection.
    35553447    d->scene->d_func()->painterStateProtection = true;
     
    35983490    if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate) {
    35993491        if (d->viewportUpdateMode != QGraphicsView::FullViewportUpdate) {
    3600             for (int i = 0; i < d->dirtyRects.size(); ++i)
    3601                 d->dirtyRects[i].translate(dx, dy);
    3602             for (int i = 0; i < d->dirtyRegions.size(); ++i)
    3603                 d->dirtyRegions[i].translate(dx, dy);
    36043492            if (d->accelerateScrolling) {
    36053493#ifndef QT_NO_RUBBERBAND
     
    36113499                }
    36123500#endif
     3501                d->dirtyScrollOffset.rx() += dx;
     3502                d->dirtyScrollOffset.ry() += dy;
     3503                d->dirtyRegion.translate(dx, dy);
    36133504                viewport()->scroll(dx, dy);
    36143505            } else {
    3615                 viewport()->update();
     3506                d->updateAll();
    36163507            }
    36173508        } else {
    3618             viewport()->update();
     3509            d->updateAll();
    36193510        }
    36203511    }
     
    36273518#endif
    36283519        ) {
     3520        // Scroll the background pixmap
     3521        QRegion exposed;
     3522        if (!d->backgroundPixmap.isNull())
     3523            d->backgroundPixmap.scroll(dx, dy, d->backgroundPixmap.rect(), &exposed);
     3524
    36293525        // Invalidate the background pixmap
    3630         d->backgroundPixmapExposed.translate(dx, 0);
    3631         if (dx > 0) {
    3632             d->backgroundPixmapExposed += QRect(0, 0, dx, viewport()->height());
    3633         } else if (dx < 0) {
    3634             d->backgroundPixmapExposed += QRect(viewport()->width() + dx, 0,
    3635                                                 -dx, viewport()->height());
    3636         }
    3637         d->backgroundPixmapExposed.translate(0, dy);
    3638         if (dy > 0) {
    3639             d->backgroundPixmapExposed += QRect(0, 0, viewport()->width(), dy);
    3640         } else if (dy < 0) {
    3641             d->backgroundPixmapExposed += QRect(0, viewport()->height() + dy,
    3642                                                 viewport()->width(), -dy);
    3643         }
    3644 
    3645         // Scroll the background pixmap
    3646         if (!d->backgroundPixmap.isNull()) {
    3647             QPixmap tmp = d->backgroundPixmap.copy();
    3648             QBrush bgBrush = viewport()->palette().brush(viewport()->backgroundRole());
    3649             if (!bgBrush.isOpaque())
    3650                 d->backgroundPixmap.fill(Qt::transparent);
    3651             QPainter painter(&d->backgroundPixmap);
    3652             painter.drawPixmap(dx, dy, tmp);
    3653         }
     3526        d->backgroundPixmapExposed.translate(dx, dy);
     3527        d->backgroundPixmapExposed += exposed;
    36543528    }
    36553529
     
    37453619    The default implementation calls the scene's drawItems() function.
    37463620
     3621    \obsolete Since Qt 4.6, this function is not called anymore unless
     3622    the QGraphicsView::IndirectPainting flag is given as an Optimization
     3623    flag.
     3624
    37473625    \sa drawForeground(), drawBackground(), QGraphicsScene::drawItems()
    37483626*/
     
    37523630{
    37533631    Q_D(QGraphicsView);
    3754     if (d->scene)
    3755         d->scene->drawItems(painter, numItems, items, options, viewport());
     3632    if (d->scene) {
     3633        QWidget *widget = painter->device() == viewport() ? viewport() : 0;
     3634        d->scene->drawItems(painter, numItems, items, options, widget);
     3635    }
    37563636}
    37573637
     
    37763656{
    37773657    Q_D(const QGraphicsView);
    3778     QTransform moveMatrix;
    3779     moveMatrix.translate(-d->horizontalScroll(), -d->verticalScroll());
     3658    QTransform moveMatrix = QTransform::fromTranslate(-d->horizontalScroll(), -d->verticalScroll());
    37803659    return d->identityMatrix ? moveMatrix : d->matrix * moveMatrix;
     3660}
     3661
     3662/*!
     3663    \since 4.6
     3664
     3665    Returns true if the view is transformed (i.e., a non-identity transform
     3666    has been assigned, or the scrollbars are adjusted).
     3667
     3668    \sa setTransform(), horizontalScrollBar(), verticalScrollBar()
     3669*/
     3670bool QGraphicsView::isTransformed() const
     3671{
     3672    Q_D(const QGraphicsView);
     3673    return !d->identityMatrix || d->horizontalScroll() || d->verticalScroll();
    37813674}
    37823675
     
    38323725
    38333726    // Any matrix operation requires a full update.
    3834     viewport()->update();
     3727    d->updateAll();
    38353728}
    38363729
     
    38453738}
    38463739
     3740QPointF QGraphicsViewPrivate::mapToScene(const QPointF &point) const
     3741{
     3742    QPointF p = point;
     3743    p.rx() += horizontalScroll();
     3744    p.ry() += verticalScroll();
     3745    return identityMatrix ? p : matrix.inverted().map(p);
     3746}
     3747
     3748QRectF QGraphicsViewPrivate::mapToScene(const QRectF &rect) const
     3749{
     3750    QPointF scrollOffset(horizontalScroll(), verticalScroll());
     3751    QPointF tl = scrollOffset + rect.topLeft();
     3752    QPointF tr = scrollOffset + rect.topRight();
     3753    QPointF br = scrollOffset + rect.bottomRight();
     3754    QPointF bl = scrollOffset + rect.bottomLeft();
     3755
     3756    QPolygonF poly(4);
     3757    if (!identityMatrix) {
     3758        QTransform x = matrix.inverted();
     3759        poly[0] = x.map(tl);
     3760        poly[1] = x.map(tr);
     3761        poly[2] = x.map(br);
     3762        poly[3] = x.map(bl);
     3763    } else {
     3764        poly[0] = tl;
     3765        poly[1] = tr;
     3766        poly[2] = br;
     3767        poly[3] = bl;
     3768    }
     3769    return poly.boundingRect();
     3770}
     3771
    38473772QT_END_NAMESPACE
    38483773
  • trunk/src/gui/graphicsview/qgraphicsview.h

    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**
     
    111111
    112112    enum OptimizationFlag {
    113         DontClipPainter = 0x1,
     113        DontClipPainter = 0x1, // obsolete
    114114        DontSavePainterState = 0x2,
    115         DontAdjustForAntialiasing = 0x4
     115        DontAdjustForAntialiasing = 0x4,
     116        IndirectPainting = 0x8
    116117    };
    117118    Q_DECLARE_FLAGS(OptimizationFlags, OptimizationFlag)
     
    170171    QTransform transform() const;
    171172    QTransform viewportTransform() const;
     173    bool isTransformed() const;
    172174    void setTransform(const QTransform &matrix, bool combine = false);
    173175    void resetTransform();
     
    274276    Q_PRIVATE_SLOT(d_func(), void _q_unsetViewportCursor())
    275277#endif
    276     Q_PRIVATE_SLOT(d_func(), void _q_updateLaterSlot())
    277278    friend class QGraphicsSceneWidget;
    278279    friend class QGraphicsScene;
    279280    friend class QGraphicsScenePrivate;
     281    friend class QGraphicsItemPrivate;
    280282};
    281283
  • trunk/src/gui/graphicsview/qgraphicsview_p.h

    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**
     
    4848//
    4949// This file is not part of the Qt API.  It exists for the convenience
    50 // of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp.  This header
    51 // file may change from version to version without notice, or even be removed.
     50// of other Qt classes.  This header file may change from version to
     51// version without notice, or even be removed.
    5252//
    5353// We mean it.
     
    5959
    6060#include <QtGui/qevent.h>
     61#include <QtCore/qcoreapplication.h>
    6162#include "qgraphicssceneevent.h"
     63#include <QtGui/qstyleoption.h>
    6264#include <private/qabstractscrollarea_p.h>
    6365
    6466QT_BEGIN_NAMESPACE
    6567
    66 class Q_GUI_EXPORT QGraphicsViewPrivate : public QAbstractScrollAreaPrivate
     68class Q_AUTOTEST_EXPORT QGraphicsViewPrivate : public QAbstractScrollAreaPrivate
    6769{
    6870    Q_DECLARE_PUBLIC(QGraphicsView)
     
    8587    qint64 verticalScroll() const;
    8688
    87     QList<QGraphicsItem *> itemsInArea(const QPainterPath &path,
    88                                        Qt::ItemSelectionMode mode = Qt::IntersectsItemShape,
    89                                        Qt::SortOrder = Qt::AscendingOrder) const;
     89    QRectF mapRectToScene(const QRect &rect) const;
     90    QRectF mapRectFromScene(const QRectF &rect) const;
    9091
    9192    QPointF mousePressItemPoint;
     
    9596    QPointF lastMouseMoveScenePoint;
    9697    QPoint lastMouseMoveScreenPoint;
     98    QPoint dirtyScrollOffset;
    9799    Qt::MouseButton mousePressButton;
    98100    QTransform matrix;
     
    160162    QRect mapToViewRect(const QGraphicsItem *item, const QRectF &rect) const;
    161163    QRegion mapToViewRegion(const QGraphicsItem *item, const QRectF &rect) const;
    162     void itemUpdated(QGraphicsItem *item, const QRectF &rect);
    163164    bool fullUpdatePending;
    164     QList<QRect> dirtyRects;
    165     QList<QRegion> dirtyRegions;
    166     int dirtyRectCount;
     165    QRegion dirtyRegion;
    167166    QRect dirtyBoundingRect;
    168     void updateLater();
    169     bool updatingLater;
    170     void _q_updateLaterSlot();
    171     void updateAll();
    172     void updateRect(const QRect &rect);
    173     void updateRegion(const QRegion &region);
     167    void processPendingUpdates();
     168    inline void updateAll()
     169    {
     170        viewport->update();
     171        fullUpdatePending = true;
     172        dirtyBoundingRect = QRect();
     173        dirtyRegion = QRegion();
     174    }
     175
     176    inline void dispatchPendingUpdateRequests()
     177    {
     178#ifndef Q_WS_MAC
     179        // QWidget::update() works slightly different on the Mac; it's not part of
     180        // our backing store so it needs special threatment.
     181        if (qt_widget_private(viewport)->paintOnScreen())
     182            QCoreApplication::sendPostedEvents(viewport, QEvent::UpdateRequest);
     183        else
     184            QCoreApplication::sendPostedEvents(viewport->window(), QEvent::UpdateRequest);
     185#else
     186        QCoreApplication::processEvents(QEventLoop::AllEvents | QEventLoop::ExcludeSocketNotifiers
     187                                        | QEventLoop::ExcludeUserInputEvents);
     188#endif
     189    }
     190
     191    bool updateRect(const QRect &rect);
     192    bool updateRegion(const QRegion &region);
    174193    bool updateSceneSlotReimplementedChecked;
    175 
    176     QList<QGraphicsItem *> findItems(const QRegion &exposedRegion, bool *allItems) const;
    177 
    178     void generateStyleOptions(const QList<QGraphicsItem *> &itemList,
    179                               QGraphicsItem **itemArray,
    180                               QStyleOptionGraphicsItem *styleOptionArray,
    181                               const QTransform &worldTransform,
    182                               bool allItems,
    183                               const QRegion &exposedRegion) const;
     194    QRegion exposedRegion;
     195
     196    QList<QGraphicsItem *> findItems(const QRegion &exposedRegion, bool *allItems,
     197                                     const QTransform &viewTransform) const;
     198
     199    QPointF mapToScene(const QPointF &point) const;
     200    QRectF mapToScene(const QRectF &rect) const;
     201    static void translateTouchEvent(QGraphicsViewPrivate *d, QTouchEvent *touchEvent);
     202    void updateInputMethodSensitivity();
    184203};
    185204
  • trunk/src/gui/graphicsview/qgraphicswidget.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**
     
    7575    items in a QGraphicsScene.
    7676    \since 4.4
    77     \ingroup multimedia
    7877    \ingroup graphicsview-api
    7978
     
    171170
    172171/*!
    173     \property QGraphicsWidget::enabled
    174     \brief whether the item is enabled or not
    175 
    176     This property is declared in QGraphicsItem.
    177 
    178     By default, this property is true.
    179 
    180     \sa QGraphicsItem::isEnabled(), QGraphicsItem::setEnabled()
    181 */
    182 
    183 /*!
    184     \property QGraphicsWidget::visible
    185     \brief whether the item is visible or not
    186 
    187     This property is declared in QGraphicsItem.
    188 
    189     By default, this property is true.
    190 
    191     \sa QGraphicsItem::isVisible(), QGraphicsItem::setVisible(), show(),
    192     hide()
    193 */
    194 
    195 /*!
    196     \property QGraphicsWidget::opacity
    197     \brief the opacity of the widget
    198 */   
    199 
    200 /*!
    201     \property QGraphicsWidget::pos
    202     \brief the position of the widget
    203 */   
    204 
    205 /*!
    206172    Constructs a QGraphicsWidget instance. The optional \a parent argument is
    207173    passed to QGraphicsItem's constructor. The optional \a wFlags argument
     
    210176*/
    211177QGraphicsWidget::QGraphicsWidget(QGraphicsItem *parent, Qt::WindowFlags wFlags)
    212     : QGraphicsItem(*new QGraphicsWidgetPrivate, 0, 0), QGraphicsLayoutItem(0, false)
     178    : QGraphicsObject(*new QGraphicsWidgetPrivate, 0, 0), QGraphicsLayoutItem(0, false)
    213179{
    214180    Q_D(QGraphicsWidget);
     
    222188*/
    223189QGraphicsWidget::QGraphicsWidget(QGraphicsWidgetPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene, Qt::WindowFlags wFlags)
    224     : QGraphicsItem(dd, 0, scene), QGraphicsLayoutItem(0, false)
     190    : QGraphicsObject(dd, 0, scene), QGraphicsLayoutItem(0, false)
    225191{
    226192    Q_D(QGraphicsWidget);
     
    292258    //we check if we have a layout previously
    293259    if (d->layout) {
    294         delete d->layout;
     260        QGraphicsLayout *temp = d->layout;
    295261        foreach (QGraphicsItem * item, childItems()) {
    296262            // In case of a custom layout which doesn't remove and delete items, we ensure that
     
    303269            }
    304270        }
     271        d->layout = 0;
     272        delete temp;
    305273    }
    306274
     
    351319
    352320/*!
     321    \property QGraphicsWidget::sizePolicy
     322    \brief the size policy for the widget
     323    \sa sizePolicy(), setSizePolicy(), QWidget::sizePolicy()
     324*/
     325
     326/*!
    353327    \property QGraphicsWidget::geometry
    354328    \brief the geometry of the widget
     
    367341{
    368342    QGraphicsWidgetPrivate *wd = QGraphicsWidget::d_func();
    369     QGraphicsLayoutItemPrivate *d = QGraphicsLayoutItem::d_ptr;
     343    QGraphicsLayoutItemPrivate *d = QGraphicsLayoutItem::d_ptr.data();
    370344    QRectF newGeom;
    371345    QPointF oldPos = d->geom.topLeft();
     
    380354        // setPos triggers ItemPositionChange, which can adjust position
    381355        wd->inSetGeometry = 1;
    382         wd->setPosHelper(newGeom.topLeft());
     356        setPos(newGeom.topLeft());
    383357        wd->inSetGeometry = 0;
    384358        newGeom.moveTopLeft(pos());
     
    441415
    442416/*!
     417    \property QGraphicsWidget::minimumSize
     418    \brief the minimum size of the widget
     419
     420    \sa setMinimumSize(), minimumSize(), preferredSize, maximumSize
     421*/
     422
     423/*!
     424    \property QGraphicsWidget::preferredSize
     425    \brief the preferred size of the widget
     426
     427    \sa setPreferredSize(), preferredSize(), minimumSize, maximumSize
     428*/
     429
     430/*!
     431    \property QGraphicsWidget::maximumSize
     432    \brief the maximum size of the widget
     433
     434    \sa setMaximumSize(), maximumSize(), minimumSize, preferredSize
     435*/
     436
     437/*!
    443438    Sets the widget's contents margins to \a left, \a top, \a right and \a
    444439    bottom.
     
    460455    Q_D(QGraphicsWidget);
    461456
    462     if (left == d->leftMargin
    463         && top == d->topMargin
    464         && right == d->rightMargin
    465         && bottom == d->bottomMargin) {
     457    if (!d->margins && left == 0 && top == 0 && right == 0 && bottom == 0)
    466458        return;
    467     }
    468 
    469     d->leftMargin = left;
    470     d->topMargin = top;
    471     d->rightMargin = right;
    472     d->bottomMargin = bottom;
     459    d->ensureMargins();
     460    if (left == d->margins[d->Left]
     461        && top == d->margins[d->Top]
     462        && right == d->margins[d->Right]
     463        && bottom == d->margins[d->Bottom])
     464        return;
     465
     466    d->margins[d->Left] = left;
     467    d->margins[d->Top] = top;
     468    d->margins[d->Right] = right;
     469    d->margins[d->Bottom] = bottom;
    473470
    474471    if (QGraphicsLayout *l = d->layout)
     
    491488{
    492489    Q_D(const QGraphicsWidget);
     490    if (left || top || right || bottom)
     491        d->ensureMargins();
    493492    if (left)
    494         *left = d->leftMargin;
     493        *left = d->margins[d->Left];
    495494    if (top)
    496         *top = d->topMargin;
     495        *top = d->margins[d->Top];
    497496    if (right)
    498         *right = d->rightMargin;
     497        *right = d->margins[d->Right];
    499498    if (bottom)
    500         *bottom = d->bottomMargin;
     499        *bottom = d->margins[d->Bottom];
    501500}
    502501
     
    514513{
    515514    Q_D(QGraphicsWidget);
    516     bool unchanged = left == d->leftWindowFrameMargin && top == d->topWindowFrameMargin
    517                      && right == d->rightWindowFrameMargin && bottom == d->bottomWindowFrameMargin;
     515
     516    if (!d->windowFrameMargins && left == 0 && top == 0 && right == 0 && bottom == 0)
     517        return;
     518    d->ensureWindowFrameMargins();
     519    bool unchanged =
     520        d->windowFrameMargins[d->Left] == left
     521        && d->windowFrameMargins[d->Top] == top
     522        && d->windowFrameMargins[d->Right] == right
     523        && d->windowFrameMargins[d->Bottom] == bottom;
    518524    if (d->setWindowFrameMargins && unchanged)
    519525        return;
    520526    if (!unchanged)
    521527        prepareGeometryChange();
    522     d->leftWindowFrameMargin = left;
    523     d->topWindowFrameMargin = top;
    524     d->rightWindowFrameMargin = right;
    525     d->bottomWindowFrameMargin = bottom;
     528    d->windowFrameMargins[d->Left] = left;
     529    d->windowFrameMargins[d->Top] = top;
     530    d->windowFrameMargins[d->Right] = right;
     531    d->windowFrameMargins[d->Bottom] = bottom;
    526532    d->setWindowFrameMargins = true;
    527533}
     
    537543{
    538544    Q_D(const QGraphicsWidget);
     545    if (left || top || right || bottom)
     546        d->ensureWindowFrameMargins();
    539547    if (left)
    540         *left = d->leftWindowFrameMargin;
     548        *left = d->windowFrameMargins[d->Left];
    541549    if (top)
    542         *top = d->topWindowFrameMargin;
     550        *top = d->windowFrameMargins[d->Top];
    543551    if (right)
    544         *right = d->rightWindowFrameMargin;
     552        *right = d->windowFrameMargins[d->Right];
    545553    if (bottom)
    546         *bottom = d->bottomWindowFrameMargin;
     554        *bottom = d->windowFrameMargins[d->Bottom];
    547555}
    548556
     
    578586{
    579587    Q_D(const QGraphicsWidget);
    580     return geometry().adjusted(-d->leftWindowFrameMargin, -d->topWindowFrameMargin,
    581                                d->rightWindowFrameMargin, d->bottomWindowFrameMargin);
     588    return d->windowFrameMargins
     589        ? geometry().adjusted(-d->windowFrameMargins[d->Left], -d->windowFrameMargins[d->Top],
     590                              d->windowFrameMargins[d->Right], d->windowFrameMargins[d->Bottom])
     591        : geometry();
    582592}
    583593
     
    590600{
    591601    Q_D(const QGraphicsWidget);
    592     return rect().adjusted(-d->leftWindowFrameMargin, -d->topWindowFrameMargin,
    593                            d->rightWindowFrameMargin, d->bottomWindowFrameMargin);
     602    return d->windowFrameMargins
     603        ? rect().adjusted(-d->windowFrameMargins[d->Left], -d->windowFrameMargins[d->Top],
     604                          d->windowFrameMargins[d->Right], d->windowFrameMargins[d->Bottom])
     605        : rect();
    594606}
    595607
     
    699711    QSizeF sh;
    700712    if (d->layout) {
    701         sh = d->layout->effectiveSizeHint(which, constraint);
    702         sh += QSizeF(d->leftMargin + d->rightMargin, d->topMargin + d->bottomMargin);
     713        QSizeF marginSize(0,0);
     714        if (d->margins) {
     715            marginSize = QSizeF(d->margins[d->Left] + d->margins[d->Right],
     716                         d->margins[d->Top] + d->margins[d->Bottom]);
     717        }
     718        sh = d->layout->effectiveSizeHint(which, constraint - marginSize);
     719        sh += marginSize;
    703720    } else {
    704721        switch (which) {
     
    9851002    very important that subclasses call the base implementation.
    9861003
    987     For example, QGraphicsWidget uses ItemVisibleChange to deliver \l Show and
    988     \l Hide events, ItemPositionHasChanged to deliver \l Move events, and
    989     ItemParentChange both to deliver \l ParentChange events, and for managing
    990     the focus chain.
    991 
    992     \sa propertyChange()
     1004    \a change specifies the type of change, and \a value is the new value.
     1005
     1006    For example, QGraphicsWidget uses ItemVisibleChange to deliver
     1007    \l{QEvent::Show} {Show} and \l{QEvent::Hide}{Hide} events,
     1008    ItemPositionHasChanged to deliver \l{QEvent::Move}{Move} events,
     1009    and ItemParentChange both to deliver \l{QEvent::ParentChange}
     1010    {ParentChange} events, and for managing the focus chain.
     1011
     1012    QGraphicsWidget enables the ItemSendsGeometryChanges flag by default in
     1013    order to track position changes.
     1014
     1015    \sa QGraphicsItem::itemChange()
    9931016*/
    9941017QVariant QGraphicsWidget::itemChange(GraphicsItemChange change, const QVariant &value)
     
    10321055    case ItemParentChange: {
    10331056        QGraphicsItem *parent = qVariantValue<QGraphicsItem *>(value);
    1034         d->fixFocusChainBeforeReparenting((parent && parent->isWidget()) ? static_cast<QGraphicsWidget *>(parent) : 0);
     1057        d->fixFocusChainBeforeReparenting((parent && parent->isWidget()) ? static_cast<QGraphicsWidget *>(parent) : 0, scene());
    10351058
    10361059        // Deliver ParentAboutToChange.
     
    10401063    }
    10411064    case ItemParentHasChanged: {
    1042         // reset window type on parent change in order to automagically remove decorations etc.
    1043         Qt::WindowFlags wflags = d->windowFlags & ~Qt::WindowType_Mask;
    1044         d->adjustWindowFlags(&wflags);
    1045         setWindowFlags(wflags);
    10461065        // Deliver ParentChange.
    10471066        QEvent event(QEvent::ParentChange);
     
    11081127bool QGraphicsWidget::sceneEvent(QEvent *event)
    11091128{
    1110     return QCoreApplication::sendEvent(this, event) || QGraphicsItem::sceneEvent(event);
     1129    return QGraphicsItem::sceneEvent(event);
    11111130}
    11121131
     
    11321151        break;
    11331152    case QEvent::GraphicsSceneMouseMove:
    1134         if (d->grabbedSection != Qt::NoSection) {
     1153        d->ensureWindowData();
     1154        if (d->windowData->grabbedSection != Qt::NoSection) {
    11351155            d->windowFrameMouseMoveEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
    11361156            event->accept();
     
    11871207    const qreal cornerMargin = 20;
    11881208    //### Not sure of this one, it should be the same value for all edges.
    1189     const qreal windowFrameWidth = d->leftWindowFrameMargin;
     1209    const qreal windowFrameWidth = d->windowFrameMargins
     1210        ? d->windowFrameMargins[d->Left] : 0;
    11901211
    11911212    Qt::WindowFrameSection s = Qt::NoSection;
     
    12131234    if (s == Qt::NoSection) {
    12141235        QRectF r1 = r;
    1215         r1.setHeight(d->topWindowFrameMargin);
     1236        r1.setHeight(d->windowFrameMargins
     1237                     ? d->windowFrameMargins[d->Top] : 0);
    12161238        if (r1.contains(pos))
    12171239            s = Qt::TitleBarArea;
     
    12231245    \reimp
    12241246
    1225     QGraphicsWidget handles the following events:
     1247    Handles the \a event.  QGraphicsWidget handles the following
     1248    events:
    12261249
    12271250    \table   \o Event                 \o Usage
     
    12791302        polishEvent();
    12801303        d->polished = true;
    1281         d->updateFont(d->font);
     1304        if (!d->font.isCopyOf(QApplication::font()))
     1305            d->updateFont(d->font);
    12821306        break;
    12831307    case QEvent::WindowActivate:
    12841308    case QEvent::WindowDeactivate:
    12851309        update();
    1286         foreach (QGraphicsItem *child, childItems()) {
    1287             if (child->isWidget())
    1288                 QApplication::sendEvent(static_cast<QGraphicsWidget *>(child), event);
    1289         }
    12901310        break;
    12911311        // Taken from QWidget::event
     
    13211341    case QEvent::GraphicsSceneMouseRelease:
    13221342    case QEvent::GraphicsSceneMouseDoubleClick:
    1323         if (d->hasDecoration() && d->grabbedSection != Qt::NoSection)
     1343        d->ensureWindowData();
     1344        if (d->hasDecoration() && d->windowData->grabbedSection != Qt::NoSection)
    13241345            return windowFrameEvent(event);
    13251346        break;
     
    13581379        // ### Don't unset if the margins are explicitly set.
    13591380        unsetWindowFrameMargins();
     1381        if (d->layout)
     1382            d->layout->invalidate();
    13601383    case QEvent::FontChange:
    13611384        update();
     
    15961619/*!
    15971620    Returns the widgets window type.
     1621
     1622    \sa windowFlags(), isWindow(), isPanel()
    15981623*/
    15991624Qt::WindowType QGraphicsWidget::windowType() const
     
    16111636
    16121637    By default, this property contains no window flags.
     1638
     1639    Windows are panels. If you set the Qt::Window flag, the ItemIsPanel flag
     1640    will be set automatically. If you clear the Qt::Window flag, the
     1641    ItemIsPanel flag is also cleared. Note that the ItemIsPanel flag can be
     1642    set independently of Qt::Window.
     1643
     1644    \sa isWindow(), isPanel()
    16131645*/
    16141646Qt::WindowFlags QGraphicsWidget::windowFlags() const
     
    16241656    bool wasPopup = (d->windowFlags & Qt::WindowType_Mask) == Qt::Popup;
    16251657
     1658    d->adjustWindowFlags(&wFlags);
    16261659    d->windowFlags = wFlags;
    16271660    if (!d->setWindowFrameMargins)
    16281661        unsetWindowFrameMargins();
     1662
     1663    setFlag(ItemIsPanel, d->windowFlags & Qt::Window);
    16291664
    16301665    bool isPopup = (d->windowFlags & Qt::WindowType_Mask) == Qt::Popup;
     
    16361671            d->scene->d_func()->addPopup(this);
    16371672    }
     1673
     1674    if (d->scene && d->scene->d_func()->allItemsIgnoreHoverEvents && d->hasDecoration()) {
     1675        d->scene->d_func()->allItemsIgnoreHoverEvents = false;
     1676        d->scene->d_func()->enableMouseTrackingOnViews();
     1677    }
    16381678}
    16391679
     
    16461686    currently has input focus, or that itself has input focus.
    16471687
    1648     \sa QGraphicsScene::activeWindow(), QGraphicsScene::setActiveWindow()
     1688    \sa QGraphicsScene::activeWindow(), QGraphicsScene::setActiveWindow(), isActive()
    16491689*/
    16501690bool QGraphicsWidget::isActiveWindow() const
    16511691{
    1652     Q_D(const QGraphicsWidget);
    1653     if (!d->scene)
    1654         return false;
    1655     const QGraphicsWidget *w = window();
    1656     return (!w && d->scene->d_func()->activationRefCount) || (w && d->scene->activeWindow() == w);
     1692    return isActive();
    16571693}
    16581694
     
    16631699    This property is only used for windows.
    16641700
    1665     By default, if no title has been set, this property contains an empty string.
     1701    By default, if no title has been set, this property contains an
     1702    empty string.
    16661703*/
    16671704void QGraphicsWidget::setWindowTitle(const QString &title)
    16681705{
    16691706    Q_D(QGraphicsWidget);
    1670     d->windowTitle = title;
     1707    d->ensureWindowData();
     1708    d->windowData->windowTitle = title;
    16711709}
    16721710QString QGraphicsWidget::windowTitle() const
    16731711{
    16741712    Q_D(const QGraphicsWidget);
    1675     return d->windowTitle;
     1713    return d->windowData ? d->windowData->windowTitle : QString();
    16761714}
    16771715
     
    17151753    If this widget, a child or descendant of this widget currently has input
    17161754    focus, this function will return a pointer to that widget. If
    1717     no descendant has input focus, 0 is returned.
    1718 
    1719     \sa QWidget::focusWidget()
     1755    no descendant widget has input focus, 0 is returned.
     1756
     1757    \sa QGraphicsItem::focusItem(), QWidget::focusWidget()
    17201758*/
    17211759QGraphicsWidget *QGraphicsWidget::focusWidget() const
    17221760{
    17231761    Q_D(const QGraphicsWidget);
    1724     return d->focusChild;
    1725 }
    1726 
     1762    if (d->subFocusItem && d->subFocusItem->d_ptr->isWidget)
     1763        return static_cast<QGraphicsWidget *>(d->subFocusItem);
     1764    return 0;
     1765}
    17271766
    17281767#ifndef QT_NO_SHORTCUT
     
    18881927    d->actions.insert(pos, action);
    18891928
    1890     QActionPrivate *apriv = action->d_func();
    1891     apriv->graphicsWidgets.append(this);
     1929    if (index == -1) {
     1930        QActionPrivate *apriv = action->d_func();
     1931        apriv->graphicsWidgets.append(this);
     1932    }
    18921933
    18931934    QActionEvent e(QEvent::ActionAdded, action, before);
     
    21092150    bar.QStyleOption::operator=(*option);
    21102151    d->initStyleOptionTitleBar(&bar);   // this clear flags in bar.state
    2111     if (d->buttonMouseOver)
     2152    d->ensureWindowData();
     2153    if (d->windowData->buttonMouseOver)
    21122154        bar.state |= QStyle::State_MouseOver;
    21132155    else
    21142156        bar.state &= ~QStyle::State_MouseOver;
    2115     if (d->buttonSunken)
     2157    if (d->windowData->buttonSunken)
    21162158        bar.state |= QStyle::State_Sunken;
    21172159    else
     
    22482290/*!
    22492291    \fn const QObjectList &QGraphicsWidget::children() const
     2292    \internal
    22502293
    22512294    This function returns the same value as QObject::children(). It's
     
    22682311            break;
    22692312        }
    2270         qDebug() << i++ << QString::number(uint(next), 16) << next->className() << next->data(0) << QString::fromAscii("focusItem:%1").arg(next->hasFocus() ? "1" : "0") << QLatin1String("next:") << next->d_func()->focusNext->data(0) << QLatin1String("prev:") << next->d_func()->focusPrev->data(0);
     2313        qDebug() << i++ << QString::number(uint(next), 16) << next->className() << next->data(0) << QString::fromAscii("focusItem:%1").arg(next->hasFocus() ? '1' : '0') << QLatin1String("next:") << next->d_func()->focusNext->data(0) << QLatin1String("prev:") << next->d_func()->focusPrev->data(0);
    22712314        if (visited.contains(next)) {
    22722315            qWarning("Already visited this node. However, I expected to dump until I found myself.");
  • trunk/src/gui/graphicsview/qgraphicswidget.h

    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**
     
    6767class QGraphicsWidgetPrivate;
    6868
    69 class Q_GUI_EXPORT QGraphicsWidget : public QObject, public QGraphicsItem, public QGraphicsLayoutItem
     69class Q_GUI_EXPORT QGraphicsWidget : public QGraphicsObject, public QGraphicsLayoutItem
    7070{
    7171    Q_OBJECT
     72    Q_INTERFACES(QGraphicsItem QGraphicsLayoutItem)
    7273    Q_PROPERTY(QPalette palette READ palette WRITE setPalette)
    7374    Q_PROPERTY(QFont font READ font WRITE setFont)
    7475    Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection RESET unsetLayoutDirection)
    7576    Q_PROPERTY(QSizeF size READ size WRITE resize)
     77    Q_PROPERTY(QSizeF minimumSize READ minimumSize WRITE setMinimumSize)
     78    Q_PROPERTY(QSizeF preferredSize READ preferredSize WRITE setPreferredSize)
     79    Q_PROPERTY(QSizeF maximumSize READ maximumSize WRITE setMaximumSize)
     80    Q_PROPERTY(QSizePolicy sizePolicy READ sizePolicy WRITE setSizePolicy)
    7681    Q_PROPERTY(Qt::FocusPolicy focusPolicy READ focusPolicy WRITE setFocusPolicy)
    77     Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
    78     Q_PROPERTY(bool visible READ isVisible WRITE setVisible)
    7982    Q_PROPERTY(Qt::WindowFlags windowFlags READ windowFlags WRITE setWindowFlags)
    8083    Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle)
    81     Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity)
    82     Q_PROPERTY(QPointF pos READ pos WRITE setPos)
    8384    Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry)
    84 
    8585public:
    8686    QGraphicsWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0);
     
    226226private:
    227227    Q_DISABLE_COPY(QGraphicsWidget)
    228     Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr, QGraphicsWidget)
     228    Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QGraphicsWidget)
    229229    friend class QGraphicsScene;
    230230    friend class QGraphicsScenePrivate;
  • trunk/src/gui/graphicsview/qgraphicswidget_p.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**
     
    6767    focusNext = focusPrev = q;
    6868    focusPolicy = Qt::NoFocus;
     69
     70    adjustWindowFlags(&wFlags);
     71    windowFlags = wFlags;
     72
    6973    q->setParentItem(parentItem);
    7074    q->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred, QSizePolicy::DefaultType));
     
    7276
    7377    resolveLayoutDirection();
    74 
    75     if (!parentItem)
    76         adjustWindowFlags(&wFlags);
    77     windowFlags = wFlags;
    7878    q->unsetWindowFrameMargins();
    79 }
     79    q->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption);
     80    q->setFlag(QGraphicsItem::ItemSendsGeometryChanges);
     81}
     82
    8083qreal QGraphicsWidgetPrivate::titleBarHeight(const QStyleOptionTitleBar &options) const
    8184{
     
    9093}
    9194
    92 void QGraphicsWidgetPrivate::getLayoutItemMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const
    93 {
    94     if (left)
    95         *left = leftLayoutItemMargin;
    96     if (top)
    97         *top = topLayoutItemMargin;
    98     if (right)
    99         *right = rightLayoutItemMargin;
    100     if (bottom)
    101         *bottom = bottomLayoutItemMargin;
    102 }
    103 
    104 void QGraphicsWidgetPrivate::setLayoutItemMargins(qreal left, qreal top, qreal right, qreal bottom)
    105 {
    106     if (leftLayoutItemMargin == left
    107         && topLayoutItemMargin == top
    108         && rightLayoutItemMargin == right
    109         && bottomLayoutItemMargin == bottom)
    110         return;
    111 
    112     Q_Q(QGraphicsWidget);
    113     leftLayoutItemMargin = left;
    114     topLayoutItemMargin = top;
    115     rightLayoutItemMargin = right;
    116     bottomLayoutItemMargin = bottom;
    117     q->updateGeometry();
    118 }
    119 
    120 void QGraphicsWidgetPrivate::setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt)
    121 {
    122     Q_Q(QGraphicsWidget);
    123     QStyleOption myOpt;
    124     if (!opt) {
    125         q->initStyleOption(&myOpt);
    126         myOpt.rect.setRect(0, 0, 32768, 32768);     // arbitrary
    127         opt = &myOpt;
    128     }
    129 
    130     QRect liRect = q->style()->subElementRect(element, opt, /* q */ 0);
    131     if (liRect.isValid()) {
    132         leftLayoutItemMargin = (opt->rect.left() - liRect.left());
    133         topLayoutItemMargin = (opt->rect.top() - liRect.top());
    134         rightLayoutItemMargin = (liRect.right() - opt->rect.right());
    135         bottomLayoutItemMargin = (liRect.bottom() - opt->rect.bottom());
    136     } else {
    137         leftLayoutItemMargin = 0;
    138         topLayoutItemMargin = 0;
    139         rightLayoutItemMargin = 0;
    140         bottomLayoutItemMargin = 0;
    141     }
     95/*!
     96    \internal
     97*/
     98QGraphicsWidgetPrivate::~QGraphicsWidgetPrivate()
     99{
     100    // Remove any lazily allocated data
     101    delete[] margins;
     102    delete[] windowFrameMargins;
     103    delete windowData;
     104}
     105
     106/*!
     107    \internal
     108
     109     Ensures that margins is allocated.
     110     This function must be called before any dereferencing.
     111*/
     112void QGraphicsWidgetPrivate::ensureMargins() const
     113{
     114    if (!margins) {
     115        margins = new qreal[4];
     116        for (int i = 0; i < 4; ++i)
     117            margins[i] = 0;
     118    }
     119}
     120
     121/*!
     122    \internal
     123
     124     Ensures that windowFrameMargins is allocated.
     125     This function must be called before any dereferencing.
     126*/
     127void QGraphicsWidgetPrivate::ensureWindowFrameMargins() const
     128{
     129    if (!windowFrameMargins) {
     130        windowFrameMargins = new qreal[4];
     131        for (int i = 0; i < 4; ++i)
     132            windowFrameMargins[i] = 0;
     133    }
     134}
     135
     136/*!
     137    \internal
     138
     139     Ensures that windowData is allocated.
     140     This function must be called before any dereferencing.
     141*/
     142void QGraphicsWidgetPrivate::ensureWindowData()
     143{
     144    if (!windowData)
     145        windowData = new WindowData;
    142146}
    143147
     
    298302{
    299303    Q_Q(QGraphicsWidget);
     304    ensureWindowData();
    300305    q->initStyleOption(option);
    301306    option->rect.setHeight(titleBarHeight(*option));
    302307    option->titleBarFlags = windowFlags;
    303308    option->subControls = QStyle::SC_TitleBarCloseButton | QStyle::SC_TitleBarLabel | QStyle::SC_TitleBarSysMenu;
    304     option->activeSubControls = hoveredSubControl;
     309    option->activeSubControls = windowData->hoveredSubControl;
    305310    bool isActive = q->isActiveWindow();
    306311    if (isActive) {
     
    314319    QFont windowTitleFont = QApplication::font("QWorkspaceTitleBar");
    315320    QRect textRect = q->style()->subControlRect(QStyle::CC_TitleBar, option, QStyle::SC_TitleBarLabel, 0);
    316     option->text = QFontMetrics(windowTitleFont).elidedText(windowTitle, Qt::ElideRight, textRect.width());
     321    option->text = QFontMetrics(windowTitleFont).elidedText(
     322        windowData->windowTitle, Qt::ElideRight, textRect.width());
    317323}
    318324
     
    342348{
    343349    Q_Q(QGraphicsWidget);
    344     if (grabbedSection != Qt::NoSection) {
    345         if (grabbedSection == Qt::TitleBarArea) {
    346             buttonSunken = false;
     350    ensureWindowData();
     351    if (windowData->grabbedSection != Qt::NoSection) {
     352        if (windowData->grabbedSection == Qt::TitleBarArea) {
     353            windowData->buttonSunken = false;
    347354            QStyleOptionTitleBar bar;
    348355            initStyleOptionTitleBar(&bar);
     
    352359            bar.rect.setHeight(q->style()->pixelMetric(QStyle::PM_TitleBarHeight, &bar));
    353360            QPointF pos = event->pos();
    354             pos.rx() += leftWindowFrameMargin;
    355             pos.ry() += topWindowFrameMargin;
     361            if (windowFrameMargins) {
     362                pos.rx() += windowFrameMargins[Left];
     363                pos.ry() += windowFrameMargins[Top];
     364            }
    356365            bar.subControls = QStyle::SC_TitleBarCloseButton;
    357366            if (q->style()->subControlRect(QStyle::CC_TitleBar, &bar,
     
    362371        }
    363372        if (!(static_cast<QGraphicsSceneMouseEvent *>(event)->buttons()))
    364             grabbedSection = Qt::NoSection;
     373            windowData->grabbedSection = Qt::NoSection;
    365374        event->accept();
    366375    }
     
    373382        return;
    374383
    375     startGeometry = q->geometry();
    376     grabbedSection = q->windowFrameSectionAt(event->pos());
    377     switch (grabbedSection) {
    378     case Qt::LeftSection:
    379     case Qt::TopLeftSection:
    380         mouseDelta = event->pos() - q->rect().topLeft();
    381         break;
    382     case Qt::TopSection:
    383     case Qt::TopRightSection:
    384         mouseDelta = event->pos() - q->rect().topRight();
    385         break;
    386     case Qt::RightSection:
    387     case Qt::BottomRightSection:
    388         mouseDelta = event->pos() - q->rect().bottomRight();
    389         break;
    390     case Qt::BottomSection:
    391     case Qt::BottomLeftSection:
    392         mouseDelta = event->pos() - q->rect().bottomLeft();
    393         break;
    394     case Qt::TitleBarArea:
    395         if (hoveredSubControl == QStyle::SC_TitleBarCloseButton) {
    396             buttonSunken = true;
    397             q->update();
    398         }
    399         break;
    400     case Qt::NoSection:
    401         break;
    402     }
    403     event->setAccepted(grabbedSection != Qt::NoSection);
     384    ensureWindowData();
     385    windowData->startGeometry = q->geometry();
     386    windowData->grabbedSection = q->windowFrameSectionAt(event->pos());
     387    ensureWindowData();
     388    if (windowData->grabbedSection == Qt::TitleBarArea
     389        && windowData->hoveredSubControl == QStyle::SC_TitleBarCloseButton) {
     390        windowData->buttonSunken = true;
     391        q->update();
     392    }
     393    event->setAccepted(windowData->grabbedSection != Qt::NoSection);
     394}
     395
     396/*!
     397  Used to calculate the
     398  Precondition:
     399  \a widget should support either hfw or wfh
     400
     401  If \a heightForWidth is set to false, this function will query the width for height
     402  instead. \a width will then be interpreted as height, \a minh and \a maxh will be interpreted
     403  as minimum width and maximum width.
     404 */
     405static qreal minimumHeightForWidth(qreal width, qreal minh, qreal maxh,
     406                                   const QGraphicsWidget *widget,
     407                                   bool heightForWidth = true)
     408{
     409    qreal minimumHeightForWidth = -1;
     410    const QSizePolicy sp = widget->layout() ? widget->layout()->sizePolicy() : widget->sizePolicy();
     411    const bool hasHFW = sp.hasHeightForWidth();
     412    if (hasHFW == heightForWidth) {
     413        minimumHeightForWidth = hasHFW
     414                                ? widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(width, -1)).height()
     415                                : widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, width)).width();    //"width" is here height!
     416    } else {
     417        // widthForHeight
     418        const qreal constraint = width;
     419        while (maxh - minh > 0.1) {
     420            qreal middle = minh + (maxh - minh)/2;
     421            // ### really bad, if we are a widget with a layout it will call
     422            // layout->effectiveSizeHint(Qt::MiniumumSize), which again will call
     423            // sizeHint three times because of how the cache works
     424            qreal hfw = hasHFW
     425                        ? widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(middle, -1)).height()
     426                        : widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, middle)).width();
     427            if (hfw > constraint) {
     428                minh = middle;
     429            } else if (hfw <= constraint) {
     430                maxh = middle;
     431            }
     432        }
     433        minimumHeightForWidth = maxh;
     434    }
     435    return minimumHeightForWidth;
     436}
     437
     438static qreal minimumWidthForHeight(qreal height, qreal minw, qreal maxw,
     439                                   const QGraphicsWidget *widget)
     440{
     441    return minimumHeightForWidth(height, minw, maxw, widget, false);
     442}
     443
     444static QSizeF closestAcceptableSize(const QSizeF &proposed,
     445                                    const QGraphicsWidget *widget)
     446{
     447    const QSizeF current = widget->size();
     448
     449    qreal minw = proposed.width();
     450    qreal maxw = current.width();
     451    qreal minh = proposed.height();
     452    qreal maxh = current.height();
     453
     454    qreal middlew = maxw;
     455    qreal middleh = maxh;
     456    qreal min_hfw;
     457    min_hfw = minimumHeightForWidth(maxw, minh, maxh, widget);
     458
     459    do {
     460        if (maxw - minw < 0.1) {
     461            // we still havent found anything, cut off binary search
     462            minw = maxw;
     463            minh = maxh;
     464        }
     465        middlew = minw + (maxw - minw)/2.0;
     466        middleh = minh + (maxh - minh)/2.0;
     467
     468        min_hfw = minimumHeightForWidth(middlew, minh, maxh, widget);
     469
     470        if (min_hfw > middleh) {
     471            minw = middlew;
     472            minh = middleh;
     473        } else if (min_hfw <= middleh) {
     474            maxw = middlew;
     475            maxh = middleh;
     476        }
     477    } while (maxw != minw);
     478
     479    min_hfw = minimumHeightForWidth(middlew, minh, maxh, widget);
     480
     481    QSizeF result;
     482    if (min_hfw < maxh) {
     483        result = QSizeF(middlew, min_hfw);
     484    } else {
     485        // Needed because of the cut-off we do above.
     486        result = QSizeF(minimumWidthForHeight(maxh, proposed.width(), current.width(), widget), maxh);
     487    }
     488    return result;
    404489}
    405490
    406491static void _q_boundGeometryToSizeConstraints(const QRectF &startGeometry,
    407492                                              QRectF *rect, Qt::WindowFrameSection section,
    408                                               const QSizeF &min, const QSizeF &max)
    409 {
    410     int height;
    411     int width;
     493                                              const QSizeF &min, const QSizeF &max,
     494                                              const QGraphicsWidget *widget)
     495{
     496    const QRectF proposedRect = *rect;
     497    qreal width = qBound(min.width(), proposedRect.width(), max.width());
     498    qreal height = qBound(min.height(), proposedRect.height(), max.height());
     499
     500    QSizePolicy sp = widget->sizePolicy();
     501    if (const QGraphicsLayout *l = widget->layout()) {
     502        sp = l->sizePolicy();
     503    }
     504    const bool hasHFW = sp.hasHeightForWidth(); // || sp.hasWidthForHeight();
     505
     506    const bool widthChanged = proposedRect.width() < widget->size().width();
     507    const bool heightChanged = proposedRect.height() < widget->size().height();
     508
     509    if (hasHFW) {
     510        if (widthChanged || heightChanged) {
     511            const qreal minh = min.height();
     512            const qreal maxh = max.height();
     513            const qreal proposedHFW = minimumHeightForWidth(width, minh, maxh, widget);
     514            if (proposedHFW > proposedRect.height()) {
     515                QSizeF effectiveSize = closestAcceptableSize(QSizeF(width, height), widget);
     516                width = effectiveSize.width();
     517                height = effectiveSize.height();
     518            }
     519        }
     520    }
     521
    412522    switch (section) {
    413523    case Qt::LeftSection:
    414         width = qRound(qBound(min.width(), rect->width(), max.width()));
    415         rect->setRect(startGeometry.right() - width, startGeometry.top(),
    416                       width, startGeometry.height());
     524        rect->setRect(startGeometry.right() - qRound(width), startGeometry.top(),
     525                      qRound(width), startGeometry.height());
    417526        break;
    418527    case Qt::TopLeftSection:
    419         width = qRound(qBound(min.width(), rect->width(), max.width()));
    420         height = qRound(qBound(min.height(), rect->height(), max.height()));
    421         rect->setRect(startGeometry.right() - width, startGeometry.bottom() - height,
    422                       width, height);
     528        rect->setRect(startGeometry.right() - qRound(width), startGeometry.bottom() - qRound(height),
     529                      qRound(width), qRound(height));
    423530        break;
    424531    case Qt::TopSection:
    425         height = qRound(qBound(min.height(), rect->height(), max.height()));
    426         rect->setRect(startGeometry.left(), startGeometry.bottom() - height,
    427                       startGeometry.width(), height);
     532        rect->setRect(startGeometry.left(), startGeometry.bottom() - qRound(height),
     533                      startGeometry.width(), qRound(height));
    428534        break;
    429535    case Qt::TopRightSection:
    430         height = qRound(qBound(min.height(), rect->height(), max.height()));
    431         rect->setTop(rect->bottom() - height);
    432         rect->setWidth(qBound(min.width(), rect->width(), max.width()));
     536        rect->setTop(rect->bottom() - qRound(height));
     537        rect->setWidth(qRound(width));
    433538        break;
    434539    case Qt::RightSection:
    435         rect->setWidth(qBound(min.width(), rect->width(), max.width()));
     540        rect->setWidth(qRound(width));
    436541        break;
    437542    case Qt::BottomRightSection:
    438         rect->setWidth(qBound(min.width(), rect->width(), max.width()));
    439         rect->setHeight(qBound(min.height(), rect->height(), max.height()));
     543        rect->setWidth(qRound(width));
     544        rect->setHeight(qRound(height));
    440545        break;
    441546    case Qt::BottomSection:
    442         rect->setHeight(qBound(min.height(), rect->height(), max.height()));
     547        rect->setHeight(qRound(height));
    443548        break;
    444549    case Qt::BottomLeftSection:
    445         height = qRound(qBound(min.height(), rect->height(), max.height()));
    446         width = qRound(qBound(min.width(), rect->width(), max.width()));
    447         rect->setRect(startGeometry.right() - width, startGeometry.top(),
    448                       width, height);
     550        rect->setRect(startGeometry.right() - qRound(width), startGeometry.top(),
     551                      qRound(width), qRound(height));
    449552        break;
    450553    default:
     
    456559{
    457560    Q_Q(QGraphicsWidget);
    458     if (!(event->buttons() & Qt::LeftButton) || hoveredSubControl != QStyle::SC_TitleBarLabel)
     561    ensureWindowData();
     562    if (!(event->buttons() & Qt::LeftButton) || windowData->hoveredSubControl != QStyle::SC_TitleBarLabel)
    459563        return;
    460564
     
    465569
    466570    QRectF newGeometry;
    467     switch (grabbedSection) {
     571    switch (windowData->grabbedSection) {
    468572    case Qt::LeftSection:
    469         newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentXDelta.dx(), parentXDelta.dy()),
    470                              startGeometry.size() - QSizeF(delta.dx(), delta.dy()));
     573        newGeometry = QRectF(windowData->startGeometry.topLeft()
     574                             + QPointF(parentXDelta.dx(), parentXDelta.dy()),
     575                             windowData->startGeometry.size() - QSizeF(delta.dx(), delta.dy()));
    471576        break;
    472577    case Qt::TopLeftSection:
    473         newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentDelta.dx(), parentDelta.dy()),
    474                              startGeometry.size() - QSizeF(delta.dx(), delta.dy()));
     578        newGeometry = QRectF(windowData->startGeometry.topLeft()
     579                             + QPointF(parentDelta.dx(), parentDelta.dy()),
     580                             windowData->startGeometry.size() - QSizeF(delta.dx(), delta.dy()));
    475581        break;
    476582    case Qt::TopSection:
    477         newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentYDelta.dx(), parentYDelta.dy()),
    478                              startGeometry.size() - QSizeF(0, delta.dy()));
     583        newGeometry = QRectF(windowData->startGeometry.topLeft()
     584                             + QPointF(parentYDelta.dx(), parentYDelta.dy()),
     585                             windowData->startGeometry.size() - QSizeF(0, delta.dy()));
    479586        break;
    480587    case Qt::TopRightSection:
    481         newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentYDelta.dx(), parentYDelta.dy()),
    482                              startGeometry.size() - QSizeF(-delta.dx(), delta.dy()));
     588        newGeometry = QRectF(windowData->startGeometry.topLeft()
     589                             + QPointF(parentYDelta.dx(), parentYDelta.dy()),
     590                             windowData->startGeometry.size() - QSizeF(-delta.dx(), delta.dy()));
    483591        break;
    484592    case Qt::RightSection:
    485         newGeometry = QRectF(startGeometry.topLeft(),
    486                              startGeometry.size() + QSizeF(delta.dx(), 0));
     593        newGeometry = QRectF(windowData->startGeometry.topLeft(),
     594                             windowData->startGeometry.size() + QSizeF(delta.dx(), 0));
    487595        break;
    488596    case Qt::BottomRightSection:
    489         newGeometry = QRectF(startGeometry.topLeft(),
    490                              startGeometry.size() + QSizeF(delta.dx(), delta.dy()));
     597        newGeometry = QRectF(windowData->startGeometry.topLeft(),
     598                             windowData->startGeometry.size() + QSizeF(delta.dx(), delta.dy()));
    491599        break;
    492600    case Qt::BottomSection:
    493         newGeometry = QRectF(startGeometry.topLeft(),
    494                              startGeometry.size() + QSizeF(0, delta.dy()));
     601        newGeometry = QRectF(windowData->startGeometry.topLeft(),
     602                             windowData->startGeometry.size() + QSizeF(0, delta.dy()));
    495603        break;
    496604    case Qt::BottomLeftSection:
    497         newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentXDelta.dx(), parentXDelta.dy()),
    498                              startGeometry.size() - QSizeF(delta.dx(), -delta.dy()));
     605        newGeometry = QRectF(windowData->startGeometry.topLeft()
     606                             + QPointF(parentXDelta.dx(), parentXDelta.dy()),
     607                             windowData->startGeometry.size() - QSizeF(delta.dx(), -delta.dy()));
    499608        break;
    500609    case Qt::TitleBarArea:
    501         newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentDelta.dx(), parentDelta.dy()),
    502                              startGeometry.size());
     610        newGeometry = QRectF(windowData->startGeometry.topLeft()
     611                             + QPointF(parentDelta.dx(), parentDelta.dy()),
     612                             windowData->startGeometry.size());
    503613        break;
    504614    case Qt::NoSection:
     
    506616    }
    507617
    508     if (grabbedSection != Qt::NoSection) {
    509         _q_boundGeometryToSizeConstraints(startGeometry, &newGeometry, grabbedSection,
     618    if (windowData->grabbedSection != Qt::NoSection) {
     619        _q_boundGeometryToSizeConstraints(windowData->startGeometry, &newGeometry,
     620                                          windowData->grabbedSection,
    510621                                          q->effectiveSizeHint(Qt::MinimumSize),
    511                                           q->effectiveSizeHint(Qt::MaximumSize));
     622                                          q->effectiveSizeHint(Qt::MaximumSize),
     623                                          q);
    512624        q->setGeometry(newGeometry);
    513625    }
     
    520632        return;
    521633
     634    ensureWindowData();
     635
    522636    if (q->rect().contains(event->pos())) {
    523         if (buttonMouseOver || hoveredSubControl != QStyle::SC_None)
     637        if (windowData->buttonMouseOver || windowData->hoveredSubControl != QStyle::SC_None)
    524638            windowFrameHoverLeaveEvent(event);
    525639        return;
    526640    }
    527641
    528     bool wasMouseOver = buttonMouseOver;
    529     QRect oldButtonRect = buttonRect;
    530     buttonRect = QRect();
    531     buttonMouseOver = false;
     642    bool wasMouseOver = windowData->buttonMouseOver;
     643    QRect oldButtonRect = windowData->buttonRect;
     644    windowData->buttonRect = QRect();
     645    windowData->buttonMouseOver = false;
    532646    QPointF pos = event->pos();
    533647    QStyleOptionTitleBar bar;
    534648    // make sure that the coordinates (rect and pos) we send to the style are positive.
    535     pos.rx() += leftWindowFrameMargin;
    536     pos.ry() += topWindowFrameMargin;
     649    if (windowFrameMargins) {
     650        pos.rx() += windowFrameMargins[Left];
     651        pos.ry() += windowFrameMargins[Top];
     652    }
    537653    initStyleOptionTitleBar(&bar);
    538654    bar.rect = q->windowFrameRect().toRect();
     
    560676            break;
    561677        case Qt::TitleBarArea:
    562             buttonRect = q->style()->subControlRect(QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarCloseButton, 0);
     678            windowData->buttonRect = q->style()->subControlRect(
     679                QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarCloseButton, 0);
    563680#ifdef Q_WS_MAC
    564681            // On mac we should hover if we are in the 'area' of the buttons
    565             buttonRect |= q->style()->subControlRect(QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMinButton, 0);
    566             buttonRect |= q->style()->subControlRect(QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMaxButton, 0);
     682            windowData->buttonRect |= q->style()->subControlRect(
     683                QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMinButton, 0);
     684            windowData->buttonRect |= q->style()->subControlRect(
     685                QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMaxButton, 0);
    567686#endif
    568             if (buttonRect.contains(pos.toPoint()))
    569                 buttonMouseOver = true;
     687            if (windowData->buttonRect.contains(pos.toPoint()))
     688                windowData->buttonMouseOver = true;
    570689            event->ignore();
    571690            break;
     
    579698#endif
    580699    // update buttons if we hover over them
    581     hoveredSubControl = q->style()->hitTestComplexControl(QStyle::CC_TitleBar, &bar, pos.toPoint(), 0);
    582     if (hoveredSubControl != QStyle::SC_TitleBarCloseButton)
    583         hoveredSubControl = QStyle::SC_TitleBarLabel;
    584 
    585     if (buttonMouseOver != wasMouseOver) {
     700    windowData->hoveredSubControl = q->style()->hitTestComplexControl(QStyle::CC_TitleBar, &bar, pos.toPoint(), 0);
     701    if (windowData->hoveredSubControl != QStyle::SC_TitleBarCloseButton)
     702        windowData->hoveredSubControl = QStyle::SC_TitleBarLabel;
     703
     704    if (windowData->buttonMouseOver != wasMouseOver) {
    586705        if (!oldButtonRect.isNull())
    587706            q->update(QRectF(oldButtonRect).translated(q->windowFrameRect().topLeft()));
    588         if (!buttonRect.isNull())
    589             q->update(QRectF(buttonRect).translated(q->windowFrameRect().topLeft()));
     707        if (!windowData->buttonRect.isNull())
     708            q->update(QRectF(windowData->buttonRect).translated(q->windowFrameRect().topLeft()));
    590709    }
    591710}
     
    601720#endif
    602721
     722        ensureWindowData();
     723
    603724        bool needsUpdate = false;
    604         if (hoveredSubControl == QStyle::SC_TitleBarCloseButton || buttonMouseOver)
     725        if (windowData->hoveredSubControl == QStyle::SC_TitleBarCloseButton
     726            || windowData->buttonMouseOver)
    605727            needsUpdate = true;
    606728
    607729        // update the hover state (of buttons etc...)
    608         hoveredSubControl = QStyle::SC_None;
    609         buttonMouseOver = false;
    610         buttonRect = QRect();
     730        windowData->hoveredSubControl = QStyle::SC_None;
     731        windowData->buttonMouseOver = false;
     732        windowData->buttonRect = QRect();
    611733        if (needsUpdate)
    612             q->update(buttonRect);
     734            q->update(windowData->buttonRect);
    613735    }
    614736}
     
    617739{
    618740    return (windowFlags & Qt::Window) && (windowFlags & Qt::WindowTitleHint);
    619 }
    620 
    621 /*!
    622     \internal
    623 */
    624 void QGraphicsWidgetPrivate::setFocusWidget()
    625 {
    626     // Update focus child chain.
    627     QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(q_ptr);
    628     QGraphicsWidget *parent = widget;
    629     bool hidden = !visible;
    630     do {
    631         parent->d_func()->focusChild = widget;
    632     } while (!parent->isWindow() && (parent = parent->parentWidget()) && (!hidden || !parent->d_func()->visible));
    633 }
    634 
    635 /*!
    636     \internal
    637 */
    638 void QGraphicsWidgetPrivate::clearFocusWidget()
    639 {
    640     // Reset focus child chain.
    641     QGraphicsWidget *parent = static_cast<QGraphicsWidget *>(q_ptr);
    642     do {
    643         if (parent->d_func()->focusChild != q_ptr)
    644             break;
    645         parent->d_func()->focusChild = 0;
    646     } while (!parent->isWindow() && (parent = parent->parentWidget()));
    647741}
    648742
     
    650744 * is called after a reparent has taken place to fix up the focus chain(s)
    651745 */
    652 void QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget *newParent, QGraphicsScene *newScene)
     746void QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget *newParent, QGraphicsScene *oldScene, QGraphicsScene *newScene)
    653747{
    654748    Q_Q(QGraphicsWidget);
     
    663757    QGraphicsWidget *firstOld = 0;
    664758    bool wasPreviousNew = true;
    665 
    666     if (focusChild) {
    667         // Ensure that the current focus child doesn't leave pointers around
    668         // before reparenting.
    669         focusChild->clearFocus();
    670     }
    671759   
    672760    while (w != q) {
     
    702790    if (newParent)
    703791        newScene = newParent->scene();
    704     QGraphicsScene *oldScene = q->scene();
     792
    705793    if (oldScene && newScene != oldScene)
    706794        oldScene->d_func()->tabFocusFirst = firstOld;
  • trunk/src/gui/graphicsview/qgraphicswidget_p.h

    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**
     
    4848//
    4949// This file is not part of the Qt API.  It exists for the convenience
    50 // of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp.  This header
    51 // file may change from version to version without notice, or even be removed.
     50// of other Qt classes.  This header file may change from version to
     51// version without notice, or even be removed.
    5252//
    5353// We mean it.
     
    6969#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW
    7070
    71 class Q_GUI_EXPORT QGraphicsWidgetPrivate : public QGraphicsItemPrivate
     71class QGraphicsWidgetPrivate : public QGraphicsItemPrivate
    7272{
    7373    Q_DECLARE_PUBLIC(QGraphicsWidget)
    7474public:
    7575    QGraphicsWidgetPrivate()
    76         : leftMargin(0),
    77           topMargin(0),
    78           rightMargin(0),
    79           bottomMargin(0),
    80           leftLayoutItemMargin(0),
    81           topLayoutItemMargin(0),
    82           rightLayoutItemMargin(0),
    83           bottomLayoutItemMargin(0),
     76        : margins(0),
    8477          layout(0),
    8578          inheritedPaletteResolveMask(0),
     
    9184          focusNext(0),
    9285          focusPrev(0),
    93           focusChild(0),
    9486          windowFlags(0),
    95           hoveredSubControl(QStyle::SC_None),
    96           grabbedSection(Qt::NoSection),
    97           buttonMouseOver(false),
    98           buttonSunken(false),
     87          windowData(0),
    9988          setWindowFrameMargins(false),
    100           leftWindowFrameMargin(0),
    101           topWindowFrameMargin(0),
    102           rightWindowFrameMargin(0),
    103           bottomWindowFrameMargin(0)
     89          windowFrameMargins(0)
    10490    { }
     91    virtual ~QGraphicsWidgetPrivate();
    10592
    10693    void init(QGraphicsItem *parentItem, Qt::WindowFlags wFlags);
     
    10895
    10996    // Margins
    110     qreal leftMargin;
    111     qreal topMargin;
    112     qreal rightMargin;
    113     qreal bottomMargin;
    114     QRectF contentsRect;
    115 
    116     // Layout item margins
    117     void getLayoutItemMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const;
    118     void setLayoutItemMargins(qreal left, qreal top, qreal right, qreal bottom);
    119     void setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt = 0);
    120 
    121     void fixFocusChainBeforeReparenting(QGraphicsWidget *newParent, QGraphicsScene *newScene = 0);
     97    enum {Left, Top, Right, Bottom};
     98    mutable qreal *margins;
     99    void ensureMargins() const;
     100
     101    void fixFocusChainBeforeReparenting(QGraphicsWidget *newParent, QGraphicsScene *oldScene, QGraphicsScene *newScene = 0);
    122102    void setLayout_helper(QGraphicsLayout *l);
    123 
    124     qreal leftLayoutItemMargin;
    125     qreal topLayoutItemMargin;
    126     qreal rightLayoutItemMargin;
    127     qreal bottomLayoutItemMargin;
    128103
    129104    // Layouts
     
    203178    QGraphicsWidget *focusNext;
    204179    QGraphicsWidget *focusPrev;
    205     QGraphicsWidget *focusChild;
    206     void setFocusWidget();
    207     void clearFocusWidget();
    208180
    209181    // Windows
    210182    Qt::WindowFlags windowFlags;
    211     QString windowTitle;
    212     QStyle::SubControl hoveredSubControl;
    213     Qt::WindowFrameSection grabbedSection;
    214     uint buttonMouseOver : 1;
    215     uint buttonSunken : 1;
    216     QPointF mouseDelta; // to compensate for small error when interactively resizing
    217     QRectF startGeometry;
    218     QRect buttonRect;
     183    struct WindowData {
     184        QString windowTitle;
     185        QStyle::SubControl hoveredSubControl;
     186        Qt::WindowFrameSection grabbedSection;
     187        uint buttonMouseOver : 1;
     188        uint buttonSunken : 1;
     189        QRectF startGeometry;
     190        QRect buttonRect;
     191        WindowData()
     192            : hoveredSubControl(QStyle::SC_None)
     193            , grabbedSection(Qt::NoSection)
     194            , buttonMouseOver(false)
     195            , buttonSunken(false)
     196        {}
     197    } *windowData;
     198    void ensureWindowData();
    219199
    220200    bool setWindowFrameMargins;
    221     qreal leftWindowFrameMargin;
    222     qreal topWindowFrameMargin;
    223     qreal rightWindowFrameMargin;
    224     qreal bottomWindowFrameMargin;
     201    mutable qreal *windowFrameMargins;
     202    void ensureWindowFrameMargins() const;
    225203
    226204#ifndef QT_NO_ACTION
  • trunk/src/gui/graphicsview/qgridlayoutengine.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**
     
    5252
    5353#include <QtDebug>
     54#include <QtCore/qmath.h>
    5455
    5556QT_BEGIN_NAMESPACE
     
    7172{
    7273    Q_ASSERT(sumDesired != 0.0);
    73     return desired * ::pow(sumAvailable / sumDesired, desired / sumDesired);
     74    return desired * qPow(sumAvailable / sumDesired, desired / sumDesired);
    7475}
    7576
     
    276277                            factors[i] = (stretch < 0) ? 1.0 : 0.0;
    277278                        } else {
    278                             factors[i] = (stretch < 0) ? sizes[i] : 0.0;                       
     279                            factors[i] = (stretch < 0) ? sizes[i] : 0.0;
    279280                        }
    280281                    } else if (stretch == sumStretches) {
     
    462463QGridLayoutItem::QGridLayoutItem(QGridLayoutEngine *engine, QGraphicsLayoutItem *layoutItem,
    463464                                 int row, int column, int rowSpan, int columnSpan,
    464                                  Qt::Alignment alignment)
     465                                 Qt::Alignment alignment, int itemAtIndex)
    465466    : q_engine(engine), q_layoutItem(layoutItem), q_alignment(alignment)
    466467{
     
    472473    q_stretches[Ver] = -1;
    473474
    474     q_engine->addItem(this);
     475    q_engine->insertItem(this, itemAtIndex);
    475476}
    476477
     
    616617        width = size.width();
    617618        height = size.height();
    618        
     619
    619620        Qt::Alignment align = q_engine->effectiveAlignment(this);
    620621        switch (align & Qt::AlignHorizontal_Mask) {
     
    718719{
    719720    count += delta;
    720    
     721
    721722    insertOrRemoveItems(stretches, row, delta);
    722723    insertOrRemoveItems(spacings, row, delta);
     
    938939}
    939940
    940 void QGridLayoutEngine::addItem(QGridLayoutItem *item)
     941/*!
     942    \internal
     943    The \a index is only used by QGraphicsLinearLayout to ensure that itemAt() reflects the order
     944    of visual arrangement. Strictly speaking it does not have to, but most people expect it to.
     945    (And if it didn't we would have to add itemArrangedAt(int index) or something..)
     946 */
     947void QGridLayoutEngine::insertItem(QGridLayoutItem *item, int index)
    941948{
    942949    maybeExpandGrid(item->lastRow(), item->lastColumn());
    943950
    944     q_items.append(item);
     951    if (index == -1)
     952        q_items.append(item);
     953    else
     954        q_items.insert(index, item);
    945955
    946956    for (int i = item->firstRow(); i <= item->lastRow(); ++i) {
     
    951961        }
    952962    }
     963}
     964
     965void QGridLayoutEngine::addItem(QGridLayoutItem *item)
     966{
     967    insertItem(item, -1);
    953968}
    954969
     
    10771092    }
    10781093    return QSizeF();
    1079 } 
     1094}
    10801095
    10811096QSizePolicy::ControlTypes QGridLayoutEngine::controlTypes(LayoutSide side) const
     
    11321147        for (int column = 0; column < internalGridColumnCount(); ++column) {
    11331148            message += QString::number(q_items.indexOf(itemAt(row, column))).rightJustified(3);
    1134             message += QLatin1String(" ");
    1135         }
    1136         message += QLatin1String("]");
     1149            message += QLatin1Char(' ');
     1150        }
     1151        message += QLatin1Char(']');
    11371152        qDebug("%*s  %s", indent, "", qPrintable(message));
    11381153    }
     
    11511166
    11521167    qDebug("%*s Geometries output", indent, "");
     1168    QVector<qreal> *cellPos = &q_yy;
    11531169    for (int pass = 0; pass < 2; ++pass) {
    1154         QVector<qreal> &cellPos = q_yy;
    11551170        QString message;
    1156         for (i = 0; i < cellPos.count(); ++i) {
     1171        for (i = 0; i < cellPos->count(); ++i) {
    11571172            message += QLatin1String((message.isEmpty() ? "[" : ", "));
    1158             message += QString::number(cellPos.at(i));
    1159         }
    1160         message += QLatin1String("]");
     1173            message += QString::number(cellPos->at(i));
     1174        }
     1175        message += QLatin1Char(']');
    11611176        qDebug("%*s %s %s", indent, "", (pass == 0 ? "rows:" : "columns:"), qPrintable(message));
    1162         cellPos = q_xx;
     1177        cellPos = &q_xx;
    11631178    }
    11641179}
     
    15391554
    15401555QT_END_NAMESPACE
    1541        
     1556
    15421557#endif //QT_NO_GRAPHICSVIEW
  • trunk/src/gui/graphicsview/qgridlayoutengine_p.h

    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**
     
    6060#include "qpair.h"
    6161#include "qvector.h"
    62 
     62#include "qgraphicslayout_p.h"
    6363#include <float.h>
    6464
     
    129129};
    130130
    131 class QLayoutStyleInfo
    132 {
    133 public:
    134     inline QLayoutStyleInfo() { invalidate(); }
    135     inline QLayoutStyleInfo(QStyle *style, QWidget *widget)
    136         : q_valid(true), q_style(style), q_widget(widget) {}
    137 
    138     inline void invalidate() { q_valid = false; q_style = 0; q_widget = 0; }
    139 
    140     inline QStyle *style() const { return q_style; }
    141     inline QWidget *widget() const { return q_widget; }
    142 
    143     inline bool operator==(const QLayoutStyleInfo &other)
    144         { return q_style == other.q_style && q_widget == other.q_widget; }
    145     inline bool operator!=(const QLayoutStyleInfo &other)
    146         { return !(*this == other); }
    147 
    148 private:
    149     bool q_valid;
    150     QStyle *q_style;
    151     QWidget *q_widget;
    152 };
    153 
    154131class QGridLayoutBox
    155132{
     
    268245public:
    269246    QGridLayoutItem(QGridLayoutEngine *engine, QGraphicsLayoutItem *layoutItem, int row, int column,
    270                     int rowSpan = 1, int columnSpan = 1, Qt::Alignment alignment = 0);
     247                    int rowSpan = 1, int columnSpan = 1, Qt::Alignment alignment = 0,
     248                    int itemAtIndex = -1);
    271249
    272250    inline int firstRow() const { return q_firstRows[Ver]; }
     
    379357
    380358
     359    void insertItem(QGridLayoutItem *item, int index);
    381360    void addItem(QGridLayoutItem *item);
    382361    void removeItem(QGridLayoutItem *item);
Note: See TracChangeset for help on using the changeset viewer.