diff options
Diffstat (limited to 'src/gui/graphicsview/qgraphicsitem.cpp')
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem.cpp | 531 |
1 files changed, 306 insertions, 225 deletions
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 3c7593d..7e155e1 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -307,8 +307,6 @@ QStyleOptionGraphicsItem::exposedRect or QStyleOptionGraphicsItem::matrix. By default, the exposedRect is initialized to the item's boundingRect and the matrix is untransformed. Enable this flag for more fine-grained values. - Note that QStyleOptionGraphicsItem::levelOfDetail is unaffected by this flag - and is always initialized to 1. Use QStyleOptionGraphicsItem::levelOfDetailFromTransform for a more fine-grained value. @@ -323,6 +321,10 @@ performance reasons, these notifications are disabled by default. You must enable this flag to receive notifications for position and transform changes. This flag was introduced in Qt 4.6. + + \value ItemAcceptsInputMethod The item supports input methods typically + used for Asian languages. + This flag was introduced in Qt 4.6. */ /*! @@ -554,6 +556,7 @@ #include "qgraphicsview.h" #include "qgraphicswidget.h" #include "qgraphicsproxywidget.h" +#include "qgraphicsscenebsptreeindex_p.h" #include <QtCore/qbitarray.h> #include <QtCore/qdebug.h> #include <QtCore/qpoint.h> @@ -575,7 +578,6 @@ #include <private/qtextcontrol_p.h> #include <private/qtextdocumentlayout_p.h> #include <private/qtextengine_p.h> -#include <private/qgesturemanager_p.h> #ifdef Q_WS_X11 #include <private/qt_x11_p.h> @@ -586,17 +588,6 @@ QT_BEGIN_NAMESPACE -// QRectF::intersects() returns false always if either the source or target -// rectangle's width or height are 0. This works around that problem. -static inline void _q_adjustRect(QRectF *rect) -{ - Q_ASSERT(rect); - if (!rect->width()) - rect->adjust(-0.00001, 0, 0.00001, 0); - if (!rect->height()) - rect->adjust(0, -0.00001, 0, 0.00001); -} - static inline void _q_adjustRect(QRect *rect) { Q_ASSERT(rect); @@ -616,8 +607,6 @@ public: }; Q_GLOBAL_STATIC(QGraphicsItemCustomDataStore, qt_dataStore) -QString qt_getStandardGestureTypeName(Qt::GestureType type); - /*! \internal @@ -660,6 +649,10 @@ void QGraphicsItemPrivate::updateAncestorFlag(QGraphicsItem::GraphicsItemFlag ch // For root items only. This is the item that has either enabled or // disabled \a childFlag, or has been reparented. switch (int(childFlag)) { + case -2: + flag = AncestorFiltersChildEvents; + enabled = q->filtersChildEvents(); + break; case -1: flag = AncestorHandlesChildEvents; enabled = q->handlesChildEvents(); @@ -680,7 +673,8 @@ void QGraphicsItemPrivate::updateAncestorFlag(QGraphicsItem::GraphicsItemFlag ch // Inherit the enabled-state from our parents. if ((parent && ((parent->d_ptr->ancestorFlags & flag) || (int(parent->d_ptr->flags & childFlag) == childFlag) - || (childFlag == -1 && parent->d_ptr->handlesChildEvents)))) { + || (childFlag == -1 && parent->d_ptr->handlesChildEvents) + || (childFlag == -2 && parent->d_ptr->filtersDescendantEvents)))) { enabled = true; ancestorFlags |= flag; } @@ -701,7 +695,9 @@ void QGraphicsItemPrivate::updateAncestorFlag(QGraphicsItem::GraphicsItemFlag ch ancestorFlags &= ~flag; // Don't process children if the item has the main flag set on itself. - if ((childFlag != -1 && int(flags & childFlag) == childFlag) || (int(childFlag) == -1 && handlesChildEvents)) + if ((childFlag != -1 && int(flags & childFlag) == childFlag) + || (int(childFlag) == -1 && handlesChildEvents) + || (int(childFlag) == -2 && filtersDescendantEvents)) return; } @@ -832,6 +828,42 @@ void QGraphicsItemPrivate::combineTransformFromParent(QTransform *x, const QTran } } +void QGraphicsItemPrivate::updateSceneTransformFromParent() +{ + if (parent) { + Q_ASSERT(!parent->d_ptr->dirtySceneTransform); + if (parent->d_ptr->sceneTransformTranslateOnly) { + sceneTransform = QTransform::fromTranslate(parent->d_ptr->sceneTransform.dx() + pos.x(), + parent->d_ptr->sceneTransform.dy() + pos.y()); + } else { + sceneTransform = parent->d_ptr->sceneTransform; + sceneTransform.translate(pos.x(), pos.y()); + } + if (transformData) { + sceneTransform = transformData->computedFullTransform(&sceneTransform); + sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate); + } else { + sceneTransformTranslateOnly = parent->d_ptr->sceneTransformTranslateOnly; + } + } else if (!transformData) { + sceneTransform = QTransform::fromTranslate(pos.x(), pos.y()); + sceneTransformTranslateOnly = 1; + } else if (transformData->onlyTransform) { + sceneTransform = transformData->transform; + if (!pos.isNull()) + sceneTransform *= QTransform::fromTranslate(pos.x(), pos.y()); + sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate); + } else if (pos.isNull()) { + sceneTransform = transformData->computedFullTransform(); + sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate); + } else { + sceneTransform = QTransform::fromTranslate(pos.x(), pos.y()); + sceneTransform = transformData->computedFullTransform(&sceneTransform); + sceneTransformTranslateOnly = (sceneTransform.type() <= QTransform::TxTranslate); + } + dirtySceneTransform = 0; +} + /*! \internal @@ -871,6 +903,11 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) if (newParent == parent) return; + if (scene) { + // Deliver the change to the index + scene->d_func()->index->itemChange(q, QGraphicsItem::ItemParentChange, newParentVariant); + } + if (QGraphicsWidget *w = isWidget ? static_cast<QGraphicsWidget *>(q) : q->parentWidget()) { // Update the child focus chain; when reparenting a widget that has a // focus child, ensure that that focus child clears its focus child @@ -922,6 +959,7 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) } // Inherit ancestor flags from the new parent. + updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2)); updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1)); updateAncestorFlag(QGraphicsItem::ItemClipsChildrenToShape); updateAncestorFlag(QGraphicsItem::ItemIgnoresTransformations); @@ -938,6 +976,7 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) } else { // Inherit ancestor flags from the new parent. + updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2)); updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1)); updateAncestorFlag(QGraphicsItem::ItemClipsChildrenToShape); updateAncestorFlag(QGraphicsItem::ItemIgnoresTransformations); @@ -958,12 +997,6 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) } } - if (scene) { - // Invalidate any sort caching; arrival of a new item means we need to - // resort. - scene->d_func()->invalidateSortCache(); - } - // Resolve depth. resolveDepth(parent ? parent->d_ptr->depth : -1); dirtySceneTransform = 1; @@ -1132,7 +1165,6 @@ QGraphicsItem::~QGraphicsItem() { d_ptr->inDestructor = 1; d_ptr->removeExtraItemCache(); - d_ptr->removeExtraGestures(); clearFocus(); if (!d_ptr->children.isEmpty()) { @@ -1203,7 +1235,7 @@ void QGraphicsItem::setGroup(QGraphicsItemGroup *group) Returns a pointer to this item's parent item. If this item does not have a parent, 0 is returned. - \sa setParentItem(), children() + \sa setParentItem(), childItems() */ QGraphicsItem *QGraphicsItem::parentItem() const { @@ -1226,7 +1258,7 @@ QGraphicsItem *QGraphicsItem::topLevelItem() const } /*! - \since 4.4 + \since 4.6 Returns a pointer to the item's parent, cast to a QGraphicsObject. returns 0 if the parent item is not a QGraphicsObject. @@ -1319,7 +1351,7 @@ const QGraphicsObject *QGraphicsItem::toGraphicsObject() const the parent. You should not \l{QGraphicsScene::addItem()}{add} the item to the scene yourself. - \sa parentItem(), children() + \sa parentItem(), childItems() */ void QGraphicsItem::setParentItem(QGraphicsItem *parent) { @@ -1442,6 +1474,8 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) flags = GraphicsItemFlags(itemChange(ItemFlagsChange, quint32(flags)).toUInt()); if (quint32(d_ptr->flags) == quint32(flags)) return; + if (d_ptr->scene) + d_ptr->scene->d_func()->index->itemChange(this, ItemFlagsChange, quint32(flags)); // Flags that alter the geometry of the item (or its children). const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations); @@ -1490,6 +1524,12 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) d_ptr->scene->d_func()->needSortTopLevelItems = 1; } + if ((flags & ItemAcceptsInputMethod) != (oldFlags & ItemAcceptsInputMethod)) { + // Update input method sensitivity in any views. + if (d_ptr->scene) + d_ptr->scene->d_func()->updateInputMethodSensitivityInViews(); + } + if (d_ptr->scene) { d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true, @@ -1794,6 +1834,8 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo if (q_ptr->isSelected()) q_ptr->setSelected(false); } else { + geometryChanged = 1; + paintedViewBoundingRectsNeedRepaint = 1; if (isWidget && scene) { QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(q_ptr); if (widget->windowType() == Qt::Popup) @@ -2254,10 +2296,10 @@ bool QGraphicsItem::acceptsHoverEvents() const stays "hovered" until the cursor leaves its area, including its children's areas. - If a parent item handles child events (setHandlesChildEvents()), it will - receive hover move, drag move, and drop events as the cursor passes - through its children, but it does not receive hover enter and hover leave, - nor drag enter and drag leave events on behalf of its children. + If a parent item handles child events, it will receive hover move, + drag move, and drop events as the cursor passes through its + children, but it does not receive hover enter and hover leave, nor + drag enter and drag leave events on behalf of its children. A QGraphicsWidget with window decorations will accept hover events regardless of the value of acceptHoverEvents(). @@ -2288,8 +2330,8 @@ void QGraphicsItem::setAcceptsHoverEvents(bool enabled) /*! \since 4.6 - Returns true if an item accepts touch events (QTouchEvent); otherwise, returns false. By - default, items do not accept touch events. + Returns true if an item accepts \l{QTouchEvent}{touch events}; + otherwise, returns false. By default, items do not accept touch events. \sa setAcceptTouchEvents() */ @@ -2301,7 +2343,7 @@ bool QGraphicsItem::acceptTouchEvents() const /*! \since 4.6 - If \a enabled is true, this item will accept touch events; + If \a enabled is true, this item will accept \l{QTouchEvent}{touch events}; otherwise, it will ignore them. By default, items do not accept touch events. */ @@ -2317,6 +2359,44 @@ void QGraphicsItem::setAcceptTouchEvents(bool enabled) } /*! + \since 4.6 + + Returns true if this item filters child events (i.e., all events + intended for any of its children are instead sent to this item); + otherwise, false is returned. + + The default value is false; child events are not filtered. + + \sa setFiltersChildEvents() +*/ +bool QGraphicsItem::filtersChildEvents() const +{ + return d_ptr->filtersDescendantEvents; +} + +/*! + \since 4.6 + + If \a enabled is true, this item is set to filter all events for + all its children (i.e., all events intented for any of its + children are instead sent to this item); otherwise, if \a enabled + is false, this item will only handle its own events. The default + value is false. + + \sa filtersChildEvents() +*/ +void QGraphicsItem::setFiltersChildEvents(bool enabled) +{ + if (d_ptr->filtersDescendantEvents == enabled) + return; + + d_ptr->filtersDescendantEvents = enabled; + d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-2)); +} + +/*! + \obsolete + Returns true if this item handles child events (i.e., all events intended for any of its children are instead sent to this item); otherwise, false is returned. @@ -2337,6 +2417,8 @@ bool QGraphicsItem::handlesChildEvents() const } /*! + \obsolete + If \a enabled is true, this item is set to handle all events for all its children (i.e., all events intented for any of its children are instead sent to this item); otherwise, if \a enabled @@ -2371,6 +2453,8 @@ void QGraphicsItem::setHandlesChildEvents(bool enabled) */ bool QGraphicsItem::hasFocus() const { + if (d_ptr->focusProxy) + return d_ptr->focusProxy->hasFocus(); return (d_ptr->scene && d_ptr->scene->focusItem() == this); } @@ -2396,12 +2480,16 @@ void QGraphicsItem::setFocus(Qt::FocusReason focusReason) { if (!d_ptr->scene || !isEnabled() || hasFocus() || !(d_ptr->flags & ItemIsFocusable)) return; - if (isVisible()) { + QGraphicsItem *item = this; + QGraphicsItem *f; + while ((f = item->d_ptr->focusProxy)) + item = f; + if (item->isVisible()) { // Visible items immediately gain focus from scene. - d_ptr->scene->setFocusItem(this, focusReason); - } else if (d_ptr->isWidget) { + d_ptr->scene->d_func()->setFocusItemHelper(item, focusReason); + } else if (item->d_ptr->isWidget) { // Just set up subfocus. - static_cast<QGraphicsWidget *>(this)->d_func()->setFocusWidget(); + static_cast<QGraphicsWidget *>(item)->d_func()->setFocusWidget(); } } @@ -2424,13 +2512,73 @@ void QGraphicsItem::clearFocus() // Invisible widget items with focus must explicitly clear subfocus. static_cast<QGraphicsWidget *>(this)->d_func()->clearFocusWidget(); } - if (d_ptr->scene->focusItem() == this) { + if (hasFocus()) { // If this item has the scene's input focus, clear it. d_ptr->scene->setFocusItem(0); } } /*! + \since 4.6 + + Returns this item's focus proxy, or 0 if the item + does not have any focus proxy. + + \sa setFocusProxy() +*/ +QGraphicsItem *QGraphicsItem::focusProxy() const +{ + return d_ptr->focusProxy; +} + +/*! + \since 4.6 + + Sets the item's focus proxy to \a item. + + If an item has a focus proxy, the focus proxy will receive + input focus when the item gains input focus. The item itself + will still have focus (i.e., hasFocus() will return true), + but only the focus proxy will receive the keyboard input. + + A focus proxy can itself have a focus proxy, and so on. In + such case, keyboard input will be handled by the outermost + focus proxy. + + \sa focusProxy() +*/ +void QGraphicsItem::setFocusProxy(QGraphicsItem *item) +{ + if (item == d_ptr->focusProxy) + return; + if (item == this) { + qWarning("QGraphicsItem::setFocusProxy: cannot assign self as focus proxy"); + return; + } + if (item) { + if (item->d_ptr->scene != d_ptr->scene) { + qWarning("QGraphicsItem::setFocusProxy: focus proxy must be in same scene"); + return; + } + for (QGraphicsItem *f = item->focusProxy(); f != 0; f = f->focusProxy()) { + if (f == this) { + qWarning("QGraphicsItem::setFocusProxy: %p is already in the focus proxy chain", item); + return; + } + } + } + + QGraphicsItem *lastFocusProxy = d_ptr->focusProxy; + d_ptr->focusProxy = item; + if (d_ptr->scene) { + if (lastFocusProxy) + d_ptr->scene->d_func()->focusProxyReverseMap.remove(lastFocusProxy, this); + if (item) + d_ptr->scene->d_func()->focusProxyReverseMap.insert(item, this); + } +} + +/*! \since 4.4 Grabs the mouse input. @@ -2565,7 +2713,7 @@ void QGraphicsItem::ungrabKeyboard() For convenience, you can also call scenePos() to determine the item's position in scene coordinates, regardless of its parent. - \sa x(), y(), setPos(), matrix(), {The Graphics View Coordinate System} + \sa x(), y(), setPos(), transform(), {The Graphics View Coordinate System} */ QPointF QGraphicsItem::pos() const { @@ -2581,10 +2729,12 @@ QPointF QGraphicsItem::pos() const */ /*! - Set's the \a x coordinate of the item's position. Equivalent to - calling setPos(x, y()). + \since 4.6 - \sa x(), setPos() + Set's the \a x coordinate of the item's position. Equivalent to + calling setPos(x, y()). + + \sa x(), setPos() */ void QGraphicsItem::setX(qreal x) { @@ -2600,10 +2750,12 @@ void QGraphicsItem::setX(qreal x) */ /*! - Set's the \a y coordinate of the item's position. Equivalent to - calling setPos(x(), y). + \since 4.6 + + Set's the \a y coordinate of the item's position. Equivalent to + calling setPos(x(), y). - \sa x(), setPos() + \sa x(), setPos() */ void QGraphicsItem::setY(qreal y) { @@ -3101,7 +3253,7 @@ void QGraphicsItem::setShear(qreal sh, qreal sv) /*! \since 4.6 - Returns the origin point used for transformation in item coordinate. + Returns the origin point for the transformation in item coordinates. The default is QPointF(0,0). @@ -3117,7 +3269,7 @@ QPointF QGraphicsItem::transformOrigin() const /*! \since 4.6 - Sets the \a origin for transformation in item coordinate + Sets the \a origin point for the transformation in item coordinates. \sa transformOrigin(), {Transformations} */ @@ -3138,9 +3290,9 @@ void QGraphicsItem::setTransformOrigin(const QPointF &origin) \since 4.6 \overload - Sets the origin for the transformation to the point - composed of \a x and \a y. - + Sets the origin point for the transformation in item coordinates. + This is equivalent to calling setTransformOrigin(QPointF(\a x, \a y)). + \sa setTransformOrigin(), {Transformations} */ @@ -3154,7 +3306,8 @@ void QGraphicsItem::setTransformOrigin(const QPointF &origin) */ QMatrix QGraphicsItem::sceneMatrix() const { - return sceneTransform().toAffine(); + d_ptr->ensureSceneTransform(); + return d_ptr->sceneTransform.toAffine(); } @@ -3177,16 +3330,7 @@ QMatrix QGraphicsItem::sceneMatrix() const */ QTransform QGraphicsItem::sceneTransform() const { - if (d_ptr->dirtySceneTransform) { - // This item and all its descendants have dirty scene transforms. - // We're about to validate this item's scene transform, so we have to - // invalidate all the children; otherwise there's no way for the descendants - // to detect that the ancestor has changed. - d_ptr->invalidateChildrenSceneTransform(); - } - - QGraphicsItem *that = const_cast<QGraphicsItem *>(this); - d_ptr->ensureSceneTransformRecursive(&that); + d_ptr->ensureSceneTransform(); return d_ptr->sceneTransform; } @@ -3216,8 +3360,10 @@ QTransform QGraphicsItem::sceneTransform() const QTransform QGraphicsItem::deviceTransform(const QTransform &viewportTransform) const { // Ensure we return the standard transform if we're not untransformable. - if (!d_ptr->itemIsUntransformable()) - return sceneTransform() * viewportTransform; + if (!d_ptr->itemIsUntransformable()) { + d_ptr->ensureSceneTransform(); + return d_ptr->sceneTransform * viewportTransform; + } // Find the topmost item that ignores view transformations. const QGraphicsItem *untransformedAncestor = this; @@ -3236,7 +3382,8 @@ QTransform QGraphicsItem::deviceTransform(const QTransform &viewportTransform) c } // First translate the base untransformable item. - QPointF mappedPoint = (untransformedAncestor->sceneTransform() * viewportTransform).map(QPointF(0, 0)); + untransformedAncestor->d_ptr->ensureSceneTransform(); + QPointF mappedPoint = (untransformedAncestor->d_ptr->sceneTransform * viewportTransform).map(QPointF(0, 0)); // COMBINE QTransform matrix = QTransform::fromTranslate(mappedPoint.x(), mappedPoint.y()); @@ -3329,8 +3476,11 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co // Find the closest common ancestor. If the two items don't share an // ancestor, then the only way is to combine their scene transforms. const QGraphicsItem *commonAncestor = commonAncestorItem(other); - if (!commonAncestor) - return sceneTransform() * other->sceneTransform().inverted(ok); + if (!commonAncestor) { + d_ptr->ensureSceneTransform(); + other->d_ptr->ensureSceneTransform(); + return d_ptr->sceneTransform * other->d_ptr->sceneTransform.inverted(ok); + } // If the two items are cousins (in sibling branches), map both to the // common ancestor, and combine the two transforms. @@ -3621,18 +3771,20 @@ void QGraphicsItem::setZValue(qreal z) qreal newZ = qreal(newZVariant.toDouble()); if (newZ == d_ptr->z) return; + + if (d_ptr->scene) { + // Z Value has changed, we have to notify the index. + d_ptr->scene->d_func()->index->itemChange(this, ItemZValueChange, newZVariant); + } + d_ptr->z = newZ; if (d_ptr->parent) d_ptr->parent->d_ptr->needSortChildren = 1; else if (d_ptr->scene) d_ptr->scene->d_func()->needSortTopLevelItems = 1; - if (d_ptr->scene) { + if (d_ptr->scene) d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true); - // Invalidate any sort caching; arrival of a new item means we need to - // resort. - d_ptr->scene->d_func()->invalidateSortCache(); - } itemChange(ItemZValueHasChanged, newZVariant); @@ -3723,7 +3875,13 @@ QRectF QGraphicsItem::sceneBoundingRect() const QRectF br = boundingRect(); br.translate(offset); - return !parentItem ? br : parentItem->sceneTransform().mapRect(br); + if (!parentItem) + return br; + if (parentItem->d_ptr->hasTranslateOnlySceneTransform()) { + br.translate(parentItem->d_ptr->sceneTransform.dx(), parentItem->d_ptr->sceneTransform.dy()); + return br; + } + return parentItem->d_ptr->sceneTransform.mapRect(br); } /*! @@ -4098,7 +4256,7 @@ bool QGraphicsItem::isObscuredBy(const QGraphicsItem *item) const { if (!item) return false; - return QGraphicsScenePrivate::closestItemFirst_withoutCache(item, this) + return QGraphicsSceneBspTreeIndexPrivate::closestItemFirst_withoutCache(item, this) && qt_QGraphicsItem_isObscured(this, item, boundingRect()); } @@ -4291,12 +4449,11 @@ bool QGraphicsItemPrivate::discardUpdateRequest(bool ignoreClipping, bool ignore { // No scene, or if the scene is updating everything, means we have nothing // to do. The only exception is if the scene tracks the growing scene rect. - return (!visible && !ignoreVisibleBit) + return !scene + || (!visible && !ignoreVisibleBit && !this->ignoreVisible) || (!ignoreDirtyBit && fullUpdatePending) - || !scene - || (scene->d_func()->updateAll && scene->d_func()->hasSceneRect) || (!ignoreClipping && (childrenClippedToShape() && isClippedAway())) - || (!ignoreOpacity && childrenCombineOpacity() && isFullyTransparent()); + || (!ignoreOpacity && !this->ignoreOpacity && childrenCombineOpacity() && isFullyTransparent()); } /*! @@ -4317,6 +4474,7 @@ void QGraphicsItemPrivate::resolveDepth(int parentDepth) void QGraphicsItemPrivate::addChild(QGraphicsItem *child) { needSortChildren = 1; + child->d_ptr->siblingIndex = children.size(); children.append(child); } @@ -4326,6 +4484,10 @@ void QGraphicsItemPrivate::addChild(QGraphicsItem *child) void QGraphicsItemPrivate::removeChild(QGraphicsItem *child) { children.removeOne(child); + // NB! Do not use children.removeAt(child->d_ptr->siblingIndex) because + // the child is not guaranteed to be at the index after the list is sorted. + // (see ensureSortedChildren()). + child->d_ptr->siblingIndex = -1; } /*! @@ -4486,9 +4648,22 @@ void QGraphicsItemPrivate::ensureSceneTransformRecursive(QGraphicsItem **topMost } // COMBINE my transform with the parent's scene transform. - sceneTransform = parent ? parent->d_ptr->sceneTransform : QTransform(); - combineTransformFromParent(&sceneTransform); - dirtySceneTransform = 0; + updateSceneTransformFromParent(); + Q_ASSERT(!dirtySceneTransform); +} + +void QGraphicsItemPrivate::ensureSceneTransform() +{ + if (dirtySceneTransform) { + // This item and all its descendants have dirty scene transforms. + // We're about to validate this item's scene transform, so we have to + // invalidate all the children; otherwise there's no way for the descendants + // to detect that the ancestor has changed. + invalidateChildrenSceneTransform(); + } + + QGraphicsItem *that = q_func(); + ensureSceneTransformRecursive(&that); } /*! @@ -4829,7 +5004,9 @@ QPointF QGraphicsItem::mapToParent(const QPointF &point) const */ QPointF QGraphicsItem::mapToScene(const QPointF &point) const { - return sceneTransform().map(point); + if (d_ptr->hasTranslateOnlySceneTransform()) + return QPointF(point.x() + d_ptr->sceneTransform.dx(), point.y() + d_ptr->sceneTransform.dy()); + return d_ptr->sceneTransform.map(point); } /*! @@ -4896,7 +5073,9 @@ QPolygonF QGraphicsItem::mapToParent(const QRectF &rect) const */ QPolygonF QGraphicsItem::mapToScene(const QRectF &rect) const { - return sceneTransform().map(rect); + if (d_ptr->hasTranslateOnlySceneTransform()) + return rect.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy()); + return d_ptr->sceneTransform.map(rect); } /*! @@ -4969,7 +5148,9 @@ QRectF QGraphicsItem::mapRectToParent(const QRectF &rect) const */ QRectF QGraphicsItem::mapRectToScene(const QRectF &rect) const { - return sceneTransform().mapRect(rect); + if (d_ptr->hasTranslateOnlySceneTransform()) + return rect.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy()); + return d_ptr->sceneTransform.mapRect(rect); } /*! @@ -5043,7 +5224,9 @@ QRectF QGraphicsItem::mapRectFromParent(const QRectF &rect) const */ QRectF QGraphicsItem::mapRectFromScene(const QRectF &rect) const { - return sceneTransform().inverted().mapRect(rect); + if (d_ptr->hasTranslateOnlySceneTransform()) + return rect.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy()); + return d_ptr->sceneTransform.inverted().mapRect(rect); } /*! @@ -5095,7 +5278,9 @@ QPolygonF QGraphicsItem::mapToParent(const QPolygonF &polygon) const */ QPolygonF QGraphicsItem::mapToScene(const QPolygonF &polygon) const { - return sceneTransform().map(polygon); + if (d_ptr->hasTranslateOnlySceneTransform()) + return polygon.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy()); + return d_ptr->sceneTransform.map(polygon); } /*! @@ -5140,7 +5325,9 @@ QPainterPath QGraphicsItem::mapToParent(const QPainterPath &path) const */ QPainterPath QGraphicsItem::mapToScene(const QPainterPath &path) const { - return sceneTransform().map(path); + if (d_ptr->hasTranslateOnlySceneTransform()) + return path.translated(d_ptr->sceneTransform.dx(), d_ptr->sceneTransform.dy()); + return d_ptr->sceneTransform.map(path); } /*! @@ -5201,7 +5388,9 @@ QPointF QGraphicsItem::mapFromParent(const QPointF &point) const */ QPointF QGraphicsItem::mapFromScene(const QPointF &point) const { - return sceneTransform().inverted().map(point); + if (d_ptr->hasTranslateOnlySceneTransform()) + return QPointF(point.x() - d_ptr->sceneTransform.dx(), point.y() - d_ptr->sceneTransform.dy()); + return d_ptr->sceneTransform.inverted().map(point); } /*! @@ -5269,7 +5458,9 @@ QPolygonF QGraphicsItem::mapFromParent(const QRectF &rect) const */ QPolygonF QGraphicsItem::mapFromScene(const QRectF &rect) const { - return sceneTransform().inverted().map(rect); + if (d_ptr->hasTranslateOnlySceneTransform()) + return rect.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy()); + return d_ptr->sceneTransform.inverted().map(rect); } /*! @@ -5319,7 +5510,9 @@ QPolygonF QGraphicsItem::mapFromParent(const QPolygonF &polygon) const */ QPolygonF QGraphicsItem::mapFromScene(const QPolygonF &polygon) const { - return sceneTransform().inverted().map(polygon); + if (d_ptr->hasTranslateOnlySceneTransform()) + return polygon.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy()); + return d_ptr->sceneTransform.inverted().map(polygon); } /*! @@ -5362,7 +5555,9 @@ QPainterPath QGraphicsItem::mapFromParent(const QPainterPath &path) const */ QPainterPath QGraphicsItem::mapFromScene(const QPainterPath &path) const { - return sceneTransform().inverted().map(path); + if (d_ptr->hasTranslateOnlySceneTransform()) + return path.translated(-d_ptr->sceneTransform.dx(), -d_ptr->sceneTransform.dy()); + return d_ptr->sceneTransform.inverted().map(path); } /*! @@ -6251,102 +6446,6 @@ QVariant QGraphicsItem::inputMethodQuery(Qt::InputMethodQuery query) const } /*! - \since 4.6 - - Subscribes the graphics item to the specified \a gesture type. - - Returns the id of the gesture. - - \sa releaseGesture(), setGestureEnabled() -*/ -int QGraphicsItem::grabGesture(Qt::GestureType gesture) -{ - /// TODO: if we are QGraphicsProxyWidget we should subscribe the widget to gesture as well. - return grabGesture(qt_getStandardGestureTypeName(gesture)); -} - -/*! - \since 4.6 - - Subscribes the graphics item to the specified \a gesture type. - - Returns the id of the gesture. - - \sa releaseGesture(), setGestureEnabled() -*/ -int QGraphicsItem::grabGesture(const QString &gesture) -{ - int id = QGestureManager::instance()->makeGestureId(gesture); - d_ptr->grabGesture(id); - return id; -} - -void QGraphicsItemPrivate::grabGesture(int id) -{ - Q_Q(QGraphicsItem); - extraGestures()->gestures << id; - if (scene) - scene->d_func()->grabGesture(q, id); -} - -bool QGraphicsItemPrivate::releaseGesture(int id) -{ - Q_Q(QGraphicsItem); - QGestureExtraData *extra = maybeExtraGestures(); - if (extra && extra->gestures.contains(id)) { - if (scene) - scene->d_func()->releaseGesture(q, id); - extra->gestures.remove(id); - return true; - } - return false; -} - -/*! - \since 4.6 - - Unsubscribes the graphics item from a gesture, which is specified - by the \a gestureId. - - \sa grabGesture(), setGestureEnabled() -*/ -void QGraphicsItem::releaseGesture(int gestureId) -{ - /// TODO: if we are QGraphicsProxyWidget we should unsubscribe the widget from gesture as well. - if (d_ptr->releaseGesture(gestureId)) - QGestureManager::instance()->releaseGestureId(gestureId); -} - -/*! - \since 4.6 - - If \a enable is true, the gesture with the given \a gestureId is - enabled; otherwise the gesture is disabled. - - The id of the gesture is returned by the grabGesture(). - - \sa grabGesture(), releaseGesture() -*/ -void QGraphicsItem::setGestureEnabled(int gestureId, bool enable) -{ - //### -} - -bool QGraphicsItemPrivate::hasGesture(const QString &name) const -{ - if (QGestureExtraData *extra = maybeExtraGestures()) { - QGestureManager *gm = QGestureManager::instance(); - QSet<int>::const_iterator it = extra->gestures.begin(), - e = extra->gestures.end(); - for (; it != e; ++it) { - if (gm->gestureNameFromId(*it) == name) - return true; - } - } - return false; -} - -/*! This virtual function is called by QGraphicsItem to notify custom items that some part of the item's state changes. By reimplementing this function, your can react to a change, and in some cases, (depending on \a @@ -6370,23 +6469,6 @@ bool QGraphicsItemPrivate::hasGesture(const QString &name) const QVariant QGraphicsItem::itemChange(GraphicsItemChange change, const QVariant &value) { Q_UNUSED(change); - if (change == QGraphicsItem::ItemSceneChange) { - QGestureExtraData *extra = d_ptr->maybeExtraGestures(); - if (!qVariantValue<QGraphicsScene*>(value) && extra) { - // the item has been removed from a scene, unsubscribe gestures. - Q_ASSERT(d_ptr->scene); - foreach(int id, extra->gestures) - d_ptr->scene->d_func()->releaseGesture(this, id); - } - } else if (change == QGraphicsItem::ItemSceneHasChanged) { - QGraphicsScene *scene = qVariantValue<QGraphicsScene*>(value); - QGestureExtraData *extra = d_ptr->maybeExtraGestures(); - if (scene && extra) { - // item has been added to the scene - foreach(int id, extra->gestures) - scene->d_func()->grabGesture(this, id); - } - } return value; } @@ -6440,7 +6522,7 @@ void QGraphicsItem::addToIndex() return; } if (d_ptr->scene) - d_ptr->scene->d_func()->addToIndex(this); + d_ptr->scene->d_func()->index->addItem(this); } /*! @@ -6457,7 +6539,7 @@ void QGraphicsItem::removeFromIndex() return; } if (d_ptr->scene) - d_ptr->scene->d_func()->removeFromIndex(this); + d_ptr->scene->d_func()->index->removeItem(this); } /*! @@ -6476,10 +6558,12 @@ void QGraphicsItem::removeFromIndex() void QGraphicsItem::prepareGeometryChange() { if (d_ptr->scene) { + d_ptr->scene->d_func()->dirtyGrowingItemsBoundingRect = true; d_ptr->geometryChanged = 1; d_ptr->paintedViewBoundingRectsNeedRepaint = 1; QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func(); + scenePrivate->index->prepareBoundingRectChange(this); scenePrivate->markDirty(this, QRectF(), /*invalidateChildren=*/true, /*maybeDirtyClipPath=*/!d_ptr->inSetPosHelper); @@ -6490,10 +6574,13 @@ void QGraphicsItem::prepareGeometryChange() // _q_processDirtyItems is called before _q_emitUpdated. if ((scenePrivate->connectedSignals & scenePrivate->changedSignalMask) || scenePrivate->views.isEmpty()) { - d_ptr->scene->update(sceneTransform().mapRect(boundingRect())); + if (d_ptr->hasTranslateOnlySceneTransform()) { + d_ptr->scene->update(boundingRect().translated(d_ptr->sceneTransform.dx(), + d_ptr->sceneTransform.dy())); + } else { + d_ptr->scene->update(d_ptr->sceneTransform.mapRect(boundingRect())); + } } - - scenePrivate->removeFromIndex(this); } QGraphicsItem *parent = this; @@ -9743,13 +9830,10 @@ QVariant QGraphicsSimpleTextItem::extension(const QVariant &variant) const setParentItem(). The boundingRect() function of QGraphicsItemGroup returns the - bounding rectangle of all items in the item group. In addition, - item groups have handlesChildEvents() enabled by default, so all - events sent to a member of the group go to the item group (i.e., - selecting one item in a group will select them all). - QGraphicsItemGroup ignores the ItemIgnoresTransformations flag on its - children (i.e., with respect to the geometry of the group item, the - children are treated as if they were transformable). + bounding rectangle of all items in the item group. + QGraphicsItemGroup ignores the ItemIgnoresTransformations flag on + its children (i.e., with respect to the geometry of the group + item, the children are treated as if they were transformable). There are two ways to construct an item group. The easiest and most common approach is to pass a list of items (e.g., all @@ -9939,17 +10023,11 @@ QDebug operator<<(QDebug debug, QGraphicsItem *item) return debug; } - QStringList flags; - if (item->isVisible()) flags << QLatin1String("isVisible"); - if (item->isEnabled()) flags << QLatin1String("isEnabled"); - if (item->isSelected()) flags << QLatin1String("isSelected"); - if (item->hasFocus()) flags << QLatin1String("HasFocus"); - debug << "QGraphicsItem(this =" << ((void*)item) << ", parent =" << ((void*)item->parentItem()) << ", pos =" << item->pos() - << ", z =" << item->zValue() << ", flags = {" - << flags.join(QLatin1String("|")) << " })"; + << ", z =" << item->zValue() << ", flags = " + << item->flags() << ")"; return debug; } @@ -10083,6 +10161,9 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag) case QGraphicsItem::ItemSendsGeometryChanges: str = "ItemSendsGeometryChanges"; break; + case QGraphicsItem::ItemAcceptsInputMethod: + str = "ItemAcceptsInputMethod"; + break; } debug << str; return debug; |