summaryrefslogtreecommitdiffstats
path: root/src/gui/graphicsview/qgraphicsscene.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/graphicsview/qgraphicsscene.cpp')
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp394
1 files changed, 280 insertions, 114 deletions
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 1f78a18d32..13f70e56e9 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -292,15 +292,21 @@ static inline bool QRectF_intersects(const QRectF &s, const QRectF &r)
// QRectF::intersects() returns false always if either the source or target
// rectangle's width or height are 0. This works around that problem.
-static QRectF _q_adjustedRect(const QRectF &rect)
+static inline void _q_adjustRect(QRectF *rect)
{
- static const qreal p = (qreal)0.00001;
- QRectF r = rect;
- if (!r.width())
- r.adjust(-p, 0, p, 0);
- if (!r.height())
- r.adjust(0, -p, 0, p);
- return r;
+ 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 QRectF adjustedItemBoundingRect(const QGraphicsItem *item)
+{
+ Q_ASSERT(item);
+ QRectF boundingRect(item->boundingRect());
+ _q_adjustRect(&boundingRect);
+ return boundingRect;
}
static void _q_hoverFromMouseEvent(QGraphicsSceneHoverEvent *hover, const QGraphicsSceneMouseEvent *mouseEvent)
@@ -632,10 +638,11 @@ void QGraphicsScenePrivate::_q_updateLater()
*/
void QGraphicsScenePrivate::_q_polishItems()
{
+ const QVariant booleanTrueVariant(true);
foreach (QGraphicsItem *item, unpolishedItems) {
if (!item->d_ptr->explicitlyHidden) {
- item->itemChange(QGraphicsItem::ItemVisibleChange, true);
- item->itemChange(QGraphicsItem::ItemVisibleHasChanged, true);
+ item->itemChange(QGraphicsItem::ItemVisibleChange, booleanTrueVariant);
+ item->itemChange(QGraphicsItem::ItemVisibleHasChanged, booleanTrueVariant);
}
if (item->isWidget()) {
QEvent event(QEvent::Polish);
@@ -690,13 +697,6 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item)
{
Q_Q(QGraphicsScene);
- if (QGraphicsItem *parent = item->d_func()->parent) {
- QVariant variant;
- qVariantSetValue<QGraphicsItem *>(variant, item);
- parent->itemChange(QGraphicsItem::ItemChildRemovedChange, variant);
- parent->d_func()->children.removeAll(item);
- }
-
// Clear focus on the item to remove any reference in the focusWidget
// chain.
item->clearFocus();
@@ -740,6 +740,15 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item)
unpolishedItems.removeAll(item);
dirtyItems.removeAll(item);
+ //We remove all references of item from the sceneEventFilter arrays
+ QMultiMap<QGraphicsItem*, QGraphicsItem*>::iterator iterator = sceneEventFilters.begin();
+ while (iterator != sceneEventFilters.end()) {
+ if (iterator.value() == item || iterator.key() == item)
+ iterator = sceneEventFilters.erase(iterator);
+ else
+ ++iterator;
+ }
+
// Remove from scene transform cache
int transformIndex = item->d_func()->sceneTransformIndex;
if (transformIndex != -1) {
@@ -1358,6 +1367,48 @@ QGraphicsWidget *QGraphicsScenePrivate::windowForItem(const QGraphicsItem *item)
return 0;
}
+
+QList<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QPointF &pos) const
+{
+ QList<QGraphicsItem *> items;
+
+ // The index returns a rough estimate of what items are inside the rect.
+ // Refine it by iterating through all returned items.
+ QRectF adjustedRect = QRectF(pos, QSize(1,1));
+ foreach (QGraphicsItem *item, estimateItemsInRect(adjustedRect)) {
+ // Find the item's scene transform in a clever way.
+ QTransform x = item->sceneTransform();
+ bool keep = false;
+
+ // ### _q_adjustedRect is only needed because QRectF::intersects,
+ // QRectF::contains and QTransform::map() and friends don't work with
+ // flat rectangles.
+ const QRectF br(adjustedItemBoundingRect(item));
+ // Rect intersects/contains item's shape
+ if (QRectF_intersects(adjustedRect, x.mapRect(br))) {
+ bool ok;
+ QTransform xinv = x.inverted(&ok);
+ if (ok) {
+ if (item->contains(xinv.map(pos))) {
+ items << item;
+ keep = true;
+ }
+ }
+ }
+
+ if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) {
+ // Recurse into children that clip children.
+ bool ok;
+ QTransform xinv = x.inverted(&ok);
+ if (ok)
+ childItems_helper(&items, item, xinv.map(pos));
+ }
+ }
+
+ sortItems(&items, Qt::AscendingOrder, sortCacheEnabled);
+ return items;
+}
+
QList<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QRectF &rect,
Qt::ItemSelectionMode mode,
Qt::SortOrder order) const
@@ -1368,7 +1419,8 @@ QList<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QRectF &rect,
// The index returns a rough estimate of what items are inside the rect.
// Refine it by iterating through all returned items.
- QRectF adjustedRect = _q_adjustedRect(rect);
+ QRectF adjustedRect(rect);
+ _q_adjustRect(&adjustedRect);
foreach (QGraphicsItem *item, estimateItemsInRect(adjustedRect)) {
// Find the item's scene transform in a clever way.
QTransform x = item->sceneTransform();
@@ -1377,7 +1429,7 @@ QList<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QRectF &rect,
// ### _q_adjustedRect is only needed because QRectF::intersects,
// QRectF::contains and QTransform::map() and friends don't work with
// flat rectangles.
- QRectF br = _q_adjustedRect(item->boundingRect());
+ const QRectF br(adjustedItemBoundingRect(item));
if (mode >= Qt::ContainsItemBoundingRect) {
// Rect intersects/contains item's bounding rect
QRectF mbr = x.mapRect(br);
@@ -1392,7 +1444,7 @@ QList<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QRectF &rect,
bool ok;
QTransform xinv = x.inverted(&ok);
if (ok) {
- if (path == QPainterPath())
+ if (path.isEmpty())
path.addRect(rect);
if (itemCollidesWithPath(item, xinv.map(path), mode)) {
items << item;
@@ -1429,7 +1481,8 @@ QList<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QPolygonF &poly
{
QList<QGraphicsItem *> items;
- QRectF polyRect = _q_adjustedRect(polygon.boundingRect());
+ QRectF polyRect(polygon.boundingRect());
+ _q_adjustRect(&polyRect);
QPainterPath path;
// The index returns a rough estimate of what items are inside the rect.
@@ -1442,7 +1495,7 @@ QList<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QPolygonF &poly
// ### _q_adjustedRect is only needed because QRectF::intersects,
// QRectF::contains and QTransform::map() and friends don't work with
// flat rectangles.
- QRectF br = _q_adjustedRect(item->boundingRect());
+ const QRectF br(adjustedItemBoundingRect(item));
if (mode >= Qt::ContainsItemBoundingRect) {
// Polygon contains/intersects item's bounding rect
if (path == QPainterPath())
@@ -1487,21 +1540,47 @@ QList<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QPainterPath &p
Qt::SortOrder order) const
{
QList<QGraphicsItem *> items;
+ QRectF pathRect(path.controlPointRect());
+ _q_adjustRect(&pathRect);
+
// The index returns a rough estimate of what items are inside the rect.
// Refine it by iterating through all returned items.
- foreach (QGraphicsItem *item, estimateItemsInRect(_q_adjustedRect(path.controlPointRect()))) {
+ foreach (QGraphicsItem *item, estimateItemsInRect(pathRect)) {
// Find the item's scene transform in a clever way.
QTransform x = item->sceneTransform();
- bool ok;
- QTransform xinv = x.inverted(&ok);
- if (ok) {
- QPainterPath mappedPath = xinv.map(path);
- if (itemCollidesWithPath(item, mappedPath, mode)) {
+ bool keep = false;
+
+ // ### _q_adjustedRect is only needed because QRectF::intersects,
+ // QRectF::contains and QTransform::map() and friends don't work with
+ // flat rectangles.
+ const QRectF br(adjustedItemBoundingRect(item));
+ if (mode >= Qt::ContainsItemBoundingRect) {
+ // Path contains/intersects item's bounding rect
+ if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(x.mapRect(br)))
+ || (mode == Qt::ContainsItemBoundingRect && path.contains(x.mapRect(br)))) {
items << item;
- if (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)
- childItems_helper(&items, item, mappedPath, mode);
+ keep = true;
+ }
+ } else {
+ // Path contains/intersects item's shape
+ if (QRectF_intersects(pathRect, x.mapRect(br))) {
+ bool ok;
+ QTransform xinv = x.inverted(&ok);
+ if (ok) {
+ if (itemCollidesWithPath(item, xinv.map(path), mode)) {
+ items << item;
+ keep = true;
+ }
+ }
}
}
+
+ if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) {
+ bool ok;
+ QTransform xinv = x.inverted(&ok);
+ if (ok)
+ childItems_helper(&items, item, xinv.map(path), mode);
+ }
}
if (order != Qt::SortOrder(-1))
@@ -1511,13 +1590,13 @@ QList<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QPainterPath &p
void QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *items,
const QGraphicsItem *parent,
- const QRectF &rect,
- Qt::ItemSelectionMode mode) const
+ const QPointF &pos) const
{
- QPainterPath path;
bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape);
- QRectF r = !parentClip ? _q_adjustedRect(rect) : _q_adjustedRect(rect).intersected(_q_adjustedRect(parent->boundingRect()));
- if (r.isEmpty())
+ if (parentClip && parent->d_ptr->isClippedAway())
+ return;
+ // ### is this needed?
+ if (parentClip && !parent->boundingRect().contains(pos))
return;
QList<QGraphicsItem *> &children = parent->d_ptr->children;
@@ -1527,31 +1606,73 @@ void QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *items,
continue;
// Skip invisible items and all their children.
- if (!item->d_ptr->visible || qFuzzyCompare(item->effectiveOpacity(), qreal(0.0)))
+ if (item->d_ptr->isInvisible())
continue;
- // ### _q_adjustedRect is only needed because QRectF::intersects,
- // QRectF::contains and QTransform::map() and friends don't work with
- // flat rectangles.
- QRectF br = _q_adjustedRect(item->boundingRect());
- QRectF mbr = item->mapRectToParent(br);
bool keep = false;
- if (mode >= Qt::ContainsItemBoundingRect) {
- // Rect intersects/contains item's bounding rect
- if ((mode == Qt::IntersectsItemBoundingRect && QRectF_intersects(rect, mbr))
- || (mode == Qt::ContainsItemBoundingRect && rect != mbr && rect.contains(br))) {
+ if (!item->d_ptr->isClippedAway()) {
+ if (item->contains(item->mapFromParent(pos))) {
items->append(item);
keep = true;
}
- } else {
- // Rect intersects/contains item's shape
- if (QRectF_intersects(rect, mbr)) {
- if (path == QPainterPath())
- path.addRect(rect);
- if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) {
+ }
+
+ if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty())
+ // Recurse into children.
+ childItems_helper(items, item, item->mapFromParent(pos));
+ }
+}
+
+
+void QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *items,
+ const QGraphicsItem *parent,
+ const QRectF &rect,
+ Qt::ItemSelectionMode mode) const
+{
+ bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape);
+ if (parentClip && parent->d_ptr->isClippedAway())
+ return;
+ QRectF adjustedRect(rect);
+ _q_adjustRect(&adjustedRect);
+ QRectF r = !parentClip ? adjustedRect : adjustedRect.intersected(adjustedItemBoundingRect(parent));
+ if (r.isEmpty())
+ return;
+
+ QPainterPath path;
+ QList<QGraphicsItem *> &children = parent->d_ptr->children;
+ for (int i = 0; i < children.size(); ++i) {
+ QGraphicsItem *item = children.at(i);
+ if (item->d_ptr->hasTransform && !item->transform().isInvertible())
+ continue;
+
+ // Skip invisible items and all their children.
+ if (item->d_ptr->isInvisible())
+ continue;
+
+ bool keep = false;
+ if (!item->d_ptr->isClippedAway()) {
+ // ### _q_adjustedRect is only needed because QRectF::intersects,
+ // QRectF::contains and QTransform::map() and friends don't work with
+ // flat rectangles.
+ const QRectF br(adjustedItemBoundingRect(item));
+ QRectF mbr = item->mapRectToParent(br);
+ if (mode >= Qt::ContainsItemBoundingRect) {
+ // Rect intersects/contains item's bounding rect
+ if ((mode == Qt::IntersectsItemBoundingRect && QRectF_intersects(rect, mbr))
+ || (mode == Qt::ContainsItemBoundingRect && rect != mbr && rect.contains(br))) {
items->append(item);
keep = true;
}
+ } else {
+ // Rect intersects/contains item's shape
+ if (QRectF_intersects(rect, mbr)) {
+ if (path == QPainterPath())
+ path.addRect(rect);
+ if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) {
+ items->append(item);
+ keep = true;
+ }
+ }
}
}
@@ -1568,18 +1689,22 @@ void QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *items,
}
}
+
void QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *items,
const QGraphicsItem *parent,
const QPolygonF &polygon,
Qt::ItemSelectionMode mode) const
{
- QPainterPath path;
bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape);
- QRectF polyRect = _q_adjustedRect(polygon.boundingRect());
- QRectF r = !parentClip ? polyRect : polyRect.intersected(_q_adjustedRect(parent->boundingRect()));
+ if (parentClip && parent->d_ptr->isClippedAway())
+ return;
+ QRectF polyRect(polygon.boundingRect());
+ _q_adjustRect(&polyRect);
+ QRectF r = !parentClip ? polyRect : polyRect.intersected(adjustedItemBoundingRect(parent));
if (r.isEmpty())
return;
+ QPainterPath path;
QList<QGraphicsItem *> &children = parent->d_ptr->children;
for (int i = 0; i < children.size(); ++i) {
QGraphicsItem *item = children.at(i);
@@ -1587,32 +1712,34 @@ void QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *items,
continue;
// Skip invisible items.
- if (!item->d_ptr->visible || qFuzzyCompare(item->effectiveOpacity() + 1, qreal(1.0)))
+ if (item->d_ptr->isInvisible())
continue;
- // ### _q_adjustedRect is only needed because QRectF::intersects,
- // QRectF::contains and QTransform::map() and friends don't work with
- // flat rectangles.
- QRectF br = _q_adjustedRect(item->boundingRect());
bool keep = false;
- if (mode >= Qt::ContainsItemBoundingRect) {
- // Polygon contains/intersects item's bounding rect
- if (path == QPainterPath())
- path.addPolygon(polygon);
- if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br)))
- || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) {
- items->append(item);
- keep = true;
- }
- } else {
- // Polygon contains/intersects item's shape
- if (QRectF_intersects(polyRect, item->mapRectToParent(br))) {
+ if (!item->d_ptr->isClippedAway()) {
+ // ### _q_adjustedRect is only needed because QRectF::intersects,
+ // QRectF::contains and QTransform::map() and friends don't work with
+ // flat rectangles.
+ const QRectF br(adjustedItemBoundingRect(item));
+ if (mode >= Qt::ContainsItemBoundingRect) {
+ // Polygon contains/intersects item's bounding rect
if (path == QPainterPath())
path.addPolygon(polygon);
- if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) {
+ if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br)))
+ || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) {
items->append(item);
keep = true;
}
+ } else {
+ // Polygon contains/intersects item's shape
+ if (QRectF_intersects(polyRect, item->mapRectToParent(br))) {
+ if (path == QPainterPath())
+ path.addPolygon(polygon);
+ if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) {
+ items->append(item);
+ keep = true;
+ }
+ }
}
}
@@ -1629,30 +1756,52 @@ void QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *items,
Qt::ItemSelectionMode mode) const
{
bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape);
- QPainterPath intersectedPath = !parentClip ? path : path.intersected(parent->shape());
- if (intersectedPath.isEmpty())
+ if (parentClip && parent->d_ptr->isClippedAway())
+ return;
+ QRectF pathRect(path.boundingRect());
+ _q_adjustRect(&pathRect);
+ QRectF r = !parentClip ? pathRect : pathRect.intersected(adjustedItemBoundingRect(parent));
+ if (r.isEmpty())
return;
QList<QGraphicsItem *> &children = parent->d_ptr->children;
for (int i = 0; i < children.size(); ++i) {
QGraphicsItem *item = children.at(i);
+ if (item->d_ptr->hasTransform && !item->transform().isInvertible())
+ continue;
// Skip invisible items.
- if (!item->d_ptr->visible || qFuzzyCompare(item->effectiveOpacity(), qreal(0.0)))
+ if (item->d_ptr->isInvisible())
continue;
- QTransform x = item->sceneTransform();
-
- bool ok;
- QTransform xinv = x.inverted(&ok);
- if (ok) {
- QPainterPath mappedPath = xinv.map(path);
- if (itemCollidesWithPath(item, mappedPath, mode)) {
- items->append(item);
- if (!item->d_ptr->children.isEmpty())
- childItems_helper(items, item, mappedPath, mode);
+ bool keep = false;
+ if (!item->d_ptr->isClippedAway()) {
+ // ### _q_adjustedRect is only needed because QRectF::intersects,
+ // QRectF::contains and QTransform::map() and friends don't work with
+ // flat rectangles.
+ const QRectF br(adjustedItemBoundingRect(item));
+ if (mode >= Qt::ContainsItemBoundingRect) {
+ // Polygon contains/intersects item's bounding rect
+ if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br)))
+ || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) {
+ items->append(item);
+ keep = true;
+ }
+ } else {
+ // Path contains/intersects item's shape
+ if (QRectF_intersects(pathRect, item->mapRectToParent(br))) {
+ if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) {
+ items->append(item);
+ keep = true;
+ }
+ }
}
}
+
+ if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) {
+ // Recurse into children that clip children.
+ childItems_helper(items, item, item->mapFromParent(path), mode);
+ }
}
}
@@ -2326,17 +2475,8 @@ QList<QGraphicsItem *> QGraphicsScene::items() const
*/
QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const
{
- QList<QGraphicsItem *> itemsAtPoint;
-
- // Find all items within a 1x1 rect area starting at pos. This can be
- // inefficient for scenes that use small coordinates (like unity
- // coordinates), or for detailed graphs. ### The index should support
- // fetching items at a pos to avoid this limitation.
- foreach (QGraphicsItem *item, items(QRectF(pos, QSizeF(1, 1)), Qt::IntersectsItemBoundingRect)) {
- if (item->contains(item->mapFromScene(pos)))
- itemsAtPoint << item;
- }
- return itemsAtPoint;
+ Q_D(const QGraphicsScene);
+ return d->items_helper(pos);
}
@@ -2723,8 +2863,9 @@ void QGraphicsScene::addItem(QGraphicsItem *item)
// Notify the item that its scene is changing, and allow the item to
// react.
- QGraphicsScene *targetScene = qVariantValue<QGraphicsScene *>(item->itemChange(QGraphicsItem::ItemSceneChange,
- qVariantFromValue<QGraphicsScene *>(this)));
+ const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange,
+ qVariantFromValue<QGraphicsScene *>(this)));
+ QGraphicsScene *targetScene = qVariantValue<QGraphicsScene *>(newSceneVariant);
if (targetScene != this) {
if (targetScene && item->scene() != targetScene)
targetScene->addItem(item);
@@ -2818,7 +2959,7 @@ void QGraphicsScene::addItem(QGraphicsItem *item)
emit selectionChanged();
// Deliver post-change notification
- item->itemChange(QGraphicsItem::ItemSceneHasChanged, qVariantFromValue<QGraphicsScene *>(this));
+ item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant);
}
/*!
@@ -3082,8 +3223,9 @@ void QGraphicsScene::removeItem(QGraphicsItem *item)
// Notify the item that it's scene is changing to 0, allowing the item to
// react.
- QGraphicsScene *targetScene = qVariantValue<QGraphicsScene *>(item->itemChange(QGraphicsItem::ItemSceneChange,
- qVariantFromValue<QGraphicsScene *>(0)));
+ const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange,
+ qVariantFromValue<QGraphicsScene *>(0)));
+ QGraphicsScene *targetScene = qVariantValue<QGraphicsScene *>(newSceneVariant);
if (targetScene != 0 && targetScene != this) {
targetScene->addItem(item);
return;
@@ -3154,6 +3296,16 @@ void QGraphicsScene::removeItem(QGraphicsItem *item)
d->unpolishedItems.removeAll(item);
d->dirtyItems.removeAll(item);
+ //We remove all references of item from the sceneEventFilter arrays
+ QMultiMap<QGraphicsItem*, QGraphicsItem*>::iterator iterator = d->sceneEventFilters.begin();
+ while (iterator != d->sceneEventFilters.end()) {
+ if (iterator.value() == item || iterator.key() == item)
+ iterator = d->sceneEventFilters.erase(iterator);
+ else
+ ++iterator;
+ }
+
+
//Ensure dirty flag have the correct default value so the next time it will be added it will receive updates
item->d_func()->dirty = 0;
item->d_func()->dirtyChildren = 0;
@@ -3181,7 +3333,7 @@ void QGraphicsScene::removeItem(QGraphicsItem *item)
emit selectionChanged();
// Deliver post-change notification
- item->itemChange(QGraphicsItem::ItemSceneHasChanged, qVariantFromValue<QGraphicsScene *>(0));
+ item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant);
}
/*!
@@ -3455,7 +3607,7 @@ QVariant QGraphicsScene::inputMethodQuery(Qt::InputMethodQuery query) const
void QGraphicsScene::update(const QRectF &rect)
{
Q_D(QGraphicsScene);
- if (d->updateAll)
+ if (d->updateAll || (rect.isEmpty() && !rect.isNull()))
return;
// Check if anyone's connected; if not, we can send updates directly to
@@ -4564,7 +4716,9 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
// Item's (local) bounding rect
QRectF brect = item->boundingRect();
- if (_q_adjustedRect(brect).isEmpty())
+ QRectF adjustedBrect(brect);
+ _q_adjustRect(&adjustedBrect);
+ if (adjustedBrect.isEmpty())
return;
// Fetch the off-screen transparent buffer and exposed area info.
@@ -4595,16 +4749,17 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
if (cacheMode == QGraphicsItem::ItemCoordinateCache) {
QSize pixmapSize;
bool fixedCacheSize = false;
+ QRectF brectAligned = brect.toAlignedRect();
if ((fixedCacheSize = itemCache->fixedSize.isValid())) {
pixmapSize = itemCache->fixedSize;
} else {
- pixmapSize = brect.toAlignedRect().size();
+ pixmapSize = brectAligned.size().toSize();
}
// Create or recreate the pixmap.
int adjust = itemCache->fixedSize.isValid() ? 0 : 2;
QSize adjustSize(adjust*2, adjust*2);
- QRectF br = brect.adjusted(-adjust, -adjust, adjust, adjust);
+ QRectF br = brectAligned.adjusted(-adjust, -adjust, adjust, adjust);
if (pix.isNull() || (!fixedCacheSize && (pixmapSize + adjustSize) != pix.size())) {
pix = QPixmap(pixmapSize + adjustSize);
itemCache->exposed.clear();
@@ -4614,9 +4769,11 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
// Redraw any newly exposed areas.
if (itemCache->allExposed || !itemCache->exposed.isEmpty()) {
// Fit the item's bounding rect into the pixmap's coordinates.
- const QPointF scale(pixmapSize.width() / brect.width(), pixmapSize.height() / brect.height());
QTransform itemToPixmap;
- itemToPixmap.scale(scale.x(), scale.y());
+ if (fixedCacheSize) {
+ const QPointF scale(pixmapSize.width() / brect.width(), pixmapSize.height() / brect.height());
+ itemToPixmap.scale(scale.x(), scale.y());
+ }
itemToPixmap.translate(-br.x(), -br.y());
// Generate the item's exposedRect and map its list of expose
@@ -4769,8 +4926,9 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
if (itemCache->allExposed || !itemCache->exposed.isEmpty() || !scrollExposure.isEmpty()) {
// Construct an item-to-pixmap transform.
QPointF p = deviceRect.topLeft();
- QTransform itemToPixmap = QTransform::fromTranslate(-p.x(), -p.y());
- itemToPixmap = painter->worldTransform() * itemToPixmap;
+ QTransform itemToPixmap = painter->worldTransform();
+ if (!p.isNull())
+ itemToPixmap *= QTransform::fromTranslate(-p.x(), -p.y());
// Map the item's logical expose to pixmap coordinates.
QRegion pixmapExposed = scrollExposure;
@@ -5104,9 +5262,12 @@ void QGraphicsScene::itemUpdated(QGraphicsItem *item, const QRectF &rect)
update(item->sceneBoundingRect());
} else {
// ### Remove _q_adjustedRects().
- QRectF boundingRect = _q_adjustedRect(item->boundingRect());
- if (!rect.isNull())
- boundingRect &= _q_adjustedRect(rect);
+ QRectF boundingRect(adjustedItemBoundingRect(item));
+ if (!rect.isNull()) {
+ QRectF adjustedRect(rect);
+ _q_adjustRect(&adjustedRect);
+ boundingRect &= adjustedRect;
+ }
// Update each view directly.
for (int i = 0; i < d->views.size(); ++i)
@@ -5118,6 +5279,9 @@ void QGraphicsScene::itemUpdated(QGraphicsItem *item, const QRectF &rect)
d->resetDirtyItemsLater();
}
+ if (!item->isVisible())
+ return; // Hiding an item won't effect the largestUntransformableItem/sceneRect.
+
// Update d->largestUntransformableItem by mapping this item's bounding
// rect back to the topmost untransformable item's untransformed
// coordinate system (which sort of equals the 1:1 coordinate system of an
@@ -5133,7 +5297,9 @@ void QGraphicsScene::itemUpdated(QGraphicsItem *item, const QRectF &rect)
// defined scene rect.
if (!d->hasSceneRect) {
QRectF oldGrowingItemsBoundingRect = d->growingItemsBoundingRect;
- d->growingItemsBoundingRect |= _q_adjustedRect(item->sceneBoundingRect());
+ QRectF adjustedItemSceneBoundingRect(item->sceneBoundingRect());
+ _q_adjustRect(&adjustedItemSceneBoundingRect);
+ d->growingItemsBoundingRect |= adjustedItemSceneBoundingRect;
if (d->growingItemsBoundingRect != oldGrowingItemsBoundingRect)
emit sceneRectChanged(d->growingItemsBoundingRect);
}