Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qgraphicssceneindex.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5/*!
6 \class QGraphicsSceneIndex
7 \brief The QGraphicsSceneIndex class provides a base class to implement
8 a custom indexing algorithm for discovering items in QGraphicsScene.
9 \since 4.6
10 \ingroup graphicsview-api
11
12 \internal
13
14 The QGraphicsSceneIndex class provides a base class to implement
15 a custom indexing algorithm for discovering items in QGraphicsScene. You
16 need to subclass it and reimplement addItem, removeItem, estimateItems
17 and items in order to have an functional indexing.
18
19 \sa QGraphicsScene, QGraphicsView
20*/
21
22#include "qdebug.h"
23#include "qgraphicsscene.h"
29#include <QtGui/qpainterpath.h>
30
32
33namespace QtPrivate { // just to keep indentation of the following functions at the same level
34
35 static bool intersect_rect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode,
36 const QTransform &deviceTransform, const void *intersectData)
37 {
38 const QRectF sceneRect = *static_cast<const QRectF *>(intersectData);
39
40 QRectF brect = item->boundingRect();
41 _q_adjustRect(&brect);
42
43 // ### Add test for this (without making things slower?)
44 Q_UNUSED(exposeRect);
45
46 bool keep = true;
47 const QGraphicsItemPrivate *itemd = QGraphicsItemPrivate::get(item);
48 if (itemd->itemIsUntransformable()) {
49 // Untransformable items; map the scene rect to item coordinates.
50 const QTransform transform = item->deviceTransform(deviceTransform);
51 QRectF itemRect = (deviceTransform * transform.inverted()).mapRect(sceneRect);
52 if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect)
53 keep = itemRect.contains(brect) && itemRect != brect;
54 else
55 keep = itemRect.intersects(brect);
56 if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
57 QPainterPath itemPath;
58 itemPath.addRect(itemRect);
59 keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, itemPath, mode);
60 }
61 } else {
62 Q_ASSERT(!itemd->dirtySceneTransform);
63 const QRectF itemSceneBoundingRect = itemd->sceneTransformTranslateOnly
64 ? brect.translated(itemd->sceneTransform.dx(),
65 itemd->sceneTransform.dy())
66 : itemd->sceneTransform.mapRect(brect);
67 if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect)
68 keep = sceneRect != brect && sceneRect.contains(itemSceneBoundingRect);
69 else
70 keep = sceneRect.intersects(itemSceneBoundingRect);
71 if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
72 QPainterPath rectPath;
73 rectPath.addRect(sceneRect);
74 if (itemd->sceneTransformTranslateOnly)
75 rectPath.translate(-itemd->sceneTransform.dx(), -itemd->sceneTransform.dy());
76 else
77 rectPath = itemd->sceneTransform.inverted().map(rectPath);
78 keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, rectPath, mode);
79 }
80 }
81 return keep;
82 }
83
84 static bool intersect_point(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode,
85 const QTransform &deviceTransform, const void *intersectData)
86 {
87 const QPointF scenePoint = *static_cast<const QPointF *>(intersectData);
88
89 QRectF brect = item->boundingRect();
90 _q_adjustRect(&brect);
91
92 // ### Add test for this (without making things slower?)
93 Q_UNUSED(exposeRect);
94
95 bool keep = false;
96 const QGraphicsItemPrivate *itemd = QGraphicsItemPrivate::get(item);
97 if (itemd->itemIsUntransformable()) {
98 // Untransformable items; map the scene point to item coordinates.
99 const QTransform transform = item->deviceTransform(deviceTransform);
100 QPointF itemPoint = (deviceTransform * transform.inverted()).map(scenePoint);
101 keep = brect.contains(itemPoint);
102 if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
103 QPainterPath pointPath;
104 pointPath.addRect(QRectF(itemPoint, QSizeF(1, 1)));
105 keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, pointPath, mode);
106 }
107 } else {
108 Q_ASSERT(!itemd->dirtySceneTransform);
109 QRectF sceneBoundingRect = itemd->sceneTransformTranslateOnly
110 ? brect.translated(itemd->sceneTransform.dx(),
111 itemd->sceneTransform.dy())
112 : itemd->sceneTransform.mapRect(brect);
113 keep = sceneBoundingRect.intersects(QRectF(scenePoint, QSizeF(1, 1)));
114 if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
115 QPointF p = itemd->sceneTransformTranslateOnly
116 ? QPointF(scenePoint.x() - itemd->sceneTransform.dx(),
117 scenePoint.y() - itemd->sceneTransform.dy())
118 : itemd->sceneTransform.inverted().map(scenePoint);
119 keep = item->contains(p);
120 }
121 }
122
123 return keep;
124 }
125
126 static bool intersect_path(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode,
127 const QTransform &deviceTransform, const void *intersectData)
128 {
129 const QPainterPath scenePath = *static_cast<const QPainterPath *>(intersectData);
130
131 QRectF brect = item->boundingRect();
132 _q_adjustRect(&brect);
133
134 // ### Add test for this (without making things slower?)
135 Q_UNUSED(exposeRect);
136
137 bool keep = true;
138 const QGraphicsItemPrivate *itemd = QGraphicsItemPrivate::get(item);
139 if (itemd->itemIsUntransformable()) {
140 // Untransformable items; map the scene rect to item coordinates.
141 const QTransform transform = item->deviceTransform(deviceTransform);
142 QPainterPath itemPath = (deviceTransform * transform.inverted()).map(scenePath);
143 if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect)
144 keep = itemPath.contains(brect);
145 else
146 keep = itemPath.intersects(brect);
147 if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape))
148 keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, itemPath, mode);
149 } else {
150 Q_ASSERT(!itemd->dirtySceneTransform);
151 const QRectF itemSceneBoundingRect = itemd->sceneTransformTranslateOnly
152 ? brect.translated(itemd->sceneTransform.dx(),
153 itemd->sceneTransform.dy())
154 : itemd->sceneTransform.mapRect(brect);
155 if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect)
156 keep = scenePath.contains(itemSceneBoundingRect);
157 else
158 keep = scenePath.intersects(itemSceneBoundingRect);
159 if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
160 QPainterPath itemPath = itemd->sceneTransformTranslateOnly
161 ? scenePath.translated(-itemd->sceneTransform.dx(),
162 -itemd->sceneTransform.dy())
163 : itemd->sceneTransform.inverted().map(scenePath);
164 keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, itemPath, mode);
165 }
166 }
167 return keep;
168 }
169
170} // namespace QtPrivate
171
172/*!
173 \class QGraphicsSceneIndexPrivate
174 \inmodule QtWidgets
175 \internal
176
177 Constructs a private scene index.
178*/
179QGraphicsSceneIndexPrivate::QGraphicsSceneIndexPrivate(QGraphicsScene *scene) : scene(scene)
180{
181}
182
183/*!
184 Destructor of private scene index.
185*/
189
190/*!
191 \internal
192
193 Checks if item collides with the path and mode, but also checks that if it
194 doesn't collide, maybe its frame rect will.
195*/
196bool QGraphicsSceneIndexPrivate::itemCollidesWithPath(const QGraphicsItem *item,
197 const QPainterPath &path,
198 Qt::ItemSelectionMode mode)
199{
200 if (item->collidesWithPath(path, mode))
201 return true;
202 if (item->isWidget()) {
203 // Check if this is a window, and if its frame rect collides.
204 const QGraphicsWidget *widget = static_cast<const QGraphicsWidget *>(item);
205 if (widget->isWindow()) {
206 QRectF frameRect = widget->windowFrameRect();
207 QPainterPath framePath;
208 framePath.addRect(frameRect);
209 bool intersects = path.intersects(frameRect);
210 if (mode == Qt::IntersectsItemShape || mode == Qt::IntersectsItemBoundingRect)
211 return intersects || path.contains(frameRect.topLeft())
212 || framePath.contains(path.elementAt(0));
213 return !intersects && path.contains(frameRect.topLeft());
214 }
215 }
216 return false;
217}
218
219/*!
220 \internal
221 This function returns the items in ascending order.
222*/
223void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRectF exposeRect,
225 QList<QGraphicsItem *> *items,
226 const QTransform &viewTransform,
227 Qt::ItemSelectionMode mode,
228 qreal parentOpacity, const void *intersectData) const
229{
230 Q_ASSERT(item);
231 if (!item->d_ptr->visible)
232 return;
233
234 const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
235 const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
236 const bool itemHasChildren = !item->d_ptr->children.isEmpty();
237 if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity()))
238 return;
239
240 // Update the item's scene transform if dirty.
241 const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable();
242 const bool wasDirtyParentSceneTransform = item->d_ptr->dirtySceneTransform && !itemIsUntransformable;
243 if (wasDirtyParentSceneTransform) {
244 item->d_ptr->updateSceneTransformFromParent();
245 Q_ASSERT(!item->d_ptr->dirtySceneTransform);
246 }
247
248 const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
249 || item->d_ptr->flags & QGraphicsItem::ItemContainsChildrenInShape);
250 bool processItem = !itemIsFullyTransparent;
251 if (processItem) {
252 processItem = intersect(item, exposeRect, mode, viewTransform, intersectData);
253 if (!processItem && (!itemHasChildren || itemClipsChildrenToShape)) {
254 if (wasDirtyParentSceneTransform)
255 item->d_ptr->invalidateChildrenSceneTransform();
256 return;
257 }
258 } // else we know for sure this item has children we must process.
259
260 int i = 0;
261 if (itemHasChildren) {
262 // Sort children.
263 item->d_ptr->ensureSortedChildren();
264
265 // Clip to shape.
266 if (itemClipsChildrenToShape && !itemIsUntransformable) {
267 QPainterPath mappedShape = item->d_ptr->sceneTransformTranslateOnly
268 ? item->shape().translated(item->d_ptr->sceneTransform.dx(),
269 item->d_ptr->sceneTransform.dy())
270 : item->d_ptr->sceneTransform.map(item->shape());
271 exposeRect &= mappedShape.controlPointRect();
272 }
273
274 // Process children behind
275 for (i = 0; i < item->d_ptr->children.size(); ++i) {
276 QGraphicsItem *child = item->d_ptr->children.at(i);
277 if (wasDirtyParentSceneTransform)
278 child->d_ptr->dirtySceneTransform = 1;
279 if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent))
280 break;
281 if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
282 continue;
283 recursive_items_helper(child, exposeRect, intersect, items, viewTransform,
284 mode, opacity, intersectData);
285 }
286 }
287
288 // Process item
289 if (processItem)
290 items->append(item);
291
292 // Process children in front
293 if (itemHasChildren) {
294 for (; i < item->d_ptr->children.size(); ++i) {
295 QGraphicsItem *child = item->d_ptr->children.at(i);
296 if (wasDirtyParentSceneTransform)
297 child->d_ptr->dirtySceneTransform = 1;
298 if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
299 continue;
300 recursive_items_helper(child, exposeRect, intersect, items, viewTransform,
301 mode, opacity, intersectData);
302 }
303 }
304}
305
307{
308 if (!scene)
309 return;
310
311 QObject::connect(scene, SIGNAL(sceneRectChanged(QRectF)),
312 q_func(), SLOT(updateSceneRect(QRectF)));
313}
314
315/*!
316 Constructs an abstract scene index for a given \a scene.
317*/
318QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsScene *scene)
319: QObject(*new QGraphicsSceneIndexPrivate(scene), scene)
320{
321 d_func()->init();
322}
323
324/*!
325 \internal
326*/
327QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsSceneIndexPrivate &dd, QGraphicsScene *scene)
328 : QObject(dd, scene)
329{
330 d_func()->init();
331}
332
333/*!
334 Destroys the scene index.
335*/
336QGraphicsSceneIndex::~QGraphicsSceneIndex()
337{
338
339}
340
341/*!
342 Returns the scene of this index.
343*/
344QGraphicsScene* QGraphicsSceneIndex::scene() const
345{
346 Q_D(const QGraphicsSceneIndex);
347 return d->scene;
348}
349
350/*!
351 \fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPointF &pos,
352 Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform
353 &deviceTransform) const
354
355 Returns all visible items that, depending on \a mode, are at the specified
356 \a pos and return a list sorted using \a order.
357
358 The default value for \a mode is Qt::IntersectsItemShape; all items whose
359 exact shape intersects with \a pos are returned.
360
361 \a deviceTransform is the transformation apply to the view.
362
363 This method use the estimation of the index (estimateItems) and refine the
364 list to get an exact result. If you want to implement your own refinement
365 algorithm you can reimplement this method.
366
367 \sa estimateItems()
368
369*/
370QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode,
371 Qt::SortOrder order, const QTransform &deviceTransform) const
372{
373
374 Q_D(const QGraphicsSceneIndex);
375 QList<QGraphicsItem *> itemList;
376 d->items_helper(QRectF(pos, QSizeF(1, 1)), &QtPrivate::intersect_point, &itemList, deviceTransform, mode, order, &pos);
377 return itemList;
378}
379
380/*!
381 \fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QRectF &rect,
382 Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform
383 &deviceTransform) const
384
385 \overload
386
387 Returns all visible items that, depending on \a mode, are either inside or
388 intersect with the specified \a rect and return a list sorted using \a order.
389
390 The default value for \a mode is Qt::IntersectsItemShape; all items whose
391 exact shape intersects with or is contained by \a rect are returned.
392
393 \a deviceTransform is the transformation apply to the view.
394
395 This method use the estimation of the index (estimateItems) and refine
396 the list to get an exact result. If you want to implement your own
397 refinement algorithm you can reimplement this method.
398
399 \sa estimateItems()
400
401*/
402QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSelectionMode mode,
403 Qt::SortOrder order, const QTransform &deviceTransform) const
404{
405 Q_D(const QGraphicsSceneIndex);
406 QRectF exposeRect = rect;
407 _q_adjustRect(&exposeRect);
408 QList<QGraphicsItem *> itemList;
409 d->items_helper(exposeRect, &QtPrivate::intersect_rect, &itemList, deviceTransform, mode, order, &rect);
410 return itemList;
411}
412
413/*!
414 \fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPolygonF
415 &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const
416 QTransform &deviceTransform) const
417
418 \overload
419
420 Returns all visible items that, depending on \a mode, are either inside or
421 intersect with the specified \a polygon and return a list sorted using \a order.
422
423 The default value for \a mode is Qt::IntersectsItemShape; all items whose
424 exact shape intersects with or is contained by \a polygon are returned.
425
426 \a deviceTransform is the transformation apply to the view.
427
428 This method use the estimation of the index (estimateItems) and refine
429 the list to get an exact result. If you want to implement your own
430 refinement algorithm you can reimplement this method.
431
432 \sa estimateItems()
433
434*/
435QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode,
436 Qt::SortOrder order, const QTransform &deviceTransform) const
437{
438 Q_D(const QGraphicsSceneIndex);
439 QList<QGraphicsItem *> itemList;
440 QRectF exposeRect = polygon.boundingRect();
441 _q_adjustRect(&exposeRect);
442 QPainterPath path;
443 path.addPolygon(polygon);
444 d->items_helper(exposeRect, &QtPrivate::intersect_path, &itemList, deviceTransform, mode, order, &path);
445 return itemList;
446}
447
448/*!
449 \fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPainterPath
450 &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform
451 &deviceTransform) const
452
453 \overload
454
455 Returns all visible items that, depending on \a mode, are either inside or
456 intersect with the specified \a path and return a list sorted using \a order.
457
458 The default value for \a mode is Qt::IntersectsItemShape; all items whose
459 exact shape intersects with or is contained by \a path are returned.
460
461 \a deviceTransform is the transformation apply to the view.
462
463 This method use the estimation of the index (estimateItems) and refine
464 the list to get an exact result. If you want to implement your own
465 refinement algorithm you can reimplement this method.
466
467 \sa estimateItems()
468
469*/
470QList<QGraphicsItem *> QGraphicsSceneIndex::items(const QPainterPath &path, Qt::ItemSelectionMode mode,
471 Qt::SortOrder order, const QTransform &deviceTransform) const
472{
473 Q_D(const QGraphicsSceneIndex);
474 QList<QGraphicsItem *> itemList;
475 QRectF exposeRect = path.controlPointRect();
476 _q_adjustRect(&exposeRect);
477 d->items_helper(exposeRect, &QtPrivate::intersect_path, &itemList, deviceTransform, mode, order, &path);
478 return itemList;
479}
480
481/*!
482 This virtual function return an estimation of items at position \a point.
483 This method return a list sorted using \a order.
484*/
485QList<QGraphicsItem *> QGraphicsSceneIndex::estimateItems(const QPointF &point, Qt::SortOrder order) const
486{
487 return estimateItems(QRectF(point, QSize(1, 1)), order);
488}
489
490QList<QGraphicsItem *> QGraphicsSceneIndex::estimateTopLevelItems(const QRectF &rect, Qt::SortOrder order) const
491{
492 Q_D(const QGraphicsSceneIndex);
493 Q_UNUSED(rect);
494 QGraphicsScenePrivate *scened = d->scene->d_func();
495 scened->ensureSortedTopLevelItems();
496 if (order == Qt::DescendingOrder) {
497 QList<QGraphicsItem *> sorted;
498 const int numTopLevelItems = scened->topLevelItems.size();
499 sorted.reserve(numTopLevelItems);
500 for (int i = numTopLevelItems - 1; i >= 0; --i)
501 sorted << scened->topLevelItems.at(i);
502 return sorted;
503 }
504 return scened->topLevelItems;
505}
506
507/*!
508 \fn QList<QGraphicsItem *> QGraphicsSceneIndex::items(Qt::SortOrder order = Qt::DescendingOrder) const
509
510 This pure virtual function all items in the index and sort them using
511 \a order.
512*/
513
514
515/*!
516 Notifies the index that the scene's scene rect has changed. \a rect
517 is thew new scene rect.
518
519 \sa QGraphicsScene::sceneRect()
520*/
521void QGraphicsSceneIndex::updateSceneRect(const QRectF &rect)
522{
523 Q_UNUSED(rect);
524}
525
526/*!
527 This virtual function removes all items in the scene index.
528*/
529void QGraphicsSceneIndex::clear()
530{
531 const QList<QGraphicsItem *> allItems = items();
532 for (int i = 0 ; i < allItems.size(); ++i)
533 removeItem(allItems.at(i));
534}
535
536/*!
537 \fn virtual void QGraphicsSceneIndex::addItem(QGraphicsItem *item) = 0
538
539 This pure virtual function inserts an \a item to the scene index.
540
541 \sa removeItem(), deleteItem()
542*/
543
544/*!
545 \fn virtual void QGraphicsSceneIndex::removeItem(QGraphicsItem *item) = 0
546
547 This pure virtual function removes an \a item to the scene index.
548
549 \sa addItem(), deleteItem()
550*/
551
552/*!
553 This method is called when an \a item has been deleted.
554 The default implementation calls removeItem. Be careful,
555 if your implementation of removeItem use pure virtual method
556 of QGraphicsItem like boundingRect(), then you should reimplement
557 this method.
558
559 \sa addItem(), removeItem()
560*/
561void QGraphicsSceneIndex::deleteItem(QGraphicsItem *item)
562{
563 removeItem(item);
564}
565
566/*!
567 This virtual function is called by QGraphicsItem to notify the index
568 that some part of the \a item 's state changes. By reimplementing this
569 function, your can react to a change, and in some cases, (depending on \a
570 change,) adjustments in the index can be made.
571
572 \a change is the parameter of the item that is changing. \a value is the
573 value that changed; the type of the value depends on \a change.
574
575 The default implementation does nothing.
576
577 \sa QGraphicsItem::GraphicsItemChange
578*/
579void QGraphicsSceneIndex::itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const void *const value)
580{
581 Q_UNUSED(item);
582 Q_UNUSED(change);
583 Q_UNUSED(value);
584}
585
586/*!
587 Notify the index for a geometry change of an \a item.
588
589 \sa QGraphicsItem::prepareGeometryChange()
590*/
591void QGraphicsSceneIndex::prepareBoundingRectChange(const QGraphicsItem *item)
592{
593 Q_UNUSED(item);
594}
595
596QT_END_NAMESPACE
597
598#include "moc_qgraphicssceneindex_p.cpp"
void recursive_items_helper(QGraphicsItem *item, QRectF exposeRect, QGraphicsSceneIndexIntersector intersect, QList< QGraphicsItem * > *items, const QTransform &viewTransform, Qt::ItemSelectionMode mode, qreal parentOpacity, const void *intersectData) const
~QGraphicsSceneIndexPrivate()
Destructor of private scene index.
\inmodule QtCore\reentrant
Definition qpoint.h:232
Combined button and popup list for selecting options.
static bool intersect_point(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode, const QTransform &deviceTransform, const void *intersectData)
static bool intersect_rect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode, const QTransform &deviceTransform, const void *intersectData)
static bool intersect_path(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode, const QTransform &deviceTransform, const void *intersectData)
bool(* QGraphicsSceneIndexIntersector)(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode, const QTransform &deviceTransform, const void *data)