QtBase  v6.3.1
qgraphicssceneindex.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtWidgets module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
56 #include "qdebug.h"
57 #include "qgraphicsscene.h"
58 #include "qgraphicsitem_p.h"
59 #include "qgraphicsscene_p.h"
60 #include "qgraphicswidget.h"
61 #include "qgraphicssceneindex_p.h"
63 #include <QtGui/qpainterpath.h>
64 
66 
67 namespace QtPrivate { // just to keep indentation of the following functions at the same level
68 
69  static bool intersect_rect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode,
70  const QTransform &deviceTransform, const void *intersectData)
71  {
72  const QRectF sceneRect = *static_cast<const QRectF *>(intersectData);
73 
74  QRectF brect = item->boundingRect();
75  _q_adjustRect(&brect);
76 
77  // ### Add test for this (without making things slower?)
78  Q_UNUSED(exposeRect);
79 
80  bool keep = true;
82  if (itemd->itemIsUntransformable()) {
83  // Untransformable items; map the scene rect to item coordinates.
85  QRectF itemRect = (deviceTransform * transform.inverted()).mapRect(sceneRect);
87  keep = itemRect.contains(brect) && itemRect != brect;
88  else
89  keep = itemRect.intersects(brect);
90  if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
91  QPainterPath itemPath;
92  itemPath.addRect(itemRect);
94  }
95  } else {
97  const QRectF itemSceneBoundingRect = itemd->sceneTransformTranslateOnly
98  ? brect.translated(itemd->sceneTransform.dx(),
99  itemd->sceneTransform.dy())
100  : itemd->sceneTransform.mapRect(brect);
102  keep = sceneRect != brect && sceneRect.contains(itemSceneBoundingRect);
103  else
104  keep = sceneRect.intersects(itemSceneBoundingRect);
105  if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
106  QPainterPath rectPath;
107  rectPath.addRect(sceneRect);
108  if (itemd->sceneTransformTranslateOnly)
109  rectPath.translate(-itemd->sceneTransform.dx(), -itemd->sceneTransform.dy());
110  else
111  rectPath = itemd->sceneTransform.inverted().map(rectPath);
113  }
114  }
115  return keep;
116  }
117 
118  static bool intersect_point(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode,
119  const QTransform &deviceTransform, const void *intersectData)
120  {
121  const QPointF scenePoint = *static_cast<const QPointF *>(intersectData);
122 
123  QRectF brect = item->boundingRect();
124  _q_adjustRect(&brect);
125 
126  // ### Add test for this (without making things slower?)
127  Q_UNUSED(exposeRect);
128 
129  bool keep = false;
131  if (itemd->itemIsUntransformable()) {
132  // Untransformable items; map the scene point to item coordinates.
134  QPointF itemPoint = (deviceTransform * transform.inverted()).map(scenePoint);
135  keep = brect.contains(itemPoint);
136  if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
137  QPainterPath pointPath;
138  pointPath.addRect(QRectF(itemPoint, QSizeF(1, 1)));
140  }
141  } else {
142  Q_ASSERT(!itemd->dirtySceneTransform);
143  QRectF sceneBoundingRect = itemd->sceneTransformTranslateOnly
144  ? brect.translated(itemd->sceneTransform.dx(),
145  itemd->sceneTransform.dy())
146  : itemd->sceneTransform.mapRect(brect);
147  keep = sceneBoundingRect.intersects(QRectF(scenePoint, QSizeF(1, 1)));
148  if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
150  ? QPointF(scenePoint.x() - itemd->sceneTransform.dx(),
151  scenePoint.y() - itemd->sceneTransform.dy())
152  : itemd->sceneTransform.inverted().map(scenePoint);
153  keep = item->contains(p);
154  }
155  }
156 
157  return keep;
158  }
159 
160  static bool intersect_path(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode,
161  const QTransform &deviceTransform, const void *intersectData)
162  {
163  const QPainterPath scenePath = *static_cast<const QPainterPath *>(intersectData);
164 
165  QRectF brect = item->boundingRect();
166  _q_adjustRect(&brect);
167 
168  // ### Add test for this (without making things slower?)
169  Q_UNUSED(exposeRect);
170 
171  bool keep = true;
173  if (itemd->itemIsUntransformable()) {
174  // Untransformable items; map the scene rect to item coordinates.
176  QPainterPath itemPath = (deviceTransform * transform.inverted()).map(scenePath);
178  keep = itemPath.contains(brect);
179  else
180  keep = itemPath.intersects(brect);
183  } else {
184  Q_ASSERT(!itemd->dirtySceneTransform);
185  const QRectF itemSceneBoundingRect = itemd->sceneTransformTranslateOnly
186  ? brect.translated(itemd->sceneTransform.dx(),
187  itemd->sceneTransform.dy())
188  : itemd->sceneTransform.mapRect(brect);
190  keep = scenePath.contains(itemSceneBoundingRect);
191  else
192  keep = scenePath.intersects(itemSceneBoundingRect);
193  if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
194  QPainterPath itemPath = itemd->sceneTransformTranslateOnly
195  ? scenePath.translated(-itemd->sceneTransform.dx(),
196  -itemd->sceneTransform.dy())
197  : itemd->sceneTransform.inverted().map(scenePath);
199  }
200  }
201  return keep;
202  }
203 
204 } // namespace QtPrivate
205 
210 {
211 }
212 
217 {
218 }
219 
227  const QPainterPath &path,
229 {
231  return true;
232  if (item->isWidget()) {
233  // Check if this is a window, and if its frame rect collides.
234  const QGraphicsWidget *widget = static_cast<const QGraphicsWidget *>(item);
235  if (widget->isWindow()) {
236  QRectF frameRect = widget->windowFrameRect();
237  QPainterPath framePath;
238  framePath.addRect(frameRect);
239  bool intersects = path.intersects(frameRect);
241  return intersects || path.contains(frameRect.topLeft())
242  || framePath.contains(path.elementAt(0));
243  return !intersects && path.contains(frameRect.topLeft());
244  }
245  }
246  return false;
247 }
248 
256  const QTransform &viewTransform,
258  qreal parentOpacity, const void *intersectData) const
259 {
260  Q_ASSERT(item);
261  if (!item->d_ptr->visible)
262  return;
263 
264  const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
265  const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
266  const bool itemHasChildren = !item->d_ptr->children.isEmpty();
267  if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity()))
268  return;
269 
270  // Update the item's scene transform if dirty.
271  const bool itemIsUntransformable = item->d_ptr->itemIsUntransformable();
272  const bool wasDirtyParentSceneTransform = item->d_ptr->dirtySceneTransform && !itemIsUntransformable;
273  if (wasDirtyParentSceneTransform) {
276  }
277 
278  const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape
280  bool processItem = !itemIsFullyTransparent;
281  if (processItem) {
282  processItem = intersect(item, exposeRect, mode, viewTransform, intersectData);
283  if (!processItem && (!itemHasChildren || itemClipsChildrenToShape)) {
284  if (wasDirtyParentSceneTransform)
286  return;
287  }
288  } // else we know for sure this item has children we must process.
289 
290  int i = 0;
291  if (itemHasChildren) {
292  // Sort children.
294 
295  // Clip to shape.
296  if (itemClipsChildrenToShape && !itemIsUntransformable) {
301  exposeRect &= mappedShape.controlPointRect();
302  }
303 
304  // Process children behind
305  for (i = 0; i < item->d_ptr->children.size(); ++i) {
307  if (wasDirtyParentSceneTransform)
308  child->d_ptr->dirtySceneTransform = 1;
309  if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent))
310  break;
311  if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
312  continue;
313  recursive_items_helper(child, exposeRect, intersect, items, viewTransform,
314  mode, opacity, intersectData);
315  }
316  }
317 
318  // Process item
319  if (processItem)
320  items->append(item);
321 
322  // Process children in front
323  if (itemHasChildren) {
324  for (; i < item->d_ptr->children.size(); ++i) {
326  if (wasDirtyParentSceneTransform)
327  child->d_ptr->dirtySceneTransform = 1;
328  if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
329  continue;
330  recursive_items_helper(child, exposeRect, intersect, items, viewTransform,
331  mode, opacity, intersectData);
332  }
333  }
334 }
335 
337 {
338  if (!scene)
339  return;
340 
341  QObject::connect(scene, SIGNAL(sceneRectChanged(QRectF)),
342  q_func(), SLOT(updateSceneRect(QRectF)));
343 }
344 
350 {
351  d_func()->init();
352 }
353 
358  : QObject(dd, scene)
359 {
360  d_func()->init();
361 }
362 
367 {
368 
369 }
370 
375 {
376  Q_D(const QGraphicsSceneIndex);
377  return d->scene;
378 }
379 
402 {
403 
404  Q_D(const QGraphicsSceneIndex);
405  QList<QGraphicsItem *> itemList;
406  d->items_helper(QRectF(pos, QSizeF(1, 1)), &QtPrivate::intersect_point, &itemList, deviceTransform, mode, order, &pos);
407  return itemList;
408 }
409 
434 {
435  Q_D(const QGraphicsSceneIndex);
436  QRectF exposeRect = rect;
437  _q_adjustRect(&exposeRect);
438  QList<QGraphicsItem *> itemList;
439  d->items_helper(exposeRect, &QtPrivate::intersect_rect, &itemList, deviceTransform, mode, order, &rect);
440  return itemList;
441 }
442 
467 {
468  Q_D(const QGraphicsSceneIndex);
469  QList<QGraphicsItem *> itemList;
470  QRectF exposeRect = polygon.boundingRect();
471  _q_adjustRect(&exposeRect);
473  path.addPolygon(polygon);
474  d->items_helper(exposeRect, &QtPrivate::intersect_path, &itemList, deviceTransform, mode, order, &path);
475  return itemList;
476 }
477 
502 {
503  Q_D(const QGraphicsSceneIndex);
504  QList<QGraphicsItem *> itemList;
505  QRectF exposeRect = path.controlPointRect();
506  _q_adjustRect(&exposeRect);
507  d->items_helper(exposeRect, &QtPrivate::intersect_path, &itemList, deviceTransform, mode, order, &path);
508  return itemList;
509 }
510 
516 {
517  return estimateItems(QRectF(point, QSize(1, 1)), order);
518 }
519 
521 {
522  Q_D(const QGraphicsSceneIndex);
523  Q_UNUSED(rect);
524  QGraphicsScenePrivate *scened = d->scene->d_func();
525  scened->ensureSortedTopLevelItems();
526  if (order == Qt::DescendingOrder) {
528  const int numTopLevelItems = scened->topLevelItems.size();
529  sorted.reserve(numTopLevelItems);
530  for (int i = numTopLevelItems - 1; i >= 0; --i)
531  sorted << scened->topLevelItems.at(i);
532  return sorted;
533  }
534  return scened->topLevelItems;
535 }
536 
552 {
553  Q_UNUSED(rect);
554 }
555 
560 {
561  const QList<QGraphicsItem *> allItems = items();
562  for (int i = 0 ; i < allItems.size(); ++i)
563  removeItem(allItems.at(i));
564 }
565 
592 {
593  removeItem(item);
594 }
595 
610 {
611  Q_UNUSED(item);
612  Q_UNUSED(change);
613  Q_UNUSED(value);
614 }
615 
622 {
623  Q_UNUSED(item);
624 }
625 
627 
628 #include "moc_qgraphicssceneindex_p.cpp"
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
The QGraphicsItem class is the base class for all graphical items in a QGraphicsScene.
Definition: qgraphicsitem.h:83
virtual bool contains(const QPointF &point) const
QTransform deviceTransform(const QTransform &viewportTransform) const
bool isWidget() const
QScopedPointer< QGraphicsItemPrivate > d_ptr
virtual QPainterPath shape() const
@ ItemClipsChildrenToShape
Definition: qgraphicsitem.h:90
@ ItemContainsChildrenInShape
@ ItemIgnoresParentOpacity
Definition: qgraphicsitem.h:92
virtual QRectF boundingRect() const =0
virtual bool collidesWithPath(const QPainterPath &path, Qt::ItemSelectionMode mode=Qt::IntersectsItemShape) const
bool isOpacityNull() const
void invalidateChildrenSceneTransform()
bool itemIsUntransformable() const
static const QGraphicsItemPrivate * get(const QGraphicsItem *item)
bool childrenCombineOpacity() const
QList< QGraphicsItem * > children
quint32 sceneTransformTranslateOnly
virtual void updateSceneTransformFromParent()
qreal combineOpacityFromParent(qreal parentOpacity) const
The QGraphicsScene class provides a surface for managing a large number of 2D graphical items.
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
virtual void updateSceneRect(const QRectF &rect)
QGraphicsSceneIndex(QGraphicsScene *scene=nullptr)
virtual void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const void *const value)
virtual void prepareBoundingRectChange(const QGraphicsItem *item)
virtual void deleteItem(QGraphicsItem *item)
virtual QList< QGraphicsItem * > estimateItems(const QPointF &point, Qt::SortOrder order) const
QGraphicsScene * scene() const
virtual void removeItem(QGraphicsItem *item)=0
QGraphicsSceneIndexPrivate(QGraphicsScene *scene)
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
QList< QGraphicsItem * > topLevelItems
The QGraphicsWidget class is the base class for all widget items in a QGraphicsScene.
qsizetype size() const noexcept
Definition: qlist.h:414
bool isEmpty() const noexcept
Definition: qlist.h:418
const_reference at(qsizetype i) const noexcept
Definition: qlist.h:457
void append(parameter_type t)
Definition: qlist.h:469
The QObject class is the base class of all Qt objects.
Definition: qobject.h:125
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Definition: qobject.cpp:2772
The QPainterPath class provides a container for painting operations, enabling graphical shapes to be ...
Definition: qpainterpath.h:65
QPainterPath translated(qreal dx, qreal dy) const
void translate(qreal dx, qreal dy)
void addRect(const QRectF &rect)
QRectF controlPointRect() const
bool intersects(const QRectF &rect) const
bool contains(const QPointF &pt) const
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:242
constexpr qreal x() const noexcept
Definition: qpoint.h:361
constexpr qreal y() const noexcept
Definition: qpoint.h:366
The QPolygonF class provides a list of points using floating point precision. \inmodule QtGui.
Definition: qpolygon.h:128
The QRectF class defines a finite rectangle in the plane using floating point precision.
Definition: qrect.h:511
constexpr QRectF translated(qreal dx, qreal dy) const noexcept
Definition: qrect.h:771
bool contains(const QRectF &r) const noexcept
Definition: qrect.cpp:2006
bool intersects(const QRectF &r) const noexcept
Definition: qrect.cpp:2284
constexpr QPointF topLeft() const noexcept
Definition: qrect.h:538
The QSizeF class defines the size of a two-dimensional object using floating point precision.
Definition: qsize.h:235
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:55
The QTransform class specifies 2D transformations of a coordinate system.
Definition: qtransform.h:56
qreal dx() const
Definition: qtransform.h:262
QPoint map(const QPoint &p) const
QTransform inverted(bool *invertible=nullptr) const
Definition: qtransform.cpp:339
QRect mapRect(const QRect &) const
qreal dy() const
Definition: qtransform.h:266
bool isWindow() const
Definition: qwidget.h:844
QOpenGLWidget * widget
[1]
QMap< QString, QString > map
[6]
rect
[4]
SortOrder
Definition: qnamespace.h:146
@ DescendingOrder
Definition: qnamespace.h:148
ItemSelectionMode
Definition: qnamespace.h:1337
@ IntersectsItemShape
Definition: qnamespace.h:1339
@ ContainsItemShape
Definition: qnamespace.h:1338
@ IntersectsItemBoundingRect
Definition: qnamespace.h:1341
@ ContainsItemBoundingRect
Definition: qnamespace.h:1340
EGLOutputLayerEXT EGLint EGLAttrib value
QT_END_INCLUDE_NAMESPACE typedef double qreal
Definition: qglobal.h:341
bool(* QGraphicsSceneIndexIntersector)(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode, const QTransform &deviceTransform, const void *data)
#define SLOT(a)
Definition: qobjectdefs.h:87
#define SIGNAL(a)
Definition: qobjectdefs.h:88
GLenum mode
GLuint GLenum GLenum transform
Definition: qopenglext.h:11564
GLsizei const GLchar *const * path
Definition: qopenglext.h:4283
GLfloat GLfloat p
[1]
Definition: qopenglext.h:12698
GLfixed GLfixed GLint GLint order
Definition: qopenglext.h:5206
#define Q_ASSERT(cond)
Definition: qrandom.cpp:84
Q_UNUSED(salary)
[21]
QGraphicsScene scene
[0]
rect sceneTransform().map(QPointF(0
QGraphicsItem * item
rect deviceTransform(view->viewportTransform()).map(QPointF(0
QList< QTreeWidgetItem * > items
QLayoutItem * child
[0]
C sorted(C c)