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

trunk: Merged in qt 4.6.1 sources.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

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

    r2 r561  
    22**
    33** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
    4 ** Contact: Qt Software Information ([email protected])
     4** All rights reserved.
     5** Contact: Nokia Corporation ([email protected])
    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
     37** @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    \im 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
     190
     191
     192
     193
     194
     195
     196
     197
     198
     199
     200
     201
     202
     203
     204
     205
     206
     207
     208
     209
     210
     211
     212
     213
     214
     215
     216
     217
     218
     219
     220
     221
     222
     223
     224
     225
     226
     227
     228
     229
     230
     231
     232
     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
     350
     351
     352
     353
     354
     355
     356
     357
     358
     359
     360
     361
     362
     363
     364
     365
     366
     367
     368
     369
     370
     371
     372
     373
     374
     375
     376
     377
     378
     379
     380
     381
     382
     383
     384
     385
     386
     387
     388
     389
     390
     391
     392
     393
     394
    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
     434   
     435   
     436   
     437   
     438   
     439   
     440    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
     468    e
     469   
     470   
     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
     573
     574
     575
     576
     577
     578
    449579*/
    450580
     
    492622*/
    493623
     624
     625
     626
     627
     628
     629
     630
     631
     632
     633
     634
     635
     636
     637
     638
     639
    494640#include "qgraphicsitem.h"
    495641
     
    502648#include "qgraphicswidget.h"
    503649#include "qgraphicsproxywidget.h"
     650
    504651#include <QtCore/qbitarray.h>
    505652#include <QtCore/qdebug.h>
     
    516663#include <QtGui/qstyleoption.h>
    517664#include <QtGui/qevent.h>
     665
     666
    518667
    519668#include <private/qgraphicsitem_p.h>
     
    522671#include <private/qtextdocumentlayout_p.h>
    523672#include <private/qtextengine_p.h>
     673
     674
     675
     676
     677
     678
     679
     680
    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
     748
     749
     750
    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
     984
     985
     986
     987
     988
     989
     990
     991
     992
     993
     994
     995
     996
     997
     998
     999
     1000
     1001
     1002
     1003
     1004
     1005
     1006
     1007
     1008
     1009
     1010
     1011
     1012
     1013
     1014
     1015
     1016
     1017
     1018
     1019
     1020
     1021
     1022
     1023
     1024
     1025
     1026
     1027
     1028
     1029
     1030
     1031
     1032
     1033
     1034
     1035
     1036
     1037
     1038
     1039
     1040
     1041
     1042
     1043
     1044
     1045
     1046
     1047
     1048
     1049
     1050
     1051
     1052
     1053
     1054
     1055
     1056
     1057
     1058
     1059
     1060
     1061
     1062
     1063
     1064
     1065
     1066
     1067
     1068
     1069
     1070
     1071
     1072
     1073
     1074
     1075
     1076
     1077
     1078
     1079
     1080
     1081
     1082
     1083
     1084
     1085
     1086
     1087
     1088
     1089
     1090
     1091
     1092
     1093
     1094
     1095
     1096
     1097
     1098
     1099
     1100
     1101
     1102
     1103
     1104
     1105
     1106
     1107
     1108
     1109
     1110
     1111
     1112
     1113
     1114
     1115
     1116
     1117
     1118
     1119
     1120
     1121
     1122
     1123
     1124
     1125
     1126
     1127
     1128
     1129
     1130
     1131
     1132
     1133
     1134
     1135
     1136
     1137
     1138
     1139
     1140
     1141
     1142
     1143
     1144
     1145
     1146
     1147
     1148
     1149
     1150
     1151
     1152
     1153
     1154
     1155
     1156
     1157
     1158
     1159
     1160
     1161
     1162
     1163
     1164
     1165
     1166
     1167
     1168
     1169
     1170
     1171
     1172
     1173
     1174
     1175
     1176
     1177
     1178
     1179
     1180
     1181
     1182
     1183
     1184
     1185
     1186
     1187
     1188
     1189
     1190
     1191
     1192
     1193
     1194
     1195
     1196
     1197
     1198
     1199
     1200
     1201
     1202
     1203
     1204
     1205
     1206
     1207
     1208
     1209
     1210
     1211
     1212
     1213
     1214
     1215
     1216
     1217
     1218
     1219
     1220
     1221
     1222
     1223
     1224
     1225
     1226
     1227
     1228
     1229
     1230
     1231
     1232
     1233
     1234
     1235
     1236
     1237
     1238
     1239
     1240
     1241
     1242
     1243
     1244
     1245
     1246
     1247
    7841248    Empty all cached pixmaps from the pixmap cache.
    7851249*/
     
    7871251{
    7881252    QPixmapCache::remove(key);
     1253
    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
     1321
    8531322*/
    8541323QGraphicsItem::~QGraphicsItem()
    8551324{
     1325
     1326
     1327
     1328
     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(), child()
    9351424*/
    9361425QGraphicsItem *QGraphicsItem::parentItem() const
     
    9551444
    9561445/*!
     1446
     1447
     1448
     1449
     1450
     1451
     1452
     1453
     1454
     1455
     1456
     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
     1509
     1510
     1511
     1512
     1513
     1514
     1515
     1516
     1517
     1518
     1519
     1520
     1521
     1522
     1523
     1524
     1525
     1526
     1527
     1528
     1529
     1530
     1531
     1532
     1533
     1534
     1535
     1536
     1537
     1538
     1539
     1540
     1541
     1542
    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
    11341588    return d_ptr->children;
    11351589}
     
    11551609{
    11561610    return isWidget() && (static_cast<const QGraphicsWidget *>(this)->windowType() & Qt::Window);
     1611
     1612
     1613
     1614
     1615
     1616
     1617
     1618
     1619
     1620
     1621
    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
     1688
     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
     1697
    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    );
     1701    bool fullUpdate = ( & geomChangeFlagsMask) != (d_ptr->flags & geomChangeFlagsMask);
    12301702    if (fullUpdate)
    1231         d_ptr->fullUpdateHelper(false, true);
     1703        d_ptr->;
    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
     1846
     1847
     1848
     1849
     1850
     1851
     1852
     1853
     1854
     1855
     1856
     1857
     1858
     1859
     1860
     1861
     1862
     1863
     1864
     1865
     1866
     1867
     1868
     1869
     1870
     1871
     1872
     1873
     1874
     1875
     1876
     1877
     1878
     1879
     1880
     1881
     1882
     1883
     1884
     1885
     1886
     1887
     1888
     1889
     1890
     1891
     1892
     1893
     1894
     1895
     1896
     1897
     1898
     1899
     1900
     1901
     1902
     1903
     1904
     1905
     1906
     1907
     1908
     1909
     1910
     1911
     1912
     1913
     1914
     1915
     1916
     1917
     1918
     1919
     1920
     1921
     1922
     1923
     1924
    13501925#ifndef QT_NO_TOOLTIP
    13511926/*!
     
    14161991    d_ptr->hasCursor = 1;
    14171992    if (d_ptr->scene) {
     1993
    14181994        foreach (QGraphicsView *view, d_ptr->scene->views()) {
     1995
    14191996            // Note: Some of this logic is duplicated in QGraphicsView's mouse events.
    14201997            if (view->underMouse()) {
     
    15232100        return;
    15242101
     2102
     2103
     2104
     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
     2131
    15482132        }
    15492133        if (q_ptr->hasFocus() && scene) {
    1550             // Hiding the closest non-window ancestor of the focus item
     2134            // Hiding the closest non- ancestor of the focus item
    15512135            QGraphicsItem *focusItem = scene->focusItem();
    15522136            bool clear = true;
    1553             if (isWidget && !focusItem->isWindow()) {
     2137            if (isWidget && !focusItem->is()) {
    15542138                do {
    15552139                    if (focusItem == q_ptr) {
     
    15572141                        break;
    15582142                    }
    1559                 } while ((focusItem = focusItem->parentWidget()) && !focusItem->isWindow());
     2143                } while ((focusItem = focusItem->parentWidget()) && !focusItem->is());
    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
     2173
     2174
     2175
     2176
     2177
     2178
     2179
     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
     2212
    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- 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->is() && 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->is());
    16872309            }
    16882310            if (clear)
     
    17002322    // Schedule redraw.
    17012323    if (update)
    1702         updateHelper();
     2324        ();
    17032325
    17042326    foreach (QGraphicsItem *child, children) {
     
    17092331    // Deliver post-change notification.
    17102332    q_ptr->itemChange(QGraphicsItem::ItemEnabledHasChanged, newEnabledVariant);
     2333
     2334
     2335
    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 ()
    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, newOpacity);
    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
     2792    s
     2793   
     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
     2805
    20502806    d_ptr->acceptsHover = quint32(enabled);
     2807
     2808
     2809
     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
     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
     3085    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(), 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
     3117
     3118
     3119
     3120
     3121
     3122
     3123
     3124
     3125
     3126
     3127
     3128
     3129
     3130
     3131
     3132
     3133
     3134
     3135
     3136
     3137
     3138
     3139
     3140
     3141
     3142
     3143
     3144
     3145
     3146
     3147
     3148
     3149
     3150
     3151
     3152
     3153
     3154
     3155
     3156
     3157
     3158
     3159
     3160
     3161
     3162
     3163
     3164
     3165
     3166
     3167
     3168
     3169
     3170
     3171
     3172
     3173
     3174
     3175
     3176
     3177
     3178
     3179
     3180
     3181
     3182
     3183
     3184
     3185
     3186
     3187
     3188
     3189
     3190
     3191
     3192
     3193
     3194
     3195
     3196
     3197
    21753198}
    21763199