Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
20#include "qdebug.h"
21#include "qgraphicsscene.h"
22#include "qgraphicsitem_p.h"
23#include "qgraphicsscene_p.h"
24#include "qgraphicswidget.h"
27#include <QtGui/qpainterpath.h>
28
30
31namespace QtPrivate { // just to keep indentation of the following functions at the same level
32
33 static bool intersect_rect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode,
34 const QTransform &deviceTransform, const void *intersectData)
35 {
36 const QRectF sceneRect = *static_cast<const QRectF *>(intersectData);
37
38 QRectF brect = item->boundingRect();
39 _q_adjustRect(&brect);
40
41 // ### Add test for this (without making things slower?)
42 Q_UNUSED(exposeRect);
43
44 bool keep = true;
46 if (itemd->itemIsUntransformable()) {
47 // Untransformable items; map the scene rect to item coordinates.
49 QRectF itemRect = (deviceTransform * transform.inverted()).mapRect(sceneRect);
51 keep = itemRect.contains(brect) && itemRect != brect;
52 else
53 keep = itemRect.intersects(brect);
55 QPainterPath itemPath;
56 itemPath.addRect(itemRect);
58 }
59 } else {
60 Q_ASSERT(!itemd->dirtySceneTransform);
61 const QRectF itemSceneBoundingRect = itemd->sceneTransformTranslateOnly
62 ? brect.translated(itemd->sceneTransform.dx(),
63 itemd->sceneTransform.dy())
64 : itemd->sceneTransform.mapRect(brect);
66 keep = sceneRect != brect && sceneRect.contains(itemSceneBoundingRect);
67 else
68 keep = sceneRect.intersects(itemSceneBoundingRect);
70 QPainterPath rectPath;
71 rectPath.addRect(sceneRect);
72 if (itemd->sceneTransformTranslateOnly)
73 rectPath.translate(-itemd->sceneTransform.dx(), -itemd->sceneTransform.dy());
74 else
75 rectPath = itemd->sceneTransform.inverted().map(rectPath);
77 }
78 }
79 return keep;
80 }
81
82 static bool intersect_point(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode,
83 const QTransform &deviceTransform, const void *intersectData)
84 {
85 const QPointF scenePoint = *static_cast<const QPointF *>(intersectData);
86
87 QRectF brect = item->boundingRect();
88 _q_adjustRect(&brect);
89
90 // ### Add test for this (without making things slower?)
91 Q_UNUSED(exposeRect);
92
93 bool keep = false;
95 if (itemd->itemIsUntransformable()) {
96 // Untransformable items; map the scene point to item coordinates.
98 QPointF itemPoint = (deviceTransform * transform.inverted()).map(scenePoint);
99 keep = brect.contains(itemPoint);
101 QPainterPath pointPath;
102 pointPath.addRect(QRectF(itemPoint, QSizeF(1, 1)));
104 }
105 } else {
106 Q_ASSERT(!itemd->dirtySceneTransform);
107 QRectF sceneBoundingRect = itemd->sceneTransformTranslateOnly
108 ? brect.translated(itemd->sceneTransform.dx(),
109 itemd->sceneTransform.dy())
110 : itemd->sceneTransform.mapRect(brect);
111 keep = sceneBoundingRect.intersects(QRectF(scenePoint, QSizeF(1, 1)));
113 QPointF p = itemd->sceneTransformTranslateOnly
114 ? QPointF(scenePoint.x() - itemd->sceneTransform.dx(),
115 scenePoint.y() - itemd->sceneTransform.dy())
116 : itemd->sceneTransform.inverted().map(scenePoint);
117 keep = item->contains(p);
118 }
119 }
120
121 return keep;
122 }
123
124 static bool intersect_path(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode,
125 const QTransform &deviceTransform, const void *intersectData)
126 {
127 const QPainterPath scenePath = *static_cast<const QPainterPath *>(intersectData);
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 = true;
137 if (itemd->itemIsUntransformable()) {
138 // Untransformable items; map the scene rect to item coordinates.
140 QPainterPath itemPath = (deviceTransform * transform.inverted()).map(scenePath);
142 keep = itemPath.contains(brect);
143 else
144 keep = itemPath.intersects(brect);
147 } else {
148 Q_ASSERT(!itemd->dirtySceneTransform);
149 const QRectF itemSceneBoundingRect = itemd->sceneTransformTranslateOnly
150 ? brect.translated(itemd->sceneTransform.dx(),
151 itemd->sceneTransform.dy())
152 : itemd->sceneTransform.mapRect(brect);
154 keep = scenePath.contains(itemSceneBoundingRect);
155 else
156 keep = scenePath.intersects(itemSceneBoundingRect);
158 QPainterPath itemPath = itemd->sceneTransformTranslateOnly
159 ? scenePath.translated(-itemd->sceneTransform.dx(),
160 -itemd->sceneTransform.dy())
161 : itemd->sceneTransform.inverted().map(scenePath);
163 }
164 }
165 return keep;
166 }
167
168} // namespace QtPrivate
169
176
183
191 const QPainterPath &path,
193{
195 return true;
196 if (item->isWidget()) {
197 // Check if this is a window, and if its frame rect collides.
198 const QGraphicsWidget *widget = static_cast<const QGraphicsWidget *>(item);
199 if (widget->isWindow()) {
200 QRectF frameRect = widget->windowFrameRect();
201 QPainterPath framePath;
202 framePath.addRect(frameRect);
203 bool intersects = path.intersects(frameRect);
205 return intersects || path.contains(frameRect.topLeft())
206 || framePath.contains(path.elementAt(0));
207 return !intersects && path.contains(frameRect.topLeft());
208 }
209 }
210 return false;
211}
212
219 QList<QGraphicsItem *> *items,
220 const QTransform &viewTransform,
222 qreal parentOpacity, const void *intersectData) const
223{
224 Q_ASSERT(item);
225 if (!item->d_ptr->visible)
226 return;
227
228 const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
229 const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
230 const bool itemHasChildren = !item->d_ptr->children.isEmpty();
231 if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity()))
232 return;
233
234 // Update the item's scene transform if dirty.
235 const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable();
236 const bool wasDirtyParentSceneTransform = item->d_ptr->dirtySceneTransform && !itemIsUntransformable;
237 if (wasDirtyParentSceneTransform) {
240 }
241
242 const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
244 bool processItem = !itemIsFullyTransparent;
245 if (processItem) {
246 processItem = intersect(item, exposeRect, mode, viewTransform, intersectData);
247 if (!processItem && (!itemHasChildren || itemClipsChildrenToShape)) {
248 if (wasDirtyParentSceneTransform)
250 return;
251 }
252 } // else we know for sure this item has children we must process.
253
254 int i = 0;
255 if (itemHasChildren) {
256 // Sort children.
258
259 // Clip to shape.
260 if (itemClipsChildrenToShape && !itemIsUntransformable) {
262 ? item->shape().translated(item->d_ptr->sceneTransform.dx(),
265 exposeRect &= mappedShape.controlPointRect();
266 }
267
268 // Process children behind
269 for (i = 0; i < item->d_ptr->children.size(); ++i) {
271 if (wasDirtyParentSceneTransform)
272 child->d_ptr->dirtySceneTransform = 1;
273 if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent))
274 break;
275 if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
276 continue;
277 recursive_items_helper(child, exposeRect, intersect, items, viewTransform,
278 mode, opacity, intersectData);
279 }
280 }
281
282 // Process item
283 if (processItem)
284 items->append(item);
285
286 // Process children in front
287 if (itemHasChildren) {
288 for (; i < item->d_ptr->children.size(); ++i) {
290 if (wasDirtyParentSceneTransform)
291 child->d_ptr->dirtySceneTransform = 1;
292 if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
293 continue;
294 recursive_items_helper(child, exposeRect, intersect, items, viewTransform,
295 mode, opacity, intersectData);
296 }
297 }
298}
299
301{
302 if (!scene)
303 return;
304
305 QObject::connect(scene, SIGNAL(sceneRectChanged(QRectF)),
306 q_func(), SLOT(updateSceneRect(QRectF)));
307}
308
317
326
334
339{
340 Q_D(const QGraphicsSceneIndex);
341 return d->scene;
342}
343
366{
367
368 Q_D(const QGraphicsSceneIndex);
369 QList<QGraphicsItem *> itemList;
370 d->items_helper(QRectF(pos, QSizeF(1, 1)), &QtPrivate::intersect_point, &itemList, deviceTransform, mode, order, &pos);
371 return itemList;
372}
373
398{
399 Q_D(const QGraphicsSceneIndex);
400 QRectF exposeRect = rect;
401 _q_adjustRect(&exposeRect);
402 QList<QGraphicsItem *> itemList;
403 d->items_helper(exposeRect, &QtPrivate::intersect_rect, &itemList, deviceTransform, mode, order, &rect);
404 return itemList;
405}
406
431{
432 Q_D(const QGraphicsSceneIndex);
433 QList<QGraphicsItem *> itemList;
434 QRectF exposeRect = polygon.boundingRect();
435 _q_adjustRect(&exposeRect);
437 path.addPolygon(polygon);
438 d->items_helper(exposeRect, &QtPrivate::intersect_path, &itemList, deviceTransform, mode, order, &path);
439 return itemList;
440}
441
466{
467 Q_D(const QGraphicsSceneIndex);
468 QList<QGraphicsItem *> itemList;
469 QRectF exposeRect = path.controlPointRect();
470 _q_adjustRect(&exposeRect);
471 d->items_helper(exposeRect, &QtPrivate::intersect_path, &itemList, deviceTransform, mode, order, &path);
472 return itemList;
473}
474
479QList<QGraphicsItem *> QGraphicsSceneIndex::estimateItems(const QPointF &point, Qt::SortOrder order) const
480{
481 return estimateItems(QRectF(point, QSize(1, 1)), order);
482}
483
485{
486 Q_D(const QGraphicsSceneIndex);
487 Q_UNUSED(rect);
488 QGraphicsScenePrivate *scened = d->scene->d_func();
490 if (order == Qt::DescendingOrder) {
491 QList<QGraphicsItem *> sorted;
492 const int numTopLevelItems = scened->topLevelItems.size();
493 sorted.reserve(numTopLevelItems);
494 for (int i = numTopLevelItems - 1; i >= 0; --i)
495 sorted << scened->topLevelItems.at(i);
496 return sorted;
497 }
498 return scened->topLevelItems;
499}
500
519
524{
525 const QList<QGraphicsItem *> allItems = items();
526 for (int i = 0 ; i < allItems.size(); ++i)
527 removeItem(allItems.at(i));
528}
529
559
574{
575 Q_UNUSED(item);
576 Q_UNUSED(change);
578}
579
589
591
592#include "moc_qgraphicssceneindex_p.cpp"
void invalidateChildrenSceneTransform()
bool itemIsUntransformable() const
bool childrenCombineOpacity() const
QList< QGraphicsItem * > children
virtual void updateSceneTransformFromParent()
static const QGraphicsItemPrivate * get(const QGraphicsItem *item)
qreal combineOpacityFromParent(qreal parentOpacity) const
The QGraphicsItem class is the base class for all graphical items in a QGraphicsScene.
virtual bool contains(const QPointF &point) const
Returns true if this item contains point, which is in local coordinates; otherwise,...
QTransform deviceTransform(const QTransform &viewportTransform) const
bool isWidget() const
GraphicsItemChange
This enum describes the state changes that are notified by QGraphicsItem::itemChange().
QScopedPointer< QGraphicsItemPrivate > d_ptr
virtual QPainterPath shape() const
Returns the shape of this item as a QPainterPath in local coordinates.
@ ItemContainsChildrenInShape
virtual QRectF boundingRect() const =0
This pure virtual function defines the outer bounds of the item as a rectangle; all painting must be ...
virtual bool collidesWithPath(const QPainterPath &path, Qt::ItemSelectionMode mode=Qt::IntersectsItemShape) const
Returns true if this item collides with path.
QGraphicsSceneIndexPrivate(QGraphicsScene *scene)
Constructs a private scene index.
static bool itemCollidesWithPath(const QGraphicsItem *item, const QPainterPath &path, Qt::ItemSelectionMode mode)
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.
The QGraphicsSceneIndex class provides a base class to implement a custom indexing algorithm for disc...
virtual QList< QGraphicsItem * > estimateTopLevelItems(const QRectF &, Qt::SortOrder order) const
virtual QList< QGraphicsItem * > items(Qt::SortOrder order=Qt::DescendingOrder) const =0
This pure virtual function all items in the index and sort them using order.
virtual void updateSceneRect(const QRectF &rect)
Notifies the index that the scene's scene rect has changed.
QGraphicsSceneIndex(QGraphicsScene *scene=nullptr)
Constructs an abstract scene index for a given scene.
virtual ~QGraphicsSceneIndex()
Destroys the scene index.
virtual void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const void *const value)
This virtual function is called by QGraphicsItem to notify the index that some part of the item 's st...
virtual void clear()
This virtual function removes all items in the scene index.
virtual void prepareBoundingRectChange(const QGraphicsItem *item)
Notify the index for a geometry change of an item.
virtual void deleteItem(QGraphicsItem *item)
This method is called when an item has been deleted.
virtual QList< QGraphicsItem * > estimateItems(const QPointF &point, Qt::SortOrder order) const
This virtual function return an estimation of items at position point.
QGraphicsScene * scene() const
Returns the scene of this index.
virtual void removeItem(QGraphicsItem *item)=0
This pure virtual function removes an item to the scene index.
The QGraphicsScene class provides a surface for managing a large number of 2D graphical items.
The QGraphicsWidget class is the base class for all widget items in a QGraphicsScene.
qsizetype size() const noexcept
Definition qlist.h:397
bool isEmpty() const noexcept
Definition qlist.h:401
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
void append(parameter_type t)
Definition qlist.h:458
bool contains(const Key &key) const
Definition qmap.h:341
\inmodule QtCore
Definition qobject.h:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
\inmodule QtGui
QPainterPath translated(qreal dx, qreal dy) const
Returns a copy of the path that is translated by ({dx}, {dy}).
void addRect(const QRectF &rect)
Adds the given rectangle to this path as a closed subpath.
\inmodule QtCore\reentrant
Definition qpoint.h:217
The QPolygonF class provides a list of points using floating point precision.
Definition qpolygon.h:96
\inmodule QtCore\reentrant
Definition qrect.h:484
constexpr QRectF translated(qreal dx, qreal dy) const noexcept
Returns a copy of the rectangle that is translated dx along the x axis and dy along the y axis,...
Definition qrect.h:762
bool contains(const QRectF &r) const noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qrect.cpp:1993
bool intersects(const QRectF &r) const noexcept
Returns true if this rectangle intersects with the given rectangle (i.e.
Definition qrect.cpp:2271
constexpr QPointF topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
Definition qrect.h:511
\inmodule QtCore
Definition qsize.h:208
\inmodule QtCore
Definition qsize.h:25
The QTransform class specifies 2D transformations of a coordinate system.
Definition qtransform.h:20
qreal dx() const
Returns the horizontal translation factor.
Definition qtransform.h:235
QPoint map(const QPoint &p) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
qreal dy() const
Returns the vertical translation factor.
Definition qtransform.h:239
bool isWindow() const
Returns true if the widget is an independent window, otherwise returns false.
Definition qwidget.h:811
QOpenGLWidget * widget
[1]
QMap< QString, QString > map
[6]
rect
[4]
Combined button and popup list for selecting options.
\macro QT_NO_KEYWORDS >
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)
SortOrder
Definition qnamespace.h:121
@ DescendingOrder
Definition qnamespace.h:123
ItemSelectionMode
@ IntersectsItemShape
@ ContainsItemShape
@ IntersectsItemBoundingRect
@ ContainsItemBoundingRect
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
static QT_BEGIN_NAMESPACE void _q_adjustRect(QRect *rect)
bool(* QGraphicsSceneIndexIntersector)(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode, const QTransform &deviceTransform, const void *data)
#define SLOT(a)
Definition qobjectdefs.h:52
#define SIGNAL(a)
Definition qobjectdefs.h:53
GLenum mode
GLuint GLenum GLenum transform
GLsizei const GLchar *const * path
GLfloat GLfloat p
[1]
GLfixed GLfixed GLint GLint order
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_UNUSED(x)
double qreal
Definition qtypes.h:187
QGraphicsScene scene
[0]
QGraphicsItem * item
rect deviceTransform(view->viewportTransform()).map(QPointF(0
QList< QTreeWidgetItem * > items
QLayoutItem * child
[0]