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
4#ifndef QGRAPHICSITEM_P_H
5#define QGRAPHICSITEM_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists for the convenience
12// of other Qt classes. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtWidgets/private/qtwidgetsglobal_p.h>
19#include "qgraphicsitem.h"
20#include "qset.h"
21#include "qpixmapcache.h"
22#include <private/qgraphicsview_p.h>
23#include "qgraphicstransform.h"
24#include <private/qgraphicstransform_p.h>
25
26#include <QtCore/qpoint.h>
27
28QT_REQUIRE_CONFIG(graphicsview);
29
30QT_BEGIN_NAMESPACE
31
32class QGraphicsItemPrivate;
33
34class QGraphicsItemCache
35{
36public:
37 QGraphicsItemCache() : allExposed(false) { }
38
39 // ItemCoordinateCache only
40 QRect boundingRect;
41 QSize fixedSize;
42 QPixmapCache::Key key;
43
44 // DeviceCoordinateCache only
45 struct DeviceData {
46 DeviceData() {}
47 QTransform lastTransform;
48 QPoint cacheIndent;
49 QPixmapCache::Key key;
50 };
51 QHash<QPaintDevice *, DeviceData> deviceData;
52
53 // List of logical exposed rects
54 QList<QRectF> exposed;
55 bool allExposed;
56
57 // Empty cache
58 void purge();
59};
60
61class Q_WIDGETS_EXPORT QGraphicsItemPrivate
62{
63 Q_DECLARE_PUBLIC(QGraphicsItem)
64public:
65 enum Extra {
66 ExtraToolTip,
67 ExtraCursor,
68 ExtraCacheData,
69 ExtraMaxDeviceCoordCacheSize,
70 ExtraBoundingRegionGranularity
71 };
72
73 enum AncestorFlag {
74 NoFlag = 0,
75 AncestorHandlesChildEvents = 0x1,
76 AncestorClipsChildren = 0x2,
77 AncestorIgnoresTransformations = 0x4,
78 AncestorFiltersChildEvents = 0x8,
79 AncestorContainsChildren = 0x10
80 };
81
82 QGraphicsItemPrivate();
83 virtual ~QGraphicsItemPrivate();
84
85 static const QGraphicsItemPrivate *get(const QGraphicsItem *item)
86 {
87 return item->d_ptr.data();
88 }
89 static QGraphicsItemPrivate *get(QGraphicsItem *item)
90 {
91 return item->d_ptr.data();
92 }
93
94 void updateChildWithGraphicsEffectFlagRecursively();
95 void updateAncestorFlag(QGraphicsItem::GraphicsItemFlag childFlag,
96 AncestorFlag flag = NoFlag, bool enabled = false, bool root = true);
97 void updateAncestorFlags();
98 void setIsMemberOfGroup(bool enabled);
99 void remapItemPos(QEvent *event, QGraphicsItem *item);
100 QTransform genericMapFromSceneTransform(const QWidget *viewport = nullptr) const;
101 QPointF genericMapFromScene(const QPointF &pos, const QWidget *viewport) const;
102 inline bool itemIsUntransformable() const
103 {
104 return (flags & QGraphicsItem::ItemIgnoresTransformations)
105 || (ancestorFlags & AncestorIgnoresTransformations);
106 }
107
108 void combineTransformToParent(QTransform *x, const QTransform *viewTransform = nullptr) const;
109 void combineTransformFromParent(QTransform *x, const QTransform *viewTransform = nullptr) const;
110 virtual void updateSceneTransformFromParent();
111
112 static bool movableAncestorIsSelected(const QGraphicsItem *item);
113
114 virtual void setPosHelper(const QPointF &pos);
115 void setTransformHelper(const QTransform &transform);
116 void prependGraphicsTransform(QGraphicsTransform *t);
117 void appendGraphicsTransform(QGraphicsTransform *t);
118 void setVisibleHelper(bool newVisible, bool explicitly, bool update = true,
119 bool hiddenByPanel = false);
120 void setEnabledHelper(bool newEnabled, bool explicitly, bool update = true);
121 bool discardUpdateRequest(bool ignoreVisibleBit = false,
122 bool ignoreDirtyBit = false, bool ignoreOpacity = false) const;
123 virtual void transformChanged() {}
124 int depth() const;
125#if QT_CONFIG(graphicseffect)
126 enum InvalidateReason {
127 OpacityChanged
128 };
129 void invalidateParentGraphicsEffectsRecursively();
130 void invalidateChildGraphicsEffectsRecursively(InvalidateReason reason);
131#endif // QT_CONFIG(graphicseffect)
132 void invalidateDepthRecursively();
133 void resolveDepth();
134 void addChild(QGraphicsItem *child);
135 void removeChild(QGraphicsItem *child);
136 void setParentItemHelper(QGraphicsItem *parent, const QVariant *newParentVariant,
137 const QVariant *thisPointerVariant);
138 void childrenBoundingRectHelper(QTransform *x, QRectF *rect, QGraphicsItem *topMostEffectItem);
139 void initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform,
140 const QRegion &exposedRegion, bool allItems = false) const;
141 QRectF effectiveBoundingRect(QGraphicsItem *topMostEffectItem = nullptr) const;
142 QRectF sceneEffectiveBoundingRect() const;
143
144 QRectF effectiveBoundingRect(const QRectF &rect) const;
145
146 virtual void resolveFont(uint inheritedMask)
147 {
148 for (int i = 0; i < children.size(); ++i)
149 children.at(i)->d_ptr->resolveFont(inheritedMask);
150 }
151
152 virtual void resolvePalette(uint inheritedMask)
153 {
154 for (int i = 0; i < children.size(); ++i)
155 children.at(i)->d_ptr->resolvePalette(inheritedMask);
156 }
157
158 virtual bool isProxyWidget() const;
159
160 inline QVariant extra(Extra type) const
161 {
162 for (int i = 0; i < extras.size(); ++i) {
163 const ExtraStruct &extra = extras.at(i);
164 if (extra.type == type)
165 return extra.value;
166 }
167 return QVariant();
168 }
169
170 inline void setExtra(Extra type, const QVariant &value)
171 {
172 int index = -1;
173 for (int i = 0; i < extras.size(); ++i) {
174 if (extras.at(i).type == type) {
175 index = i;
176 break;
177 }
178 }
179
180 if (index == -1) {
181 extras << ExtraStruct(type, value);
182 } else {
183 extras[index].value = value;
184 }
185 }
186
187 inline void unsetExtra(Extra type)
188 {
189 for (int i = 0; i < extras.size(); ++i) {
190 if (extras.at(i).type == type) {
191 extras.removeAt(i);
192 return;
193 }
194 }
195 }
196
197 struct ExtraStruct {
198 ExtraStruct() { } // for QList, don't use
199 ExtraStruct(Extra type, const QVariant &value)
200 : type(type), value(value)
201 { }
202
203 Extra type;
204 QVariant value;
205
206 bool operator<(Extra extra) const
207 { return type < extra; }
208 };
209
210 QList<ExtraStruct> extras;
211
212 QGraphicsItemCache *maybeExtraItemCache() const;
213 QGraphicsItemCache *extraItemCache() const;
214 void removeExtraItemCache();
215
216 void updatePaintedViewBoundingRects(bool updateChildren);
217 void ensureSceneTransformRecursive(QGraphicsItem **topMostDirtyItem);
218 inline void ensureSceneTransform()
219 {
220 QGraphicsItem *that = q_func();
221 ensureSceneTransformRecursive(topMostDirtyItem: &that);
222 }
223
224 inline bool hasTranslateOnlySceneTransform()
225 {
226 ensureSceneTransform();
227 return sceneTransformTranslateOnly;
228 }
229
230 inline void invalidateChildrenSceneTransform()
231 {
232 for (int i = 0; i < children.size(); ++i)
233 children.at(i)->d_ptr->dirtySceneTransform = 1;
234 }
235
236 inline qreal calcEffectiveOpacity() const
237 {
238 qreal o = opacity;
239 QGraphicsItem *p = parent;
240 int myFlags = flags;
241 while (p) {
242 int parentFlags = p->d_ptr->flags;
243
244 // If I have a parent, and I don't ignore my parent's opacity, and my
245 // parent propagates to me, then combine my local opacity with my parent's
246 // effective opacity into my effective opacity.
247 if ((myFlags & QGraphicsItem::ItemIgnoresParentOpacity)
248 || (parentFlags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) {
249 break;
250 }
251
252 o *= p->d_ptr->opacity;
253 p = p->d_ptr->parent;
254 myFlags = parentFlags;
255 }
256 return o;
257 }
258
259 inline bool isOpacityNull() const
260 { return (opacity < qreal(0.001)); }
261
262 static inline bool isOpacityNull(qreal opacity)
263 { return (opacity < qreal(0.001)); }
264
265 inline bool isFullyTransparent() const
266 {
267 if (isOpacityNull())
268 return true;
269 if (!parent)
270 return false;
271
272 return isOpacityNull(opacity: calcEffectiveOpacity());
273 }
274
275 inline qreal effectiveOpacity() const {
276 if (!parent || !opacity)
277 return opacity;
278
279 return calcEffectiveOpacity();
280 }
281
282 inline qreal combineOpacityFromParent(qreal parentOpacity) const
283 {
284 if (parent && !(flags & QGraphicsItem::ItemIgnoresParentOpacity)
285 && !(parent->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) {
286 return parentOpacity * opacity;
287 }
288 return opacity;
289 }
290
291 inline bool childrenCombineOpacity() const
292 {
293 if (!children.size())
294 return true;
295 if (flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)
296 return false;
297
298 for (int i = 0; i < children.size(); ++i) {
299 if (children.at(i)->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)
300 return false;
301 }
302 return true;
303 }
304
305 inline bool childrenClippedToShape() const
306 { return (flags & QGraphicsItem::ItemClipsChildrenToShape) || children.isEmpty(); }
307
308 inline bool isInvisible() const
309 {
310 return !visible || (childrenCombineOpacity() && isFullyTransparent());
311 }
312
313 inline void markParentDirty(bool updateBoundingRect = false);
314
315 void setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromHide);
316 void clearFocusHelper(bool giveFocusToParent, bool hiddenByParentPanel);
317 void setSubFocus(QGraphicsItem *rootItem = nullptr, QGraphicsItem *stopItem = nullptr);
318 void clearSubFocus(QGraphicsItem *rootItem = nullptr, QGraphicsItem *stopItem = nullptr);
319 void resetFocusProxy();
320 virtual void subFocusItemChange();
321 virtual void focusScopeItemChange(bool isSubFocusItem);
322
323 inline QTransform transformToParent() const;
324 inline void ensureSortedChildren();
325 static inline bool insertionOrder(QGraphicsItem *a, QGraphicsItem *b);
326 void ensureSequentialSiblingIndex();
327 inline void sendScenePosChange();
328 virtual void siblingOrderChange();
329
330 // Private Properties
331 virtual qreal width() const;
332 virtual void setWidth(qreal);
333 virtual void resetWidth();
334
335 virtual qreal height() const;
336 virtual void setHeight(qreal);
337 virtual void resetHeight();
338
339 QRectF childrenBoundingRect;
340 QRectF needsRepaint;
341 QHash<QWidget *, QRect> paintedViewBoundingRects;
342 QPointF pos;
343 qreal z;
344 qreal opacity;
345 QGraphicsScene *scene;
346 QGraphicsItem *parent;
347 QList<QGraphicsItem *> children;
348 struct TransformData;
349 TransformData *transformData;
350 QGraphicsEffect *graphicsEffect;
351 QTransform sceneTransform;
352 int index;
353 int siblingIndex;
354 int itemDepth; // Lazily calculated when calling depth().
355 QGraphicsItem *focusProxy;
356 QList<QGraphicsItem **> focusProxyRefs;
357 QGraphicsItem *subFocusItem;
358 QGraphicsItem *focusScopeItem;
359 Qt::InputMethodHints imHints;
360 QGraphicsItem::PanelModality panelModality;
361#ifndef QT_NO_GESTURES
362 QMap<Qt::GestureType, Qt::GestureFlags> gestureContext;
363#endif
364
365 // Packed 32 bits
366 quint32 acceptedMouseButtons : 5;
367 quint32 visible : 1;
368 quint32 explicitlyHidden : 1;
369 quint32 enabled : 1;
370 quint32 explicitlyDisabled : 1;
371 quint32 selected : 1;
372 quint32 acceptsHover : 1;
373 quint32 acceptDrops : 1;
374 quint32 isMemberOfGroup : 1;
375 quint32 handlesChildEvents : 1;
376 quint32 itemDiscovered : 1;
377 quint32 hasCursor : 1;
378 quint32 ancestorFlags : 5;
379 quint32 cacheMode : 2;
380 quint32 hasBoundingRegionGranularity : 1;
381 quint32 isWidget : 1;
382 quint32 dirty : 1;
383 quint32 dirtyChildren : 1;
384 quint32 localCollisionHack : 1;
385 quint32 inSetPosHelper : 1;
386 quint32 needSortChildren : 1;
387 quint32 allChildrenDirty : 1;
388 quint32 fullUpdatePending : 1;
389
390 // Packed 32 bits
391 quint32 flags : 20;
392 quint32 paintedViewBoundingRectsNeedRepaint : 1;
393 quint32 dirtySceneTransform : 1;
394 quint32 geometryChanged : 1;
395 quint32 inDestructor : 1;
396 quint32 isObject : 1;
397 quint32 ignoreVisible : 1;
398 quint32 ignoreOpacity : 1;
399 quint32 acceptTouchEvents : 1;
400 quint32 acceptedTouchBeginEvent : 1;
401 quint32 filtersDescendantEvents : 1;
402 quint32 sceneTransformTranslateOnly : 1;
403 quint32 notifyBoundingRectChanged : 1;
404#ifdef Q_OS_WASM
405 unsigned char :0; //this aligns 64bit field for wasm see QTBUG-65259
406#endif
407 // New 32 bits
408 quint32 notifyInvalidated : 1;
409 quint32 mouseSetsFocus : 1;
410 quint32 explicitActivate : 1;
411 quint32 wantsActive : 1;
412 quint32 holesInSiblingIndex : 1;
413 quint32 sequentialOrdering : 1;
414 quint32 updateDueToGraphicsEffect : 1;
415 quint32 scenePosDescendants : 1;
416 quint32 pendingPolish : 1;
417 quint32 mayHaveChildWithGraphicsEffect : 1;
418 quint32 sendParentChangeNotification : 1;
419 quint32 dirtyChildrenBoundingRect : 1;
420 quint32 padding : 20;
421
422 // Optional stacking order
423 int globalStackingOrder;
424 QGraphicsItem *q_ptr;
425};
426Q_DECLARE_TYPEINFO(QGraphicsItemPrivate::ExtraStruct, Q_RELOCATABLE_TYPE);
427
428struct QGraphicsItemPrivate::TransformData
429{
430 QTransform transform;
431 qreal scale;
432 qreal rotation;
433 qreal xOrigin;
434 qreal yOrigin;
435 QList<QGraphicsTransform *> graphicsTransforms;
436 bool onlyTransform;
437
438 TransformData() :
439 scale(1.0), rotation(0.0),
440 xOrigin(0.0), yOrigin(0.0),
441 onlyTransform(true)
442 { }
443
444 QTransform computedFullTransform(QTransform *postmultiplyTransform = nullptr) const
445 {
446 if (onlyTransform) {
447 if (!postmultiplyTransform || postmultiplyTransform->isIdentity())
448 return transform;
449 if (transform.isIdentity())
450 return *postmultiplyTransform;
451 return transform * *postmultiplyTransform;
452 }
453
454 QTransform x(transform);
455 if (!graphicsTransforms.isEmpty()) {
456 QMatrix4x4 m;
457 for (int i = 0; i < graphicsTransforms.size(); ++i)
458 graphicsTransforms.at(i)->applyTo(matrix: &m);
459 x *= m.toTransform();
460 }
461 x.translate(dx: xOrigin, dy: yOrigin);
462 x.rotate(a: rotation);
463 x.scale(sx: scale, sy: scale);
464 x.translate(dx: -xOrigin, dy: -yOrigin);
465 if (postmultiplyTransform)
466 x *= *postmultiplyTransform;
467 return x;
468 }
469};
470
471struct QGraphicsItemPaintInfo
472{
473 inline QGraphicsItemPaintInfo(const QTransform *const xform1, const QTransform *const xform2,
474 const QTransform *const xform3,
475 QRegion *r, QWidget *w, QStyleOptionGraphicsItem *opt,
476 QPainter *p, qreal o, bool b1, bool b2)
477 : viewTransform(xform1), transformPtr(xform2), effectTransform(xform3), exposedRegion(r), widget(w),
478 option(opt), painter(p), opacity(o), wasDirtySceneTransform(b1), drawItem(b2)
479 {}
480
481 const QTransform *viewTransform;
482 const QTransform *transformPtr;
483 const QTransform *effectTransform;
484 QRegion *exposedRegion;
485 QWidget *widget;
486 QStyleOptionGraphicsItem *option;
487 QPainter *painter;
488 qreal opacity;
489 quint32 wasDirtySceneTransform : 1;
490 quint32 drawItem : 1;
491};
492
493#if QT_CONFIG(graphicseffect)
494class QGraphicsItemEffectSourcePrivate : public QGraphicsEffectSourcePrivate
495{
496public:
497 QGraphicsItemEffectSourcePrivate(QGraphicsItem *i)
498 : QGraphicsEffectSourcePrivate(), item(i), info(nullptr)
499 {}
500
501 void detach() override
502 {
503 item->d_ptr->graphicsEffect = nullptr;
504 item->prepareGeometryChange();
505 }
506
507 const QGraphicsItem *graphicsItem() const override
508 { return item; }
509
510 const QWidget *widget() const override
511 { return nullptr; }
512
513 void update() override {
514 item->d_ptr->updateDueToGraphicsEffect = true;
515 item->update();
516 item->d_ptr->updateDueToGraphicsEffect = false;
517 }
518
519 void effectBoundingRectChanged() override
520 { item->prepareGeometryChange(); }
521
522 bool isPixmap() const override
523 {
524 return item->type() == QGraphicsPixmapItem::Type
525 && !(item->flags() & QGraphicsItem::ItemIsSelectable)
526 && item->d_ptr->children.size() == 0;
527 }
528
529 const QStyleOption *styleOption() const override
530 { return info ? info->option : nullptr; }
531
532 QRect deviceRect() const override
533 {
534 if (!info || !info->widget) {
535 qWarning(msg: "QGraphicsEffectSource::deviceRect: Not yet implemented, lacking device context");
536 return QRect();
537 }
538 return info->widget->rect();
539 }
540
541 QRectF boundingRect(Qt::CoordinateSystem system) const override;
542 void draw(QPainter *) override;
543 QPixmap pixmap(Qt::CoordinateSystem system,
544 QPoint *offset,
545 QGraphicsEffect::PixmapPadMode mode) const override;
546 QRectF paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded = nullptr) const;
547
548 QGraphicsItem *item;
549 QGraphicsItemPaintInfo *info;
550 QTransform lastEffectTransform;
551};
552#endif // QT_CONFIG(graphicseffect)
553
554/*!
555 Returns \c true if \a item1 is on top of \a item2.
556 The items don't need to be siblings.
557
558 \internal
559*/
560inline bool qt_closestItemFirst(const QGraphicsItem *item1, const QGraphicsItem *item2)
561{
562 // Siblings? Just check their z-values.
563 const QGraphicsItemPrivate *d1 = item1->d_ptr.data();
564 const QGraphicsItemPrivate *d2 = item2->d_ptr.data();
565 if (d1->parent == d2->parent)
566 return qt_closestLeaf(item1, item2);
567
568 // Find common ancestor, and each item's ancestor closest to the common
569 // ancestor.
570 int item1Depth = d1->depth();
571 int item2Depth = d2->depth();
572 const QGraphicsItem *p = item1;
573 const QGraphicsItem *t1 = item1;
574 while (item1Depth > item2Depth && (p = p->d_ptr->parent)) {
575 if (p == item2) {
576 // item2 is one of item1's ancestors; item1 is on top
577 return !(t1->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent);
578 }
579 t1 = p;
580 --item1Depth;
581 }
582 p = item2;
583 const QGraphicsItem *t2 = item2;
584 while (item2Depth > item1Depth && (p = p->d_ptr->parent)) {
585 if (p == item1) {
586 // item1 is one of item2's ancestors; item1 is not on top
587 return (t2->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent);
588 }
589 t2 = p;
590 --item2Depth;
591 }
592
593 // item1Ancestor is now at the same level as item2Ancestor, but not the same.
594 const QGraphicsItem *p1 = t1;
595 const QGraphicsItem *p2 = t2;
596 while (t1 && t1 != t2) {
597 p1 = t1;
598 p2 = t2;
599 t1 = t1->d_ptr->parent;
600 t2 = t2->d_ptr->parent;
601 }
602
603 // in case we have a common ancestor, we compare the immediate children in the ancestor's path.
604 // otherwise we compare the respective items' topLevelItems directly.
605 return qt_closestLeaf(p1, p2);
606}
607
608/*!
609 Returns \c true if \a item2 is on top of \a item1.
610 The items don't need to be siblings.
611
612 \internal
613*/
614inline bool qt_closestItemLast(const QGraphicsItem *item1, const QGraphicsItem *item2)
615{
616 return qt_closestItemFirst(item1: item2, item2: item1);
617}
618
619/*!
620 \internal
621*/
622inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2)
623{
624 // Return true if sibling item1 is on top of item2.
625 const QGraphicsItemPrivate *d1 = item1->d_ptr.data();
626 const QGraphicsItemPrivate *d2 = item2->d_ptr.data();
627 bool f1 = d1->flags & QGraphicsItem::ItemStacksBehindParent;
628 bool f2 = d2->flags & QGraphicsItem::ItemStacksBehindParent;
629 if (f1 != f2)
630 return f2;
631 if (d1->z != d2->z)
632 return d1->z > d2->z;
633 return d1->siblingIndex > d2->siblingIndex;
634}
635
636/*!
637 \internal
638*/
639inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2)
640{ return qt_closestLeaf(item1: item2, item2: item1); }
641
642/*
643 return the full transform of the item to the parent. This include the position and all the transform data
644*/
645inline QTransform QGraphicsItemPrivate::transformToParent() const
646{
647 QTransform matrix;
648 combineTransformToParent(x: &matrix);
649 return matrix;
650}
651
652/*!
653 \internal
654*/
655inline void QGraphicsItemPrivate::ensureSortedChildren()
656{
657 if (needSortChildren) {
658 needSortChildren = 0;
659 sequentialOrdering = 1;
660 if (children.isEmpty())
661 return;
662 std::sort(first: children.begin(), last: children.end(), comp: qt_notclosestLeaf);
663 for (int i = 0; i < children.size(); ++i) {
664 if (children.at(i)->d_ptr->siblingIndex != i) {
665 sequentialOrdering = 0;
666 break;
667 }
668 }
669 }
670}
671
672/*!
673 \internal
674*/
675inline bool QGraphicsItemPrivate::insertionOrder(QGraphicsItem *a, QGraphicsItem *b)
676{
677 return a->d_ptr->siblingIndex < b->d_ptr->siblingIndex;
678}
679
680/*!
681 \internal
682*/
683inline void QGraphicsItemPrivate::markParentDirty(bool updateBoundingRect)
684{
685 QGraphicsItemPrivate *parentp = this;
686#if QT_CONFIG(graphicseffect)
687 if (updateBoundingRect && parentp->graphicsEffect && !parentp->inSetPosHelper) {
688 parentp->notifyInvalidated = 1;
689 static_cast<QGraphicsItemEffectSourcePrivate *>(parentp->graphicsEffect->d_func()
690 ->source->d_func())->invalidateCache();
691 }
692#endif
693 while (parentp->parent) {
694 parentp = parentp->parent->d_ptr.data();
695 parentp->dirtyChildren = 1;
696
697 if (updateBoundingRect) {
698 parentp->dirtyChildrenBoundingRect = 1;
699 // ### Only do this if the parent's effect applies to the entire subtree.
700 parentp->notifyBoundingRectChanged = 1;
701 }
702#if QT_CONFIG(graphicseffect)
703 if (parentp->graphicsEffect) {
704 if (updateBoundingRect) {
705 static_cast<QGraphicsItemEffectSourcePrivate *>(parentp->graphicsEffect->d_func()
706 ->source->d_func())->invalidateCache();
707 parentp->notifyInvalidated = 1;
708 }
709 if (parentp->scene && parentp->graphicsEffect->isEnabled()) {
710 parentp->dirty = 1;
711 parentp->fullUpdatePending = 1;
712 }
713 }
714#endif
715 }
716}
717
718QT_END_NAMESPACE
719
720#endif
721

source code of qtbase/src/widgets/graphicsview/qgraphicsitem_p.h