diff options
Diffstat (limited to 'src/gui/graphicsview/qgraphicsitem_p.h')
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem_p.h | 290 |
1 files changed, 256 insertions, 34 deletions
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 233c674..805b554 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -54,6 +54,13 @@ // #include "qgraphicsitem.h" +#include "qset.h" +#include "qpixmapcache.h" +#include "qgraphicsview_p.h" +#include "qgraphicstransform.h" +#include "qgraphicstransform_p.h" + +#include <QtCore/qpoint.h> #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW @@ -69,13 +76,14 @@ public: // ItemCoordinateCache only QRect boundingRect; QSize fixedSize; - QString key; + QPixmapCache::Key key; // DeviceCoordinateCache only struct DeviceData { + DeviceData() {} QTransform lastTransform; QPoint cacheIndent; - QString key; + QPixmapCache::Key key; }; QMap<QPaintDevice *, DeviceData> deviceData; @@ -92,29 +100,33 @@ class Q_AUTOTEST_EXPORT QGraphicsItemPrivate Q_DECLARE_PUBLIC(QGraphicsItem) public: enum Extra { - ExtraTransform, ExtraToolTip, ExtraCursor, ExtraCacheData, ExtraMaxDeviceCoordCacheSize, - ExtraBoundingRegionGranularity, - ExtraOpacity, - ExtraEffectiveOpacity + ExtraBoundingRegionGranularity }; enum AncestorFlag { NoFlag = 0, AncestorHandlesChildEvents = 0x1, AncestorClipsChildren = 0x2, - AncestorIgnoresTransformations = 0x4 + AncestorIgnoresTransformations = 0x4, + AncestorFiltersChildEvents = 0x8 }; inline QGraphicsItemPrivate() : z(0), + opacity(1.), scene(0), parent(0), + transformData(0), index(-1), + siblingIndex(-1), depth(0), + focusProxy(0), + subFocusItem(0), + imHints(Qt::ImhNone), acceptedMouseButtons(0x1f), visible(1), explicitlyHidden(0), @@ -126,14 +138,10 @@ public: isMemberOfGroup(0), handlesChildEvents(0), itemDiscovered(0), - hasTransform(0), hasCursor(0), ancestorFlags(0), cacheMode(0), hasBoundingRegionGranularity(0), - flags(0), - hasOpacity(0), - hasEffectiveOpacity(0), isWidget(0), dirty(0), dirtyChildren(0), @@ -141,9 +149,23 @@ public: dirtyClipPath(1), emptyClipPath(0), inSetPosHelper(0), - allChildrenCombineOpacity(1), + needSortChildren(1), + allChildrenDirty(0), + fullUpdatePending(0), + flags(0), + dirtyChildrenBoundingRect(1), + paintedViewBoundingRectsNeedRepaint(0), + dirtySceneTransform(1), + geometryChanged(1), + inDestructor(0), + isObject(0), + ignoreVisible(0), + ignoreOpacity(0), + acceptTouchEvents(0), + acceptedTouchBeginEvent(0), + filtersDescendantEvents(0), + sceneTransformTranslateOnly(0), globalStackingOrder(-1), - sceneTransformIndex(-1), q_ptr(0) { } @@ -151,28 +173,48 @@ public: inline virtual ~QGraphicsItemPrivate() { } + static const QGraphicsItemPrivate *get(const QGraphicsItem *item) + { + return item->d_ptr; + } + static QGraphicsItemPrivate *get(QGraphicsItem *item) + { + return item->d_ptr; + } + void updateAncestorFlag(QGraphicsItem::GraphicsItemFlag childFlag, AncestorFlag flag = NoFlag, bool enabled = false, bool root = true); void setIsMemberOfGroup(bool enabled); void remapItemPos(QEvent *event, QGraphicsItem *item); QPointF genericMapFromScene(const QPointF &pos, const QWidget *viewport) const; - bool itemIsUntransformable() const; + inline bool itemIsUntransformable() const + { + return (flags & QGraphicsItem::ItemIgnoresTransformations) + || (ancestorFlags & AncestorIgnoresTransformations); + } + + void combineTransformToParent(QTransform *x, const QTransform *viewTransform = 0) const; + void combineTransformFromParent(QTransform *x, const QTransform *viewTransform = 0) const; + virtual void updateSceneTransformFromParent(); // ### Qt 5: Remove. Workaround for reimplementation added after Qt 4.4. virtual QVariant inputMethodQueryHelper(Qt::InputMethodQuery query) const; static bool movableAncestorIsSelected(const QGraphicsItem *item); void setPosHelper(const QPointF &pos); + void setTransformHelper(const QTransform &transform); + void appendGraphicsTransform(QGraphicsTransform *t); void setVisibleHelper(bool newVisible, bool explicitly, bool update = true); void setEnabledHelper(bool newEnabled, bool explicitly, bool update = true); bool discardUpdateRequest(bool ignoreClipping = false, bool ignoreVisibleBit = false, bool ignoreDirtyBit = false, bool ignoreOpacity = false) const; - void updateHelper(const QRectF &rect = QRectF(), bool force = false, bool maybeDirtyClipPath = false); - void fullUpdateHelper(bool childrenOnly = false, bool maybeDirtyClipPath = false, bool ignoreOpacity = false); - void updateEffectiveOpacity(); - void resolveEffectiveOpacity(qreal effectiveParentOpacity); void resolveDepth(int parentDepth); - void invalidateSceneTransformCache(); + void addChild(QGraphicsItem *child); + void removeChild(QGraphicsItem *child); + void setParentItemHelper(QGraphicsItem *parent); + void childrenBoundingRectHelper(QTransform *x, QRectF *rect); + void initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform, + const QRegion &exposedRegion, bool allItems = false) const; virtual void resolveFont(uint inheritedMask) { @@ -236,8 +278,10 @@ public: bool operator<(Extra extra) const { return type < extra; } }; + QList<ExtraStruct> extras; + QGraphicsItemCache *maybeExtraItemCache() const; QGraphicsItemCache *extraItemCache() const; void removeExtraItemCache(); @@ -261,12 +305,83 @@ public: void invalidateCachedClipPathRecursively(bool childrenOnly = false, const QRectF &emptyIfOutsideThisRect = QRectF()); void updateCachedClipPathFromSetPosHelper(const QPointF &newPos); + void ensureSceneTransformRecursive(QGraphicsItem **topMostDirtyItem); + void ensureSceneTransform(); + + inline bool hasTranslateOnlySceneTransform() + { + ensureSceneTransform(); + return sceneTransformTranslateOnly; + } + + inline void invalidateChildrenSceneTransform() + { + for (int i = 0; i < children.size(); ++i) + children.at(i)->d_ptr->dirtySceneTransform = 1; + } + + inline qreal calcEffectiveOpacity() const + { + qreal o = opacity; + QGraphicsItem *p = parent; + int myFlags = flags; + while (p) { + int parentFlags = p->d_ptr->flags; + + // If I have a parent, and I don't ignore my parent's opacity, and my + // parent propagates to me, then combine my local opacity with my parent's + // effective opacity into my effective opacity. + if ((myFlags & QGraphicsItem::ItemIgnoresParentOpacity) + || (parentFlags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) { + break; + } + + o *= p->d_ptr->opacity; + p = p->d_ptr->parent; + myFlags = parentFlags; + } + return o; + } inline bool isFullyTransparent() const - { return hasEffectiveOpacity && qFuzzyCompare(q_func()->effectiveOpacity() + 1, qreal(1.0)); } + { + if (opacity < 0.001) + return true; + if (!parent) + return false; + + return calcEffectiveOpacity() < 0.001; + } + + inline qreal effectiveOpacity() const { + if (!parent || !opacity) + return opacity; + + return calcEffectiveOpacity(); + } + + inline qreal combineOpacityFromParent(qreal parentOpacity) const + { + if (parent && !(flags & QGraphicsItem::ItemIgnoresParentOpacity) + && !(parent->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) { + return parentOpacity * opacity; + } + return opacity; + } inline bool childrenCombineOpacity() const - { return allChildrenCombineOpacity || children.isEmpty(); } + { + if (!children.size()) + return true; + if (flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren) + return false; + + for (int i = 0; i < children.size(); ++i) { + if (children.at(i)->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity) + return false; + } + return true; + } inline bool isClippedAway() const { return !dirtyClipPath && q_func()->isClipped() && (emptyClipPath || cachedClipPath.isEmpty()); } @@ -281,16 +396,33 @@ public: || (childrenCombineOpacity() && isFullyTransparent()); } + void setSubFocus(); + void clearSubFocus(); + + inline QTransform transformToParent() const; + inline void ensureSortedChildren(); + QPainterPath cachedClipPath; + QRectF childrenBoundingRect; + QRectF needsRepaint; + QMap<QWidget *, QRect> paintedViewBoundingRects; QPointF pos; qreal z; + qreal opacity; QGraphicsScene *scene; QGraphicsItem *parent; QList<QGraphicsItem *> children; + struct TransformData; + TransformData *transformData; + QTransform sceneTransform; int index; + int siblingIndex; int depth; + QGraphicsItem *focusProxy; + QGraphicsItem *subFocusItem; + Qt::InputMethodHints imHints; - // Packed 32 bytes + // Packed 32 bits quint32 acceptedMouseButtons : 5; quint32 visible : 1; quint32 explicitlyHidden : 1; @@ -302,32 +434,122 @@ public: quint32 isMemberOfGroup : 1; quint32 handlesChildEvents : 1; quint32 itemDiscovered : 1; - quint32 hasTransform : 1; quint32 hasCursor : 1; - quint32 ancestorFlags : 3; + quint32 ancestorFlags : 4; quint32 cacheMode : 2; quint32 hasBoundingRegionGranularity : 1; - quint32 flags : 9; - - // New 32 bytes - quint32 hasOpacity : 1; - quint32 hasEffectiveOpacity : 1; quint32 isWidget : 1; - quint32 dirty : 1; - quint32 dirtyChildren : 1; + quint32 dirty : 1; + quint32 dirtyChildren : 1; quint32 localCollisionHack : 1; quint32 dirtyClipPath : 1; quint32 emptyClipPath : 1; quint32 inSetPosHelper : 1; - quint32 allChildrenCombineOpacity : 1; + quint32 needSortChildren : 1; + quint32 allChildrenDirty : 1; + + // New 32 bits + quint32 fullUpdatePending : 1; + quint32 flags : 14; + quint32 dirtyChildrenBoundingRect : 1; + quint32 paintedViewBoundingRectsNeedRepaint : 1; + quint32 dirtySceneTransform : 1; + quint32 geometryChanged : 1; + quint32 inDestructor : 1; + quint32 isObject : 1; + quint32 ignoreVisible : 1; + quint32 ignoreOpacity : 1; + quint32 acceptTouchEvents : 1; + quint32 acceptedTouchBeginEvent : 1; + quint32 filtersDescendantEvents : 1; + quint32 sceneTransformTranslateOnly : 1; + quint32 unused : 5; // feel free to use // Optional stacking order int globalStackingOrder; - int sceneTransformIndex; - QGraphicsItem *q_ptr; }; +struct QGraphicsItemPrivate::TransformData +{ + QTransform transform; + qreal scale; + qreal rotation; + qreal xOrigin; + qreal yOrigin; + QList<QGraphicsTransform *> graphicsTransforms; + bool onlyTransform; + + TransformData() : + scale(1.0), rotation(0.0), + xOrigin(0.0), yOrigin(0.0), + onlyTransform(true) + { } + + QTransform computedFullTransform(QTransform *postmultiplyTransform = 0) const + { + if (onlyTransform) { + if (!postmultiplyTransform || postmultiplyTransform->isIdentity()) + return transform; + if (transform.isIdentity()) + return *postmultiplyTransform; + return transform * *postmultiplyTransform; + } + + QTransform x(transform); + for (int i = 0; i < graphicsTransforms.size(); ++i) + graphicsTransforms.at(i)->applyTo(&x); + x.translate(xOrigin, yOrigin); + x.rotate(rotation, Qt::ZAxis); + x.scale(scale, scale); + x.translate(-xOrigin, -yOrigin); + if (postmultiplyTransform) + x *= *postmultiplyTransform; + return x; + } +}; + +/*! + \internal +*/ +inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) +{ + // Return true if sibling item1 is on top of item2. + const QGraphicsItemPrivate *d1 = item1->d_ptr; + const QGraphicsItemPrivate *d2 = item2->d_ptr; + bool f1 = d1->flags & QGraphicsItem::ItemStacksBehindParent; + bool f2 = d2->flags & QGraphicsItem::ItemStacksBehindParent; + if (f1 != f2) + return f2; + if (d1->z != d2->z) + return d1->z > d2->z; + return d1->siblingIndex > d2->siblingIndex; +} + +/*! + \internal +*/ +static inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) +{ return qt_closestLeaf(item2, item1); } + +/* + return the full transform of the item to the parent. This include the position and all the transform data +*/ +inline QTransform QGraphicsItemPrivate::transformToParent() const +{ + QTransform matrix; + combineTransformToParent(&matrix); + return matrix; +} + +inline void QGraphicsItemPrivate::ensureSortedChildren() +{ + if (needSortChildren) { + qSort(children.begin(), children.end(), qt_notclosestLeaf); + needSortChildren = 0; + } +} + QT_END_NAMESPACE #endif // QT_NO_GRAPHICSVIEW |