Merge remote-tracking branch 'origin/api_changes'
[profile/ivi/qtbase.git] / src / widgets / graphicsview / qgraphicsitem_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #ifndef QGRAPHICSITEM_P_H
43 #define QGRAPHICSITEM_P_H
44
45 //
46 //  W A R N I N G
47 //  -------------
48 //
49 // This file is not part of the Qt API.  It exists for the convenience
50 // of other Qt classes.  This header file may change from version to
51 // version without notice, or even be removed.
52 //
53 // We mean it.
54 //
55
56 #include "qgraphicsitem.h"
57 #include "qset.h"
58 #include "qpixmapcache.h"
59 #include <private/qgraphicsview_p.h>
60 #include "qgraphicstransform.h"
61 #include <private/qgraphicstransform_p.h>
62
63 #include <private/qgraphicseffect_p.h>
64 #include <qgraphicseffect.h>
65
66 #include <QtCore/qpoint.h>
67
68 #if !defined(QT_NO_GRAPHICSVIEW)
69
70 QT_BEGIN_NAMESPACE
71
72 class QGraphicsItemPrivate;
73
74 #ifndef QDECLARATIVELISTPROPERTY
75 #define QDECLARATIVELISTPROPERTY
76 template<typename T>
77 class QDeclarativeListProperty {
78 public:
79     typedef void (*AppendFunction)(QDeclarativeListProperty<T> *, T*);
80     typedef int (*CountFunction)(QDeclarativeListProperty<T> *);
81     typedef T *(*AtFunction)(QDeclarativeListProperty<T> *, int);
82     typedef void (*ClearFunction)(QDeclarativeListProperty<T> *);
83
84     QDeclarativeListProperty()
85         : object(0), data(0), append(0), count(0), at(0), clear(0), dummy1(0), dummy2(0) {}
86     QDeclarativeListProperty(QObject *o, QList<T *> &list)
87         : object(o), data(&list), append(qlist_append), count(qlist_count), at(qlist_at),
88           clear(qlist_clear), dummy1(0), dummy2(0) {}
89     QDeclarativeListProperty(QObject *o, void *d, AppendFunction a, CountFunction c = 0, AtFunction t = 0,
90                     ClearFunction r = 0)
91         : object(o), data(d), append(a), count(c), at(t), clear(r), dummy1(0), dummy2(0) {}
92
93     bool operator==(const QDeclarativeListProperty &o) const {
94         return object == o.object &&
95                data == o.data &&
96                append == o.append &&
97                count == o.count &&
98                at == o.at &&
99                clear == o.clear;
100     }
101
102     QObject *object;
103     void *data;
104
105     AppendFunction append;
106
107     CountFunction count;
108     AtFunction at;
109
110     ClearFunction clear;
111
112     void *dummy1;
113     void *dummy2;
114
115 private:
116     static void qlist_append(QDeclarativeListProperty *p, T *v) {
117         ((QList<T *> *)p->data)->append(v);
118     }
119     static int qlist_count(QDeclarativeListProperty *p) {
120         return ((QList<T *> *)p->data)->count();
121     }
122     static T *qlist_at(QDeclarativeListProperty *p, int idx) {
123         return ((QList<T *> *)p->data)->at(idx);
124     }
125     static void qlist_clear(QDeclarativeListProperty *p) {
126         return ((QList<T *> *)p->data)->clear();
127     }
128 };
129 #endif
130
131 class QGraphicsItemCache
132 {
133 public:
134     QGraphicsItemCache() : allExposed(false) { }
135
136     // ItemCoordinateCache only
137     QRect boundingRect;
138     QSize fixedSize;
139     QPixmapCache::Key key;
140
141     // DeviceCoordinateCache only
142     struct DeviceData {
143         DeviceData() {}
144         QTransform lastTransform;
145         QPoint cacheIndent;
146         QPixmapCache::Key key;
147     };
148     QHash<QPaintDevice *, DeviceData> deviceData;
149
150     // List of logical exposed rects
151     QVector<QRectF> exposed;
152     bool allExposed;
153
154     // Empty cache
155     void purge();
156 };
157
158 class Q_WIDGETS_EXPORT QGraphicsItemPrivate
159 {
160     Q_DECLARE_PUBLIC(QGraphicsItem)
161 public:
162     enum Extra {
163         ExtraToolTip,
164         ExtraCursor,
165         ExtraCacheData,
166         ExtraMaxDeviceCoordCacheSize,
167         ExtraBoundingRegionGranularity
168     };
169
170     enum AncestorFlag {
171         NoFlag = 0,
172         AncestorHandlesChildEvents = 0x1,
173         AncestorClipsChildren = 0x2,
174         AncestorIgnoresTransformations = 0x4,
175         AncestorFiltersChildEvents = 0x8
176     };
177
178     inline QGraphicsItemPrivate()
179         : z(0),
180         opacity(1.),
181         scene(0),
182         parent(0),
183         transformData(0),
184         graphicsEffect(0),
185         index(-1),
186         siblingIndex(-1),
187         itemDepth(-1),
188         focusProxy(0),
189         subFocusItem(0),
190         focusScopeItem(0),
191         imHints(Qt::ImhNone),
192         panelModality(QGraphicsItem::NonModal),
193         acceptedMouseButtons(0x1f),
194         visible(1),
195         explicitlyHidden(0),
196         enabled(1),
197         explicitlyDisabled(0),
198         selected(0),
199         acceptsHover(0),
200         acceptDrops(0),
201         isMemberOfGroup(0),
202         handlesChildEvents(0),
203         itemDiscovered(0),
204         hasCursor(0),
205         ancestorFlags(0),
206         cacheMode(0),
207         hasBoundingRegionGranularity(0),
208         isWidget(0),
209         dirty(0),
210         dirtyChildren(0),
211         localCollisionHack(0),
212         inSetPosHelper(0),
213         needSortChildren(0),
214         allChildrenDirty(0),
215         fullUpdatePending(0),
216         dirtyChildrenBoundingRect(1),
217         flags(0),
218         paintedViewBoundingRectsNeedRepaint(0),
219         dirtySceneTransform(1),
220         geometryChanged(1),
221         inDestructor(0),
222         isObject(0),
223         ignoreVisible(0),
224         ignoreOpacity(0),
225         acceptTouchEvents(0),
226         acceptedTouchBeginEvent(0),
227         filtersDescendantEvents(0),
228         sceneTransformTranslateOnly(0),
229         notifyBoundingRectChanged(0),
230         notifyInvalidated(0),
231         mouseSetsFocus(1),
232         explicitActivate(0),
233         wantsActive(0),
234         holesInSiblingIndex(0),
235         sequentialOrdering(1),
236         updateDueToGraphicsEffect(0),
237         scenePosDescendants(0),
238         pendingPolish(0),
239         mayHaveChildWithGraphicsEffect(0),
240         isDeclarativeItem(0),
241         sendParentChangeNotification(0),
242         globalStackingOrder(-1),
243         q_ptr(0)
244     {
245     }
246
247     inline virtual ~QGraphicsItemPrivate()
248     { }
249
250     static const QGraphicsItemPrivate *get(const QGraphicsItem *item)
251     {
252         return item->d_ptr.data();
253     }
254     static QGraphicsItemPrivate *get(QGraphicsItem *item)
255     {
256         return item->d_ptr.data();
257     }
258
259     void updateChildWithGraphicsEffectFlagRecursively();
260     void updateAncestorFlag(QGraphicsItem::GraphicsItemFlag childFlag,
261                             AncestorFlag flag = NoFlag, bool enabled = false, bool root = true);
262     void updateAncestorFlags();
263     void setIsMemberOfGroup(bool enabled);
264     void remapItemPos(QEvent *event, QGraphicsItem *item);
265     QPointF genericMapFromScene(const QPointF &pos, const QWidget *viewport) const;
266     inline bool itemIsUntransformable() const
267     {
268         return (flags & QGraphicsItem::ItemIgnoresTransformations)
269             || (ancestorFlags & AncestorIgnoresTransformations);
270     }
271
272     void combineTransformToParent(QTransform *x, const QTransform *viewTransform = 0) const;
273     void combineTransformFromParent(QTransform *x, const QTransform *viewTransform = 0) const;
274     virtual void updateSceneTransformFromParent();
275
276     // ### Qt 5: Remove. Workaround for reimplementation added after Qt 4.4.
277     virtual QVariant inputMethodQueryHelper(Qt::InputMethodQuery query) const;
278     static bool movableAncestorIsSelected(const QGraphicsItem *item);
279
280     virtual void setPosHelper(const QPointF &pos);
281     void setTransformHelper(const QTransform &transform);
282     void prependGraphicsTransform(QGraphicsTransform *t);
283     void appendGraphicsTransform(QGraphicsTransform *t);
284     void setVisibleHelper(bool newVisible, bool explicitly, bool update = true);
285     void setEnabledHelper(bool newEnabled, bool explicitly, bool update = true);
286     bool discardUpdateRequest(bool ignoreVisibleBit = false,
287                               bool ignoreDirtyBit = false, bool ignoreOpacity = false) const;
288     virtual void transformChanged() {}
289     int depth() const;
290 #ifndef QT_NO_GRAPHICSEFFECT
291     enum InvalidateReason {
292         OpacityChanged
293     };
294     void invalidateParentGraphicsEffectsRecursively();
295     void invalidateChildGraphicsEffectsRecursively(InvalidateReason reason);
296 #endif //QT_NO_GRAPHICSEFFECT
297     void invalidateDepthRecursively();
298     void resolveDepth();
299     void addChild(QGraphicsItem *child);
300     void removeChild(QGraphicsItem *child);
301     QDeclarativeListProperty<QGraphicsObject> childrenList();
302     void setParentItemHelper(QGraphicsItem *parent, const QVariant *newParentVariant,
303                              const QVariant *thisPointerVariant);
304     void childrenBoundingRectHelper(QTransform *x, QRectF *rect, QGraphicsItem *topMostEffectItem);
305     void initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform,
306                          const QRegion &exposedRegion, bool allItems = false) const;
307     QRectF effectiveBoundingRect(QGraphicsItem *topMostEffectItem = 0) const;
308     QRectF sceneEffectiveBoundingRect() const;
309
310     QRectF effectiveBoundingRect(const QRectF &rect) const;
311
312     virtual void resolveFont(uint inheritedMask)
313     {
314         for (int i = 0; i < children.size(); ++i)
315             children.at(i)->d_ptr->resolveFont(inheritedMask);
316     }
317
318     virtual void resolvePalette(uint inheritedMask)
319     {
320         for (int i = 0; i < children.size(); ++i)
321             children.at(i)->d_ptr->resolveFont(inheritedMask);
322     }
323
324     virtual bool isProxyWidget() const;
325
326     inline QVariant extra(Extra type) const
327     {
328         for (int i = 0; i < extras.size(); ++i) {
329             const ExtraStruct &extra = extras.at(i);
330             if (extra.type == type)
331                 return extra.value;
332         }
333         return QVariant();
334     }
335
336     inline void setExtra(Extra type, const QVariant &value)
337     {
338         int index = -1;
339         for (int i = 0; i < extras.size(); ++i) {
340             if (extras.at(i).type == type) {
341                 index = i;
342                 break;
343             }
344         }
345
346         if (index == -1) {
347             extras << ExtraStruct(type, value);
348         } else {
349             extras[index].value = value;
350         }
351     }
352
353     inline void unsetExtra(Extra type)
354     {
355         for (int i = 0; i < extras.size(); ++i) {
356             if (extras.at(i).type == type) {
357                 extras.removeAt(i);
358                 return;
359             }
360         }
361     }
362
363     struct ExtraStruct {
364         ExtraStruct(Extra type, QVariant value)
365             : type(type), value(value)
366         { }
367
368         Extra type;
369         QVariant value;
370
371         bool operator<(Extra extra) const
372         { return type < extra; }
373     };
374
375     QList<ExtraStruct> extras;
376
377     QGraphicsItemCache *maybeExtraItemCache() const;
378     QGraphicsItemCache *extraItemCache() const;
379     void removeExtraItemCache();
380
381     void updatePaintedViewBoundingRects(bool updateChildren);
382     void ensureSceneTransformRecursive(QGraphicsItem **topMostDirtyItem);
383     inline void ensureSceneTransform()
384     {
385         QGraphicsItem *that = q_func();
386         ensureSceneTransformRecursive(&that);
387     }
388
389     inline bool hasTranslateOnlySceneTransform()
390     {
391         ensureSceneTransform();
392         return sceneTransformTranslateOnly;
393     }
394
395     inline void invalidateChildrenSceneTransform()
396     {
397         for (int i = 0; i < children.size(); ++i)
398             children.at(i)->d_ptr->dirtySceneTransform = 1;
399     }
400
401     inline qreal calcEffectiveOpacity() const
402     {
403         qreal o = opacity;
404         QGraphicsItem *p = parent;
405         int myFlags = flags;
406         while (p) {
407             int parentFlags = p->d_ptr->flags;
408
409             // If I have a parent, and I don't ignore my parent's opacity, and my
410             // parent propagates to me, then combine my local opacity with my parent's
411             // effective opacity into my effective opacity.
412             if ((myFlags & QGraphicsItem::ItemIgnoresParentOpacity)
413                 || (parentFlags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) {
414                 break;
415             }
416
417             o *= p->d_ptr->opacity;
418             p = p->d_ptr->parent;
419             myFlags = parentFlags;
420         }
421         return o;
422     }
423
424     inline bool isOpacityNull() const
425     { return (opacity < qreal(0.001)); }
426
427     static inline bool isOpacityNull(qreal opacity)
428     { return (opacity < qreal(0.001)); }
429
430     inline bool isFullyTransparent() const
431     {
432         if (isOpacityNull())
433             return true;
434         if (!parent)
435             return false;
436
437         return isOpacityNull(calcEffectiveOpacity());
438     }
439
440     inline qreal effectiveOpacity() const {
441         if (!parent || !opacity)
442             return opacity;
443
444         return calcEffectiveOpacity();
445     }
446
447     inline qreal combineOpacityFromParent(qreal parentOpacity) const
448     {
449         if (parent && !(flags & QGraphicsItem::ItemIgnoresParentOpacity)
450             && !(parent->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) {
451             return parentOpacity * opacity;
452         }
453         return opacity;
454     }
455
456     inline bool childrenCombineOpacity() const
457     {
458         if (!children.size())
459             return true;
460         if (flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)
461             return false;
462
463         for (int i = 0; i < children.size(); ++i) {
464             if (children.at(i)->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)
465                 return false;
466         }
467         return true;
468     }
469
470     inline bool childrenClippedToShape() const
471     { return (flags & QGraphicsItem::ItemClipsChildrenToShape) || children.isEmpty(); }
472
473     inline bool isInvisible() const
474     {
475         return !visible || (childrenCombineOpacity() && isFullyTransparent());
476     }
477
478     inline void markParentDirty(bool updateBoundingRect = false);
479
480     void setFocusHelper(Qt::FocusReason focusReason, bool climb, bool focusFromHide);
481     void clearFocusHelper(bool giveFocusToParent);
482     void setSubFocus(QGraphicsItem *rootItem = 0, QGraphicsItem *stopItem = 0);
483     void clearSubFocus(QGraphicsItem *rootItem = 0, QGraphicsItem *stopItem = 0);
484     void resetFocusProxy();
485     virtual void subFocusItemChange();
486     virtual void focusScopeItemChange(bool isSubFocusItem);
487
488     static void children_append(QDeclarativeListProperty<QGraphicsObject> *list, QGraphicsObject *item);
489     static int children_count(QDeclarativeListProperty<QGraphicsObject> *list);
490     static QGraphicsObject *children_at(QDeclarativeListProperty<QGraphicsObject> *list, int);
491     static void children_clear(QDeclarativeListProperty<QGraphicsObject> *list);
492
493     inline QTransform transformToParent() const;
494     inline void ensureSortedChildren();
495     static inline bool insertionOrder(QGraphicsItem *a, QGraphicsItem *b);
496     void ensureSequentialSiblingIndex();
497     inline void sendScenePosChange();
498     virtual void siblingOrderChange();
499
500     // Private Properties
501     virtual qreal width() const;
502     virtual void setWidth(qreal);
503     virtual void resetWidth();
504
505     virtual qreal height() const;
506     virtual void setHeight(qreal);
507     virtual void resetHeight();
508
509     QRectF childrenBoundingRect;
510     QRectF needsRepaint;
511     QHash<QWidget *, QRect> paintedViewBoundingRects;
512     QPointF pos;
513     qreal z;
514     qreal opacity;
515     QGraphicsScene *scene;
516     QGraphicsItem *parent;
517     QList<QGraphicsItem *> children;
518     struct TransformData;
519     TransformData *transformData;
520     QGraphicsEffect *graphicsEffect;
521     QTransform sceneTransform;
522     int index;
523     int siblingIndex;
524     int itemDepth;  // Lazily calculated when calling depth().
525     QGraphicsItem *focusProxy;
526     QList<QGraphicsItem **> focusProxyRefs;
527     QGraphicsItem *subFocusItem;
528     QGraphicsItem *focusScopeItem;
529     Qt::InputMethodHints imHints;
530     QGraphicsItem::PanelModality panelModality;
531 #ifndef QT_NO_GESTURES
532     QMap<Qt::GestureType, Qt::GestureFlags> gestureContext;
533 #endif
534
535     // Packed 32 bits
536     quint32 acceptedMouseButtons : 5;
537     quint32 visible : 1;
538     quint32 explicitlyHidden : 1;
539     quint32 enabled : 1;
540     quint32 explicitlyDisabled : 1;
541     quint32 selected : 1;
542     quint32 acceptsHover : 1;
543     quint32 acceptDrops : 1;
544     quint32 isMemberOfGroup : 1;
545     quint32 handlesChildEvents : 1;
546     quint32 itemDiscovered : 1;
547     quint32 hasCursor : 1;
548     quint32 ancestorFlags : 4;
549     quint32 cacheMode : 2;
550     quint32 hasBoundingRegionGranularity : 1;
551     quint32 isWidget : 1;
552     quint32 dirty : 1;
553     quint32 dirtyChildren : 1;
554     quint32 localCollisionHack : 1;
555     quint32 inSetPosHelper : 1;
556     quint32 needSortChildren : 1;
557     quint32 allChildrenDirty : 1;
558     quint32 fullUpdatePending : 1;
559     quint32 dirtyChildrenBoundingRect : 1;
560
561     // Packed 32 bits
562     quint32 flags : 19;
563     quint32 paintedViewBoundingRectsNeedRepaint : 1;
564     quint32 dirtySceneTransform : 1;
565     quint32 geometryChanged : 1;
566     quint32 inDestructor : 1;
567     quint32 isObject : 1;
568     quint32 ignoreVisible : 1;
569     quint32 ignoreOpacity : 1;
570     quint32 acceptTouchEvents : 1;
571     quint32 acceptedTouchBeginEvent : 1;
572     quint32 filtersDescendantEvents : 1;
573     quint32 sceneTransformTranslateOnly : 1;
574     quint32 notifyBoundingRectChanged : 1;
575     quint32 notifyInvalidated : 1;
576
577     // New 32 bits
578     quint32 mouseSetsFocus : 1;
579     quint32 explicitActivate : 1;
580     quint32 wantsActive : 1;
581     quint32 holesInSiblingIndex : 1;
582     quint32 sequentialOrdering : 1;
583     quint32 updateDueToGraphicsEffect : 1;
584     quint32 scenePosDescendants : 1;
585     quint32 pendingPolish : 1;
586     quint32 mayHaveChildWithGraphicsEffect : 1;
587     quint32 isDeclarativeItem : 1;
588     quint32 sendParentChangeNotification : 1;
589     quint32 padding : 21;
590
591     // Optional stacking order
592     int globalStackingOrder;
593     QGraphicsItem *q_ptr;
594 };
595
596 struct QGraphicsItemPrivate::TransformData
597 {
598     QTransform transform;
599     qreal scale;
600     qreal rotation;
601     qreal xOrigin;
602     qreal yOrigin;
603     QList<QGraphicsTransform *> graphicsTransforms;
604     bool onlyTransform;
605
606     TransformData() :
607         scale(1.0), rotation(0.0),
608         xOrigin(0.0), yOrigin(0.0),
609         onlyTransform(true)
610     { }
611
612     QTransform computedFullTransform(QTransform *postmultiplyTransform = 0) const
613     {
614         if (onlyTransform) {
615             if (!postmultiplyTransform || postmultiplyTransform->isIdentity())
616                 return transform;
617             if (transform.isIdentity())
618                 return *postmultiplyTransform;
619             return transform * *postmultiplyTransform;
620         }
621
622         QTransform x(transform);
623         if (!graphicsTransforms.isEmpty()) {
624             QMatrix4x4 m;
625             for (int i = 0; i < graphicsTransforms.size(); ++i)
626                 graphicsTransforms.at(i)->applyTo(&m);
627             x *= m.toTransform();
628         }
629         x.translate(xOrigin, yOrigin);
630         x.rotate(rotation);
631         x.scale(scale, scale);
632         x.translate(-xOrigin, -yOrigin);
633         if (postmultiplyTransform)
634             x *= *postmultiplyTransform;
635         return x;
636     }
637 };
638
639 struct QGraphicsItemPaintInfo
640 {
641     inline QGraphicsItemPaintInfo(const QTransform *const xform1, const QTransform *const xform2,
642                                   const QTransform *const xform3,
643                                   QRegion *r, QWidget *w, QStyleOptionGraphicsItem *opt,
644                                   QPainter *p, qreal o, bool b1, bool b2)
645         : viewTransform(xform1), transformPtr(xform2), effectTransform(xform3), exposedRegion(r), widget(w),
646           option(opt), painter(p), opacity(o), wasDirtySceneTransform(b1), drawItem(b2)
647     {}
648
649     const QTransform *viewTransform;
650     const QTransform *transformPtr;
651     const QTransform *effectTransform;
652     QRegion *exposedRegion;
653     QWidget *widget;
654     QStyleOptionGraphicsItem *option;
655     QPainter *painter;
656     qreal opacity;
657     quint32 wasDirtySceneTransform : 1;
658     quint32 drawItem : 1;
659 };
660
661 #ifndef QT_NO_GRAPHICSEFFECT
662 class QGraphicsItemEffectSourcePrivate : public QGraphicsEffectSourcePrivate
663 {
664 public:
665     QGraphicsItemEffectSourcePrivate(QGraphicsItem *i)
666         : QGraphicsEffectSourcePrivate(), item(i), info(0)
667     {}
668
669     inline void detach()
670     {
671         item->d_ptr->graphicsEffect = 0;
672         item->prepareGeometryChange();
673     }
674
675     inline const QGraphicsItem *graphicsItem() const
676     { return item; }
677
678     inline const QWidget *widget() const
679     { return 0; }
680
681     inline void update() {
682         item->d_ptr->updateDueToGraphicsEffect = true;
683         item->update();
684         item->d_ptr->updateDueToGraphicsEffect = false;
685     }
686
687     inline void effectBoundingRectChanged()
688     { item->prepareGeometryChange(); }
689
690     inline bool isPixmap() const
691     {
692         return item->type() == QGraphicsPixmapItem::Type
693                && !(item->flags() & QGraphicsItem::ItemIsSelectable)
694                && item->d_ptr->children.size() == 0;
695             //|| (item->d_ptr->isObject && qobject_cast<QDeclarativeImage *>(q_func()));
696     }
697
698     inline const QStyleOption *styleOption() const
699     { return info ? info->option : 0; }
700
701     inline QRect deviceRect() const
702     {
703         if (!info || !info->widget) {
704             qWarning("QGraphicsEffectSource::deviceRect: Not yet implemented, lacking device context");
705             return QRect();
706         }
707         return info->widget->rect();
708     }
709
710     QRectF boundingRect(Qt::CoordinateSystem system) const;
711     void draw(QPainter *);
712     QPixmap pixmap(Qt::CoordinateSystem system,
713                    QPoint *offset,
714                    QGraphicsEffect::PixmapPadMode mode) const;
715     QRect paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded = 0) const;
716
717     QGraphicsItem *item;
718     QGraphicsItemPaintInfo *info;
719     QTransform lastEffectTransform;
720 };
721 #endif //QT_NO_GRAPHICSEFFECT
722
723 /*!
724     Returns true if \a item1 is on top of \a item2.
725     The items don't need to be siblings.
726
727     \internal
728 */
729 inline bool qt_closestItemFirst(const QGraphicsItem *item1, const QGraphicsItem *item2)
730 {
731     // Siblings? Just check their z-values.
732     const QGraphicsItemPrivate *d1 = item1->d_ptr.data();
733     const QGraphicsItemPrivate *d2 = item2->d_ptr.data();
734     if (d1->parent == d2->parent)
735         return qt_closestLeaf(item1, item2);
736
737     // Find common ancestor, and each item's ancestor closest to the common
738     // ancestor.
739     int item1Depth = d1->depth();
740     int item2Depth = d2->depth();
741     const QGraphicsItem *p = item1;
742     const QGraphicsItem *t1 = item1;
743     while (item1Depth > item2Depth && (p = p->d_ptr->parent)) {
744         if (p == item2) {
745             // item2 is one of item1's ancestors; item1 is on top
746             return !(t1->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent);
747         }
748         t1 = p;
749         --item1Depth;
750     }
751     p = item2;
752     const QGraphicsItem *t2 = item2;
753     while (item2Depth > item1Depth && (p = p->d_ptr->parent)) {
754         if (p == item1) {
755             // item1 is one of item2's ancestors; item1 is not on top
756             return (t2->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent);
757         }
758         t2 = p;
759         --item2Depth;
760     }
761
762     // item1Ancestor is now at the same level as item2Ancestor, but not the same.
763     const QGraphicsItem *p1 = t1;
764     const QGraphicsItem *p2 = t2;
765     while (t1 && t1 != t2) {
766         p1 = t1;
767         p2 = t2;
768         t1 = t1->d_ptr->parent;
769         t2 = t2->d_ptr->parent;
770     }
771
772     // in case we have a common ancestor, we compare the immediate children in the ancestor's path.
773     // otherwise we compare the respective items' topLevelItems directly.
774     return qt_closestLeaf(p1, p2);
775 }
776
777 /*!
778     Returns true if \a item2 is on top of \a item1.
779     The items don't need to be siblings.
780
781     \internal
782 */
783 inline bool qt_closestItemLast(const QGraphicsItem *item1, const QGraphicsItem *item2)
784 {
785     return qt_closestItemFirst(item2, item1);
786 }
787
788 /*!
789     \internal
790 */
791 inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2)
792 {
793     // Return true if sibling item1 is on top of item2.
794     const QGraphicsItemPrivate *d1 = item1->d_ptr.data();
795     const QGraphicsItemPrivate *d2 = item2->d_ptr.data();
796     bool f1 = d1->flags & QGraphicsItem::ItemStacksBehindParent;
797     bool f2 = d2->flags & QGraphicsItem::ItemStacksBehindParent;
798     if (f1 != f2)
799         return f2;
800     if (d1->z != d2->z)
801         return d1->z > d2->z;
802     return d1->siblingIndex > d2->siblingIndex;
803 }
804
805 /*!
806     \internal
807 */
808 inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2)
809 { return qt_closestLeaf(item2, item1); }
810
811 /*
812    return the full transform of the item to the parent.  This include the position and all the transform data
813 */
814 inline QTransform QGraphicsItemPrivate::transformToParent() const
815 {
816     QTransform matrix;
817     combineTransformToParent(&matrix);
818     return matrix;
819 }
820
821 /*!
822     \internal
823 */
824 inline void QGraphicsItemPrivate::ensureSortedChildren()
825 {
826     if (needSortChildren) {
827         needSortChildren = 0;
828         sequentialOrdering = 1;
829         if (children.isEmpty())
830             return;
831         qSort(children.begin(), children.end(), qt_notclosestLeaf);
832         for (int i = 0; i < children.size(); ++i) {
833             if (children.at(i)->d_ptr->siblingIndex != i) {
834                 sequentialOrdering = 0;
835                 break;
836             }
837         }
838     }
839 }
840
841 /*!
842     \internal
843 */
844 inline bool QGraphicsItemPrivate::insertionOrder(QGraphicsItem *a, QGraphicsItem *b)
845 {
846     return a->d_ptr->siblingIndex < b->d_ptr->siblingIndex;
847 }
848
849 /*!
850     \internal
851 */
852 inline void QGraphicsItemPrivate::markParentDirty(bool updateBoundingRect)
853 {
854     QGraphicsItemPrivate *parentp = this;
855 #ifndef QT_NO_GRAPHICSEFFECT
856     if (updateBoundingRect && parentp->graphicsEffect && !parentp->inSetPosHelper) {
857         parentp->notifyInvalidated = 1;
858         static_cast<QGraphicsItemEffectSourcePrivate *>(parentp->graphicsEffect->d_func()
859                                                         ->source->d_func())->invalidateCache();
860     }
861 #endif
862     while (parentp->parent) {
863         parentp = parentp->parent->d_ptr.data();
864         parentp->dirtyChildren = 1;
865
866         if (updateBoundingRect) {
867             parentp->dirtyChildrenBoundingRect = 1;
868             // ### Only do this if the parent's effect applies to the entire subtree.
869             parentp->notifyBoundingRectChanged = 1;
870         }
871 #ifndef QT_NO_GRAPHICSEFFECT
872         if (parentp->graphicsEffect) {
873             if (updateBoundingRect) {
874                 static_cast<QGraphicsItemEffectSourcePrivate *>(parentp->graphicsEffect->d_func()
875                                                                 ->source->d_func())->invalidateCache();
876                 parentp->notifyInvalidated = 1;
877             }
878             if (parentp->scene && parentp->graphicsEffect->isEnabled()) {
879                 parentp->dirty = 1;
880                 parentp->fullUpdatePending = 1;
881             }
882         }
883 #endif
884     }
885 }
886
887 QT_END_NAMESPACE
888
889 #endif // QT_NO_GRAPHICSVIEW
890
891 #endif