summaryrefslogtreecommitdiffstats
path: root/src/gui/graphicsview/qgraphicsitem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/graphicsview/qgraphicsitem.cpp')
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp531
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;