src/gui/graphicsview/qgraphicssceneindex.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 /*!
       
    42     \class QGraphicsSceneIndex
       
    43     \brief The QGraphicsSceneIndex class provides a base class to implement
       
    44     a custom indexing algorithm for discovering items in QGraphicsScene.
       
    45     \since 4.6
       
    46     \ingroup graphicsview-api
       
    47 
       
    48     \internal
       
    49 
       
    50     The QGraphicsSceneIndex class provides a base class to implement
       
    51     a custom indexing algorithm for discovering items in QGraphicsScene. You
       
    52     need to subclass it and reimplement addItem, removeItem, estimateItems
       
    53     and items in order to have an functional indexing.
       
    54 
       
    55     \sa QGraphicsScene, QGraphicsView
       
    56 */
       
    57 
       
    58 #include "qdebug.h"
       
    59 #include "qgraphicsscene.h"
       
    60 #include "qgraphicsitem_p.h"
       
    61 #include "qgraphicsscene_p.h"
       
    62 #include "qgraphicswidget.h"
       
    63 #include "qgraphicssceneindex_p.h"
       
    64 #include "qgraphicsscenebsptreeindex_p.h"
       
    65 
       
    66 #ifndef QT_NO_GRAPHICSVIEW
       
    67 
       
    68 QT_BEGIN_NAMESPACE
       
    69 
       
    70 class QGraphicsSceneIndexRectIntersector : public QGraphicsSceneIndexIntersector
       
    71 {
       
    72 public:
       
    73     bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode,
       
    74                    const QTransform &deviceTransform) const
       
    75     {
       
    76         QRectF brect = item->boundingRect();
       
    77         _q_adjustRect(&brect);
       
    78 
       
    79         // ### Add test for this (without making things slower?)
       
    80         Q_UNUSED(exposeRect);
       
    81 
       
    82         bool keep = true;
       
    83         const QGraphicsItemPrivate *itemd = QGraphicsItemPrivate::get(item);
       
    84         if (itemd->itemIsUntransformable()) {
       
    85             // Untransformable items; map the scene rect to item coordinates.
       
    86             const QTransform transform = item->deviceTransform(deviceTransform);
       
    87             QRectF itemRect = (deviceTransform * transform.inverted()).mapRect(sceneRect);
       
    88             if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect)
       
    89                 keep = itemRect.contains(brect) && itemRect != brect;
       
    90             else
       
    91                 keep = itemRect.intersects(brect);
       
    92             if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
       
    93                 QPainterPath itemPath;
       
    94                 itemPath.addRect(itemRect);
       
    95                 keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, itemPath, mode);
       
    96             }
       
    97         } else {
       
    98             Q_ASSERT(!itemd->dirtySceneTransform);
       
    99             const QRectF itemSceneBoundingRect = itemd->sceneTransformTranslateOnly
       
   100                                                ? brect.translated(itemd->sceneTransform.dx(),
       
   101                                                                   itemd->sceneTransform.dy())
       
   102                                                : itemd->sceneTransform.mapRect(brect);
       
   103             if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect)
       
   104                 keep = sceneRect != brect && sceneRect.contains(itemSceneBoundingRect);
       
   105             else
       
   106                 keep = sceneRect.intersects(itemSceneBoundingRect);
       
   107             if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
       
   108                 QPainterPath rectPath;
       
   109                 rectPath.addRect(sceneRect);
       
   110                 if (itemd->sceneTransformTranslateOnly)
       
   111                     rectPath.translate(-itemd->sceneTransform.dx(), -itemd->sceneTransform.dy());
       
   112                 else
       
   113                     rectPath = itemd->sceneTransform.inverted().map(rectPath);
       
   114                 keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, rectPath, mode);
       
   115             }
       
   116         }
       
   117         return keep;
       
   118     }
       
   119 
       
   120     QRectF sceneRect;
       
   121 };
       
   122 
       
   123 class QGraphicsSceneIndexPointIntersector : public QGraphicsSceneIndexIntersector
       
   124 {
       
   125 public:
       
   126     bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode,
       
   127                    const QTransform &deviceTransform) const
       
   128     {
       
   129         QRectF brect = item->boundingRect();
       
   130         _q_adjustRect(&brect);
       
   131 
       
   132         // ### Add test for this (without making things slower?)
       
   133         Q_UNUSED(exposeRect);
       
   134 
       
   135         bool keep = false;
       
   136         const QGraphicsItemPrivate *itemd = QGraphicsItemPrivate::get(item);
       
   137         if (itemd->itemIsUntransformable()) {
       
   138             // Untransformable items; map the scene point to item coordinates.
       
   139             const QTransform transform = item->deviceTransform(deviceTransform);
       
   140             QPointF itemPoint = (deviceTransform * transform.inverted()).map(scenePoint);
       
   141             keep = brect.contains(itemPoint);
       
   142             if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
       
   143                 QPainterPath pointPath;
       
   144                 pointPath.addRect(QRectF(itemPoint, QSizeF(1, 1)));
       
   145                 keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, pointPath, mode);
       
   146             }
       
   147         } else {
       
   148             Q_ASSERT(!itemd->dirtySceneTransform);
       
   149             QRectF sceneBoundingRect = itemd->sceneTransformTranslateOnly
       
   150                                      ? brect.translated(itemd->sceneTransform.dx(),
       
   151                                                         itemd->sceneTransform.dy())
       
   152                                      : itemd->sceneTransform.mapRect(brect);
       
   153             keep = sceneBoundingRect.intersects(QRectF(scenePoint, QSizeF(1, 1)));
       
   154             if (keep) {
       
   155                 QPointF p = itemd->sceneTransformTranslateOnly
       
   156                           ? QPointF(scenePoint.x() - itemd->sceneTransform.dx(),
       
   157                                     scenePoint.y() - itemd->sceneTransform.dy())
       
   158                           : itemd->sceneTransform.inverted().map(scenePoint);
       
   159                 keep = item->contains(p);
       
   160             }
       
   161         }
       
   162 
       
   163         return keep;
       
   164     }
       
   165 
       
   166     QPointF scenePoint;
       
   167 };
       
   168 
       
   169 class QGraphicsSceneIndexPathIntersector : public QGraphicsSceneIndexIntersector
       
   170 {
       
   171 public:
       
   172     bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode,
       
   173                    const QTransform &deviceTransform) const
       
   174     {
       
   175         QRectF brect = item->boundingRect();
       
   176         _q_adjustRect(&brect);
       
   177 
       
   178         // ### Add test for this (without making things slower?)
       
   179         Q_UNUSED(exposeRect);
       
   180 
       
   181         bool keep = true;
       
   182         const QGraphicsItemPrivate *itemd = QGraphicsItemPrivate::get(item);
       
   183         if (itemd->itemIsUntransformable()) {
       
   184             // Untransformable items; map the scene rect to item coordinates.
       
   185             const QTransform transform = item->deviceTransform(deviceTransform);
       
   186             QPainterPath itemPath = (deviceTransform * transform.inverted()).map(scenePath);
       
   187             if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect)
       
   188                 keep = itemPath.contains(brect);
       
   189             else
       
   190                 keep = itemPath.intersects(brect);
       
   191             if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape))
       
   192                 keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, itemPath, mode);
       
   193         } else {
       
   194             Q_ASSERT(!itemd->dirtySceneTransform);
       
   195             const QRectF itemSceneBoundingRect = itemd->sceneTransformTranslateOnly
       
   196                                                ? brect.translated(itemd->sceneTransform.dx(),
       
   197                                                                   itemd->sceneTransform.dy())
       
   198                                                : itemd->sceneTransform.mapRect(brect);
       
   199             if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect)
       
   200                 keep = scenePath.contains(itemSceneBoundingRect);
       
   201             else
       
   202                 keep = scenePath.intersects(itemSceneBoundingRect);
       
   203             if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
       
   204                 QPainterPath itemPath = itemd->sceneTransformTranslateOnly
       
   205                                       ? scenePath.translated(-itemd->sceneTransform.dx(),
       
   206                                                              -itemd->sceneTransform.dy())
       
   207                                       : itemd->sceneTransform.inverted().map(scenePath);
       
   208                 keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, itemPath, mode);
       
   209             }
       
   210         }
       
   211         return keep;
       
   212     }
       
   213 
       
   214     QPainterPath scenePath;
       
   215 };
       
   216 
       
   217 /*!
       
   218     Constructs a private scene index.
       
   219 */
       
   220 QGraphicsSceneIndexPrivate::QGraphicsSceneIndexPrivate(QGraphicsScene *scene) : scene(scene)
       
   221 {
       
   222     pointIntersector = new QGraphicsSceneIndexPointIntersector;
       
   223     rectIntersector = new QGraphicsSceneIndexRectIntersector;
       
   224     pathIntersector =  new QGraphicsSceneIndexPathIntersector;
       
   225 }
       
   226 
       
   227 /*!
       
   228     Destructor of private scene index.
       
   229 */
       
   230 QGraphicsSceneIndexPrivate::~QGraphicsSceneIndexPrivate()
       
   231 {
       
   232     delete pointIntersector;
       
   233     delete rectIntersector;
       
   234     delete pathIntersector;
       
   235 }
       
   236 
       
   237 /*!
       
   238     \internal
       
   239 
       
   240     Checks if item collides with the path and mode, but also checks that if it
       
   241     doesn't collide, maybe its frame rect will.
       
   242 */
       
   243 bool QGraphicsSceneIndexPrivate::itemCollidesWithPath(const QGraphicsItem *item,
       
   244                                                       const QPainterPath &path,
       
   245                                                       Qt::ItemSelectionMode mode)
       
   246 {
       
   247     if (item->collidesWithPath(path, mode))
       
   248         return true;
       
   249     if (item->isWidget()) {
       
   250         // Check if this is a window, and if its frame rect collides.
       
   251         const QGraphicsWidget *widget = static_cast<const QGraphicsWidget *>(item);
       
   252         if (widget->isWindow()) {
       
   253             QRectF frameRect = widget->windowFrameRect();
       
   254             QPainterPath framePath;
       
   255             framePath.addRect(frameRect);
       
   256             bool intersects = path.intersects(frameRect);
       
   257             if (mode == Qt::IntersectsItemShape || mode == Qt::IntersectsItemBoundingRect)
       
   258                 return intersects || path.contains(frameRect.topLeft())
       
   259                     || framePath.contains(path.elementAt(0));
       
   260             return !intersects && path.contains(frameRect.topLeft());
       
   261         }
       
   262     }
       
   263     return false;
       
   264 }
       
   265 
       
   266 /*!
       
   267     \internal
       
   268     This function returns the items in ascending order.
       
   269 */
       
   270 void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRectF exposeRect,
       
   271                                                         QGraphicsSceneIndexIntersector *intersector,
       
   272                                                         QList<QGraphicsItem *> *items,
       
   273                                                         const QTransform &viewTransform,
       
   274                                                         Qt::ItemSelectionMode mode,
       
   275                                                         qreal parentOpacity) const
       
   276 {
       
   277     Q_ASSERT(item);
       
   278     if (!item->d_ptr->visible)
       
   279         return;
       
   280 
       
   281     const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
       
   282     const bool itemIsFullyTransparent = (opacity < 0.0001);
       
   283     const bool itemHasChildren = !item->d_ptr->children.isEmpty();
       
   284     if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity()))
       
   285         return;
       
   286 
       
   287     // Update the item's scene transform if dirty.
       
   288     const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable();
       
   289     const bool wasDirtyParentSceneTransform = item->d_ptr->dirtySceneTransform && !itemIsUntransformable;
       
   290     if (wasDirtyParentSceneTransform) {
       
   291         item->d_ptr->updateSceneTransformFromParent();
       
   292         Q_ASSERT(!item->d_ptr->dirtySceneTransform);
       
   293     }
       
   294 
       
   295     const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
       
   296     bool processItem = !itemIsFullyTransparent;
       
   297     if (processItem) {
       
   298         processItem = intersector->intersect(item, exposeRect, mode, viewTransform);
       
   299         if (!processItem && (!itemHasChildren || itemClipsChildrenToShape)) {
       
   300             if (wasDirtyParentSceneTransform)
       
   301                 item->d_ptr->invalidateChildrenSceneTransform();
       
   302             return;
       
   303         }
       
   304     } // else we know for sure this item has children we must process.
       
   305 
       
   306     int i = 0;
       
   307     if (itemHasChildren) {
       
   308         // Sort children.
       
   309         item->d_ptr->ensureSortedChildren();
       
   310 
       
   311         // Clip to shape.
       
   312         if (itemClipsChildrenToShape && !itemIsUntransformable) {
       
   313             QPainterPath mappedShape = item->d_ptr->sceneTransformTranslateOnly
       
   314                                      ? item->shape().translated(item->d_ptr->sceneTransform.dx(),
       
   315                                                                 item->d_ptr->sceneTransform.dy())
       
   316                                      : item->d_ptr->sceneTransform.map(item->shape());
       
   317             exposeRect &= mappedShape.controlPointRect();
       
   318         }
       
   319 
       
   320         // Process children behind
       
   321         for (i = 0; i < item->d_ptr->children.size(); ++i) {
       
   322             QGraphicsItem *child = item->d_ptr->children.at(i);
       
   323             if (wasDirtyParentSceneTransform)
       
   324                 child->d_ptr->dirtySceneTransform = 1;
       
   325             if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent))
       
   326                 break;
       
   327             if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
       
   328                 continue;
       
   329             recursive_items_helper(child, exposeRect, intersector, items, viewTransform,
       
   330                                    mode, opacity);
       
   331         }
       
   332     }
       
   333 
       
   334     // Process item
       
   335     if (processItem)
       
   336         items->append(item);
       
   337 
       
   338     // Process children in front
       
   339     if (itemHasChildren) {
       
   340         for (; i < item->d_ptr->children.size(); ++i) {
       
   341             QGraphicsItem *child = item->d_ptr->children.at(i);
       
   342             if (wasDirtyParentSceneTransform)
       
   343                 child->d_ptr->dirtySceneTransform = 1;
       
   344             if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
       
   345                 continue;
       
   346             recursive_items_helper(child, exposeRect, intersector, items, viewTransform,
       
   347                                    mode, opacity);
       
   348         }
       
   349     }
       
   350 }
       
   351 
       
   352 void QGraphicsSceneIndexPrivate::init()
       
   353 {
       
   354     if (!scene)
       
   355         return;
       
   356 
       
   357     QObject::connect(scene, SIGNAL(sceneRectChanged(const QRectF&)),
       
   358                      q_func(), SLOT(updateSceneRect(const QRectF&)));
       
   359 }
       
   360 
       
   361 /*!
       
   362     Constructs an abstract scene index for a given \a scene.
       
   363 */
       
   364 QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsScene *scene)
       
   365 : QObject(*new QGraphicsSceneIndexPrivate(scene), scene)
       
   366 {
       
   367     d_func()->init();
       
   368 }
       
   369 
       
   370 /*!
       
   371     \internal
       
   372 */
       
   373 QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsSceneIndexPrivate &dd, QGraphicsScene *scene)
       
   374     : QObject(dd, scene)
       
   375 {
       
   376     d_func()->init();
       
   377 }
       
   378 
       
   379 /*!
       
   380     Destroys the scene index.
       
   381 */
       
   382 QGraphicsSceneIndex::~QGraphicsSceneIndex()
       
   383 {
       
   384 
       
   385 }
       
   386 
       
   387 /*!
       
   388     Returns the scene of this index.
       
   389 */
       
   390 QGraphicsScene* QGraphicsSceneIndex::scene() const
       
   391 {
       
   392     Q_D(const QGraphicsSceneIndex);
       
   393     return d->scene;
       
   394 }
       
   395 
       
   396 /*!
       
   397     \fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPointF &pos,
       
   398     Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform
       
   399     &deviceTransform) const
       
   400 
       
   401     Returns all visible items that, depending on \a mode, are at the specified
       
   402     \a pos and return a list sorted using \a order.
       
   403 
       
   404     The default value for \a mode is Qt::IntersectsItemShape; all items whose
       
   405     exact shape intersects with \a pos are returned.
       
   406 
       
   407     \a deviceTransform is the transformation apply to the view.
       
   408 
       
   409     This method use the estimation of the index (estimateItems) and refine the
       
   410     list to get an exact result. If you want to implement your own refinement
       
   411     algorithm you can reimplement this method.
       
   412 
       
   413     \sa estimateItems()
       
   414 
       
   415 */
       
   416 QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode,
       
   417                                                   Qt::SortOrder order, const QTransform &deviceTransform) const
       
   418 {
       
   419 
       
   420     Q_D(const QGraphicsSceneIndex);
       
   421     QList<QGraphicsItem *> itemList;
       
   422     d->pointIntersector->scenePoint = pos;
       
   423     d->items_helper(QRectF(pos, QSizeF(1, 1)), d->pointIntersector, &itemList, deviceTransform, mode, order);
       
   424     return itemList;
       
   425 }
       
   426 
       
   427 /*!
       
   428     \fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QRectF &rect,
       
   429     Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform
       
   430     &deviceTransform) const
       
   431 
       
   432     \overload
       
   433 
       
   434     Returns all visible items that, depending on \a mode, are either inside or
       
   435     intersect with the specified \a rect and return a list sorted using \a order.
       
   436 
       
   437     The default value for \a mode is Qt::IntersectsItemShape; all items whose
       
   438     exact shape intersects with or is contained by \a rect are returned.
       
   439 
       
   440     \a deviceTransform is the transformation apply to the view.
       
   441 
       
   442     This method use the estimation of the index (estimateItems) and refine
       
   443     the list to get an exact result. If you want to implement your own
       
   444     refinement algorithm you can reimplement this method.
       
   445 
       
   446     \sa estimateItems()
       
   447 
       
   448 */
       
   449 QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSelectionMode mode,
       
   450                                                   Qt::SortOrder order, const QTransform &deviceTransform) const
       
   451 {
       
   452     Q_D(const QGraphicsSceneIndex);
       
   453     QRectF exposeRect = rect;
       
   454     _q_adjustRect(&exposeRect);
       
   455     QList<QGraphicsItem *> itemList;
       
   456     d->rectIntersector->sceneRect = rect;
       
   457     d->items_helper(exposeRect, d->rectIntersector, &itemList, deviceTransform, mode, order);
       
   458     return itemList;
       
   459 }
       
   460 
       
   461 /*!
       
   462     \fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPolygonF
       
   463     &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const
       
   464     QTransform &deviceTransform) const
       
   465 
       
   466     \overload
       
   467 
       
   468     Returns all visible items that, depending on \a mode, are either inside or
       
   469     intersect with the specified \a polygon and return a list sorted using \a order.
       
   470 
       
   471     The default value for \a mode is Qt::IntersectsItemShape; all items whose
       
   472     exact shape intersects with or is contained by \a polygon are returned.
       
   473 
       
   474     \a deviceTransform is the transformation apply to the view.
       
   475 
       
   476     This method use the estimation of the index (estimateItems) and refine
       
   477     the list to get an exact result. If you want to implement your own
       
   478     refinement algorithm you can reimplement this method.
       
   479 
       
   480     \sa estimateItems()
       
   481 
       
   482 */
       
   483 QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode,
       
   484                                                   Qt::SortOrder order, const QTransform &deviceTransform) const
       
   485 {
       
   486     Q_D(const QGraphicsSceneIndex);
       
   487     QList<QGraphicsItem *> itemList;
       
   488     QRectF exposeRect = polygon.boundingRect();
       
   489     _q_adjustRect(&exposeRect);
       
   490     QPainterPath path;
       
   491     path.addPolygon(polygon);
       
   492     d->pathIntersector->scenePath = path;
       
   493     d->items_helper(exposeRect, d->pathIntersector, &itemList, deviceTransform, mode, order);
       
   494     return itemList;
       
   495 }
       
   496 
       
   497 /*!
       
   498     \fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPainterPath
       
   499     &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform
       
   500     &deviceTransform) const
       
   501 
       
   502     \overload
       
   503 
       
   504     Returns all visible items that, depending on \a mode, are either inside or
       
   505     intersect with the specified \a path and return a list sorted using \a order.
       
   506 
       
   507     The default value for \a mode is Qt::IntersectsItemShape; all items whose
       
   508     exact shape intersects with or is contained by \a path are returned.
       
   509 
       
   510     \a deviceTransform is the transformation apply to the view.
       
   511 
       
   512     This method use the estimation of the index (estimateItems) and refine
       
   513     the list to get an exact result. If you want to implement your own
       
   514     refinement algorithm you can reimplement this method.
       
   515 
       
   516     \sa estimateItems()
       
   517 
       
   518 */
       
   519 QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPainterPath &path, Qt::ItemSelectionMode mode,
       
   520                                                   Qt::SortOrder order, const QTransform &deviceTransform) const
       
   521 {
       
   522     Q_D(const QGraphicsSceneIndex);
       
   523     QList<QGraphicsItem *> itemList;
       
   524     QRectF exposeRect = path.controlPointRect();
       
   525     _q_adjustRect(&exposeRect);
       
   526     d->pathIntersector->scenePath = path;
       
   527     d->items_helper(exposeRect, d->pathIntersector, &itemList, deviceTransform, mode, order);
       
   528     return itemList;
       
   529 }
       
   530 
       
   531 /*!
       
   532     This virtual function return an estimation of items at position \a point.
       
   533     This method return a list sorted using \a order.
       
   534 */
       
   535 QList<QGraphicsItem *> QGraphicsSceneIndex::estimateItems(const QPointF &point, Qt::SortOrder order) const
       
   536 {
       
   537     return estimateItems(QRectF(point, QSize(1, 1)), order);
       
   538 }
       
   539 
       
   540 QList<QGraphicsItem *> QGraphicsSceneIndex::estimateTopLevelItems(const QRectF &rect, Qt::SortOrder order) const
       
   541 {
       
   542     Q_D(const QGraphicsSceneIndex);
       
   543     Q_UNUSED(rect);
       
   544     QGraphicsScenePrivate *scened = d->scene->d_func();
       
   545     scened->ensureSortedTopLevelItems();
       
   546     if (order == Qt::DescendingOrder) {
       
   547         QList<QGraphicsItem *> sorted;
       
   548         for (int i = scened->topLevelItems.size() - 1; i >= 0; --i)
       
   549             sorted << scened->topLevelItems.at(i);
       
   550         return sorted;
       
   551     }
       
   552     return scened->topLevelItems;
       
   553 }
       
   554 
       
   555 /*!
       
   556     \fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(Qt::SortOrder order = Qt::DescendingOrder) const
       
   557     
       
   558     This pure virtual function all items in the index and sort them using
       
   559     \a order.
       
   560 */
       
   561 
       
   562 
       
   563 /*!
       
   564     Notifies the index that the scene's scene rect has changed. \a rect
       
   565     is thew new scene rect.
       
   566 
       
   567     \sa QGraphicsScene::sceneRect()
       
   568 */
       
   569 void QGraphicsSceneIndex::updateSceneRect(const QRectF &rect)
       
   570 {
       
   571     Q_UNUSED(rect);
       
   572 }
       
   573 
       
   574 /*!
       
   575     This virtual function removes all items in the scene index.
       
   576 */
       
   577 void QGraphicsSceneIndex::clear()
       
   578 {
       
   579     const QList<QGraphicsItem *> allItems = items();
       
   580     for (int i = 0 ; i < allItems.size(); ++i)
       
   581         removeItem(allItems.at(i));
       
   582 }
       
   583 
       
   584 /*!
       
   585     \fn virtual void QGraphicsSceneIndex::addItem(QGraphicsItem *item) = 0
       
   586 
       
   587     This pure virtual function inserts an \a item to the scene index.
       
   588 
       
   589     \sa removeItem(), deleteItem()
       
   590 */
       
   591 
       
   592 /*!
       
   593     \fn virtual void QGraphicsSceneIndex::removeItem(QGraphicsItem *item) = 0
       
   594 
       
   595     This pure virtual function removes an \a item to the scene index.
       
   596 
       
   597     \sa addItem(), deleteItem()
       
   598 */
       
   599 
       
   600 /*!
       
   601     This method is called when an \a item has been deleted.
       
   602     The default implementation call removeItem. Be carefull,
       
   603     if your implementation of removeItem use pure virtual method
       
   604     of QGraphicsItem like boundingRect(), then you should reimplement
       
   605     this method.
       
   606 
       
   607     \sa addItem(), removeItem()
       
   608 */
       
   609 void QGraphicsSceneIndex::deleteItem(QGraphicsItem *item)
       
   610 {
       
   611     removeItem(item);
       
   612 }
       
   613 
       
   614 /*!
       
   615     This virtual function is called by QGraphicsItem to notify the index
       
   616     that some part of the \a item 's state changes. By reimplementing this
       
   617     function, your can react to a change, and in some cases, (depending on \a
       
   618     change,) adjustments in the index can be made.
       
   619 
       
   620     \a change is the parameter of the item that is changing. \a value is the
       
   621     value that changed; the type of the value depends on \a change.
       
   622 
       
   623     The default implementation does nothing.
       
   624 
       
   625     \sa QGraphicsItem::GraphicsItemChange
       
   626 */
       
   627 void QGraphicsSceneIndex::itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value)
       
   628 {
       
   629     Q_UNUSED(item);
       
   630     Q_UNUSED(change);
       
   631     Q_UNUSED(value);
       
   632 }
       
   633 
       
   634 /*!
       
   635     Notify the index for a geometry change of an \a item.
       
   636 
       
   637     \sa QGraphicsItem::prepareGeometryChange()
       
   638 */
       
   639 void QGraphicsSceneIndex::prepareBoundingRectChange(const QGraphicsItem *item)
       
   640 {
       
   641     Q_UNUSED(item);
       
   642 }
       
   643 
       
   644 QT_END_NAMESPACE
       
   645 
       
   646 #include "moc_qgraphicssceneindex_p.cpp"
       
   647 
       
   648 #endif // QT_NO_GRAPHICSVIEW